diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Sun Feb  9 08:07:20 2003
+++ b/CREDITS	Wed Mar  5 07:11:17 2003
@@ -3492,9 +3492,9 @@
 
 N: Marc Zyngier
 E: maz@wild-wind.fr.eu.org
+W: http://www.misterjones.org
 D: MD driver
-S: 11 rue Victor HUGO
-S: 95560 Montsoult
+D: EISA/sysfs subsystem
 S: France
 
 # Don't add your name here, unless you really _are_ after Marc
diff -Nru a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl
--- a/Documentation/DocBook/journal-api.tmpl	Wed Feb  5 20:04:26 2003
+++ b/Documentation/DocBook/journal-api.tmpl	Tue Mar 11 10:19:58 2003
@@ -216,7 +216,7 @@
 <para>
 A new feature of jbd since 2.5.25 is commit callbacks with the new
 journal_callback_set() function you can now ask the journalling layer
-to call you back when the transaction is finally commited to disk, so that
+to call you back when the transaction is finally committed to disk, so that
 you can do some of your own management. The key to this is the journal_callback
 struct, this maintains the internal callback information but you can
 extend it like this:-
@@ -232,7 +232,7 @@
 </programlisting>
 
 <para>
-this would be useful if you needed to know when data was commited to a 
+this would be useful if you needed to know when data was committed to a 
 particular inode.
 </para>
 
diff -Nru a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl
--- a/Documentation/DocBook/sis900.tmpl	Sun Sep 29 15:17:17 2002
+++ b/Documentation/DocBook/sis900.tmpl	Tue Mar 11 10:19:58 2003
@@ -536,7 +536,7 @@
 <ListItem>
 <Para>
 November 13, 2000, Revision 1.07, seventh release, 630E problem fixed 
-and furthur clean up.
+and further clean up.
 </Para>
 </ListItem>
 
diff -Nru a/Documentation/arm/Booting b/Documentation/arm/Booting
--- a/Documentation/arm/Booting	Sun Jan 12 04:07:10 2003
+++ b/Documentation/arm/Booting	Tue Mar 11 10:19:58 2003
@@ -47,7 +47,7 @@
 used for debugging purposes, or communication with the target.)
 
 As an alternative, the boot loader can pass the relevant 'console='
-option to the kernel via the tagged lists specifing the port, and
+option to the kernel via the tagged lists specifying the port, and
 serial format options as described in
 
        linux/Documentation/kernel-parameters.txt.
diff -Nru a/Documentation/arm/SA1100/serial_UART b/Documentation/arm/SA1100/serial_UART
--- a/Documentation/arm/SA1100/serial_UART	Mon Feb  4 23:44:55 2002
+++ b/Documentation/arm/SA1100/serial_UART	Tue Mar 11 10:19:58 2003
@@ -39,7 +39,7 @@
 name. The classic example is the content of the /etc/inittab file where
 you might have a getty process started on ttyS0.  In this case:
 
-- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc.
+- replace occurrences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc.
 
 - don't forget to add 'ttySA0', 'console', or the appropriate tty name
   in /etc/securetty for root to be allowed to login as well.
diff -Nru a/Documentation/arm/Setup b/Documentation/arm/Setup
--- a/Documentation/arm/Setup	Tue Feb  5 09:40:37 2002
+++ b/Documentation/arm/Setup	Tue Mar 11 10:19:58 2003
@@ -97,7 +97,7 @@
  initrd_size
 
    This describes the kernel virtual start address and size of the
-   inital ramdisk.
+   initial ramdisk.
 
  rd_start
 
diff -Nru a/Documentation/arm/XScale/IOP3XX/dma.txt b/Documentation/arm/XScale/IOP3XX/dma.txt
--- a/Documentation/arm/XScale/IOP3XX/dma.txt	Thu Feb 27 16:28:26 2003
+++ b/Documentation/arm/XScale/IOP3XX/dma.txt	Tue Mar 11 10:19:58 2003
@@ -142,7 +142,7 @@
 	/* User's responsibility to keep buffers cached coherent */
 	cpu_dcache_clean(sgl->data, sgl->data + 1024);
 
-    	/* queing the buffer, this function will sleep since no callback */
+    	/* queuing the buffer, this function will sleep since no callback */
     	err = dma_queue_buffer(channel, sgl_head);
 
     	/* now we are woken from DMA complete */
@@ -186,7 +186,7 @@
 int dma_flush_all(dmach_t channel);
 
 This completely flushes all queued buffers and on-going DMA transfers on a
-given channel. This is called when DMA channel errors have occured.
+given channel. This is called when DMA channel errors have occurred.
 
 
 void dma_free(dmach_t channel);
diff -Nru a/Documentation/arm/mem_alignment b/Documentation/arm/mem_alignment
--- a/Documentation/arm/mem_alignment	Fri Nov 30 06:36:13 2001
+++ b/Documentation/arm/mem_alignment	Tue Mar 11 10:19:58 2003
@@ -51,7 +51,7 @@
 	echo 1 > /proc/sys/debug/alignment
 
 You can also read the content of the same file to get statistical
-information on unaligned access occurences plus the current mode of
+information on unaligned access occurrences plus the current mode of
 operation for user space code.
 
 
diff -Nru a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/basic_profiling.txt	Tue Mar  4 23:48:44 2003
@@ -0,0 +1,48 @@
+These instructions are deliberately very basic. If you want something clever,
+go read the real docs ;-) Please don't add more stuff, but feel free to 
+correct my mistakes ;-)    (mbligh@aracnet.com)
+Thanks to John Levon, Dave Hansen, et al. for help writing this.
+
+<test> is the thing you're trying to measure.
+Make sure you have the correct System.map / vmlinux referenced!
+IMHO it's easier to use "make install" for linux and hack /sbin/installkernel
+to copy config files, system.map, vmlinux to /boot.
+
+Readprofile
+-----------
+You need a fixed readprofile command for 2.5 ... either get hold of
+a current version from:
+http://www.kernel.org/pub/linux/utils/util-linux/
+or get readprofile binary fixed for 2.5 / akpm's 2.5 patch from 
+ftp://ftp.kernel.org/pub/linux/kernel/people/mbligh/tools/readprofile/
+
+Add "profile=2" to the kernel command line.
+
+clear		readprofile -r
+		<test>
+dump output	readprofile -m /boot/System.map > captured_profile
+
+Oprofile
+--------
+get source (I use 0.5) from http://oprofile.sourceforge.net/
+add "idle=poll" to the kernel command line 
+Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
+./configure --with-kernel-support
+make install
+
+One time setup (pick appropriate one for your CPU):
+P3		opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=CPU_CLK_UNHALTED --ctr0-count=100000
+Athlon/x86-64	opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=RETIRED_INSNS --ctr0-count=100000
+P4		opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=GLOBAL_POWER_EVENTS \
+		--ctr0-unit-mask=1 --ctr0-count=100000
+
+start daemon	opcontrol --start-daemon
+clear		opcontrol --reset
+start		opcontrol --start
+		<test>
+stop		opcontrol --stop
+dump output	oprofpp -dl -i /boot/vmlinux  >  output_file
+
diff -Nru a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
--- a/Documentation/block/biodoc.txt	Tue Feb 25 11:05:27 2003
+++ b/Documentation/block/biodoc.txt	Tue Mar 11 10:19:58 2003
@@ -635,9 +635,9 @@
 be one of the many segments in the current bio (i.e i/o completion unit).
 The nr_sectors value refers to the total number of sectors in the whole
 request that remain to be transferred (no change). The purpose of the
-hard_xxx values is for block to remember these counts everytime it hands
+hard_xxx values is for block to remember these counts every time it hands
 over the request to the driver. These values are updated by block on
-end_that_request_first, i.e. everytime the driver completes a part of the
+end_that_request_first, i.e. every time the driver completes a part of the
 transfer and invokes block end*request helpers to mark this. The
 driver should not modify these values. The block layer sets up the
 nr_sectors and current_nr_sectors fields (based on the corresponding
diff -Nru a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
--- a/Documentation/cdrom/cdrom-standard.tex	Tue Feb  5 09:40:36 2002
+++ b/Documentation/cdrom/cdrom-standard.tex	Sat Mar  8 14:50:21 2003
@@ -758,11 +758,8 @@
 \subsection{$Struct\ file_operations\ cdrom_fops$}
 
 The contents of this structure were described in section~\ref{cdrom.c}.
-As already stated, this structure should be used to register block
-devices with the kernel:
-$$
-register_blkdev(major, <name>, \&cdrom_fops);
-$$
+A pointer to this structure is assigned to the $fops$ field
+of the $struct gendisk$.
 
 \subsection{$Int\ register_cdrom( struct\ cdrom_device_info\ * cdi)$}
 
diff -Nru a/Documentation/computone.txt b/Documentation/computone.txt
--- a/Documentation/computone.txt	Mon Feb  4 23:54:04 2002
+++ b/Documentation/computone.txt	Tue Mar 11 10:19:58 2003
@@ -539,7 +539,7 @@
 X		for PORTNO in $MINORS
 X		do
 X			if test ! -c /dev/ttyF$PORTNO ; then
-X				# We got the harware but no device - make it
+X				# We got the hardware but no device - make it
 X				mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
 X			fi	
 X		done
@@ -552,7 +552,7 @@
 X		for PORTNO in $MINORS
 X		do
 X			if test ! -c /dev/cuf$PORTNO ; then
-X				# We got the harware but no device - make it
+X				# We got the hardware but no device - make it
 X				mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
 X			fi	
 X		done
diff -Nru a/Documentation/cpqarray.txt b/Documentation/cpqarray.txt
--- a/Documentation/cpqarray.txt	Tue Feb  5 09:40:37 2002
+++ b/Documentation/cpqarray.txt	Tue Mar 11 10:19:58 2003
@@ -49,9 +49,9 @@
 -----------------
 
 If you want to use an EISA controller you'll have to supply some
-insmod/lilo paramaters.  If the driver is compiled into the kernel, must
+insmod/lilo parameters.  If the driver is compiled into the kernel, must
 give it the controller's IO port address at boot time (it is no longer
-necessary to specifiy the IRQ).  For example, if you had two SMART-2/E
+necessary to specify the IRQ).  For example, if you had two SMART-2/E
 controllers, in EISA slots 1 and 2 you'd give it a boot argument like
 this:
 
diff -Nru a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt
--- a/Documentation/cpu-freq/core.txt	Tue Feb  4 11:04:44 2003
+++ b/Documentation/cpu-freq/core.txt	Sat Mar  8 01:39:53 2003
@@ -35,6 +35,10 @@
 kernel "constant" loops_per_jiffy is updated on frequency changes
 here.
 
+Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
+which make sure that the cpufreq processor driver is correctly
+registered with the core, and will not be unloaded until
+cpufreq_put_cpu is called.
 
 2. CPUFreq notifiers
 ====================
diff -Nru a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
--- a/Documentation/cpu-freq/cpu-drivers.txt	Sat Mar  1 08:56:11 2003
+++ b/Documentation/cpu-freq/cpu-drivers.txt	Tue Mar 11 13:50:59 2003
@@ -35,7 +35,7 @@
 
 So, you just got a brand-new CPU / chipset with datasheets and want to
 add cpufreq support for this CPU / chipset? Great. Here are some hints
-on what is neccessary:
+on what is necessary:
 
 
 1.1 Initialization
@@ -54,7 +54,7 @@
 cpufreq_driver.init -		A pointer to the per-CPU initialization 
 				function.
 
-cpufreq_driver.verify -		A pointer to a "verfication" funciton.
+cpufreq_driver.verify -		A pointer to a "verification" function.
 
 cpufreq_driver.setpolicy _or_ 
 cpufreq_driver.target -		See below on the differences.
@@ -63,13 +63,16 @@
 
 cpufreq_driver.exit -		A pointer to a per-CPU cleanup function.
 
+cpufreq_driver.attr -		A pointer to a NULL-terminated list of
+				"struct freq_attr" which allow to
+				export values to sysfs.
 
 
 1.2 Per-CPU Initialization
 --------------------------
 
 Whenever a new CPU is registered with the device model, or after the
-cpufreq driver registers itself, the per-CPU initialization fucntion 
+cpufreq driver registers itself, the per-CPU initialization function 
 cpufreq_driver.init is called. It takes a struct cpufreq_policy
 *policy as argument. What to do now?
 
@@ -91,7 +94,7 @@
 				this CPU (if appropriate)
 policy->min, 
 policy->max, 
-policy->policy and, if neccessary,
+policy->policy and, if necessary,
 policy->governor		must contain the "default policy" for
 				this CPU. A few moments later,
 				cpufreq_driver.verify and either
diff -Nru a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
--- a/Documentation/cpu-freq/governors.txt	Sat Mar  1 08:56:11 2003
+++ b/Documentation/cpu-freq/governors.txt	Tue Mar 11 05:56:20 2003
@@ -98,7 +98,7 @@
 -------------
 
 The CPUfreq governor "userspace" allows the user, or any userspace
-program running with UID "root", to set the CPU to a specifc frequency
+program running with UID "root", to set the CPU to a specific frequency
 by making a sysfs file "scaling_setspeed" available in the CPU-device
 directory.
 
diff -Nru a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
--- a/Documentation/cpu-freq/user-guide.txt	Sat Mar  1 08:56:11 2003
+++ b/Documentation/cpu-freq/user-guide.txt	Mon Mar 10 09:59:54 2003
@@ -58,7 +58,8 @@
 Intel Pentium 4, Intel Xeon
 National Semiconductors Geode GX
 Transmeta Crusoe
-varios processors on some ACPI 2.0-compatible systems [**]
+VIA Cyrix 3 / C3
+various processors on some ACPI 2.0-compatible systems [**]
 
 [*] only certain Intel mobile PIII processors are supported. If you
 know that you own a speedstep-capable processor, pass the option
@@ -81,9 +82,9 @@
 2. "Policy" / "Governor" ?
 ==========================
 
-Some CPU frequency scaling-capable processor switch between varios
+Some CPU frequency scaling-capable processor switch between various
 frequencies and operating voltages "on the fly" without any kernel or
-user involvement. This guarantuees very fast switching to a frequency
+user involvement. This guarantees very fast switching to a frequency
 which is high enough to serve the user's needs, but low enough to save
 power.
 
@@ -93,7 +94,7 @@
 
 On these systems, all you can do is select the lower and upper
 frequency limit as well as whether you want more aggressive
-power-saving or more instantly avaialble processing power.
+power-saving or more instantly available processing power.
 
 
 2.2 Governor
@@ -114,9 +115,9 @@
 ------------------------------
 
 The preferred interface is located in the sysfs filesystem. If you
-mounted it at /sys, the cpufreq interface is located in the 
-cpu-device directory (e.g. /sys/devices/sys/cpu0/ for the first
-CPU).
+mounted it at /sys, the cpufreq interface is located in a subdirectory
+"cpufreq" within the cpu-device directory
+(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
 
 cpuinfo_min_freq :		this file shows the minimum operating
 				frequency the processor can run at(in kHz) 
@@ -125,7 +126,7 @@
 scaling_driver :		this file shows what cpufreq driver is
 				used to set the frequency on this CPU
 
-available_scaling_governors :	this file shows the CPUfreq governors
+scaling_available_governors :	this file shows the CPUfreq governors
 				available in this kernel. You can see the
 				currently activated governor in
 
diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt	Tue Jan 14 03:45:05 2003
+++ b/Documentation/crypto/api-intro.txt	Sat Mar  8 15:26:02 2003
@@ -38,9 +38,8 @@
 Compressors.  The compression algorithms especially seem to be performing
 very well so far.
 
-An asynchronous scheduling interface is in planning but not yet
-implemented, as we need to further analyze the requirements of all of
-the possible hardware scenarios (e.g. IPsec NIC offload).
+Support for hardware crypto devices via an asynchronous interface is
+under development.
 
 Here's an example of how to use the API:
 
@@ -87,8 +86,8 @@
 
 DEVELOPER NOTES
 
-None of this code should be called from hardirq context, only softirq and
-user contexts.
+Transforms may only be allocated in user context, and cryptographic
+methods may only be called from softirq and user contexts.
 
 When using the API for ciphers, performance will be optimal if each
 scatterlist contains data which is a multiple of the cipher's block
@@ -137,16 +136,11 @@
 list, see:
 http://samba.org/~jamesm/crypto/
 
-Ongoing development discussion may also be found on
-kerneli cryptoapi-devel, 
-see http://www.kerneli.org/mailman/listinfo/cryptoapi-devel
-
 
 AUTHORS
 
 James Morris
 David S. Miller
-Jean-Francois Dive (SHA1 algorithm module)
 
 
 CREDITS
@@ -191,6 +185,10 @@
   Matthew Skala (Twofish)
   Dag Arne Osvik (Serpent)
   Brian Gladman (AES)
+
+
+SHA1 algorithm contributors:
+  Jean-Francois Dive
   
 DES algorithm contributors:
   Raimar Falke
@@ -215,6 +213,8 @@
   Herbert Valerio Riedel
   Kyle McMartin
   Adam J. Richter
+
+Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
 James Morris <jmorris@intercode.com.au>
diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt
--- a/Documentation/devices.txt	Sat Dec 14 09:40:39 2002
+++ b/Documentation/devices.txt	Tue Mar 11 10:20:18 2003
@@ -898,7 +898,7 @@
 		    ...
 
 		Network Block Device is somehow similar to loopback
-		devices: If you read from it, it sends packet accross
+		devices: If you read from it, it sends packet across
 		network asking server for data. If you write to it, it
 		sends packet telling server to write. It could be used
 		to mounting filesystems over the net, swapping over
diff -Nru a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
--- a/Documentation/driver-model/driver.txt	Tue Jan 14 07:45:55 2003
+++ b/Documentation/driver-model/driver.txt	Tue Mar 11 10:20:18 2003
@@ -36,7 +36,7 @@
 ~~~~~~~~~~~~~~
 
 The driver must initialize at least the name and bus fields. It should
-also initalize the devclass field (when it arrives), so it may obtain
+also initialize the devclass field (when it arrives), so it may obtain
 the proper linkage internally. It should also initialize as many of
 the callbacks as possible, though each is optional.
 
@@ -93,7 +93,7 @@
        },
 };
 
-Some may find the syntax of embedded struct intialization awkward or
+Some may find the syntax of embedded struct initialization awkward or
 even a bit ugly. So far, it's the best way we've found to do what we want...
 
 Registration
@@ -198,7 +198,7 @@
 	int	(*suspend)	(struct device * dev, u32 state, u32 level);
 
 suspend is called to put the device in a low power state. There are
-several stages to sucessfully suspending a device, which is denoted in
+several stages to successfully suspending a device, which is denoted in
 the @level parameter. Breaking the suspend transition into several
 stages affords the platform flexibility in performing device power
 management based on the requirements of the system and the
@@ -206,7 +206,7 @@
 
 SUSPEND_NOTIFY notifies the device that a suspend transition is about
 to happen. This happens on system power state transition to verify
-that all devices can sucessfully suspend.
+that all devices can successfully suspend.
 
 A driver may choose to fail on this call, which should cause the
 entire suspend transition to fail. A driver should fail only if it
diff -Nru a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
--- a/Documentation/driver-model/platform.txt	Mon Aug 26 23:13:05 2002
+++ b/Documentation/driver-model/platform.txt	Tue Mar 11 10:20:18 2003
@@ -34,7 +34,7 @@
 gives them a common parent if they don't already have one. 
 
 But, besides the organizational benefits, the platform bus can also
-accomodate firmware-based enumeration. 
+accommodate firmware-based enumeration. 
 
 
 Device Discovery
diff -Nru a/Documentation/eisa.txt b/Documentation/eisa.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/eisa.txt	Wed Mar  5 07:11:17 2003
@@ -0,0 +1,164 @@
+EISA bus support (Marc Zyngier <maz@wild-wind.fr.eu.org>)
+
+This document groups random notes about porting EISA drivers to the
+new EISA/sysfs API.
+
+Starting from version 2.5.59, the EISA bus is almost given the same
+status as other much more mainstream busses such as PCI or USB. This
+has been possible through sysfs, which defines a nice enough set of
+abstractions to manage busses, devices and drivers.
+
+Although the new API is quite simple to use, converting existing
+drivers to the new infrastructure is not an easy task (mostly because
+detection code is generally also used to probe ISA cards). Moreover,
+most EISA drivers are among the oldest Linux drivers so, as you can
+imagine, some dust has settled here over the years.
+
+The EISA infrastructure is made up of three parts :
+
+    - The bus code implements most of the generic code. It is shared
+    among all the architectures that the EISA code runs on. It
+    implements bus probing (detecting EISA cards avaible on the bus),
+    allocates I/O resources, allows fancy naming through sysfs, and
+    offers interfaces for driver to register.
+
+    - The bus root driver implements the glue between the bus hardware
+    and the generic bus code. It is responsible for discovering the
+    device implementing the bus, and setting it up to be latter probed
+    by the bus code. This can go from something as simple as reserving
+    an I/O region on x86, to the rather more complex, like the hppa
+    EISA code. This is the part to implement in order to have EISA
+    running on an "new" platform.
+
+    - The driver offers the bus a list of devices that it manages, and
+    implements the necessary callbacks to probe and release devices
+    whenever told to.
+
+Every function/structure below lives in <linux/eisa.h>, which depends
+heavily on <linux/device.h>.
+
+** Bus root driver :
+
+int eisa_root_register (struct eisa_root_device *root);
+
+The eisa_root_register function is used to declare a device as the
+root of an EISA bus. The eisa_root_device structure holds a reference
+to this device, as well as some parameters for probing purposes.
+
+struct eisa_root_device {
+        struct list_head node;
+        struct device   *dev;    /* Pointer to bridge device */
+        struct resource *res;
+        unsigned long    bus_base_addr;
+        int              slots;  /* Max slot number */
+        int              bus_nr; /* Set by eisa_root_register */
+};
+
+node          : used for eisa_root_register internal purpose
+dev           : pointer to the root device
+res           : root device I/O resource
+bus_base_addr : slot 0 address on this bus
+slots	      : max slot number to probe
+bus_nr	      : unique bus id, set by eisa_root_register
+
+** Driver :
+
+int eisa_driver_register (struct eisa_driver *edrv);
+void eisa_driver_unregister (struct eisa_driver *edrv);
+
+Clear enough ?
+
+struct eisa_device_id {
+        char sig[EISA_SIG_LEN];
+	unsigned long driver_data;
+};
+
+struct eisa_driver {
+        const struct eisa_device_id *id_table;
+        struct device_driver         driver;
+};
+
+id_table	: an array of NULL terminated EISA id strings,
+		  followed by an empty string. Each string can be
+		  paired with a driver-dependant value (driver_data).
+
+driver		: a generic driver, such as described in
+		  Documentation/driver-model/driver.txt. Only .name,
+		  .probe and .remove members are mandatory.
+
+An example is the 3c509 driver :
+
+struct eisa_device_id el3_eisa_ids[] = {
+        { "TCM5092" },
+        { "TCM5093" },
+        { "" }
+};
+
+struct eisa_driver el3_eisa_driver = {
+        .id_table = el3_eisa_ids,
+        .driver   = {
+                .name    = "3c509",
+                .probe   = el3_eisa_probe,
+                .remove  = __devexit_p (el3_device_remove)
+        }
+};
+
+** Device :
+
+The sysfs framework calls .probe and .remove functions upon device
+discovery and removal (note that the .remove function is only called
+when driver is built as a module).
+
+Both functions are passed a pointer to a 'struct device', which is
+encapsulated in a 'struct eisa_device' described as follows :
+
+struct eisa_device {
+        struct eisa_device_id id;
+        int                   slot;
+        unsigned long         base_addr;
+        struct resource       res;
+        struct device         dev; /* generic device */
+};
+
+id	: EISA id, as read from device. id.driver_data is set from the
+	  matching driver EISA id.
+slot	: slot number which the device was detected on
+res	: I/O resource allocated to this device
+dev	: generic device (see Documentation/driver-model/device.txt)
+
+You can get the 'struct eisa_device' from 'struct device' using the
+'to_eisa_device' macro.
+
+** Misc stuff :
+
+void eisa_set_drvdata (struct eisa_device *edev, void *data);
+
+Stores data into the device's driver_data area.
+
+void *eisa_get_drvdata (struct eisa_device *edev):
+
+Gets the pointer previously stored into the device's driver_data area.
+
+** Random notes :
+
+Converting an EISA driver to the new API mostly involves *deleting*
+code (since probing is now in the core EISA code). Unfortunately, most
+drivers share their probing routine between ISA, MCA and EISA. Special
+care must be taken when ripping out the EISA code, so other busses
+won't suffer from these surgical strikes...
+
+You *must not* expect any EISA device to be detected when returning
+from eisa_driver_register, since the chances are that the bus has not
+yet been probed. In fact, that's what happens most of the time (the
+bus root driver usually kicks in rather late in the boot process).
+Unfortunately, most drivers are doing the probing by themselves, and
+expect to have explored the whole machine when they exit their probe
+routine.
+
+** Thanks :
+
+I'd like to thank the following people for their help :
+- Xavier Benigni for lending me a wonderful Alpha Jensen,
+- James Bottomley, Jeff Garzik for getting this stuff into the kernel,
+- Andries Brouwer for contributing numerous EISA ids,
+- Catrin Jones for coping with too many machines at home
diff -Nru a/Documentation/filesystems/Exporting b/Documentation/filesystems/Exporting
--- a/Documentation/filesystems/Exporting	Mon Apr 15 22:17:05 2002
+++ b/Documentation/filesystems/Exporting	Tue Mar 11 10:20:18 2003
@@ -45,7 +45,7 @@
    to already have a (non-connected) dentry, and must be able to move
    that dentry into place (based on the parent and name in the
    ->lookup).   This is particuarly needed for directories as
-   it is a dcache invarient that directories only have one dentry.
+   it is a dcache invariant that directories only have one dentry.
 
 To implement these features, the dcache has:
 
diff -Nru a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README
--- a/Documentation/filesystems/devfs/README	Tue Aug 20 21:09:12 2002
+++ b/Documentation/filesystems/devfs/README	Tue Mar 11 10:20:18 2003
@@ -56,7 +56,7 @@
 Operational issues (essential reading)
 
 Instructions for the impatient
-Permissions persistence accross reboots
+Permissions persistence across reboots
 Dealing with drivers without devfs support
 All the way with Devfs
 Other Issues
@@ -1465,13 +1465,6 @@
 The simplest option (especially when porting drivers to devfs) is to
 keep using the old major and minor numbers. Devfs will take whatever
 values are given for major&minor and pass them onto userspace.
-
-Alternatively, you can have devfs choose unique device numbers for
-you. When you register a character or block device using
-devfs_register you can provide the optional
-DEVFS_FL_AUTO_DEVNUM flag, which will then automatically allocate a
-unique device number (the allocation is separated for the character
-and block devices).
 
 This device number is a 16 bit number, so this leaves plenty of space
 for large numbers of discs and partitions. This scheme can also be
diff -Nru a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking
--- a/Documentation/filesystems/directory-locking	Mon Sep  9 12:31:05 2002
+++ b/Documentation/filesystems/directory-locking	Tue Mar 11 10:20:18 2003
@@ -110,4 +110,4 @@
 	Notice that "directory" in the above == "anything that might have
 children", so if we are going to introduce hybrid objects we will need
 either to make sure that link(2) doesn't work for them or to make changes
-in is_subdir() that would make it work even in presense of such beasts.
+in is_subdir() that would make it work even in presence of such beasts.
diff -Nru a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
--- a/Documentation/filesystems/ext3.txt	Fri Feb  7 00:20:33 2003
+++ b/Documentation/filesystems/ext3.txt	Tue Mar 11 10:20:18 2003
@@ -48,11 +48,11 @@
 
 sb=n			Use alternate superblock at this location.
 
-data=journal		All data are commited into the journal prior 
+data=journal		All data are committed into the journal prior 
 			to being written into the main file system.
 		
 data=ordered	(*)	All data are forced directly out to the main file 
-			system prior to its metadata being commited to 
+			system prior to its metadata being committed to 
 			the journal.
 		
 data=writeback  	Data ordering is not preserved, data may be 
diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
--- a/Documentation/filesystems/proc.txt	Mon Feb  3 04:47:42 2003
+++ b/Documentation/filesystems/proc.txt	Tue Mar 11 10:20:18 2003
@@ -344,7 +344,7 @@
 Each column represents the number of pages of a certain order which are 
 available.  In this case, there are 0 chunks of 2^0*PAGE_SIZE available in 
 ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE 
-availble in ZONE_NORMAL, etc... 
+available in ZONE_NORMAL, etc... 
 
 
 1.3 IDE devices in /proc/ide
diff -Nru a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
--- a/Documentation/filesystems/sysfs.txt	Tue Jan 14 10:27:04 2003
+++ b/Documentation/filesystems/sysfs.txt	Tue Mar 11 10:20:18 2003
@@ -55,7 +55,7 @@
 value per file, so it is socially acceptable to express an array of
 values of the same type. 
 
-Mixing types, expressing mulitple lines of data, and doing fancy
+Mixing types, expressing multiple lines of data, and doing fancy
 formatting of data is heavily frowned upon. Doing these things may get
 you publically humiliated and your code rewritten without notice. 
 
diff -Nru a/Documentation/hw_random.txt b/Documentation/hw_random.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/hw_random.txt	Thu Mar 13 15:18:14 2003
@@ -0,0 +1,134 @@
+	Hardware driver for Intel i810 Random Number Generator (RNG)
+	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+
+Introduction:
+
+	The i810_rng device driver is software that makes use of a
+	special hardware feature on the Intel i8xx-based chipsets,
+	a Random Number Generator (RNG).
+
+	In order to make effective use of this device driver, you
+	should download the support software as well.  Download the
+	latest version of the "intel-rng-tools" package from the
+	i810_rng driver's official Web site:
+
+		http://sourceforge.net/projects/gkernel/
+
+About the Intel RNG hardware, from the firmware hub datasheet:
+
+	The Firmware Hub integrates a Random Number Generator (RNG)
+	using thermal noise generated from inherently random quantum
+	mechanical properties of silicon. When not generating new random
+	bits the RNG circuitry will enter a low power state. Intel will
+	provide a binary software driver to give third party software
+	access to our RNG for use as a security feature. At this time,
+	the RNG is only to be used with a system in an OS-present state.
+
+Theory of operation:
+
+	Character driver.  Using the standard open()
+	and read() system calls, you can read random data from
+	the i810 RNG device.  This data is NOT CHECKED by any
+	fitness tests, and could potentially be bogus (if the
+	hardware is faulty or has been tampered with).  Data is only
+	output if the hardware "has-data" flag is set, but nevertheless
+	a security-conscious person would run fitness tests on the
+	data before assuming it is truly random.
+
+	/dev/intel_rng is char device major 10, minor 183.
+
+Driver notes:
+
+	* FIXME: support poll(2)
+
+	NOTE: request_mem_region was removed, for two reasons:
+	1) Only one RNG is supported by this driver, 2) The location
+	used by the RNG is a fixed location in MMIO-addressable memory,
+	3) users with properly working BIOS e820 handling will always
+	have the region in which the RNG is located reserved, so
+	request_mem_region calls always fail for proper setups.
+	However, for people who use mem=XX, BIOS e820 information is
+	-not- in /proc/iomem, and request_mem_region(RNG_ADDR) can
+	succeed.
+
+Driver details:
+
+	Based on:
+	Intel 82802AB/82802AC Firmware Hub (FWH) Datasheet
+		May 1999 Order Number: 290658-002 R
+
+	Intel 82802 Firmware Hub: Random Number Generator
+	Programmer's Reference Manual
+		December 1999 Order Number: 298029-001 R
+
+	Intel 82802 Firmware HUB Random Number Generator Driver
+	Copyright (c) 2000 Matt Sottek <msottek@quiknet.com>
+
+	Special thanks to Matt Sottek.  I did the "guts", he
+	did the "brains" and all the testing.
+
+Change history:
+
+	Version 0.9.8:
+	* Support other i8xx chipsets by adding 82801E detection
+	* 82801DB detection is the same as for 82801CA.
+
+	Version 0.9.7:
+	* Support other i8xx chipsets too (by adding 82801BA(M) and
+	  82801CA(M) detection)
+
+	Version 0.9.6:
+	* Internal driver cleanups, prep for 1.0.0 release.
+
+	Version 0.9.5:
+	* Rip out entropy injection via timer.  It never ever worked,
+	  and a better solution (rngd) is now available.
+
+	Version 0.9.4:
+	* Fix: Remove request_mem_region
+	* Fix: Horrible bugs in FIPS calculation and test execution
+
+	Version 0.9.3:
+	* Clean up rng_read a bit.
+	* Update i810_rng driver Web site URL.
+	* Increase default timer interval to 4 samples per second.
+	* Abort if mem region is not available.
+	* BSS zero-initialization cleanup.
+	* Call misc_register() from rng_init_one.
+	* Fix O_NONBLOCK to occur before we schedule.
+
+	Version 0.9.2:
+	* Simplify open blocking logic
+
+	Version 0.9.1:
+	* Support i815 chipsets too (Matt Sottek)
+	* Fix reference counting when statically compiled (prumpf)
+	* Rewrite rng_dev_read (prumpf)
+	* Make module races less likely (prumpf)
+	* Small miscellaneous bug fixes (prumpf)
+	* Use pci table for PCI id list
+
+	Version 0.9.0:
+	* Don't register a pci_driver, because we are really
+	  using PCI bridge vendor/device ids, and someone
+	  may want to register a driver for the bridge. (bug fix)
+	* Don't let the usage count go negative (bug fix)
+	* Clean up spinlocks (bug fix)
+	* Enable PCI device, if necessary (bug fix)
+	* iounmap on module unload (bug fix)
+	* If RNG chrdev is already in use when open(2) is called,
+	  sleep until it is available.
+	* Remove redundant globals rng_allocated, rng_use_count
+	* Convert numeric globals to unsigned
+	* Module unload cleanup
+
+	Version 0.6.2:
+	* Clean up spinlocks.  Since we don't have any interrupts
+	  to worry about, but we do have a timer to worry about,
+	  we use spin_lock_bh everywhere except the timer function
+	  itself.
+	* Fix module load/unload.
+	* Fix timer function and h/w enable/disable logic
+	* New timer interval sysctl
+	* Clean up sysctl names
diff -Nru a/Documentation/i810_rng.txt b/Documentation/i810_rng.txt
--- a/Documentation/i810_rng.txt	Mon Oct 28 21:14:41 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,134 +0,0 @@
-	Hardware driver for Intel i810 Random Number Generator (RNG)
-	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
-	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
-
-Introduction:
-
-	The i810_rng device driver is software that makes use of a
-	special hardware feature on the Intel i8xx-based chipsets,
-	a Random Number Generator (RNG).
-
-	In order to make effective use of this device driver, you
-	should download the support software as well.  Download the
-	latest version of the "intel-rng-tools" package from the
-	i810_rng driver's official Web site:
-
-		http://sourceforge.net/projects/gkernel/
-
-About the Intel RNG hardware, from the firmware hub datasheet:
-
-	The Firmware Hub integrates a Random Number Generator (RNG)
-	using thermal noise generated from inherently random quantum
-	mechanical properties of silicon. When not generating new random
-	bits the RNG circuitry will enter a low power state. Intel will
-	provide a binary software driver to give third party software
-	access to our RNG for use as a security feature. At this time,
-	the RNG is only to be used with a system in an OS-present state.
-
-Theory of operation:
-
-	Character driver.  Using the standard open()
-	and read() system calls, you can read random data from
-	the i810 RNG device.  This data is NOT CHECKED by any
-	fitness tests, and could potentially be bogus (if the
-	hardware is faulty or has been tampered with).  Data is only
-	output if the hardware "has-data" flag is set, but nevertheless
-	a security-conscious person would run fitness tests on the
-	data before assuming it is truly random.
-
-	/dev/intel_rng is char device major 10, minor 183.
-
-Driver notes:
-
-	* FIXME: support poll(2)
-
-	NOTE: request_mem_region was removed, for two reasons:
-	1) Only one RNG is supported by this driver, 2) The location
-	used by the RNG is a fixed location in MMIO-addressable memory,
-	3) users with properly working BIOS e820 handling will always
-	have the region in which the RNG is located reserved, so
-	request_mem_region calls always fail for proper setups.
-	However, for people who use mem=XX, BIOS e820 information is
-	-not- in /proc/iomem, and request_mem_region(RNG_ADDR) can
-	succeed.
-
-Driver details:
-
-	Based on:
-	Intel 82802AB/82802AC Firmware Hub (FWH) Datasheet
-		May 1999 Order Number: 290658-002 R
-
-	Intel 82802 Firmware Hub: Random Number Generator
-	Programmer's Reference Manual
-		December 1999 Order Number: 298029-001 R
-
-	Intel 82802 Firmware HUB Random Number Generator Driver
-	Copyright (c) 2000 Matt Sottek <msottek@quiknet.com>
-
-	Special thanks to Matt Sottek.  I did the "guts", he
-	did the "brains" and all the testing.
-
-Change history:
-
-	Version 0.9.8:
-	* Support other i8xx chipsets by adding 82801E detection
-	* 82801DB detection is the same as for 82801CA.
-
-	Version 0.9.7:
-	* Support other i8xx chipsets too (by adding 82801BA(M) and
-	  82801CA(M) detection)
-
-	Version 0.9.6:
-	* Internal driver cleanups, prep for 1.0.0 release.
-
-	Version 0.9.5:
-	* Rip out entropy injection via timer.  It never ever worked,
-	  and a better solution (rngd) is now available.
-
-	Version 0.9.4:
-	* Fix: Remove request_mem_region
-	* Fix: Horrible bugs in FIPS calculation and test execution
-
-	Version 0.9.3:
-	* Clean up rng_read a bit.
-	* Update i810_rng driver Web site URL.
-	* Increase default timer interval to 4 samples per second.
-	* Abort if mem region is not available.
-	* BSS zero-initialization cleanup.
-	* Call misc_register() from rng_init_one.
-	* Fix O_NONBLOCK to occur before we schedule.
-
-	Version 0.9.2:
-	* Simplify open blocking logic
-
-	Version 0.9.1:
-	* Support i815 chipsets too (Matt Sottek)
-	* Fix reference counting when statically compiled (prumpf)
-	* Rewrite rng_dev_read (prumpf)
-	* Make module races less likely (prumpf)
-	* Small miscellaneous bug fixes (prumpf)
-	* Use pci table for PCI id list
-
-	Version 0.9.0:
-	* Don't register a pci_driver, because we are really
-	  using PCI bridge vendor/device ids, and someone
-	  may want to register a driver for the bridge. (bug fix)
-	* Don't let the usage count go negative (bug fix)
-	* Clean up spinlocks (bug fix)
-	* Enable PCI device, if necessary (bug fix)
-	* iounmap on module unload (bug fix)
-	* If RNG chrdev is already in use when open(2) is called,
-	  sleep until it is available.
-	* Remove redundant globals rng_allocated, rng_use_count
-	* Convert numeric globals to unsigned
-	* Module unload cleanup
-
-	Version 0.6.2:
-	* Clean up spinlocks.  Since we don't have any interrupts
-	  to worry about, but we do have a timer to worry about,
-	  we use spin_lock_bh everywhere except the timer function
-	  itself.
-	* Fix module load/unload.
-	* Fix timer function and h/w enable/disable logic
-	* New timer interval sysctl
-	* Clean up sysctl names
diff -Nru a/Documentation/ia64/IRQ-redir.txt b/Documentation/ia64/IRQ-redir.txt
--- a/Documentation/ia64/IRQ-redir.txt	Sat Mar  9 02:24:39 2002
+++ b/Documentation/ia64/IRQ-redir.txt	Tue Mar 11 10:20:18 2003
@@ -29,7 +29,7 @@
 The output of the command
      cat /proc/irq/IRQ#/smp_affinity
 gives the target CPU mask for the specified interrupt vector. If the CPU
-mask is preceeded by the character "r", the interrupt is redirectable
+mask is preceded by the character "r", the interrupt is redirectable
 (i.e. lowest priority mode routing is used), otherwise its route is
 fixed.
 
diff -Nru a/Documentation/ia64/fsys.txt b/Documentation/ia64/fsys.txt
--- a/Documentation/ia64/fsys.txt	Mon Jan 27 10:57:50 2003
+++ b/Documentation/ia64/fsys.txt	Wed Feb 12 00:11:32 2003
@@ -4,7 +4,7 @@
 		-----------------------------------
 
 		        Started: 13-Jan-2003
-		    Last update: 24-Jan-2003
+		    Last update: 11-Feb-2003
 
 	              David Mosberger-Tang
 		      <davidm@hpl.hp.com>
@@ -42,9 +42,9 @@
     can disable interrupts and avoid all other interruption-sources
     to avoid preemption)
 
-  - neither the memory nor the register stack can be trusted while
+  - neither the memory-stack nor the register-stack can be trusted while
     in fsys-mode (they point to the user-level stacks, which may
-    be invalid)
+    be invalid, or completely bogus addresses)
 
 In summary, fsys-mode is much more similar to running in user-mode
 than it is to running in kernel-mode.  Of course, given that the
diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt
--- a/Documentation/ide.txt	Mon Jul 29 18:48:20 2002
+++ b/Documentation/ide.txt	Tue Mar 11 10:20:18 2003
@@ -4,7 +4,7 @@
 ==============================================================================
 
    
-   The hdparm utility can be used to controll various IDE features on a
+   The hdparm utility can be used to control various IDE features on a
    running system. It is packaged separately.  Please Look for it on popular
    linux FTP sites.
    
@@ -37,7 +37,7 @@
 ================================================================================
 Common pitfalls:
 
-- 40-conductor IDE cables are capable of transfering data in DMA modes up to
+- 40-conductor IDE cables are capable of transferring data in DMA modes up to
   udma2, but no faster.
 
 - If possible devices should be attached to separate channels if they are
diff -Nru a/Documentation/input/ff.txt b/Documentation/input/ff.txt
--- a/Documentation/input/ff.txt	Wed Sep  4 13:10:37 2002
+++ b/Documentation/input/ff.txt	Tue Mar 11 10:20:18 2003
@@ -163,7 +163,7 @@
 ~~~~~~~~~~~~~~~~~~~~
 Not all devices have the same strength. Therefore, users should set a gain
 factor depending on how strong they want effects to be. This setting is
-persistent accross access to the driver, so you should not care about it if
+persistent across access to the driver, so you should not care about it if
 you are writing games, as another utility probably already set this for you.
 
 /* Set the gain of the device
@@ -200,7 +200,7 @@
 Proceed as if you wanted to upload a new effect, except that instead of
 setting the id field to -1, you set it to the wanted effect id.
 Normally, the effect is not stopped and restarted. However, depending on the
-type of device, not all paramaters can be dynamically updated. For example,
+type of device, not all parameters can be dynamically updated. For example,
 the direction of an effect cannot be updated with iforce devices. In this
 case, the driver stops the effect, up-load it, and restart it.
 
diff -Nru a/Documentation/isdn/INTERFACE b/Documentation/isdn/INTERFACE
--- a/Documentation/isdn/INTERFACE	Mon Feb  4 23:38:55 2002
+++ b/Documentation/isdn/INTERFACE	Tue Mar 11 10:20:18 2003
@@ -735,7 +735,7 @@
       driver      = driver-Id
       command     = ISDN_STAT_PROT
       arg         = The lower 8 Bits define the addressed protocol as defined
-                    in ISDN_PTYPE..., the upper bits are used to differenciate
+                    in ISDN_PTYPE..., the upper bits are used to differentiate
                     the protocol specific STAT.  
       
       para        = protocol and function specific. See isdnif.h for detail.
diff -Nru a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
--- a/Documentation/kbuild/kconfig-language.txt	Thu Nov  7 16:40:58 2002
+++ b/Documentation/kbuild/kconfig-language.txt	Tue Mar 11 10:20:18 2003
@@ -69,7 +69,7 @@
   default values are visible, only the first defined one is active.
   Default values are not limited to the menu entry, where they are
   defined, this means the default can be defined somewhere else or be
-  overriden by an earlier definition.
+  overridden by an earlier definition.
   The default value is only assigned to the config symbol if no other
   value was set by the user (via the input prompt above). If an input
   prompt is visible the default value is presented to the user and can
@@ -142,7 +142,7 @@
 --------------
 
 The position of a menu entry in the tree is determined in two ways. First
-it can be specified explicitely:
+it can be specified explicitly:
 
 menu "Network device support"
 	depends NET
diff -Nru a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
--- a/Documentation/kbuild/makefiles.txt	Sun Jan 26 11:23:48 2003
+++ b/Documentation/kbuild/makefiles.txt	Sat Mar 15 21:52:28 2003
@@ -10,7 +10,7 @@
 	   --- 3.1 Goal definitions
 	   --- 3.2 Built-in object goals - obj-y
 	   --- 3.3 Loadable module goals - obj-m
-	   --- 3.4 Objects which export symbols - export-objs
+	   --- 3.4 Objects which export symbols
 	   --- 3.5 Library file goals - L_TARGET
 	   --- 3.6 Descending down in directories
 	   --- 3.7 Compilation flags
@@ -208,32 +208,11 @@
 	kbuild will build an ext2.o file for you out of the individual
 	parts and then link this into built-in.o, as you would expect.
 
---- 3.4 Objects which export symbols - export-objs
+--- 3.4 Objects which export symbols
 
-	When using loadable modules, not every global symbol in the
-	kernel / other modules is automatically available, only those
-	explicitly exported are available for your module.
-
-	To make a symbol available for use in modules, to "export" it,
-	use the EXPORT_SYMBOL(<symbol>) directive in your source. In
-	addition, you need to list all object files which export symbols
-	(i.e. their source contains an EXPORT_SYMBOL() directive) in the
-	Makefile variable $(export-objs).
-
-	Example:
-		#drivers/isdn/i4l/Makefile
-		# Objects that export symbols.
-		export-objs     := isdn_common.o
-
-	since isdn_common.c contains
-
-	    EXPORT_SYMBOL(register_isdn);
-
-	which makes the function register_isdn available to
-	low-level ISDN drivers.
-	There exist a EXPORT_SYMBOL_GPL() variant with similar functionality,
-	but more restrictive with what may use that symbol. The requirement
-	to list the .o file in export-objs is the same.
+	No special notation is required in the makefiles for
+	modules exporting symbols.
+	See also Documentation/modules.txt.
 
 --- 3.5 Library file goals - L_TARGET
 
@@ -400,7 +379,7 @@
 
 The second step is to add an explicit dependency to the executable.
 This can be done in two ways. Either add the dependency in a rule, 
-or utilise the variable build-targets.
+or utilise the variable $(always).
 Both possibilities are described in the following.
 
 --- 4.1 Simple Host Program
@@ -526,15 +505,15 @@
 	$(obj)/gen-devlist is updated. Note that references to
 	the host programs in special rules must be prefixed with $(obj).
 
-	(2) Use $(build-targets)
+	(2) Use $(always)
 	When there is no suitable special rule, and the host program
-	shall be built when a makefile is entered, the $(build-targets)
+	shall be built when a makefile is entered, the $(always)
 	variable shall be used.
 
 	Example:
 		#scripts/lxdialog/Makefile
 		host-progs    := lxdialog
-		build-targets := $(host-progs)
+		always        := $(host-progs)
 
 	This will tell kbuild to build lxdialog even if not referenced in
 	any rule.
@@ -543,13 +522,13 @@
 
 "make clean" deletes most generated files in the src tree where the kernel
 is compiled. This includes generated files such as host programs.
-Kbuild knows targets listed in $(host-progs) and $(EXTRA_TARGETS) and
-they are all deleted during "make clean".
+Kbuild knows targets listed in $(host-progs), $(always), $(extra-y) and
+$(targets). They are all deleted during "make clean".
 Files matching the patterns "*.[oas]", "*.ko", plus some additional files
 generated by kbuild are deleted all over the kernel src tree when
 "make clean" is executed.
 
-Additional files can be specified by means of $(clean-files).
+Additional files can be specified in kbuild makefiles by use of $(clean-files).
 
 	Example:
 		#drivers/pci/Makefile
@@ -561,7 +540,7 @@
 
 Usually kbuild descends down in subdirectories due to "obj-* := dir/",
 but in the architecture makefiles where the kbuild infrastructure
-is not sufficent this sometimes needs to be explicit.
+is not sufficient this sometimes needs to be explicit.
 
 	Example:
 		#arch/i386/boot/Makefile
@@ -818,31 +797,23 @@
 
 --- 6.5 Building non-kbuild targets
 
-    EXTRA_TARGETS
+    extra-y
 
-	EXTRA_TARGETS specify additional targets created in current
+	extra-y specify additional targets created in current
 	directory, in addition to any targets specified by obj-*.
 
-	Listing all targets in EXTRA_TARGETS is required for three purposes:
-	1) Avoid that the target is linked in as part of built-in.o
-	2) Enable kbuild to check changes in command lines
+	Listing all targets in extra-y is required for two purposes:
+	1) Enable kbuild to check changes in command lines
 	   - When $(call if_changed,xxx) is used
-	3) kbuild knows what file to delete during "make clean"
+	2) kbuild knows what files to delete during "make clean"
 
 	Example:
 		#arch/i386/kernel/Makefile
-		EXTRA_TARGETS := head.o init_task.o
+		extra-y := head.o init_task.o
 
-	In this example EXTRA_TARGETS is used to list object files that
+	In this example extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
-	Example:
-		#arch/i386/boot/Makefile
-		EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o
-
-	In this example EXTRA_TARGETS is used to list all intermediate
-	targets, and all final targets.
-	The targets are added to EXTRA_TARGETS to enable 2) and 3) above.
 	
 --- 6.6 Commands useful for building a boot image
 
@@ -861,9 +832,10 @@
 	needs an update, or the commandline has changed since last
 	invocation. The latter will force a rebuild if any options
 	to the executable have changed.
-	Any target that utilises if_changed must be listed in EXTRA_TARGETS,
+	Any target that utilises if_changed must be listed in $(targets),
 	otherwise the command line check will fail, and the target will
 	always be built.
+	Assignments to $(targets) are without $(obj)/ prefix.
 	if_changed may be used in conjunction with custom commands as
 	defined in 6.7 "Custom kbuild commands".
 	Note: It is a typical mistake to forget the FORCE prerequisite.
@@ -874,10 +846,34 @@
     objcopy
 	Copy binary. Uses OBJCOPYFLAGS usually specified in
 	arch/$(ARCH)/Makefile.
+	OBJCOPYFLAGS_$@ may be used to set additional options.
 
     gzip
 	Compress target. Use maximum compression to compress target.
 
+	Example:
+		#arch/i386/boot/Makefile
+		LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
+		LDFLAGS_setup    := -Ttext 0x0 -s --oformat binary -e begtext
+
+		targets += setup setup.o bootsect bootsect.o
+		$(obj)/setup $(obj)/bootsect: %: %.o FORCE
+			$(call if_changed,ld)
+
+	In this example there is two possible targets, requiring different
+	options to the linker. the linker options are specified using the
+	LDFLAGS_$@ syntax - one for each potential target.
+	$(targets) are assinged all potential targets, herby kbuild knows
+	the targets and will:
+		1) check for commandline changes
+		2) delete target during make clean
+
+	The ": %: %.o" part of the prerequisite is a shorthand that
+	free us from listing the setup.o and bootsect.o files.
+	Note: It is a common mistake to forget the "target :=" assignment,
+	      resulting in the target file being recompiled for no
+	      obvious reason.
+
 
 --- 6.7 Custom kbuild commands
 
@@ -894,6 +890,7 @@
 		      cmd_image = $(obj)/tools/build $(BUILDFLAGS) \
 		                                     $(obj)/vmlinux.bin > $@
 
+		targets += bzImage
 		$(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 			$(call if_changed,image)
 			@echo 'Kernel: $@ is ready'
diff -Nru a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
--- a/Documentation/kernel-doc-nano-HOWTO.txt	Wed Jul 24 16:03:18 2002
+++ b/Documentation/kernel-doc-nano-HOWTO.txt	Tue Mar 11 10:20:18 2003
@@ -21,7 +21,7 @@
 
   This is a program for converting SGML template files into SGML
   files. When a file is referenced it is searched for symbols
-  exported (EXPORT_SYMBOL), to be able to distingush between internal
+  exported (EXPORT_SYMBOL), to be able to distinguish between internal
   and external functions.
   It invokes kernel-doc, giving it the list of functions that
   are to be documented.
diff -Nru a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
--- a/Documentation/kernel-docs.txt	Sun Sep 29 15:17:10 2002
+++ b/Documentation/kernel-docs.txt	Tue Mar 11 10:20:18 2003
@@ -488,7 +488,7 @@
        memory allocation.
        Description: Article written for people wishing to make their data
        acquisition boards work on their GNU/Linux machines. Gives a basic
-       overview on writting drivers, from the naming of functions to
+       overview on writing drivers, from the naming of functions to
        interrupt handling.
        Notes: Two-parts article. Part II is at
        http://www.ednmag.com/ednmag/reg/2000/07062000/14df.htm
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	Wed Feb 26 15:06:12 2003
+++ b/Documentation/kernel-parameters.txt	Sun Mar 16 22:33:11 2003
@@ -71,6 +71,8 @@
 
 Parameters denoted with BOOT are actually interpreted by the boot
 loader, and have no meaning to the kernel directly.
+Do not modify the syntax of boot loader parameters without extreme
+need or coordination with <Documentation/i386/boot.txt>.
 
 Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
 a trailing = on the name of any parameter states that that parameter will
@@ -502,30 +504,30 @@
 			Format: <first>,<last>
 			Specifies range of consoles to be captured by the MDA.
  
-	mem=exactmap	[KNL,BOOT,IA-32] Enable setting of an exact
-			E820 memory map, as specified by the user.
-			Such mem=exactmap lines can be constructed based on
-			BIOS output or other requirements. See the mem=nn@ss
-			option description.
-
 	mem=nn[KMG]	[KNL,BOOT] Force usage of a specific amount of memory
 			Amount of memory to be used when the kernel is not able
 			to see the whole system memory or for test.
 
-	mem=nn[KMG]@ss[KMG]
-			[KNL,BOOT] Force usage of a specific region of memory
-			Region of memory to be used, from ss to ss+nn.
+	mem=nopentium	[BUGS=IA-32] Disable usage of 4MB pages for kernel
+			memory.
 
-	mem=nn[KMG]#ss[KMG]
-			[KNL,BOOT,ACPI] Mark specific memory as ACPI data.
+	memmap=exactmap	[KNL,IA-32] Enable setting of an exact
+			E820 memory map, as specified by the user.
+			Such memmap=exactmap lines can be constructed based on
+			BIOS output or other requirements. See the memmap=nn@ss
+			option description.
+
+	memmap=nn[KMG]@ss[KMG]
+			[KNL] Force usage of a specific region of memory
 			Region of memory to be used, from ss to ss+nn.
 
-	mem=nn[KMG]$ss[KMG]
-			[KNL,BOOT,ACPI] Mark specific memory as reserved.
+	memmap=nn[KMG]#ss[KMG]
+			[KNL,ACPI] Mark specific memory as ACPI data.
 			Region of memory to be used, from ss to ss+nn.
 
-	mem=nopentium	[BUGS=IA-32] Disable usage of 4MB pages for kernel
-			memory.
+	memmap=nn[KMG]$ss[KMG]
+			[KNL,ACPI] Mark specific memory as reserved.
+			Region of memory to be used, from ss to ss+nn.
 
 	memfrac=	[KNL]
 
diff -Nru a/Documentation/kobject.txt b/Documentation/kobject.txt
--- a/Documentation/kobject.txt	Tue Jan  7 09:25:38 2003
+++ b/Documentation/kobject.txt	Tue Mar 11 10:20:18 2003
@@ -7,7 +7,7 @@
 
 0. Introduction
 
-The kobject infrastructure performs basic object managment that larger
+The kobject infrastructure performs basic object management that larger
 data structures and subsystems can leverage, rather than reimplement
 similar functionality. This functionality consists primarily concerns:
 
diff -Nru a/Documentation/magic-number.txt b/Documentation/magic-number.txt
--- a/Documentation/magic-number.txt	Mon Nov 11 12:32:58 2002
+++ b/Documentation/magic-number.txt	Tue Mar 11 10:20:18 2003
@@ -146,7 +146,7 @@
 NMI_MAGIC             0x48414d4d455201 nmi_s        include/asm-mips64/sn/nmi.h
 
 Note that there are also defined special per-driver magic numbers in sound
-memory managment. See include/sound/sndmagic.h for complete list of them. Many
+memory management. See include/sound/sndmagic.h for complete list of them. Many
 OSS sound drivers have their magic numbers constructed from the soundcard PCI
 ID - these are not listed here as well.
 
diff -Nru a/Documentation/md.txt b/Documentation/md.txt
--- a/Documentation/md.txt	Fri Feb  7 00:20:36 2003
+++ b/Documentation/md.txt	Tue Mar 11 18:46:37 2003
@@ -1,10 +1,10 @@
 Tools that manage md devices can be found at
-   http://www.<country>.kernel.org/pub/linux/daemons/raid/....
+   http://www.<country>.kernel.org/pub/linux/utils/raid/....
 
 
 
-You can boot (if you selected boot support in the configuration) with your md 
-device with the following kernel command lines:
+You can boot with your md device with the following kernel command
+lines:
 
 for old raid arrays without persistent superblocks:
   md=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn
@@ -33,4 +33,64 @@
 A possible loadlin line (Harald Hoyer <HarryH@Royal.Net>)  looks like this:
 
 e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
-			    
+
+-------------------------------
+The md driver can support a variety of different superblock formats.
+(It doesn't yet, but it can)
+
+The kernel does *NOT* autodetect which format superblock is being
+used. It must be told.
+
+Superblock format '0' is treated differently to others for legacy
+reasons.
+
+
+General Rules - apply for all superblock formats
+------------------------------------------------
+
+An array is 'created' by writing appropriate superblocks to all
+devices.
+It is 'assembled' by associating each of these devices with an
+particular md virtual device.  Once it is completely assembled, it can
+be accessed.
+
+An array should be created by a user-space tool.  This will write
+superblocks to all devices.  It will usually mark the array as
+'unclean', or with some devices missing so that the kernel md driver
+can create approrpriate redundancy (copying in raid1, parity
+calculation in raid4/5).
+
+When an array is assembled, it is first initialised with the
+SET_ARRAY_INFO ioctl.  This contains, in particular, a major and minor
+version number.  The major version number selects which superblock
+format is to be used.  The minor number might be used to tune handling
+of the format, such as suggesting where on each device to look for the
+superblock.
+
+Then each device is added using the ADD_NEW_DISK ioctl.  This
+provides, in particular, a major and minor number identifying the
+device to add.
+
+The array is started with the RUN_ARRAY ioctl.
+
+Once started, new devices can be added.  They should have an
+appropriate superblock written to them, and then passed be in with
+ADD_NEW_DISK.
+
+Devices that have failed or are not yet active can be detached from an
+array using HOT_REMOVE_DISK.
+
+
+Specific Rules that apply to format-0 super block arrays, and
+       arrays with no superblock (non-presistant).
+-------------------------------------------------------------
+
+An array can be 'created' by describing the array (level, chunksize
+etc) in a SET_ARRAY_INFO ioctl.  This must has major_version==0 and
+raid_disks != 0.
+Then uninitialised devices can be added with ADD_NEW_DISK.  The
+structure passed to ADD_NEW_DISK must specify the state of the device
+and it's role in the array.
+
+One started with RUN_ARRAY, uninitialised spares can be added with
+HOT_ADD_DISK.
diff -Nru a/Documentation/networking/3c359.txt b/Documentation/networking/3c359.txt
--- a/Documentation/networking/3c359.txt	Sun Feb 17 08:04:00 2002
+++ b/Documentation/networking/3c359.txt	Tue Mar 11 10:20:18 2003
@@ -41,7 +41,7 @@
 message_level: Controls level of messages created by the driver. Defaults to 0:
 which only displays start-up and critical messages.  Presently any non-zero 
 value will display all soft messages as well.  NB This does not turn 
-debuging messages on, that must be done by modified the source code.
+debugging messages on, that must be done by modified the source code.
 
 Variable MTU size:
 
diff -Nru a/Documentation/networking/3c509.txt b/Documentation/networking/3c509.txt
--- a/Documentation/networking/3c509.txt	Tue Apr 30 23:05:25 2002
+++ b/Documentation/networking/3c509.txt	Tue Mar 11 10:20:18 2003
@@ -106,7 +106,7 @@
 8  transceiver type and duplex mode taken from card's EEPROM config settings
 12 10baseT (RJ-45 connector); force full-duplex mode
 
-Prior to driver version 1.18c, only tranceiver codes 0-4 were supported. Note
+Prior to driver version 1.18c, only transceiver codes 0-4 were supported. Note
 that the new transceiver codes 8 and 12 are the *only* ones that will enable
 full-duplex mode, no matter what the card's detected EEPROM settings might be.
 This insured that merely upgrading the driver from an earlier version would
@@ -146,7 +146,7 @@
 Tx Carrier Errors Reported in /proc/net/dev 
 If an EtherLink III appears to transmit packets, but the "Tx carrier errors"
 field in /proc/net/dev increments as quickly as the Tx packet count, you
-likely have an unterminated network or the incorrect media tranceiver selected. 
+likely have an unterminated network or the incorrect media transceiver selected. 
 
 3c509B card is not detected on machines with an ISA PnP BIOS. 
 While the updated driver works with most PnP BIOS programs, it does not work
diff -Nru a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt
--- a/Documentation/networking/NAPI_HOWTO.txt	Fri Jan 10 01:10:02 2003
+++ b/Documentation/networking/NAPI_HOWTO.txt	Tue Mar 11 10:20:18 2003
@@ -85,7 +85,7 @@
 	In this case your only choice is to move all to dev->poll()
 
 	II) Clear-on-write (COW)
-	 i) you clear the status by writting a 1 in the bit-location you want.
+	 i) you clear the status by writing a 1 in the bit-location you want.
 		These are the majority of the NICs and work the best with NAPI.
 		Put only receive events in dev->poll(); leave the rest in
 		the old interrupt handler.
@@ -200,7 +200,7 @@
 /* two new additions */
 /* first register my poll method */
 dev->poll = my_poll;
-/* next register my weight/quanta; can be overriden in /proc */
+/* next register my weight/quanta; can be overridden in /proc */
 dev->weight = 16;
 .
 .
@@ -346,10 +346,10 @@
 netif_rx_schedule_prep() returns 1 if device is in running state and
 gets successfully added to the core poll list. If we get a zero value
 we can _almost_ assume are already added to the list (instead of not running. 
-Logic based on the fact that you shouldnt get interrupt if not running)
+Logic based on the fact that you shouldn't get interrupt if not running)
 We rectify this by disabling rx and rxnobuf interrupts.
 
-II) that receive_packets(dev) and make_rx_buffs_avail() may have dissapeared.
+II) that receive_packets(dev) and make_rx_buffs_avail() may have disappeared.
 These functionalities are still around actually......
 
 infact, receive_packets(dev) is very close to my_poll() and 
@@ -442,7 +442,7 @@
 	int rx_work_limit = dev->quota;
 
 /************************ end note note *********************************/		
-    do {  // outer beggining loop starts here
+    do {  // outer beginning loop starts here
 
 	clear_rx_status_register_bit();
 
diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
--- a/Documentation/networking/bonding.txt	Tue Feb 18 10:50:37 2003
+++ b/Documentation/networking/bonding.txt	Tue Mar 11 10:20:18 2003
@@ -304,7 +304,7 @@
 Configuring Multiple ARP Targets
 ================================
 
-While ARP monitoring can be done with just one target, it can be usefull
+While ARP monitoring can be done with just one target, it can be useful
 in a High Availability setup to have several targets to monitor. In the
 case of just one target,  the target itself may go down or have a problem
 making it unresponsive to ARP requests. Having an additional target (or
diff -Nru a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
--- a/Documentation/networking/ifenslave.c	Tue Feb 25 10:47:06 2003
+++ b/Documentation/networking/ifenslave.c	Tue Mar 11 10:20:18 2003
@@ -540,7 +540,7 @@
 
 static short mif_flags;
 
-/* Get the inteface configuration from the kernel. */
+/* Get the interface configuration from the kernel. */
 static int if_getconfig(char *ifname)
 {
 	struct ifreq ifr;
diff -Nru a/Documentation/networking/sis900.txt b/Documentation/networking/sis900.txt
--- a/Documentation/networking/sis900.txt	Tue Feb  5 09:40:36 2002
+++ b/Documentation/networking/sis900.txt	Tue Mar 11 10:20:18 2003
@@ -243,7 +243,7 @@
 Chapter 7. Revision History
 
      * November 13, 2000, Revision 1.07, seventh release, 630E problem
-       fixed and furthur clean up.
+       fixed and further clean up.
      * November 4, 1999, Revision 1.06, Second release, lots of clean up
        and optimization.
      * August 8, 1999, Revision 1.05, Initial Public Release
diff -Nru a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt
--- a/Documentation/networking/sk98lin.txt	Mon Feb 24 12:31:17 2003
+++ b/Documentation/networking/sk98lin.txt	Tue Mar 11 10:20:18 2003
@@ -138,7 +138,7 @@
 options sk98lin ...
 
 For "...", use the same syntax as described below for the command
-line paramaters of modprobe.
+line parameters of modprobe.
 You either have to reboot your computer or unload and reload
 the driver to activate the new parameters.
 The syntax of the driver parameters is:
@@ -276,7 +276,7 @@
 
 Large frames (also called jumbo frames) are now supported by the
 driver. This can result in a greatly improved throughput if
-transfering large amounts of data.
+transferring large amounts of data.
 To enable large frames, set the MTU (maximum transfer unit)
 of the interface to the value you wish (up to 9000). The command
 for this is:
@@ -489,7 +489,7 @@
   established (#10402)
 - Installation problems with RedHat 6.0 (#10409)
 New Features:
-- Connection state ouput at "network connection up"
+- Connection state output at "network connection up"
 Known limitations:
 - None
 
diff -Nru a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
--- a/Documentation/networking/tuntap.txt	Tue Oct  1 15:41:57 2002
+++ b/Documentation/networking/tuntap.txt	Tue Mar 11 10:20:18 2003
@@ -40,7 +40,7 @@
   
   Set permissions:
      e.g. chmod 0700 /dev/net/tun
-     if you want the device only accesible by root. Giving regular users the
+     if you want the device only accessible by root. Giving regular users the
      right to assign network devices is NOT a good idea. Users could assign
      bogus network interfaces to trick firewalls or administrators.
 
diff -Nru a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt
--- a/Documentation/networking/wan-router.txt	Mon Feb  4 23:39:16 2002
+++ b/Documentation/networking/wan-router.txt	Tue Mar 11 10:20:18 2003
@@ -577,7 +577,7 @@
 bata2-2.2.1	Feb 20 2001
 
 			o Bug fixes to the CHDLC device drivers.
-				The driver had compilation problmes under kernels
+				The driver had compilation problems under kernels
 				2.2.14 or lower.
 
 			o Bug fixes to the Setup installation script.
diff -Nru a/Documentation/networking/wanpipe.txt b/Documentation/networking/wanpipe.txt
--- a/Documentation/networking/wanpipe.txt	Mon Feb  4 23:39:16 2002
+++ b/Documentation/networking/wanpipe.txt	Tue Mar 11 10:20:18 2003
@@ -577,7 +577,7 @@
 bata2-2.2.1	Feb 20 2001
 
 			o Bug fixes to the CHDLC device drivers.
-				The driver had compilation problmes under kernels
+				The driver had compilation problems under kernels
 				2.2.14 or lower.
 
 			o Bug fixes to the Setup installation script.
diff -Nru a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
--- a/Documentation/oops-tracing.txt	Mon Dec 31 19:24:58 2001
+++ b/Documentation/oops-tracing.txt	Tue Mar 11 10:20:18 2003
@@ -219,7 +219,7 @@
   2: 'F' if any module was force loaded by insmod -f, ' ' if all
      modules were loaded normally.
 
-  3: 'S' if the oops occured on an SMP kernel running on hardware that
+  3: 'S' if the oops occurred on an SMP kernel running on hardware that
       hasn't been certified as safe to run multiprocessor.
 	  Currently this occurs only on various Athlons that are not
 	  SMP capable.
diff -Nru a/Documentation/pnp.txt b/Documentation/pnp.txt
--- a/Documentation/pnp.txt	Tue Feb 18 10:25:13 2003
+++ b/Documentation/pnp.txt	Tue Mar 11 10:20:18 2003
@@ -96,7 +96,7 @@
 	All Plug and Play drivers, protocols, and services meet at a central location 
 called the Plug and Play Layer.  This layer is responsible for the exchange of 
 information between PnP drivers and PnP protocols.  Thus it automatically 
-forwards commands to the proper protocol.  This makes writting PnP drivers 
+forwards commands to the proper protocol.  This makes writing PnP drivers 
 significantly easier.
 
 The following functions are available from the Plug and Play Layer:
diff -Nru a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt
--- a/Documentation/s390/Debugging390.txt	Tue Feb 18 10:31:36 2003
+++ b/Documentation/s390/Debugging390.txt	Tue Mar 11 10:20:18 2003
@@ -52,7 +52,7 @@
  
 16  General propose registers, 32 bit on s/390 64 bit on z/Architecture, r0-r15 or gpr0-gpr15 used for arithmetic & addressing. 
 
-16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory managment,
+16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory management,
 interrupt control,debugging control etc.
 
 16 Access registers ( ar0-ar15 ) 32 bit on s/390 & z/Architecture
@@ -243,7 +243,7 @@
 spaces for the user & kernel.
 
 This means we can support 2GB of non Extended RAM on s/390, & more
-with the Extended memory managment swap device & 
+with the Extended memory management swap device & 
 currently 4TB of physical memory currently on z/Architecture.
 
 
@@ -385,7 +385,7 @@
 of extra space on the callers stack which is obviously freed
 up on function exit ( e.g. the caller may choose to allocate nothing
 of a buffer of 4k if required for temporary purposes ), it generates 
-very efficent code ( a few cycles  ) when compared to alternatives 
+very efficient code ( a few cycles  ) when compared to alternatives 
 like malloc.
 
 automatics: These are local variables on the stack,
@@ -1091,7 +1091,7 @@
 The VM Debugger is case insensitive.
 
 VM's strengths are usually other debuggers weaknesses you can get at any resource
-no matter how sensitive e.g. memory managment resources,change address translation
+no matter how sensitive e.g. memory management resources,change address translation
 in the PSW. For kernel hacking you will reap dividends if you get good at it.
 
 The VM Debugger displays operators but not operands, probably because some
@@ -1194,7 +1194,7 @@
 Displaying & modifying Registers
 --------------------------------
 D G will display all the gprs
-Adding a extra G to all the commands is neccessary to access the full 64 bit 
+Adding a extra G to all the commands is necessary to access the full 64 bit 
 content in VM on z/Architecture obviously this isn't required for access registers
 as these are still 32 bit.
 e.g. DGG instead of DG 
@@ -1280,7 +1280,7 @@
 
 Tracing particular processes
 ----------------------------
-The kernels text segment is intentionally at an address in memory that it will
+The kernel's text segment is intentionally at an address in memory that it will
 very seldom collide with text segments of user programs ( thanks Martin ),
 this simplifies debugging the kernel.
 However it is quite common for user processes to have addresses which collide
@@ -1425,7 +1425,7 @@
 shutdown -h now or halt.
 do a Q CPUS to find out how many cpus you have
 detach each one of them from cp except cpu 0 
-by issueing a 
+by issuing a 
 DETACH CPU 01-(number of cpus in configuration)
 & boot linux again.
 TR SIGP will trace inter processor signal processor instructions.
@@ -1671,7 +1671,7 @@
 ( & many other instructions ) they consist of a length field & an absolute address field.
 For each IO typically get 1 or 2 interrupts one for channel end ( primary status ) when the
 channel is idle & the second for device end ( secondary status ) sometimes you get both
-concurrently, you check how the IO went on by issueing a TEST SUBCHANNEL at each interrupt,
+concurrently, you check how the IO went on by issuing a TEST SUBCHANNEL at each interrupt,
 from which you receive an Interruption response block (IRB). If you get channel & device end 
 status in the IRB without channel checks etc. your IO probably went okay. If you didn't you
 probably need a doctorto examine the IRB & extended status word etc.
@@ -2153,14 +2153,14 @@
 current working directory.
 This is very useful in that a customer can mail a core dump to a technical support department
 & the technical support department can reconstruct what happened.
-Provided the have an indentical copy of this program with debugging symbols compiled in & 
+Provided the have an identical copy of this program with debugging symbols compiled in & 
 the source base of this build is available.
 In short it is far more useful than something like a crash log could ever hope to be.
 
 In theory all that is missing to restart a core dumped program is a kernel patch which
 will do the following.
 1) Make a new kernel task structure
-2) Reload all the dumped pages back into the kernels memory managment structures.
+2) Reload all the dumped pages back into the kernel's memory management structures.
 3) Do the required clock fixups
 4) Get all files & network connections for the process back into an identical state ( really difficult ).
 5) A few more difficult things I haven't thought of.
@@ -2374,7 +2374,7 @@
 e.g. 
 to switch on the lcs "debug feature"
 echo 5 > /proc/s390dbf/lcs/level
-& then after the error occured.
+& then after the error occurred.
 cat /proc/s390dbf/lcs/sprintf >/logfile
 the logfile now contains some information which may help
 tech support resolve a problem in the field.
@@ -2462,9 +2462,9 @@
 SGI's lcrash tool which allows one to look at kernel structures in a
 running kernel.
 
-It also complements a tool called dumptool which dumps all the kernels
+It also complements a tool called dumptool which dumps all the kernel's
 memory pages & registers to either a tape or a disk.
-This can be used by tech support or an ambitous end user do
+This can be used by tech support or an ambitious end user do
 post mortem debugging of a machine like gdb core dumps.
 
 Going into how to use this tool in detail will be explained
diff -Nru a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt
--- a/Documentation/s390/cds.txt	Tue Feb 18 10:50:37 2003
+++ b/Documentation/s390/cds.txt	Tue Mar 11 10:20:18 2003
@@ -214,7 +214,7 @@
 cdev   - the ccw_device the data is requested for.
 buffer - Pointer to a buffer pointer. The read_conf_data() routine
          will allocate a buffer and initialize the buffer pointer
-         accordingly. It's the device driver's responsability to
+         accordingly. It's the device driver's responsibility to
          release the kernel memory if no longer needed. 
 length - Length of the buffer allocated and retrieved.
 lpm    - Logical path mask to be used for retrieving the data. If
@@ -224,7 +224,7 @@
           0 - Successful completion
 -ENODEV     - cdev invalid.
 -EINVAL     - An invalid parameter was detected, or the function was called early.
--EIO        - An irrecoverable I/O error occured or the device is
+-EIO        - An irrecoverable I/O error occurred or the device is
               not operational.
 -ENOMEM     - The read_conf_data() routine couldn't obtain storage.
 -EOPNOTSUPP - The device doesn't support the read configuration 
@@ -428,7 +428,7 @@
 can handle lost data on the network to allow for enhanced I/O processing.
 
 Unless the channel subsystem at any time presents a secondary status interrupt,
-exploiting this feature will cause only primary status interrups to be
+exploiting this feature will cause only primary status interrupts to be
 presented to the device driver while overlapping I/O is performed. When a
 secondary status without error (alert status) is presented, this indicates
 successful completion for all overlapping ccw_device_start() requests that have
diff -Nru a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt
--- a/Documentation/s390/driver-model.txt	Mon Feb 24 10:24:08 2003
+++ b/Documentation/s390/driver-model.txt	Tue Mar 11 10:20:18 2003
@@ -53,7 +53,7 @@
 
 a. Each driver can provide one or more parameter interfaces where parameters can
    be specified. These interfaces are also in the driver's responsibility.
-b. After a. has been performed, if neccessary, the device is finally brought up
+b. After a. has been performed, if necessary, the device is finally brought up
    via the 'online' interface.
 
 
@@ -145,7 +145,7 @@
 
 
 The handler field of the struct ccw_device is meant to be set to the interrupt
-handler for the device. In order to accomodate drivers which use several 
+handler for the device. In order to accommodate drivers which use several 
 distinct handlers (e.g. multi subchannel devices), this is a member of ccw_device
 instead of ccw_driver.
 The handler is registered with the common layer during set_online() processing
diff -Nru a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx
--- a/Documentation/scsi/ChangeLog.ncr53c8xx	Mon Nov 11 07:54:39 2002
+++ b/Documentation/scsi/ChangeLog.ncr53c8xx	Tue Mar 11 10:20:18 2003
@@ -247,7 +247,7 @@
 	- Add the 53c876 description to the chip table. This is only useful 
 	  for printing the right name of the controller.
 	- DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15).
-	- Add additionnal checking of INQUIRY data:
+	- Add additional checking of INQUIRY data:
 	  Check INQUIRY data received length is at least 7. Byte 7 of 
 	  inquiry data contains device features bits and the driver might 
 	  be confused by garbage. Also check peripheral qualifier.
@@ -420,7 +420,7 @@
 	- Split DATA_IN and DATA_OUT scripts into 2 sub-scripts.
 	  64 segments are moved from on-chip RAM scripts.
 	  If more segments, a script in main memory is used for the 
-	  additionnal segments.
+	  additional segments.
 	- Since the SCRIPTS processor continues SCRIPTS execution after 
 	  having won arbitration, do some stuff prior to testing any SCSI 
 	  phase on reselection. This should have the vertue to process 
@@ -475,7 +475,7 @@
         ------------------------------
 	- Use FAST-5 instead of SLOW for slow scsi devices according to 
 	  new SPI-2 draft.
-	- Make some changes in order to accomodate with 875 rev <= 3 
+	- Make some changes in order to accommodate with 875 rev <= 3 
 	  device errata listing 397. Minor consequences are:
 	  . Leave use of PCI Write and Invalidate under user control.
 	    Now, by default the driver does not enable PCI MWI and option
diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx b/Documentation/scsi/ChangeLog.sym53c8xx
--- a/Documentation/scsi/ChangeLog.sym53c8xx	Fri Feb  7 00:20:34 2003
+++ b/Documentation/scsi/ChangeLog.sym53c8xx	Tue Mar 11 10:20:18 2003
@@ -15,7 +15,7 @@
 	- In ncr_soft_reset(), only try to ABORT the current operation 
 	  for chips that support SRUN bit in ISTAT1 and if SCRIPTS are 
 	  currently running, as 896 and 1010 manuals suggest.
-	- In the CCB abort path, donnot assume that the CCB is currently 
+	- In the CCB abort path, do not assume that the CCB is currently 
 	  queued to SCRIPTS. This is not always true, notably after a 
 	  QUEUE FULL status or when using untagged commands.
 
@@ -562,7 +562,7 @@
 	* version pre-sym53c8xx-0.10
 	- Add the 53c876 description to the chip table. This is only useful 
 	  for printing the right name of the controller.
-	- Add additionnal checking of INQUIRY data:
+	- Add additional checking of INQUIRY data:
 	  Check INQUIRY data received length is at least 7. Byte 7 of 
 	  inquiry data contains device features bits and the driver might 
 	  be confused by garbage. Also check peripheral qualifier.
diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx_2 b/Documentation/scsi/ChangeLog.sym53c8xx_2
--- a/Documentation/scsi/ChangeLog.sym53c8xx_2	Tue Feb 18 10:50:37 2003
+++ b/Documentation/scsi/ChangeLog.sym53c8xx_2	Tue Mar 11 10:20:18 2003
@@ -32,7 +32,7 @@
 	  missing free of this memory on instance detach.
 	- Check against GPIO3 pulled low for HVD controllers (driver did 
 	  just the opposite).
-	  Misdetection of BUS mode was triggerred on module reload only, 
+	  Misdetection of BUS mode was triggered on module reload only, 
 	  since BIOS settings were trusted instead on first load.
 
 Wed Feb 7 21:00 2001 Gerard Roudier 
@@ -71,7 +71,7 @@
 	  #LUN <= 7.
 	- Set busy_itl in LCB to 1 if the LCB is allocated and a 
 	  SCSI command is active. This is a simplification.
-	- In sym_hcb_free(), donnot scan the free_ccbq if no CCBs 
+	- In sym_hcb_free(), do not scan the free_ccbq if no CCBs 
 	  has been allocated. This fixes a panic if attach failed.
 	- Add DT/ST (double/simple transition) in the transfer 
 	  negotiation announce.
diff -Nru a/Documentation/scsi/dpti.txt b/Documentation/scsi/dpti.txt
--- a/Documentation/scsi/dpti.txt	Mon Nov 11 07:54:40 2002
+++ b/Documentation/scsi/dpti.txt	Tue Mar 11 10:20:18 2003
@@ -75,7 +75,7 @@
  * to the board.  
  *
  * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the
- * interface files for Adaptecs managment routines.  These define the structures used
+ * interface files for Adaptec's management routines.  These define the structures used
  * in the ioctls.  They are written to be portable.  They are hard to read, but I need
  * to use them 'as is' or I can miss changes in the interface.
  *
diff -Nru a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt
--- a/Documentation/scsi/ibmmca.txt	Mon Feb 24 12:16:14 2003
+++ b/Documentation/scsi/ibmmca.txt	Tue Mar 11 10:20:18 2003
@@ -810,9 +810,9 @@
       commandline parameter is added, called 'activity'.
    2) Added the READ_CONTROL bit for test_unit_ready SCSI-command.
    3) Added some suppress_exception bits to read_device_capacity and
-      all device_inquiry occurences in the driver code.
+      all device_inquiry occurrences in the driver code.
    4) Complaints about the various KERNEL_VERSION implementations are
-      taken into account. Every local_LinuxKernelVersion occurence is
+      taken into account. Every local_LinuxKernelVersion occurrence is
       now replaced by KERNEL_VERSION, defined in linux/version.h. 
       Corresponding changes were applied to ibmmca.h, too. This was a
       contribution to all kernel-parts by Philipp Hahn.
@@ -866,7 +866,7 @@
    2) Adapter-information and autoadaption to address-space is done.
    3) Auto-probing for maximum synchronous SCSI transfer rate is working.
    4) Optimization to some embedded function calls is applied.
-   5) Added some comment for the user to wait for SCSI-devices beeing probed.
+   5) Added some comment for the user to wait for SCSI-devices being probed.
    6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but...
    - Michael Lang
    
@@ -966,7 +966,7 @@
 		                ------DA
 				
 		    where '-' stays dark, 'D' shows the SCSI-device id
-		    and 'A' shows the SCSI hostindex, beeing currently 
+		    and 'A' shows the SCSI hostindex, being currently 
 		    accessed. During boottime, this will give the message
 		    
 		                SCSIini*
@@ -1091,7 +1091,7 @@
 	now. Normally you really won't need to activate this flag in the
 	kernel configuration, as all post 1989 SCSI-devices should accept
 	the reset-signal, when the computer is switched on. The SCSI-
-	subsystem generates this reset while beeing initialized. This flag
+	subsystem generates this reset while being initialized. This flag
 	is really reserved for users with very old, very strange or self-made
 	SCSI-devices.
      Q: Why is the SCSI-order of my drives mirrored to the device-order
diff -Nru a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
--- a/Documentation/scsi/ncr53c8xx.txt	Mon Nov 11 07:54:41 2002
+++ b/Documentation/scsi/ncr53c8xx.txt	Tue Mar 11 10:20:18 2003
@@ -238,7 +238,7 @@
 optimizations based on actual head positions and its mechanical 
 characteristics. This feature may also reduce average command latency.
 In order to really gain advantage of this feature, devices must have 
-a reasonnable cache size (No miracle is to be expected for a low-end 
+a reasonable cache size (No miracle is to be expected for a low-end 
 hard disk with 128 KB or less).
 Some kown SCSI devices do not properly support tagged command queuing.
 Generally, firmware revisions that fix this kind of problems are available 
@@ -592,7 +592,7 @@
     Some SCSI-2 devices do not report this feature in byte 7 of inquiry 
     response but do support it properly (TAMARACK scanners for example).
 
-CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT   (default and only reasonnable answer: n)
+CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT   (default and only reasonable answer: n)
     If you suspect a device of yours does not properly support disconnections,
     you can answer "y". Then, all SCSI devices will never disconnect the bus 
     even while performing long SCSI operations.
@@ -827,7 +827,7 @@
 
     Available option bits:
         0x0:   No check.
-        0x1:   Check and donnot attach the controller on error.  
+        0x1:   Check and do not attach the controller on error.  
         0x2:   Check and just warn on error.
         0x4:   Disable SCSI bus integrity checking.
 
@@ -850,7 +850,7 @@
 
 10.2.22 Enable use of IMMEDIATE ARBITRATION
         (only supported by the sym53c8xx driver. See 10.7 for more details)
-        iarb:0    donnot use this feature.
+        iarb:0    do not use this feature.
         iarb:#x   use this feature according to bit fields as follow:
 
     bit 0 (1) : enable IARB each time the initiator has been reselected 
@@ -880,7 +880,7 @@
   settle time			10 seconds		settle:10
   differential support		from BIOS settings	diff:1
   irq mode			from BIOS settings	irqm:1
-  SCSI BUS check		donnot attach on error	buschk:1
+  SCSI BUS check		do not attach on error	buschk:1
   immediate arbitration		disabled		iarb:0
 
 10.3 Advised boot setup commands
@@ -1272,7 +1272,7 @@
 - terminations at both end of the SCSI chain
 - linux syslog messages (some of them may help you)
 
-If you donnot find the source of problems, you can configure the
+If you do not find the source of problems, you can configure the
 driver with no features enabled.
 
 - only asynchronous data transfers
@@ -1345,14 +1345,14 @@
 Field C : SIST io register (SCSI Interrupt Status)
   Bit 0x08 : SGE  SCSI GROSS ERROR
              Indicates that the chip detected a severe error condition 
-             on the SCSI BUS that prevents the SCSI protocol from functionning
+             on the SCSI BUS that prevents the SCSI protocol from functioning
              properly.
-  Bit 0x04 : UDC  Undexpected Disconnection
+  Bit 0x04 : UDC  Unexpected Disconnection
              Indicates that the device released the SCSI BUS when the chip 
              was not expecting this to happen. A device may behave so to 
              indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occurred.
   Bit 0x02 : RST  SCSI BUS Reset
-             Generally SCSI targets donnot reset the SCSI BUS, although any 
+             Generally SCSI targets do not reset the SCSI BUS, although any 
              device on the BUS can reset it at any time.
   Bit 0x01 : PAR  Parity
              SCSI parity error detected.
diff -Nru a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
--- a/Documentation/scsi/sym53c8xx_2.txt	Mon Nov 11 07:52:10 2002
+++ b/Documentation/scsi/sym53c8xx_2.txt	Tue Mar 11 10:20:18 2003
@@ -205,7 +205,7 @@
 optimizations based on actual head positions and its mechanical 
 characteristics. This feature may also reduce average command latency.
 In order to really gain advantage of this feature, devices must have 
-a reasonnable cache size (No miracle is to be expected for a low-end 
+a reasonable cache size (No miracle is to be expected for a low-end 
 hard disk with 128 KB or less).
 Some kown old SCSI devices do not properly support tagged command queuing.
 Generally, firmware revisions that fix this kind of problems are available 
@@ -579,7 +579,7 @@
 
     Available option bits:
         0x0:   No check.
-        0x1:   Check and donnot attach the controller on error.  
+        0x1:   Check and do not attach the controller on error.  
         0x2:   Check and just warn on error.
 
 10.2.16 Exclude a host from being attached
@@ -698,7 +698,7 @@
 - terminations at both end of the SCSI chain
 - linux syslog messages (some of them may help you)
 
-If you donnot find the source of problems, you can configure the
+If you do not find the source of problems, you can configure the
 driver or devices in the NVRAM with minimal features.
 
 - only asynchronous data transfers
@@ -756,14 +756,14 @@
 Field C : SIST io register (SCSI Interrupt Status)
   Bit 0x08 : SGE  SCSI GROSS ERROR
              Indicates that the chip detected a severe error condition 
-             on the SCSI BUS that prevents the SCSI protocol from functionning
+             on the SCSI BUS that prevents the SCSI protocol from functioning
              properly.
-  Bit 0x04 : UDC  Undexpected Disconnection
+  Bit 0x04 : UDC  Unexpected Disconnection
              Indicates that the device released the SCSI BUS when the chip 
              was not expecting this to happen. A device may behave so to 
-             indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occured.
+             indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occurred.
   Bit 0x02 : RST  SCSI BUS Reset
-             Generally SCSI targets donnot reset the SCSI BUS, although any 
+             Generally SCSI targets do not reset the SCSI BUS, although any 
              device on the BUS can reset it at any time.
   Bit 0x01 : PAR  Parity
              SCSI parity error detected.
diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt
--- a/Documentation/sonypi.txt	Tue Feb 18 03:34:09 2003
+++ b/Documentation/sonypi.txt	Tue Mar 11 10:20:18 2003
@@ -130,7 +130,7 @@
 	  tested) when using the driver with the fnkeyinit parameter. I cannot
 	  reproduce it on my laptop and not all users have this problem.
 	  This happens because the fnkeyinit parameter enables the ACPI 
-	  mode (but without additionnal ACPI control, like processor 
+	  mode (but without additional ACPI control, like processor 
 	  speed handling etc). Use ACPI instead of APM if it works on your
 	  laptop.
 	
diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
--- a/Documentation/sound/alsa/ALSA-Configuration.txt	Sat Feb  8 12:10:43 2003
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt	Tue Mar 11 10:20:18 2003
@@ -659,7 +659,7 @@
     Module supports autoprobe and multiple chips (max 8).
     Note: on some notebooks the buffer address cannot be detected
     automatically, or causes hang-up during initialization.
-    In such a case, specify the buffer top address explicity via
+    In such a case, specify the buffer top address explicitly via
     buffer_top option.
     For example,
       Sony F250: buffer_top=0x25a800
diff -Nru a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	Wed Feb 19 12:24:19 2003
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	Tue Mar 11 10:20:19 2003
@@ -2807,7 +2807,7 @@
         </para>
 
         <para>
-          If you aquire a spinlock in the interrupt handler, and the
+          If you acquire a spinlock in the interrupt handler, and the
         lock is used in other pcm callbacks, too, then you have to
         release the lock before calling
         <function>snd_pcm_period_elapsed()</function>, because
diff -Nru a/Documentation/sound/oss/NEWS b/Documentation/sound/oss/NEWS
--- a/Documentation/sound/oss/NEWS	Thu Mar  7 10:26:17 2002
+++ b/Documentation/sound/oss/NEWS	Tue Mar 11 10:20:19 2003
@@ -19,7 +19,7 @@
 
 Before Linux 2.4 you had to specify the resources for sounddrivers
 statically linked into the kernel at compile time
-(in make config/menuconfig/xconfig). In Linux 2.4 the ressources are
+(in make config/menuconfig/xconfig). In Linux 2.4 the resources are
 now specified at the boot-time kernel commandline (e.g. the lilo
 'append=' line or everything that's after the kernel name in grub).
 Read the Configure.help entry for your card for the parameters.
diff -Nru a/Documentation/sound/oss/PSS-updates b/Documentation/sound/oss/PSS-updates
--- a/Documentation/sound/oss/PSS-updates	Tue Feb 18 10:25:13 2003
+++ b/Documentation/sound/oss/PSS-updates	Tue Mar 11 10:20:19 2003
@@ -22,12 +22,12 @@
 	This parameter takes a port address as its parameter.  Any available port 
 address can be specified to enable the CDROM port, except for 0x0 and -1 as 
 these values would leave the port disabled.  Like the joystick port, the cdrom 
-port will require that an appropiate CDROM driver be loaded before you can make 
+port will require that an appropriate CDROM driver be loaded before you can make 
 use of the newly enabled CDROM port.  Like the joystick port option above, 
 remember to load the CDROM driver AFTER the pss sound driver.  While it may 
 differ on some PSS sound cards, all the PSS sound cards that I have seen have a 
 builtin Wearnes CDROM port.  If this is the case with your PSS sound card you 
-should load aztcd with the appropiate port option that matches the port you 
+should load aztcd with the appropriate port option that matches the port you 
 assigned to the CDROM port when you loaded your pss sound driver.  (ex. 
 modprobe pss pss_cdrom_port=0x340 && modprobe aztcd aztcd=0x340)  The default 
 setting of this parameter leaves the CDROM port disabled to maintain full 
@@ -44,7 +44,7 @@
 value will only attept to configure the CDROM and joystick ports.  This 
 parameter can be used by a user who only wished to use the builtin joystick 
 and/or CDROM port(s) of his PSS sound card.  If this driver is loaded with this 
-parameter and with the paramter below set to true then a user can safely unload 
+parameter and with the parameter below set to true then a user can safely unload 
 this driver with the following command "rmmod pss && rmmod ad1848 && rmmod 
 mpu401 && rmmod sound && rmmod soundcore" and retain the full functionality of 
 his CDROM and/or joystick port(s) while gaining back the memory previously used 
diff -Nru a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx
--- a/Documentation/sound/oss/cs46xx	Thu Mar  7 10:26:17 2002
+++ b/Documentation/sound/oss/cs46xx	Tue Mar 11 10:20:19 2003
@@ -78,7 +78,7 @@
 driver to disable compilation of the CS_DBGOUT print statements:
 #define CSDEBUG 1
  
-Please see the defintions for cs_debuglevel and cs_debugmask for additional
+Please see the definitions for cs_debuglevel and cs_debugmask for additional
 information on the debug levels and sections.
 
 There is also a csdbg executable to allow runtime manipulation of these 
diff -Nru a/Documentation/specialix.txt b/Documentation/specialix.txt
--- a/Documentation/specialix.txt	Tue Feb  5 09:40:37 2002
+++ b/Documentation/specialix.txt	Tue Mar 11 10:20:19 2003
@@ -326,7 +326,7 @@
 
 
   Fixed bugs and restrictions:
-       - During intialization, interrupts are blindly turned on.
+       - During initialization, interrupts are blindly turned on.
             Having a shadow variable would cause an extra memory
             access on every IO instruction. 
        - The interrupt (on the card) should be disabled when we
diff -Nru a/Documentation/swsusp.txt b/Documentation/swsusp.txt
--- a/Documentation/swsusp.txt	Wed Sep 25 12:14:42 2002
+++ b/Documentation/swsusp.txt	Tue Mar 11 10:20:19 2003
@@ -90,7 +90,7 @@
 function do_software_suspend, it is called. Here we shrink everything including
 dcache, inodes, buffers and memory (here mainly processes are swapped out). We
 count how many pages we need to duplicate (we have to be atomical!) then we
-create an appropiate sized page directory. It will point to the original and
+create an appropriate sized page directory. It will point to the original and
 the new (copied) address of the page. We get the free pages by
 __get_free_pages() but since it changes state we have to be able to track it
 later so it also flips in a bit in page's flags (a new Nosave flag). We
diff -Nru a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt
--- a/Documentation/uml/UserModeLinux-HOWTO.txt	Mon Nov 18 11:17:36 2002
+++ b/Documentation/uml/UserModeLinux-HOWTO.txt	Tue Mar 11 10:20:19 2003
@@ -2509,7 +2509,7 @@
   1100..88..  ssttoopp
 
   This puts the UML in a loop reading mconsole requests until a 'go'
-  mconsole command is recieved. This is very useful for making backups
+  mconsole command is received. This is very useful for making backups
   of UML filesystems, as the UML can be stopped, then synced via 'sysrq
   s', so that everything is written to the filesystem. You can then copy
   the filesystem and then send the UML 'go' via mconsole.
diff -Nru a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
--- a/Documentation/usb/URB.txt	Tue Oct 29 09:53:33 2002
+++ b/Documentation/usb/URB.txt	Tue Mar 11 10:20:19 2003
@@ -86,7 +86,7 @@
 
 Return value is a pointer to the allocated URB, 0 if allocation failed.
 The parameter isoframes specifies the number of isochronous transfer frames
-you want to schedule. For CTRL/BULK/INT, use 0.  The mem_flags paramter
+you want to schedule. For CTRL/BULK/INT, use 0.  The mem_flags parameter
 holds standard memory allocation flags, letting you control (among other
 things) whether the underlying code may block or not.
 
diff -Nru a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt
--- a/Documentation/usb/hiddev.txt	Thu Feb  6 07:33:47 2003
+++ b/Documentation/usb/hiddev.txt	Tue Mar 11 10:20:19 2003
@@ -173,7 +173,7 @@
 usage to be retrieved can be specified as above, or the user can
 choose to fill in the report_type field and specify the report_id as
 HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be
-filled in with the report and field infomation associated with this
+filled in with the report and field information associated with this
 usage if it is found. 
 
 HIDIOCSUSAGE - struct hiddev_usage_ref (write)
diff -Nru a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt
--- a/Documentation/usb/philips.txt	Sat Mar  9 18:27:56 2002
+++ b/Documentation/usb/philips.txt	Tue Mar 11 10:20:19 2003
@@ -27,9 +27,9 @@
    Specifies the desired framerate. Is an integer in the range of 4-30.
 
 fbufs
-   This paramter specifies the number of internal buffers to use for storing 
+   This parameter specifies the number of internal buffers to use for storing 
    frames from the cam. This will help if the process that reads images from 
-   the cam is a bit slow or momentarely busy. However, on slow machines it 
+   the cam is a bit slow or momentarily busy. However, on slow machines it
    only introduces lag, so choose carefully. The default is 3, which is 
    reasonable. You can set it between 2 and 5.
 
diff -Nru a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt
--- a/Documentation/usb/scanner.txt	Tue Jan  7 12:57:22 2003
+++ b/Documentation/usb/scanner.txt	Tue Mar 11 10:20:19 2003
@@ -282,7 +282,7 @@
 	}
 
 	if((fpout=fopen("out.dat", "w+")) == NULL) {
-		perror("Unable to open ouput file");
+		perror("Unable to open output file");
 		exit(1);
 	}
 
diff -Nru a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ
--- a/Documentation/video4linux/bttv/Sound-FAQ	Mon Feb 24 12:36:40 2003
+++ b/Documentation/video4linux/bttv/Sound-FAQ	Tue Mar 11 10:20:19 2003
@@ -15,18 +15,18 @@
 
 	bttv0: model: BT848(Hauppauge old) [autodetected]
 
-You should verify this is correct.  If it is'nt, you have to pass the
+You should verify this is correct.  If it isn't, you have to pass the
 correct board type as insmod argument, "insmod bttv card=2" for
 example.  The file CARDLIST has a list of valid arguments for card.
-If your card is'nt listed there, you might check the source code for
-new entries which are not listed yet.  If there is'nt one for your
+If your card isn't listed there, you might check the source code for
+new entries which are not listed yet.  If there isn't one for your
 card, you can check if one of the existing entries does work for you
 (just trial and error...).
 
 Some boards have an extra processor for sound to do stereo decoding
 and other nice features.  The msp34xx chips are used by Hauppauge for
 example.  If your board has one, you might have to load a helper
-module like msp3400.o to make sound work.  If there is'nt one for the
+module like msp3400.o to make sound work.  If there isn't one for the
 chip used on your board:  Bad luck.  Start writing a new one.  Well,
 you might want to check the video4linux mailing list archive first...
 
diff -Nru a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt
--- a/Documentation/video4linux/zr36120.txt	Tue Feb  5 09:40:37 2002
+++ b/Documentation/video4linux/zr36120.txt	Tue Mar 11 10:20:19 2003
@@ -146,10 +146,10 @@
 The consequence is that, when loading the driver as a module,
 the module may tell you it's out of memory, but 'free' says
 otherwise. The reason is simple; the modules wants its memory
-contingious, not fragmented, and after a long uptime there
+contiguous, not fragmented, and after a long uptime there
 probably isn't a fragment of memory large enough...
 
-The driver uses a double buffering scheme, which should realy
+The driver uses a double buffering scheme, which should really
 be an n-way buffer, depending on the size of allocated framebuffer
 and the requested grab-size/format.
 This current version also fixes a dead-lock situation during irq
diff -Nru a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
--- a/Documentation/vm/hugetlbpage.txt	Sun Mar  2 18:14:36 2003
+++ b/Documentation/vm/hugetlbpage.txt	Tue Mar 11 10:20:19 2003
@@ -69,7 +69,7 @@
 
 	mount none /mnt/huge -t hugetlbfs
 
-This commands mounts a (psuedo) filesystem of type hugetlbfs on the directory
+This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
 /mnt/huge.  Any files created on /mnt/huge uses hugepages.  An example is
 given at the end of this document.
 
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Tue Feb 18 10:57:56 2003
+++ b/MAINTAINERS	Thu Mar  6 09:07:03 2003
@@ -641,7 +641,7 @@
 P:	Rui Sousa	
 M:	rui.p.m.sousa@clix.pt	
 L:	emu10k1-devel@lists.sourceforge.net
-W:	http://opensource.creative.com/
+W:	http://sourceforge.net/projects/emu10k1/
 S:	Maintained
 
 ETHEREXPRESS-16 NETWORK DRIVER
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Tue Mar  4 19:11:15 2003
+++ b/Makefile	Mon Mar 17 04:25:51 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 64
-EXTRAVERSION =
+EXTRAVERSION = -bk12
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -107,6 +107,11 @@
 
 #	For now, leave verbose as default
 
+ifdef V
+  ifeq ("$(origin V)", "command line")
+    KBUILD_VERBOSE = $(V)
+  endif
+endif
 ifndef KBUILD_VERBOSE
   KBUILD_VERBOSE = 1
 endif
@@ -193,7 +198,7 @@
 comma := ,
 depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
 
-noconfig_targets := xconfig menuconfig config oldconfig randconfig \
+noconfig_targets := xconfig gconfig menuconfig config oldconfig randconfig \
 		    defconfig allyesconfig allnoconfig allmodconfig \
 		    clean mrproper distclean rpm \
 		    help tags TAGS cscope sgmldocs psdocs pdfdocs htmldocs \
@@ -328,8 +333,10 @@
 	  . $(srctree)/scripts/mkversion > .tmp_version;		\
 	  mv -f .tmp_version .version;					\
 	  $(MAKE) $(build)=init;					\
-	)
-	$(call cmd,vmlinux__);						\
+	)								\
+	$(if $($(quiet)cmd_vmlinux__),					\
+	  echo '  $($(quiet)cmd_vmlinux__)' &&) 			\
+	$(cmd_vmlinux__);						\
 	echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
 endef
 
@@ -472,17 +479,19 @@
 
 uts_len := 64
 
-include/linux/version.h: Makefile
-	@if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \
+define filechk_version.h
+	if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \
 	  echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
 	  exit 1; \
 	fi;
-	@echo -n '  GEN     $@'
-	@(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
+	(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
 	  echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \
 	 echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \
-	) > $@.tmp
-	@$(update-if-changed)
+	)
+endef
+
+include/linux/version.h: Makefile
+	$(call filechk,version.h)
 
 # ---------------------------------------------------------------------------
 
@@ -551,7 +560,7 @@
 # Generate asm-offsets.h 
 # ---------------------------------------------------------------------------
 
-define generate-asm-offsets.h
+define filechk_gen-asm-offsets
 	(set -e; \
 	 echo "#ifndef __ASM_OFFSETS_H__"; \
 	 echo "#define __ASM_OFFSETS_H__"; \
@@ -567,7 +576,6 @@
 	 echo "#endif" )
 endef
 
-
 else # ifdef include_config
 
 ifeq ($(filter-out $(noconfig_targets),$(MAKECMDGOALS)),)
@@ -598,15 +606,18 @@
 # Kernel configuration
 # ---------------------------------------------------------------------------
 
-.PHONY: oldconfig xconfig menuconfig config \
+.PHONY: oldconfig xconfig gconfig menuconfig config \
 	make_with_config rpm
 
-scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf: scripts/fixdep FORCE
+scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf scripts/kconfig/gconf: scripts/fixdep FORCE
 	$(Q)$(MAKE) $(build)=scripts/kconfig $@
 
 xconfig: scripts/kconfig/qconf
 	./scripts/kconfig/qconf arch/$(ARCH)/Kconfig
 
+gconfig: scripts/kconfig/gconf
+	./scripts/kconfig/gconf arch/$(ARCH)/Kconfig
+
 menuconfig: scripts/kconfig/mconf
 	$(Q)$(MAKE) $(build)=scripts/lxdialog
 	./scripts/kconfig/mconf arch/$(ARCH)/Kconfig
@@ -875,13 +886,27 @@
 
 cmd = @$(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
 
-define update-if-changed
-	if [ -r $@ ] && cmp -s $@ $@.tmp; then \
-		echo ' (unchanged)'; \
-		rm -f $@.tmp; \
-	else \
-		echo ' (updated)'; \
-		mv -f $@.tmp $@; \
+# filechk is used to check if the content of a generated file is updated.
+# Sample usage:
+# define filechk_sample
+#	echo $KERNELRELEASE
+# endef
+# version.h : Makefile
+#	$(call filechk,sample)
+# The rule defined shall write to stdout the content of the new file.
+# The existing file will be compared with the new one.
+# - If no file exist it is created
+# - If the content differ the new file is used
+# - If they are equal no change, and no timestamp update
+
+define filechk
+	@echo '  CHK     $@';
+	@set -e; $(filechk_$(1)) > $@.tmp
+	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
+		rm -f $@.tmp;			\
+	else					\
+		echo '  UPD     $@';		\
+		mv -f $@.tmp $@;		\
 	fi
 endef
 
diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig
--- a/arch/alpha/Kconfig	Tue Feb 18 15:57:50 2003
+++ b/arch/alpha/Kconfig	Sat Mar  8 14:50:37 2003
@@ -15,10 +15,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 
diff -Nru a/arch/alpha/Makefile b/arch/alpha/Makefile
--- a/arch/alpha/Makefile	Tue Feb 18 15:57:50 2003
+++ b/arch/alpha/Makefile	Fri Mar  7 13:28:49 2003
@@ -119,15 +119,12 @@
 				   include/config/MARKER
 
 include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
 
 archclean:
 	$(Q)$(MAKE) -f scripts/Makefile.clean obj=$(boot)
 
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h.tmp \
-	       include/asm-$(ARCH)/asm_offsets.h
+CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
 
 define archhelp
   echo '* boot		- Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
diff -Nru a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile
--- a/arch/alpha/boot/Makefile	Thu Jan  9 03:38:01 2003
+++ b/arch/alpha/boot/Makefile	Sun Mar  9 13:47:41 2003
@@ -9,7 +9,7 @@
 #
 
 host-progs	:= tools/mkbb tools/objstrip
-EXTRA_TARGETS	:= vmlinux.gz vmlinux \
+targets		:= vmlinux.gz vmlinux \
 		   vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
 		   bootloader bootpheader 
 OBJSTRIP	:= $(obj)/tools/objstrip
diff -Nru a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
--- a/arch/alpha/kernel/Makefile	Thu Feb 20 13:51:55 2003
+++ b/arch/alpha/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS	:= head.o
+extra-y		:= head.o
 EXTRA_AFLAGS	:= $(CFLAGS)
 EXTRA_CFLAGS	:= -Werror -Wno-sign-compare
 
diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
--- a/arch/alpha/kernel/core_marvel.c	Fri Feb 14 05:51:04 2003
+++ b/arch/alpha/kernel/core_marvel.c	Sat Feb 15 04:55:38 2003
@@ -1076,7 +1076,7 @@
 	/*
 	 * Fill it in.
 	 */
-	agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
+	agp->type = ALPHA_CORE_AGP;
 	agp->hose = hose;
 	agp->private = NULL;
 	agp->ops = &marvel_agp_ops;
diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
--- a/arch/alpha/kernel/core_titan.c	Fri Jan 17 11:59:36 2003
+++ b/arch/alpha/kernel/core_titan.c	Sat Feb 15 04:55:54 2003
@@ -764,7 +764,7 @@
 	/*
 	 * Fill it in.
 	 */
-	agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
+	agp->type = ALPHA_CORE_AGP;
 	agp->hose = hose;
 	agp->private = port;
 	agp->ops = &titan_agp_ops;
diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
--- a/arch/alpha/kernel/irq.c	Tue Jan 21 05:42:33 2003
+++ b/arch/alpha/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -515,6 +515,7 @@
 #endif
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 #ifdef CONFIG_SMP
 	seq_puts(p, "           ");
@@ -525,9 +526,10 @@
 #endif
 
 	for (i = 0; i < ACTUAL_NR_IRQS; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -538,15 +540,18 @@
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %c%s",
-			     (action->flags & SA_INTERRUPT)?'+':' ',
-			     action->name);
+			(action->flags & SA_INTERRUPT)?'+':' ',
+			action->name);
 
 		for (action=action->next; action; action = action->next) {
 			seq_printf(p, ", %c%s",
-				     (action->flags & SA_INTERRUPT)?'+':' ',
-				     action->name);
+				  (action->flags & SA_INTERRUPT)?'+':' ',
+				   action->name);
 		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #if CONFIG_SMP
 	seq_puts(p, "IPI: ");
diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
--- a/arch/alpha/kernel/pci.c	Wed Feb 26 17:20:09 2003
+++ b/arch/alpha/kernel/pci.c	Sun Mar 16 14:16:29 2003
@@ -12,7 +12,7 @@
  * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
  *	     PCI-PCI bridges cleanup
  */
-
+#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -264,45 +264,6 @@
 	}
 }
 
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *parent,
-			struct resource *res, int resource)
-{
-	struct pci_controller *hose = dev->sysdata;
-	struct resource *root;
-	int where;
-	u32 reg;
-
-	if (resource < PCI_ROM_RESOURCE) 
-		where = PCI_BASE_ADDRESS_0 + (resource * 4);
-	else if (resource == PCI_ROM_RESOURCE)
-		where = dev->rom_base_reg;
-	else {
-		return; /* Don't update non-standard resources here. */
-	}
-
-	/* Point root at the hose root. */
-	if (res->flags & IORESOURCE_IO)
-		root = hose->io_space;
-	else if (res->flags & IORESOURCE_MEM)
-		root = hose->mem_space;
-	else {
-		return; /* Don't update non-standard resources here. */
-	}
-
-	reg = (res->start - root->start) | (res->flags & 0xf);
-	pci_write_config_dword(dev, where, reg);
-	if ((res->flags & (PCI_BASE_ADDRESS_SPACE
-			   | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
-	    == (PCI_BASE_ADDRESS_SPACE_MEMORY
-		| PCI_BASE_ADDRESS_MEM_TYPE_64)) {
-		pci_write_config_dword(dev, where+4, 0);
-		printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->dev.name);
-	}
-
-	/* ??? FIXME -- record old value for shutdown.  */
-}
-
 void __init
 pcibios_update_irq(struct pci_dev *dev, int irq)
 {
@@ -334,21 +295,25 @@
 }
 
 void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus * bus,
-			  struct pbus_set_ranges_data * ranges)
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res)
 {
-	struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
+	struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+	unsigned long offset = 0;
 
-	ranges->io_start -= hose->io_space->start;
-	ranges->io_end -= hose->io_space->start;
-	ranges->mem_start -= hose->mem_space->start;
-	ranges->mem_end -= hose->mem_space->start;
-/* FIXME: On older alphas we could use dense memory space
-	  to access prefetchable resources. */
-	ranges->prefetch_start -= hose->mem_space->start;
-	ranges->prefetch_end -= hose->mem_space->start;
+	if (res->flags & IORESOURCE_IO)
+		offset = hose->io_space->start;
+	else if (res->flags & IORESOURCE_MEM)
+		offset = hose->mem_space->start;
+
+	region->start = res->start - offset;
+	region->end = res->end - offset;
 }
 
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
 int
 pcibios_enable_device(struct pci_dev *dev, int mask)
 {
@@ -393,26 +358,36 @@
 }
 
 static void __init
+pcibios_claim_one_bus(struct pci_bus *b)
+{
+	struct list_head *ld;
+	struct pci_bus *child_bus;
+
+	for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
+		struct pci_dev *dev = pci_dev_b(ld);
+		int i;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *r = &dev->resource[i];
+
+			if (r->parent || !r->start || !r->flags)
+				continue;
+			pci_claim_resource(dev, i);
+		}
+	}
+
+	list_for_each_entry(child_bus, &b->children, node)
+		pcibios_claim_one_bus(child_bus);
+}
+
+static void __init
 pcibios_claim_console_setup(void)
 {
 	struct list_head *lb;
 
 	for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) {
 		struct pci_bus *b = pci_bus_b(lb);
-		struct list_head *ld;
-
-		for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
-			struct pci_dev *dev = pci_dev_b(ld);
-			int i;
-
-			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-				struct resource *r = &dev->resource[i];
-
-				if (r->parent || !r->start || !r->flags)
-					continue;
-				pci_claim_resource(dev, i);
-			}
-		}
+		pcibios_claim_one_bus(b);
 	}
 }
 
diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
--- a/arch/alpha/kernel/sys_nautilus.c	Thu Jan 23 10:59:07 2003
+++ b/arch/alpha/kernel/sys_nautilus.c	Sun Mar  2 17:34:25 2003
@@ -78,6 +78,8 @@
 nautilus_kill_arch(int mode)
 {
 	struct pci_bus *bus = pci_isa_hose->bus;
+	u32 pmuport;
+	int off;
 
 	switch (mode) {
 	case LINUX_REBOOT_CMD_RESTART:
@@ -92,14 +94,18 @@
 		break;
 
 	case LINUX_REBOOT_CMD_POWER_OFF:
-		{
-			u32 pmuport;
-			pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
-			pmuport &= 0xfffe;
-			outl(0xffff, pmuport); /* clear pending events */
-			outw(0x2000, pmuport+4); /* power off */
-			/* NOTREACHED */
+		/* Assume M1543C */
+		off = 0x2000;		/* SLP_TYPE = 0, SLP_EN = 1 */
+		pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
+		if (!pmuport) {
+			/* M1535D/D+ */
+			off = 0x3400;	/* SLP_TYPE = 5, SLP_EN = 1 */
+			pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport);
 		}
+		pmuport &= 0xfffe;
+		outw(0xffff, pmuport);	/* Clear pending events. */
+		outw(off, pmuport + 4);
+		/* NOTREACHED */
 		break;
 	}
 }
diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
--- a/arch/alpha/mm/fault.c	Mon Jan  6 10:11:27 2003
+++ b/arch/alpha/mm/fault.c	Thu Mar  6 08:19:03 2003
@@ -232,11 +232,11 @@
 	else {
 		/* Synchronize this task's top level page-table
 		   with the "reference" page table from init.  */
-		long offset = __pgd_offset(address);
+		long index = pgd_index(address);
 		pgd_t *pgd, *pgd_k;
 
-		pgd = current->active_mm->pgd + offset;
-		pgd_k = swapper_pg_dir + offset;
+		pgd = current->active_mm->pgd + index;
+		pgd_k = swapper_pg_dir + index;
 		if (!pgd_present(*pgd) && pgd_present(*pgd_k)) {
 			pgd_val(*pgd) = pgd_val(*pgd_k);
 			return;
diff -Nru a/arch/alpha/oprofile/op_model_ev4.c b/arch/alpha/oprofile/op_model_ev4.c
--- a/arch/alpha/oprofile/op_model_ev4.c	Tue Feb 18 19:05:36 2003
+++ b/arch/alpha/oprofile/op_model_ev4.c	Fri Mar  7 20:31:28 2003
@@ -34,7 +34,7 @@
 	   for these "disabled" counter overflows are ignored by the
 	   interrupt handler.
 
-	   This is most irritating, becuase the hardware *can* enable and
+	   This is most irritating, because the hardware *can* enable and
 	   disable the interrupts for these counters independently, but the
 	   wrperfmon interface doesn't allow it.  */
 
diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S
--- a/arch/alpha/vmlinux.lds.S	Wed Jan 15 19:04:27 2003
+++ b/arch/alpha/vmlinux.lds.S	Fri Mar  7 00:58:06 2003
@@ -63,6 +63,13 @@
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
 
+  . = ALIGN(8);
+  .con_initcall.init : {
+	__con_initcall_start = .;
+	*(.con_initcall.init)
+	__con_initcall_end = .;
+  }
+
   . = ALIGN(64);
   __per_cpu_start = .;
   .data.percpu : { *(.data.percpu) }
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	Sat Feb 15 01:34:08 2003
+++ b/arch/arm/Kconfig	Sat Mar  8 14:50:37 2003
@@ -20,10 +20,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config EISA
 	bool
 	---help---
@@ -534,15 +530,63 @@
 	  written) to implement the policy. If you don't understand what this
 	  is all about, it's safe to say 'N'.
 
+
+# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor
+
+config CPU_FREQ_SA1100
+	bool
+	depends on CPU_FREQ && SA1100_LART
+	default y
+
+config CPU_FREQ_SA1110
+	bool
+	depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
+	default y
+
+if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110)
+
+config CPU_FREQ_GOV_USERSPACE
+ 	bool
+ 	depends on CPU_FREQ
+ 	default y
+
 config CPU_FREQ_24_API
 	bool
-	depends on CPU_FREQ
+	depends on CPU_FREQ_GOV_USERSPACE && SYSCTL
 	default y
 
 config CPU_FREQ_PROC_INTF
-	tristate
-	depends on CPU_FREQ
+	tristate "/proc/cpufreq interface (deprecated)"
+	depends on CPU_FREQ && PROC_FS
+	help
+	  This enables the /proc/cpufreq interface for controlling
+	  CPUFreq. Please note that it is recommended to use the sysfs
+	  interface instead (which is built automatically).
+
+	  For details, take a look at linux/Documentation/cpufreq.
+
+	  If in doubt, say N.
+
+endif
+
+# CPUfreq on Integrator can use the generic cpufreq core
+
+config CPU_FREQ_INTEGRATOR
+	tristate "CPUfreq driver for ARM Integrator CPUs"
+	depends on ARCH_INTEGRATOR && CPU_FREQ
 	default y
+	help
+	  This enables the CPUfreq driver for ARM Integrator CPUs.
+
+	  For details, take a look at linux/Documentation/cpufreq.
+
+	  If in doubt, say Y.
+
+if (CPU_FREQ_INTEGRATOR)
+
+source "drivers/cpufreq/Kconfig"
+
+endif
 
 source "drivers/pci/Kconfig"
 
diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile
--- a/arch/arm/Makefile	Mon Feb  3 13:06:32 2003
+++ b/arch/arm/Makefile	Fri Mar  7 13:28:49 2003
@@ -211,9 +211,7 @@
 				   include/config/MARKER
 
 include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
 
 define archhelp
   echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
diff -Nru a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
--- a/arch/arm/boot/Makefile	Mon Dec 30 23:13:28 2002
+++ b/arch/arm/boot/Makefile	Sun Mar  9 13:47:41 2003
@@ -69,7 +69,7 @@
 
 export	ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS
 
-EXTRA_TARGETS := Image zImage bootpImage
+targets := Image zImage bootpImage
 
 $(obj)/Image: vmlinux FORCE
 	$(call if_changed,objcopy)
@@ -106,5 +106,4 @@
 	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
-clean-files := $(addprefix $(obj)/,Image zImage bootpImage)
 subdir-	    := bootp compressed
diff -Nru a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile
--- a/arch/arm/boot/bootp/Makefile	Sun Nov 10 14:04:55 2002
+++ b/arch/arm/boot/bootp/Makefile	Sun Mar  9 14:15:54 2003
@@ -7,7 +7,7 @@
 		 --defsym initrd_addr=$(INITRD_PHYS) \
 		 --defsym params=$(PARAMS_PHYS)
 
-EXTRA_TARGETS := bootp
+extra-y := bootp
 
 # Note that bootp.lds picks up kernel.o and initrd.o
 $(obj)/bootp:	$(addprefix $(obj)/,init.o kernel.o initrd.o bootp.lds)
diff -Nru a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
--- a/arch/arm/boot/compressed/Makefile	Sat Dec 28 08:10:17 2002
+++ b/arch/arm/boot/compressed/Makefile	Sun Mar  9 13:47:41 2003
@@ -65,8 +65,8 @@
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-EXTRA_TARGETS := vmlinux vmlinux.lds piggy piggy.gz\
-                 piggy.o font.o head.o $(OBJS)
+targets       := vmlinux vmlinux.lds piggy piggy.gz piggy.o \
+                 font.o head.o $(OBJS)
 EXTRA_CFLAGS  := $(CFLAGS_BOOT) -fpic
 EXTRA_AFLAGS  := -traditional
 
@@ -94,8 +94,6 @@
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in Makefile arch/arm/boot/Makefile .config
 	@sed "$(SEDFLAGS)" < $< > $@
-
-clean-files := $(addprefix $(obj)/,vmlinux piggy* vmlinux.lds)
 
 $(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c
 
diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
--- a/arch/arm/common/sa1111.c	Mon Feb 17 12:43:37 2003
+++ b/arch/arm/common/sa1111.c	Thu Mar  6 08:08:19 2003
@@ -743,25 +743,23 @@
 static int sa1111_suspend(struct device *dev, u32 state, u32 level)
 {
 	struct sa1111 *sachip = dev_get_drvdata(dev);
+	struct sa1111_save_data *save;
 	unsigned long flags;
 	char *base;
 
+	if (!dev->saved_state && level == SUSPEND_NOTIFY)
+		dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
+	if (!dev->saved_state)
+		return -ENOMEM;
+
+	save = (struct sa1111_save_data *)dev->saved_state;
+
+	spin_lock_irqsave(&sachip->lock, flags);
+
 	/*
 	 * Save state.
 	 */
-	if (level == SUSPEND_SAVE_STATE ||
-	    level == SUSPEND_DISABLE ||
-	    level == SUSPEND_POWER_DOWN) {
-		struct sa1111_save_data *save;
-
-		if (!dev->saved_state)
-			dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
-		if (!dev->saved_state)
-			return -ENOMEM;
-
-		save = (struct sa1111_save_data *)dev->saved_state;
-
-		spin_lock_irqsave(&sachip->lock, flags);
+	if (level == SUSPEND_SAVE_STATE) {
 		base = sachip->base;
 		save->skcr     = sa1111_readl(base + SA1111_SKCR);
 		save->skpcr    = sa1111_readl(base + SA1111_SKPCR);
@@ -779,26 +777,21 @@
 		save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
 		save->wakeen0  = sa1111_readl(base + SA1111_WAKEEN0);
 		save->wakeen1  = sa1111_readl(base + SA1111_WAKEEN1);
-		spin_unlock_irqrestore(&sachip->lock, flags);
 	}
 
 	/*
 	 * Disable.
 	 */
-	if (level == SUSPEND_DISABLE && state == 4) {
-		unsigned int val;
-
-		spin_lock_irqsave(&sachip->lock, flags);
-		base = sachip->base;
-
-		sa1111_writel(0, base + SA1111_SKPWM0);
-		sa1111_writel(0, base + SA1111_SKPWM1);
-		val = sa1111_readl(base + SA1111_SKCR);
-		sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR);
+	if (level == SUSPEND_POWER_DOWN && state == 4) {
+		unsigned int val = sa1111_readl(sachip->base + SA1111_SKCR);
 
-		spin_unlock_irqrestore(&sachip->lock, flags);
+		sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
+		sa1111_writel(0, sachip->base + SA1111_SKPWM0);
+		sa1111_writel(0, sachip->base + SA1111_SKPWM1);
 	}
 
+	spin_unlock_irqrestore(&sachip->lock, flags);
+
 	return 0;
 }
 
@@ -819,17 +812,15 @@
 	unsigned long flags, id;
 	char *base;
 
-	if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE)
-		return 0;
-
 	save = (struct sa1111_save_data *)dev->saved_state;
 	if (!save)
 		return 0;
 
-	dev->saved_state = NULL;
+	spin_lock_irqsave(&sachip->lock, flags);
 
 	/*
 	 * Ensure that the SA1111 is still here.
+	 * FIXME: shouldn't do this here.
 	 */
 	id = sa1111_readl(sachip->base + SA1111_SKID);
 	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
@@ -839,29 +830,42 @@
 		return 0;
 	}
 
-	spin_lock_irqsave(&sachip->lock, flags);
-	sa1111_wake(sachip);
+	/*
+	 * First of all, wake up the chip.
+	 */
+	if (level == RESUME_POWER_ON) {
+		sa1111_wake(sachip);
+
+		sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
+		sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
+	}
+
+	if (level == RESUME_RESTORE_STATE) {
+		base = sachip->base;
+		sa1111_writel(save->skcr,     base + SA1111_SKCR);
+		sa1111_writel(save->skpcr,    base + SA1111_SKPCR);
+		sa1111_writel(save->skcdr,    base + SA1111_SKCDR);
+		sa1111_writel(save->skaud,    base + SA1111_SKAUD);
+		sa1111_writel(save->skpwm0,   base + SA1111_SKPWM0);
+		sa1111_writel(save->skpwm1,   base + SA1111_SKPWM1);
+
+		base = sachip->base + SA1111_INTC;
+		sa1111_writel(save->intpol0,  base + SA1111_INTPOL0);
+		sa1111_writel(save->intpol1,  base + SA1111_INTPOL1);
+		sa1111_writel(save->inten0,   base + SA1111_INTEN0);
+		sa1111_writel(save->inten1,   base + SA1111_INTEN1);
+		sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
+		sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
+		sa1111_writel(save->wakeen0,  base + SA1111_WAKEEN0);
+		sa1111_writel(save->wakeen1,  base + SA1111_WAKEEN1);
+	}
 
-	base = sachip->base;
-	sa1111_writel(save->skcr,     base + SA1111_SKCR);
-	sa1111_writel(save->skpcr,    base + SA1111_SKPCR);
-	sa1111_writel(save->skcdr,    base + SA1111_SKCDR);
-	sa1111_writel(save->skaud,    base + SA1111_SKAUD);
-	sa1111_writel(save->skpwm0,   base + SA1111_SKPWM0);
-	sa1111_writel(save->skpwm1,   base + SA1111_SKPWM1);
-
-	base = sachip->base + SA1111_INTC;
-	sa1111_writel(save->intpol0,  base + SA1111_INTPOL0);
-	sa1111_writel(save->intpol1,  base + SA1111_INTPOL1);
-	sa1111_writel(save->inten0,   base + SA1111_INTEN0);
-	sa1111_writel(save->inten1,   base + SA1111_INTEN1);
-	sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
-	sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
-	sa1111_writel(save->wakeen0,  base + SA1111_WAKEEN0);
-	sa1111_writel(save->wakeen1,  base + SA1111_WAKEEN1);
 	spin_unlock_irqrestore(&sachip->lock, flags);
 
-	kfree(save);
+	if (level == RESUME_ENABLE) {
+		dev->saved_state = NULL;
+		kfree(save);
+	}
 
 	return 0;
 }
diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
--- a/arch/arm/kernel/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/arm/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -11,11 +11,9 @@
 obj-y		:= arch.o compat.o dma.o $(ENTRY_OBJ) entry-common.o irq.o   \
 		   process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
 		   time.o traps.o
-obj-m		:=
-obj-n		:=
-obj-		:=
 
 obj-$(CONFIG_APM)		+= apm.o
+obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_ARCH_ACORN)	+= ecard.o time-acorn.o
 obj-$(CONFIG_ARCH_CLPS7500)	+= time-acorn.o
 obj-$(CONFIG_FOOTBRIDGE)	+= isa.o
@@ -34,7 +32,7 @@
 obj-$(CONFIG_DEBUG_LL)	+= debug.o
 endif
 
-EXTRA_TARGETS := $(head-y) init_task.o
+extra-y := $(head-y) init_task.o
 
 # Spell out some dependencies that `make dep' doesn't spot
 $(obj)/entry-armv.o: 	$(obj)/entry-header.S include/asm-arm/constants.h
diff -Nru a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/kernel/apm.c	Thu Mar  6 07:59:42 2003
@@ -0,0 +1,573 @@
+/*
+ * bios-less APM driver for ARM Linux 
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+
+#include <asm/system.h>
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV	134
+
+/*
+ * See Documentation/Config.help for the configuration options.
+ *
+ * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
+ *	apm=on/off			enable/disable APM
+ */
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS		20
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+	struct list_head	list;
+
+	int			suser: 1;
+	int			writer: 1;
+	int			reader: 1;
+	int			suspend_wait: 1;
+	int			suspend_result;
+
+	int			suspends_pending;
+	int			standbys_pending;
+	unsigned int		suspends_read;
+	unsigned int		standbys_read;
+
+	int			event_head;
+	int			event_tail;
+	apm_event_t		events[APM_MAX_EVENTS];
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+static int standbys_pending;
+static int apm_disabled;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(apm_user_list);
+
+/*
+ * The kapmd info.
+ */
+static struct task_struct *kapmd;
+static DECLARE_COMPLETION(kapmd_exit);
+
+static const char driver_version[] = "1.13";	/* no spaces */
+
+/*
+ * This structure gets filled in by the machine specific 'get_power_status'
+ * implementation.  Any fields which are not set default to a safe value.
+ */
+struct apm_power_info {
+	unsigned char	ac_line_status;
+	unsigned char	battery_status;
+	unsigned char	battery_flag;
+	unsigned char	battery_life;
+	int		time;
+	int		units;
+};
+
+/*
+ * Compatibility cruft until the IPAQ people move over to the new
+ * interface.
+ */
+static void __apm_get_power_status(struct apm_power_info *info)
+{
+#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600)
+	extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *,
+					      u_char *, u_short *);
+
+	if (machine_is_h3600()) {
+		int dx;
+		h3600_apm_get_power_status(&info->ac_line_status,
+				&info->battery_status, &info->battery_flag,
+				&info->battery_life, &dx);
+		info->time = dx & 0x7fff;
+		info->units = dx & 0x8000 ? 0 : 1;
+	}
+#endif
+}
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
+EXPORT_SYMBOL(apm_get_power_status);
+
+static int queue_empty(struct apm_user *as)
+{
+	return as->event_head == as->event_tail;
+}
+
+static apm_event_t get_queued_event(struct apm_user *as)
+{
+	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+	return as->events[as->event_tail];
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+	as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
+	if (as->event_head == as->event_tail) {
+		static int notified;
+
+		if (notified++ == 0)
+		    printk(KERN_ERR "apm: an event queue overflowed\n");
+		as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+	}
+	as->events[as->event_head] = event;
+
+	if (!as->suser || !as->writer)
+		return;
+
+	switch (event) {
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+		as->suspends_pending++;
+		suspends_pending++;
+		break;
+
+	case APM_SYS_STANDBY:
+	case APM_USER_STANDBY:
+		as->standbys_pending++;
+		standbys_pending++;
+		break;
+	}
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+	struct list_head *l;
+
+	spin_lock(&user_list_lock);
+	list_for_each(l, &apm_user_list) {
+		struct apm_user *as = list_entry(l, struct apm_user, list);
+
+		if (as != sender && as->reader)
+			queue_event_one_user(as, event);
+	}
+	spin_unlock(&user_list_lock);
+	wake_up_interruptible(&apm_waitqueue);
+}
+
+/* defined in pm.c */
+extern int suspend(void);
+
+static int apm_suspend(void)
+{
+	struct list_head *l;
+	int err = suspend();
+
+	/*
+	 * Anyone on the APM queues will think we're still suspended.
+	 * Send a message so everyone knows we're now awake again.
+	 */
+	queue_event(APM_NORMAL_RESUME, NULL);
+
+	/*
+	 * Finally, wake up anyone who is sleeping on the suspend.
+	 */
+	spin_lock(&user_list_lock);
+	list_for_each(l, &apm_user_list) {
+		struct apm_user *as = list_entry(l, struct apm_user, list);
+
+		as->suspend_result = err;
+		as->suspend_wait = 0;
+	}
+	spin_unlock(&user_list_lock);
+
+	wake_up_interruptible(&apm_suspend_waitqueue);
+	return err;
+}
+
+static ssize_t apm_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
+{
+	struct apm_user *as = fp->private_data;
+	apm_event_t event;
+	int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK;
+
+	if (count < sizeof(apm_event_t))
+		return -EINVAL;
+
+	if (queue_empty(as) && nonblock)
+		return -EAGAIN;
+
+	wait_event_interruptible(apm_waitqueue, !queue_empty(as));
+
+	while ((i >= sizeof(event)) && !queue_empty(as)) {
+		event = get_queued_event(as);
+		printk("  apm_read: event=%d\n", event);
+
+		ret = -EFAULT;
+		if (copy_to_user(buf, &event, sizeof(event)))
+			break;
+
+		switch (event) {
+		case APM_SYS_SUSPEND:
+		case APM_USER_SUSPEND:
+			as->suspends_read++;
+			break;
+
+		case APM_SYS_STANDBY:
+		case APM_USER_STANDBY:
+			as->standbys_read++;
+			break;
+		}
+
+		buf += sizeof(event);
+		i -= sizeof(event);
+	}
+
+	if (i < count)
+		ret = count - i;
+
+	return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+	struct apm_user * as = fp->private_data;
+
+	poll_wait(fp, &apm_waitqueue, wait);
+	return queue_empty(as) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+	struct apm_user *as = filp->private_data;
+	int err = -EINVAL;
+
+	if (!as->suser || !as->writer)
+		return -EPERM;
+
+	switch (cmd) {
+	case APM_IOC_STANDBY:
+		break;
+
+	case APM_IOC_SUSPEND:
+		/*
+		 * If we read a suspend command from /dev/apm_bios,
+		 * then the corresponding APM_IOC_SUSPEND ioctl is
+		 * interpreted as an acknowledge.
+		 */
+		if (as->suspends_read > 0) {
+			as->suspends_read--;
+			as->suspends_pending--;
+			suspends_pending--;
+		} else {
+			queue_event(APM_USER_SUSPEND, as);
+		}
+
+		/*
+		 * If there are outstanding suspend requests for other
+		 * people on /dev/apm_bios, we must sleep for them.
+		 * Last one to bed turns the lights out.
+		 */
+		if (suspends_pending > 0) {
+			as->suspend_wait = 1;
+			err = wait_event_interruptible(apm_suspend_waitqueue,
+						 as->suspend_wait == 0);
+			if (err == 0)
+				err = as->suspend_result;
+		} else {			
+			err = apm_suspend();
+		}
+		break;
+	}
+
+	return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as = filp->private_data;
+	filp->private_data = NULL;
+
+	spin_lock(&user_list_lock);
+	list_del(&as->list);
+	spin_unlock(&user_list_lock);
+
+	/*
+	 * We are now unhooked from the chain.  As far as new
+	 * events are concerned, we no longer exist.  However, we
+	 * need to balance standbys_pending and suspends_pending,
+	 * which means the possibility of sleeping.
+	 */
+	if (as->standbys_pending > 0) {
+		standbys_pending -= as->standbys_pending;
+//		if (standbys_pending <= 0)
+//			standby();
+	}
+	if (as->suspends_pending > 0) {
+		suspends_pending -= as->suspends_pending;
+		if (suspends_pending <= 0)
+			apm_suspend();
+	}
+
+	kfree(as);
+	return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as;
+
+	as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+	if (as) {
+		memset(as, 0, sizeof(*as));
+
+		/*
+		 * XXX - this is a tiny bit broken, when we consider BSD
+		 * process accounting. If the device is opened by root, we
+		 * instantly flag that we used superuser privs. Who knows,
+		 * we might close the device immediately without doing a
+		 * privileged operation -- cevans
+		 */
+		as->suser = capable(CAP_SYS_ADMIN);
+		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+		spin_lock(&user_list_lock);
+		list_add(&as->list, &apm_user_list);
+		spin_unlock(&user_list_lock);
+
+		filp->private_data = as;
+	}
+
+	return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+	owner:		THIS_MODULE,
+	read:		apm_read,
+	poll:		apm_poll,
+	ioctl:		apm_ioctl,
+	open:		apm_open,
+	release:	apm_release,
+};
+
+static struct miscdevice apm_device = {
+	minor:		APM_MINOR_DEV,
+	name:		"apm_bios",
+	fops:		&apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   0) Linux driver version (this will change if format changes)
+ *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
+ *   2) APM flags from APM Installation Check (0x00):
+ *	bit 0: APM_16_BIT_SUPPORT
+ *	bit 1: APM_32_BIT_SUPPORT
+ *	bit 2: APM_IDLE_SLOWS_CLOCK
+ *	bit 3: APM_BIOS_DISABLED
+ *	bit 4: APM_BIOS_DISENGAGED
+ *   3) AC line status
+ *	0x00: Off-line
+ *	0x01: On-line
+ *	0x02: On backup power (BIOS >= 1.1 only)
+ *	0xff: Unknown
+ *   4) Battery status
+ *	0x00: High
+ *	0x01: Low
+ *	0x02: Critical
+ *	0x03: Charging
+ *	0x04: Selected battery not present (BIOS >= 1.2 only)
+ *	0xff: Unknown
+ *   5) Battery flag
+ *	bit 0: High
+ *	bit 1: Low
+ *	bit 2: Critical
+ *	bit 3: Charging
+ *	bit 7: No system battery
+ *	0xff: Unknown
+ *   6) Remaining battery life (percentage of charge):
+ *	0-100: valid
+ *	-1: Unknown
+ *   7) Remaining battery life (time units):
+ *	Number of remaining minutes or seconds
+ *	-1: Unknown
+ *   8) min = minutes; sec = seconds
+ */
+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+	struct apm_power_info info;
+	char *units;
+	int ret;
+
+	info.ac_line_status = 0xff;
+	info.battery_status = 0xff;
+	info.battery_flag   = 0xff;
+	info.battery_life   = 255;
+	info.time	    = -1;
+	info.units	    = -1;
+
+	if (apm_get_power_status)
+		apm_get_power_status(&info);
+
+	switch (info.units) {
+	default:	units = "?";	break;
+	case 0: 	units = "min";	break;
+	case 1: 	units = "sec";	break;
+	}
+
+	ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+		     driver_version, APM_32_BIT_SUPPORT,
+		     info.ac_line_status, info.battery_status,
+		     info.battery_flag, info.battery_life,
+		     info.time, units);
+
+ 	return ret;
+}
+#endif
+
+#if 0
+static int kapmd(void *startup)
+{
+	struct task_struct *tsk = current;
+
+	daemonize();
+	strcpy(tsk->comm, "kapmd");
+	kapmd = tsk;
+
+	spin_lock_irq(&tsk->sigmask_lock);
+	siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
+	recalc_sigpending(tsk);
+	spin_unlock_irq(&tsk->sigmask_lock);
+
+	complete((struct completion *)startup);
+
+	do {
+		set_task_state(tsk, TASK_INTERRUPTIBLE);
+		schedule();
+	} while (!signal_pending(tsk));
+
+	complete_and_exit(&kapmd_exit, 0);
+}
+#endif
+
+static int __init apm_init(void)
+{
+//	struct completion startup = COMPLETION_INITIALIZER(startup);
+	int ret;
+
+	if (apm_disabled) {
+		printk(KERN_NOTICE "apm: disabled on user request.\n");
+		return -ENODEV;
+	}
+
+	if (PM_IS_ACTIVE()) {
+		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+		return -EINVAL;
+	}
+
+//	ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
+//	if (ret)
+//		return ret;
+//	wait_for_completion(&startup);
+
+	pm_active = 1;
+
+#ifdef CONFIG_PROC_FS
+	create_proc_info_entry("apm", 0, NULL, apm_get_info);
+#endif
+
+	ret = misc_register(&apm_device);
+	if (ret != 0) {
+		pm_active = 0;
+		remove_proc_entry("apm", NULL);
+		send_sig(SIGQUIT, kapmd, 1);
+		wait_for_completion(&kapmd_exit);
+	}
+
+	return ret;
+}
+
+static void __exit apm_exit(void)
+{
+	misc_deregister(&apm_device);
+	remove_proc_entry("apm", NULL);
+	pm_active = 0;
+//	send_sig(SIGQUIT, kapmd, 1);
+//	wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+
+#ifndef MODULE
+static int __init apm_setup(char *str)
+{
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "off", 3) == 0)
+			apm_disabled = 1;
+		if (strncmp(str, "on", 2) == 0)
+			apm_disabled = 0;
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+	return 1;
+}
+
+__setup("apm=", apm_setup);
+#endif
diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
--- a/arch/arm/kernel/bios32.c	Thu Jan 16 06:42:22 2003
+++ b/arch/arm/kernel/bios32.c	Sun Mar 16 14:16:30 2003
@@ -18,7 +18,6 @@
 #include <asm/mach/pci.h>
 
 static int debug_pci;
-int have_isa_bridge;
 
 void pcibios_report_status(u_int status_mask, int warn)
 {
@@ -260,47 +259,6 @@
 	}, { 0 }
 };
 
-void __devinit
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-	struct pci_sys_data *sys = dev->sysdata;
-	u32 val, check;
-	int reg;
-
-	if (debug_pci)
-		printk("PCI: Assigning %3s %08lx to %s\n",
-			res->flags & IORESOURCE_IO ? "IO" : "MEM",
-			res->start, dev->dev.name);
-
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		reg = dev->rom_base_reg;
-	} else {
-		/* Somebody might have asked allocation of a
-		 * non-standard resource.
-		 */
-		return;
-	}
-
-	val = res->start;
-	if (res->flags & IORESOURCE_MEM)
-		val -= sys->mem_offset;
-	else
-		val -= sys->io_offset;
-	val |= res->flags & PCI_REGION_FLAG_MASK;
-
-	pci_write_config_dword(dev, reg, val);
-	pci_read_config_dword(dev, reg, &check);
-	if ((val ^ check) & ((val & PCI_BASE_ADDRESS_SPACE_IO) ?
-	    PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-			"%s/%d (%08x != %08x)\n", dev->slot_name,
-			resource, val, check);
-	}
-}
-
 void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
 {
 	if (debug_pci)
@@ -363,9 +321,8 @@
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_sys_data *root = bus->sysdata;
-	struct list_head *walk;
-	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
-	u16 all_status = -1;
+	struct pci_dev *dev;
+	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
 
 	pbus_assign_bus_resources(bus, root);
 
@@ -373,42 +330,43 @@
 	 * Walk the devices on this bus, working out what we can
 	 * and can't support.
 	 */
-	for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) {
-		struct pci_dev *dev = pci_dev_b(walk);
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		u16 status;
 
 		pdev_fixup_device_resources(root, dev);
 
 		pci_read_config_word(dev, PCI_STATUS, &status);
-		all_status &= status;
+
+		/*
+		 * If any device on this bus does not support fast back
+		 * to back transfers, then the bus as a whole is not able
+		 * to support them.  Having fast back to back transfers
+		 * on saves us one PCI cycle per transaction.
+		 */
+		if (!(status & PCI_STATUS_FAST_BACK))
+			features &= ~PCI_COMMAND_FAST_BACK;
 
 		if (pdev_bad_for_parity(dev))
 			features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
 
-		/*
-		 * If this device is an ISA bridge, set the have_isa_bridge
-		 * flag.  We will then go looking for things like keyboard,
-		 * etc
-		 */
-		if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA ||
-		    dev->class >> 8 == PCI_CLASS_BRIDGE_EISA)
-			have_isa_bridge = !0;
+		switch (dev->class >> 8) {
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+		case PCI_CLASS_BRIDGE_ISA:
+		case PCI_CLASS_BRIDGE_EISA:
+			/*
+			 * If this device is an ISA bridge, set isa_bridge
+			 * to point at this device.  We will then go looking
+			 * for things like keyboard, etc.
+			 */
+			isa_bridge = dev;
+			break;
+#endif
 	}
 
 	/*
-	 * If any device on this bus does not support fast back to back
-	 * transfers, then the bus as a whole is not able to support them.
-	 * Having fast back to back transfers on saves us one PCI cycle
-	 * per transaction.
-	 */
-	if (all_status & PCI_STATUS_FAST_BACK)
-		features |= PCI_COMMAND_FAST_BACK;
-
-	/*
 	 * Now walk the devices again, this time setting them up.
 	 */
-	for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) {
-		struct pci_dev *dev = pci_dev_b(walk);
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		u16 cmd;
 
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -416,7 +374,17 @@
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 
 		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
-				      SMP_CACHE_BYTES >> 2);
+				      L1_CACHE_BYTES >> 2);
+	}
+
+	/*
+	 * Propagate the flags to the PCI bridge.
+	 */
+	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		if (features & PCI_COMMAND_FAST_BACK)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+		if (features & PCI_COMMAND_PARITY)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
 	}
 
 	/*
@@ -430,18 +398,26 @@
  * Convert from Linux-centric to bus-centric addresses for bridge devices.
  */
 void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res)
 {
-	struct pci_sys_data *root = bus->sysdata;
+	struct pci_sys_data *root = dev->sysdata;
+	unsigned long offset = 0;
+
+	if (res->flags & IORESOURCE_IO)
+		offset = root->io_offset;
+	if (res->flags & IORESOURCE_MEM)
+		offset = root->mem_offset;
 
-	ranges->io_start -= root->io_offset;
-	ranges->io_end -= root->io_offset;
-	ranges->mem_start -= root->mem_offset;
-	ranges->mem_end -= root->mem_offset;
-	ranges->prefetch_start -= root->mem_offset;
-	ranges->prefetch_end -= root->mem_offset;
+	region->start = res->start - offset;
+	region->end   = res->end - offset;
 }
 
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
 /*
  * This is the standard PCI-PCI bridge swizzling algorithm:
  *
@@ -454,20 +430,17 @@
  */
 u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp)
 {
-	int pin = *pinp;
+	int pin = *pinp - 1;
 
-	if (pin != 0) {
-		pin -= 1;
-		while (dev->bus->self) {
-			pin = (pin + PCI_SLOT(dev->devfn)) & 3;
-			/*
-			 * move up the chain of bridges,
-			 * swizzling as we go.
-			 */
-			dev = dev->bus->self;
-		}
-		*pinp = pin + 1;
+	while (dev->bus->self) {
+		pin = (pin + PCI_SLOT(dev->devfn)) & 3;
+		/*
+		 * move up the chain of bridges,
+		 * swizzling as we go.
+		 */
+		dev = dev->bus->self;
 	}
+	*pinp = pin + 1;
 
 	return PCI_SLOT(dev->devfn);
 }
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	Tue Feb 11 14:57:50 2003
+++ b/arch/arm/kernel/ecard.c	Thu Mar  6 05:14:05 2003
@@ -37,7 +37,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
-#include <linux/notifier.h>
 #include <linux/device.h>
 #include <linux/init.h>
 
@@ -57,7 +56,7 @@
 
 enum req {
 	req_readbytes,
-	req_reset_all
+	req_reset
 };
 
 struct ecard_request {
@@ -131,14 +130,11 @@
 #define POD_INT_ADDR(x)	((volatile unsigned char *)\
 			 ((BUS_ADDR((x)) - IO_BASE) + IO_START))
 
-static inline void ecard_task_reset(void)
+static inline void ecard_task_reset(struct ecard_request *req)
 {
-	ecard_t *ec;
-
-	for (ec = cards; ec; ec = ec->next)
-		if (ec->loader)
-			ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
-					   ec->loader);
+	struct expansion_card *ec = req->ec;
+	if (ec->loader)
+		ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
 }
 
 static void
@@ -218,8 +214,8 @@
 		ecard_task_readbytes(req);
 		break;
 
-	case req_reset_all:
-		ecard_task_reset();
+	case req_reset:
+		ecard_task_reset(req);
 		break;
 	}
 }
@@ -355,60 +351,6 @@
 
 /* ======================= Mid-level card control ===================== */
 
-/*
- * This function is responsible for resetting the expansion cards to a
- * sensible state immediately prior to rebooting the system.  This function
- * has process state (keventd), so we can sleep.
- *
- * Possible "val" values here:
- *  SYS_RESTART   -  restarting system
- *  SYS_HALT      - halting system
- *  SYS_POWER_OFF - powering down system
- *
- * We ignore all calls, unless it is a SYS_RESTART call - power down/halts
- * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again.
- */
-static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v)
-{
-	struct ecard_request req;
-
-	if (val != SYS_RESTART)
-		return 0;
-
-	/*
-	 * Disable the expansion card interrupt
-	 */
-	disable_irq(IRQ_EXPANSIONCARD);
-
-	/*
-	 * If we have any expansion card loader code which will handle
-	 * the reset for us, call it now.
-	 */
-	req.req = req_reset_all;
-	ecard_call(&req);
-
-	/*
-	 * Disable the expansion card interrupt again, just to be sure.
-	 */
-	disable_irq(IRQ_EXPANSIONCARD);
-
-	/*
-	 * Finally, reset the expansion card interrupt mask to
-	 * all enable (RISC OS doesn't set this)
-	 */
-#ifdef HAS_EXPMASK
-	have_expmask = ~0;
-	__raw_writeb(have_expmask, EXPMASK_ENABLE);
-#endif
-	return 0;
-}
-
-static struct notifier_block ecard_reboot_notifier = {
-	.notifier_call	= ecard_reboot,
-};
-
-
-
 static void
 ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
 {
@@ -1083,11 +1025,6 @@
 {
 	int slot, irqhw;
 
-	/*
-	 * Register our reboot notifier
-	 */
-	register_reboot_notifier(&ecard_reboot_notifier);
-
 #ifdef CONFIG_CPU_32
 	init_waitqueue_head(&ecard_wait);
 #endif
@@ -1158,11 +1095,32 @@
 	return 0;
 }
 
+/*
+ * Before rebooting, we must make sure that the expansion card is in a
+ * sensible state, so it can be re-detected.  This means that the first
+ * page of the ROM must be visible.  We call the expansion cards reset
+ * handler, if any.
+ */
+static void ecard_drv_shutdown(struct device *dev)
+{
+	struct expansion_card *ec = ECARD_DEV(dev);
+	struct ecard_driver *drv = ECARD_DRV(dev->driver);
+	struct ecard_request req;
+
+	if (drv->shutdown)
+		drv->shutdown(ec);
+	ecard_release(ec);
+	req.req = req_reset;
+	req.ec = ec;
+	ecard_call(&req);
+}
+
 int ecard_register_driver(struct ecard_driver *drv)
 {
 	drv->drv.bus = &ecard_bus_type;
 	drv->drv.probe = ecard_drv_probe;
 	drv->drv.remove = ecard_drv_remove;
+	drv->drv.shutdown = ecard_drv_shutdown;
 
 	return driver_register(&drv->drv);
 }
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S	Mon Feb 24 12:42:23 2003
+++ b/arch/arm/kernel/entry-armv.S	Thu Mar  6 07:52:20 2003
@@ -1028,8 +1028,10 @@
 		@
 		@ now branch to the relevant MODE handling routine
 		@
-		mov	r13, #PSR_I_BIT | MODE_SVC
-		msr	spsr_c, r13			@ switch to SVC_32 mode
+		mrs	r13, cpsr
+		bic	r13, r13, #MODE_MASK
+		orr	r13, r13, #MODE_SVC
+		msr	spsr, r13			@ switch to SVC_32 mode
 
 		and	lr, lr, #15
 		ldr	lr, [pc, lr, lsl #2]
diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
--- a/arch/arm/kernel/entry-common.S	Sat Jul 27 12:49:37 2002
+++ b/arch/arm/kernel/entry-common.S	Thu Mar  6 05:18:11 2003
@@ -75,9 +75,8 @@
  * This is how we return from a fork.
  */
 ENTRY(ret_from_fork)
-#ifdef CONFIG_PREEMPT
+	ldr	r0, [r0, #TI_TASK]
 	bl	schedule_tail
-#endif
 	get_thread_info tsk
 	ldr	r1, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	mov	why, #1
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	Tue Feb 11 15:05:29 2003
+++ b/arch/arm/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -165,17 +165,22 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_controller_lock, flags);
 	    	action = irq_desc[i].action;
 		if (!action)
-			continue;
+			goto unlock;
+
 		seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
 		seq_printf(p, "  %s", action->name);
-		for (action = action->next; action; action = action->next) {
+		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
-		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_controller_lock, flags);
 	}
 
 #ifdef CONFIG_ARCH_ACORN
diff -Nru a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/kernel/pm.c	Thu Mar  6 07:59:45 2003
@@ -0,0 +1,126 @@
+/*
+ *  linux/arch/arm/kernel/suspend.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ *
+ *  This is the common support code for suspending an ARM machine.
+ *  pm_do_suspend() is responsible for actually putting the CPU to
+ *  sleep.
+ */
+#include <linux/config.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/cpufreq.h>
+
+#include <asm/leds.h>
+#include <asm/system.h>
+
+int suspend(void)
+{
+	int ret;
+
+	/*
+	 * Suspend "legacy" devices.
+	 */
+	ret = pm_send_all(PM_SUSPEND, (void *)3);
+	if (ret != 0)
+		goto out;
+
+	/*
+	 * Tell LDM devices we're going to suspend.
+	 */
+	ret = device_suspend(4, SUSPEND_NOTIFY);
+	if (ret != 0)
+		goto resume_legacy;
+
+	/*
+	 * Disable, devices, and save state.
+	 */
+	device_suspend(4, SUSPEND_DISABLE);
+	device_suspend(4, SUSPEND_SAVE_STATE);
+
+	/*
+	 * Tell devices that they're going to be powered off.
+	 */
+	device_suspend(4, SUSPEND_POWER_DOWN);
+
+	local_irq_disable();
+	leds_event(led_stop);
+
+	ret = pm_do_suspend();
+
+	leds_event(led_start);
+	local_irq_enable();
+
+	/*
+	 * Tell devices that they now have power.
+	 */
+	device_resume(RESUME_POWER_ON);
+
+	/*
+	 * Restore the CPU frequency settings.
+	 */
+#ifdef CONFIG_CPU_FREQ
+	cpufreq_restore();
+#endif
+
+	/*
+	 * Resume LDM devices.
+	 */
+	device_resume(RESUME_RESTORE_STATE);
+	device_resume(RESUME_ENABLE);
+
+ resume_legacy:
+	/*
+	 * Resume "legacy" devices.
+	 */
+	pm_send_all(PM_RESUME, (void *)0);
+
+ out:
+	return ret;
+}
+
+#ifdef CONFIG_SYSCTL
+#include <linux/init.h>
+#include <linux/sysctl.h>
+
+/*
+ * This came from arch/arm/mach-sa1100/pm.c:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *  with modifications by Nicolas Pitre and Russell King.
+ *
+ * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
+ * linux/sysctl.h.
+ *
+ * This means our interface here won't survive long - it needs a new
+ * interface.  Quick hack to get this working - use sysctl id 9999.
+ */
+#warning ACPI broke the kernel, this interface needs to be fixed up.
+#define CTL_ACPI 9999
+#define ACPI_S1_SLP_TYP 19
+
+static struct ctl_table pm_table[] =
+{
+	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend},
+	{0}
+};
+
+static struct ctl_table pm_dir_table[] =
+{
+	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
+	{0}
+};
+
+/*
+ * Initialize power interface
+ */
+static int __init pm_init(void)
+{
+	register_sysctl_table(pm_dir_table, 1);
+	return 0;
+}
+
+fs_initcall(pm_init);
+
+#endif
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c	Mon Feb 24 23:13:09 2003
+++ b/arch/arm/kernel/time.c	Thu Mar  6 05:40:54 2003
@@ -200,6 +200,7 @@
 
 static struct irqaction timer_irq = {
 	.name	= "timer",
+	.flags	= SA_INTERRUPT,
 };
 
 /*
diff -Nru a/arch/arm/mach-arc/Makefile b/arch/arm/mach-arc/Makefile
--- a/arch/arm/mach-arc/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/arm/mach-arc/Makefile	Sun Mar  9 14:15:54 2003
@@ -6,12 +6,9 @@
 
 obj-y			:= arch.o dma.o fault.o irq.o mm.o oldlatches.o \
 			   small_page.o
-obj-m			:=
-obj-n			:=
-obj-			:=
 
 obj-$(CONFIG_DEBUG_LL)	+= debug.o
 
-EXTRA_TARGETS 		:= head.o
+extra-y 		:= head.o
 
 AFLAGS_head.o		:= -DTEXTADDR=$(TEXTADDR)
diff -Nru a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
--- a/arch/arm/mach-integrator/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/arm/mach-integrator/Makefile	Thu Mar  6 08:48:28 2003
@@ -4,10 +4,11 @@
 
 # Object file lists.
 
-obj-y			:= arch.o cpu.o irq.o mm.o time.o
+obj-y			:= arch.o irq.o mm.o time.o
 obj-m			:=
 obj-n			:=
 obj-			:=
 
 obj-$(CONFIG_LEDS)	+= leds.o
 obj-$(CONFIG_PCI)	+= pci_v3.o pci.o
+obj-$(CONFIG_CPU_FREQ_INTEGRATOR)	+= cpu.o
diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
--- a/arch/arm/mach-integrator/cpu.c	Tue Jan 14 16:01:39 2003
+++ b/arch/arm/mach-integrator/cpu.c	Thu Mar  6 11:27:03 2003
@@ -23,6 +23,8 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 
+static struct cpufreq_driver integrator_driver;
+
 #define CM_ID  	(IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET)
 #define CM_OSC	(IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET)
 #define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET)
@@ -43,7 +45,6 @@
 	return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor;
 }
 
-#ifdef CONFIG_CPU_FREQ
 /*
  * Divisor indexes in ascending divisor order
  */
@@ -69,21 +70,17 @@
 	return vco;
 }
 
+
 /*
- * Validate the speed in khz.  If it is outside our
- * range, then return the lowest.
+ * Validate the speed policy.
  */
-static int integrator_verify_speed(struct cpufreq_policy *policy)
+static int integrator_verify_policy(struct cpufreq_policy *policy)
 {
 	struct vco vco;
 
-	if (policy->max > policy->cpuinfo.max_freq)
-		policy->max = policy->cpuinfo.max_freq;
-
-	if (policy->max < 12000)
-		policy->max = 12000;
-	if (policy->max > 160000)
-		policy->max = 160000;
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
 
 	vco = freq_to_vco(policy->max, 1);
 
@@ -92,12 +89,28 @@
 	if (vco.vdw > 152)
 		vco.vdw = 152;
 
-	policy->min = policy->max = vco_to_freq(vco, 1);
+	policy->max = vco_to_freq(vco, 1);
+
+	vco = freq_to_vco(policy->min, 1);
+
+	if (vco.vdw < 4)
+		vco.vdw = 4;
+	if (vco.vdw > 152)
+		vco.vdw = 152;
+
+	policy->min = vco_to_freq(vco, 1);
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
 
 	return 0;
 }
 
-static int integrator_set_policy(struct cpufreq_policy *policy)
+
+static int integrator_set_target(struct cpufreq_policy *policy,
+				 unsigned int target_freq,
+				 unsigned int relation)
 {
 	unsigned long cpus_allowed;
 	int cpu = policy->cpu;
@@ -121,9 +134,18 @@
 	cm_osc = __raw_readl(CM_OSC);
 	vco.od = (cm_osc >> 8) & 7;
 	vco.vdw = cm_osc & 255;
-
 	freqs.old = vco_to_freq(vco, 1);
-	freqs.new = target_freq;
+
+	/* freq_to_vco rounds down -- so we need the next larger freq in
+	 * case of CPUFREQ_RELATION_L.
+	 */
+	if (relation == CPUFREQ_RELATION_L)
+		target_freq += 1999;
+	if (target_freq > policy->max)
+		target_freq = policy->max;
+	vco = freq_to_vco(target_freq, 1);
+	freqs.new = vco_to_freq(vco, 1);
+
 	freqs.cpu = policy->cpu;
 
 	if (freqs.old == freqs.new) {
@@ -132,7 +154,6 @@
 	}
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	vco = freq_to_vco(policy->max, 1);
 
 	cm_osc = __raw_readl(CM_OSC);
 	cm_osc &= 0xfffff800;
@@ -152,80 +173,64 @@
 	return 0;
 }
 
-static struct cpufreq_policy integrator_policy = {
-	.cpu		= 0,
-	.policy		= CPUFREQ_POLICY_POWERSAVE,
-	.cpuinfo	= {
-		.max_freq		= 160000,
-		.min_freq		= 12000,
-		.transition_latency	= CPUFREQ_ETERNAL,
-	},
-};
+static int integrator_cpufreq_init(struct cpufreq *policy)
+{
+	unsigned long cus_allowed;
+	unsigned int cpu = policy->cpu;
+	u_int cm_osc, cm_stat, mem_freq_khz;
+	struct vco vco;
 
-static struct cpufreq_driver integrator_driver = {
-	.verify		= integrator_verify_speed,
-	.setpolicy	= integrator_set_policy,
-	.policy		= &integrator_policy,
-	.name		= "integrator",
-};
-#endif
+	cpus_allowed = current->cpus_allowed;
 
-static int __init integrator_cpu_init(void)
-{
-	struct cpufreq_policy *policies;
-	unsigned long cpus_allowed;
-	int cpu;
+	set_cpus_allowed(current, 1 << cpu);
+	BUG_ON(cpu != smp_processor_id());
 
-	policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS,
-			   GFP_KERNEL);
-	if (!policies) {
-		printk(KERN_ERR "CPU: unable to allocate policies structure\n");
-		return -ENOMEM;
-	}
+	/* detect memory etc. */
+	cm_stat = __raw_readl(CM_STAT);
+	cm_osc = __raw_readl(CM_OSC);
+	vco.od  = (cm_osc >> 20) & 7;
+	vco.vdw = (cm_osc >> 12) & 255;
+	mem_freq_khz = vco_to_freq(vco, 2);
+
+	printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
+	printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
+	       cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
 
-	cpus_allowed = current->cpus_allowed;
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-		u_int cm_osc, cm_stat, mem_freq_khz;
-		struct vco vco;
-
-		if (!cpu_online(cpu))
-			continue;
-
-		set_cpus_allowed(current, 1 << cpu);
-		BUG_ON(cpu != smp_processor_id());
-
-		cm_stat = __raw_readl(CM_STAT);
-		cm_osc = __raw_readl(CM_OSC);
-		vco.od  = (cm_osc >> 20) & 7;
-		vco.vdw = (cm_osc >> 12) & 255;
-		mem_freq_khz = vco_to_freq(vco, 2);
-
-		printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
-		printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
-			cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
-
-		vco.od = (cm_osc >> 8) & 7;
-		vco.vdw = cm_osc & 255;
-
-		policies[cpu].cpu = cpu;
-		policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE,
-		policies[cpu].cpuinfo.max_freq = 160000;
-		policies[cpu].cpuinfo.min_freq = 12000;
-		policies[cpu].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-		policies[cpu].min =
-		policies[cpu].max = vco_to_freq(vco, 1);
-	}
+	vco.od = (cm_osc >> 8) & 7;
+	vco.vdw = cm_osc & 255;
 
-	set_cpus_allowed(current, cpus_allowed);
+	/* set default policy and cpuinfo */
+	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+	policy->cpuinfo.max_freq = 160000;
+	policy->cpuinfo.min_freq = 12000;
+	policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */
+	policy->cur = policy->min = policy->max = vco_to_freq(vco, 1); /* current freq */
 
-#ifdef CONFIG_CPU_FREQ
-	integrator_driver.policy = policies;
-	cpufreq_register(&integrator_driver);
-#else
-	kfree(policies);
-#endif
+	set_cpus_allowed(current, cpus_allowed);
 
 	return 0;
 }
 
-arch_initcall(integrator_cpu_init);
+static struct cpufreq_driver integrator_driver = {
+	.verify		= integrator_verify_policy,
+	.target		= integrator_set_target,
+	.init		= integrator_cpufreq_init,
+	.name		= "integrator",
+};
+
+static int __init integrator_cpu_init(void)
+{
+	return cpufreq_register_driver(&integrator_driver);
+}
+
+static void __exit integrator_cpu_exit(void)
+{
+	cpufreq_unregister_driver(&integrator_driver);
+}
+
+MODULE_AUTHOR ("Russell M. King");
+MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
+MODULE_LICENSE ("GPL");
+
+module_init(integrator_cpu_init);
+module_exit(integrator_cpu_exit);
diff -Nru a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
--- a/arch/arm/mach-sa1100/Kconfig	Wed Nov 13 08:41:25 2002
+++ b/arch/arm/mach-sa1100/Kconfig	Thu Mar  6 16:15:28 2003
@@ -326,6 +326,15 @@
 #	help
 #	  :: write me ::
 
+config SA1100_SSP
+	tristate "Generic PIO SSP"
+	depends on ARCH_SA1100
+	help
+	  Say Y here to enable support for the generic PIO SSP driver.
+	  This isn't for audio support, but for attached sensors and
+	  other devices, eg for BadgePAD 4 sensor support, or Jornada
+	  720 touchscreen support.
+
 config SA1100_USB
 	tristate "SA1100 USB function support"
 	depends on ARCH_SA1100
diff -Nru a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
--- a/arch/arm/mach-sa1100/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/arm/mach-sa1100/Makefile	Thu Mar  6 16:15:28 2003
@@ -9,15 +9,8 @@
 obj-  :=
 led-y := leds.o
 
-# This needs to be cleaned up.  We probably need to have SA1100
-# and SA1110 config symbols.
-ifeq ($(CONFIG_CPU_FREQ),y)
-obj-$(CONFIG_SA1100_ASSABET)		+= cpu-sa1110.o
-obj-$(CONFIG_SA1100_CERF)		+= cpu-sa1110.o
-obj-$(CONFIG_SA1100_HACKKIT)		+= cpu-sa1110.o
-obj-$(CONFIG_SA1100_LART)		+= cpu-sa1100.o
-obj-$(CONFIG_SA1100_PT_SYSTEM3)		+= cpu-sa1110.o
-endif
+obj-$(CONFIG_CPU_FREQ_SA1100)		+= cpu-sa1100.o
+obj-$(CONFIG_CPU_FREQ_SA1110)		+= cpu-sa1110.o
 
 # Specific board support
 obj-$(CONFIG_SA1100_ADSBITSY)		+= adsbitsy.o
@@ -99,3 +92,4 @@
 
 # Miscelaneous functions
 obj-$(CONFIG_PM)			+= pm.o sleep.o
+obj-$(CONFIG_SA1100_SSP)		+= ssp.o
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
--- a/arch/arm/mach-sa1100/cpu-sa1100.c	Tue Jan 14 16:01:40 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c	Thu Mar  6 11:27:04 2003
@@ -101,7 +101,7 @@
 } sa1100_dram_regs_t;
 
 
-
+static struct cpufreq_driver sa1100_driver;
 
 static sa1100_dram_regs_t sa1100_dram_settings[] =
 {
@@ -176,60 +176,73 @@
 	}
 }
 
-static int sa1100_setspeed(struct cpufreq_policy *policy)
+static int sa1100_target(struct cpufreq_policy *policy,
+			 unsigned int target_freq,
+			 unsigned int relation)
 {
 	unsigned int cur = sa11x0_getspeed();
+	unsigned int new_ppcr;
+
 	struct cpufreq_freqs freqs;
+	switch(relation){
+	case CPUFREQ_RELATION_L:
+		new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
+			new_ppcr--;
+		break;
+	case CPUFREQ_RELATION_H:
+		new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
+		    (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
+			mew_ppcr--;
+		break;
+	}
 
 	freqs.old = cur;
-	freqs.new = policy->max;
+	freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
 	freqs.cpu = 0;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	if (policy->max > cur)
-		sa1100_update_dram_timings(cur, policy->max);
+	if (freqs.new > cur)
+		sa1100_update_dram_timings(cur, freqs.new);
 
-	PPCR = sa11x0_freq_to_ppcr(policy->max);
+	PPCR = new_ppcr;
 
-	if (policy->max < cur)
-		sa1100_update_dram_timings(cur, policy->max);
+	if (freqs.new < cur)
+		sa1100_update_dram_timings(cur, freqs.new);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
 
-static struct cpufreq_policy sa1100_policy = {
-	.cpu		= 0,
-	.policy		= CPUFREQ_POLICY_POWERSAVE,
-	.cpuinfo	= {
-		.max_freq		= 287000,
-		.min_freq		= 59000,
-		.transition_latency	= CPUFREQ_ETERNAL,
-	},
-};
+static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+	policy->cur = policy->min = policy->max = sa11x0_getspeed();
+	policy->policy = CPUFREQ_POLICY_POWERSAVE;
+	policy->cpuinfo.min_freq = 59000;
+	policy->cpuinfo.max_freq = 287000;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	return 0;
+}
 
 static struct cpufreq_driver sa1100_driver = {
 	.verify		= sa11x0_verify_speed,
-	.setpolicy	= sa1100_setspeed,
-	.policy		= &sa1100_policy,
+	.target		= sa1100_target,
+	.init		= sa1100_cpu_init,
 	.name		= "sa1100",
 };
 
 static int __init sa1100_dram_init(void)
 {
-	int ret = -ENODEV;
-
-	if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
-		sa1100_driver.cpu_cur_freq[0] =
-		sa1100_policy.min =
-		sa1100_policy.max = sa11x0_getspeed();
-
-		ret = cpufreq_register(&sa1100_driver);
-	}
-
-	return ret;
+	cpufreq_gov_userspace_init();
+ 	if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID)
+		return cpufreq_register_driver(&sa1100_driver);
+	else
+		return -ENODEV;
 }
 
 arch_initcall(sa1100_dram_init);
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
--- a/arch/arm/mach-sa1100/cpu-sa1110.c	Tue Jan 14 16:01:40 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c	Thu Mar  6 11:27:04 2003
@@ -32,6 +32,8 @@
 
 #undef DEBUG
 
+static struct cpufreq_driver sa1110_driver;
+
 struct sdram_params {
 	u_char  rows;		/* bits				 */
 	u_char  cas_latency;	/* cycles			 */
@@ -208,11 +210,11 @@
 }
 
 /*
- * Ok, set the CPU frequency.  Since we've done the validation
- * above, we can match for an exact frequency.  If we don't find
- * an exact match, we will to set the lowest frequency to be safe.
+ * Ok, set the CPU frequency.  
  */
-static int sa1110_setspeed(struct cpufreq_policy *policy)
+static int sa1110_target(struct cpufreq_policy *policy,
+			 unsigned int target_freq,
+			 unsigned int relation)
 {
 	struct sdram_params *sdram = &sdram_params;
 	struct cpufreq_freqs freqs;
@@ -220,8 +222,25 @@
 	unsigned long flags;
 	unsigned int ppcr, unused;
 
-	ppcr = sa11x0_freq_to_ppcr(policy->max);
-	sdram_calculate_timing(&sd, policy->max, sdram);
+	switch(relation){
+	case CPUFREQ_RELATION_L:
+		ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
+			ppcr--;
+		break;
+	case CPUFREQ_RELATION_H:
+		ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
+		    (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
+			ppcr--;
+		break;
+	}
+
+	freqs.old = sa11x0_getspeed();
+	freqs.new = sa11x0_ppcr_to_freq(ppcr);
+	freqs.cpu = 0;
+
+	sdram_calculate_timing(&sd, freqs.new, sdram);
 
 #if 0
 	/*
@@ -240,10 +259,6 @@
 	sd.mdcas[2] = 0xaaaaaaaa;
 #endif
 
-	freqs.old = sa11x0_getspeed();
-	freqs.new = policy->max;
-	freqs.cpu = 0;
-
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/*
@@ -288,27 +303,29 @@
 	/*
 	 * Now, return the SDRAM refresh back to normal.
 	 */
-	sdram_update_refresh(policy->max, sdram);
+	sdram_update_refresh(freqs.new, sdram);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
 
-static struct cpufreq_policy sa1110_policy = {
-	.cpu		= 0,
-	.policy		= CPUFREQ_POLICY_POWERSAVE,
-	.cpuinfo	= {
-		.max_freq		= 287000,
-		.min_freq		= 59000,
-		.transition_latency	= CPUFREQ_ETERNAL,
-	},
-};
+static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+	policy->cur = policy->min = policy->max = sa11x0_getspeed();
+	policy->policy = CPUFREQ_POLICY_POWERSAVE;
+	policy->cpuinfo.min_freq = 59000;
+	policy->cpuinfo.max_freq = 287000;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	return 0;
+}
 
 static struct cpufreq_driver sa1110_driver = {
-	.verify		 = sa11x0_verify_speed,
-	.setpolicy	 = sa1110_setspeed,
-	.policy		 = &sa1110_policy,
+	.verify		= sa11x0_verify_speed,
+	.target		= sa1110_target,
+	.init		= sa1110_cpu_init,
 	.name		= "sa1110",
 };
 
@@ -331,15 +348,11 @@
 			sdram->tck, sdram->trcd, sdram->trp,
 			sdram->twr, sdram->refresh, sdram->cas_latency);
 
+		cpufreq_gov_userspace_init();
+ 
 		memcpy(&sdram_params, sdram, sizeof(sdram_params));
 
-		sa1110_driver.cpu_cur_freq[0] =
-		sa1110_policy.min =
-		sa1110_policy.max = sa11x0_getspeed();
-
-		sa1110_setspeed(&sa1110_policy);
-
-		return cpufreq_register(&sa1110_driver);
+		return cpufreq_register_driver(&sa1110_driver);
 	}
 
 	return 0;
diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
--- a/arch/arm/mach-sa1100/generic.c	Fri Dec 13 06:22:36 2002
+++ b/arch/arm/mach-sa1100/generic.c	Thu Mar  6 12:25:44 2003
@@ -48,33 +48,48 @@
 	2802    /* 280.2 MHz */
 };
 
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110)
+/* rounds up(!)  */
 unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
 {
 	int i;
 
 	khz /= 100;
 
-	for (i = NR_FREQS - 1; i > 0; i--)
-		if (cclk_frequency_100khz[i] <= khz)
+	for (i = 0; i < NR_FREQS; i++)
+		if (cclk_frequency_100khz[i] >= khz)
 			break;
 
 	return i;
 }
 
-/*
- * Validate the policy.  We aren't able to do any fancy in-kernel
- * scaling, so we force min=max, and set the policy to "performance".
- * If we can't generate the precise frequency requested, round it up.
+unsigned int sa11x0_ppcr_to_freq(unsigned int idx)
+{
+	unsigned int freq = 0;
+	if (idx < NR_FREQS)
+		freq = cclk_frequency_100khz[idx] * 100;
+	return freq;
+}
+
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
  */
 int sa11x0_verify_speed(struct cpufreq_policy *policy)
 {
-	if (policy->max > policy->cpuinfo.max_freq)
-		policy->max = policy->cpuinfo.max_freq;
+	unsigned int tmp;
+	if (policy->cpu)
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+	/* make sure that at least one frequency is within the policy */
+	tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100;
+	if (tmp > policy->max)
+		policy->max = tmp;
+
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
 
-	policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100;
-	policy->min = policy->max;
-	policy->policy = CPUFREQ_POLICY_POWERSAVE;
 	return 0;
 }
 
diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
--- a/arch/arm/mach-sa1100/generic.h	Sun Nov 24 15:14:21 2002
+++ b/arch/arm/mach-sa1100/generic.h	Thu Mar  6 08:48:29 2003
@@ -23,3 +23,4 @@
 extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
 extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
 extern unsigned int sa11x0_getspeed(void);
+extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
--- a/arch/arm/mach-sa1100/irq.c	Sun Mar  2 23:32:23 2003
+++ b/arch/arm/mach-sa1100/irq.c	Thu Mar  6 12:33:33 2003
@@ -211,6 +211,99 @@
 	.end	= 0x9005ffff,
 };
 
+struct sa1100irq_state {
+	unsigned int	saved;
+	unsigned int	icmr;
+	unsigned int	iclr;
+	unsigned int	iccr;
+};
+
+static int sa1100irq_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct sa1100irq_state *st;
+
+	if (!dev->saved_state && level == SUSPEND_NOTIFY)
+		dev->saved_state = kmalloc(sizeof(struct sa1100irq_state),
+					   GFP_KERNEL);
+	if (!dev->saved_state)
+		return -ENOMEM;
+
+	if (level == SUSPEND_POWER_DOWN) {
+		st = (struct sa1100irq_state *)dev->saved_state;
+
+		st->saved = 1;
+		st->icmr = ICMR;
+		st->iclr = ICLR;
+		st->iccr = ICCR;
+
+		/*
+		 * Disable all GPIO-based interrupts.
+		 */
+		ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
+			  IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
+			  IC_GPIO1|IC_GPIO0);
+
+		/*
+		 * Set the appropriate edges for wakeup.
+		 */
+		GRER = PWER & GPIO_IRQ_rising_edge;
+		GFER = PWER & GPIO_IRQ_falling_edge;
+
+		/*
+		 * Clear any pending GPIO interrupts.
+		 */
+		GEDR = GEDR;
+	}
+	return 0;
+}
+
+static int sa1100irq_resume(struct device *dev, u32 level)
+{
+	struct sa1100irq_state *st;
+
+	if (level == RESUME_POWER_ON) {
+		st = (struct sa1100irq_state *)dev->saved_state;
+		dev->saved_state = NULL;
+
+		if (st->saved) {
+			ICCR = st->iccr;
+			ICLR = st->iclr;
+
+			GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+			GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+
+			ICMR = st->icmr;
+		}
+
+		kfree(st);
+	}
+	return 0;
+}
+
+static struct device_driver sa1100irq_driver = {
+	.name		= "sa11x0-irq",
+	.bus		= &system_bus_type,
+	.suspend	= sa1100irq_suspend,
+	.resume		= sa1100irq_resume,
+};
+
+static struct sys_device sa1100irq_device = {
+	.name		= "irq",
+	.id		= 0,
+	.dev = {
+		.name	= "Intel SA11x0 [Interrupt Controller]",
+		.driver	= &sa1100irq_driver,
+	},
+};
+
+static int __init sa1100irq_init_devicefs(void)
+{
+	driver_register(&sa1100irq_driver);
+	return sys_device_register(&sa1100irq_device);
+}
+
+device_initcall(sa1100irq_init_devicefs);
+
 void __init sa1100_init_irq(void)
 {
 	unsigned int irq;
diff -Nru a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
--- a/arch/arm/mach-sa1100/pm.c	Sun Nov 17 07:31:13 2002
+++ b/arch/arm/mach-sa1100/pm.c	Thu Mar  6 08:08:20 2003
@@ -22,25 +22,12 @@
  * 2002-05-27:	Nicolas Pitre	Killed sleep.h and the kmalloced save array.
  * 				Storage is local on the stack now.
  */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pm.h>
-#include <linux/sysctl.h>
 #include <linux/errno.h>
-#include <linux/device.h>
-#include <linux/cpufreq.h>
+#include <linux/time.h>
 
 #include <asm/hardware.h>
 #include <asm/memory.h>
 #include <asm/system.h>
-#include <asm/leds.h>
-
-
-/*
- * Debug macros
- */
-#undef DEBUG
 
 extern void sa1100_cpu_suspend(void);
 extern void sa1100_cpu_resume(void);
@@ -58,10 +45,9 @@
 	SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
 	SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
 
-	SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR,
+	SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
 	SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
 
-	SLEEP_SAVE_ICMR,
 	SLEEP_SAVE_Ser1SDCR0,
 
 	SLEEP_SAVE_SIZE
@@ -72,10 +58,6 @@
 {
 	unsigned long sleep_save[SLEEP_SAVE_SIZE];
 
-	local_irq_disable();
-
-	leds_event(led_stop);
-
 	/* preserve current time */
 	RCNR = xtime.tv_sec;
 
@@ -88,8 +70,6 @@
 	SAVE(OIER);
 
 	SAVE(GPDR);
-	SAVE(GRER);
-	SAVE(GFER);
 	SAVE(GAFR);
 
 	SAVE(PPDR);
@@ -99,13 +79,6 @@
 
 	SAVE(Ser1SDCR0);
 
-	SAVE(ICMR);
-
-	/* ... maybe a global variable initialized by arch code to set this? */
-	GRER = PWER;
-	GFER = 0;
-	GEDR = GEDR;
-
 	/* Clear previous reset status */
 	RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
 
@@ -115,22 +88,23 @@
 	/* go zzz */
 	sa1100_cpu_suspend();
 
-	/* ensure not to come back here if it wasn't intended */
+	/*
+	 * Ensure not to come back here if it wasn't intended
+	 */
 	PSPR = 0;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "*** made it back from resume\n");
-#endif
+	/*
+	 * Ensure interrupt sources are disabled; we will re-init
+	 * the interrupt subsystem via the device manager.
+	 */
+	ICLR = 0;
+	ICCR = 1;
+	ICMR = 0;
 
 	/* restore registers */
 	RESTORE(GPDR);
-	RESTORE(GRER);
-	RESTORE(GFER);
 	RESTORE(GAFR);
 
-	/* clear any edge detect bit */
-	GEDR = GEDR;
-
 	RESTORE(PPDR);
 	RESTORE(PPSR);
 	RESTORE(PPAR);
@@ -138,6 +112,9 @@
 
 	RESTORE(Ser1SDCR0);
 
+	/*
+	 * Clear the peripheral sleep-hold bit.
+	 */
 	PSSR = PSSR_PH;
 
 	RESTORE(OSMR0);
@@ -147,24 +124,9 @@
 	RESTORE(OSCR);
 	RESTORE(OIER);
 
-	ICLR = 0;
-	ICCR = 1;
-	RESTORE(ICMR);
-
 	/* restore current time */
 	xtime.tv_sec = RCNR;
 
-	leds_event(led_start);
-
-	local_irq_enable();
-
-	/*
-	 * Restore the CPU frequency settings.
-	 */
-#ifdef CONFIG_CPU_FREQ
-	cpufreq_restore();
-#endif
-
 	return 0;
 }
 
@@ -172,78 +134,3 @@
 {
 	return virt_to_phys(sp);
 }
-
-#ifdef CONFIG_SYSCTL
-/*
- * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
- * linux/sysctl.h.
- *
- * This means our interface here won't survive long - it needs a new
- * interface.  Quick hack to get this working - use sysctl id 9999.
- */
-#warning ACPI broke the kernel, this interface needs to be fixed up.
-#define CTL_ACPI 9999
-#define ACPI_S1_SLP_TYP 19
-
-/*
- * Send us to sleep.
- */
-static int sysctl_pm_do_suspend(void)
-{
-	int retval;
-
-	/*
-	 * Suspend "legacy" devices.
-	 */
-	retval = pm_send_all(PM_SUSPEND, (void *)3);
-	if (retval == 0) {
-		/*
-		 * Suspend LDM devices.
-		 */
-		device_suspend(4, SUSPEND_NOTIFY);
-		device_suspend(4, SUSPEND_SAVE_STATE);
-		device_suspend(4, SUSPEND_DISABLE);
-
-		retval = pm_do_suspend();
-
-		/*
-		 * Resume LDM devices.
-		 */
-		device_resume(RESUME_RESTORE_STATE);
-		device_resume(RESUME_ENABLE);
-
-		/*
-		 * Resume "legacy" devices.
-		 */
-		pm_send_all(PM_RESUME, (void *)0);
-	}
-
-	return retval;
-}
-
-static struct ctl_table pm_table[] =
-{
-	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
-	{0}
-};
-
-static struct ctl_table pm_dir_table[] =
-{
-	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-	{0}
-};
-
-/*
- * Initialize power interface
- */
-static int __init pm_init(void)
-{
-	register_sysctl_table(pm_dir_table, 1);
-	return 0;
-}
-
-fs_initcall(pm_init);
-
-#endif
-
-EXPORT_SYMBOL(pm_do_suspend);
diff -Nru a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-sa1100/ssp.c	Thu Mar  6 16:15:28 2003
@@ -0,0 +1,208 @@
+/*
+ *  linux/arch/arm/mach-sa1100/ssp.c
+ *
+ *  Copyright (C) 2003 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Generic SSP driver.  This provides the generic core for simple
+ *  IO-based SSP applications.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/hardware/ssp.h>
+
+static void ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int status = Ser4SSSR;
+
+	if (status & SSSR_ROR) {
+		printk(KERN_WARNING "SSP: receiver overrun\n");
+	}
+
+	Ser4SSSR = SSSR_ROR;
+}
+
+/**
+ * ssp_write_word - write a word to the SSP port
+ * @data: 16-bit, MSB justified data to write.
+ *
+ * Wait for a free entry in the SSP transmit FIFO, and write a data
+ * word to the SSP port.
+ *
+ * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ *   %-ETIMEDOUT	timeout occurred (for future)
+ *   0			success
+ */
+int ssp_write_word(u16 data)
+{
+	while (!(Ser4SSSR & SSSR_TNF))
+		cpu_relax();
+
+	Ser4SSDR = data;
+
+	return 0;
+}
+
+/**
+ * ssp_read_word - read a word from the SSP port
+ *
+ * Wait for a data word in the SSP receive FIFO, and return the
+ * received data.  Data is LSB justified.
+ *
+ * Note: Currently, if data is not expected to be received, this
+ * function will wait for ever.
+ *
+ * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ *   %-ETIMEDOUT	timeout occurred (for future)
+ *   16-bit data	success
+ */
+int ssp_read_word(void)
+{
+	while (!(Ser4SSSR & SSSR_RNE))
+		cpu_relax();
+
+	return Ser4SSDR;
+}
+
+/**
+ * ssp_flush - flush the transmit and receive FIFOs
+ *
+ * Wait for the SSP to idle, and ensure that the receive FIFO
+ * is empty.
+ *
+ * The caller is expected to perform the necessary locking.
+ */
+void ssp_flush(void)
+{
+	do {
+		while (Ser4SSSR & SSSR_RNE) {
+			(void) Ser4SSDR;
+		}
+	} while (Ser4SSSR & SSSR_BSY);
+}
+
+/**
+ * ssp_enable - enable the SSP port
+ *
+ * Turn on the SSP port.
+ */
+void ssp_enable(void)
+{
+	Ser4SSCR0 |= SSCR0_SSE;
+}
+
+/**
+ * ssp_disable - shut down the SSP port
+ *
+ * Turn off the SSP port, optionally powering it down.
+ */
+void ssp_disable(void)
+{
+	Ser4SSCR0 &= ~SSCR0_SSE;
+}
+
+/**
+ * ssp_save_state - save the SSP configuration
+ * @ssp: pointer to structure to save SSP configuration
+ *
+ * Save the configured SSP state for suspend.
+ */
+void ssp_save_state(struct ssp_state *ssp)
+{
+	ssp->cr0 = Ser4SSCR0;
+	ssp->cr1 = Ser4SSCR1;
+
+	Ser4SSCR0 &= ~SSCR0_SSE;
+}
+
+/**
+ * ssp_restore_state - restore a previously saved SSP configuration
+ * @ssp: pointer to configuration saved by ssp_save_state
+ *
+ * Restore the SSP configuration saved previously by ssp_save_state.
+ */
+void ssp_restore_state(struct ssp_state *ssp)
+{
+	Ser4SSSR = SSSR_ROR;
+
+	Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
+	Ser4SSCR1 = ssp->cr1;
+	Ser4SSCR0 = ssp->cr0;
+}
+
+/**
+ * ssp_init - setup the SSP port
+ *
+ * initialise and claim resources for the SSP port.
+ *
+ * Returns:
+ *   %-ENODEV	if the SSP port is unavailable
+ *   %-EBUSY	if the resources are already in use
+ *   %0		on success
+ */
+int ssp_init(void)
+{
+	int ret;
+
+	if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
+		return -ENODEV;
+
+	if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
+		return -EBUSY;
+	}
+
+	Ser4SSSR = SSSR_ROR;
+
+	ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
+	if (ret)
+		goto out_region;
+
+	return 0;
+
+ out_region:
+	release_mem_region(__PREG(Ser4SSCR0), 0x18);
+	return ret;
+}
+
+/**
+ * ssp_exit - undo the effects of ssp_init
+ *
+ * release and free resources for the SSP port.
+ */
+void ssp_exit(void)
+{
+	Ser4SSCR0 &= ~SSCR0_SSE;
+
+	free_irq(IRQ_Ser4SSP, NULL);
+	release_mem_region(__PREG(Ser4SSCR0), 0x18);
+}
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ssp_write_word);
+EXPORT_SYMBOL(ssp_read_word);
+EXPORT_SYMBOL(ssp_flush);
+EXPORT_SYMBOL(ssp_enable);
+EXPORT_SYMBOL(ssp_disable);
+EXPORT_SYMBOL(ssp_save_state);
+EXPORT_SYMBOL(ssp_restore_state);
+EXPORT_SYMBOL(ssp_init);
+EXPORT_SYMBOL(ssp_exit);
diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
--- a/arch/arm/mach-sa1100/system3.c	Sun Nov 17 07:31:13 2002
+++ b/arch/arm/mach-sa1100/system3.c	Thu Mar  6 08:48:29 2003
@@ -213,11 +213,17 @@
 static int sdram_notifier(struct notifier_block *nb, unsigned long event,
 		void *data)
 {
+	struct cpufreq_policy *policy = data;
 	switch (event) {
-		case CPUFREQ_MINMAX:
-			cpufreq_updateminmax(data, 147500, 206000);
+		case CPUFREQ_ADJUST:
+		case CPUFREQ_INCOMPATIBLE:
+			cpufreq_verify_within_limits(policy, 147500, 206000);
+			break;
+		case CPUFREQ_NOTIFY:
+			if ((policy->min < 147500) || 
+			    (policy->max > 206000))
+				panic("cpufreq failed to limit the speed\n");
 			break;
-
 	}
 	return 0;
 }
@@ -405,7 +411,7 @@
 		goto DONE;
 	}
 
-#if defined( CONFIG_CPU_FREQ )
+#ifdef CONFIG_CPU_FREQ
 	ret = cpufreq_register_notifier(&system3_clkchg_block);
 	if ( ret != 0 ) {
 		printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
diff -Nru a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
--- a/arch/arm/mm/fault-common.c	Sun Jan 12 09:11:08 2003
+++ b/arch/arm/mm/fault-common.c	Thu Mar  6 08:19:03 2003
@@ -342,20 +342,20 @@
 			 struct pt_regs *regs)
 {
 	struct task_struct *tsk;
-	unsigned int offset;
+	unsigned int index;
 	pgd_t *pgd, *pgd_k;
 	pmd_t *pmd, *pmd_k;
 
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
-	offset = __pgd_offset(addr);
+	index = pgd_index(addr);
 
 	/*
 	 * FIXME: CP15 C1 is write only on ARMv3 architectures.
 	 */
-	pgd = cpu_get_pgd() + offset;
-	pgd_k = init_mm.pgd + offset;
+	pgd = cpu_get_pgd() + index;
+	pgd_k = init_mm.pgd + index;
 
 	if (pgd_none(*pgd_k))
 		goto bad_area;
diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
--- a/arch/arm/tools/mach-types	Thu Jan 16 06:52:35 2003
+++ b/arch/arm/tools/mach-types	Thu Mar  6 06:57:42 2003
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Mon Jan 13 22:55:16 2003
+# Last update: Wed Mar 5 22:11:59 2003
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -228,7 +228,7 @@
 arnold			SA1100_ARNOLD		ARNOLD			217
 psiboard		SA1100_PSIBOARD		PSIBOARD		218
 jz8028			ARCH_JZ8028		JZ8028			219
-ipaq3			ARCH_IPAQ3		IPAQ3			220
+h5400			ARCH_IPAQ3		IPAQ3			220
 forte			SA1100_FORTE		FORTE			221
 acam			SA1100_ACAM		ACAM			222
 abox			SA1100_ABOX		ABOX			223
@@ -259,7 +259,7 @@
 stork_egg		ARCH_STORK_EGG		STORK_EGG		248
 wismo			SA1100_WISMO		WISMO			249
 ezlinx			ARCH_EZLINX		EZLINX			250
-at91rm9200		ARCH_AT91		AT91			251
+at91			ARCH_AT91		AT91			251
 orion			ARCH_ORION		ORION			252
 neptune			ARCH_NEPTUNE		NEPTUNE			253
 hackkit			SA1100_HACKKIT		HACKKIT			254
@@ -281,3 +281,27 @@
 siren			ARCH_SIREN		SIREN			270
 greenlake		ARCH_GREENLAKE		GREENLAKE		271
 argus			ARCH_ARGUS		ARGUS			272
+combadge		SA1100_COMBADGE		COMBADGE		273
+rokepxa			ARCH_ROKEPXA		ROKEPXA			274
+cintegrator		ARCH_CINTEGRATOR	CINTEGRATOR		275
+guidea07		ARCH_GUIDEA07		GUIDEA07		276
+tat257			ARCH_TAT257		TAT257			277
+igp2425			ARCH_IGP2425		IGP2425			278
+bluegrama		ARCH_BLUEGRAMMA		BLUEGRAMMA		279
+ipod			ARCH_IPOD		IPOD			280
+adsbitsyx		ARCH_ADSBITSYX		ADSBITSYX		281
+trizeps2		ARCH_TRIZEPS2		TRIZEPS2		282
+viper			ARCH_VIPER		VIPER			283
+adsbitsyplus		SA1100_ADSBITSYPLUS	ADSBITSYPLUS		284
+adsagc			SA1100_ADSAGC		ADSAGC			285
+stp7312			ARCH_STP7312		STP7312			286
+nx_phnx			ARCH_PXA255		PXA255			287
+wep_ep250		ARCH_WEP_EP250		WEP_EP250		288
+inhandelf3		ARCH_INHANDELF3		INHANDELF3		289
+adi_coyote		ARCH_ADI_COYOTE		ADI_COYOTE		290
+iyonix			ARCH_IYONIX		IYONIX			291
+damicam_sa1110		ARCH_DAMICAM_SA1110	DAMICAM_SA1110		292
+meg03			ARCH_MEG03		MEG03			293
+pxa_whitechapel		ARCH_PXA_WHITECHAPEL	PXA_WHITECHAPEL		294
+nwsc			ARCH_NWSC		NWSC			295
+nwlarm			ARCH_NWLARM		NWLARM			296
diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
--- a/arch/arm/vmlinux-armo.lds.in	Wed Jan 15 09:48:42 2003
+++ b/arch/arm/vmlinux-armo.lds.in	Fri Feb 14 14:36:57 2003
@@ -38,6 +38,9 @@
 			*(.initcall6.init)
 			*(.initcall7.init)
 		__initcall_end = .;
+		__con_initcall_start = .;
+			*(.con_initcall.init)
+		__con_initcall_end = .;
 		. = ALIGN(32768);
 		__init_end = .;
 	}
diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
--- a/arch/arm/vmlinux-armv.lds.in	Tue Feb 11 08:24:17 2003
+++ b/arch/arm/vmlinux-armv.lds.in	Wed Feb 19 07:21:37 2003
@@ -45,6 +45,9 @@
 			*(.initcall6.init)
 			*(.initcall7.init)
 		__initcall_end = .;
+		__con_initcall_start = .;
+			*(.con_initcall.init)
+		__con_initcall_end = .;
 		. = ALIGN(32);
 		__initramfs_start = .;
 			usr/built-in.o(.init.ramfs)
diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig
--- a/arch/cris/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/cris/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
--- a/arch/cris/kernel/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/cris/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -3,7 +3,7 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS	:= head.o
+extra-y	:= head.o
 
 obj-y   := process.o signal.o entry.o traps.o irq.o \
            ptrace.o setup.o time.o sys_cris.o shadows.o \
diff -Nru a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
--- a/arch/cris/kernel/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/cris/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -228,11 +228,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0; i < NR_IRQS; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %10u %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -243,6 +245,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S
--- a/arch/cris/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/cris/vmlinux.lds.S	Fri Feb 14 14:37:05 2003
@@ -69,7 +69,12 @@
 		*(.initcall6.init);
 		*(.initcall7.init);
 		__initcall_end = .;
-
+	}
+	.con_initcall.init : {
+		__con_initcall_start = .;
+		*(.con_initcall.init)
+		__con_initcall_end = .;
+	
 		/* We fill to the next page, so we can discard all init
 		   pages without needing to consider what payload might be
 		   appended to the kernel image.  */
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Sun Mar  2 18:14:31 2003
+++ b/arch/i386/Kconfig	Sat Mar  8 14:50:37 2003
@@ -18,15 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool "Support for paging of anonymous memory"
-	default y
-	help
-	  This option allows you to choose whether you want to have support
-	  for socalled swap devices or swap files in your kernel that are
-	  used to provide more virtual memory than the actual RAM present
-	  in your computer.  If unusre say Y.
-
 config SBUS
 	bool
 
@@ -488,7 +479,7 @@
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation Support"
-	depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)))
+	depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) || X86_PC
 
 config DISCONTIGMEM
 	bool
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	Fri Feb 21 19:34:09 2003
+++ b/arch/i386/Makefile	Tue Mar  4 15:09:44 2003
@@ -92,7 +92,8 @@
 
 boot := arch/i386/boot
 
-.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install
+.PHONY: zImage bzImage compressed zlilo bzlilo \
+	zdisk bzdisk fdimage fdimage144 fdimage288 install
 
 all: bzImage
 
@@ -110,8 +111,8 @@
 zdisk bzdisk: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
 
-install: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) install
+install fdimage fdimage144 fdimage288: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
 
 archclean:
 	$(Q)$(MAKE) $(clean)=arch/i386/boot
@@ -122,5 +123,8 @@
   echo  '		   (your) ~/bin/installkernel or'
   echo  '		   (distribution) /sbin/installkernel or'
   echo  '		   install to $$(INSTALL_PATH) and run lilo'
+  echo  '  bzdisk       - Create a boot floppy in /dev/fd0'
+  echo  '  fdimage      - Create a boot floppy image'
 endef
 
+CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf
diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
--- a/arch/i386/boot/Makefile	Mon Dec 30 23:11:35 2002
+++ b/arch/i386/boot/Makefile	Sat Mar 15 21:52:29 2003
@@ -25,9 +25,8 @@
 
 #RAMDISK := -DRAMDISK=512
 
-EXTRA_TARGETS	:= vmlinux.bin bootsect bootsect.o \
-		   setup setup.o zImage bzImage
-
+targets		:= vmlinux.bin bootsect bootsect.o setup setup.o \
+		   zImage bzImage
 subdir- 	:= compressed
 
 host-progs	:= tools/build
@@ -62,8 +61,36 @@
 	$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
 					IMAGE_OFFSET=$(IMAGE_OFFSET) $@
 
-zdisk: $(BOOTIMAGE)
-	dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
+# Set this if you want to pass append arguments to the zdisk/fdimage kernel
+FDARGS = 
+
+$(obj)/mtools.conf: $(src)/mtools.conf.in
+	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
+
+# This requires write access to /dev/fd0
+zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
+	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
+	syslinux /dev/fd0					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
+
+# These require being root or having syslinux 2.02 or higher installed
+fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
+	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
+	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
+	syslinux $(obj)/fdimage					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
+
+fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
+	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
+	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
+	syslinux $(obj)/fdimage					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
 
 zlilo: $(BOOTIMAGE)
 	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
diff -Nru a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
--- a/arch/i386/boot/bootsect.S	Fri Feb 21 06:03:16 2003
+++ b/arch/i386/boot/bootsect.S	Tue Mar  4 15:10:25 2003
@@ -4,29 +4,13 @@
  *	modified by Drew Eckhardt
  *	modified by Bruce Evans (bde)
  *	modified by Chris Noe (May 1999) (as86 -> gas)
- *
- * 360k/720k disk support: Andrzej Krzysztofowicz <ankry@green.mif.pg.gda.pl>
+ *	gutted by H. Peter Anvin (Jan 2003)
  *
  * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
  * addresses must be multiplied by 16 to obtain their respective linear
  * addresses. To avoid confusion, linear addresses are written using leading
  * hex while segment addresses are written as segment:offset.
  *
- * bde - should not jump blindly, there may be systems with only 512K low
- * memory.  Use int 0x12 to get the top of memory, etc.
- *
- * It then loads 'setup' directly after itself (0x90200), and the system
- * at 0x10000, using BIOS interrupts. 
- *
- * NOTE! currently system is at most (8*65536-4096) bytes long. This should 
- * be no problem, even in the future. I want to keep it simple. This 508 kB
- * kernel size should be enough, especially as this doesn't contain the
- * buffer cache as in minix (and especially now that the kernel is 
- * compressed :-)
- *
- * The loader has been made as simple as possible, and continuous
- * read errors will result in a unbreakable loop. Reboot by hand. It
- * loads pretty fast by getting whole tracks at a time whenever possible.
  */
 
 #include <asm/boot.h>
@@ -59,359 +43,51 @@
 .global _start
 _start:
 
-# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there.
+	# Normalize the start address
+	jmpl	$BOOTSEG, $start2
 
-	movw	$BOOTSEG, %ax
-	movw	%ax, %ds		# %ds = BOOTSEG
-	movw	$INITSEG, %ax
-	movw	%ax, %es		# %ax = %es = INITSEG
-	movw	$256, %cx
-	subw	%si, %si
-	subw	%di, %di
-	cld
-	rep
-	movsw
-	ljmp	$INITSEG, $go
-
-# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
-# wouldn't have to worry about this if we checked the top of memory.  Also
-# my BIOS can be configured to put the wini drive tables in high memory
-# instead of in the vector table.  The old stack might have clobbered the
-# drive table.
-
-go:	movw	$0x4000-12, %di		# 0x4000 is an arbitrary value >=
-					# length of bootsect + length of
-					# setup + room for stack;
-					# 12 is disk parm size.
-	movw	%ax, %ds		# %ax and %es already contain INITSEG
+start2:
+	movw	%cs, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
 	movw	%ax, %ss
-	movw	%di, %sp		# put stack at INITSEG:0x4000-12.
+	movw	$0x7c00, %sp
+	sti
+	cld
 
-# Many BIOS's default disk parameter tables will not recognize
-# multi-sector reads beyond the maximum sector number specified
-# in the default diskette parameter tables - this may mean 7
-# sectors in some cases.
-#
-# Since single sector reads are slow and out of the question,
-# we must take care of this by creating new parameter tables
-# (for the first disk) in RAM.  We will set the maximum sector
-# count to 36 - the most we will encounter on an ED 2.88.  
-#
-# High doesn't hurt.  Low does.
-#
-# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0,
-# and %gs is unused.
-
-	movw	%cx, %fs		# %fs = 0
-	movw	$0x78, %bx		# %fs:%bx is parameter table address
-	pushw	%ds
-	ldsw	%fs:(%bx), %si		# %ds:%si is source
-	movb	$6, %cl			# copy 12 bytes
-	pushw	%di			# %di = 0x4000-12.
-	rep				# don't worry about cld
-	movsw				# already done above
-	popw	%di
-	popw	%ds
-	movb	$36, 0x4(%di)		# patch sector count
-	movw	%di, %fs:(%bx)
-	movw	%es, %fs:2(%bx)
-
-# Get disk drive parameters, specifically number of sectors/track.
-
-# It seems that there is no BIOS call to get the number of sectors.
-# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
-# can be read, 15 if sector 15 can be read.  Otherwise guess 9.
-# Note that %cx = 0 from rep movsw above.
+	movw	$bugger_off_msg, %si
 
-	movw	$disksizes, %si		# table of sizes to try
-probe_loop:
+msg_loop:
 	lodsb
-	cbtw				# extend to word
-	movw	%ax, sectors
-	cmpw	$disksizes+4, %si
-	jae	got_sectors		# If all else fails, try 9
-
-	xchgw	%cx, %ax		# %cx = track and sector
-	xorw	%dx, %dx		# drive 0, head 0
-	movw	$0x0200, %bx		# address = 512, in INITSEG (%es = %cs)
-	movw	$0x0201, %ax		# service 2, 1 sector
-	int	$0x13
-	jc	probe_loop		# try next value
-
-got_sectors:
-	movb	$0x03, %ah		# read cursor pos
-	xorb	%bh, %bh
-	int	$0x10
-	movw	$9, %cx
-	movb	$0x07, %bl		# page 0, attribute 7 (normal)
-					# %bh is set above; int10 doesn't
-					# modify it
-	movw	$msg1, %bp
-	movw	$0x1301, %ax		# write string, move cursor
-	int	$0x10			# tell the user we're loading..
-
-# Load the setup-sectors directly after the moved bootblock (at 0x90200).
-# We should know the drive geometry to do it, as setup may exceed first
-# cylinder (for 9-sector 360K and 720K floppies).
-
-	movw	$0x0001, %ax		# set sread (sector-to-read) to 1 as
-	movw	$sread, %si		# the boot sector has already been read
-	movw	%ax, (%si)
-
-	call	kill_motor		# reset FDC
-	movw	$0x0200, %bx		# address = 512, in INITSEG
-next_step:
-	movb	setup_sects, %al
-	movw	sectors, %cx
-	subw	(%si), %cx		# (%si) = sread
-	cmpb	%cl, %al
-	jbe	no_cyl_crossing
-	movw	sectors, %ax
-	subw	(%si), %ax		# (%si) = sread
-no_cyl_crossing:
-	call	read_track
-	pushw	%ax			# save it
-	call	set_next		# set %bx properly; it uses %ax,%cx,%dx
-	popw	%ax			# restore
-	subb	%al, setup_sects	# rest - for next step
-	jnz	next_step
-
-	pushw	$SYSSEG
-	popw	%es			# %es = SYSSEG
-	call	read_it
-	call	kill_motor
-	call	print_nl
-
-# After that we check which root-device to use. If the device is
-# defined (!= 0), nothing is done and the given device is used.
-# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
-# depending on the number of sectors we pretend to know we have.
-
-# Segments are as follows: %cs = %ds = %ss = INITSEG,
-#	%es = SYSSEG, %fs = 0, %gs is unused.
-
-	movw	root_dev, %ax
-	orw	%ax, %ax
-	jne	root_defined
-
-	movw	sectors, %bx
-	movw	$0x0208, %ax		# /dev/ps0 - 1.2Mb
-	cmpw	$15, %bx
-	je	root_defined
-
-	movb	$0x1c, %al		# /dev/PS0 - 1.44Mb
-	cmpw	$18, %bx
-	je	root_defined
-
-	movb	$0x20, %al		# /dev/fd0H2880 - 2.88Mb
-	cmpw	$36, %bx
-	je	root_defined
-
-	movb	$0, %al			# /dev/fd0 - autodetect
-root_defined:
-	movw	%ax, root_dev
-
-# After that (everything loaded), we jump to the setup-routine
-# loaded directly after the bootblock:
-
-	ljmp	$SETUPSEG, $0
-
-# These variables are addressed via %si register as it gives shorter code.
-
-sread:	.word 0				# sectors read of current track
-head:	.word 0				# current head
-track:	.word 0				# current track
-
-# This routine loads the system at address SYSSEG, making sure
-# no 64kB boundaries are crossed. We try to load it as fast as
-# possible, loading whole tracks whenever we can.
-
-read_it:
-	movw	%es, %ax		# %es = SYSSEG when called
-	testw	$0x0fff, %ax
-die:	jne	die			# %es must be at 64kB boundary
-	xorw	%bx, %bx		# %bx is starting address within segment
-rp_read:
-#ifdef __BIG_KERNEL__			# look in setup.S for bootsect_kludge
-	bootsect_kludge = 0x220		# 0x200 + 0x20 which is the size of the
-	lcall	*bootsect_kludge	# bootsector + bootsect_kludge offset
-#else
-	movw	%es, %ax
-	subw	$SYSSEG, %ax
-	movw	%bx, %cx
-	shr	$4, %cx
-	add	%cx, %ax		# check offset
-#endif
-	cmpw	syssize, %ax		# have we loaded everything yet?
-	jbe	ok1_read
-
-	ret
-
-ok1_read:
-	movw	sectors, %ax
-	subw	(%si), %ax		# (%si) = sread
-	movw	%ax, %cx
-	shlw	$9, %cx
-	addw	%bx, %cx
-	jnc	ok2_read
-
-	je	ok2_read
-
-	xorw	%ax, %ax
-	subw	%bx, %ax
-	shrw	$9, %ax
-ok2_read:
-	call	read_track
-	call	set_next
-	jmp	rp_read
-
-read_track:
-	pusha
-	pusha	
-	movw	$0xe2e, %ax 		# loading... message 2e = .
+	andb	%al, %al
+	jz	die
+	movb	$0xe, %ah
 	movw	$7, %bx
- 	int	$0x10
-	popa		
-
-# Accessing head, track, sread via %si gives shorter code.
+	int	$0x10
+	jmp	msg_loop
 
-	movw	4(%si), %dx		# 4(%si) = track
-	movw	(%si), %cx		# (%si)  = sread
-	incw	%cx
-	movb	%dl, %ch
-	movw	2(%si), %dx		# 2(%si) = head
-	movb	%dl, %dh
-	andw	$0x0100, %dx
-	movb	$2, %ah
-	pushw	%dx			# save for error dump
-	pushw	%cx
-	pushw	%bx
-	pushw	%ax
-	int	$0x13
-	jc	bad_rt
-
-	addw	$8, %sp
-	popa
-	ret
-
-set_next:
-	movw	%ax, %cx
-	addw	(%si), %ax		# (%si) = sread
-	cmp	sectors, %ax
-	jne	ok3_set
-	movw	$0x0001, %ax
-	xorw	%ax, 2(%si)		# change head
-	jne	ok4_set
-	incw	4(%si)			# next track
-ok4_set:
+die:
+	# Allow the user to press a key, then reboot
 	xorw	%ax, %ax
-ok3_set:
-	movw	%ax, (%si)		# set sread
-	shlw	$9, %cx
-	addw	%cx, %bx
-	jnc	set_next_fin
-	movw	%es, %ax
-	addb	$0x10, %ah
-	movw	%ax, %es
-	xorw	%bx, %bx
-set_next_fin:
-	ret
-
-bad_rt:
-	pushw	%ax			# save error code
-	call	print_all		# %ah = error, %al = read
-	xorb	%ah, %ah
-	xorb	%dl, %dl
-	int	$0x13
-	addw	$10, %sp
-	popa
-	jmp read_track
-
-# print_all is for debugging purposes.  
-#
-# it will print out all of the registers.  The assumption is that this is
-# called from a routine, with a stack frame like
-#
-#	%dx 
-#	%cx
-#	%bx
-#	%ax
-#	(error)
-#	ret <- %sp
- 
-print_all:
-	movw	$5, %cx			# error code + 4 registers
-	movw	%sp, %bp
-print_loop:
-	pushw	%cx			# save count remaining
-	call	print_nl		# <-- for readability
-	cmpb	$5, %cl
-	jae	no_reg			# see if register name is needed
-	
-	movw	$0xe05 + 'A' - 1, %ax
-	subb	%cl, %al
-	int	$0x10
-	movb	$'X', %al
-	int	$0x10
-	movb	$':', %al
-	int	$0x10
-no_reg:
-	addw	$2, %bp			# next register
-	call	print_hex		# print it
-	popw	%cx
-	loop	print_loop
-	ret
+	int	$0x16
+	int	$0x19
 
-print_nl:
-	movw	$0xe0d, %ax		# CR
-	int	$0x10
-	movb	$0xa, %al		# LF
-	int 	$0x10
-	ret
-
-# print_hex is for debugging purposes, and prints the word
-# pointed to by %ss:%bp in hexadecimal.
-
-print_hex:
-	movw	$4, %cx			# 4 hex digits
-	movw	(%bp), %dx		# load word into %dx
-print_digit:
-	rolw	$4, %dx			# rotate to use low 4 bits
-	movw	$0xe0f, %ax		# %ah = request
-	andb	%dl, %al		# %al = mask for nybble
-	addb	$0x90, %al		# convert %al to ascii hex
-	daa				# in only four instructions!
-	adc	$0x40, %al
-	daa
-	int	$0x10
-	loop	print_digit
-	ret
+	# int 0x19 should never return.  In case it does anyway,
+	# invoke the BIOS reset code...
+	ljmp	$0xf000,$0xfff0
 
-# This procedure turns off the floppy drive motor, so
-# that we enter the kernel in a known state, and
-# don't have to worry about it later.
-# NOTE: Doesn't save %ax or %dx; do it yourself if you need to.
-
-kill_motor:
-#if 1
-	xorw	%ax, %ax		# reset FDC
-	xorb	%dl, %dl
-	int	$0x13
-#else
-	movw	$0x3f2, %dx
-	xorb	%al, %al
-	outb	%al, %dx
-#endif
-	ret
 
-sectors:	.word 0
-disksizes:	.byte 36, 21, 18, 15, 9
-msg1:		.byte 13, 10
-		.ascii "Loading"
+bugger_off_msg:
+	.ascii	"Direct booting from floppy is no longer supported.\r\n"
+	.ascii	"Please use a boot loader program instead.\r\n"
+	.ascii	"\n"
+	.ascii	"Remove disk and press any key to reboot . . .\r\n"
+	.byte	0
+	
 
-# XXX: This is a fairly snug fit.
+	# Kernel attributes; used by setup
 
-.org 497
+	.org 497
 setup_sects:	.byte SETUPSECTS
 root_flags:	.word ROOT_RDONLY
 syssize:	.word SYSSIZE
diff -Nru a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
--- a/arch/i386/boot/compressed/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/i386/boot/compressed/Makefile	Sun Mar  9 13:47:41 2003
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-EXTRA_TARGETS	:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
 EXTRA_AFLAGS	:= -traditional
 
 LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
diff -Nru a/arch/i386/boot/mtools.conf.in b/arch/i386/boot/mtools.conf.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/boot/mtools.conf.in	Tue Mar  4 15:09:44 2003
@@ -0,0 +1,17 @@
+#
+# mtools configuration file for "make (b)zdisk"
+#
+
+# Actual floppy drive
+drive a:
+  file="/dev/fd0"
+
+# 1.44 MB floppy disk image
+drive v:
+  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
+
+# 2.88 MB floppy disk image (mostly for virtual uses)
+drive w:
+  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
+
+
diff -Nru a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
--- a/arch/i386/boot/tools/build.c	Mon Feb  4 23:41:17 2002
+++ b/arch/i386/boot/tools/build.c	Tue Mar  4 15:09:44 2003
@@ -150,13 +150,10 @@
 	sz = sb.st_size;
 	fprintf (stderr, "System is %d kB\n", sz/1024);
 	sys_size = (sz + 15) / 16;
-	/* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
-	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+	/* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */
+	if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE))
 		die("System is too big. Try using %smodules.",
 			is_big_kernel ? "" : "bzImage or ");
-	if (sys_size > 0xefff)
-		fprintf(stderr,"warning: kernel is too big for standalone boot "
-		    "from floppy\n");
 	while (sz > 0) {
 		int l, n;
 
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	Mon Feb 24 23:13:14 2003
+++ b/arch/i386/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS := head.o init_task.o
+extra-y := head.o init_task.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
diff -Nru a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
--- a/arch/i386/kernel/cpu/centaur.c	Thu Feb 13 14:21:33 2003
+++ b/arch/i386/kernel/cpu/centaur.c	Thu Mar 13 15:47:14 2003
@@ -248,6 +248,37 @@
 }
 #endif
 
+static void __init init_c3(struct cpuinfo_x86 *c)
+{
+	u32  lo, hi;
+
+	/* Test for Centaur Extended Feature Flags presence */
+	if (cpuid_eax(0xC0000000) >= 0xC0000001) {
+		/* store Centaur Extended Feature Flags as
+		 * word 5 of the CPU capability bit array
+		 */
+		c->x86_capability[5] = cpuid_edx(0xC0000001);
+	}
+
+	switch (c->x86_model) {
+		case 6 ... 8:		/* Cyrix III family */
+			rdmsr (MSR_VIA_FCR, lo, hi);
+			lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
+			wrmsr (MSR_VIA_FCR, lo, hi);
+
+			set_bit(X86_FEATURE_CX8, c->x86_capability);
+			set_bit(X86_FEATURE_3DNOW, c->x86_capability);
+
+			/* fall through */
+
+		case 9:	/* Nehemiah */
+		default:
+			get_model_name(c);
+			display_cacheinfo(c);
+			break;
+	}
+}
+
 static void __init init_centaur(struct cpuinfo_x86 *c)
 {
 	enum {
@@ -386,21 +417,7 @@
 			break;
 
 		case 6:
-			switch (c->x86_model) {
-				case 6 ... 8:		/* Cyrix III family */
-					rdmsr (MSR_VIA_FCR, lo, hi);
-					lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
-					wrmsr (MSR_VIA_FCR, lo, hi);
-
-					set_bit(X86_FEATURE_CX8, c->x86_capability);
-					set_bit(X86_FEATURE_3DNOW, c->x86_capability);
-
-				case 9:	/* Nehemiah */
-				default:
-					get_model_name(c);
-					display_cacheinfo(c);
-					break;
-			}
+			init_c3(c);
 			break;
 	}
 }
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c	Wed Feb 19 17:48:55 2003
+++ b/arch/i386/kernel/cpu/common.c	Thu Mar 13 15:47:14 2003
@@ -211,9 +211,10 @@
 	
 		/* Intel-defined flags: level 0x00000001 */
 		if ( c->cpuid_level >= 0x00000001 ) {
-			u32 capability;
-			cpuid(0x00000001, &tfms, &junk, &junk, &capability);
+			u32 capability, excap;
+			cpuid(0x00000001, &tfms, &junk, &excap, &capability);
 			c->x86_capability[0] = capability;
+			c->x86_capability[4] = excap;
 			c->x86 = (tfms >> 8) & 15;
 			c->x86_model = (tfms >> 4) & 15;
 			c->x86_mask = tfms & 15;
@@ -480,7 +481,7 @@
 	 */
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
-	if(current->mm)
+	if (current->mm)
 		BUG();
 	enter_lazy_tlb(&init_mm, current, cpu);
 
@@ -508,7 +509,7 @@
 	/*
 	 * Force FPU initialization:
 	 */
-	clear_thread_flag(TIF_USEDFPU);
+	current_thread_info()->status = 0;
 	current->used_math = 0;
 	stts();
 }
diff -Nru a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c	Fri Feb 28 07:59:47 2003
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c	Sat Mar  8 01:37:35 2003
@@ -619,6 +619,7 @@
 	.init		= acpi_cpufreq_cpu_init,
 	.exit		= acpi_cpufreq_cpu_exit,
 	.name		= "acpi-cpufreq",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
--- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Fri Feb 28 07:52:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Sat Mar  8 01:37:35 2003
@@ -250,6 +250,7 @@
 	.target 	= elanfreq_target,
 	.init		= elanfreq_cpu_init,
 	.name		= "elanfreq",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	Fri Feb 28 07:52:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	Tue Mar 11 15:37:30 2003
@@ -444,13 +444,14 @@
 
 /* 
  * cpufreq_gx_init:
- *   MediaGX/Geode GX initilize cpufreq driver
+ *   MediaGX/Geode GX initialize cpufreq driver
  */
 static struct cpufreq_driver gx_suspmod_driver = {
 	.verify		= cpufreq_gx_verify,
 	.target		= cpufreq_gx_target,
 	.init		= cpufreq_gx_cpu_init,
 	.name		= "gx-suspmod",
+	.owner		= THIS_MODULE,
 };
 
 static int __init cpufreq_gx_init(void)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c	Fri Feb 28 08:02:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c	Tue Mar 11 17:20:59 2003
@@ -40,18 +40,15 @@
 #define dprintk(msg...) do { } while(0);
 #endif
 
-static int numscales=16, numvscales;
+static unsigned int numscales=16, numvscales;
 static int minvid, maxvid;
 static int can_scale_voltage;
-static int can_scale_fsb;
 static int vrmrev;
 
 
 /* Module parameters */
-static int prefer_slow_fsb;
 static int dont_scale_voltage;
-static int dont_scale_fsb;
-static int current_fsb;
+static unsigned int fsb;
 
 #define __hlt()     __asm__ __volatile__("hlt": : :"memory")
 
@@ -231,14 +228,6 @@
 	145, /* 1111 -> 14.5x */
 };
 
-/* fsb values as defined in CPU */
-static unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
-/* fsb values to favour low fsb speed (lower power) */
-static unsigned int power_fsb_table[] = { 66, 100, 133, -1 };
-/* fsb values to favour high fsb speed (for e.g. if lowering CPU 
-   freq because of heat, but want to maintain highest performance possible) */
-static unsigned int perf_fsb_table[] = { 133, 100, 66, -1 };
-
 /* Voltage scales. Div by 1000 to get actual voltage. */
 static int __initdata vrm85scales[32] = {
 	1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700,
@@ -258,21 +247,22 @@
 static int clock_ratio[32];
 static int eblcr_table[32];
 static int voltage_table[32];
-static int highest_speed, lowest_speed; /* kHz */
+static unsigned int highest_speed, lowest_speed; /* kHz */
 static int longhaul; /* version. */
 static struct cpufreq_frequency_table *longhaul_table;
 
 
 static int longhaul_get_cpu_fsb (void)
 {
+	unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
 	unsigned long invalue=0,lo, hi;
 
-	if (current_fsb == 0) {
+	if (fsb == 0) {
 		rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
 		invalue = (lo & (1<<18|1<<19)) >>18;
 		return eblcr_fsb_table[invalue];
 	} else {
-		return current_fsb;
+		return fsb;
 	}
 }
 
@@ -294,12 +284,11 @@
 /**
  * longhaul_set_cpu_frequency()
  * @clock_ratio_index : index of clock_ratio[] for new frequency
- * @newfsb: the new FSB
  *
  * Sets a new clock ratio, and -if applicable- a new Front Side Bus
  */
 
-static void longhaul_setstate (unsigned int clock_ratio_index, unsigned int newfsb)
+static void longhaul_setstate (unsigned int clock_ratio_index)
 {
 	unsigned long lo, hi;
 	unsigned int bits;
@@ -307,24 +296,21 @@
 	int vidindex, i;
 	struct cpufreq_freqs freqs;
 	
-	if (!newfsb || (clock_ratio[clock_ratio_index] == -1))
-		return;
-
-	if ((!can_scale_fsb) && (newfsb != current_fsb))
+	if (clock_ratio[clock_ratio_index] == -1)
 		return;
 
-	if (((clock_ratio[clock_ratio_index] * newfsb * 100) > highest_speed) ||
-	    ((clock_ratio[clock_ratio_index] * newfsb * 100) < lowest_speed))
+	if (((clock_ratio[clock_ratio_index] * fsb * 100) > highest_speed) ||
+	    ((clock_ratio[clock_ratio_index] * fsb * 100) < lowest_speed))
 		return;
 
 	freqs.old = longhaul_get_cpu_mult() * longhaul_get_cpu_fsb() * 100;
-	freqs.new = clock_ratio[clock_ratio_index] * newfsb * 100;
+	freqs.new = clock_ratio[clock_ratio_index] * fsb * 100;
 	freqs.cpu = 0; /* longhaul.c is UP only driver */
 	
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	dprintk (KERN_INFO "longhaul: New FSB:%d Mult(x10):%d\n",
-				newfsb, clock_ratio[clock_ratio_index]);
+	dprintk (KERN_INFO "longhaul: FSB:%d Mult(x10):%d\n",
+				fsb * 100, clock_ratio[clock_ratio_index]);
 
 	bits = clock_ratio_index;
 	/* "bits" contains the bitpattern of the new multiplier.
@@ -358,14 +344,9 @@
 		lo |= revkey;
 
 		if (can_scale_voltage) {
-			if (can_scale_fsb==1) {
-				dprintk (KERN_INFO "longhaul: Voltage scaling + FSB scaling not done yet.\n");
-				goto bad_voltage;
-			} else {
-				/* PB: TODO fix this up */
-				vidindex = (((highest_speed-lowest_speed) / (newfsb/2)) -
-						((highest_speed-((clock_ratio[clock_ratio_index] * newfsb * 100)/1000)) / (newfsb/2)));
-			}
+			/* PB: TODO fix this up */
+			vidindex = (((highest_speed-lowest_speed) / (fsb/2)) -
+					((highest_speed-((clock_ratio[clock_ratio_index] * fsb * 100)/1000)) / (fsb/2)));
 			for (i=0;i<32;i++) {
 				dprintk (KERN_INFO "VID hunting. Looking for %d, found %d\n",
 						minvid+(vidindex*25), voltage_table[i]);
@@ -403,17 +384,6 @@
 		lo |= (1<<8);	/* EnableSoftBusRatio */
 		lo |= revkey;
 
-		/* Set FSB */
-		if (can_scale_fsb==1) {
-			lo &= ~(1<<28|1<<29);
-			switch (newfsb) {
-				case 66:	lo |= (1<<28|1<<29); /* 11 */
-							break;
-				case 100:	lo |= 1<<28;	/* 01 */
-							break;
-				case 133:	break;	/* 00*/
-			}
-		}
 		wrmsr (MSR_VIA_LONGHAUL, lo, hi);
 		__hlt();
 
@@ -431,14 +401,11 @@
 static int __init longhaul_get_ranges (void)
 {
 	unsigned long lo, hi, invalue;
-	unsigned int minmult=0, maxmult=0, minfsb=0, maxfsb=0;
+	unsigned int minmult=0, maxmult=0;
 	unsigned int multipliers[32]= {
 		50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
 		-1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
-	unsigned int fsb_table[4] = { 133, 100, -1, 66 };
-	unsigned int fsbcount = 1;
-	unsigned int i, j, k = 0;
-	static unsigned int *fsb_search_table;
+	unsigned int j, k = 0;
 
 	switch (longhaul) {
 	case 1:
@@ -446,7 +413,6 @@
 		   Assume min=3.0x & max = whatever we booted at. */
 		minmult = 30;
 		maxmult = longhaul_get_cpu_mult();
-		minfsb = maxfsb = current_fsb;
 		break;
 
 	case 2 ... 3:
@@ -465,55 +431,30 @@
 #else
 		minmult = 30; /* as per spec */
 #endif
-
-		if (can_scale_fsb==1) {
-			invalue = (hi & (1<<9|1<<10)) >> 9;
-			maxfsb = fsb_table[invalue];
-
-			invalue = (hi & (1<<25|1<<26)) >> 25;
-			minfsb = fsb_table[invalue];
-
-			dprintk (KERN_INFO "longhaul: Min FSB=%d Max FSB=%d\n",
-				minfsb, maxfsb);
-			fsbcount = 0;
-			for (i=0;i<4;i++) {
-				if((fsb_table[i] >= minfsb) && (fsb_table[i] <= maxfsb))
-					fsbcount++;
-			}
-		} else {
-			minfsb = maxfsb = current_fsb;
-		}
 		break;
 	}
 
-	highest_speed = maxmult * maxfsb * 100;
-	lowest_speed = minmult * minfsb * 100;
+	highest_speed = maxmult * fsb * 100;
+	lowest_speed = minmult * fsb * 100;
 	dprintk (KERN_INFO "longhaul: MinMult(x10)=%d MaxMult(x10)=%d\n",
 		 minmult, maxmult);
 	dprintk (KERN_INFO "longhaul: Lowestspeed=%d Highestspeed=%d\n",
 		 lowest_speed, highest_speed);
 
-	longhaul_table = kmalloc((numscales * fsbcount + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
+	longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
 	if(!longhaul_table)
 		return -ENOMEM;
 
-	if (prefer_slow_fsb) 
-		fsb_search_table = perf_fsb_table;   // yep, this is right: the last entry is preferred by cpufreq_frequency_table_* ...
-	else
-		fsb_search_table = power_fsb_table;
-
-	for (i=0; (i<4); i++) {
-		if ((fsb_search_table[i] > maxfsb) || (fsb_search_table[i] < minfsb) || (fsb_search_table[i] == -1))
+	for (j=0; (j<numscales); j++) {
+		if (clock_ratio[j] == -1)
 			continue;
-		for (j=0; (j<numscales); j++) {
-			if ((clock_ratio[j] > maxmult) || (clock_ratio[j] < minmult) || (clock_ratio[j] == -1))
-				continue;
-			longhaul_table[k].frequency= clock_ratio[j] * fsb_search_table[i] * 100;
-			longhaul_table[k].index	= (j << 8) | (i);
-			k++;
-		}
+		if (((unsigned int)clock_ratio[j] > maxmult) || ((unsigned int)clock_ratio[j] < minmult))
+			continue;
+		longhaul_table[k].frequency= clock_ratio[j] * fsb * 100;
+		longhaul_table[k].index	= (j << 8);
+		k++;
 	}
-	
+
 	longhaul_table[k].frequency = CPUFREQ_TABLE_END;
 	if (!k)
 		return -EINVAL;
@@ -568,16 +509,14 @@
 			    unsigned int relation)
 {
 	unsigned int    table_index = 0;
- 	unsigned int    new_fsb = 0;
  	unsigned int    new_clock_ratio = 0;
 
 	if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
 		return -EINVAL;
 
 	new_clock_ratio = longhaul_table[table_index].index & 0xFF;
-	new_fsb = power_fsb_table[(longhaul_table[table_index].index & 0xFF00) >> 8];
  
-	longhaul_setstate(new_clock_ratio, new_fsb);
+	longhaul_setstate(new_clock_ratio);
 
 	return 0;
 }
@@ -628,9 +567,6 @@
 		rdmsr (MSR_VIA_LONGHAUL, lo, hi);
 		if ((lo & (1<<0)) && (dont_scale_voltage==0))
 			longhaul_setup_voltagescaling (lo, hi);
-
-		if ((lo & (1<<1)) && (dont_scale_fsb==0) && (current_fsb==0))
-			can_scale_fsb = 1;
 	}
 
 	if (longhaul_get_ranges())
@@ -639,7 +575,7 @@
  	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
  	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
-        policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100);
+	policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100);
 
 	return cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
 }
@@ -649,6 +585,7 @@
 	.target 	= longhaul_target,
 	.init		= longhaul_cpu_init,
 	.name		= "longhaul",
+	.owner		= THIS_MODULE,
 };
 
 static int __init longhaul_init (void)
@@ -676,10 +613,7 @@
 	kfree(longhaul_table);
 }
 
-MODULE_PARM (dont_scale_fsb, "i");
 MODULE_PARM (dont_scale_voltage, "i");
-MODULE_PARM (current_fsb, "i");
-MODULE_PARM (prefer_slow_fsb, "i");
 
 MODULE_AUTHOR ("Dave Jones <davej@suse.de>");
 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c
--- a/arch/i386/kernel/cpu/cpufreq/longrun.c	Fri Feb 28 08:08:36 2003
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c	Sat Mar  8 01:37:35 2003
@@ -253,6 +253,7 @@
 	.setpolicy 	= longrun_set_policy,
 	.init		= longrun_cpu_init,
 	.name		= "longrun",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Fri Feb 28 07:52:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Sat Mar  8 01:39:17 2003
@@ -214,6 +214,7 @@
 		else
 			p4clockmod_table[i].frequency = (stock_freq * i)/8;
 	}
+	cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
 	
 	/* cpuinfo and default policy values */
 	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
@@ -226,9 +227,14 @@
 
 static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
 {
+	cpufreq_frequency_table_put_attr(policy->cpu);    
 	return cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
 }
 
+static struct freq_attr* p4clockmod_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
 
 static struct cpufreq_driver p4clockmod_driver = {
 	.verify 	= cpufreq_p4_verify,
@@ -236,6 +242,8 @@
 	.init		= cpufreq_p4_cpu_init,
 	.exit		= cpufreq_p4_cpu_exit,
 	.name		= "p4-clockmod",
+	.owner		= THIS_MODULE,
+	.attr		= p4clockmod_attr,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Fri Feb 28 08:03:44 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Sat Mar  8 01:37:35 2003
@@ -190,6 +190,7 @@
 	.init		= powernow_k6_cpu_init,
 	.exit		= powernow_k6_cpu_exit,
 	.name		= "powernow-k6",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Fri Feb 28 08:03:52 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Tue Mar 11 16:54:54 2003
@@ -151,7 +151,7 @@
 	}
 
 	if (!(edx & (1 << 1 | 1 << 2))) {
-		printk (" nothing.\n");
+		printk ("nothing.\n");
 		return 0;
 	}
 
@@ -162,9 +162,8 @@
 
 static int get_ranges (unsigned char *pst)
 {
-	int j;
+	unsigned int j, speed;
 	u8 fid, vid;
-	unsigned int speed;
 
 	powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);
 	if (!powernow_table)
@@ -239,12 +238,17 @@
 		__asm__("\tcli\n");
 	rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
 	fidvidctl.bits.SGTC = latency;	/* Stop grant timeout counter */
+
 	fidvidctl.bits.FID = fid;
-	fidvidctl.bits.VID = vid;
-	/* Note, we could set these lazily. Ie, only do voltage transition
-	   if its changed since last time (Some speeds have the same voltage) */
 	fidvidctl.bits.FIDC = 1;
-	fidvidctl.bits.VIDC = 1;
+
+	/* Set the voltage lazily. Ie, only do voltage transition
+	   if its changed since last time (Some speeds have the same voltage) */
+	if (fidvidctl.bits.VID != vid) {
+		fidvidctl.bits.VID = vid;
+		fidvidctl.bits.VIDC = 1;
+	}
+
 	wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
 	if (have_a0 == 1)
 		__asm__("\tsti\n");
@@ -253,7 +257,7 @@
 }
 
 
-int powernow_decode_bios (int maxfid, int startvid)
+static int powernow_decode_bios (int maxfid, int startvid)
 {
 	struct psb_s *psb;
 	struct pst_s *pst;
@@ -377,6 +381,7 @@
 	.target 	= powernow_target,
 	.init		= powernow_cpu_init,
 	.name		= "powernow-k7",
+	.owner		= THIS_MODULE,
 };
 
 static int __init powernow_init (void)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c
--- a/arch/i386/kernel/cpu/cpufreq/speedstep.c	Fri Feb 28 08:04:04 2003
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c	Sat Mar  8 01:46:02 2003
@@ -29,7 +29,6 @@
 
 #include <asm/msr.h>
 
-
 /* speedstep_chipset:
  *   It is necessary to know which chipset is used. As accesses to 
  * this device occur at various places in this module, we need a 
@@ -40,7 +39,7 @@
 
 #define SPEEDSTEP_CHIPSET_ICH2M         0x00000002
 #define SPEEDSTEP_CHIPSET_ICH3M         0x00000003
-
+#define SPEEDSTEP_CHIPSET_ICH4M         0x00000004
 
 /* speedstep_processor
  */
@@ -106,6 +105,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 		/* get PMBASE */
 		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
 		if (!(pmbase & 0x01))
@@ -166,6 +166,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 		/* get PMBASE */
 		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
 		if (!(pmbase & 0x01))
@@ -245,6 +246,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 	{
 		u16             value = 0;
 
@@ -277,6 +279,14 @@
 static unsigned int speedstep_detect_chipset (void)
 {
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82801DB_12, 
+			      PCI_ANY_ID,
+			      PCI_ANY_ID,
+			      NULL);
+	if (speedstep_chipset_dev)
+		return SPEEDSTEP_CHIPSET_ICH4M;
+
+	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82801CA_12, 
 			      PCI_ANY_ID,
 			      PCI_ANY_ID,
@@ -658,6 +668,7 @@
 	.verify 	= speedstep_verify,
 	.target 	= speedstep_target,
 	.init		= speedstep_cpu_init,
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
--- a/arch/i386/kernel/cpu/proc.c	Tue Jan 14 02:00:33 2003
+++ b/arch/i386/kernel/cpu/proc.c	Thu Mar 13 15:47:14 2003
@@ -37,7 +37,20 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Other (Linux-defined) */
-		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL,
+		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+		NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+		/* Intel-defined (#2) */
+		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, NULL,
+		"tm2", NULL, "cnxt_id", NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+		/* VIA/Cyrix/Centaur-defined */
+		NULL, NULL, "xstore", NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	Mon Feb 24 12:31:17 2003
+++ b/arch/i386/kernel/dmi_scan.c	Thu Mar 13 12:16:41 2003
@@ -3,6 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/apm_bios.h>
 #include <linux/slab.h>
 #include <asm/io.h>
@@ -893,3 +894,5 @@
 	if(err == 0)
 		dmi_check_blacklist();
 }
+
+EXPORT_SYMBOL(is_unsafe_smbus);
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Tue Feb 25 11:06:46 2003
+++ b/arch/i386/kernel/entry.S	Mon Mar 10 14:41:23 2003
@@ -72,6 +72,12 @@
 NT_MASK		= 0x00004000
 VM_MASK		= 0x00020000
 
+/*
+ * ESP0 is at offset 4. 0x100 is the size of the TSS, and
+ * also thus the top-of-stack pointer offset of SYSENTER_ESP
+ */
+TSS_ESP0_OFFSET = (4 - 0x100)
+
 #ifdef CONFIG_PREEMPT
 #define preempt_stop		cli
 #else
@@ -229,6 +235,8 @@
 
 	# sysenter call handler stub
 ENTRY(sysenter_entry)
+	movl TSS_ESP0_OFFSET(%esp),%esp
+sysenter_past_esp:
 	sti
 	pushl $(__USER_DS)
 	pushl %ebp
@@ -458,12 +466,36 @@
 	addl $4, %esp
 	jmp ret_from_exception
 
+/*
+ * Debug traps and NMI can happen at the one SYSENTER instruction
+ * that sets up the real kernel stack. Check here, since we can't
+ * allow the wrong stack to be used.
+ *
+ * "TSS_ESP0_OFFSET+12" is because the NMI/debug handler will have
+ * already pushed 3 words if it hits on the sysenter instruction:
+ * eflags, cs and eip.
+ *
+ * We just load the right stack, and push the three (known) values
+ * by hand onto the new stack - while updating the return eip past
+ * the instruction that would have done it for sysenter.
+ */
+#define CHECK_SYSENTER_EIP			\
+	cmpl $sysenter_entry,(%esp);		\
+	jne 1f;					\
+	movl TSS_ESP0_OFFSET+12(%esp),%esp;	\
+	pushfl;					\
+	pushl $__KERNEL_CS;			\
+	pushl $sysenter_past_esp;		\
+1:
+
 ENTRY(debug)
+	CHECK_SYSENTER_EIP
 	pushl $0
 	pushl $do_debug
 	jmp error_code
 
 ENTRY(nmi)
+	CHECK_SYSENTER_EIP
 	pushl %eax
 	SAVE_ALL
 	movl %esp, %edx
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	Fri Feb 28 00:05:34 2003
+++ b/arch/i386/kernel/i386_ksyms.c	Wed Mar  5 00:44:17 2003
@@ -68,6 +68,7 @@
 EXPORT_SYMBOL(MCA_bus);
 #ifdef CONFIG_DISCONTIGMEM
 EXPORT_SYMBOL(node_data);
+EXPORT_SYMBOL(physnode_map);
 #endif
 #ifdef CONFIG_X86_NUMAQ
 EXPORT_SYMBOL(xquad_portio);
diff -Nru a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
--- a/arch/i386/kernel/i387.c	Mon Dec  2 12:31:00 2002
+++ b/arch/i386/kernel/i387.c	Mon Mar 10 10:20:30 2003
@@ -52,29 +52,13 @@
  * FPU lazy state save handling.
  */
 
-static inline void __save_init_fpu( struct task_struct *tsk )
-{
-	if ( cpu_has_fxsr ) {
-		asm volatile( "fxsave %0 ; fnclex"
-			      : "=m" (tsk->thread.i387.fxsave) );
-	} else {
-		asm volatile( "fnsave %0 ; fwait"
-			      : "=m" (tsk->thread.i387.fsave) );
-	}
-	clear_tsk_thread_flag(tsk, TIF_USEDFPU);
-}
-
-void save_init_fpu( struct task_struct *tsk )
-{
-	__save_init_fpu(tsk);
-	stts();
-}
-
 void kernel_fpu_begin(void)
 {
+	struct thread_info *thread = current_thread_info();
+
 	preempt_disable();
-	if (test_thread_flag(TIF_USEDFPU)) {
-		__save_init_fpu(current);
+	if (thread->status & TS_USEDFPU) {
+		__save_init_fpu(thread->task);
 		return;
 	}
 	clts();
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/kernel/io_apic.c	Sat Mar  8 14:50:47 2003
@@ -221,8 +221,9 @@
 #  define Dprintk(x...) 
 # endif
 
-extern unsigned long irq_affinity [NR_IRQS];
-int __cacheline_aligned pending_irq_balance_apicid [NR_IRQS];
+extern unsigned long irq_affinity[NR_IRQS];
+
+static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS];
 static int irqbalance_disabled = NO_BALANCE_IRQ;
 static int physical_balance = 0;
 
@@ -251,8 +252,54 @@
 #define BALANCED_IRQ_LESS_DELTA		(HZ)
 
 long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
-					 
-static inline void balance_irq(int cpu, int irq);
+
+static unsigned long move(int curr_cpu, unsigned long allowed_mask,
+			unsigned long now, int direction)
+{
+	int search_idle = 1;
+	int cpu = curr_cpu;
+
+	goto inside;
+
+	do {
+		if (unlikely(cpu == curr_cpu))
+			search_idle = 0;
+inside:
+		if (direction == 1) {
+			cpu++;
+			if (cpu >= NR_CPUS)
+				cpu = 0;
+		} else {
+			cpu--;
+			if (cpu == -1)
+				cpu = NR_CPUS-1;
+		}
+	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
+			(search_idle && !IDLE_ENOUGH(cpu,now)));
+
+	return cpu;
+}
+
+static inline void balance_irq(int cpu, int irq)
+{
+	unsigned long now = jiffies;
+	unsigned long allowed_mask;
+	unsigned int new_cpu;
+		
+	if (irqbalance_disabled)
+		return;
+
+	allowed_mask = cpu_online_map & irq_affinity[irq];
+	new_cpu = move(cpu, allowed_mask, now, 1);
+	if (cpu != new_cpu) {
+		irq_desc_t *desc = irq_desc + irq;
+		unsigned long flags;
+
+		spin_lock_irqsave(&desc->lock, flags);
+		pending_irq_balance_apicid[irq]=cpu_to_logical_apicid(new_cpu);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
+}
 
 static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
 {
@@ -263,7 +310,8 @@
 			if (!irq_desc[j].action)
 				continue;
 			/* Is it a significant load ?  */
-			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < useful_load_threshold)
+			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
+						useful_load_threshold)
 				continue;
 			balance_irq(i, j);
 		}
@@ -430,7 +478,8 @@
 	 * We seek the least loaded sibling by making the comparison
 	 * (A+B)/2 vs B
 	 */
-	if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > CPU_IRQ(cpu_sibling_map[min_loaded]))
+	if (physical_balance && (CPU_IRQ(min_loaded) >> 1) >
+					CPU_IRQ(cpu_sibling_map[min_loaded]))
 		min_loaded = cpu_sibling_map[min_loaded];
 
 	allowed_mask = cpu_online_map & irq_affinity[selected_irq];
@@ -438,11 +487,15 @@
 
 	if (target_cpu_mask & allowed_mask) {
 		irq_desc_t *desc = irq_desc + selected_irq;
-		Dprintk("irq = %d moved to cpu = %d\n", selected_irq, min_loaded);
+		unsigned long flags;
+
+		Dprintk("irq = %d moved to cpu = %d\n",
+				selected_irq, min_loaded);
 		/* mark for change destination */
-		spin_lock(&desc->lock);
-		pending_irq_balance_apicid[selected_irq] = cpu_to_logical_apicid(min_loaded);
-		spin_unlock(&desc->lock);
+		spin_lock_irqsave(&desc->lock, flags);
+		pending_irq_balance_apicid[selected_irq] =
+				cpu_to_logical_apicid(min_loaded);
+		spin_unlock_irqrestore(&desc->lock, flags);
 		/* Since we made a change, come back sooner to 
 		 * check for more variation.
 		 */
@@ -453,58 +506,16 @@
 	goto tryanotherirq;
 
 not_worth_the_effort:
-	/* if we did not find an IRQ to move, then adjust the time interval upward */
+	/*
+	 * if we did not find an IRQ to move, then adjust the time interval
+	 * upward
+	 */
 	balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
 		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);	
 	Dprintk("IRQ worth rotating not found\n");
 	return;
 }
 
-static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
-{
-	int search_idle = 1;
-	int cpu = curr_cpu;
-
-	goto inside;
-
-	do {
-		if (unlikely(cpu == curr_cpu))
-			search_idle = 0;
-inside:
-		if (direction == 1) {
-			cpu++;
-			if (cpu >= NR_CPUS)
-				cpu = 0;
-		} else {
-			cpu--;
-			if (cpu == -1)
-				cpu = NR_CPUS-1;
-		}
-	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
-			(search_idle && !IDLE_ENOUGH(cpu,now)));
-
-	return cpu;
-}
-
-static inline void balance_irq (int cpu, int irq)
-{
-	unsigned long now = jiffies;
-	unsigned long allowed_mask;
-	unsigned int new_cpu;
-		
-	if (irqbalance_disabled)
-		return;
-
-	allowed_mask = cpu_online_map & irq_affinity[irq];
-	new_cpu = move(cpu, allowed_mask, now, 1);
-	if (cpu != new_cpu) {
-		irq_desc_t *desc = irq_desc + irq;
-		spin_lock(&desc->lock);
-		pending_irq_balance_apicid[irq] = cpu_to_logical_apicid(new_cpu);
-		spin_unlock(&desc->lock);
-	}
-}
-
 int balanced_irq(void *unused)
 {
 	int i;
@@ -516,26 +527,32 @@
 	/* push everything to CPU 0 to give us a starting point.  */
 	for (i = 0 ; i < NR_IRQS ; i++)
 		pending_irq_balance_apicid[i] = cpu_to_logical_apicid(0);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		time_remaining = schedule_timeout(time_remaining);
-		if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) {
-			Dprintk("balanced_irq: calling do_irq_balance() %lu\n", jiffies);
-			do_irq_balance();
-			prev_balance_time = jiffies;
-			time_remaining = balanced_irq_interval;
-		}
-        }
+
+repeat:
+	set_current_state(TASK_INTERRUPTIBLE);
+	time_remaining = schedule_timeout(time_remaining);
+	if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) {
+		Dprintk("balanced_irq: calling do_irq_balance() %lu\n",
+					jiffies);
+		do_irq_balance();
+		prev_balance_time = jiffies;
+		time_remaining = balanced_irq_interval;
+	}
+	goto repeat;
 }
 
 static int __init balanced_irq_init(void)
 {
 	int i;
 	struct cpuinfo_x86 *c;
+
         c = &boot_cpu_data;
 	if (irqbalance_disabled)
 		return 0;
-	/* Enable physical balance only if more than 1 physical processor is present */
+	/*
+	 * Enable physical balance only if more than 1 physical processor
+	 * is present
+	 */
 	if (smp_num_siblings > 1 && cpu_online_map >> 2)
 		physical_balance = 1;
 
@@ -1150,11 +1167,8 @@
 	enable_8259A_irq(0);
 }
 
-void __init UNEXPECTED_IO_APIC(void)
+static inline void UNEXPECTED_IO_APIC(void)
 {
-	printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n");
-	printk(KERN_WARNING "      http://bugzilla.kernel.org\n");
-	printk(KERN_WARNING "      if your kernel is less than 3 months old.\n");
 }
 
 void __init print_IO_APIC(void)
@@ -1566,7 +1580,7 @@
  */
 static int __init timer_irq_works(void)
 {
-	unsigned int t1 = jiffies;
+	unsigned long t1 = jiffies;
 
 	local_irq_enable();
 	/* Let ten ticks pass... */
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Tue Feb 25 01:38:22 2003
+++ b/arch/i386/kernel/irq.c	Sat Mar  8 14:50:44 2003
@@ -135,43 +135,47 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "CPU%d       ",j);
+			seq_printf(p, "CPU%d       ",j);
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < NR_CPUS; j++)
 			if (cpu_online(j))
-				p += seq_printf(p, "%10u ",
-					     kstat_cpu(j).irqs[i]);
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "%10u ", nmi_count(j));
+			seq_printf(p, "%10u ", nmi_count(j));
 	seq_putc(p, '\n');
 #if CONFIG_X86_LOCAL_APIC
 	seq_printf(p, "LOC: ");
 	for (j = 0; j < NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
+			seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
 	seq_putc(p, '\n');
 #endif
 	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
--- a/arch/i386/kernel/microcode.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/kernel/microcode.c	Tue Mar 11 06:16:36 2003
@@ -372,7 +372,6 @@
 		ret = (ssize_t)len;
 	}
 out_fsize:
-	devfs_set_file_size(devfs_handle, mc_fsize);
 	vfree(microcode);
 out_unlock:
 	up_write(&microcode_rwsem);
@@ -388,7 +387,6 @@
 			if (mc_applied) {
 				int bytes = NR_CPUS * sizeof(struct microcode);
 
-				devfs_set_file_size(devfs_handle, 0);
 				kfree(mc_applied);
 				mc_applied = NULL;
 				printk(KERN_INFO "microcode: freed %d bytes\n", bytes);
diff -Nru a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c
--- a/arch/i386/kernel/numaq.c	Fri Feb 28 00:05:34 2003
+++ b/arch/i386/kernel/numaq.c	Tue Mar  4 23:41:55 2003
@@ -31,8 +31,7 @@
 #include <asm/numaq.h>
 
 /* These are needed before the pgdat's are created */
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern long node_start_pfn[], node_end_pfn[];
 
 #define	MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
 
@@ -64,26 +63,6 @@
 		}
 	}
 }
-
-/*
- * -----------------------------------------
- *
- * functions related to physnode_map
- *
- * -----------------------------------------
- */
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id.  so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(physnode_map);
 
 /*
  * for each node mark the regions
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	Thu Feb 20 20:33:52 2003
+++ b/arch/i386/kernel/process.c	Mon Mar 10 10:20:30 2003
@@ -275,6 +275,15 @@
 	release_x86_irqs(dead_task);
 }
 
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+	unlazy_fpu(tsk);
+}
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 	unsigned long unused,
 	struct task_struct * p, struct pt_regs * regs)
@@ -297,9 +306,6 @@
 	savesegment(gs,p->thread.gs);
 
 	tsk = current;
-	unlazy_fpu(tsk);
-	struct_cpy(&p->thread.i387, &tsk->thread.i387);
-
 	if (unlikely(NULL != tsk->thread.ts_io_bitmap)) {
 		p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
 		if (!p->thread.ts_io_bitmap)
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Thu Feb 27 16:10:55 2003
+++ b/arch/i386/kernel/setup.c	Sun Mar 16 22:33:11 2003
@@ -525,8 +525,11 @@
 		 * "mem=nopentium" disables the 4MB page tables.
 		 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
 		 * to <mem>, overriding the bios size.
-		 * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+		 * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
 		 * <start> to <start>+<mem>, overriding the bios size.
+		 *
+		 * HPA tells me bootloaders need to parse mem=, so no new
+		 * option should be mem=  [also see Documentation/i386/boot.txt]
 		 */
 		if (c == ' ' && !memcmp(from, "mem=", 4)) {
 			if (to != command_line)
@@ -535,8 +538,26 @@
 				from += 9+4;
 				clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
 				disable_pse = 1;
-			} else if (!memcmp(from+4, "exactmap", 8)) {
-				from += 8+4;
+			} else {
+				/* If the user specifies memory size, we
+				 * limit the BIOS-provided memory map to
+				 * that size. exactmap can be used to specify
+				 * the exact map. mem=number can be used to
+				 * trim the existing memory map.
+				 */
+				unsigned long long mem_size;
+ 
+				mem_size = memparse(from+4, &from);
+				limit_regions(mem_size);
+				userdef=1;
+			}
+		}
+
+		if (c == ' ' && !memcmp(from, "memmap=", 7)) {
+			if (to != command_line)
+				to--;
+			if (!memcmp(from+7, "exactmap", 8)) {
+				from += 8+7;
 				e820.nr_map = 0;
 				userdef = 1;
 			} else {
@@ -548,7 +569,7 @@
 				 */
 				unsigned long long start_at, mem_size;
  
-				mem_size = memparse(from+4, &from);
+				mem_size = memparse(from+7, &from);
 				if (*from == '@') {
 					start_at = memparse(from+1, &from);
 					add_memory_region(start_at, mem_size, E820_RAM);
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	Tue Feb 25 10:47:22 2003
+++ b/arch/i386/kernel/smpboot.c	Tue Mar  4 23:41:54 2003
@@ -966,6 +966,7 @@
 		if (APIC_init_uniprocessor())
 			printk(KERN_NOTICE "Local APIC not detected."
 					   " Using dummy APIC emulation.\n");
+		map_cpu_to_logical_apicid();
 		return;
 	}
 
diff -Nru a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
--- a/arch/i386/kernel/srat.c	Mon Feb 24 23:13:14 2003
+++ b/arch/i386/kernel/srat.c	Wed Mar  5 00:44:17 2003
@@ -57,8 +57,7 @@
 static int zholes_size_init;
 static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
 
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern unsigned long node_start_pfn[], node_end_pfn[];
 
 extern void * boot_ioremap(unsigned long, unsigned long);
 
@@ -182,30 +181,19 @@
 	}
 }
 
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id.  so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int pfnnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(pfnnode_map);
-
-static void __init initialize_pfnnode_map(void)
+static void __init initialize_physnode_map(void)
 {
-	unsigned long topofchunk, cur = 0;
 	int i;
-	
-	for (i = 0; i < num_memory_chunks; i++) {
-		cur = node_memory_chunk[i].start_pfn;
-		topofchunk = node_memory_chunk[i].end_pfn;
-		while (cur < topofchunk) {
-			pfnnode_map[PFN_TO_ELEMENT(cur)] = node_memory_chunk[i].nid;
-			cur ++;
+	unsigned long pfn;
+	struct node_memory_chunk_s *nmcp;
+
+	/* Run the list of memory chunks and fill in the phymap. */
+	nmcp = node_memory_chunk;
+	for (i = num_memory_chunks; --i >= 0; nmcp++) {
+		for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn;
+						pfn += PAGES_PER_ELEMENT)
+		{
+			physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid;
 		}
 	}
 }
@@ -272,7 +260,7 @@
 	for (i = 0; i < num_memory_chunks; i++)
 		node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
 
-	initialize_pfnnode_map();
+	initialize_physnode_map();
 	
 	printk("pxm bitmap: ");
 	for (i = 0; i < sizeof(pxm_bitmap); i++) {
diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
--- a/arch/i386/kernel/sysenter.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/kernel/sysenter.c	Mon Mar 10 14:41:23 2003
@@ -40,8 +40,10 @@
 	int cpu = get_cpu();
 	struct tss_struct *tss = init_tss + cpu;
 
+	tss->ss1 = __KERNEL_CS;
+	tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
 	wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
-	wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0);
+	wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0);
 	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
 
 	printk("Enabling SEP on CPU %d\n", cpu);
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Fri Feb 21 17:44:10 2003
+++ b/arch/i386/kernel/traps.c	Mon Mar 10 10:20:30 2003
@@ -737,13 +737,14 @@
  */
 asmlinkage void math_state_restore(struct pt_regs regs)
 {
-	struct task_struct *tsk = current;
-	clts();		/* Allow maths ops (or we recurse) */
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = thread->task;
 
+	clts();		/* Allow maths ops (or we recurse) */
 	if (!tsk->used_math)
 		init_fpu(tsk);
 	restore_fpu(tsk);
-	set_thread_flag(TIF_USEDFPU);	/* So we fnsave on switch_to() */
+	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
 }
 
 #ifndef CONFIG_MATH_EMULATION
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	Sat Feb 15 19:30:17 2003
+++ b/arch/i386/kernel/vm86.c	Sun Mar  9 18:49:37 2003
@@ -291,7 +291,7 @@
 
 	tss = init_tss + smp_processor_id();
 	tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
-	disable_sysenter();
+	disable_sysenter(tss);
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
 	if (info->flags & VM86_SCREEN_BITMAP)
diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
--- a/arch/i386/mm/discontig.c	Fri Feb 28 15:08:58 2003
+++ b/arch/i386/mm/discontig.c	Tue Mar  4 23:41:55 2003
@@ -36,11 +36,36 @@
 struct pglist_data *node_data[MAX_NUMNODES];
 bootmem_data_t node0_bdata;
 
+/*
+ * numa interface - we expect the numa architecture specfic code to have
+ *                  populated the following initialisation.
+ *
+ * 1) numnodes         - the total number of nodes configured in the system
+ * 2) physnode_map     - the mapping between a pfn and owning node
+ * 3) node_start_pfn   - the starting page frame number for a node
+ * 3) node_end_pfn     - the ending page fram number for a node
+ */
+
+/*
+ * physnode_map keeps track of the physical memory layout of a generic
+ * numa node on a 256Mb break (each element of the array will
+ * represent 256Mb of memory and will be marked by the node id.  so,
+ * if the first gig is on node 0, and the second gig is on node 1
+ * physnode_map will contain:
+ *
+ *     physnode_map[0-3] = 0;
+ *     physnode_map[4-7] = 1;
+ *     physnode_map[8- ] = -1;
+ */
+u8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+
+unsigned long node_start_pfn[MAX_NUMNODES];
+unsigned long node_end_pfn[MAX_NUMNODES];
+
 extern unsigned long find_max_low_pfn(void);
 extern void find_max_pfn(void);
 extern void one_highpage_init(struct page *, int, int);
 
-extern unsigned long node_start_pfn[], node_end_pfn[];
 extern struct e820map e820;
 extern char _end;
 extern unsigned long highend_pfn, highstart_pfn;
@@ -55,6 +80,36 @@
 unsigned long node_remap_offset[MAX_NUMNODES];
 void *node_remap_start_vaddr[MAX_NUMNODES];
 void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
+
+/*
+ * FLAT - support for basic PC memory model with discontig enabled, essentially
+ *        a single node with all available processors in it with a flat
+ *        memory map.
+ */
+void __init get_memcfg_numa_flat(void)
+{
+	int pfn;
+
+	printk("NUMA - single node, flat memory mode\n");
+
+	/* Run the memory configuration and find the top of memory. */
+	find_max_pfn();
+	node_start_pfn[0]  = 0;
+	node_end_pfn[0]	  = max_pfn;
+
+	/* Fill in the physnode_map with our simplistic memory model,
+	* all memory is in node 0.
+	*/
+	for (pfn = node_start_pfn[0]; pfn <= node_end_pfn[0];
+	       pfn += PAGES_PER_ELEMENT)
+	{
+		physnode_map[pfn / PAGES_PER_ELEMENT] = 0;
+	}
+
+         /* Indicate there is one node available. */
+	node_set_online(0);
+	numnodes = 1;
+}
 
 /*
  * Find the highest page frame number we have available for the node
diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
--- a/arch/i386/mm/fault.c	Fri Jan 10 19:29:47 2003
+++ b/arch/i386/mm/fault.c	Thu Mar  6 08:19:03 2003
@@ -394,14 +394,14 @@
 		 * Do _not_ use "tsk" here. We might be inside
 		 * an interrupt in the middle of a task switch..
 		 */
-		int offset = __pgd_offset(address);
+		int index = pgd_index(address);
 		pgd_t *pgd, *pgd_k;
 		pmd_t *pmd, *pmd_k;
 		pte_t *pte_k;
 
 		asm("movl %%cr3,%0":"=r" (pgd));
-		pgd = offset + (pgd_t *)__va(pgd);
-		pgd_k = init_mm.pgd + offset;
+		pgd = index + (pgd_t *)__va(pgd);
+		pgd_k = init_mm.pgd + index;
 
 		if (!pgd_present(*pgd_k))
 			goto no_context;
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Mon Feb  3 23:46:49 2003
+++ b/arch/i386/mm/init.c	Thu Mar  6 08:19:07 2003
@@ -98,26 +98,26 @@
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
-	int pgd_ofs, pmd_ofs;
+	int pgd_idx, pmd_idx;
 	unsigned long vaddr;
 
 	vaddr = start;
-	pgd_ofs = __pgd_offset(vaddr);
-	pmd_ofs = __pmd_offset(vaddr);
-	pgd = pgd_base + pgd_ofs;
+	pgd_idx = pgd_index(vaddr);
+	pmd_idx = pmd_index(vaddr);
+	pgd = pgd_base + pgd_idx;
 
-	for ( ; (pgd_ofs < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_ofs++) {
+	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
 		if (pgd_none(*pgd)) 
 			one_md_table_init(pgd);
 
 		pmd = pmd_offset(pgd, vaddr);
-		for (; (pmd_ofs < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_ofs++) {
+		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
 			if (pmd_none(*pmd)) 
 				one_page_table_init(pmd);
 
 			vaddr += PMD_SIZE;
 		}
-		pmd_ofs = 0;
+		pmd_idx = 0;
 	}
 }
 
@@ -132,17 +132,17 @@
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
-	int pgd_ofs, pmd_ofs, pte_ofs;
+	int pgd_idx, pmd_idx, pte_ofs;
 
-	pgd_ofs = __pgd_offset(PAGE_OFFSET);
-	pgd = pgd_base + pgd_ofs;
+	pgd_idx = pgd_index(PAGE_OFFSET);
+	pgd = pgd_base + pgd_idx;
 	pfn = 0;
 
-	for (; pgd_ofs < PTRS_PER_PGD; pgd++, pgd_ofs++) {
+	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
 		pmd = one_md_table_init(pgd);
 		if (pfn >= max_low_pfn)
 			continue;
-		for (pmd_ofs = 0; pmd_ofs < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_ofs++) {
+		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
 			/* Map with big pages if possible, otherwise create normal page tables. */
 			if (cpu_has_pse) {
 				set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
@@ -214,7 +214,7 @@
 	vaddr = PKMAP_BASE;
 	page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
 
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	pmd = pmd_offset(pgd, vaddr);
 	pte = pte_offset_kernel(pmd, vaddr);
 	pkmap_page_table = pte;	
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c	Mon Feb 24 23:13:24 2003
+++ b/arch/i386/mm/ioremap.c	Thu Mar  6 06:34:47 2003
@@ -148,7 +148,7 @@
 	 */
 	offset = phys_addr & ~PAGE_MASK;
 	phys_addr &= PAGE_MASK;
-	size = PAGE_ALIGN(last_addr) - phys_addr;
+	size = PAGE_ALIGN(last_addr+1) - phys_addr;
 
 	/*
 	 * Ok, go for it..
diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
--- a/arch/i386/mm/pgtable.c	Sun Mar  2 18:14:31 2003
+++ b/arch/i386/mm/pgtable.c	Thu Mar  6 08:19:03 2003
@@ -64,7 +64,7 @@
 	pmd_t *pmd;
 	pte_t *pte;
 
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	if (pgd_none(*pgd)) {
 		BUG();
 		return;
@@ -104,7 +104,7 @@
 		printk ("set_pmd_pfn: pfn misaligned\n");
 		return; /* BUG(); */
 	}
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	if (pgd_none(*pgd)) {
 		printk ("set_pmd_pfn: pgd_none\n");
 		return; /* BUG(); */
diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
--- a/arch/i386/oprofile/nmi_int.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/oprofile/nmi_int.c	Wed Mar  5 11:46:56 2003
@@ -58,7 +58,7 @@
 	unsigned int const nr_ctrls = model->num_controls; 
 	struct op_msr_group * counters = &msrs->counters;
 	struct op_msr_group * controls = &msrs->controls;
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < nr_ctrs; ++i) {
 		rdmsr(counters->addrs[i],
@@ -108,7 +108,7 @@
 	unsigned int const nr_ctrls = model->num_controls; 
 	struct op_msr_group * counters = &msrs->counters;
 	struct op_msr_group * controls = &msrs->controls;
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < nr_ctrls; ++i) {
 		wrmsr(controls->addrs[i],
@@ -182,7 +182,7 @@
 
 static int nmi_create_files(struct super_block * sb, struct dentry * root)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry * dir;
diff -Nru a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
--- a/arch/i386/oprofile/op_model_athlon.c	Thu Jan 23 12:24:53 2003
+++ b/arch/i386/oprofile/op_model_athlon.c	Sun Mar  9 05:09:00 2003
@@ -104,10 +104,11 @@
 		if (CTR_OVERFLOWED(low)) {
 			oprofile_add_sample(eip, is_kernel, i, cpu);
 			CTR_WRITE(reset_value[i], msrs, i);
-			return 1;
 		}
 	}
-	return 0;
+
+	/* See op_model_ppro.c */
+	return 1;
 }
 
  
diff -Nru a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
--- a/arch/i386/oprofile/op_model_p4.c	Thu Jan 30 19:57:28 2003
+++ b/arch/i386/oprofile/op_model_p4.c	Sun Mar  9 05:08:41 2003
@@ -389,7 +389,7 @@
 
 static void p4_fill_in_addresses(struct op_msrs * const msrs)
 {
-	int i; 
+	unsigned int i; 
 	unsigned int addr, stag;
 
 	setup_num_counters();
@@ -608,13 +608,14 @@
  			CTR_WRITE(reset_value[i], real);
 			/* P4 quirk: you have to re-unmask the apic vector */
 			apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
-			return 1;
 		}
 	}
 
 	/* P4 quirk: you have to re-unmask the apic vector */
 	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
-	return 0;
+
+	/* See op_model_ppro.c */
+	return 1;
 }
 
 
diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
--- a/arch/i386/oprofile/op_model_ppro.c	Thu Jan 23 12:24:53 2003
+++ b/arch/i386/oprofile/op_model_ppro.c	Sun Mar  9 06:15:07 2003
@@ -98,10 +98,17 @@
 		if (CTR_OVERFLOWED(low)) {
 			oprofile_add_sample(eip, is_kernel, i, cpu);
 			CTR_WRITE(reset_value[i], msrs, i);
-			return 1;
 		}
 	}
-	return 0;
+
+	/* We can't work out if we really handled an interrupt. We
+	 * might have caught a *second* counter just after overflowing
+	 * the interrupt for this counter then arrives
+	 * and we don't find a counter that's overflowed, so we
+	 * would return 0 and get dazed + confused. Instead we always
+	 * assume we found an overflow. This sucks.
+	 */
+	return 1;
 }
 
  
diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c
--- a/arch/i386/pci/common.c	Tue Feb 18 18:58:56 2003
+++ b/arch/i386/pci/common.c	Sun Mar 16 13:55:55 2003
@@ -90,11 +90,6 @@
 	}
 }
 
-void __devinit
-pcibios_fixup_pbus_ranges (struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-}
-
 /*
  *  Called after each bus is probed, but before its children
  *  are examined.
diff -Nru a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
--- a/arch/i386/pci/i386.c	Tue Oct  8 13:56:14 2002
+++ b/arch/i386/pci/i386.c	Sun Mar 16 14:16:30 2003
@@ -33,34 +33,6 @@
 
 #include "pci.h"
 
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-
-	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		new |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
-		return;
-	}
-	
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
-}
-
 /*
  * We need to avoid collisions with `mirrored' VGA ports
  * and other strange ISA hardware, so we always want the
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c	Mon Oct  7 07:36:47 2002
+++ b/arch/i386/pci/irq.c	Fri Mar  7 19:36:28 2003
@@ -804,6 +804,7 @@
 int pirq_enable_irq(struct pci_dev *dev)
 {
 	u8 pin;
+	extern int interrupt_line_quirk;
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
 		char *msg;
@@ -813,9 +814,17 @@
 			msg = "";
 		else
 			msg = " Please try using pci=biosirq.";
+			
+		/* With IDE legacy devices the IRQ lookup failure is not a problem.. */
+		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
+			return 0;
+			
 		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
 		       'A' + pin - 1, dev->slot_name, msg);
 	}
-
+	/* VIA bridges use interrupt line for apic/pci steering across
+	   the V-Link */
+	else if (interrupt_line_quirk)
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 	return 0;
 }
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
--- a/arch/i386/vmlinux.lds.S	Tue Feb 18 18:58:52 2003
+++ b/arch/i386/vmlinux.lds.S	Sun Feb 16 15:55:23 2003
@@ -74,6 +74,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/ia64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -22,11 +22,7 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
-config RWSEM_GENERIC_SPINLOCK
+config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
@@ -424,6 +420,18 @@
 
 	  If you don't know what to do here, say N.
 
+config PREEMPT
+	bool "Preemptible Kernel"
+        help
+          This option reduces the latency of the kernel when reacting to
+          real-time or interactive events by allowing a low priority process to
+          be preempted even if it is in kernel mode executing a system call.
+          This allows applications to run more reliably even when the system is
+          under load.
+
+          Say Y here if you are building a kernel for a desktop, embedded
+          or real-time system.  Say N if you are unsure.
+
 config IA32_SUPPORT
 	bool "Support running of Linux/x86 binaries"
 	help
@@ -874,6 +882,12 @@
 	  and certain other kinds of spinlock errors commonly made.  This is
 	  best used in conjunction with the NMI watchdog so that spinlock
 	  deadlocks are also debuggable.
+
+config DEBUG_SPINLOCK_SLEEP
+	  bool "Sleep-inside-spinlock checking"
+	  help
+	    If you say Y here, various routines which may sleep will become very
+	    noisy if they are called with a spinlock held.
 
 config IA64_DEBUG_CMPXCHG
 	bool "Turn on compare-and-exchange bug checking (slow!)"
diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile
--- a/arch/ia64/Makefile	Thu Feb  6 22:47:17 2003
+++ b/arch/ia64/Makefile	Mon Feb 24 05:40:16 2003
@@ -52,18 +52,19 @@
 core-$(CONFIG_IA64_HP_ZX1)	+= arch/ia64/dig/
 core-$(CONFIG_IA64_SGI_SN)	+= arch/ia64/sn/kernel/ \
 				   arch/ia64/sn/io/ \
+				   arch/ia64/sn/io/sn2/ \
+				   arch/ia64/sn/io/sn2/pcibr/ \
 				   arch/ia64/sn/kernel/sn2/
 drivers-$(CONFIG_PCI)		+= arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)	+= arch/ia64/hp/sim/
 drivers-$(CONFIG_IA64_HP_ZX1)	+= arch/ia64/hp/common/ arch/ia64/hp/zx1/
-drivers-$(CONFIG_IA64_SGI_SN)	+= arch/ia64/sn/fakeprom/
 
 boot := arch/ia64/boot
 tools := arch/ia64/tools
 
 .PHONY: boot compressed include/asm-ia64/offsets.h
 
-all: vmlinux
+all: prepare vmlinux
 
 compressed: vmlinux.gz
 
diff -Nru a/arch/ia64/boot/Makefile b/arch/ia64/boot/Makefile
--- a/arch/ia64/boot/Makefile	Mon Dec 16 18:06:42 2002
+++ b/arch/ia64/boot/Makefile	Sun Mar  9 13:47:41 2003
@@ -8,16 +8,14 @@
 # Copyright (C) 1998 by David Mosberger-Tang <davidm@hpl.hp.com>
 #
 
-EXTRA_TARGETS := vmlinux.bin vmlinux.gz
-
 targets-$(CONFIG_IA64_HP_SIM)  += bootloader
 targets-$(CONFIG_IA64_GENERIC) += bootloader
-EXTRA_TARGETS += $(sort $(targets-y))
+targets := vmlinux.bin vmlinux.gz $(targets-y)
 
 quiet_cmd_cptotop = LN      $@
       cmd_cptotop = ln -f $< $@
 
-vmlinux.gz: $(obj)/vmlinux.gz $(targets-y)
+vmlinux.gz: $(obj)/vmlinux.gz $(addprefix $(obj)/,$(targets-y))
 	$(call cmd,cptotop)
 	@echo '  Kernel: $@ is ready'
 
diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
--- a/arch/ia64/hp/sim/simscsi.c	Tue Feb  4 17:06:04 2003
+++ b/arch/ia64/hp/sim/simscsi.c	Wed Feb 12 00:11:32 2003
@@ -156,7 +156,7 @@
 	if (sc->request_bufflen < req.len)
 		return;
 
-	stat.fd = desc[sc->target];
+	stat.fd = desc[sc->device->id];
 	if (DBG)
 		printk("simscsi_%s @ %lx (off %lx)\n",
 		       mode == SSC_READ ? "read":"write", req.addr, offset);
@@ -178,7 +178,7 @@
 	struct disk_stat stat;
 	struct disk_req req;
 
-	stat.fd = desc[sc->target];
+	stat.fd = desc[sc->device->id];
 
 	while (list_len) {
 		req.addr = __pa(page_address(sl->page) + sl->offset);
@@ -259,6 +259,7 @@
 int
 simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
 {
+	unsigned int target_id = sc->device->id;
 	char fname[MAX_ROOT_LEN+16];
 	size_t disk_size;
 	char *buf;
@@ -267,21 +268,21 @@
 
 	if (DBG)
 		printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n",
-		       sc->target, sc->cmnd[0], sc->serial_number, sp, done);
+		       target_id, sc->cmnd[0], sc->serial_number, sp, done);
 #endif
 
 	sc->result = DID_BAD_TARGET << 16;
 	sc->scsi_done = done;
-	if (sc->target <= 15 && sc->lun == 0) {
+	if (target_id <= 15 && sc->device->lun == 0) {
 		switch (sc->cmnd[0]) {
 		      case INQUIRY:
 			if (sc->request_bufflen < 35) {
 				break;
 			}
-			sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target);
-			desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
-						    0, 0, SSC_OPEN);
-			if (desc[sc->target] < 0) {
+			sprintf (fname, "%s%c", simscsi_root, 'a' + target_id);
+			desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
+						   0, 0, SSC_OPEN);
+			if (desc[target_id] < 0) {
 				/* disk doesn't exist... */
 				break;
 			}
@@ -303,37 +304,37 @@
 			break;
 
 		      case READ_6:
-			if (desc[sc->target] < 0 )
+			if (desc[target_id] < 0 )
 				break;
 			simscsi_readwrite6(sc, SSC_READ);
 			break;
 
 		      case READ_10:
-			if (desc[sc->target] < 0 )
+			if (desc[target_id] < 0 )
 				break;
 			simscsi_readwrite10(sc, SSC_READ);
 			break;
 
 		      case WRITE_6:
-			if (desc[sc->target] < 0)
+			if (desc[target_id] < 0)
 				break;
 			simscsi_readwrite6(sc, SSC_WRITE);
 			break;
 
 		      case WRITE_10:
-			if (desc[sc->target] < 0)
+			if (desc[target_id] < 0)
 				break;
 			simscsi_readwrite10(sc, SSC_WRITE);
 			break;
 
 
 		      case READ_CAPACITY:
-			if (desc[sc->target] < 0 || sc->request_bufflen < 8) {
+			if (desc[target_id] < 0 || sc->request_bufflen < 8) {
 				break;
 			}
 			buf = sc->request_buffer;
 
-			disk_size = simscsi_get_disk_size(desc[sc->target]);
+			disk_size = simscsi_get_disk_size(desc[target_id]);
 
 			/* pretend to be a 1GB disk (partition table contains real stuff): */
 			buf[0] = (disk_size >> 24) & 0xff;
diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
--- a/arch/ia64/hp/sim/simserial.c	Tue Feb  4 17:06:04 2003
+++ b/arch/ia64/hp/sim/simserial.c	Thu Feb 13 05:43:47 2003
@@ -63,7 +63,6 @@
 
 static char *serial_name = "SimSerial driver";
 static char *serial_version = "0.6";
-static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * This has been extracted from asm/serial.h. We need one eventually but
@@ -235,14 +234,14 @@
 
 	if (!tty || !info->xmit.buf) return;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 		return;
 	}
 	info->xmit.buf[info->xmit.head] = ch;
 	info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 }
 
 static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
@@ -250,7 +249,8 @@
 	int count;
 	unsigned long flags;
 
-	spin_lock_irqsave(&serial_lock, flags);
+
+	local_irq_save(flags);
 
 	if (info->x_char) {
 		char c = info->x_char;
@@ -293,7 +293,7 @@
 		info->xmit.tail += count;
 	}
 out:
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
@@ -334,7 +334,7 @@
 				break;
 			}
 
-			spin_lock_irqsave(&serial_lock, flags);
+			local_irq_save(flags);
 			{
 				c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail,
 						       SERIAL_XMIT_SIZE);
@@ -344,7 +344,7 @@
 				info->xmit.head = ((info->xmit.head + c) &
 						   (SERIAL_XMIT_SIZE-1));
 			}
-			spin_unlock_irqrestore(&serial_lock, flags);
+			local_irq_restore(flags);
 
 			buf += c;
 			count -= c;
@@ -352,7 +352,7 @@
 		}
 		up(&tmp_buf_sem);
 	} else {
-		spin_lock_irqsave(&serial_lock, flags);
+		local_irq_save(flags);
 		while (1) {
 			c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
 			if (count < c)
@@ -367,7 +367,7 @@
 			count -= c;
 			ret += c;
 		}
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 	}
 	/*
 	 * Hey, we transmit directly from here in our case
@@ -398,9 +398,9 @@
 	struct async_struct *info = (struct async_struct *)tty->driver_data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	info->xmit.head = info->xmit.tail = 0;
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 
 	wake_up_interruptible(&tty->write_wait);
 
@@ -573,7 +573,7 @@
 	       state->irq);
 #endif
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	{
 		/*
 		 * First unlink the serial port from the IRQ chain...
@@ -611,7 +611,7 @@
 
 		info->flags &= ~ASYNC_INITIALIZED;
 	}
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 }
 
 /*
@@ -634,13 +634,13 @@
 
 	state = info->state;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	if (tty_hung_up_p(filp)) {
 #ifdef SIMSERIAL_DEBUG
 		printk("rs_close: hung_up\n");
 #endif
 		MOD_DEC_USE_COUNT;
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 		return;
 	}
 #ifdef SIMSERIAL_DEBUG
@@ -665,11 +665,11 @@
 	}
 	if (state->count) {
 		MOD_DEC_USE_COUNT;
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 		return;
 	}
 	info->flags |= ASYNC_CLOSING;
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 
 	/*
 	 * Now we wait for the transmit buffer to clear; and we notify
@@ -776,7 +776,7 @@
 	if (!page)
 		return -ENOMEM;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 
 	if (info->flags & ASYNC_INITIALIZED) {
 		free_page(page);
@@ -857,11 +857,11 @@
 	}
 
 	info->flags |= ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 	return 0;
 
 errout:
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	Sun Jan 12 16:07:06 2003
+++ b/arch/ia64/ia32/ia32_entry.S	Sat Mar  8 11:30:11 2003
@@ -300,7 +300,7 @@
 	data8 compat_sys_statfs
 	data8 compat_sys_fstatfs	  /* 100 */
 	data8 sys32_ioperm
-	data8 sys32_socketcall
+	data8 compat_sys_socketcall
 	data8 sys_syslog
 	data8 compat_sys_setitimer
 	data8 compat_sys_getitimer	  /* 105 */
@@ -424,6 +424,26 @@
 	data8 sys_ni_syscall		/* reserved for Security */
 	data8 sys_gettid
 	data8 sys_readahead	  /* 225 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall	/* 230 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall	/* 235 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 compat_sys_futex	/* 240 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall	/* 245 */
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
--- a/arch/ia64/ia32/ia32_ioctl.c	Tue Feb  4 17:06:05 2003
+++ b/arch/ia64/ia32/ia32_ioctl.c	Thu Mar  6 11:06:44 2003
@@ -97,11 +97,9 @@
 	int info;		/* [o] auxiliary information */
 } sg_io_hdr32_t;  /* 64 bytes long (on IA32) */
 
-struct iovec32 { unsigned int iov_base; int iov_len; };
-
 static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
 {
-	struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
+	struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
 	sg_iovec_t *kiov;
 	int i;
 
@@ -136,7 +134,7 @@
 
 static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
 {
-	struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
+	struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
 	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
 	int i;
 
diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
--- a/arch/ia64/ia32/ia32_support.c	Fri Jan 17 14:56:29 2003
+++ b/arch/ia64/ia32/ia32_support.c	Thu Jan 30 06:14:13 2003
@@ -93,7 +93,7 @@
 {
 	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
 	struct pt_regs *regs = ia64_task_regs(t);
-	int nr = smp_processor_id();	/* LDT and TSS depend on CPU number: */
+	int nr = get_cpu();	/* LDT and TSS depend on CPU number: */
 
 	eflag = t->thread.eflag;
 	fsr = t->thread.fsr;
@@ -119,6 +119,7 @@
 
 	regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17;
 	regs->r30 = load_desc(_LDT(nr));				/* LDTD */
+	put_cpu();
 }
 
 /*
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/ia64/ia32/sys_ia32.c	Sat Mar  8 11:30:11 2003
@@ -924,12 +924,11 @@
 			    (struct compat_timeval *) A(a.tvp));
 }
 
-struct iovec32 { unsigned int iov_base; int iov_len; };
 asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
 asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
 
 static struct iovec *
-get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
+get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type)
 {
 	int i;
 	u32 buf, len;
@@ -939,7 +938,7 @@
 
 	if (!count)
 		return 0;
-	if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count))
 		return NULL;
 	if (count > UIO_MAXIOV)
 		return NULL;
@@ -971,14 +970,14 @@
 }
 
 asmlinkage long
-sys32_readv (int fd, struct iovec32 *vector, u32 count)
+sys32_readv (int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	long ret;
 	mm_segment_t old_fs = get_fs();
 
-	iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE);
+	iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE);
 	if (!iov)
 		return -EFAULT;
 	set_fs(KERNEL_DS);
@@ -990,14 +989,14 @@
 }
 
 asmlinkage long
-sys32_writev (int fd, struct iovec32 *vector, u32 count)
+sys32_writev (int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	long ret;
 	mm_segment_t old_fs = get_fs();
 
-	iov = get_iovec32(vector, iovstack, count, VERIFY_READ);
+	iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ);
 	if (!iov)
 		return -EFAULT;
 	set_fs(KERNEL_DS);
@@ -1080,701 +1079,6 @@
 }
 
 /*
- *  Declare the IA32 version of the msghdr
- */
-
-struct msghdr32 {
-	unsigned int    msg_name;	/* Socket name			*/
-	int		msg_namelen;	/* Length of name		*/
-	unsigned int    msg_iov;	/* Data blocks			*/
-	unsigned int	msg_iovlen;	/* Number of blocks		*/
-	unsigned int    msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
-	unsigned int	msg_controllen;	/* Length of cmsg list */
-	unsigned	msg_flags;
-};
-
-struct cmsghdr32 {
-	compat_size_t cmsg_len;
-	int               cmsg_level;
-	int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen)	cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-#define CMSG32_DATA(cmsg) \
-	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) \
-	(CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-#define __CMSG32_FIRSTHDR(ctl,len) \
-	((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-static inline struct cmsghdr32 *
-__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len)
-{
-	struct cmsghdr32 * ptr;
-
-	ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len));
-	if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size)
-		return NULL;
-	return ptr;
-}
-
-static inline struct cmsghdr32 *
-cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len)
-{
-	return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len);
-}
-
-static inline int
-get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32)
-{
-	int ret;
-	unsigned int i;
-
-	if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
-		return -EFAULT;
-	ret = __get_user(i, &mp32->msg_name);
-	mp->msg_name = (void *)A(i);
-	ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
-	ret |= __get_user(i, &mp32->msg_iov);
-	mp->msg_iov = (struct iovec *)A(i);
-	ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
-	ret |= __get_user(i, &mp32->msg_control);
-	mp->msg_control = (void *)A(i);
-	ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
-	ret |= __get_user(mp->msg_flags, &mp32->msg_flags);
-	return ret ? -EFAULT : 0;
-}
-
-/*
- * There is a lot of hair here because the alignment rules (and thus placement) of cmsg
- * headers and length are different for 32-bit apps.  -DaveM
- */
-static int
-get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize)
-{
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	__kernel_size_t kcmlen, tmp;
-	compat_size_t ucmlen;
-	struct cmsghdr32 *ucmsg;
-	long err;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while (ucmsg != NULL) {
-		if (get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen)
-		    > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if (kcmlen == 0)
-		return -EINVAL;
-
-	/*
-	 * The kcmlen holds the 64-bit version of the control length.  It may not be
-	 * modified as we do not stick it into the kmsg until we have successfully copied
-	 * over all of the data from the user.
-	 */
-	if (kcmlen > *bufsize) {
-		*bufsize = kcmlen;
-		kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
-	}
-	if (kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while (ucmsg != NULL) {
-		err = get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg),
-				      (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))));
-		if (err)
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if (kcmsg_base != (struct cmsghdr *)stackbuf)
-		sock_kfree_s(sk, kcmsg_base, kcmlen);
-	return -EFAULT;
-}
-
-/*
- *	Verify & re-shape IA32 iovec. The caller must ensure that the
- *      iovec is big enough to hold the re-shaped message iovec.
- *
- *	Save time not doing verify_area. copy_*_user will make this work
- *	in any case.
- *
- *	Don't need to check the total size for overflow (cf net/core/iovec.c),
- *	32-bit sizes can't overflow a 64-bit count.
- */
-
-static inline int
-verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode)
-{
-	int size, err, ct;
-	struct iovec32 *iov32;
-
-	if (m->msg_namelen) {
-		if (mode == VERIFY_READ) {
-			err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
-			if (err < 0)
-				goto out;
-		}
-		m->msg_name = address;
-	} else
-		m->msg_name = NULL;
-
-	err = -EFAULT;
-	size = m->msg_iovlen * sizeof(struct iovec32);
-	if (copy_from_user(iov, m->msg_iov, size))
-		goto out;
-	m->msg_iov = iov;
-
-	err = 0;
-	iov32 = (struct iovec32 *)iov;
-	for (ct = m->msg_iovlen; ct-- > 0; ) {
-		iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
-		iov[ct].iov_base = (void *) A(iov32[ct].iov_base);
-		err += iov[ct].iov_len;
-	}
-out:
-	return err;
-}
-
-static void
-put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data,
-			cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void
-scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32))
-		/ sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm);
-	     i < fdmax;
-	     i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		current->files->fd[new_fd] = fp[i];
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/*
- * In these cases we (currently) can just copy to data over verbatim because all CMSGs
- * created by the kernel have well defined types which have the same layout in both the
- * 32-bit and 64-bit API.  One must add some special cased conversions here if we start
- * sending control messages with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void
-cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-	long err;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if (workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while (((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/*
-		 * UCMSG is the 64-bit format CMSG entry in user-space.  KCMSG32 is within
-		 * the kernel space temporary buffer we use to convert into a 32-bit style
-		 * CMSG.
-		 */
-		err = get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		err |= get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		err |= get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-		if (err)
-			goto fail2;
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	if (copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz))
-		goto fail2;
-
-	kmsg->msg_control = (struct cmsghdr *) (((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-	kfree(workbuf);
-	return;
-
-  fail2:
-	kfree(workbuf);
-  fail:
-	/*
-	 * If we leave the 64-bit format CMSG chunks in there, the application could get
-	 * confused and crash.  So to ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain -
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-/*
- *	BSD sendmsg interface
- */
-
-int
-sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */
-	unsigned char *ctl_buf = ctl;
-	struct msghdr msg_sys;
-	int err, iov_size, total_len;
-	size_t ctl_len;
-
-	err = -EFAULT;
-	if (get_msghdr32(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	/* do not move before msg_sys is valid */
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/* This will also move the address data into kernel space */
-	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out_freeiov;
-	total_len = err;
-
-	err = -ENOBUFS;
-
-	if (msg_sys.msg_controllen > INT_MAX)
-		goto out_freeiov;
-	if (msg_sys.msg_controllen) {
-		ctl_len = sizeof(ctl);
-		err = get_cmsghdr32(&msg_sys, ctl_buf, sock->sk, &ctl_len);
-		if (err)
-			goto out_freeiov;
-		ctl_buf = msg_sys.msg_control;
-	}
-	msg_sys.msg_flags = flags;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		msg_sys.msg_flags |= MSG_DONTWAIT;
-	err = sock_sendmsg(sock, &msg_sys, total_len);
-
-	if (ctl_buf != ctl)
-		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:
-	return err;
-}
-
-/*
- *	BSD recvmsg interface
- */
-
-int
-sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
-{
-	struct socket *sock;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov=iovstack;
-	struct msghdr msg_sys;
-	unsigned long cmsg_ptr;
-	int err, iov_size, total_len, len;
-
-	/* kernel mode address */
-	char addr[MAX_SOCK_ADDR];
-
-	/* user mode address pointers */
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-
-	err = -EFAULT;
-	if (get_msghdr32(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/*
-	 *	Save the user-mode address (verify_iovec will change the
-	 *	kernel msghdr to use the kernel address space)
-	 */
-
-	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out_freeiov;
-	total_len=err;
-
-	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		flags |= MSG_DONTWAIT;
-
-	/* XXX This code needs massive updating... -DaveM */
-	lock_kernel();
-	{
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &msg_sys;
-		si->size = total_len;
-		si->flags = flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len,
-					 flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if (err < 0)
-			goto out_unlock_freeiov;
-
-		len = err;
-		if (!msg_sys.msg_control) {
-			if (sock->passcred || si->scm->fp)
-				msg_sys.msg_flags |= MSG_CTRUNC;
-			if (si->scm->fp)
-				__scm_destroy(si->scm);
-		} else {
-			/*
-			 * If recvmsg processing itself placed some control messages into
-			 * user space, it's is using 64-bit CMSG processing, so we need to
-			 * fix it up before we tack on more stuff.
-			 */
-			if ((unsigned long) msg_sys.msg_control != cmsg_ptr)
-				cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr);
-
-			/* Wheee... */
-			if (sock->passcred)
-				put_cmsg32(&msg_sys, SOL_SOCKET, SCM_CREDENTIALS,
-					   sizeof(si->scm->creds),
-					   &si->scm->creds);
-			if (si->scm->fp != NULL)
-				scm_detach_fds32(&msg_sys, si->scm);
-		}
-	}
-	unlock_kernel();
-
-	if (uaddr != NULL) {
-		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
-		if (err < 0)
-			goto out_freeiov;
-	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
-	if (err)
-		goto out_freeiov;
-	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,
-							 &msg->msg_controllen);
-	if (err)
-		goto out_freeiov;
-	err = len;
-
-  out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-  out_put:
-	sockfd_put(sock);
-  out:
-	return err;
-
-  out_unlock_freeiov:
-	goto out_freeiov;
-}
-
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(u32))
-static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-				    AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-				    AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
-				  int addrlen);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
-				 int *upeer_addrlen);
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
-				   unsigned flags, u32 addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
-				     unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				       u32 optval, u32 optlen);
-
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol,
-				     int usockvec[2]);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_listen(int fd, int backlog);
-
-asmlinkage long
-sys32_socketcall (int call, u32 *args)
-{
-	int ret;
-	u32 a[6];
-	u32 a0,a1;
-
-	if (call<SYS_SOCKET||call>SYS_RECVMSG)
-		return -EINVAL;
-	if (copy_from_user(a, args, nas[call]))
-		return -EFAULT;
-	a0=a[0];
-	a1=a[1];
-
-	switch(call)
-	{
-		case SYS_SOCKET:
-			ret = sys_socket(a0, a1, a[2]);
-			break;
-		case SYS_BIND:
-			ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_CONNECT:
-			ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_LISTEN:
-			ret = sys_listen(a0, a1);
-			break;
-		case SYS_ACCEPT:
-			ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
-			break;
-		case SYS_GETSOCKNAME:
-			ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
-			break;
-		case SYS_GETPEERNAME:
-			ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
-			break;
-		case SYS_SOCKETPAIR:
-			ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
-			break;
-		case SYS_SEND:
-			ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_SENDTO:
-			ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_RECV:
-			ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_RECVFROM:
-			ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_SHUTDOWN:
-			ret = sys_shutdown(a0,a1);
-			break;
-		case SYS_SETSOCKOPT:
-			ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
-					      a[4]);
-			break;
-		case SYS_GETSOCKOPT:
-			ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
-			break;
-		case SYS_SENDMSG:
-			ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]);
-			break;
-		case SYS_RECVMSG:
-			ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]);
-			break;
-		default:
-			ret = EINVAL;
-			break;
-	}
-	return ret;
-}
-
-/*
  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
  *
  * This is really horribly ugly.
@@ -3151,6 +2455,7 @@
 asmlinkage long
 sys32_sysctl (struct sysctl32 *args)
 {
+#ifdef CONFIG_SYSCTL
 	struct sysctl32 a32;
 	mm_segment_t old_fs = get_fs ();
 	void *oldvalp, *newvalp;
@@ -3188,6 +2493,9 @@
 		return -EFAULT;
 
 	return ret;
+#else
+	return -ENOSYS;
+#endif
 }
 
 asmlinkage long
@@ -3433,8 +2741,12 @@
 	u32 bufferram;
 	u32 totalswap;
 	u32 freeswap;
-	unsigned short procs;
-	char _f[22];
+	u16 procs;
+	u16 pad;
+	u32 totalhigh;
+	u32 freehigh;
+	u32 mem_unit;
+	char _f[8];
 };
 
 asmlinkage long
@@ -3463,6 +2775,9 @@
 	err |= __put_user(s.totalswap, &info->totalswap);
 	err |= __put_user(s.freeswap, &info->freeswap);
 	err |= __put_user(s.procs, &info->procs);
+	err |= __put_user (s.totalhigh, &info->totalhigh);
+	err |= __put_user (s.freehigh, &info->freehigh);
+	err |= __put_user (s.mem_unit, &info->mem_unit);
 	if (err)
 		return -EFAULT;
 	return ret;
diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
--- a/arch/ia64/kernel/Makefile	Thu Feb  6 22:38:03 2003
+++ b/arch/ia64/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y	:= head.o init_task.o
 
 obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o \
 	 irq.o irq_ia64.o irq_lsapic.o ivt.o \
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Tue Feb  4 17:06:06 2003
+++ b/arch/ia64/kernel/acpi.c	Thu Mar  6 22:21:39 2003
@@ -55,6 +55,7 @@
 asm (".weak iosapic_override_isa_irq");
 asm (".weak iosapic_register_platform_intr");
 asm (".weak iosapic_init");
+asm (".weak iosapic_system_init");
 asm (".weak iosapic_version");
 
 void (*pm_idle) (void);
@@ -182,7 +183,9 @@
 #define ACPI_MAX_PLATFORM_INTERRUPTS	256
 
 /* Array to record platform interrupt vectors for generic interrupt routing. */
-int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 };
+int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = {
+	[0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1
+};
 
 enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
 
@@ -291,40 +294,6 @@
 
 
 static int __init
-acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address)
-{
-	struct acpi_table_iosapic *iosapic;
-	int ver;
-	int max_pin;
-	char *p;
-	char *end;
-
-	if (!gsi_base || !iosapic_address)
-		return -ENODEV;
-
-	p = (char *) (acpi_madt + 1);
-	end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt));
-
-	while (p < end) {
-		if (*p == ACPI_MADT_IOSAPIC) {
-			iosapic = (struct acpi_table_iosapic *) p;
-
-			*gsi_base = iosapic->global_irq_base;
-			*iosapic_address = ioremap(iosapic->address, 0);
-
-			ver = iosapic_version(*iosapic_address);
-			max_pin = (ver >> 16) & 0xff;
-
-			if ((gsi - *gsi_base) <= max_pin)
-				return 0;	/* Found it! */
-		}
-		p += p[1];
-	}
-	return -ENODEV;
-}
-
-
-static int __init
 acpi_parse_iosapic (acpi_table_entry_header *header)
 {
 	struct acpi_table_iosapic *iosapic;
@@ -335,16 +304,9 @@
 
 	acpi_table_print_madt_entry(header);
 
-	if (iosapic_init) {
-#ifndef CONFIG_ITANIUM
-		/* PCAT_COMPAT flag indicates dual-8259 setup */
-		iosapic_init(iosapic->address, iosapic->global_irq_base,
-			     acpi_madt->flags.pcat_compat);
-#else
-		/* Firmware on old Itanium systems is broken */
-		iosapic_init(iosapic->address, iosapic->global_irq_base, 1);
-#endif
-	}
+	if (iosapic_init)
+		iosapic_init(iosapic->address, iosapic->global_irq_base);
+
 	return 0;
 }
 
@@ -354,8 +316,6 @@
 {
 	struct acpi_table_plat_int_src *plintsrc;
 	int vector;
-	u32 gsi_base;
-	char *iosapic_address;
 
 	plintsrc = (struct acpi_table_plat_int_src *) header;
 	if (!plintsrc)
@@ -368,11 +328,6 @@
 		return -ENODEV;
 	}
 
-	if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) {
-		printk(KERN_WARNING PREFIX "IOSAPIC not found\n");
-		return -ENODEV;
-	}
-
 	/*
 	 * Get vector assignment for this interrupt, set attributes,
 	 * and program the IOSAPIC routing table.
@@ -382,10 +337,8 @@
 						plintsrc->iosapic_vector,
 						plintsrc->eid,
 						plintsrc->id,
-						(plintsrc->flags.polarity == 1) ? 1 : 0,
-						(plintsrc->flags.trigger == 1) ? 1 : 0,
-						gsi_base,
-						iosapic_address);
+						(plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+						(plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 
 	platform_intr_list[plintsrc->type] = vector;
 	return 0;
@@ -408,8 +361,8 @@
 		return 0;
 
 	iosapic_override_isa_irq(p->bus_irq, p->global_irq,
-				 (p->flags.polarity == 1) ? 1 : 0,
-				 (p->flags.trigger == 1) ? 1 : 0);
+				 (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+				 (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 	return 0;
 }
 
@@ -439,7 +392,13 @@
 	acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
 
 	/* remember the value for reference after free_initmem() */
+#ifdef CONFIG_ITANIUM
+	has_8259 = 1; /* Firmware on old Itanium systems is broken */
+#else
 	has_8259 = acpi_madt->flags.pcat_compat;
+#endif
+	if (iosapic_system_init)
+		iosapic_system_init(has_8259);
 
 	/* Get base address of IPI Message Block */
 
@@ -571,7 +530,7 @@
 }
 
 void __init
-acpi_numa_arch_fixup(void)
+acpi_numa_arch_fixup (void)
 {
 	int i, j, node_from, node_to;
 
@@ -618,7 +577,7 @@
 			if (!pxm_bit_test(j))
 				continue;
 			node_to = pxm_to_nid_map[j];
-			node_distance(node_from, node_to) = 
+			node_distance(node_from, node_to) =
 				slit_table->entry[i*slit_table->localities + j];
 		}
 	}
@@ -639,8 +598,7 @@
 {
 	struct acpi_table_header *fadt_header;
 	struct fadt_descriptor_rev2 *fadt;
-	u32 sci_irq, gsi_base;
-	char *iosapic_address;
+	u32 sci_irq;
 
 	if (!phys_addr || !size)
 		return -EINVAL;
@@ -662,8 +620,7 @@
 	if (has_8259 && sci_irq < 16)
 		return 0;	/* legacy, no setup required */
 
-	if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address))
-		iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address);
+	iosapic_register_intr(sci_irq, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
 	return 0;
 }
 
@@ -717,8 +674,6 @@
 	if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
 	    (spcr->int_type == ACPI_SERIAL_INT_SAPIC))
 	{
-		u32 gsi_base;
-		char *iosapic_address;
 		int vector;
 
 		/* We have a UART in memory space with an SAPIC interrupt */
@@ -728,11 +683,7 @@
 			 (spcr->global_int[1] << 8)  |
 			 (spcr->global_int[0])  );
 
-		/* Which iosapic does this interrupt belong to? */
-
-		if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address))
-			vector = iosapic_register_intr(gsi, 1, 1,
-						       gsi_base, iosapic_address);
+		vector = iosapic_register_intr(gsi, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 	return 0;
 }
@@ -741,7 +692,7 @@
 
 
 int __init
-acpi_boot_init (char *cmdline)
+acpi_boot_init (void)
 {
 
 	/*
@@ -812,20 +763,20 @@
 	smp_boot_data.cpu_count = total_cpus;
 
 	smp_build_cpu_map();
-#ifdef CONFIG_NUMA
+# ifdef CONFIG_NUMA
 	build_cpu_to_node_map();
-#endif
+# endif
 #endif
 	/* Make boot-up look pretty */
 	printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
 	return 0;
 }
 
+/*
+ * PCI Interrupt Routing
+ */
 
-/* --------------------------------------------------------------------------
-                             PCI Interrupt Routing
-   -------------------------------------------------------------------------- */
-
+#ifdef CONFIG_PCI
 int __init
 acpi_get_prt (struct pci_vector_struct **vectors, int *count)
 {
@@ -866,6 +817,7 @@
 	*count = acpi_prt.count;
 	return 0;
 }
+#endif /* CONFIG_PCI */
 
 /* Assume IA64 always use I/O SAPIC */
 
@@ -888,12 +840,10 @@
 	return gsi_to_vector(irq);
 }
 
-int __init
+int
 acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
 {
 	int vector = 0;
-	u32 irq_base;
-	char *iosapic_address;
 
 	if (acpi_madt->flags.pcat_compat && (gsi < 16))
 		return isa_irq_to_vector(gsi);
@@ -901,12 +851,9 @@
 	if (!iosapic_register_intr)
 		return 0;
 
-	/* Find the IOSAPIC */
-	if (!acpi_find_iosapic(gsi, &irq_base, &iosapic_address)) {
-		/* Turn it on */
-		vector = iosapic_register_intr (gsi, polarity, trigger,
-						irq_base, iosapic_address);
-	}
+	/* Turn it on */
+	vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+			trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 	return vector;
 }
 
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Tue Jan 21 18:31:31 2003
+++ b/arch/ia64/kernel/entry.S	Thu Mar  6 14:56:33 2003
@@ -586,10 +586,21 @@
 	// work.need_resched etc. mustn't get changed by this CPU before it returns to
 	// user- or fsys-mode:
 (pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
+#ifdef CONFIG_PREEMPT
+	rsm psr.i				// disable interrupts
+	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+	;;
+(pKStk) ld4  r21=[r20]			// preempt_count ->r21
+	;;
+(pKStk)	cmp4.eq	p6,p0=r21,r0		// p6 <- preempt_count == 0
+	;;
+#else /* CONFIG_PREEMPT */
 (pUStk)	rsm psr.i
 	;;
 (pUStk)	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
 	;;
+#endif /* CONFIG_PREEMPT */
 .work_processed:
 (p6)	ld4 r18=[r17]				// load current_thread_info()->flags
 	adds r2=PT(R8)+16,r12
@@ -701,7 +712,7 @@
 	 * NOTE: alloc, loadrs, and cover can't be predicated.
 	 */
 (pNonSys) br.cond.dpnt dont_preserve_current_frame
-	cover				// add current frame into dirty partition
+	cover				// add current frame into dirty partition and set cr.ifs
 	;;
 	mov r19=ar.bsp			// get new backing store pointer
 	sub r16=r16,r18			// krbs = old bsp - size of dirty partition
@@ -727,7 +738,7 @@
 #	define Nregs	14
 #endif
 	alloc loc0=ar.pfs,2,Nregs-2,2,0
-	shr.u loc1=r18,9		// RNaTslots <= dirtySize / (64*8) + 1
+	shr.u loc1=r18,9		// RNaTslots <= floor(dirtySize / (64*8))
 	sub r17=r17,r18			// r17 = (physStackedSize + 8) - dirtySize
 	;;
 	mov ar.rsc=r19			// load ar.rsc to be used for "loadrs"
@@ -774,13 +785,13 @@
 	;;
 	mov loc3=0
 	mov loc4=0
-	mov loc9=0
 	mov loc5=0
 	mov loc6=0
+	mov loc7=0
 (pRecurse) br.call.sptk.many b6=rse_clear_invalid
 	;;
-	mov loc7=0
 	mov loc8=0
+	mov loc9=0
 	cmp.ne pReturn,p0=r0,in1	// if recursion count != 0, we need to do a br.ret
 	mov loc10=0
 	mov loc11=0
@@ -810,15 +821,27 @@
 .work_pending:
 	tbit.z p6,p0=r18,TIF_NEED_RESCHED		// current_thread_info()->need_resched==0?
 (p6)	br.cond.sptk.few .notify
+#ifdef CONFIG_PREEMPT
+(pKStk)	dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
+	;;
+(pKStk) st4 [r20]=r21
+	ssm  psr.i		// enable interrupts
+#endif
+
 #if __GNUC__ < 3
 	br.call.spnt.many rp=invoke_schedule
 #else
 	br.call.spnt.many rp=schedule
 #endif
 .ret9:	cmp.eq p6,p0=r0,r0				// p6 <- 1
-	rsm psr.i
+	rsm psr.i		// disable interrupts
 	;;
 	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+#if CONFIG_PREEMPT
+(pKStk)	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+	;;
+(pKStk)	st4 [r20]=r0		// preempt_count() <- 0
+#endif
 	br.cond.sptk.many .work_processed		// re-check
 
 .notify:
@@ -904,13 +927,14 @@
 	mov r9=ar.unat
 	mov loc0=rp				// save return address
 	mov out0=0				// there is no "oldset"
-	adds out1=0,sp				// out1=&sigscratch
+	adds out1=8,sp				// out1=&sigscratch->ar_pfs
 (pSys)	mov out2=1				// out2==1 => we're in a syscall
 	;;
 (pNonSys) mov out2=0				// out2==0 => not a syscall
 	.fframe 16
 	.spillpsp ar.unat, 16			// (note that offset is relative to psp+0x10!)
 	st8 [sp]=r9,-16				// allocate space for ar.unat and save it
+	st8 [out1]=loc1,-8			// save ar.pfs, out1=&sigscratch
 	.body
 	br.call.sptk.many rp=do_notify_resume_user
 .ret15:	.restore sp
@@ -931,11 +955,12 @@
 	mov loc0=rp				// save return address
 	mov out0=in0				// mask
 	mov out1=in1				// sigsetsize
-	adds out2=0,sp				// out2=&sigscratch
+	adds out2=8,sp				// out2=&sigscratch->ar_pfs
 	;;
 	.fframe 16
 	.spillpsp ar.unat, 16			// (note that offset is relative to psp+0x10!)
 	st8 [sp]=r9,-16				// allocate space for ar.unat and save it
+	st8 [out2]=loc1,-8			// save ar.pfs, out2=&sigscratch
 	.body
 	br.call.sptk.many rp=ia64_rt_sigsuspend
 .ret17:	.restore sp
@@ -1242,7 +1267,7 @@
 	data8 sys_sched_setaffinity
 	data8 sys_sched_getaffinity
 	data8 sys_set_tid_address
-	data8 ia64_ni_syscall
+	data8 sys_fadvise64
 	data8 ia64_ni_syscall 			// 1235
 	data8 sys_exit_group
 	data8 sys_lookup_dcookie
@@ -1256,15 +1281,15 @@
 	data8 sys_epoll_wait			// 1245
 	data8 sys_restart_syscall
 	data8 sys_semtimedop
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall			// 1250
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall			// 1255
-	data8 ia64_ni_syscall
+	data8 sys_timer_create
+	data8 sys_timer_settime
+	data8 sys_timer_gettime			// 1250
+	data8 sys_timer_getoverrun
+	data8 sys_timer_delete
+	data8 sys_clock_settime
+	data8 sys_clock_gettime
+	data8 sys_clock_getres			// 1255
+	data8 sys_clock_nanosleep
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
--- a/arch/ia64/kernel/fsys.S	Wed Jan 29 22:16:51 2003
+++ b/arch/ia64/kernel/fsys.S	Fri Feb 28 16:51:10 2003
@@ -3,11 +3,16 @@
  *
  * Copyright (C) 2003 Hewlett-Packard Co
  * 	David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 18-Feb-03 louisk	Implement fsys_gettimeofday().
+ * 28-Feb-03 davidm	Fixed several bugs in fsys_gettimeofday().  Tuned it some more,
+ *			probably broke it along the way... ;-)
  */
 
 #include <asm/asmmacro.h>
 #include <asm/errno.h>
 #include <asm/offsets.h>
+#include <asm/percpu.h>
 #include <asm/thread_info.h>
 
 /*
@@ -123,6 +128,183 @@
 	br.ret.sptk.many b6
 END(fsys_set_tid_address)
 
+/*
+ * Note 1: This routine uses floating-point registers, but only with registers that
+ *	   operate on integers.  Because of that, we don't need to set ar.fpsr to the
+ *	   kernel default value.
+ *
+ * Note 2: For now, we will assume that all CPUs run at the same clock-frequency.
+ *	   If that wasn't the case, we would have to disable preemption (e.g.,
+ *	   by disabling interrupts) between reading the ITC and reading
+ *	   local_cpu_data->nsec_per_cyc.
+ *
+ * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector,
+ *	   we ought to either skip the ITC-based interpolation or run an ntp-like
+ *	   daemon to keep the ITCs from drifting too far apart.
+ */
+ENTRY(fsys_gettimeofday)
+	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
+	movl r3=THIS_CPU(cpu_info)
+
+	mov.m r31=ar.itc		// put time stamp into r31 (ITC) == now		(35 cyc)
+	movl r19=xtime			// xtime is a timespec struct
+	;;
+
+#ifdef CONFIG_SMP
+	movl r10=__per_cpu_offset
+	;;
+	ld8 r10=[r10]			// r10 <- __per_cpu_offset[0]
+	movl r21=cpu_info__per_cpu
+	;;
+	add r10=r21, r10		// r10 <- &cpu_data(time_keeper_id)
+#else
+	mov r10=r3
+#endif
+	ld4 r9=[r9]
+	movl r17=xtime_lock
+	;;
+
+	// r32, r33 should contain the 2 args of gettimeofday
+	adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10
+	mov r2=-1
+	tnat.nz p6,p7=r32		// guard against NaT args
+	;;
+
+	adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10
+(p7)	tnat.nz p6,p0=r33
+(p6)	br.cond.spnt.few .fail
+
+	adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3
+	movl r24=2361183241434822607	// for division hack (only for / 1000)
+	;;
+
+	ldf8 f7=[r10]			// f7 now contains itm_delta
+	setf.sig f11=r2
+	adds r10=8, r32
+
+	adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19	// r20 = &xtime->tv_nsec
+	movl r26=jiffies
+
+	setf.sig f9=r24			// f9 is used for division hack
+	movl r27=wall_jiffies
+
+	and r9=TIF_ALLWORK_MASK,r9
+	movl r25=last_nsec_offset
+	;;
+
+	/*
+	 * Verify that we have permission to write to struct timeval.  Note:
+	 * Another thread might unmap the mapping before we actually get
+	 * to store the result.  That's OK as long as the stores are also
+	 * protect by EX().
+	 */
+EX(.fail, probe.w.fault r32, 3)		// this must come _after_ NaT-check
+EX(.fail, probe.w.fault r10, 3)		// this must come _after_ NaT-check
+	nop 0
+
+	ldf8 f10=[r8]			// f10 <- local_cpu_data->nsec_per_cyc value
+	cmp.ne p8, p0=0, r9
+(p8)	br.spnt.many fsys_fallback_syscall
+	;;
+.retry:	// *** seq = read_seqbegin(&xtime_lock); ***
+	ld4.acq r23=[r17]		// since &xtime_lock == &xtime_lock->sequence
+	ld8 r14=[r25]			// r14 (old) = last_nsec_offset
+
+	ld8 r28=[r26]			// r28 = jiffies
+	ld8 r29=[r27]			// r29 = wall_jiffies
+	;;
+
+	ldf8 f8=[r21]			// f8 now contains itm_next
+	sub r28=r29, r28, 1		// r28 now contains "-(lost + 1)"
+	tbit.nz p9, p10=r23, 0		// p9 <- is_odd(r23), p10 <- is_even(r23)
+	;;
+
+	ld8 r2=[r19]			// r2 = sec = xtime.tv_sec
+	ld8 r29=[r20]			// r29 = nsec = xtime.tv_nsec
+
+	setf.sig f6=r28			// f6 <- -(lost + 1)				(6 cyc)
+	;;
+
+	mf
+	xma.l f8=f6, f7, f8	// f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next	(5 cyc)
+	nop 0
+
+	setf.sig f12=r31		// f12 <- ITC					(6 cyc)
+	// *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; ***
+	ld4 r24=[r17]			// r24 = xtime_lock->sequence (re-read)
+	nop 0
+	;;
+
+	mov r31=ar.itc			// re-read ITC in case we .retry		(35 cyc)
+	xma.l f8=f11, f8, f12	// f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick)
+	nop 0
+	;;
+
+	getf.sig r18=f8			// r18 <- (now - last_tick)
+	xmpy.l f8=f8, f10		// f8 <- elapsed_cycles*nsec_per_cyc (5 cyc)
+	add r3=r29, r14			// r3 = (nsec + old)
+	;;
+
+	cmp.lt p7, p8=r18, r0		// if now < last_tick, set p7 = 1, p8 = 0
+	getf.sig r18=f8			// r18 = elapsed_cycles*nsec_per_cyc		(6 cyc)
+	nop 0
+	;;
+
+(p10)	cmp.ne p9, p0=r23, r24		// if xtime_lock->sequence != seq, set p9
+	shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT	// r18 <- offset
+(p9)	br.spnt.many .retry
+	;;
+
+	mov ar.ccv=r14			// ar.ccv = old					(1 cyc)
+	cmp.leu p7, p8=r18, r14		// if (offset <= old), set p7 = 1, p8 = 0
+	;;
+
+(p8)	cmpxchg8.rel r24=[r25], r18, ar.ccv	// compare-and-exchange (atomic!)
+(p8)	add r3=r29, r18			// r3 = (nsec + offset)
+	;;
+	shr.u r3=r3, 3			// initiate dividing r3 by 1000
+	;;
+	setf.sig f8=r3			//						(6 cyc)
+	mov r10=1000000			// r10 = 1000000
+	;;
+(p8)	cmp.ne.unc p9, p0=r24, r14
+	xmpy.hu f6=f8, f9		//						(5 cyc)
+(p9)	br.spnt.many .retry
+	;;
+
+	getf.sig r3=f6			//						(6 cyc)
+	;;
+	shr.u r3=r3, 4			// end of division, r3 is divided by 1000 (=usec)
+	;;
+
+1:	cmp.geu p7, p0=r3, r10		// while (usec >= 1000000)
+	;;
+(p7)	sub r3=r3, r10			// usec -= 1000000
+(p7)	adds r2=1, r2			// ++sec
+(p7)	br.spnt.many 1b
+
+	// finally: r2 = sec, r3 = usec
+EX(.fail, st8 [r32]=r2)
+	adds r9=8, r32
+	mov r8=r0			// success
+	;;
+EX(.fail, st8 [r9]=r3)			// store them in the timeval struct
+	mov r10=0
+	MCKINLEY_E9_WORKAROUND
+	br.ret.sptk.many b6		// return to caller
+	/*
+	 * Note: We are NOT clearing the scratch registers here.  Since the only things
+	 *	 in those registers are time-related variables and some addresses (which
+	 *	 can be obtained from System.map), none of this should be security-sensitive
+	 *	 and we should be fine.
+	 */
+
+.fail:	adds r8=EINVAL, r0		// r8 = EINVAL
+	adds r10=-1, r0			// r10 = -1
+	MCKINLEY_E9_WORKAROUND
+	br.ret.spnt.many b6		// return with r8 set to EINVAL
+END(fsys_gettimeofday)
+
 	.rodata
 	.align 8
 	.globl fsyscall_table
@@ -190,7 +372,7 @@
 	data8 fsys_fallback_syscall	// setrlimit
 	data8 fsys_fallback_syscall	// getrlimit		// 1085
 	data8 fsys_fallback_syscall	// getrusage
-	data8 fsys_fallback_syscall	// gettimeofday
+	data8 fsys_gettimeofday		// gettimeofday
 	data8 fsys_fallback_syscall	// settimeofday
 	data8 fsys_fallback_syscall	// select
 	data8 fsys_fallback_syscall	// poll			// 1090
diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
--- a/arch/ia64/kernel/gate.S	Fri Jan 17 19:18:54 2003
+++ b/arch/ia64/kernel/gate.S	Mon Feb 10 18:28:00 2003
@@ -145,11 +145,12 @@
 	 */
 
 #define SIGTRAMP_SAVES										\
-	.unwabi @svr4, 's'		// mark this as a sigtramp handler (saves scratch regs)	\
-	.savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF						\
-	.savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF						\
-	.savesp pr, PR_OFF+SIGCONTEXT_OFF							\
-	.savesp rp, RP_OFF+SIGCONTEXT_OFF							\
+	.unwabi @svr4, 's';	/* mark this as a sigtramp handler (saves scratch regs) */	\
+	.savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF;						\
+	.savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF;						\
+	.savesp pr, PR_OFF+SIGCONTEXT_OFF;     							\
+	.savesp rp, RP_OFF+SIGCONTEXT_OFF;							\
+	.savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF;							\
 	.vframesp SP_OFF+SIGCONTEXT_OFF
 
 GLOBAL_ENTRY(ia64_sigtramp)
@@ -173,9 +174,7 @@
 	.spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
 (p8)	br.cond.spnt setup_rbs		// yup -> (clobbers r14, r15, and r16)
 back_from_setup_rbs:
-
-	.spillreg ar.pfs, r8
-	alloc r8=ar.pfs,0,0,3,0		// get CFM0, EC0, and CPL0 into r8
+	alloc r8=ar.pfs,0,0,3,0
 	ld8 out0=[base0],16		// load arg0 (signum)
 	adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
 	;;
@@ -184,17 +183,12 @@
 	;;
 	ld8 out2=[base0]		// load arg2 (sigcontextp)
 	ld8 gp=[r17]			// get signal handler's global pointer
-
 	adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
 	;;
 	.spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
-	st8 [base0]=r9,(CFM_OFF-BSP_OFF)	// save sc_ar_bsp
-	dep r8=0,r8,38,26			// clear EC0, CPL0 and reserved bits
-	adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
-	;;
-	.spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF
-	st8 [base0]=r8				// save CFM0
+	st8 [base0]=r9			// save sc_ar_bsp
 	adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
+	adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
 	;;
 	stf.spill [base0]=f6,32
 	stf.spill [base1]=f7,32
@@ -217,7 +211,6 @@
 	ld8 r15=[base0],(CFM_OFF-BSP_OFF)	// fetch sc_ar_bsp and advance to CFM_OFF
 	mov r14=ar.bsp
 	;;
-	ld8 r8=[base0]				// restore (perhaps modified) CFM0, EC0, and CPL0
 	cmp.ne p8,p0=r14,r15			// do we need to restore the rbs?
 (p8)	br.cond.spnt restore_rbs		// yup -> (clobbers r14-r18, f6 & f7)
 	;;
diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
--- a/arch/ia64/kernel/init_task.c	Tue Sep 17 23:22:09 2002
+++ b/arch/ia64/kernel/init_task.c	Wed Feb 12 00:11:32 2003
@@ -17,6 +17,7 @@
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	Tue Feb  4 17:06:08 2003
+++ b/arch/ia64/kernel/iosapic.c	Wed Feb 19 14:07:24 2003
@@ -29,6 +29,9 @@
  * 02/07/29	T. Kochi	Allocate interrupt vectors dynamically
  * 02/08/04	T. Kochi	Cleaned up terminology (irq, global system interrupt, vector, etc.)
  * 02/09/20	D. Mosberger	Simplified by taking advantage of ACPI's pci_irq code.
+ * 03/02/19	B. Helgaas	Make pcat_compat system-wide, not per-IOSAPIC.
+ *				Remove iosapic_address & gsi_base from external interfaces.
+ *				Rationalize __init/__devinit attributes.
  */
 /*
  * Here is what the interrupt logic between a PCI device and the kernel looks like:
@@ -111,16 +114,17 @@
 	char		*addr;		/* base address of IOSAPIC */
 	unsigned int 	gsi_base;	/* first GSI assigned to this IOSAPIC */
 	unsigned short 	num_rte;	/* number of RTE in this IOSAPIC */
-	unsigned char	pcat_compat;	/* 8259 compatibility flag */
-} iosapic_lists[256] __devinitdata;
+} iosapic_lists[256];
 
-static int num_iosapic = 0;
+static int num_iosapic;
+
+static unsigned char pcat_compat __initdata;	/* 8259 compatibility flag */
 
 
 /*
  * Find an IOSAPIC associated with a GSI
  */
-static inline int __devinit
+static inline int
 find_iosapic (unsigned int gsi)
 {
 	int i;
@@ -423,7 +427,7 @@
  * if the given vector is already owned by other,
  *  assign a new vector for the other and make the vector available
  */
-static void
+static void __init
 iosapic_reassign_vector (int vector)
 {
 	int new_vector;
@@ -443,50 +447,36 @@
 
 static void
 register_intr (unsigned int gsi, int vector, unsigned char delivery,
-	       unsigned long polarity, unsigned long edge_triggered,
-	       unsigned int gsi_base, char *iosapic_address)
+	       unsigned long polarity, unsigned long trigger)
 {
 	irq_desc_t *idesc;
 	struct hw_interrupt_type *irq_type;
 	int rte_index;
+	int index;
+	unsigned long gsi_base;
+	char *iosapic_address;
+
+	index = find_iosapic(gsi);
+	if (index < 0) {
+		printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi);
+		return;
+	}
+
+	iosapic_address = iosapic_lists[index].addr;
+	gsi_base = iosapic_lists[index].gsi_base;
 
 	rte_index = gsi - gsi_base;
 	iosapic_intr_info[vector].rte_index = rte_index;
-	iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+	iosapic_intr_info[vector].polarity = polarity;
 	iosapic_intr_info[vector].dmode    = delivery;
+	iosapic_intr_info[vector].addr     = iosapic_address;
+	iosapic_intr_info[vector].gsi_base = gsi_base;
+	iosapic_intr_info[vector].trigger  = trigger;
 
-	/*
-	 * In override, it may not provide addr/gsi_base.  GSI is enough to
-	 * locate iosapic addr, gsi_base and rte_index by examining
-	 * gsi_base and num_rte of registered iosapics (tbd)
-	 */
-#ifndef	OVERRIDE_DEBUG
-	if (iosapic_address) {
-		iosapic_intr_info[vector].addr = iosapic_address;
-		iosapic_intr_info[vector].gsi_base = gsi_base;
-	}
-#else
-	if (iosapic_address) {
-		if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address))
-			printk(KERN_WARNING "warning: register_intr: diff IOSAPIC ADDRESS for "
-			       "GSI 0x%x, vector %d\n", gsi, vector);
-		iosapic_intr_info[vector].addr = iosapic_address;
-		if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) {
-			printk(KERN_WARNING "warning: register_intr: diff GSI base 0x%x for "
-			       "GSI 0x%x, vector %d\n", gsi_base, gsi, vector);
-		}
-		iosapic_intr_info[vector].gsi_base = gsi_base;
-	} else if (!iosapic_intr_info[vector].addr)
-		printk(KERN_WARNING "warning: register_intr: invalid override for GSI 0x%x, "
-		       "vector %d\n", gsi, vector);
-#endif
-	if (edge_triggered) {
-		iosapic_intr_info[vector].trigger = IOSAPIC_EDGE;
+	if (trigger == IOSAPIC_EDGE)
 		irq_type = &irq_type_iosapic_edge;
-	} else {
-		iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL;
+	else
 		irq_type = &irq_type_iosapic_level;
-	}
 
 	idesc = irq_desc(vector);
 	if (idesc->handler != irq_type) {
@@ -504,8 +494,7 @@
  */
 int
 iosapic_register_intr (unsigned int gsi,
-		       unsigned long polarity, unsigned long edge_triggered,
-		       unsigned int gsi_base, char *iosapic_address)
+		       unsigned long polarity, unsigned long trigger)
 {
 	int vector;
 	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
@@ -515,11 +504,11 @@
 		vector = ia64_alloc_vector();
 
 	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-		      polarity, edge_triggered, gsi_base, iosapic_address);
+		      polarity, trigger);
 
 	printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       gsi, (polarity ? "high" : "low"),
-	       (edge_triggered ? "edge" : "level"), dest, vector);
+	       gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
@@ -530,11 +519,10 @@
  * ACPI calls this when it finds an entry for a platform interrupt.
  * Note that the irq_base and IOSAPIC address must be set in iosapic_init().
  */
-int
+int __init
 iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
 				int iosapic_vector, u16 eid, u16 id,
-				unsigned long polarity, unsigned long edge_triggered,
-				unsigned int gsi_base, char *iosapic_address)
+				unsigned long polarity, unsigned long trigger)
 {
 	unsigned char delivery;
 	int vector;
@@ -564,11 +552,11 @@
 	}
 
 	register_intr(gsi, vector, delivery, polarity,
-		      edge_triggered, gsi_base, iosapic_address);
+		      trigger);
 
 	printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       int_type, gsi, (polarity ? "high" : "low"),
-	       (edge_triggered ? "edge" : "level"), dest, vector);
+	       int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
@@ -580,54 +568,36 @@
  * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
  * Note that the gsi_base and IOSAPIC address must be set in iosapic_init().
  */
-void
+void __init
 iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
 			  unsigned long polarity,
-			  unsigned long edge_triggered)
+			  unsigned long trigger)
 {
-	int index, vector;
-	unsigned int gsi_base;
-	char *addr;
+	int vector;
 	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
 
-	index = find_iosapic(gsi);
-
-	if (index < 0) {
-		printk(KERN_ERR "ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n",
-		       isa_irq, gsi);
-		return;
-	}
-
 	vector = isa_irq_to_vector(isa_irq);
-	addr = iosapic_lists[index].addr;
-	gsi_base = iosapic_lists[index].gsi_base;
 
-	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered,
-		      gsi_base, addr);
+	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
 
 	DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
 	    isa_irq, gsi,
-	    polarity ? "high" : "low", edge_triggered ? "edge" : "level",
+	    polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level",
 	    dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
 }
 
-void __devinit
-iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat)
+void __init
+iosapic_system_init (int system_pcat_compat)
 {
-	int num_rte, vector;
-	unsigned int isa_irq, ver;
-	char *addr;
-	static int first_time = 1;
+	int vector;
 
-	if (first_time) {
-		first_time = 0;
-		for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
-			iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
-	}
+	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
+		iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
 
+	pcat_compat = system_pcat_compat;
 	if (pcat_compat) {
 		/*
 		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
@@ -637,6 +607,14 @@
 		outb(0xff, 0xA1);
 		outb(0xff, 0x21);
 	}
+}
+
+void __init
+iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
+{
+	int num_rte;
+	unsigned int isa_irq, ver;
+	char *addr;
 
 	addr = ioremap(phys_addr, 0);
 	ver = iosapic_version(addr);
@@ -649,7 +627,6 @@
 	num_rte = ((ver >> 16) & 0xff) + 1;
 
 	iosapic_lists[num_iosapic].addr = addr;
-	iosapic_lists[num_iosapic].pcat_compat = pcat_compat;
 	iosapic_lists[num_iosapic].gsi_base = gsi_base;
 	iosapic_lists[num_iosapic].num_rte = num_rte;
 	num_iosapic++;
@@ -658,30 +635,18 @@
 	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
 
 	if ((gsi_base == 0) && pcat_compat) {
-		unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
 
 		/*
 		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may
 		 * get reprogrammed later on with data from the ACPI Interrupt Source
 		 * Override table.
 		 */
-		for (isa_irq = 0; isa_irq < 16; ++isa_irq) {
-			vector = isa_irq_to_vector(isa_irq);
-
-			register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY,
-				     /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */
-				     1, 1, gsi_base, addr);
-
-			DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n",
-			    isa_irq, isa_irq, dest, vector);
-
-			/* program the IOSAPIC routing table: */
-			set_rte(vector, dest);
-		}
+		for (isa_irq = 0; isa_irq < 16; ++isa_irq)
+			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 }
 
-static void
+static void __init
 fixup_vector (int vector, unsigned int gsi, const char *pci_id)
 {
 	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
@@ -731,10 +696,9 @@
 {
 	struct acpi_prt_entry *entry;
 	struct list_head *node;
-	unsigned int gsi, gsi_base;
-	int index, vector, pcat_compat;
+	unsigned int gsi;
+	int vector;
 	char pci_id[16];
-	char *addr;
 
 	list_for_each(node, &acpi_prt.entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
@@ -748,23 +712,13 @@
 		vector = gsi_to_vector(gsi);
 		if (vector < 0) {
 			/* allocate a vector for this interrupt line */
-			index = find_iosapic(gsi);
-
-			if (index < 0) {
-				printk(KERN_WARNING "IOSAPIC: GSI 0x%x has no IOSAPIC!\n", gsi);
-				continue;
-			}
-			addr = iosapic_lists[index].addr;
-			gsi_base = iosapic_lists[index].gsi_base;
-			pcat_compat = iosapic_lists[index].pcat_compat;
-
 			if (pcat_compat && (gsi < 16))
 				vector = isa_irq_to_vector(gsi);
 			else
 				/* new GSI; allocate a vector for it */
 				vector = ia64_alloc_vector();
 
-			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 0, 0, gsi_base, addr);
+			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
 		}
 		snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
 			 entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin);
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	Tue Feb 25 01:38:25 2003
+++ b/arch/ia64/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -154,6 +154,7 @@
 	int i, j;
 	struct irqaction * action;
 	irq_desc_t *idesc;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -163,9 +164,10 @@
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		idesc = irq_desc(i);
+		spin_lock_irqsave(&idesc->lock, flags);
 		action = idesc->action;
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -176,10 +178,12 @@
 #endif
 		seq_printf(p, " %14s", idesc->handler->typename);
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+		
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&idesc->lock, flags);
 	}
 	seq_puts(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
@@ -340,12 +344,14 @@
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int cpu = smp_processor_id();
+	int cpu;
 	irq_desc_t *desc = irq_desc(irq);
 	struct irqaction * action;
 	unsigned int status;
 
 	irq_enter();
+	cpu = smp_processor_id();
+
 	kstat_cpu(cpu).irqs[irq]++;
 
 	if (desc->status & IRQ_PER_CPU) {
diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
--- a/arch/ia64/kernel/ivt.S	Wed Jan 15 16:26:26 2003
+++ b/arch/ia64/kernel/ivt.S	Sat Feb 15 04:39:48 2003
@@ -848,7 +848,7 @@
 	alloc r15=ar.pfs,0,0,6,0	// must first in an insn group
 	;;
 	ld4 r8=[r14],8		// r8 == eax (syscall number)
-	mov r15=230		// number of entries in ia32 system call table
+	mov r15=250		// number of entries in ia32 system call table
 	;;
 	cmp.ltu.unc p6,p7=r8,r15
 	ld4 out1=[r14],8	// r9 == ecx
diff -Nru a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
--- a/arch/ia64/kernel/machvec.c	Tue Feb  4 17:06:10 2003
+++ b/arch/ia64/kernel/machvec.c	Thu Feb 20 02:35:33 2003
@@ -10,19 +10,6 @@
 
 struct ia64_machine_vector ia64_mv;
 
-/*
- * Most platforms use this routine for mapping page frame addresses into a memory map
- * index.
- *
- * Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if
- * X is outside the identity mapped kernel space.
- */
-unsigned long
-map_nr_dense (unsigned long addr)
-{
-	return (addr - PAGE_OFFSET) >> PAGE_SHIFT;
-}
-
 static struct ia64_machine_vector *
 lookup_machvec (const char *name)
 {
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	Tue Feb  4 17:06:10 2003
+++ b/arch/ia64/kernel/mca.c	Tue Mar  4 18:33:56 2003
@@ -825,7 +825,7 @@
 	plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);
 	proc_ptr = &plog_ptr->proc_err;
 
-	ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area);
+	ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area);
 
 	/* Clear the INIT SAL logs now that they have been saved in the OS buffer */
 	ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
@@ -1620,7 +1620,7 @@
 	 *  absent. Also, current implementations only allocate space for number of
 	 *  elements used.  So we walk the data pointer from here on.
 	 */
-	p_data = &slpi->cache_check_info[0];
+	p_data = &slpi->info[0];
 
 	/* Print the cache check information if any*/
 	for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
--- a/arch/ia64/kernel/palinfo.c	Tue Feb  4 17:06:11 2003
+++ b/arch/ia64/kernel/palinfo.c	Thu Feb 13 05:43:47 2003
@@ -341,11 +341,11 @@
 		return 0;
 	}
 
-	p += sprintf(p, "\nTLB walker                     : %s implemented\n" \
+	p += sprintf(p, "\nTLB walker                     : %simplemented\n" \
 			"Number of DTR                  : %d\n" \
 			"Number of ITR                  : %d\n" \
 			"TLB insertable page sizes      : ",
-			vm_info_1.pal_vm_info_1_s.vw ? "\b":"not",
+			vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
 			vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
 			vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
 
@@ -894,10 +894,12 @@
 	 * in SMP mode, we may need to call another CPU to get correct
 	 * information. PAL, by definition, is processor specific
 	 */
-	if (f->req_cpu == smp_processor_id())
+	if (f->req_cpu == get_cpu())
 		len = (*palinfo_entries[f->func_id].proc_read)(page);
 	else
 		len = palinfo_handle_smp(f, page);
+
+	put_cpu();
 
 	if (len <= off+count) *eof = 1;
 
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	Tue Feb 25 09:44:04 2003
+++ b/arch/ia64/kernel/perfmon.c	Thu Mar  6 11:40:52 2003
@@ -8,7 +8,7 @@
  * Modifications by Stephane Eranian, Hewlett-Packard Co.
  * Modifications by David Mosberger-Tang, Hewlett-Packard Co.
  *
- * Copyright (C) 1999-2002  Hewlett Packard Co
+ * Copyright (C) 1999-2003  Hewlett Packard Co
  *               Stephane Eranian <eranian@hpl.hp.com>
  *               David Mosberger-Tang <davidm@hpl.hp.com>
  */
@@ -230,9 +230,15 @@
 	unsigned int protected:1;	/* allow access to creator of context only */
 	unsigned int using_dbreg:1;	/* using range restrictions (debug registers) */
 	unsigned int excl_idle:1;	/* exclude idle task in system wide session */
-	unsigned int reserved:23;
+	unsigned int trap_reason:2;	/* reason for going into pfm_block_ovfl_reset() */
+	unsigned int reserved:21;
 } pfm_context_flags_t;
 
+#define PFM_TRAP_REASON_NONE		0x0	/* default value */
+#define PFM_TRAP_REASON_BLOCKSIG	0x1	/* we need to block on overflow and signal user */
+#define PFM_TRAP_REASON_SIG		0x2	/* we simply need to signal user */
+#define PFM_TRAP_REASON_RESET		0x3	/* we need to reset PMDs */
+
 /*
  * perfmon context: encapsulates all the state of a monitoring session
  * XXX: probably need to change layout
@@ -277,6 +283,7 @@
 #define ctx_fl_protected	ctx_flags.protected
 #define ctx_fl_using_dbreg	ctx_flags.using_dbreg
 #define ctx_fl_excl_idle	ctx_flags.excl_idle
+#define ctx_fl_trap_reason	ctx_flags.trap_reason
 
 /*
  * global information about all sessions
@@ -1225,6 +1232,8 @@
 	ctx->ctx_fl_system    = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
 	ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0;
 	ctx->ctx_fl_frozen    = 0;
+	ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
+
 	/*
 	 * setting this flag to 0 here means, that the creator or the task that the
 	 * context is being attached are granted access. Given that a context can only
@@ -1505,7 +1514,7 @@
 	unsigned long value, hw_value;
 	unsigned int cnum;
 	int i;
-	int ret = 0;
+	int ret = -EINVAL;
 
 	/* we don't quite support this right now */
 	if (task != current) return -EINVAL;
@@ -1514,10 +1523,10 @@
 	 * Cannot do anything before PMU is enabled 
 	 */
 	if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
+	preempt_disable();
 
 	/* XXX: ctx locking may be required here */
 
-	ret = -EINVAL;
 
 	for (i = 0; i < count; i++, req++) {
 
@@ -1591,10 +1600,12 @@
 				ctx->ctx_used_pmds[0],
 				ctx->ctx_soft_pmds[cnum].reset_pmds[0]));
 	}
-
+	preempt_enable();
 	return 0;
 
 abort_mission:
+	preempt_enable();
+
 	/*
 	 * for now, we have only one possibility for error
 	 */
@@ -1639,6 +1650,7 @@
 	DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid));
 
 	for (i = 0; i < count; i++, req++) {
+		int me;
 #if __GNUC__ < 3
 		foo = __get_user(cnum, &req->reg_num);
 		if (foo) return -EFAULT;
@@ -1666,13 +1678,16 @@
 		 * PMU state is still in the local live register due to lazy ctxsw.
 		 * If true, then we read directly from the registers.
 		 */
-		if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){
+		me = get_cpu();
+		if (atomic_read(&ctx->ctx_last_cpu) == me){
 			ia64_srlz_d();
 			val = ia64_get_pmd(cnum);
 			DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val));
 		} else {
 			val = th->pmd[cnum];
 		}
+
+
 		if (PMD_IS_COUNTING(cnum)) {
 			/*
 			 * XXX: need to check for overflow
@@ -1694,6 +1709,8 @@
 
 		PFM_REG_RETFLAG_SET(reg_flags, ret);
 
+		put_cpu();
+
 		DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n", 
 					cnum, ret, val, ia64_get_pmc(cnum)));
 
@@ -1831,6 +1848,7 @@
 			ctx->ctx_fl_frozen,
 			ctx->ctx_ovfl_regs[0]));
 
+		preempt_disable();
 		pfm_reset_regs(ctx, ctx->ctx_ovfl_regs, PFM_PMD_LONG_RESET);
 
 		ctx->ctx_ovfl_regs[0] = 0UL;
@@ -1849,6 +1867,8 @@
 		/* simply unfreeze */
 		pfm_unfreeze_pmu();
 
+		preempt_enable();
+
 		return 0;
 	} 
 	/* restart on another task */
@@ -1906,6 +1926,7 @@
 				ctx->ctx_fl_system, PMU_OWNER(),
 				current));
 
+	preempt_disable();
 	/* simply stop monitoring but not the PMU */
 	if (ctx->ctx_fl_system) {
 
@@ -1933,6 +1954,7 @@
 		 */
 		ia64_psr(regs)->up = 0;
 	}
+	preempt_enable();
 	return 0;
 }
 
@@ -1945,6 +1967,7 @@
 
 	if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
 
+	preempt_disable();
 	/*
 	 * stop monitoring, freeze PMU, and save state in context
 	 * this call will clear IA64_THREAD_PM_VALID for per-task sessions.
@@ -1965,6 +1988,7 @@
 	DBprintk(("enabling psr.sp for [%d]\n", current->pid));
 
 	ctx->ctx_flags.state = PFM_CTX_DISABLED;
+	preempt_enable();
 
 	return 0;
 }
@@ -2314,6 +2338,7 @@
 		return -EINVAL;
 	}
 
+	preempt_disable();
 	if (ctx->ctx_fl_system) {
 		
 		PFM_CPUINFO_SET(PFM_CPUINFO_DCR_PP);
@@ -2331,6 +2356,7 @@
 
 	} else {
 		if ((task->thread.flags & IA64_THREAD_PM_VALID) == 0) {
+			preempt_enable();
 			printk(KERN_DEBUG "perfmon: pfm_start task flag not set for [%d]\n",
 			       task->pid);
 			return -EINVAL;
@@ -2344,6 +2370,7 @@
 		ia64_srlz_i();
 	}
 
+	preempt_enable();
 	return 0;
 }
 
@@ -2351,9 +2378,13 @@
 pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, 
 	   struct pt_regs *regs)
 {
+	int me;
+
 	/* we don't quite support this right now */
 	if (task != current) return -EINVAL;
 
+	me = get_cpu();  /* make sure we're not migrated or preempted */
+
 	if (ctx->ctx_fl_system == 0 && PMU_OWNER()  && PMU_OWNER() != current) 
 		pfm_lazy_save_regs(PMU_OWNER());
 
@@ -2397,11 +2428,13 @@
 	SET_PMU_OWNER(task);
 
 	ctx->ctx_flags.state = PFM_CTX_ENABLED;
-	atomic_set(&ctx->ctx_last_cpu, smp_processor_id());
+	atomic_set(&ctx->ctx_last_cpu, me);
 
 	/* simply unfreeze */
 	pfm_unfreeze_pmu();
 
+	put_cpu();
+
 	return 0;
 }
 
@@ -2547,6 +2580,10 @@
 
 			task = find_task_by_pid(pid);
 
+			if (task) get_task_struct(task);
+
+			read_unlock(&tasklist_lock);
+
 			if (!task) goto abort_call;
 
 			ret = -EPERM;
@@ -2584,16 +2621,116 @@
 	ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(task, ctx, arg, count, regs);
 
 abort_call:
-	if (task != current) read_unlock(&tasklist_lock);
+	if (task && task != current) put_task_struct(task);
 
 	return ret;
 }
 
+/*
+ * send SIGPROF to register task, must be invoked when it
+ * is safe to send a signal, e.g., not holding any runqueue
+ * related locks.
+ */
+static int
+pfm_notify_user(pfm_context_t *ctx)
+{
+	struct siginfo si;
+	int ret;
+
+	if (ctx->ctx_notify_task == NULL) {
+		DBprintk(("[%d] no notifier\n", current->pid));
+		return -EINVAL;
+	}
+
+	si.si_errno    = 0;
+	si.si_addr     = NULL;
+	si.si_pid      = current->pid; /* who is sending */
+	si.si_signo    = SIGPROF;
+	si.si_code     = PROF_OVFL;
+
+	si.si_pfm_ovfl[0] = ctx->ctx_ovfl_regs[0];
+
+	/*
+	 * when the target of the signal is not ourself, we have to be more
+	 * careful. The notify_task may being cleared by the target task itself
+	 * in release_thread(). We must ensure mutual exclusion here such that
+	 * the signal is delivered (even to a dying task) safely.
+	 */
+
+	if (ctx->ctx_notify_task != current) {
+		/*
+		 * grab the notification lock for this task
+		 * This guarantees that the sequence: test + send_signal
+		 * is atomic with regards to the ctx_notify_task field.
+		 *
+		 * We need a spinlock and not just an atomic variable for this.
+		 *
+		 */
+		spin_lock(&ctx->ctx_lock);
+
+		/*
+		 * now notify_task cannot be modified until we're done
+		 * if NULL, they it got modified while we were in the handler
+		 */
+		if (ctx->ctx_notify_task == NULL) {
+
+			spin_unlock(&ctx->ctx_lock);
+
+			/*
+			 * If we've lost the notified task, then we will run
+			 * to completion wbut keep the PMU frozen. Results
+			 * will be incorrect anyway. We do not kill task
+			 * to leave it possible to attach perfmon context
+			 * to already running task.
+			 */
+			printk("perfmon: pfm_notify_user() lost notify_task\n");
+			DBprintk_ovfl(("notification task has disappeared !\n"));
+
+			/* we cannot afford to block now */
+			ctx->ctx_fl_block = 0;
+
+			return  -EINVAL;
+		}
+
+		/*
+		 * required by send_sig_info() to make sure the target
+		 * task does not disappear on us.
+		 */
+		read_lock(&tasklist_lock);
+	}
+	/*
+ 	 * in this case, we don't stop the task, we let it go on. It will
+ 	 * necessarily go to the signal handler (if any) when it goes back to
+ 	 * user mode.
+ 	 */
+	DBprintk_ovfl(("[%d] sending notification to [%d]\n", 
+			current->pid, ctx->ctx_notify_task->pid));
+
+	/* 
+	 * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
+	 */
+	ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task);
+	if (ret) {
+		printk("perfmon: send_sig_info(process %d, SIGPROF)=%d\n", 
+				ctx->ctx_notify_task->pid, ret);
+	}
+
+	/*
+	 * now undo the protections in order
+	 */
+	if (ctx->ctx_notify_task != current) {
+		read_unlock(&tasklist_lock);
+		spin_unlock(&ctx->ctx_lock);
+	}
+	return ret;
+}
+
 void
 pfm_ovfl_block_reset(void)
 {
 	struct thread_struct *th = &current->thread;
 	pfm_context_t *ctx = current->thread.pfm_context;
+	unsigned int reason;
 	int ret;
 
 	/*
@@ -2609,8 +2746,31 @@
 		printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid);
 		return;
 	}
+	/*
+	 * extract reason for being here and clear
+	 */
+	reason = ctx->ctx_fl_trap_reason;
+	ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
 
-	if (CTX_OVFL_NOBLOCK(ctx)) goto non_blocking;
+	DBprintk(("[%d] reason=%d\n", current->pid, reason));
+
+	/*
+	 * just here for a reset (non-blocking context only)
+	 */
+	if (reason == PFM_TRAP_REASON_RESET) goto non_blocking;
+
+	/*
+	 * first notify user. This can fail if notify_task has disappeared.
+	 */
+	if (reason == PFM_TRAP_REASON_SIG || reason == PFM_TRAP_REASON_BLOCKSIG) {
+		ret = pfm_notify_user(ctx);
+		if (ret) return;
+	}
+
+	/*
+	 * came here just to signal (non-blocking)
+	 */
+	if (reason == PFM_TRAP_REASON_SIG) return;
 
 	DBprintk(("[%d] before sleeping\n", current->pid));
 
@@ -2691,7 +2851,7 @@
 	 * initialize entry header
 	 */
 	h->pid  = current->pid;
-	h->cpu  = smp_processor_id();
+	h->cpu  = get_cpu();
 	h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL;
 	h->ip   = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL;
 	h->regs = ovfl_mask; 			/* which registers overflowed */
@@ -2718,7 +2878,7 @@
 		DBprintk_ovfl(("e=%p pmd%d =0x%lx\n", (void *)e, j, *e));
 		e++;
 	}
-	pfm_stats[smp_processor_id()].pfm_recorded_samples_count++;
+	pfm_stats[h->cpu].pfm_recorded_samples_count++;
 
 	/*
 	 * make the new entry visible to user, needs to be atomic
@@ -2735,9 +2895,11 @@
 		/*
 		 * XXX: must reset buffer in blocking mode and lost notified
 		 */
-		pfm_stats[smp_processor_id()].pfm_full_smpl_buffer_count++;
+		pfm_stats[h->cpu].pfm_full_smpl_buffer_count++;
+		put_cpu();
 		return 1;
 	}
+	put_cpu();
 	return 0;
 }
 
@@ -2756,7 +2918,6 @@
 	unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL;
 	int i;
 	int ret = 1;
-	struct siginfo si;
 	/*
 	 * It is never safe to access the task for which the overflow interrupt is destinated
 	 * using the current variable as the interrupt may occur in the middle of a context switch
@@ -2770,6 +2931,8 @@
 	 * valid one, i.e. the one that caused the interrupt.
 	 */
 
+	preempt_disable();
+
 	t   = &task->thread;
 
 	/*
@@ -2779,6 +2942,7 @@
 	if ((t->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system == 0) {
 		printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d not "
 		       "using perfmon\n", task->pid);
+		preempt_enable_no_resched();
 		return 0x1;
 	}
 	/*
@@ -2787,6 +2951,7 @@
 	if ((pmc0 & 0x1) == 0) {
 		printk(KERN_DEBUG "perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n",
 		       task->pid, pmc0);
+		preempt_enable_no_resched();
 		return 0x0;
 	}
 
@@ -2869,7 +3034,8 @@
 	if (ovfl_notify == 0UL) {
 		if (ovfl_pmds) 
 			pfm_reset_regs(ctx, &ovfl_pmds, PFM_PMD_SHORT_RESET);
-		return 0x0;
+		preempt_enable_no_resched();
+		return 0x0UL;
 	}
 
 	/* 
@@ -2877,142 +3043,35 @@
 	 */
 	ctx->ctx_ovfl_regs[0]  = ovfl_pmds; 
 
-	/*
-	 * we have come to this point because there was an overflow and that notification
-	 * was requested. The notify_task may have disappeared, in which case notify_task
-	 * is NULL.
-	 */
-	if (ctx->ctx_notify_task) {
-
-		si.si_errno    = 0;
-		si.si_addr     = NULL;
-		si.si_pid      = task->pid; /* who is sending */
-
-		si.si_signo    = SIGPROF;
-		si.si_code     = PROF_OVFL; /* indicates a perfmon SIGPROF signal */
-		/*
-		 * Shift the bitvector such that the user sees bit 4 for PMD4 and so on.
-		 * We only use smpl_ovfl[0] for now. It should be fine for quite a while
-		 * until we have more than 61 PMD available.
-		 */
-		si.si_pfm_ovfl[0] = ovfl_notify;
-	
-		/*
-		 * when the target of the signal is not ourself, we have to be more
-		 * careful. The notify_task may being cleared by the target task itself
-		 * in release_thread(). We must ensure mutual exclusion here such that
-		 * the signal is delivered (even to a dying task) safely.
-		 */
-
-		if (ctx->ctx_notify_task != current) {
-			/*
-			 * grab the notification lock for this task
-			 * This guarantees that the sequence: test + send_signal
-			 * is atomic with regards to the ctx_notify_task field.
-			 *
-			 * We need a spinlock and not just an atomic variable for this.
-			 *
-			 */
-			spin_lock(&ctx->ctx_lock);
-
-			/*
-			 * now notify_task cannot be modified until we're done
-			 * if NULL, they it got modified while we were in the handler
-			 */
-			if (ctx->ctx_notify_task == NULL) {
-
-				spin_unlock(&ctx->ctx_lock);
+	DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", 
+		ctx->ctx_fl_block,
+		ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, 
+		current->pid ));
 
-				/*
-				 * If we've lost the notified task, then we will run
-				 * to completion wbut keep the PMU frozen. Results
-				 * will be incorrect anyway. We do not kill task
-				 * to leave it possible to attach perfmon context
-				 * to already running task.
-				 */
-				goto lost_notify;
-			}
-			/*
-			 * required by send_sig_info() to make sure the target
-			 * task does not disappear on us.
-			 */
-			read_lock(&tasklist_lock);
-		}
-		/*
-	 	 * in this case, we don't stop the task, we let it go on. It will
-	 	 * necessarily go to the signal handler (if any) when it goes back to
-	 	 * user mode.
-	 	 */
-		DBprintk_ovfl(("[%d] sending notification to [%d]\n", 
-			  task->pid, ctx->ctx_notify_task->pid));
-
-
-		/* 
-		 * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
-		 */
-		ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task);
-		if (ret != 0)
-			printk(KERN_DEBUG "send_sig_info(process %d, SIGPROF)=%d\n",
-			       ctx->ctx_notify_task->pid, ret);
-		/*
-		 * now undo the protections in order
-		 */
-		if (ctx->ctx_notify_task != current) {
-			read_unlock(&tasklist_lock);
-			spin_unlock(&ctx->ctx_lock);
-		}
-
-		/*
-		 * if we block set the pfm_must_block bit
-		 * when in block mode, we can effectively block only when the notified
-		 * task is not self, otherwise we would deadlock. 
-		 * in this configuration, the notification is sent, the task will not 
-		 * block on the way back to user mode, but the PMU will be kept frozen
-		 * until PFM_RESTART.
-		 * Note that here there is still a race condition with notify_task
-		 * possibly being nullified behind our back, but this is fine because
-		 * it can only be changed to NULL which by construction, can only be
-		 * done when notify_task != current. So if it was already different
-		 * before, changing it to NULL will still maintain this invariant.
-		 * Of course, when it is equal to current it cannot change at this point.
-		 */
-		DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", 
-			ctx->ctx_fl_block,
-			ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, 
-			current->pid ));
-
-		if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != task) {
-			t->pfm_ovfl_block_reset = 1; /* will cause blocking */
-		}
+	/* 
+	 * ctx_notify_task could already be NULL, checked in pfm_notify_user() 
+	 */
+	if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) {
+		t->pfm_ovfl_block_reset = 1; /* will cause blocking */
+		ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG;
 	} else {
-lost_notify: /* XXX: more to do here, to convert to non-blocking (reset values) */
-
-		DBprintk_ovfl(("notification task has disappeared !\n"));
-		/*
-		 * for a non-blocking context, we make sure we do not fall into the 
-		 * pfm_overflow_notify() trap. Also in the case of a blocking context with lost 
-		 * notify process, then we do not want to block either (even though it is 
-		 * interruptible). In this case, the PMU will be kept frozen and the process will 
-		 * run to completion without monitoring enabled.
-		 *
-		 * Of course, we cannot loose notify process when self-monitoring.
-		 */
-		t->pfm_ovfl_block_reset = 0; 
-
+		t->pfm_ovfl_block_reset = 1; /* will cause blocking */
+		ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG;
 	}
+
 	/*
-	 * If notification was successful, then we rely on the pfm_restart()
-	 * call to unfreeze and reset (in both blocking or non-blocking mode).
-	 *
-	 * If notification failed, then we will keep the PMU frozen and run
-	 * the task to completion
+	 * keep the PMU frozen until either pfm_restart() or 
+	 * task completes (non-blocking or notify_task gone).
 	 */
 	ctx->ctx_fl_frozen = 1;
 
-	DBprintk_ovfl(("return pmc0=0x%x must_block=%ld\n",
-				ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset));
+	DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n",
+		ctx->ctx_fl_frozen ? 0x1 : 0x0, 
+		t->pfm_ovfl_block_reset,
+		ctx->ctx_fl_trap_reason));
 
-	return ctx->ctx_fl_frozen ? 0x1 : 0x0;
+	preempt_enable_no_resched();
+	return 0x1UL;
 }
 
 static void
@@ -3022,13 +3081,14 @@
 	struct task_struct *task;
 	pfm_context_t *ctx;
 
-	pfm_stats[smp_processor_id()].pfm_ovfl_intr_count++;
+	pfm_stats[get_cpu()].pfm_ovfl_intr_count++;
 
 	/*
 	 * if an alternate handler is registered, just bypass the default one
 	 */
 	if (pfm_alternate_intr_handler) {
 		(*pfm_alternate_intr_handler->handler)(irq, arg, regs);
+		put_cpu();
 		return;
 	}
 
@@ -3053,6 +3113,7 @@
 		if (!ctx) {
 			printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has "
 			       "no PFM context\n", task->pid);
+			put_cpu();
 			return;
 		}
 
@@ -3060,17 +3121,25 @@
 		 * assume PMC[0].fr = 1 at this point 
 		 */
 		pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs);
-
 		/*
-		 * We always clear the overflow status bits and either unfreeze
-		 * or keep the PMU frozen.
+		 * we can only update pmc0 when the overflow
+		 * is for the current context. In UP the current
+		 * task may not be the one owning the PMU
 		 */
-		ia64_set_pmc(0, pmc0);
-		ia64_srlz_d();
-
+		if (task == current) {
+			/*
+		 	 * We always clear the overflow status bits and either unfreeze
+		 	 * or keep the PMU frozen.
+		 	 */
+			ia64_set_pmc(0, pmc0);
+			ia64_srlz_d();
+		} else {
+			task->thread.pmc[0] = pmc0;
+		}
 	} else {
 		pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++;
 	}
+	put_cpu_no_resched();
 }
 
 /* for debug only */
@@ -3141,6 +3210,7 @@
 	unsigned long dcr;
 	unsigned long dcr_pp;
 
+	preempt_disable();
 	dcr_pp = info & PFM_CPUINFO_DCR_PP ? 1 : 0;
 
 	/*
@@ -3151,6 +3221,7 @@
 		regs = (struct pt_regs *)((unsigned long) task + IA64_STK_OFFSET);
 		regs--;
 		ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0;
+		preempt_enable();
 		return;
 	}
 	/*
@@ -3166,6 +3237,7 @@
 			ia64_set_dcr(dcr & ~IA64_DCR_PP);
 			pfm_clear_psr_pp();
 			ia64_srlz_i();
+			preempt_enable();
 			return;
 		}
 		/* 
@@ -3179,6 +3251,7 @@
 		pfm_set_psr_pp();
 		ia64_srlz_i();
 	}
+	preempt_enable();
 }
 
 void
@@ -3189,6 +3262,8 @@
 	u64 psr;
 	int i;
 
+	preempt_disable();
+
 	ctx = task->thread.pfm_context;
 
 
@@ -3242,6 +3317,7 @@
 	 */
 	atomic_set(&ctx->ctx_last_cpu, -1);
 #endif
+	preempt_enable();
 }
 
 static void
@@ -3252,6 +3328,7 @@
 	unsigned long mask;
 	int i;
 
+	preempt_disable();
 	DBprintk(("on [%d] by [%d]\n", task->pid, current->pid));
 
 	t   = &task->thread;
@@ -3278,6 +3355,7 @@
 
 	/* not owned by this CPU */
 	atomic_set(&ctx->ctx_last_cpu, -1);
+	preempt_enable();
 }
 
 void
@@ -3290,11 +3368,14 @@
 	u64 psr;
 	int i;
 
+	preempt_disable();
+
 	owner = PMU_OWNER();
 	ctx   = task->thread.pfm_context;
 	t     = &task->thread;
 
 	if (ctx == NULL) {
+		preempt_enable();
 		printk("perfmon: pfm_load_regs: null ctx for [%d]\n", task->pid);
 		return;
 	}
@@ -3333,7 +3414,7 @@
 
 		psr = ctx->ctx_saved_psr;
 		pfm_set_psr_l(psr);
-
+		preempt_enable();
 		return;
 	}
 
@@ -3373,16 +3454,20 @@
 		if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]);
 	}
 
+	/*
+	 * manually invoke core interrupt handler
+	 * if the task had a pending overflow when it was ctxsw out.
+	 * Side effect on ctx_fl_frozen is possible.
+	 */
 	if (t->pmc[0] & ~0x1) {
-		pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
+		t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
 	}
 
 	/*
-	 * fl_frozen==1 when we are in blocking mode waiting for restart
+	 * unfreeze PMU if possible
 	 */
-	if (ctx->ctx_fl_frozen == 0) {
-		pfm_unfreeze_pmu();
-	}
+	if (ctx->ctx_fl_frozen == 0) pfm_unfreeze_pmu();
+
 	atomic_set(&ctx->ctx_last_cpu, smp_processor_id());
 
 	SET_PMU_OWNER(task);
@@ -3391,6 +3476,7 @@
 	 * restore the psr we changed in pfm_save_regs()
 	 */
 	psr = ctx->ctx_saved_psr;
+	preempt_enable();
 	pfm_set_psr_l(psr);
 }
 
@@ -3408,6 +3494,7 @@
 		printk("perfmon: invalid task in pfm_reset_pmu()\n");
 		return;
 	}
+	preempt_disable();
 
 	/* Let's make sure the PMU is frozen */
 	pfm_freeze_pmu();
@@ -3490,6 +3577,7 @@
 	ctx->ctx_used_dbrs[0] = 0UL;
 
 	ia64_srlz_d();
+	preempt_enable();
 }
 
 /*
@@ -3519,6 +3607,7 @@
 	 */
 	if (ctx->ctx_flags.state == PFM_CTX_DISABLED) return;
 
+	preempt_disable();
 	/*
 	 * stop monitoring:
 	 * This is the only way to stop monitoring without destroying overflow
@@ -3646,7 +3735,7 @@
 	 * indicates that context has been saved
 	 */
 	atomic_set(&ctx->ctx_last_cpu, -1);
-
+	preempt_enable();
 }
 
 
@@ -3669,6 +3758,7 @@
 	ctx    = task->thread.pfm_context;
 	thread = &task->thread;
 
+	preempt_disable();
 	/*
 	 * make sure child cannot mess up the monitoring session
 	 */
@@ -3723,6 +3813,8 @@
 		 */
 	 	ia64_psr(regs)->up = 0;
 
+		preempt_enable();
+
 		/* copy_thread() clears IA64_THREAD_PM_VALID */
 		return 0;
 	}
@@ -3770,8 +3862,9 @@
 		}
 	}
 
-	nctx->ctx_fl_frozen    = 0;
-	nctx->ctx_ovfl_regs[0] = 0UL;
+	nctx->ctx_fl_frozen      = 0;
+	nctx->ctx_ovfl_regs[0]   = 0UL;
+	nctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
 	atomic_set(&nctx->ctx_last_cpu, -1);
 
 	/*
@@ -3827,6 +3920,8 @@
 		thread->flags |= IA64_THREAD_PM_VALID;
 	}
 
+	preempt_enable();
+
 	return 0;
 }
 
@@ -3848,6 +3943,7 @@
 	/*
 	 * check sampling buffer
 	 */
+	preempt_disable();
 	if (ctx->ctx_psb) {
 		pfm_smpl_buffer_desc_t *psb = ctx->ctx_psb;
 
@@ -3940,6 +4036,7 @@
 	}
 
 	UNLOCK_CTX(ctx);
+	preempt_enable();
 
 	pfm_unreserve_session(task, ctx->ctx_fl_system, 1UL << ctx->ctx_cpu);
 
@@ -4118,17 +4215,27 @@
 {
 	int ret;
 
+
 	/* some sanity checks */
-	if (hdl == NULL || hdl->handler == NULL) return -EINVAL;
+	if (hdl == NULL || hdl->handler == NULL) {
+		return -EINVAL;
+	}
 
 	/* do the easy test first */
-	if (pfm_alternate_intr_handler) return -EBUSY;
+	if (pfm_alternate_intr_handler) {
+		return -EBUSY;
+	}
 
+	preempt_disable();
 	/* reserve our session */
 	ret = pfm_reserve_session(NULL, 1, cpu_online_map);
-	if (ret) return ret;
+	if (ret) {
+		preempt_enable();
+		return ret;
+	}
 
 	if (pfm_alternate_intr_handler) {
+		preempt_enable();
 		printk(KERN_DEBUG "perfmon: install_alternate, intr_handler not NULL "
 		       "after reserve\n");
 		return -EINVAL;
@@ -4136,17 +4243,21 @@
 
 	pfm_alternate_intr_handler = hdl;
 
+	preempt_enable();
 	return 0;
 }
 
 int
 pfm_remove_alternate_syswide_subsystem(pfm_intr_handler_desc_t *hdl)
 {
-	if (hdl == NULL) return -EINVAL;
+	if (hdl == NULL)
+		return -EINVAL;
 
 	/* cannot remove someone else's handler! */
-	if (pfm_alternate_intr_handler != hdl) return -EINVAL;
+	if (pfm_alternate_intr_handler != hdl) 
+		return -EINVAL;
 
+	preempt_disable();
 	pfm_alternate_intr_handler = NULL;
 
 	/* 
@@ -4154,6 +4265,8 @@
 	 */
 	pfm_unreserve_session(NULL, 1, cpu_online_map);
 
+	preempt_enable();
+
 	return 0;
 }
 
@@ -4234,8 +4347,9 @@
 pfm_init_percpu(void)
 {
 	int i;
+	int me = get_cpu();
 
-	if (smp_processor_id() == 0)
+	if (me == 0)
 		register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
 
 	ia64_set_pmv(IA64_PERFMON_VECTOR);
@@ -4259,6 +4373,7 @@
 		if (PMD_IS_IMPL(i) == 0) continue;
 		ia64_set_pmd(i, 0UL);
 	}
+	put_cpu();
 	pfm_freeze_pmu();
 }
 
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c	Fri Jan 24 11:56:49 2003
+++ b/arch/ia64/kernel/process.c	Thu Mar  6 21:11:46 2003
@@ -746,7 +746,7 @@
 
 	memcpy(tsk, orig, sizeof(struct task_struct) + sizeof(struct thread_info));
 	tsk->thread_info = (struct thread_info *) ((char *) tsk + IA64_TASK_SIZE);
-	atomic_set(&tsk->usage, 1);
+	atomic_set(&tsk->usage, 2);
 	return tsk;
 }
 
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c	Tue Jan 14 21:57:29 2003
+++ b/arch/ia64/kernel/ptrace.c	Thu Mar  6 14:56:33 2003
@@ -1,7 +1,7 @@
 /*
  * Kernel support for the ptrace() and syscall tracing interfaces.
  *
- * Copyright (C) 1999-2002 Hewlett-Packard Co
+ * Copyright (C) 1999-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Derived from the x86 and Alpha versions.  Most of the code in here
@@ -1235,19 +1235,12 @@
 		ret = 0;
 		goto out_tsk;
 
-	      case PTRACE_GETSIGINFO:
-		ret = -EIO;
-		if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo)
-			goto out_tsk;
-		ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo);
+	      case PTRACE_OLD_GETSIGINFO:		/* for backwards-compatibility */
+		ret = ptrace_request(child, PTRACE_GETSIGINFO, addr, data);
 		goto out_tsk;
 
-	      case PTRACE_SETSIGINFO:
-		ret = -EIO;
-		if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t))
-		    || child->thread.siginfo == 0)
-			goto out_tsk;
-		ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data);
+	      case PTRACE_OLD_SETSIGINFO:		/* for backwards-compatibility */
+		ret = ptrace_request(child, PTRACE_SETSIGINFO, addr, data);
 		goto out_tsk;
 
 	      case PTRACE_SYSCALL:	/* continue and stop at next (return from) syscall */
@@ -1349,15 +1342,12 @@
 	 * The 0x80 provides a way for the tracing parent to distinguish between a syscall
 	 * stop and SIGTRAP delivery.
 	 */
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	set_current_state(TASK_STOPPED);
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+
 	/*
-	 * This isn't the same as continuing with a signal, but it
-	 * will do for normal use.  strace only continues with a
-	 * signal if the stopping signal is not SIGTRAP.  -brl
+	 * This isn't the same as continuing with a signal, but it will do for normal use.
+	 * strace only continues with a signal if the stopping signal is not SIGTRAP.
+	 * -brl
 	 */
 	if (current->exit_code) {
 		send_sig(current->exit_code, current, 1);
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c	Tue Feb  4 17:06:14 2003
+++ b/arch/ia64/kernel/setup.c	Wed Feb 12 00:11:32 2003
@@ -363,7 +363,7 @@
 
 #ifdef CONFIG_ACPI_BOOT
 	/* Initialize the ACPI boot-time table parser */
-	acpi_table_init(*cmdline_p);
+	acpi_table_init();
 # ifdef CONFIG_ACPI_NUMA
 	acpi_numa_init();
 # endif
@@ -422,7 +422,7 @@
 	cpu_init();	/* initialize the bootstrap CPU */
 
 #ifdef CONFIG_ACPI_BOOT
-	acpi_boot_init(*cmdline_p);
+	acpi_boot_init();
 #endif
 #ifdef CONFIG_SERIAL_HCDP
 	if (efi.hcdp) {
diff -Nru a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
--- a/arch/ia64/kernel/sigframe.h	Fri Mar  8 18:11:39 2002
+++ b/arch/ia64/kernel/sigframe.h	Mon Feb 10 18:28:00 2003
@@ -1,6 +1,6 @@
 struct sigscratch {
 	unsigned long scratch_unat;	/* ar.unat for the general registers saved in pt */
-	unsigned long pad;
+	unsigned long ar_pfs;		/* for syscalls, the user-level function-state  */
 	struct pt_regs pt;
 };
 
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	Tue Feb 11 04:25:29 2003
+++ b/arch/ia64/kernel/signal.c	Thu Mar  6 11:40:52 2003
@@ -315,7 +315,7 @@
 static long
 setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
 {
-	unsigned long flags = 0, ifs, nat;
+	unsigned long flags = 0, ifs, cfm, nat;
 	long err;
 
 	ifs = scr->pt.cr_ifs;
@@ -325,7 +325,9 @@
 	if ((ifs & (1UL << 63)) == 0) {
 		/* if cr_ifs isn't valid, we got here through a syscall */
 		flags |= IA64_SC_FLAG_IN_SYSCALL;
-	}
+		cfm = scr->ar_pfs & ((1UL << 38) - 1);
+	} else
+		cfm = ifs & ((1UL << 38) - 1);
 	ia64_flush_fph(current);
 	if ((current->thread.flags & IA64_THREAD_FPH_VALID)) {
 		flags |= IA64_SC_FLAG_FPH_VALID;
@@ -344,6 +346,7 @@
 
 	err |= __put_user(nat, &sc->sc_nat);
 	err |= PUT_SIGSET(mask, &sc->sc_mask);
+	err |= __put_user(cfm, &sc->sc_cfm);
 	err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um);
 	err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
 	err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
@@ -422,6 +425,15 @@
 	scr->pt.ar_fpsr = FPSR_DEFAULT;			/* reset fpsr for signal handler */
 	scr->pt.cr_iip = tramp_addr;
 	ia64_psr(&scr->pt)->ri = 0;			/* start executing in first slot */
+	/*
+	 * Force the interruption function mask to zero.  This has no effect when a
+	 * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is
+	 * ignored), but it has the desirable effect of making it possible to deliver a
+	 * signal with an incomplete register frame (which happens when a mandatory RSE
+	 * load faults).  Furthermore, it has no negative effect on the getting the user's
+	 * dirty partition preserved, because that's governed by scr->pt.loadrs.
+	 */
+	scr->pt.cr_ifs = (1UL << 63);
 
 	/*
 	 * Note: this affects only the NaT bits of the scratch regs (the ones saved in
@@ -522,7 +534,7 @@
 		if (signr <= 0)
 			break;
 
-		ka = &current->sig->action[signr - 1];
+		ka = &current->sighand->action[signr - 1];
 
 		if (restart) {
 			switch (errno) {
diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
--- a/arch/ia64/kernel/smp.c	Sun Mar  2 18:13:32 2003
+++ b/arch/ia64/kernel/smp.c	Thu Mar  6 11:40:52 2003
@@ -90,7 +90,7 @@
 void
 handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
 {
-	int this_cpu = smp_processor_id();
+	int this_cpu = get_cpu();
 	unsigned long *pending_ipis = &__get_cpu_var(ipi_operation);
 	unsigned long ops;
 
@@ -146,8 +146,12 @@
 		} while (ops);
 		mb();	/* Order data access and bit testing. */
 	}
+	put_cpu();
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_single (int dest_cpu, int op)
 {
@@ -155,6 +159,9 @@
 	platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_allbutself (int op)
 {
@@ -166,6 +173,9 @@
 	}
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_all (int op)
 {
@@ -176,12 +186,18 @@
 			send_IPI_single(i, op);
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_self (int op)
 {
 	send_IPI_single(smp_processor_id(), op);
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 void
 smp_send_reschedule (int cpu)
 {
@@ -197,12 +213,15 @@
 smp_send_reschedule_all (void)
 {
 	int i;
+	int cpu = get_cpu(); /* disable preemption */
 
 	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_online(i) && i != smp_processor_id())
+		if (cpu_online(i) && i != cpu)
 			smp_send_reschedule(i);
+	put_cpu();
 }
 
+
 void
 smp_flush_tlb_all (void)
 {
@@ -247,9 +266,11 @@
 {
 	struct call_data_struct data;
 	int cpus = 1;
+	int me = get_cpu(); /* prevent preemption and reschedule on another processor */
 
-	if (cpuid == smp_processor_id()) {
+	if (cpuid == me) {
 		printk("%s: trying to call self\n", __FUNCTION__);
+		put_cpu();
 		return -EBUSY;
 	}
 
@@ -276,6 +297,7 @@
 	call_data = NULL;
 
 	spin_unlock_bh(&call_lock);
+	put_cpu();
 	return 0;
 }
 
diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c	Mon Jan 27 11:04:16 2003
+++ b/arch/ia64/kernel/sys_ia64.c	Wed Feb 26 06:03:08 2003
@@ -33,17 +33,8 @@
 		return -ENOMEM;
 
 #ifdef CONFIG_HUGETLB_PAGE
-#define COLOR_HALIGN(addr) ((addr + HPAGE_SIZE - 1) & ~(HPAGE_SIZE - 1))
-#define TASK_HPAGE_BASE ((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE)
-	if (filp && is_file_hugepages(filp)) {
-		if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE -1)))
-			addr = TASK_HPAGE_BASE;
-		addr = COLOR_HALIGN(addr);
-	}
-	else {
-		if (REGION_NUMBER(addr) == REGION_HPAGE)
-			addr = 0;
-	}
+	if (REGION_NUMBER(addr) == REGION_HPAGE)
+		addr = 0;
 #endif
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	Mon Feb 24 23:13:09 2003
+++ b/arch/ia64/kernel/time.c	Thu Mar  6 11:40:52 2003
@@ -25,7 +25,7 @@
 #include <asm/system.h>
 
 extern unsigned long wall_jiffies;
-extern unsigned long last_time_offset;
+extern unsigned long last_nsec_offset;
 
 u64 jiffies_64 = INITIAL_JIFFIES;
 
@@ -74,13 +74,13 @@
 		     - (lost + 1)*cpu_data(time_keeper_id)->itm_delta);
 
 	now = ia64_get_itc();
-	if ((long) (now - last_tick) < 0) {
+	if (unlikely((long) (now - last_tick) < 0)) {
 		printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n",
 		       smp_processor_id(), now, last_tick);
-		return last_time_offset;
+		return last_nsec_offset;
 	}
 	elapsed_cycles = now - last_tick;
-	return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
+	return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT;
 }
 
 void
@@ -115,30 +115,55 @@
 void
 do_gettimeofday (struct timeval *tv)
 {
-	unsigned long seq, usec, sec, old;
+	unsigned long seq, nsec, usec, sec, old, offset;
 
-	do {
+	while (1) {
 		seq = read_seqbegin(&xtime_lock);
-		usec = gettimeoffset();
-
+		{
+			old = last_nsec_offset;
+			offset = gettimeoffset();
+			sec = xtime.tv_sec;
+			nsec = xtime.tv_nsec;
+		}
+		if (unlikely(read_seqretry(&xtime_lock, seq)))
+			continue;
 		/*
-		 * Ensure time never goes backwards, even when ITC on 
-		 * different CPUs are not perfectly synchronized.
+		 * Ensure that for any pair of causally ordered gettimeofday() calls, time
+		 * never goes backwards (even when ITC on different CPUs are not perfectly
+		 * synchronized).  (A pair of concurrent calls to gettimeofday() is by
+		 * definition non-causal and hence it makes no sense to talk about
+		 * time-continuity for such calls.)
+		 *
+		 * Doing this in a lock-free and race-free manner is tricky.  Here is why
+		 * it works (most of the time): read_seqretry() just succeeded, which
+		 * implies we calculated a consistent (valid) value for "offset".  If the
+		 * cmpxchg() below succeeds, we further know that last_nsec_offset still
+		 * has the same value as at the beginning of the loop, so there was
+		 * presumably no timer-tick or other updates to last_nsec_offset in the
+		 * meantime.  This isn't 100% true though: there _is_ a possibility of a
+		 * timer-tick occurring right right after read_seqretry() and then getting
+		 * zero or more other readers which will set last_nsec_offset to the same
+		 * value as the one we read at the beginning of the loop.  If this
+		 * happens, we'll end up returning a slightly newer time than we ought to
+		 * (the jump forward is at most "offset" nano-seconds).  There is no
+		 * danger of causing time to go backwards, though, so we are safe in that
+		 * sense.  We could make the probability of this unlucky case occurring
+		 * arbitrarily small by encoding a version number in last_nsec_offset, but
+		 * even without versioning, the probability of this unlucky case should be
+		 * so small that we won't worry about it.
 		 */
-		do {
-			old = last_time_offset;
-			if (usec <= old) {
-				usec = old;
-				break;
-			}
-		} while (cmpxchg(&last_time_offset, old, usec) != old);
-
-		sec = xtime.tv_sec;
-		usec += xtime.tv_nsec / 1000;
-	} while (read_seqend(&xtime_lock, seq));
+		if (offset <= old) {
+			offset = old;
+			break;
+		} else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old))
+			break;
+
+		/* someone else beat us to updating last_nsec_offset; try again */
+	}
 
+	usec = (nsec + offset) / 1000;
 
-	while (usec >= 1000000) {
+	while (unlikely(usec >= 1000000)) {
 		usec -= 1000000;
 		++sec;
 	}
@@ -278,7 +303,7 @@
 	local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
 	local_cpu_data->itc_freq = itc_freq;
 	local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000;
-	local_cpu_data->usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
+	local_cpu_data->nsec_per_cyc = ((1000000000UL<<IA64_NSEC_PER_CYC_SHIFT)
 					+ itc_freq/2)/itc_freq;
 
 	/* Setup the CPU local timer tick */
diff -Nru a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
--- a/arch/ia64/kernel/traps.c	Tue Feb  4 17:06:16 2003
+++ b/arch/ia64/kernel/traps.c	Thu Mar  6 13:42:08 2003
@@ -486,19 +486,23 @@
 
 	      case 26: /* NaT Consumption */
 		if (user_mode(regs)) {
+			void *addr;
+
 			if (((isr >> 4) & 0xf) == 2) {
 				/* NaT page consumption */
 				sig = SIGSEGV;
 				code = SEGV_ACCERR;
+				addr = (void *) ifa;
 			} else {
 				/* register NaT consumption */
 				sig = SIGILL;
 				code = ILL_ILLOPN;
+				addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
 			}
 			siginfo.si_signo = sig;
 			siginfo.si_code = code;
 			siginfo.si_errno = 0;
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = addr;
 			siginfo.si_imm = vector;
 			siginfo.si_flags = __ISR_VALID;
 			siginfo.si_isr = isr;
diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
--- a/arch/ia64/kernel/unwind.c	Tue Feb  4 17:06:17 2003
+++ b/arch/ia64/kernel/unwind.c	Thu Mar  6 21:11:46 2003
@@ -51,18 +51,24 @@
 #define UNW_LOG_HASH_SIZE	(UNW_LOG_CACHE_SIZE + 1)
 #define UNW_HASH_SIZE		(1 << UNW_LOG_HASH_SIZE)
 
-#define UNW_DEBUG	0
 #define UNW_STATS	0	/* WARNING: this disabled interrupts for long time-spans!! */
 
-#if UNW_DEBUG
-  static long unw_debug_level = 255;
-# define debug(level,format...)	if (unw_debug_level > level) printk(format)
-# define dprintk(format...)	printk(format)
-# define inline
-#else
-# define debug(level,format...)
-# define dprintk(format...)
-#endif
+#ifdef UNW_DEBUG
+  static unsigned int unw_debug_level = UNW_DEBUG;
+#  ifdef CONFIG_KDB
+#    include <linux/kdb.h>
+#    define UNW_DEBUG_ON(n)	(unw_debug_level >= n && !KDB_IS_RUNNING())
+#    define UNW_DPRINT(n, ...)	if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
+#  else	/* !CONFIG_KDB */
+#    define UNW_DEBUG_ON(n)	unw_debug_level >= n
+     /* Do not code a printk level, not all debug lines end in newline */
+#    define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
+#  endif /* CONFIG_KDB */
+#  define inline
+#else /* !UNW_DEBUG */
+#  define UNW_DEBUG_ON(n)  0
+#  define UNW_DPRINT(n, ...)
+#endif /* UNW_DEBUG */
 
 #if UNW_STATS
 # define STAT(x...)	x
@@ -111,7 +117,7 @@
 	/* script cache: */
 	struct unw_script cache[UNW_CACHE_SIZE];
 
-# if UNW_DEBUG
+# ifdef UNW_DEBUG
 	const char *preg_name[UNW_NUM_REGS];
 # endif
 # if UNW_STATS
@@ -190,7 +196,7 @@
 		struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
 	},
 	.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
-#if UNW_DEBUG
+#ifdef UNW_DEBUG
 	.preg_name = {
 		"pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
 		"r4", "r5", "r6", "r7",
@@ -223,10 +229,22 @@
 	else if (reg <= 31)
 		off = struct_offset(struct pt_regs, r16) + 8*(reg - 16);
 	else
-		dprintk("unwind: bad scratch reg r%lu\n", reg);
+		UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
 	return off;
 }
 
+static inline struct pt_regs *
+get_scratch_regs (struct unw_frame_info *info)
+{
+	if (!info->pt) {
+		/* This should not happen with valid unwind info.  */
+		UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __FUNCTION__);
+		info->pt = info->sp - 16;
+	}
+	UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __FUNCTION__, info->sp, info->pt);
+	return (struct pt_regs *) info->pt;
+}
+
 int
 unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
 {
@@ -235,7 +253,8 @@
 	struct pt_regs *pt;
 
 	if ((unsigned) regnum - 1 >= 127) {
-		dprintk("unwind: trying to access non-existent r%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 
@@ -280,8 +299,9 @@
 					if ((unsigned long) addr < info->regstk.limit
 					    || (unsigned long) addr >= info->regstk.top)
 					{
-						dprintk("unwind: %p outside of regstk "
-							"[0x%lx-0x%lx)\n", (void *) addr,
+						UNW_DPRINT(0, "unwind.%s: %p outside of regstk "
+							"[0x%lx-0x%lx)\n",
+							__FUNCTION__, (void *) addr,
 							info->regstk.limit,
 							info->regstk.top);
 						return -1;
@@ -298,11 +318,13 @@
 			}
 		} else {
 			/* access a scratch register */
-			if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-				pt = (struct pt_regs *) info->psp - 1;
-			else
-				pt = (struct pt_regs *) info->sp - 1;
-			addr = (unsigned long *) ((long) pt + pt_regs_off(regnum));
+			if (!info->pt) {
+				UNW_DPRINT(0, "unwind.%s: no pt-regs; cannot access r%d\n",
+					   __FUNCTION__, regnum);
+				return -1;
+			}
+			pt = get_scratch_regs(info);
+			addr = (unsigned long *) (pt + pt_regs_off(regnum));
 			if (info->pri_unat_loc)
 				nat_addr = info->pri_unat_loc;
 			else
@@ -316,7 +338,8 @@
 		if ((unsigned long) addr < info->regstk.limit
 		    || (unsigned long) addr >= info->regstk.top)
 		{
-			dprintk("unwind: ignoring attempt to access register outside of rbs\n");
+			UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside "
+				   "of rbs\n",  __FUNCTION__);
 			return -1;
 		}
 		if ((unsigned long) nat_addr >= info->regstk.top)
@@ -348,10 +371,7 @@
 	unsigned long *addr;
 	struct pt_regs *pt;
 
-	if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-		pt = (struct pt_regs *) info->psp - 1;
-	else
-		pt = (struct pt_regs *) info->sp - 1;
+	pt = get_scratch_regs(info);
 	switch (regnum) {
 		/* scratch: */
 	      case 0: addr = &pt->b0; break;
@@ -366,7 +386,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: trying to access non-existent b%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 	if (write)
@@ -383,14 +404,12 @@
 	struct pt_regs *pt;
 
 	if ((unsigned) (regnum - 2) >= 126) {
-		dprintk("unwind: trying to access non-existent f%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 
-	if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-		pt = (struct pt_regs *) info->psp - 1;
-	else
-		pt = (struct pt_regs *) info->sp - 1;
+	pt = get_scratch_regs(info);
 
 	if (regnum <= 5) {
 		addr = *(&info->f2_loc + (regnum - 2));
@@ -428,11 +447,7 @@
 	unsigned long *addr;
 	struct pt_regs *pt;
 
-	if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-		pt = (struct pt_regs *) info->psp - 1;
-	else
-		pt = (struct pt_regs *) info->sp - 1;
-
+	pt = get_scratch_regs(info);
 	switch (regnum) {
 	      case UNW_AR_BSP:
 		addr = info->bsp_loc;
@@ -495,7 +510,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: trying to access non-existent ar%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 
@@ -612,7 +628,7 @@
 	      default:
 		break;
 	}
-	dprintk("unwind: bad abreg=0x%x\n", abreg);
+	UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg);
 	return UNW_REG_LC;
 }
 
@@ -652,7 +668,7 @@
 			return;
 		}
 	}
-	dprintk("unwind: excess spill!\n");
+	UNW_DPRINT(0, "unwind.%s: excess spill!\n",  __FUNCTION__);
 }
 
 static inline void
@@ -720,7 +736,7 @@
 desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,
 	       struct unw_state_record *sr)
 {
-	int i;
+	int i, region_start;
 
 	if (!(sr->in_body || sr->first_region))
 		finish_prologue(sr);
@@ -732,19 +748,20 @@
 		return;
 	}
 
+	region_start = sr->region_start + sr->region_len;
+
 	for (i = 0; i < sr->epilogue_count; ++i)
 		pop(sr);
 	sr->epilogue_count = 0;
 	sr->epilogue_start = UNW_WHEN_NEVER;
 
-	if (!body)
-		push(sr);
-
-	sr->region_start += sr->region_len;
+	sr->region_start = region_start;
 	sr->region_len = rlen;
 	sr->in_body = body;
 
 	if (!body) {
+		push(sr);
+
 		for (i = 0; i < 4; ++i) {
 			if (mask & 0x8)
 				set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,
@@ -765,10 +782,13 @@
 static inline void
 desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
 {
-	if (abi == 0 && context == 'i')
+	if (abi == 0 && context == 'i') {
 		sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
+		UNW_DPRINT(3, "unwind.%s: interrupt frame\n",  __FUNCTION__);
+	}
 	else
-		dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context);
+		UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",
+				__FUNCTION__, abi, context);
 }
 
 static inline void
@@ -1136,6 +1156,9 @@
 	unsigned short index;
 	unsigned long ip, pr;
 
+	if (UNW_DEBUG_ON(0))
+		return 0;	/* Always regenerate scripts in debug mode */
+
 	STAT(++unw.stat.cache.lookups);
 
 	ip = info->ip;
@@ -1260,8 +1283,8 @@
 script_emit (struct unw_script *script, struct unw_insn insn)
 {
 	if (script->count >= UNW_MAX_SCRIPT_LEN) {
-		dprintk("unwind: script exceeds maximum size of %u instructions!\n",
-			UNW_MAX_SCRIPT_LEN);
+		UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",
+			__FUNCTION__, UNW_MAX_SCRIPT_LEN);
 		return;
 	}
 	script->insn[script->count++] = insn;
@@ -1302,7 +1325,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: don't know how to emit nat info for where = %u\n", r->where);
+		UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n",
+			   __FUNCTION__, r->where);
 		return;
 	}
 	insn.opc = opc;
@@ -1339,8 +1363,9 @@
 			}
 			val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
 		} else {
-			opc = UNW_INSN_ADD_SP;
-			val = -sizeof(struct pt_regs) + pt_regs_off(rval);
+			/* register got spilled to a scratch register */
+			opc = UNW_INSN_MOVE_SCRATCH;
+			val = pt_regs_off(rval);
 		}
 		break;
 
@@ -1350,12 +1375,12 @@
 		else if (rval >= 16 && rval <= 31)
 			val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
 		else {
-			opc = UNW_INSN_ADD_SP;
-			val = -sizeof(struct pt_regs);
+			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval <= 9)
-				val += struct_offset(struct pt_regs, f6) + 16*(rval - 6);
+				val = struct_offset(struct pt_regs, f6) + 16*(rval - 6);
 			else
-				dprintk("unwind: kernel may not touch f%lu\n", rval);
+				UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
+					   __FUNCTION__, rval);
 		}
 		break;
 
@@ -1363,14 +1388,13 @@
 		if (rval >= 1 && rval <= 5)
 			val = unw.preg_index[UNW_REG_B1 + (rval - 1)];
 		else {
-			opc = UNW_INSN_ADD_SP;
-			val = -sizeof(struct pt_regs);
+			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval == 0)
-				val += struct_offset(struct pt_regs, b0);
+				val = struct_offset(struct pt_regs, b0);
 			else if (rval == 6)
-				val += struct_offset(struct pt_regs, b6);
+				val = struct_offset(struct pt_regs, b6);
 			else
-				val += struct_offset(struct pt_regs, b7);
+				val = struct_offset(struct pt_regs, b7);
 		}
 		break;
 
@@ -1383,7 +1407,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: register %u has unexpected `where' value of %u\n", i, r->where);
+		UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n",
+			   __FUNCTION__, i, r->where);
 		break;
 	}
 	insn.opc = opc;
@@ -1456,9 +1481,10 @@
 		r->when = UNW_WHEN_NEVER;
 	sr.pr_val = info->pr;
 
+	UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip);
 	script = script_new(ip);
 	if (!script) {
-		dprintk("unwind: failed to create unwind script\n");
+		UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n",  __FUNCTION__);
 		STAT(unw.stat.script.build_time += ia64_get_itc() - start);
 		return 0;
 	}
@@ -1476,8 +1502,8 @@
 	}
 	if (!e) {
 		/* no info, return default unwinder (leaf proc, no mem stack, no saved regs)  */
-		dprintk("unwind: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", ip,
-			unw.cache[info->prev_script].ip);
+		UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n",
+			__FUNCTION__, ip, unw.cache[info->prev_script].ip);
 		sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
 		sr.curr.reg[UNW_REG_RP].when = -1;
 		sr.curr.reg[UNW_REG_RP].val = 0;
@@ -1525,26 +1551,32 @@
 		sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
 		sr.curr.reg[UNW_REG_RP].when = -1;
 		sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg;
+		UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n",
+			   __FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where,
+			   sr.curr.reg[UNW_REG_RP].val);
 	}
 
-#if UNW_DEBUG
-	printk("unwind: state record for func 0x%lx, t=%u:\n",
-	       table->segment_base + e->start_offset, sr.when_target);
+#ifdef UNW_DEBUG
+	UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n",
+		__FUNCTION__, table->segment_base + e->start_offset, sr.when_target);
 	for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) {
 		if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) {
-			printk("  %s <- ", unw.preg_name[r - sr.curr.reg]);
+			UNW_DPRINT(1, "  %s <- ", unw.preg_name[r - sr.curr.reg]);
 			switch (r->where) {
-			      case UNW_WHERE_GR:     printk("r%lu", r->val); break;
-			      case UNW_WHERE_FR:     printk("f%lu", r->val); break;
-			      case UNW_WHERE_BR:     printk("b%lu", r->val); break;
-			      case UNW_WHERE_SPREL:  printk("[sp+0x%lx]", r->val); break;
-			      case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break;
+			      case UNW_WHERE_GR:     UNW_DPRINT(1, "r%lu", r->val); break;
+			      case UNW_WHERE_FR:     UNW_DPRINT(1, "f%lu", r->val); break;
+			      case UNW_WHERE_BR:     UNW_DPRINT(1, "b%lu", r->val); break;
+			      case UNW_WHERE_SPREL:  UNW_DPRINT(1, "[sp+0x%lx]", r->val); break;
+			      case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break;
 			      case UNW_WHERE_NONE:
-				printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
+				UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
+				break;
+
+			      default:
+				UNW_DPRINT(1, "BADWHERE(%d)", r->where);
 				break;
-			      default:		     printk("BADWHERE(%d)", r->where); break;
 			}
-			printk("\t\t%d\n", r->when);
+			UNW_DPRINT(1, "\t\t%d\n", r->when);
 		}
 	}
 #endif
@@ -1642,6 +1674,16 @@
 			s[dst] = s[val];
 			break;
 
+		      case UNW_INSN_MOVE_SCRATCH:
+			if (state->pt) {
+				s[dst] = (unsigned long) get_scratch_regs(state) + val;
+			} else {
+				s[dst] = 0;
+				UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n",
+					   __FUNCTION__, dst, val);
+			}
+			break;
+
 		      case UNW_INSN_MOVE_STACKED:
 			s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
 								    val);
@@ -1667,11 +1709,12 @@
 			break;
 
 		      case UNW_INSN_LOAD:
-#if UNW_DEBUG
+#ifdef UNW_DEBUG
 			if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
 			    || s[val] < TASK_SIZE)
 			{
-				debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]);
+				UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n",
+					   __FUNCTION__, s[val]);
 				break;
 			}
 #endif
@@ -1704,7 +1747,8 @@
 
 	if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
 		/* don't let obviously bad addresses pollute the cache */
-		debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip);
+		/* FIXME: should really be level 0 but it occurs too often. KAO */
+		UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
 		info->rp_loc = 0;
 		return -1;
 	}
@@ -1713,8 +1757,9 @@
 	if (!scr) {
 		scr = build_script(info);
 		if (!scr) {
-			dprintk("unwind: failed to locate/build unwind script for ip %lx\n",
-				info->ip);
+			UNW_DPRINT(0,
+				   "unwind.%s: failed to locate/build unwind script for ip %lx\n",
+				   __FUNCTION__, info->ip);
 			return -1;
 		}
 		have_write_lock = 1;
@@ -1747,7 +1792,9 @@
 
 	/* restore the ip */
 	if (!info->rp_loc) {
-		debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip);
+		/* FIXME: should really be level 0 but it occurs too often. KAO */
+		UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
+			   __FUNCTION__, info->ip);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1757,14 +1804,14 @@
 		 * We don't have unwind info for the gate page, so we consider that part
 		 * of user-space for the purpose of unwinding.
 		 */
-		debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip);
+		UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
 
 	/* restore the cfm: */
 	if (!info->pfs_loc) {
-		dprintk("unwind: failed to locate ar.pfs!\n");
+		UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1774,16 +1821,18 @@
 	pr = info->pr;
 	num_regs = 0;
 	if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) {
+		info->pt = info->sp + 16;
 		if ((pr & (1UL << pNonSys)) != 0)
 			num_regs = *info->cfm_loc & 0x7f;		/* size of frame */
 		info->pfs_loc =
-			(unsigned long *) (info->sp + 16 + struct_offset(struct pt_regs, ar_pfs));
+			(unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs));
+		UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt);
 	} else
 		num_regs = (*info->cfm_loc >> 7) & 0x7f;	/* size of locals */
 	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs);
 	if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) {
-		dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
-			info->bsp, info->regstk.limit, info->regstk.top);
+		UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
+			__FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1791,14 +1840,15 @@
 	/* restore the sp: */
 	info->sp = info->psp;
 	if (info->sp < info->memstk.top || info->sp > info->memstk.limit) {
-		dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
-			info->sp, info->memstk.top, info->memstk.limit);
+		UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
+			__FUNCTION__, info->sp, info->memstk.top, info->memstk.limit);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
 
 	if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) {
-		dprintk("unwind: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", ip);
+		UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n",
+			   __FUNCTION__, ip);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1822,7 +1872,8 @@
 	while (unw_unwind(info) >= 0) {
 		if (unw_get_rp(info, &ip) < 0) {
 			unw_get_ip(info, &ip);
-			dprintk("unwind: failed to read return pointer (ip=0x%lx)\n", ip);
+			UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
+				   __FUNCTION__, ip);
 			return -1;
 		}
 		/*
@@ -1833,7 +1884,7 @@
 			return 0;
 	}
 	unw_get_ip(info, &ip);
-	dprintk("unwind: failed to unwind to user-level (ip=0x%lx)\n", ip);
+	UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
 	return -1;
 }
 
@@ -1874,11 +1925,30 @@
 	info->task = t;
 	info->sw  = sw;
 	info->sp = info->psp = (unsigned long) (sw + 1) - 16;
+	info->pt = 0;
 	info->cfm_loc = &sw->ar_pfs;
 	sol = (*info->cfm_loc >> 7) & 0x7f;
 	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
 	info->ip = sw->b0;
 	info->pr = sw->pr;
+	UNW_DPRINT(3,
+			"unwind.%s\n"
+			"  rbslimit 0x%lx\n"
+			"  rbstop   0x%lx\n"
+			"  stklimit 0x%lx\n"
+			"  stktop   0x%lx\n"
+			"  task     0x%lx\n"
+			"  sw       0x%lx\n",
+			__FUNCTION__, rbslimit, rbstop, stklimit, stktop,
+			(unsigned long)(info->task),
+			(unsigned long)(info->sw));
+	UNW_DPRINT(3,
+			"  sp/psp   0x%lx\n"
+			"  sol      0x%lx\n"
+			"  bsp      0x%lx\n"
+			"  ip       0x%lx\n"
+			"  pr       0x%lx\n",
+			info->sp, sol, info->bsp, info->ip, info->pr);
 
 	find_save_locs(info);
 	STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
@@ -1889,6 +1959,7 @@
 {
 	struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
 
+	UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__);
 	unw_init_frame_info(info, t, sw);
 }
 
@@ -1916,7 +1987,8 @@
 	unsigned long flags;
 
 	if (end - start <= 0) {
-		dprintk("unwind: ignoring attempt to insert empty unwind table\n");
+		UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
+			   __FUNCTION__);
 		return 0;
 	}
 
@@ -1946,13 +2018,15 @@
 	long index;
 
 	if (!handle) {
-		dprintk("unwind: ignoring attempt to remove non-existent unwind table\n");
+		UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n",
+			   __FUNCTION__);
 		return;
 	}
 
 	table = handle;
 	if (table == &unw.kernel_table) {
-		dprintk("unwind: sorry, freeing the kernel's unwind table is a no-can-do!\n");
+		UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a "
+			   "no-can-do!\n", __FUNCTION__);
 		return;
 	}
 
@@ -1964,7 +2038,8 @@
 			if (prev->next == table)
 				break;
 		if (!prev) {
-			dprintk("unwind: failed to find unwind table %p\n", (void *) table);
+			UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n",
+				   __FUNCTION__, (void *) table);
 			spin_unlock_irqrestore(&unw.lock, flags);
 			return;
 		}
diff -Nru a/arch/ia64/kernel/unwind_i.h b/arch/ia64/kernel/unwind_i.h
--- a/arch/ia64/kernel/unwind_i.h	Tue Apr  2 10:57:30 2002
+++ b/arch/ia64/kernel/unwind_i.h	Mon Mar  3 16:00:00 2003
@@ -137,7 +137,8 @@
 	UNW_INSN_SETNAT_MEMSTK,		/* s[dst+1].nat.type = MEMSTK;
 					   s[dst+1].nat.off = *s.pri_unat - s[dst] */
 	UNW_INSN_SETNAT_TYPE,		/* s[dst+1].nat.type = val */
-	UNW_INSN_LOAD			/* s[dst] = *s[val] */
+	UNW_INSN_LOAD,			/* s[dst] = *s[val] */
+	UNW_INSN_MOVE_SCRATCH,		/* s[dst] = scratch reg "val" */
 };
 
 struct unw_insn {
diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
--- a/arch/ia64/mm/fault.c	Tue Feb  4 17:06:20 2003
+++ b/arch/ia64/mm/fault.c	Thu Feb 13 05:43:47 2003
@@ -55,7 +55,7 @@
 	/*
 	 * If we're in an interrupt or have no user context, we must not take the fault..
 	 */
-	if (in_interrupt() || !mm)
+	if (in_atomic() || !mm)
 		goto no_context;
 
 	down_read(&mm->mmap_sem);
@@ -79,7 +79,7 @@
 
 #	if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \
 	    || (1 << VM_EXEC_BIT) != VM_EXEC)
-#		error File is out of sync with <linux/mm.h>.  Pleaes update.
+#		error File is out of sync with <linux/mm.h>.  Please update.
 #	endif
 
 	mask = (  (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
--- a/arch/ia64/mm/hugetlbpage.c	Mon Feb 24 23:13:11 2003
+++ b/arch/ia64/mm/hugetlbpage.c	Thu Mar  6 13:34:27 2003
@@ -19,6 +19,8 @@
 
 #include <linux/sysctl.h>
 
+#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT)
+
 static long    htlbpagemem;
 int     htlbpage_max;
 static long    htlbzone_pages;
@@ -98,7 +100,6 @@
 	set_pte(page_table, entry);
 	return;
 }
-
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -108,6 +109,20 @@
 		return -EINVAL;
 	if (addr & ~HPAGE_MASK)
 		return -EINVAL;
+	if (REGION_NUMBER(addr) != REGION_HPAGE)
+		return -EINVAL;
+
+	return 0;
+}
+/* This function checks if the address and address+len falls out of HugeTLB region.  It
+ * return -EINVAL if any part of address range falls in HugeTLB region.
+ */
+int  is_invalid_hugepage_range(unsigned long addr, unsigned long len)
+{
+	if (REGION_NUMBER(addr) == REGION_HPAGE)
+		return -EINVAL;
+	if (REGION_NUMBER(addr+len) == REGION_HPAGE)
+		return -EINVAL;
 	return 0;
 }
 
@@ -173,6 +188,39 @@
 	return i;
 }
 
+struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long addr)
+{
+	if (mm->used_hugetlb) {
+		if (REGION_NUMBER(addr) == REGION_HPAGE) {
+			struct vm_area_struct *vma = find_vma(mm, addr);
+			if (vma && is_vm_hugetlb_page(vma))
+				return vma;
+		}
+	}
+	return NULL;
+}
+
+struct page *follow_huge_addr(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, int write)
+{
+	struct page *page;
+	pte_t *ptep;
+
+	ptep = huge_pte_offset(mm, addr);
+	page = pte_page(*ptep);
+	page += ((addr & ~HPAGE_MASK) >> PAGE_SHIFT);
+	get_page(page);
+	return page;
+}
+int pmd_huge(pmd_t pmd)
+{
+	return 0;
+}
+struct page *
+follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
+{
+	return NULL;
+}
+
 void free_huge_page(struct page *page)
 {
 	BUG_ON(page_count(page));
@@ -204,8 +252,6 @@
 	BUG_ON(start & (HPAGE_SIZE - 1));
 	BUG_ON(end & (HPAGE_SIZE - 1));
 
-	spin_lock(&htlbpage_lock);
-	spin_unlock(&htlbpage_lock);
 	for (address = start; address < end; address += HPAGE_SIZE) {
 		pte = huge_pte_offset(mm, address);
 		if (pte_none(*pte))
@@ -257,8 +303,12 @@
 				ret = -ENOMEM;
 				goto out;
 			}
-			add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
+			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
 			unlock_page(page);
+			if (ret) {
+				free_huge_page(page);
+				goto out;
+			}
 		}
 		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
 	}
@@ -267,6 +317,29 @@
 	return ret;
 }
 
+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
+		unsigned long pgoff, unsigned long flags)
+{
+	struct vm_area_struct *vmm;
+
+	if (len > RGN_MAP_LIMIT)
+		return -ENOMEM;
+	if (len & ~HPAGE_MASK)
+		return -EINVAL;
+	/* This code assumes that REGION_HPAGE != 0. */
+	if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
+		addr = TASK_HPAGE_BASE;
+	else
+		addr = ALIGN(addr, HPAGE_SIZE);
+	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+		/* At this point:  (!vmm || addr < vmm->vm_end). */
+		if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT)
+			return -ENOMEM;
+		if (!vmm || (addr + len) <= vmm->vm_start)
+			return addr;
+		addr = ALIGN(vmm->vm_end, HPAGE_SIZE);
+	}
+}
 void update_and_free_page(struct page *page)
 {
 	int j;
@@ -302,8 +375,8 @@
 				break;
 		}
 		page = list_entry(p, struct page, list);
-		if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem
-				map = page;
+		if (!PageHighMem(page))
+			map = page;
 	}
 	if (map) {
 		list_del(&map->list);
@@ -317,8 +390,8 @@
 
 int set_hugetlb_mem_size(int count)
 {
-	int j, lcount;
-	struct page *page, *map;
+	int  lcount;
+	struct page *page ;
 	extern long htlbzone_pages;
 	extern struct list_head htlbpage_freelist;
 
@@ -417,5 +490,4 @@
 
 struct vm_operations_struct hugetlb_vm_ops = {
 	.nopage =	hugetlb_nopage,
-	.close =	zap_hugetlb_resources,
 };
diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
--- a/arch/ia64/mm/tlb.c	Wed Nov 13 17:57:34 2002
+++ b/arch/ia64/mm/tlb.c	Thu Jan 30 06:14:13 2003
@@ -81,9 +81,13 @@
 	}
 	read_unlock(&tasklist_lock);
 	/* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
-	for (i = 0; i < NR_CPUS; ++i)
-		if (i != smp_processor_id())
-			per_cpu(ia64_need_tlb_flush, i) = 1;
+	{
+		int cpu = get_cpu(); /* prevent preemption/migration */
+		for (i = 0; i < NR_CPUS; ++i)
+			if (i != cpu)
+				per_cpu(ia64_need_tlb_flush, i) = 1;
+		put_cpu();
+	}
 	local_flush_tlb_all();
 }
 
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c	Tue Nov  5 07:08:17 2002
+++ b/arch/ia64/pci/pci.c	Sun Mar 16 14:16:30 2003
@@ -143,21 +143,7 @@
 	return;
 }
 
-void __devinit
-pcibios_update_resource (struct pci_dev *dev, struct resource *root,
-			 struct resource *res, int resource)
-{
-	unsigned long where, size;
-	u32 reg;
-
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
-	size = res->end - res->start;
-	pci_read_config_dword(dev, where, &reg);
-	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-	pci_write_config_dword(dev, where, reg);
-
-	/* ??? FIXME -- record old value for shutdown.  */
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
 
 void __devinit
 pcibios_update_irq (struct pci_dev *dev, int irq)
@@ -167,11 +153,6 @@
 	/* ??? FIXME -- record old value for shutdown.  */
 }
 
-void __devinit
-pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
-{
-}
-
 static inline int
 pcibios_enable_resources (struct pci_dev *dev, int mask)
 {
@@ -271,4 +252,77 @@
 		return -EAGAIN;
 
 	return 0;
+}
+
+/**
+ * pci_cacheline_size - determine cacheline size for PCI devices
+ * @dev: void
+ *
+ * We want to use the line-size of the outer-most cache.  We assume
+ * that this line-size is the same for all CPUs.
+ *
+ * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
+ *
+ * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
+ */
+static unsigned long
+pci_cacheline_size (void)
+{
+	u64 levels, unique_caches;
+	s64 status;
+	pal_cache_config_info_t cci;
+	static u8 cacheline_size;
+
+	if (cacheline_size)
+		return cacheline_size;
+
+	status = ia64_pal_cache_summary(&levels, &unique_caches);
+	if (status != 0) {
+		printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
+		       __FUNCTION__, status);
+		return SMP_CACHE_BYTES;
+	}
+
+	status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2,
+					    &cci);
+	if (status != 0) {
+		printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n",
+		       __FUNCTION__, status);
+		return SMP_CACHE_BYTES;
+	}
+	cacheline_size = 1 << cci.pcci_line_size;
+	return cacheline_size;
+}
+
+/**
+ * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi()
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * For ia64, we can get the cacheline sizes from PAL.
+ *
+ * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
+ */
+int
+pcibios_prep_mwi (struct pci_dev *dev)
+{
+	unsigned long desired_linesize, current_linesize;
+	int rc = 0;
+	u8 pci_linesize;
+
+	desired_linesize = pci_cacheline_size();
+
+	pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize);
+	current_linesize = 4 * pci_linesize;
+	if (desired_linesize != current_linesize) {
+		printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,",
+		       dev->slot_name, current_linesize);
+		if (current_linesize > desired_linesize) {
+			printk(" expected %lu bytes instead\n", desired_linesize);
+			rc = -EINVAL;
+		} else {
+			printk(" correcting to %lu\n", desired_linesize);
+			pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4);
+		}
+	}
+	return rc;
 }
diff -Nru a/arch/ia64/sn/io/Makefile b/arch/ia64/sn/io/Makefile
--- a/arch/ia64/sn/io/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/ia64/sn/io/Makefile	Mon Feb 24 04:55:04 2003
@@ -17,6 +17,6 @@
 		hcl.o labelcl.o invent.o sgi_io_sim.o \
 		klgraph_hack.o hcl_util.o cdl.o hubdev.o hubspc.o \
 		alenlist.o pci.o pci_dma.o ate_utils.o \
-		ifconfig_net.o io.o ifconfig_bus.o
+		ifconfig_net.o io.o ioconfig_bus.o
 
 obj-$(CONFIG_PCIBA)		+= pciba.o
diff -Nru a/arch/ia64/sn/io/ioconfig_bus.c b/arch/ia64/sn/io/ioconfig_bus.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/ioconfig_bus.c	Mon Feb 24 04:55:13 2003
@@ -0,0 +1,402 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ *  ioconfig_bus - SGI's Persistent PCI Bus Numbering.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+
+#include <asm/sn/sgi.h>
+#include <linux/devfs_fs.h>
+#include <linux/devfs_fs_kernel.h>
+#include <asm/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm//sn/sn_sal.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/ioconfig_bus.h>
+
+#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
+#define SGI_IOCONFIG_BUS_VERSION "1.0"
+
+/*
+ * Some Global definitions.
+ */
+devfs_handle_t ioconfig_bus_handle = NULL;
+unsigned long ioconfig_bus_debug = 0;
+
+#ifdef IOCONFIG_BUS_DEBUG
+#define DBG(x...)	printk(x)
+#else
+#define DBG(x...)
+#endif
+
+u64 ioconfig_file = 0;
+u64 ioconfig_file_size = 0;
+u64 ioconfig_activated = 0;
+char ioconfig_kernopts[128];
+
+/*
+ * For debugging purpose .. hardcode a table ..
+ */
+struct  ascii_moduleid *ioconfig_bus_table;
+u64 ioconfig_bus_table_size = 0;
+
+
+int free_entry = 0;
+int new_entry = 0;
+
+int next_basebus_number = 0;
+
+void
+ioconfig_get_busnum(char *io_moduleid, int *bus_num)
+{
+	struct	ascii_moduleid  *temp;
+	int index;
+
+	DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
+
+	*bus_num = -1;
+	temp = ioconfig_bus_table;
+	for (index = 0; index < free_entry; temp++, index++) {
+		if ( (io_moduleid[0] == temp->io_moduleid[0]) &&
+		     (io_moduleid[1] == temp->io_moduleid[1]) &&
+		     (io_moduleid[2] == temp->io_moduleid[2]) &&
+		     (io_moduleid[4] == temp->io_moduleid[4]) &&
+		     (io_moduleid[5] == temp->io_moduleid[5]) ) {
+			*bus_num = index * 0x10;
+			return;
+		}
+	}
+
+	/*
+	 * New IO Brick encountered.
+	 */
+	if (((int)io_moduleid[0]) == 0) {
+		DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
+		return;
+	}
+
+	io_moduleid[3] = '#';
+	strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid);
+	*bus_num = free_entry * 0x10;
+	free_entry++;
+}
+
+void
+dump_ioconfig_table()
+{
+
+	int index = 0;
+	struct ascii_moduleid *temp;
+
+	temp = ioconfig_bus_table;
+	while (index < free_entry) {
+		DBG("ASSCI Module ID %s\n", temp->io_moduleid);
+		temp++;
+		index++;
+	}
+}
+
+/*
+ * nextline
+ *	This routine returns the nextline in the buffer.
+ */
+int nextline(char *buffer, char **next, char *line)
+{
+
+	char *temp;
+
+	if (buffer[0] == 0x0) {
+		return(0);
+	}
+
+	temp = buffer;
+	while (*temp != 0) {
+		*line = *temp;
+		if (*temp != '\n'){
+			*line = *temp;
+			temp++; line++;
+		} else
+			break;
+	}
+
+	if (*temp == 0)
+		*next = temp;
+	else
+		*next = ++temp;
+
+	return(1);
+}
+
+/*
+ * build_pcibus_name
+ *	This routine parses the ioconfig contents read into
+ *	memory by ioconfig command in EFI and builds the
+ *	persistent pci bus naming table.
+ */
+void
+build_moduleid_table(char *file_contents, struct ascii_moduleid *table)
+{
+	/*
+	 * Read the whole file into memory.
+	 */
+	int rc;
+	char *name;
+	char *temp;
+	char *next;
+	char *current;
+	char *line;
+	struct ascii_moduleid *moduleid;
+
+	line = kmalloc(256, GFP_KERNEL);
+	memset(line, 0,256);
+	name = kmalloc(125, GFP_KERNEL);
+	memset(name, 0, 125);
+	moduleid = table;
+	current = file_contents;
+	while (nextline(current, &next, line)){
+
+		DBG("current 0x%lx next 0x%lx\n", current, next);
+
+		temp = line;
+		/*
+		 * Skip all leading Blank lines ..
+		 */
+		while (isspace(*temp))
+			if (*temp != '\n')
+				temp++;
+			else
+				break;
+
+		if (*temp == '\n') {
+			current = next;
+			memset(line, 0, 256);
+			continue;
+		}
+ 
+		/*
+		 * Skip comment lines
+		 */
+		if (*temp == '#') {
+			current = next;
+			memset(line, 0, 256);
+			continue;
+		}
+
+		/*
+		 * Get the next free entry in the table.
+		 */
+		rc = sscanf(temp, "%s", name);
+		strcpy(&moduleid->io_moduleid[0], name);
+		DBG("Found %s\n", name);
+		moduleid++;
+		free_entry++;
+		current = next;
+		memset(line, 0, 256);
+	}
+
+	new_entry = free_entry;
+	kfree(line);
+	kfree(name);
+
+	return;
+}
+
+void
+ioconfig_bus_init(void)
+{
+
+	struct ia64_sal_retval ret_stuff;
+	u64	*temp;
+	int	cnode;
+
+	DBG("ioconfig_bus_init called.\n");
+
+        for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid_t nasid;
+		/*
+	 	 * Make SAL call to get the address of the bus configuration table.
+	 	 */
+		ret_stuff.status = (uint64_t)0;
+		ret_stuff.v0 = (uint64_t)0;
+		ret_stuff.v1 = (uint64_t)0;
+		ret_stuff.v2 = (uint64_t)0;
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+		SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0);
+		temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0);
+		ioconfig_file = *temp;
+		DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid,
+			ret_stuff.v0);
+		if (ioconfig_file) {
+			ioconfig_file_size = ret_stuff.v1;
+			ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE);
+			ioconfig_activated = 1;
+			break;
+		}
+	}
+
+	DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n",
+		ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size);
+
+	ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
+	memset(ioconfig_bus_table, 0, 512);
+
+	/*
+	 * If ioconfig options are given on the bootline .. take it.
+	 */
+	if (*ioconfig_kernopts != '\0') {
+		/*
+		 * ioconfig="..." kernel options given.
+		 */
+		DBG("ioconfig_bus_init: Kernel Options given.\n");
+		(void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table);
+		(void) dump_ioconfig_table(ioconfig_bus_table);
+		return;
+	}
+
+	if (ioconfig_activated) {
+		DBG("ioconfig_bus_init: ioconfig file given.\n");
+		(void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table);
+		(void) dump_ioconfig_table(ioconfig_bus_table);
+	} else {
+		DBG("ioconfig_bus_init: ioconfig command not executed in prom\n");
+	}
+
+}
+
+void
+ioconfig_bus_new_entries(void)
+{
+
+	
+	int index = 0;
+	struct ascii_moduleid *temp;
+
+	if ((ioconfig_activated) && (free_entry > new_entry)) {
+		printk("### Please add the following new IO Bricks Module ID \n");
+		printk("### to your Persistent Bus Numbering Config File\n");
+	} else
+		return;
+
+	index = new_entry;
+	temp = &ioconfig_bus_table[index];
+        while (index < free_entry) {
+                printk("%s\n", temp);
+		temp++;
+                index++;
+        }
+	printk("### End\n");
+
+}
+static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
+        unsigned int cmd, unsigned long arg)
+{
+
+	struct ioconfig_parm parm;
+
+	/*
+	 * Copy in the parameters.
+	 */
+	copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm));
+	parm.number = free_entry - new_entry;
+	parm.ioconfig_activated = ioconfig_activated;
+	copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm));
+	copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct  ascii_moduleid) * (free_entry - new_entry));
+
+	return 0;
+}
+
+/*
+ * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
+ */
+static int ioconfig_bus_open(struct inode * inode, struct file * filp)
+{
+	if (ioconfig_bus_debug) {
+        	DBG("ioconfig_bus_open called.\n");
+	}
+
+        return(0);
+
+}
+
+/*
+ * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
+ */
+static int ioconfig_bus_close(struct inode * inode, struct file * filp)
+{
+
+	if (ioconfig_bus_debug) {
+        	DBG("ioconfig_bus_close called.\n");
+	}
+
+        return(0);
+}
+
+struct file_operations ioconfig_bus_fops = {
+	ioctl:ioconfig_bus_ioctl,
+	open:ioconfig_bus_open,		/* open */
+	release:ioconfig_bus_close	/* release */
+};
+
+
+/*
+ * init_ifconfig_bus() - Boot time initialization.  Ensure that it is called 
+ *	after devfs has been initialized.
+ *
+ */
+int init_ioconfig_bus(void)
+{
+	ioconfig_bus_handle = NULL;
+	ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus",
+			0, DEVFS_FL_AUTO_DEVNUM,
+			0, 0,
+			S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+			&ioconfig_bus_fops, NULL);
+
+	if (ioconfig_bus_handle == NULL) {
+		panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
+	}
+
+	return(0);
+
+}
+
+static int __init ioconfig_bus_setup (char *str)
+{
+
+	char *temp;
+
+	DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
+
+	temp = (char *)ioconfig_kernopts;
+	memset(temp, 0, 128);
+	while ( (*str != '\0') && !isspace (*str) ) {
+		if (*str == ',') {
+			*temp = '\n';
+			temp++;
+			str++;
+			continue;
+		}
+		*temp = *str;
+		temp++;
+		str++;
+	}
+
+	return(0);
+		
+}
+__setup("ioconfig=", ioconfig_bus_setup);
diff -Nru a/arch/ia64/sn/io/sn2/Makefile b/arch/ia64/sn/io/sn2/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/Makefile	Mon Feb 24 05:40:29 2003
@@ -0,0 +1,19 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# Makefile for the sn2 specific io routines.
+
+EXTRA_CFLAGS    := -DLITTLE_ENDIAN
+
+obj-y += bte_error.o geo_op.o klconflib.o klgraph.o l1.o \
+	 l1_command.o ml_iograph.o ml_SN_init.o ml_SN_intr.o module.o \
+	 pci_bus_cvlink.o pciio.o pic.o sgi_io_init.o shub.o shuberror.o \
+	 shub_intr.o shubio.o xbow.o xtalk.o
+
+obj-$(CONFIG_KDB) += kdba_io.o 
+
+obj-$(CONFIG_SHUB_1_0_SPECIFIC) += efi-rtc.o
diff -Nru a/arch/ia64/sn/io/sn2/geo_op.c b/arch/ia64/sn/io/sn2/geo_op.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/geo_op.c	Mon Feb 24 05:23:08 2003
@@ -0,0 +1,314 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * @doc file m:hwcfg
+ * DESCRIPTION:
+ * 
+ * This file contains routines for manipulating and generating 
+ * Geographic IDs.  They are in a file by themself since they have
+ * no dependencies on other modules.
+ *  
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/smp.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
+#include <asm/sn/types.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn2/shub_mmr_t.h>
+#include <asm/sn/sn2/shubio.h>
+#include <asm/sal.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/module.h>
+#include <asm/sn/geo.h>
+
+/********** Global functions and data (visible outside the module) ***********/
+
+/*
+ * @doc gf:geo_module
+ * 
+ * moduleid_t geo_module(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return the moduleid component of a geoid.
+ *  
+ * INTERNALS:
+ * 
+ * Return INVALID_MODULE for an invalid geoid.  Otherwise extract the
+ * moduleid from the structure, and return it.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+moduleid_t
+geo_module(geoid_t g)
+{
+    if (g.any.type == GEO_TYPE_INVALID)
+	return INVALID_MODULE;
+    else
+	return g.any.module;
+}
+
+
+/*
+ * @doc gf:geo_slab
+ * 
+ * slabid_t geo_slab(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return the slabid component of a geoid.
+ *  
+ * INTERNALS:
+ * 
+ * Return INVALID_SLAB for an invalid geoid.  Otherwise extract the
+ * slabid from the structure, and return it.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+slabid_t
+geo_slab(geoid_t g)
+{
+    if (g.any.type == GEO_TYPE_INVALID)
+	return INVALID_SLAB;
+    else
+	return g.any.slab;
+}
+
+
+/*
+ * @doc gf:geo_type
+ * 
+ * geo_type_t geo_type(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return the type component of a geoid.
+ *  
+ * INTERNALS:
+ * 
+ * Extract the type from the structure, and return it.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+geo_type_t
+geo_type(geoid_t g)
+{
+    return g.any.type;
+}
+
+
+/*
+ * @doc gf:geo_valid
+ * 
+ * int geo_valid(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return nonzero if g has a valid geoid type.
+ *  
+ * INTERNALS:
+ * 
+ * Test the type against GEO_TYPE_INVALID, and return the result.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+int
+geo_valid(geoid_t g)
+{
+    return g.any.type != GEO_TYPE_INVALID;
+}
+
+
+/*
+ * @doc gf:geo_cmp
+ * 
+ * int geo_cmp(geoid_t g0, geoid_t g1)
+ * 
+ * DESCRIPTION:
+ * 
+ * Compare two geoid_t values, from the coarsest field to the finest.
+ * The comparison should be consistent with the physical locations of
+ * of the hardware named by the geoids.
+ *  
+ * INTERNALS:
+ * 
+ * First compare the module, then the slab, type, and type-specific fields.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+int
+geo_cmp(geoid_t g0, geoid_t g1)
+{
+    int rv;
+
+    /* Compare the common fields */
+    rv = MODULE_CMP(geo_module(g0), geo_module(g1));
+    if (rv != 0)
+	return rv;
+
+    rv = geo_slab(g0) - geo_slab(g1);
+    if (rv != 0)
+	return rv;
+
+    /* Within a slab, sort by type */
+    rv = geo_type(g0) - geo_type(g1);
+    if (rv != 0)
+	return rv;
+
+    switch(geo_type(g0)) {
+    case GEO_TYPE_CPU:
+	rv = g0.cpu.slice - g1.cpu.slice;
+	break;
+
+    case GEO_TYPE_IOCARD:
+	rv = g0.pcicard.bus - g1.pcicard.bus;
+	if (rv) break;
+	rv = SLOTNUM_GETSLOT(g0.pcicard.slot) -
+	    SLOTNUM_GETSLOT(g1.pcicard.slot);
+	break;
+
+    case GEO_TYPE_MEM:
+	rv = g0.mem.membus - g1.mem.membus;
+	if (rv) break;
+	rv = g0.mem.memslot - g1.mem.memslot;
+	break;
+
+    default:
+	rv = 0;
+    }
+
+    return rv;
+}
+
+
+/*
+ * @doc gf:geo_new
+ * 
+ * geoid_t geo_new(geo_type_t type, ...)
+ * 
+ * DESCRIPTION:
+ * 
+ * Generate a new geoid_t value of the given type from its components.
+ * Expected calling sequences:
+ * \@itemize \@bullet
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_INVALID)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_MODULE, moduleid_t m)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_NODE, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_RTR, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_IOCNTL, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_IOCARD, moduleid_t m, slabid_t s, char bus, slotid_t slot)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_CPU, moduleid_t m, slabid_t s, char slice)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_MEM, moduleid_t m, slabid_t s, char membus, char slot)\}
+ * \@end itemize
+ *
+ * Invalid types return a GEO_TYPE_INVALID geoid_t.
+ *  
+ * INTERNALS:
+ * 
+ * Use the type to determine which fields to expect.  Write the fields into
+ * a new geoid_t and return it.  Note:  scalars smaller than an "int" are
+ * promoted to "int" by the "..." operator, so we need extra casts on "char",
+ * "slotid_t", and "slabid_t".
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+geoid_t
+geo_new(geo_type_t type, ...)
+{
+    va_list al;
+    geoid_t g;
+    memset(&g, 0, sizeof(g));
+
+    va_start(al, type);
+
+    /* Make sure the type is sane */
+    if (type >= GEO_TYPE_MAX)
+	type = GEO_TYPE_INVALID;
+
+    g.any.type = type;
+    if (type == GEO_TYPE_INVALID)
+	goto done;		/* invalid geoids have no components at all */
+
+    g.any.module = va_arg(al, moduleid_t);
+    if (type == GEO_TYPE_MODULE)
+	goto done;
+
+    g.any.slab = (slabid_t)va_arg(al, int);
+
+    /* Some types have additional components */
+    switch(type) {
+    case GEO_TYPE_CPU:
+	g.cpu.slice = (char)va_arg(al, int);
+	break;
+
+    case GEO_TYPE_IOCARD:
+	g.pcicard.bus = (char)va_arg(al, int);
+	g.pcicard.slot = (slotid_t)va_arg(al, int);
+	break;
+
+    case GEO_TYPE_MEM:
+	g.mem.membus = (char)va_arg(al, int);
+	g.mem.memslot = (char)va_arg(al, int);
+	break;
+
+    default:
+	break;
+    }
+
+ done:
+    va_end(al);
+    return g;
+}
diff -Nru a/arch/ia64/sn/io/sn2/klconflib.c b/arch/ia64/sn/io/sn2/klconflib.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/klconflib.c	Mon Feb 24 05:23:53 2003
@@ -0,0 +1,933 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/module.h>
+#include <asm/sn/router.h>
+#include <asm/sn/xtalk/xbow.h>
+
+#define printf printk
+int hasmetarouter;
+
+#define LDEBUG 0
+#define NIC_UNKNOWN ((nic_t) -1)
+
+#undef DEBUG_KLGRAPH
+#ifdef DEBUG_KLGRAPH
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG_KLGRAPH */
+
+static void sort_nic_names(lboard_t *) ;
+
+u64 klgraph_addr[MAX_COMPACT_NODES];
+int module_number = 0;
+
+lboard_t *
+find_lboard(lboard_t *start, unsigned char brd_type)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (start->brd_type == brd_type)
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_class(lboard_t *start, unsigned char brd_type)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+klinfo_t *
+find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
+{
+	int index, j;
+
+	if (kli == (klinfo_t *)NULL) {
+		index = 0;
+	} else {
+		for (j = 0; j < KLCF_NUM_COMPS(brd); j++) {
+			if (kli == KLCF_COMP(brd, j))
+				break;
+		}
+		index = j;
+		if (index == KLCF_NUM_COMPS(brd)) {
+			DBG("find_component: Bad pointer: 0x%p\n", kli);
+			return (klinfo_t *)NULL;
+		}
+		index++;	/* next component */
+	}
+	
+	for (; index < KLCF_NUM_COMPS(brd); index++) {		
+		kli = KLCF_COMP(brd, index);
+		DBG("find_component: brd %p kli %p  request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli));
+		if (KLCF_COMP_TYPE(kli) == struct_type)
+			return kli;
+	}
+
+	/* Didn't find it. */
+	return (klinfo_t *)NULL;
+}
+
+klinfo_t *
+find_first_component(lboard_t *brd, unsigned char struct_type)
+{
+	return find_component(brd, (klinfo_t *)NULL, struct_type);
+}
+
+lboard_t *
+find_lboard_modslot(lboard_t *start, geoid_t geoid)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (geo_cmp(start->brd_geoid, geoid))
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_module(lboard_t *start, geoid_t geoid)
+{
+        /* Search all boards stored on this node. */
+        while (start) {
+                if (geo_cmp(start->brd_geoid, geoid))
+                        return start;
+                start = KLCF_NEXT(start);
+        }
+
+        /* Didn't find it. */
+        return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_module_class(lboard_t *start, geoid_t geoid,
+                                                unsigned char brd_type)
+{
+	while (start) {
+		DBG("find_lboard_module_class: lboard 0x%p, start->brd_geoid 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_geoid, geoid, start->brd_type, brd_type);
+
+		if (geo_cmp(start->brd_geoid, geoid) &&
+			(KLCLASS(start->brd_type) == KLCLASS(brd_type)))
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+/*
+ * Convert a NIC name to a name for use in the hardware graph.
+ */
+void
+nic_name_convert(char *old_name, char *new_name)
+{
+        int i;
+        char c;
+        char *compare_ptr;
+
+	if ((old_name[0] == '\0') || (old_name[1] == '\0')) {
+                strcpy(new_name, EDGE_LBL_XWIDGET);
+        } else {
+                for (i = 0; i < strlen(old_name); i++) {
+                        c = old_name[i];
+
+                        if (isalpha(c))
+                                new_name[i] = tolower(c);
+                        else if (isdigit(c))
+                                new_name[i] = c;
+                        else
+                                new_name[i] = '_';
+                }
+                new_name[i] = '\0';
+        }
+
+        /* XXX -
+         * Since a bunch of boards made it out with weird names like
+         * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and
+         * replace it with "baseio" to avoid confusion in the field.
+	 * We also have to make sure we don't report media_io instead of
+	 * baseio.
+         */
+
+        /* Skip underscores at the beginning of the name */
+        for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++)
+                ;
+
+	/*
+	 * Check for some names we need to replace.  Early boards
+	 * had junk following the name so check only the first
+	 * characters.
+	 */
+        if (!strncmp(new_name, "io6", 3) || 
+            !strncmp(new_name, "mio", 3) || 
+	    !strncmp(new_name, "media_io", 8))
+		strcpy(new_name, "baseio");
+	else if (!strncmp(new_name, "divo", 4))
+		strcpy(new_name, "divo") ;
+
+}
+
+/*
+ * Find the lboard structure and get the board name.
+ * If we can't find the structure or it's too low a revision,
+ * use default name.
+ */
+lboard_t *
+get_board_name(nasid_t nasid, geoid_t geoid, slotid_t slot, char *name)
+{
+	lboard_t *brd;
+
+	brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid),
+				  geoid);
+
+#ifndef _STANDALONE
+	{
+		cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid);
+
+		if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID))
+			brd = find_lboard_modslot((lboard_t *)
+				KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer),
+				geoid);
+	}
+#endif
+
+	if (!brd || (brd->brd_sversion < 2)) {
+		strcpy(name, EDGE_LBL_XWIDGET);
+	} else {
+		nic_name_convert(brd->brd_name, name);
+	}
+
+	/*
+	 * PV # 540860
+	 * If the name is not 'baseio'
+	 * get the lowest of all the names in the nic string.
+	 * This is needed for boards like divo, which can have
+	 * a bunch of daughter cards, but would like to be called
+	 * divo. We could do this for baseio
+	 * but it has some special case names that we would not
+	 * like to disturb at this point.
+	 */
+
+	/* gfx boards don't need any of this name scrambling */
+	if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) {
+		return(brd);
+	}
+
+	if (!(!strcmp(name, "baseio") )) {
+		if (brd) {
+			sort_nic_names(brd) ;
+			/* Convert to small case, '-' to '_' etc */
+			nic_name_convert(brd->brd_name, name) ;
+		}
+	}
+
+	return(brd);
+}
+
+/*
+ * get_actual_nasid
+ *
+ *	Completely disabled brds have their klconfig on 
+ *	some other nasid as they have no memory. But their
+ *	actual nasid is hidden in the klconfig. Use this
+ *	routine to get it. Works for normal boards too.
+ */
+nasid_t
+get_actual_nasid(lboard_t *brd)
+{
+	klhub_t	*hub ;
+
+	if (!brd)
+		return INVALID_NASID ;
+
+	/* find out if we are a completely disabled brd. */
+
+        hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+	if (!hub)
+                return INVALID_NASID ;
+	if (!(hub->hub_info.flags & KLINFO_ENABLE))	/* disabled node brd */
+		return hub->hub_info.physid ;
+	else
+		return brd->brd_nasid ;
+}
+
+int
+xbow_port_io_enabled(nasid_t nasid, int link)
+{
+	lboard_t *brd;
+	klxbow_t *xbow_p;
+
+	/*
+	 * look for boards that might contain an xbow or xbridge
+	 */
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
+	if (brd == NULL) return 0;
+		
+	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
+	    == NULL)
+	    return 0;
+
+	if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
+	    return 0;
+
+	return 1;
+}
+
+void
+board_to_path(lboard_t *brd, char *path)
+{
+	moduleid_t modnum;
+	char *board_name;
+	char buffer[16];
+
+	ASSERT(brd);
+
+	switch (KLCLASS(brd->brd_type)) {
+
+		case KLCLASS_NODE:
+			board_name = EDGE_LBL_NODE;
+			break;
+		case KLCLASS_ROUTER:
+			if (brd->brd_type == KLTYPE_META_ROUTER) {
+				board_name = EDGE_LBL_META_ROUTER;
+				hasmetarouter++;
+			} else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
+				board_name = EDGE_LBL_REPEATER_ROUTER;
+				hasmetarouter++;
+			} else
+				board_name = EDGE_LBL_ROUTER;
+			break;
+		case KLCLASS_MIDPLANE:
+			board_name = EDGE_LBL_MIDPLANE;
+			break;
+		case KLCLASS_IO:
+			board_name = EDGE_LBL_IO;
+			break;
+		case KLCLASS_IOBRICK:
+			if (brd->brd_type == KLTYPE_PBRICK)
+				board_name = EDGE_LBL_PBRICK;
+			else if (brd->brd_type == KLTYPE_IBRICK)
+				board_name = EDGE_LBL_IBRICK;
+			else if (brd->brd_type == KLTYPE_XBRICK)
+				board_name = EDGE_LBL_XBRICK;
+			else
+				board_name = EDGE_LBL_IOBRICK;
+			break;
+		default:
+			board_name = EDGE_LBL_UNKNOWN;
+	}
+			
+	modnum = geo_module(brd->brd_geoid);
+	memset(buffer, 0, 16);
+	format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF);
+	sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name);
+}
+
+/*
+ * Get the module number for a NASID.
+ */
+moduleid_t
+get_module_id(nasid_t nasid)
+{
+	lboard_t *brd;
+
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+
+	if (!brd)
+		return INVALID_MODULE;
+	else
+		return geo_module(brd->brd_geoid);
+}
+
+
+#define MHZ	1000000
+
+
+/* Get the canonical hardware graph name for the given pci component
+ * on the given io board.
+ */
+void
+device_component_canonical_name_get(lboard_t 	*brd,
+				    klinfo_t 	*component,
+				    char 	*name)
+{
+	slotid_t 	slot;
+	char 		board_name[20];
+
+	ASSERT(brd);
+
+	/* Convert the [ CLASS | TYPE ] kind of slotid
+	 * into a string
+	 */
+	slot = brd->brd_slot;
+
+	/* Get the io board name  */
+	if (!brd || (brd->brd_sversion < 2)) {
+		strcpy(name, EDGE_LBL_XWIDGET);
+	} else {
+		nic_name_convert(brd->brd_name, board_name);
+	}
+
+	/* Give out the canonical  name of the pci device*/
+	sprintf(name,
+		"/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/"
+		EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d",
+		geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid), 
+		board_name, KLCF_BRIDGE_W_ID(component));
+}
+
+/*
+ * Get the serial number of the main  component of a board
+ * Returns 0 if a valid serial number is found
+ * 1 otherwise.
+ * Assumptions: Nic manufacturing string  has the following format
+ *			*Serial:<serial_number>;*
+ */
+static int
+component_serial_number_get(lboard_t 		*board,
+			    klconf_off_t 	mfg_nic_offset,
+			    char		*serial_number,
+			    char		*key_pattern)
+{
+
+	char	*mfg_nic_string;
+	char	*serial_string,*str;
+	int	i;
+	char	*serial_pattern = "Serial:";
+
+	/* We have an error on a null mfg nic offset */
+	if (!mfg_nic_offset)
+		return(1);
+	/* Get the hub's manufacturing nic information
+	 * which is in the form of a pre-formatted string
+	 */
+	mfg_nic_string = 
+		(char *)NODE_OFFSET_TO_K0(NASID_GET(board),
+					  mfg_nic_offset);
+	/* There is no manufacturing nic info */
+	if (!mfg_nic_string)
+		return(1);
+
+	str = mfg_nic_string;
+	/* Look for the key pattern first (if it is  specified)
+	 * and then print the serial number corresponding to that.
+	 */
+	if (strcmp(key_pattern,"") && 
+	    !(str = strstr(mfg_nic_string,key_pattern)))
+		return(1);
+
+	/* There is no serial number info in the manufacturing
+	 * nic info
+	 */
+	if (!(serial_string = strstr(str,serial_pattern)))
+		return(1);
+
+	serial_string = serial_string + strlen(serial_pattern);
+	/*  Copy the serial number information from the klconfig */
+	i = 0;
+	while (serial_string[i] != ';') {
+		serial_number[i] = serial_string[i];
+		i++;
+	}
+	serial_number[i] = 0;
+	
+	return(0);
+}
+/*
+ * Get the serial number of a board
+ * Returns 0 if a valid serial number is found
+ * 1 otherwise.
+ */
+
+int
+board_serial_number_get(lboard_t *board,char *serial_number)
+{
+	ASSERT(board && serial_number);
+	if (!board || !serial_number)
+		return(1);
+
+	strcpy(serial_number,"");
+	switch(KLCLASS(board->brd_type)) {
+	case KLCLASS_CPU: {	/* Node board */
+		klhub_t	*hub;
+		
+		/* Get the hub component information */
+		hub = (klhub_t *)find_first_component(board,
+						      KLSTRUCT_HUB);
+		/* If we don't have a hub component on an IP27
+		 * then we have a weird klconfig.
+		 */
+		if (!hub)
+			return(1);
+		/* Get the serial number information from
+		 * the hub's manufacturing nic info
+		 */
+		if (component_serial_number_get(board,
+						hub->hub_mfg_nic,
+						serial_number,
+						"IP37"))
+				return(1);
+		break;
+	}
+	case KLCLASS_IO: {	/* IO board */
+		if (KLTYPE(board->brd_type) == KLTYPE_TPU) {
+		/* Special case for TPU boards */
+			kltpu_t *tpu;	
+		
+			/* Get the tpu component information */
+			tpu = (kltpu_t *)find_first_component(board,
+						      KLSTRUCT_TPU);
+			/* If we don't have a tpu component on a tpu board
+			 * then we have a weird klconfig.
+			 */
+			if (!tpu)
+				return(1);
+			/* Get the serial number information from
+			 * the tpu's manufacturing nic info
+			 */
+			if (component_serial_number_get(board,
+						tpu->tpu_mfg_nic,
+						serial_number,
+						""))
+				return(1);
+			break;
+		} else  if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ||
+		            (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) {
+		/* Special case for GSN boards */
+			klgsn_t *gsn;	
+		
+			/* Get the gsn component information */
+			gsn = (klgsn_t *)find_first_component(board,
+			      ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ?
+					KLSTRUCT_GSN_A : KLSTRUCT_GSN_B));
+			/* If we don't have a gsn component on a gsn board
+			 * then we have a weird klconfig.
+			 */
+			if (!gsn)
+				return(1);
+			/* Get the serial number information from
+			 * the gsn's manufacturing nic info
+			 */
+			if (component_serial_number_get(board,
+						gsn->gsn_mfg_nic,
+						serial_number,
+						""))
+				return(1);
+			break;
+		} else {
+		     	klbri_t	*bridge;
+		
+			/* Get the bridge component information */
+			bridge = (klbri_t *)find_first_component(board,
+							 KLSTRUCT_BRI);
+			/* If we don't have a bridge component on an IO board
+			 * then we have a weird klconfig.
+			 */
+			if (!bridge)
+				return(1);
+			/* Get the serial number information from
+		 	 * the bridge's manufacturing nic info
+			 */
+			if (component_serial_number_get(board,
+						bridge->bri_mfg_nic,
+						serial_number,
+						""))
+				return(1);
+			break;
+		}
+	}
+	case KLCLASS_ROUTER: {	/* Router board */
+		klrou_t *router;	
+		
+		/* Get the router component information */
+		router = (klrou_t *)find_first_component(board,
+							 KLSTRUCT_ROU);
+		/* If we don't have a router component on a router board
+		 * then we have a weird klconfig.
+		 */
+		if (!router)
+			return(1);
+		/* Get the serial number information from
+		 * the router's manufacturing nic info
+		 */
+		if (component_serial_number_get(board,
+						router->rou_mfg_nic,
+						serial_number,
+						""))
+			return(1);
+		break;
+	}
+	case KLCLASS_GFX: {	/* Gfx board */
+		klgfx_t *graphics;
+		
+		/* Get the graphics component information */
+		graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX);
+		/* If we don't have a gfx component on a gfx board
+		 * then we have a weird klconfig.
+		 */
+		if (!graphics)
+			return(1);
+		/* Get the serial number information from
+		 * the graphics's manufacturing nic info
+		 */
+		if (component_serial_number_get(board,
+						graphics->gfx_mfg_nic,
+						serial_number,
+						""))
+			return(1);
+		break;
+	}
+	default:
+		strcpy(serial_number,"");
+		break;
+	}
+	return(0);
+}
+
+#include "asm/sn/sn_private.h"
+
+xwidgetnum_t
+nodevertex_widgetnum_get(devfs_handle_t node_vtx)
+{
+	hubinfo_t hubinfo_p;
+
+	hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, 
+			     (arbitrary_info_t *) &hubinfo_p);
+	return(hubinfo_p->h_widgetid);
+}
+
+devfs_handle_t
+nodevertex_xbow_peer_get(devfs_handle_t node_vtx)
+{
+	hubinfo_t hubinfo_p;
+	nasid_t xbow_peer_nasid;
+	cnodeid_t xbow_peer;
+
+	hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO,
+				     (arbitrary_info_t *) &hubinfo_p);
+	xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer;
+	if(xbow_peer_nasid == INVALID_NASID) 
+			return ( (devfs_handle_t)-1);
+	xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid);
+	return(NODEPDA(xbow_peer)->node_vertex);
+}
+
+/* NIC Sorting Support */
+
+#define MAX_NICS_PER_STRING 	32
+#define MAX_NIC_NAME_LEN	32
+
+static char *
+get_nic_string(lboard_t *lb)
+{
+        int         	i;
+        klinfo_t    	*k = NULL ;
+    	klconf_off_t    mfg_off = 0 ;
+    	char            *mfg_nic = NULL ;
+
+        for (i = 0; i < KLCF_NUM_COMPS(lb); i++) {
+                k = KLCF_COMP(lb, i) ;
+                switch(k->struct_type) {
+                        case KLSTRUCT_BRI:
+            			mfg_off = ((klbri_t *)k)->bri_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_HUB:
+            			mfg_off = ((klhub_t *)k)->hub_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_ROU:
+            			mfg_off = ((klrou_t *)k)->rou_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_GFX:
+            			mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_TPU:
+            			mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_GSN_A:
+                        case KLSTRUCT_GSN_B:
+            			mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_XTHD:
+                                mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ;
+                                break;
+
+			default:
+				mfg_off = 0 ;
+                                break ;
+                }
+		if (mfg_off)
+			break ;
+        }
+
+	if ((mfg_off) && (k))
+		mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ;
+
+        return mfg_nic ;
+}
+
+char *
+get_first_string(char **ptrs, int n)
+{
+        int     i ;
+        char    *tmpptr ;
+
+        if ((ptrs == NULL) || (n == 0))
+                return NULL ;
+
+        tmpptr = ptrs[0] ;
+
+        if (n == 1)
+                return tmpptr ;
+
+        for (i = 0 ; i < n ; i++) {
+                if (strcmp(tmpptr, ptrs[i]) > 0)
+                        tmpptr = ptrs[i] ;
+        }
+
+        return tmpptr ;
+}
+
+int
+get_ptrs(char *idata, char **ptrs, int n, char *label)
+{
+        int     i = 0 ;
+        char    *tmp = idata ;
+
+        if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0))
+                return 0 ;
+
+        while  ( (tmp = strstr(tmp, label)) ){
+                tmp += strlen(label) ;
+                /* check for empty name field, and last NULL ptr */
+                if ((i < (n-1)) && (*tmp != ';')) {
+                        ptrs[i++] = tmp ;
+                }
+        }
+
+        ptrs[i] = NULL ;
+
+        return i ;
+}
+
+/*
+ * sort_nic_names
+ *
+ * 	Does not really do sorting. Find the alphabetically lowest
+ *	name among all the nic names found in a nic string.
+ *
+ * Return:
+ *	Nothing
+ *
+ * Side Effects:
+ *
+ *	lb->brd_name gets the new name found
+ */
+
+static void
+sort_nic_names(lboard_t *lb)
+{
+	char 	*nic_str ;
+        char    *ptrs[MAX_NICS_PER_STRING] ;
+        char    name[MAX_NIC_NAME_LEN] ;
+        char    *tmp, *tmp1 ;
+
+	*name = 0 ;
+
+	/* Get the nic pointer from the lb */
+
+	if ((nic_str = get_nic_string(lb)) == NULL)
+		return ;
+
+        tmp = get_first_string(ptrs,
+                        get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ;
+
+        if (tmp == NULL)
+		return ;
+
+        if  ( (tmp1 = strchr(tmp, ';')) ){
+                strncpy(name, tmp, tmp1-tmp) ;
+                name[tmp1-tmp] = 0 ;
+        } else {
+                strncpy(name, tmp, (sizeof(name) -1)) ;
+                name[sizeof(name)-1] = 0 ;
+        }
+
+	strcpy(lb->brd_name, name) ;
+}
+
+
+
+char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#012345";
+
+/*
+ * Format a module id for printing.
+ */
+void
+format_module_id(char *buffer, moduleid_t m, int fmt)
+{
+	int rack, position;
+	char brickchar;
+
+	rack = MODULE_GET_RACK(m);
+	ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
+	brickchar = MODULE_GET_BTCHAR(m);
+	position = MODULE_GET_BPOS(m);
+
+	if (fmt == MODULE_FORMAT_BRIEF) {
+	    /* Brief module number format, eg. 002c15 */
+
+	    /* Decompress the rack number */
+	    *buffer++ = '0' + RACK_GET_CLASS(rack);
+	    *buffer++ = '0' + RACK_GET_GROUP(rack);
+	    *buffer++ = '0' + RACK_GET_NUM(rack);
+
+	    /* Add the brick type */
+	    *buffer++ = brickchar;
+	}
+	else if (fmt == MODULE_FORMAT_LONG) {
+	    /* Fuller hwgraph format, eg. rack/002/bay/15 */
+
+	    strcpy(buffer, EDGE_LBL_RACK "/");  buffer += strlen(buffer);
+
+	    *buffer++ = '0' + RACK_GET_CLASS(rack);
+	    *buffer++ = '0' + RACK_GET_GROUP(rack);
+	    *buffer++ = '0' + RACK_GET_NUM(rack);
+
+	    strcpy(buffer, "/" EDGE_LBL_RPOS "/");  buffer += strlen(buffer);
+	}
+
+	/* Add the bay position, using at least two digits */
+	if (position < 10)
+	    *buffer++ = '0';
+	sprintf(buffer, "%d", position);
+
+}
+
+/*
+ * Parse a module id, in either brief or long form.
+ * Returns < 0 on error.
+ * The long form does not include a brick type, so it defaults to 0 (CBrick)
+ */
+int
+parse_module_id(char *buffer)
+{
+	unsigned int	v, rack, bay, type, form;
+	moduleid_t	m;
+	char 		c;
+
+	if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) {
+		form = MODULE_FORMAT_LONG;
+		buffer += strlen(EDGE_LBL_RACK "/");
+
+		/* A long module ID must be exactly 5 non-template chars. */
+		if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5)
+			return -1;
+	}
+	else {
+		form = MODULE_FORMAT_BRIEF;
+
+		/* A brief module id must be exactly 6 characters */
+		if (strlen(buffer) != 6)
+			return -2;
+	}
+
+	/* The rack number must be exactly 3 digits */
+	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2])))
+		return -3;
+
+	rack = 0;
+	v = *buffer++ - '0';
+	if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
+		return -4;
+	RACK_ADD_CLASS(rack, v);
+
+	v = *buffer++ - '0';
+	if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
+		return -5;
+	RACK_ADD_GROUP(rack, v);
+
+	v = *buffer++ - '0';
+	/* rack numbers are 1-based */
+	if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
+		return -6;
+	RACK_ADD_NUM(rack, v);
+
+	if (form == MODULE_FORMAT_BRIEF) {
+		/* Next should be a module type character.  Accept ucase or lcase. */
+		c = *buffer++;
+		if (!isalpha(c))
+			return -7;
+
+		/* strchr() returns a pointer into brick_types[], or NULL */
+		type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types);
+		if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT)
+			return -8;
+	}
+	else {
+		/* Hardcode the module type, and skip over the boilerplate */
+		type = MODULE_CBRICK;
+
+		if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer)
+			return -9;
+
+		buffer += strlen("/" EDGE_LBL_RPOS "/");
+	}
+		
+	/* The bay number is last.  Make sure it's exactly two digits */
+
+	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2]))
+		return -10;
+
+	bay = 10 * (buffer[0] - '0') + (buffer[1] - '0');
+
+	if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
+		return -11;
+
+	m = RBT_TO_MODULE(rack, bay, type);
+
+	/* avoid sign extending the moduleid_t */
+	return (int)(unsigned short)m;
+}
diff -Nru a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/klgraph.c	Mon Feb 24 05:24:10 2003
@@ -0,0 +1,866 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * klgraph.c-
+ *      This file specifies the interface between the kernel and the PROM's
+ *      configuration data structures.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/kldir.h>
+#include <asm/sn/gda.h> 
+#include <asm/sn/klconfig.h>
+#include <asm/sn/router.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/hcl_util.h>
+
+// #define KLGRAPH_DEBUG 1
+#ifdef KLGRAPH_DEBUG
+#define GRPRINTF(x)	printk x
+#define CE_GRPANIC	CE_PANIC
+#else
+#define GRPRINTF(x)
+#define CE_GRPANIC	CE_PANIC
+#endif
+
+#include <asm/sn/sn_private.h>
+
+extern char arg_maxnodes[];
+extern u64 klgraph_addr[];
+void mark_cpuvertex_as_cpu(devfs_handle_t vhdl, cpuid_t cpuid);
+
+
+/*
+ * Support for verbose inventory via hardware graph. 
+ * klhwg_invent_alloc allocates the necessary size of inventory information
+ * and fills in the generic information.
+ */
+invent_generic_t *
+klhwg_invent_alloc(cnodeid_t cnode, int class, int size)
+{
+	invent_generic_t *invent;
+
+	invent = kern_malloc(size);
+	if (!invent) return NULL;
+	
+	invent->ig_module = NODE_MODULEID(cnode);
+	invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode));
+	invent->ig_invclass = class;
+
+	return invent;
+}
+
+/*
+ * Add detailed disabled cpu inventory info to the hardware graph.
+ */
+void
+klhwg_disabled_cpu_invent_info(devfs_handle_t cpuv,
+                               cnodeid_t cnode,
+                               klcpu_t *cpu, slotid_t slot)
+{
+	invent_cpuinfo_t *cpu_invent;
+	diag_inv_t       *diag_invent;
+
+	cpu_invent = (invent_cpuinfo_t *)
+	klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
+	if (!cpu_invent)
+		return;
+
+	/* Diag information on this processor */
+	diag_invent = (diag_inv_t *)
+	klhwg_invent_alloc(cnode, INV_CPUDIAGVAL, sizeof(diag_inv_t));
+
+	if (!diag_invent)
+		return;
+
+
+	/* Disabled CPU */
+	cpu_invent->ic_gen.ig_flag = 0x0;
+	cpu_invent->ic_gen.ig_slot = slot;
+	cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
+	cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
+	cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
+
+	cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
+	cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
+	cpu_invent->ic_slice = cpu->cpu_info.physid;
+
+	/* Disabled CPU label */
+	hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			(arbitrary_info_t) cpu_invent);
+	hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			sizeof(invent_cpuinfo_t));
+
+	/* Diagval label - stores reason for disable +{virt,phys}id +diagval*/
+	hwgraph_info_add_LBL(cpuv, INFO_LBL_DIAGVAL,
+			(arbitrary_info_t) diag_invent);
+
+	hwgraph_info_export_LBL(cpuv, INFO_LBL_DIAGVAL,
+			sizeof(diag_inv_t));
+}
+
+/*
+ * Add detailed cpu inventory info to the hardware graph.
+ */
+void
+klhwg_cpu_invent_info(devfs_handle_t cpuv,
+			cnodeid_t cnode,
+			klcpu_t *cpu)
+{
+	invent_cpuinfo_t *cpu_invent;
+
+	cpu_invent = (invent_cpuinfo_t *)
+		klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
+	if (!cpu_invent)
+		return;
+
+	if (KLCONFIG_INFO_ENABLED((klinfo_t *)cpu))
+		cpu_invent->ic_gen.ig_flag = INVENT_ENABLED;
+	else
+		cpu_invent->ic_gen.ig_flag = 0x0;
+
+	cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
+	cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
+	cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
+
+	cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
+	cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
+	cpu_invent->ic_slice = cpu_physical_id_to_slice(cpu->cpu_info.virtid);
+
+	hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			(arbitrary_info_t) cpu_invent);
+	hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			sizeof(invent_cpuinfo_t));
+}
+
+/* 
+ * Add information about the baseio prom version number
+ * as a part of detailed inventory info in the hwgraph.
+ */
+void
+klhwg_baseio_inventory_add(devfs_handle_t baseio_vhdl,cnodeid_t cnode)
+{
+	invent_miscinfo_t	*baseio_inventory;
+	unsigned char		version = 0,revision = 0;
+
+	/* Allocate memory for the "detailed inventory" info
+	 * for the baseio
+	 */
+	baseio_inventory = (invent_miscinfo_t *) 
+		klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t));
+	baseio_inventory->im_type = INV_IO6PROM;
+	/* Store the revision info  in the inventory */
+	baseio_inventory->im_version = version;
+	baseio_inventory->im_rev = revision;
+	/* Put the inventory info in the hardware graph */
+	hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, 
+			     (arbitrary_info_t) baseio_inventory);
+	/* Make the information available to the user programs
+	 * thru hwgfs.
+	 */
+        hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT,
+				sizeof(invent_miscinfo_t));
+}
+
+char	*hub_rev[] = {
+	"0.0",
+	"1.0",
+	"2.0",
+	"2.1",
+	"2.2",
+	"2.3"
+};
+
+/*
+ * Add detailed cpu inventory info to the hardware graph.
+ */
+void
+klhwg_hub_invent_info(devfs_handle_t hubv,
+		      cnodeid_t cnode, 
+		      klhub_t *hub)
+{
+	invent_miscinfo_t *hub_invent;
+
+	hub_invent = (invent_miscinfo_t *) 
+	    klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t));
+	if (!hub_invent)
+	    return;
+
+	if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub))
+	    hub_invent->im_gen.ig_flag = INVENT_ENABLED;
+
+	hub_invent->im_type = INV_HUB;
+	hub_invent->im_rev = hub->hub_info.revision;
+	hub_invent->im_speed = hub->hub_speed;
+	hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT, 
+			     (arbitrary_info_t) hub_invent);
+        hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT,
+				sizeof(invent_miscinfo_t));
+}
+
+/* ARGSUSED */
+void
+klhwg_add_hub(devfs_handle_t node_vertex, klhub_t *hub, cnodeid_t cnode)
+{
+	devfs_handle_t myhubv;
+	devfs_handle_t hub_mon;
+	int rc;
+	extern struct file_operations shub_mon_fops;
+
+	GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB));
+	(void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);
+	rc = device_master_set(myhubv, node_vertex);
+	hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON,
+		0, DEVFS_FL_AUTO_DEVNUM,
+		0, 0,
+		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+		&shub_mon_fops, (void *)(long)cnode);
+}
+
+/* ARGSUSED */
+void
+klhwg_add_disabled_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot)
+{
+        devfs_handle_t my_cpu;
+        char name[120];
+        cpuid_t cpu_id;
+	nasid_t nasid;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+        cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
+        if(cpu_id != -1){
+		sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid);
+		(void) hwgraph_path_add(node_vertex, name, &my_cpu);
+
+		mark_cpuvertex_as_cpu(my_cpu, cpu_id);
+		device_master_set(my_cpu, node_vertex);
+
+		klhwg_disabled_cpu_invent_info(my_cpu, cnode, cpu, slot);
+		return;
+        }
+}
+
+/* ARGSUSED */
+void
+klhwg_add_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu)
+{
+        devfs_handle_t my_cpu, cpu_dir;
+        char name[120];
+        cpuid_t cpu_id;
+	nasid_t nasid;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+        cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
+
+        sprintf(name, "%s/%d/%c",
+                EDGE_LBL_CPUBUS,
+                0,
+                'a' + cpu->cpu_info.physid);
+
+        GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex));
+        (void) hwgraph_path_add(node_vertex, name, &my_cpu);
+        mark_cpuvertex_as_cpu(my_cpu, cpu_id);
+        device_master_set(my_cpu, node_vertex);
+
+        /* Add an alias under the node's CPU directory */
+        if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
+                sprintf(name, "%c", 'a' + cpu->cpu_info.physid);
+                (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
+        }
+
+        klhwg_cpu_invent_info(my_cpu, cnode, cpu);
+}
+
+
+void
+klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid)
+{
+	lboard_t *brd;
+	klxbow_t *xbow_p;
+	nasid_t hub_nasid;
+	cnodeid_t hub_cnode;
+	int widgetnum;
+	devfs_handle_t xbow_v, hubv;
+	/*REFERENCED*/
+	graph_error_t err;
+
+	if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
+			return;
+
+	if (KL_CONFIG_DUPLICATE_BOARD(brd))
+	    return;
+
+	GRPRINTF(("klhwg_add_xbow: adding cnode %d nasid %d xbow edges\n",
+			cnode, nasid));
+
+	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
+	    == NULL)
+	    return;
+
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+		if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum)) 
+		    continue;
+
+		hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum);
+		if (hub_nasid == INVALID_NASID) {
+			printk(KERN_WARNING  "hub widget %d, skipping xbow graph\n", widgetnum);
+			continue;
+		}
+
+		hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid);
+
+		if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) {
+			continue;
+		}
+			
+		hubv = cnodeid_to_vertex(hub_cnode);
+
+		err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v);
+                if (err != GRAPH_SUCCESS) {
+                        if (err == GRAPH_DUP)
+                                printk(KERN_WARNING  "klhwg_add_xbow: Check for "
+                                        "working routers and router links!");
+
+                        PRINT_PANIC("klhwg_add_xbow: Failed to add "
+                                "edge: vertex 0x%p to vertex 0x%p,"
+                                "error %d\n",
+                                (void *)hubv, (void *)xbow_v, err);
+                }
+		xswitch_vertex_init(xbow_v); 
+
+		NODEPDA(hub_cnode)->xbow_vhdl = xbow_v;
+
+		/*
+		 * XXX - This won't work is we ever hook up two hubs
+		 * by crosstown through a crossbow.
+		 */
+		if (hub_nasid != nasid) {
+			NODEPDA(hub_cnode)->xbow_peer = nasid;
+			NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer =
+				hub_nasid;
+		}
+
+		GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n",
+			hub_nasid, EDGE_LBL_XTALK, hubv));
+	}
+}
+
+
+/* ARGSUSED */
+void
+klhwg_add_node(devfs_handle_t hwgraph_root, cnodeid_t cnode, gda_t *gdap)
+{
+	nasid_t nasid;
+	lboard_t *brd;
+	klhub_t *hub;
+	devfs_handle_t node_vertex = NULL;
+	char path_buffer[100];
+	int rv;
+	char *s;
+	int board_disabled = 0;
+	klcpu_t *cpu;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+	GRPRINTF(("klhwg_add_node: Adding cnode %d, nasid %d, brd 0x%p\n",
+                cnode, nasid, brd));
+	ASSERT(brd);
+
+	do {
+		devfs_handle_t cpu_dir;
+
+		/* Generate a hardware graph path for this board. */
+		board_to_path(brd, path_buffer);
+
+		GRPRINTF(("klhwg_add_node: adding %s to vertex 0x%p\n",
+			path_buffer, hwgraph_root));
+		rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
+
+		if (rv != GRAPH_SUCCESS)
+			PRINT_PANIC("Node vertex creation failed.  "
+					  "Path == %s",
+				path_buffer);
+
+		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+		ASSERT(hub);
+		if(hub->hub_info.flags & KLINFO_ENABLE)
+			board_disabled = 0;
+		else
+			board_disabled = 1;
+		
+		if(!board_disabled) {
+			mark_nodevertex_as_node(node_vertex,
+					    cnode + board_disabled * numnodes);
+
+			s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
+			NODEPDA(cnode)->hwg_node_name =
+						kmalloc(strlen(s) + 1,
+						GFP_KERNEL);
+			ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
+			strcpy(NODEPDA(cnode)->hwg_node_name, s);
+
+			hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
+
+			/* Set up node board's slot */
+			NODEPDA(cnode)->slotdesc = brd->brd_slot;
+
+			/* Set up the module we're in */
+			NODEPDA(cnode)->geoid = brd->brd_geoid;
+			NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
+		}
+
+		/* Get the first CPU structure */
+		cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
+
+		/*
+		* If there's at least 1 CPU, add a "cpu" directory to represent
+		* the collection of all CPUs attached to this node.
+		*/
+		if (cpu) {
+			graph_error_t rv;
+
+			rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir);
+			if (rv != GRAPH_SUCCESS)
+				panic("klhwg_add_node: Cannot create CPU directory\n");
+		}
+
+		/* Add each CPU */
+		while (cpu) {
+			cpuid_t cpu_id;
+			cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid);
+			if (cpu_enabled(cpu_id))
+				klhwg_add_cpu(node_vertex, cnode, cpu);
+			else
+				klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot);
+
+			cpu = (klcpu_t *)
+				find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU);
+		} /* while */
+
+		if(!board_disabled)
+			klhwg_add_hub(node_vertex, hub, cnode);
+		
+		brd = KLCF_NEXT(brd);
+		if (brd)
+			brd = find_lboard(brd, KLTYPE_SNIA);
+		else
+			break;
+	} while(brd);
+}
+
+
+/* ARGSUSED */
+void
+klhwg_add_all_routers(devfs_handle_t hwgraph_root)
+{
+	nasid_t nasid;
+	cnodeid_t cnode;
+	lboard_t *brd;
+	devfs_handle_t node_vertex;
+	char path_buffer[100];
+	int rv;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+		GRPRINTF(("klhwg_add_all_routers: adding router on cnode %d\n",
+			cnode));
+
+		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+				KLTYPE_ROUTER);
+
+		if (!brd)
+			/* No routers stored in this node's memory */
+			continue;
+
+		do {
+			ASSERT(brd);
+			GRPRINTF(("Router board struct is %p\n", brd));
+
+			/* Don't add duplicate boards. */
+			if (brd->brd_flags & DUPLICATE_BOARD)
+				continue;
+
+			GRPRINTF(("Router 0x%p module number is %d\n", brd, brd->brd_geoid));
+			/* Generate a hardware graph path for this board. */
+			board_to_path(brd, path_buffer);
+
+			GRPRINTF(("Router path is %s\n", path_buffer));
+
+			/* Add the router */
+			GRPRINTF(("klhwg_add_all_routers: adding %s to vertex 0x%p\n",
+				path_buffer, hwgraph_root));
+			rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
+
+			if (rv != GRAPH_SUCCESS)
+				PRINT_PANIC("Router vertex creation "
+						  "failed.  Path == %s",
+					path_buffer);
+
+			GRPRINTF(("klhwg_add_all_routers: get next board from 0x%p\n",
+					brd));
+		/* Find the rest of the routers stored on this node. */
+		} while ( (brd = find_lboard_class(KLCF_NEXT(brd),
+			 KLTYPE_ROUTER)) );
+
+		GRPRINTF(("klhwg_add_all_routers: Done.\n"));
+	}
+
+}
+
+/* ARGSUSED */
+void
+klhwg_connect_one_router(devfs_handle_t hwgraph_root, lboard_t *brd,
+			 cnodeid_t cnode, nasid_t nasid)
+{
+	klrou_t *router;
+	char path_buffer[50];
+	char dest_path[50];
+	devfs_handle_t router_hndl;
+	devfs_handle_t dest_hndl;
+	int rc;
+	int port;
+	lboard_t *dest_brd;
+
+	GRPRINTF(("klhwg_connect_one_router: Connecting router on cnode %d\n",
+			cnode));
+
+	/* Don't add duplicate boards. */
+	if (brd->brd_flags & DUPLICATE_BOARD) {
+		GRPRINTF(("klhwg_connect_one_router: Duplicate router 0x%p on cnode %d\n",
+			brd, cnode));
+		return;
+	}
+
+	/* Generate a hardware graph path for this board. */
+	board_to_path(brd, path_buffer);
+
+	rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl);
+
+	if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes))
+			return;
+
+	if (rc != GRAPH_SUCCESS)
+		printk(KERN_WARNING  "Can't find router: %s", path_buffer);
+
+	/* We don't know what to do with multiple router components */
+	if (brd->brd_numcompts != 1) {
+		PRINT_PANIC("klhwg_connect_one_router: %d cmpts on router\n",
+			brd->brd_numcompts);
+		return;
+	}
+
+
+	/* Convert component 0 to klrou_t ptr */
+	router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd),
+					      brd->brd_compts[0]);
+
+	for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
+		/* See if the port's active */
+		if (router->rou_port[port].port_nasid == INVALID_NASID) {
+			GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n",
+				 port));
+			continue;
+		}
+		if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) 
+		    == INVALID_CNODEID) {
+			continue;
+		}
+
+		dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+				router->rou_port[port].port_nasid,
+				router->rou_port[port].port_offset);
+
+		/* Generate a hardware graph path for this board. */
+		board_to_path(dest_brd, dest_path);
+
+		rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
+
+		if (rc != GRAPH_SUCCESS) {
+			if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
+				continue;
+			PRINT_PANIC("Can't find router: %s", dest_path);
+		}
+		GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n",
+			  path_buffer, port, dest_path));
+
+		sprintf(dest_path, "%d", port);
+
+		rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path);
+
+		if (rc == GRAPH_DUP) {
+			GRPRINTF(("Skipping port %d. nasid %d %s/%s\n",
+				  port, router->rou_port[port].port_nasid,
+				  path_buffer, dest_path));
+			continue;
+		}
+
+		if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes))
+			PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
+				path_buffer, dest_path, (void *)dest_hndl, rc);
+		
+	}
+}
+
+
+void
+klhwg_connect_routers(devfs_handle_t hwgraph_root)
+{
+	nasid_t nasid;
+	cnodeid_t cnode;
+	lboard_t *brd;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+		GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n",
+			cnode));
+
+		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+				KLTYPE_ROUTER);
+
+		if (!brd)
+			continue;
+
+		do {
+
+			nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+			klhwg_connect_one_router(hwgraph_root, brd,
+						 cnode, nasid);
+
+		/* Find the rest of the routers stored on this node. */
+		} while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
+	}
+}
+
+
+
+void
+klhwg_connect_hubs(devfs_handle_t hwgraph_root)
+{
+	nasid_t nasid;
+	cnodeid_t cnode;
+	lboard_t *brd;
+	klhub_t *hub;
+	lboard_t *dest_brd;
+	devfs_handle_t hub_hndl;
+	devfs_handle_t dest_hndl;
+	char path_buffer[50];
+	char dest_path[50];
+	graph_error_t rc;
+	int port;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+		GRPRINTF(("klhwg_connect_hubs: Connecting hubs on cnode %d\n",
+			cnode));
+
+		brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+		ASSERT(brd);
+
+		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+		ASSERT(hub);
+
+		for (port = 1; port <= MAX_NI_PORTS; port++) {
+			/* See if the port's active */
+			if (hub->hub_port[port].port_nasid == INVALID_NASID) {
+				GRPRINTF(("klhwg_connect_hubs: port inactive.\n"));
+				continue;
+			}
+
+			if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID)
+				continue;
+
+			/* Generate a hardware graph path for this board. */
+			board_to_path(brd, path_buffer);
+
+			GRPRINTF(("klhwg_connect_hubs: Hub path is %s.\n", path_buffer));
+			rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl);
+
+			if (rc != GRAPH_SUCCESS)
+				printk(KERN_WARNING  "Can't find hub: %s", path_buffer);
+
+			dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+					hub->hub_port[port].port_nasid,
+					hub->hub_port[port].port_offset);
+
+			/* Generate a hardware graph path for this board. */
+			board_to_path(dest_brd, dest_path);
+
+			rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
+
+			if (rc != GRAPH_SUCCESS) {
+				if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
+					continue;
+				PRINT_PANIC("Can't find board: %s", dest_path);
+			} else {
+				char buf[1024];
+		
+
+				GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n",
+			  	path_buffer, dest_path));
+
+				rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl);
+				sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT);
+				rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl);
+				sprintf(buf,"%d",port);
+				rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf);
+
+				if (rc != GRAPH_SUCCESS)
+					PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
+					path_buffer, dest_path, (void *)dest_hndl, rc);
+
+			}
+		}
+	}
+}
+
+/* Store the pci/vme disabled board information as extended administrative
+ * hints which can later be used by the drivers using the device/driver
+ * admin interface. 
+ */
+void
+klhwg_device_disable_hints_add(void)
+{
+	cnodeid_t	cnode; 		/* node we are looking at */
+	nasid_t		nasid;		/* nasid of the node */
+	lboard_t	*board;		/* board we are looking at */
+	int		comp_index;	/* component index */
+	klinfo_t	*component;	/* component in the board we are
+					 * looking at 
+					 */
+	char		device_name[MAXDEVNAME];
+	
+	for(cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+		board = (lboard_t *)KL_CONFIG_INFO(nasid);
+		/* Check out all the board info stored  on a node */
+		while(board) {
+			/* No need to look at duplicate boards or non-io 
+			 * boards
+			 */
+			if (KL_CONFIG_DUPLICATE_BOARD(board) ||
+			    KLCLASS(board->brd_type) != KLCLASS_IO) {
+				board = KLCF_NEXT(board);
+				continue;
+			}
+			/* Check out all the components of a board */
+			for (comp_index = 0; 
+			     comp_index < KLCF_NUM_COMPS(board);
+			     comp_index++) {
+				component = KLCF_COMP(board,comp_index);
+				/* If the component is enabled move on to
+				 * the next component
+				 */
+				if (KLCONFIG_INFO_ENABLED(component))
+					continue;
+				/* NOTE : Since the prom only supports
+				 * the disabling of pci devices the following
+				 * piece of code makes sense. 
+				 * Make sure that this assumption is valid
+				 */
+				/* This component is disabled. Store this
+				 * hint in the extended device admin table
+				 */
+				/* Get the canonical name of the pci device */
+				device_component_canonical_name_get(board,
+							    component,
+							    device_name);
+#ifdef DEBUG
+				printf("%s DISABLED\n",device_name);
+#endif				
+			}
+			/* go to the next board info stored on this 
+			 * node 
+			 */
+			board = KLCF_NEXT(board);
+		}
+	}
+}
+
+void
+klhwg_add_all_modules(devfs_handle_t hwgraph_root)
+{
+	cmoduleid_t	cm;
+	char		name[128];
+	devfs_handle_t	vhdl;
+	devfs_handle_t  module_vhdl;
+	int		rc;
+	char		buffer[16];
+
+	/* Add devices under each module */
+
+	for (cm = 0; cm < nummodules; cm++) {
+		/* Use module as module vertex fastinfo */
+
+		memset(buffer, 0, 16);
+		format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF);
+		sprintf(name, EDGE_LBL_MODULE "/%s", buffer);
+
+		rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl);
+		ASSERT(rc == GRAPH_SUCCESS);
+		rc = rc;
+
+		hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]);
+
+		/* Add system controller */
+		sprintf(name,
+			EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1,
+			buffer);
+
+		rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
+		ASSERT_ALWAYS(rc == GRAPH_SUCCESS); 
+		rc = rc;
+
+		hwgraph_info_add_LBL(vhdl,
+				     INFO_LBL_ELSC,
+				     (arbitrary_info_t) (__psint_t) 1);
+
+	}
+}
+
+void
+klhwg_add_all_nodes(devfs_handle_t hwgraph_root)
+{
+	cnodeid_t	cnode;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		klhwg_add_node(hwgraph_root, cnode, NULL);
+	}
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode));
+	}
+
+	/*
+	 * As for router hardware inventory information, we set this
+	 * up in router.c. 
+	 */
+	
+	klhwg_add_all_routers(hwgraph_root);
+	klhwg_connect_routers(hwgraph_root);
+	klhwg_connect_hubs(hwgraph_root);
+
+	/* Go through the entire system's klconfig
+	 * to figure out which pci components have been disabled
+	 */
+	klhwg_device_disable_hints_add();
+
+}
diff -Nru a/arch/ia64/sn/io/sn2/l1.c b/arch/ia64/sn/io/sn2/l1.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/l1.c	Mon Feb 24 05:24:28 2003
@@ -0,0 +1,244 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+/* In general, this file is organized in a hierarchy from lower-level
+ * to higher-level layers, as follows:
+ *
+ *	UART routines
+ *	Bedrock/L1 "PPP-like" protocol implementation
+ *	System controller "message" interface (allows multiplexing
+ *		of various kinds of requests and responses with
+ *		console I/O)
+ *	Console interface:
+ *	  "l1_cons", the glue that allows the L1 to act
+ *		as the system console for the stdio libraries
+ *
+ * Routines making use of the system controller "message"-style interface
+ * can be found in l1_command.c.
+ */
+
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/router.h>
+#include <asm/sn/module.h>
+#include <asm/sn/ksys/l1.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/uart16550.h>
+#include <asm/sn/simulator.h>
+
+
+#define UART_BAUD_RATE          57600
+
+int 
+get_L1_baud(void)
+{
+    return UART_BAUD_RATE;
+}
+
+
+
+/* Return the current interrupt level */
+int
+l1_get_intr_value( void )
+{
+	return(0);
+}
+
+/* Disconnect the callup functions - throw away interrupts */
+
+void
+l1_unconnect_intr(void)
+{
+}
+
+/* Set up uart interrupt handling for this node's uart */
+
+void
+l1_connect_intr(void *rx_notify, void *tx_notify)
+{
+#if 0
+	// Will need code here for sn2 - something like this
+	console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid());
+	intr_connect_level(console_nodepda->node_first_cpu,
+                                SGI_UART_VECTOR, INTPEND0_MAXMASK,
+                                dummy_intr_func);
+	request_irq(SGI_UART_VECTOR | (console_nodepda->node_first_cpu << 8),
+                                intr_func, SA_INTERRUPT | SA_SHIRQ,
+                                "l1_protocol_driver", (void *)sc);
+#endif
+}
+
+
+/* These are functions to use from serial_in/out when in protocol
+ * mode to send and receive uart control regs. These are external
+ * interfaces into the protocol driver.
+ */
+
+void
+l1_control_out(int offset, int value)
+{
+	/* quietly ignore unless simulator */
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		if ( master_node_bedrock_address != (u64)0 ) {
+			writeb(value, (unsigned long)master_node_bedrock_address +
+				(offset<< 3));
+		}
+		return;
+	}
+}
+
+/* Console input exported interface. Return a register value.  */
+
+int
+l1_control_in_polled(int offset)
+{
+	static int l1_control_in_local(int);
+
+	return(l1_control_in_local(offset));
+}
+
+int
+l1_control_in(int offset)
+{
+	static int l1_control_in_local(int);
+
+	return(l1_control_in_local(offset));
+}
+
+static int
+l1_control_in_local(int offset)
+{
+	int sal_call_status = 0, input;
+	int ret = 0;
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		ret = readb((unsigned long)master_node_bedrock_address +
+				(offset<< 3));
+		return(ret);
+	}		
+	if ( offset == REG_LSR ) {
+		ret = (LSR_XHRE | LSR_XSRE);	/* can send anytime */
+		sal_call_status = ia64_sn_console_check(&input);
+		if ( !sal_call_status && input ) {
+			/* input pending */
+			ret |= LSR_RCA;
+		}
+	}
+	return(ret);
+}
+
+/*
+ * Console input exported interface. Return a character (if one is available)
+ */
+
+int
+l1_serial_in_polled(void)
+{
+	static int l1_serial_in_local(void);
+
+	return(l1_serial_in_local());
+}
+
+int
+l1_serial_in(void)
+{
+	static int l1_serial_in_local(void);
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
+	}	
+	return(l1_serial_in_local());
+}
+
+static int
+l1_serial_in_local(void)
+{
+	int ch;
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
+	}		
+
+	if ( !(ia64_sn_console_getc(&ch)) )
+		return(ch);
+	else
+		return(0);
+}
+
+/* Console output exported interface. Write message to the console.  */
+
+int
+l1_serial_out( char *str, int len )
+{
+	int counter = len;
+
+	/* Ignore empty messages */
+	if ( len == 0 )
+		return(len);
+
+#if defined(CONFIG_IA64_EARLY_PRINTK)
+	/* Need to setup SAL calls so the PROM calls will work */
+	{
+		static int inited;
+		void early_sn_setup(void);
+		if(!inited) {
+			inited=1;
+			early_sn_setup();
+		}
+	}
+#endif
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		void early_sn_setup(void);
+		if (!master_node_bedrock_address)
+			early_sn_setup();
+		if ( master_node_bedrock_address != (u64)0 ) {
+#ifdef FLAG_DIRECT_CONSOLE_WRITES
+			/* This is an easy way to pre-pend the output to know whether the output
+			 * was done via sal or directly */
+			writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+			writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+			writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+			writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+#endif	/* FLAG_DIRECT_CONSOLE_WRITES */
+			while ( counter > 0 ) {
+				writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+				counter--;
+				str++;
+			}
+		}
+		return(len);
+	}
+
+	/* Attempt to write things out thru the sal */
+	if ( ia64_sn_console_putb(str, len) )
+		return(0);
+
+	return((counter <= 0) ? 0 : (len - counter));
+}
diff -Nru a/arch/ia64/sn/io/sn2/l1_command.c b/arch/ia64/sn/io/sn2/l1_command.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/l1_command.c	Mon Feb 24 05:24:42 2003
@@ -0,0 +1,207 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */ 
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/router.h>
+#include <asm/sn/module.h>
+#include <asm/sn/ksys/l1.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/sn_sal.h>
+#include <linux/ctype.h>
+
+#define ELSC_TIMEOUT	1000000		/* ELSC response timeout (usec) */
+#define LOCK_TIMEOUT	5000000		/* Hub lock timeout (usec) */
+
+#define hub_cpu_get()	0
+
+#define LBYTE(caddr)	(*(char *) caddr)
+
+extern char *bcopy(const char * src, char * dest, int count);
+
+#define LDEBUG		0
+
+/*
+ * ELSC data is in NVRAM page 7 at the following offsets.
+ */
+
+#define NVRAM_MAGIC_AD	0x700		/* magic number used for init */
+#define NVRAM_PASS_WD	0x701		/* password (4 bytes in length) */
+#define NVRAM_DBG1	0x705		/* virtual XOR debug switches */
+#define NVRAM_DBG2	0x706		/* physical XOR debug switches */
+#define NVRAM_CFG	0x707		/* ELSC Configuration info */
+#define NVRAM_MODULE	0x708		/* system module number */
+#define NVRAM_BIST_FLG	0x709		/* BIST flags (2 bits per nodeboard) */
+#define NVRAM_PARTITION 0x70a		/* module's partition id */
+#define	NVRAM_DOMAIN	0x70b		/* module's domain id */
+#define	NVRAM_CLUSTER	0x70c		/* module's cluster id */
+#define	NVRAM_CELL	0x70d		/* module's cellid */
+
+#define NVRAM_MAGIC_NO	0x37		/* value of magic number */
+#define NVRAM_SIZE	16		/* 16 bytes in nvram */
+
+
+/* elsc_display_line writes up to 12 characters to either the top or bottom
+ * line of the L1 display.  line points to a buffer containing the message
+ * to be displayed.  The zero-based line number is specified by lnum (so
+ * lnum == 0 specifies the top line and lnum == 1 specifies the bottom).
+ * Lines longer than 12 characters, or line numbers not less than
+ * L1_DISPLAY_LINES, cause elsc_display_line to return an error.
+ */
+int elsc_display_line(nasid_t nasid, char *line, int lnum)
+{
+    return 0;
+}
+
+/*
+ * iobrick routines
+ */
+
+/* iobrick_rack_bay_type_get fills in the three int * arguments with the
+ * rack number, bay number and brick type of the L1 being addressed.  Note
+ * that if the L1 operation fails and this function returns an error value, 
+ * garbage may be written to brick_type.
+ */
+
+
+int iobrick_rack_bay_type_get( nasid_t nasid, uint *rack, 
+			       uint *bay, uint *brick_type )
+{
+	int result = 0;
+
+	if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
+		return( ELSC_ERROR_CMD_SEND );
+
+	*rack = (result & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT;
+	*bay = (result & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT;
+	*brick_type = (result & L1_ADDR_TYPE_MASK) >> L1_ADDR_TYPE_SHFT;
+	*brick_type = toupper(*brick_type);
+
+	return 0;
+}
+
+
+int iomoduleid_get(nasid_t nasid)
+{
+
+	int result = 0;
+
+	if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
+		return( ELSC_ERROR_CMD_SEND );
+
+	return result;
+
+}
+
+int iobrick_module_get(nasid_t nasid)
+{
+    uint rnum, rack, bay, brick_type, t;
+    int ret;
+
+    /* construct module ID from rack and slot info */
+
+    if ((ret = iobrick_rack_bay_type_get(nasid, &rnum, &bay, &brick_type)) < 0)
+        return ret;
+
+    if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
+        return ELSC_ERROR_MODULE;
+
+    /* Build a moduleid_t-compatible rack number */
+
+    rack = 0;           
+    t = rnum / 100;             /* rack class (CPU/IO) */
+    if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
+        return ELSC_ERROR_MODULE;
+    RACK_ADD_CLASS(rack, t);
+    rnum %= 100;
+
+    t = rnum / 10;              /* rack group */
+    if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
+        return ELSC_ERROR_MODULE;
+    RACK_ADD_GROUP(rack, t);
+
+    t = rnum % 10;              /* rack number (one-based) */
+    if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
+        return ELSC_ERROR_MODULE;
+    RACK_ADD_NUM(rack, t);
+
+    switch( brick_type ) {
+      case 'I': 
+	brick_type = MODULE_IBRICK; break;
+      case 'P':
+	brick_type = MODULE_PBRICK; break;
+      case 'X':
+	brick_type = MODULE_XBRICK; break;
+    }
+
+    ret = RBT_TO_MODULE(rack, bay, brick_type);
+
+    return ret;
+}
+
+/*
+ * iobrick_module_get_nasid() returns a module_id which has the brick
+ * type encoded in bits 15-12, but this is not the true brick type...
+ * The module_id returned by iobrick_module_get_nasid() is modified
+ * to make a PEBRICKs & PXBRICKs look like a PBRICK.  So this routine
+ * iobrick_type_get_nasid() returns the true unmodified brick type.
+ */
+int
+iobrick_type_get_nasid(nasid_t nasid)
+{
+    uint rack, bay, type;
+    int t, ret;
+    extern char brick_types[];
+
+    if ((ret = iobrick_rack_bay_type_get(nasid, &rack, &bay, &type)) < 0) {
+        return ret;
+    }
+
+    /* convert brick_type to lower case */
+    if ((type >= 'A') && (type <= 'Z'))
+        type = type - 'A' + 'a';
+
+    /* convert to a module.h brick type */
+    for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
+        if( brick_types[t] == type )
+            return t;
+    }
+
+    return -1;    /* unknown brick */
+}
+
+int iobrick_module_get_nasid(nasid_t nasid)
+{
+    int io_moduleid;
+
+#ifdef PIC_LATER
+    uint rack, bay;
+
+    if (PEBRICK_NODE(nasid)) {
+        if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) {
+            printf("Could not read rack and bay location "
+                   "of PEBrick at nasid %d\n", nasid);
+        }
+
+        io_moduleid = peer_iobrick_module_get(sc, rack, bay);
+    }
+#endif	/* PIC_LATER */
+    io_moduleid = iobrick_module_get(nasid);
+    return io_moduleid;
+}
diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_init.c b/arch/ia64/sn/io/sn2/ml_SN_init.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/ml_SN_init.c	Mon Feb 24 05:21:39 2003
@@ -0,0 +1,160 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/snconfig.h>
+
+extern int numcpus;
+extern char arg_maxnodes[];
+extern cpuid_t master_procid;
+
+extern int hasmetarouter;
+
+int		maxcpus;
+cpumask_t	boot_cpumask;
+hubreg_t	region_mask = 0;
+
+
+extern xwidgetnum_t hub_widget_id(nasid_t);
+
+extern int valid_icache_reasons;	/* Reasons to flush the icache */
+extern int valid_dcache_reasons;	/* Reasons to flush the dcache */
+extern u_char miniroot;
+extern volatile int	need_utlbmiss_patch;
+extern void iograph_early_init(void);
+
+nasid_t master_nasid = INVALID_NASID;		/* This is the partition master nasid */
+nasid_t master_baseio_nasid = INVALID_NASID;	/* This is the master base I/O nasid */
+
+
+/*
+ * mlreset(void)
+ * 	very early machine reset - at this point NO interrupts have been
+ * 	enabled; nor is memory, tlb, p0, etc setup.
+ *
+ * 	slave is zero when mlreset is called for the master processor and
+ *	is nonzero thereafter.
+ */
+
+
+void
+mlreset(int slave)
+{
+	/*
+	 * We are the master cpu and node.
+	 */ 
+	master_nasid = get_nasid();
+	set_master_bridge_base();
+
+	/* We're the master processor */
+	master_procid = smp_processor_id();
+	master_nasid = cpuid_to_nasid(master_procid);
+
+	/*
+	 * master_nasid we get back better be same as one from
+	 * get_nasid()
+	 */
+	ASSERT_ALWAYS(master_nasid == get_nasid());
+
+	/* early initialization of iograph */
+	iograph_early_init();
+
+	/* Initialize Hub Pseudodriver Management */
+	hubdev_init();
+}
+
+
+/* XXX - Move the meat of this to intr.c ? */
+/*
+ * Set up the platform-dependent fields in the nodepda.
+ */
+void init_platform_nodepda(nodepda_t *npda, cnodeid_t node)
+{
+	hubinfo_t hubinfo;
+
+	extern void router_map_init(nodepda_t *);
+	extern void router_queue_init(nodepda_t *,cnodeid_t);
+	extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int);
+
+	/* Allocate per-node platform-dependent data */
+	hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(node), sizeof(struct hubinfo_s));
+
+	npda->pdinfo = (void *)hubinfo;
+	hubinfo->h_nodepda = npda;
+	hubinfo->h_cnodeid = node;
+	hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node);
+
+	spin_lock_init(&hubinfo->h_crblock);
+
+	hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
+	npda->xbow_peer = INVALID_NASID;
+
+	/* 
+	 * Initialize the linked list of
+	 * router info pointers to the dependent routers
+	 */
+	npda->npda_rip_first = NULL;
+
+	/*
+	 * npda_rip_last always points to the place
+	 * where the next element is to be inserted
+	 * into the list 
+	 */
+	npda->npda_rip_last = &npda->npda_rip_first;
+	npda->geoid.any.type = GEO_TYPE_INVALID;
+
+	mutex_init_locked(&npda->xbow_sema); /* init it locked? */
+}
+
+/* XXX - Move the interrupt stuff to intr.c ? */
+/*
+ * Set up the platform-dependent fields in the processor pda.
+ * Must be done _after_ init_platform_nodepda().
+ * If we need a lock here, something else is wrong!
+ */
+void init_platform_pda(cpuid_t cpu)
+{
+}
+
+void
+update_node_information(cnodeid_t cnodeid)
+{
+	nodepda_t *npda = NODEPDA(cnodeid);
+	nodepda_router_info_t *npda_rip;
+	
+	/* Go through the list of router info 
+	 * structures and copy some frequently
+	 * accessed info from the info hanging
+	 * off the corresponding router vertices
+	 */
+	npda_rip = npda->npda_rip_first;
+	while(npda_rip) {
+		if (npda_rip->router_infop) {
+			npda_rip->router_portmask = 
+				npda_rip->router_infop->ri_portmask;
+			npda_rip->router_slot = 
+				npda_rip->router_infop->ri_slotnum;
+		} else {
+			/* No router, no ports. */
+			npda_rip->router_portmask = 0;
+		}
+		npda_rip = npda_rip->router_next;
+	}
+}
diff -Nru a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/ml_iograph.c	Mon Feb 24 05:24:56 2003
@@ -0,0 +1,1395 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/xtalk/xtalk_private.h>
+#include <asm/sn/xtalk/xtalkaddrs.h>
+
+/* #define IOGRAPH_DEBUG */
+#ifdef IOGRAPH_DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* IOGRAPH_DEBUG */
+
+/* #define PROBE_TEST */
+
+/* At most 2 hubs can be connected to an xswitch */
+#define NUM_XSWITCH_VOLUNTEER 2
+
+extern unsigned char Is_pic_on_this_nasid[512];
+
+/*
+ * Track which hubs have volunteered to manage devices hanging off of
+ * a Crosstalk Switch (e.g. xbow).  This structure is allocated,
+ * initialized, and hung off the xswitch vertex early on when the
+ * xswitch vertex is created.
+ */
+typedef struct xswitch_vol_s {
+	mutex_t xswitch_volunteer_mutex;
+	int		xswitch_volunteer_count;
+	devfs_handle_t	xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];
+} *xswitch_vol_t;
+
+void
+xswitch_vertex_init(devfs_handle_t xswitch)
+{
+	xswitch_vol_t xvolinfo;
+	int rc;
+	extern void * snia_kmem_zalloc(size_t size, int flag);
+
+	xvolinfo = snia_kmem_zalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);
+	mutex_init(&xvolinfo->xswitch_volunteer_mutex);
+	rc = hwgraph_info_add_LBL(xswitch, 
+			INFO_LBL_XSWITCH_VOL,
+			(arbitrary_info_t)xvolinfo);
+	ASSERT(rc == GRAPH_SUCCESS); rc = rc;
+}
+
+
+/*
+ * When assignment of hubs to widgets is complete, we no longer need the
+ * xswitch volunteer structure hanging around.  Destroy it.
+ */
+static void
+xswitch_volunteer_delete(devfs_handle_t xswitch)
+{
+	xswitch_vol_t xvolinfo;
+	int rc;
+	extern void snia_kmem_free(void *ptr, size_t size);
+
+	rc = hwgraph_info_remove_LBL(xswitch, 
+				INFO_LBL_XSWITCH_VOL,
+				(arbitrary_info_t *)&xvolinfo);
+	snia_kmem_free(xvolinfo, sizeof(struct xswitch_vol_s));
+}
+/*
+ * A Crosstalk master volunteers to manage xwidgets on the specified xswitch.
+ */
+/* ARGSUSED */
+static void
+volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master)
+{
+	xswitch_vol_t xvolinfo = NULL;
+	devfs_handle_t hubv;
+	hubinfo_t hubinfo;
+
+	(void)hwgraph_info_get_LBL(xswitch, 
+				INFO_LBL_XSWITCH_VOL, 
+				(arbitrary_info_t *)&xvolinfo);
+	if (xvolinfo == NULL) {
+	    if (!is_headless_node_vertex(master))
+		    printk(KERN_WARNING
+			"volunteer for widgets: vertex 0x%p has no info label",
+			(void *)xswitch);
+	    return;
+	}
+
+	mutex_lock(&xvolinfo->xswitch_volunteer_mutex);
+	ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);
+	xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;
+	xvolinfo->xswitch_volunteer_count++;
+
+	/*
+	 * if dual ported, make the lowest widgetid always be 
+	 * xswitch_volunteer[0].
+	 */
+	if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) {
+		hubv = xvolinfo->xswitch_volunteer[0];
+		hubinfo_get(hubv, &hubinfo);
+		if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) {
+			xvolinfo->xswitch_volunteer[0] = 
+						xvolinfo->xswitch_volunteer[1];
+			xvolinfo->xswitch_volunteer[1] = hubv;
+		}
+	}
+	mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);
+}
+
+extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);
+
+/*
+ * Assign all the xwidgets hanging off the specified xswitch to the
+ * Crosstalk masters that have volunteered for xswitch duty.
+ */
+/* ARGSUSED */
+static void
+assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv)
+{
+	xswitch_info_t xswitch_info;
+	xswitch_vol_t xvolinfo = NULL;
+	xwidgetnum_t widgetnum;
+	int num_volunteer;
+	nasid_t nasid;
+	hubinfo_t hubinfo;
+	extern int iobrick_type_get_nasid(nasid_t);
+
+
+	hubinfo_get(hubv, &hubinfo);
+	nasid = hubinfo->h_nasid;
+	
+	xswitch_info = xswitch_info_get(xswitch);
+	ASSERT(xswitch_info != NULL);
+
+	(void)hwgraph_info_get_LBL(xswitch, 
+				INFO_LBL_XSWITCH_VOL, 
+				(arbitrary_info_t *)&xvolinfo);
+	if (xvolinfo == NULL) {
+	    if (!is_headless_node_vertex(hubv))
+		    printk(KERN_WARNING
+			"assign_widgets_to_volunteers:vertex 0x%p has "
+			" no info label",
+			(void *)xswitch);
+	    return;
+	}
+
+	num_volunteer = xvolinfo->xswitch_volunteer_count;
+	ASSERT(num_volunteer > 0);
+
+	/* Assign master hub for xswitch itself.  */
+	if (HUB_WIDGET_ID_MIN > 0) {
+		hubv = xvolinfo->xswitch_volunteer[0];
+		xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv);
+	}
+
+	/*
+	 * TBD: Use administrative information to alter assignment of
+	 * widgets to hubs.
+	 */
+	for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+		int i;
+
+		/*
+		 * Ignore disabled/empty ports.
+		 */
+		if (!xbow_port_io_enabled(nasid, widgetnum)) 
+		    continue;
+
+		/*
+		 * If this is the master IO board, assign it to the same 
+		 * hub that owned it in the prom.
+		 */
+		if (is_master_baseio_nasid_widget(nasid, widgetnum)) {
+			extern nasid_t get_master_baseio_nasid(void);
+			for (i=0; i<num_volunteer; i++) {
+				hubv = xvolinfo->xswitch_volunteer[i];
+				hubinfo_get(hubv, &hubinfo);
+				nasid = hubinfo->h_nasid;
+				if (nasid == get_master_baseio_nasid())
+					goto do_assignment;
+			}
+			PRINT_PANIC("Nasid == %d, console nasid == %d",
+				nasid, get_master_baseio_nasid());
+		}
+
+		/*
+		 * Assuming that we're dual-hosted and that PCI cards 
+		 * are naturally placed left-to-right, alternate PCI 
+		 * buses across both Cbricks.   For Pbricks, and Ibricks,
+                 * io_brick_map_widget() returns the PCI bus number
+                 * associated with the given brick type and widget number.
+                 * For Xbricks, it returns the XIO slot number.
+		 */
+
+		i = 0;
+		if (num_volunteer > 1) {
+                        int	       bt;
+
+                       	bt = iobrick_type_get_nasid(nasid);
+                        if (bt >= 0) {
+				/*
+				 * PXBRICK has two busses per widget so this
+				 * algorithm wouldn't work (all busses would
+				 * be assigned to one volunteer). Change the
+				 * bricktype to PBRICK whose mapping is setup
+				 * suchthat 2 of the PICs will be assigned to
+				 * one volunteer and the other one will be
+				 * assigned to the other volunteer.
+				 */
+				if (bt == MODULE_PXBRICK) 
+					bt = MODULE_PBRICK;
+
+			        i = io_brick_map_widget(bt, widgetnum) & 1;
+                        }
+                }
+
+		hubv = xvolinfo->xswitch_volunteer[i];
+
+do_assignment:
+		/*
+		 * At this point, we want to make hubv the master of widgetnum.
+		 */
+		xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv);
+	}
+
+	xswitch_volunteer_delete(xswitch);
+}
+
+/*
+ * Early iograph initialization.  Called by master CPU in mlreset().
+ * Useful for including iograph.o in kernel.o.
+ */
+void
+iograph_early_init(void)
+{
+/*
+ * Need new way to get this information ..
+ */
+	cnodeid_t cnode;
+	nasid_t nasid;
+	lboard_t *board;
+	
+	/*
+	 * Init. the board-to-hwgraph link early, so FRU analyzer
+	 * doesn't trip on leftover values if we panic early on.
+	 */
+	for(cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+		board = (lboard_t *)KL_CONFIG_INFO(nasid);
+		DBG("iograph_early_init: Found board 0x%p\n", board);
+
+		/* Check out all the board info stored on a node */
+		while(board) {
+			board->brd_graph_link = GRAPH_VERTEX_NONE;
+			board = KLCF_NEXT(board);
+			DBG("iograph_early_init: Found board 0x%p\n", board);
+		}
+	}
+
+	hubio_init();
+}
+
+/*
+ * Let boot processor know that we're done initializing our node's IO
+ * and then exit.
+ */
+/* ARGSUSED */
+static void
+io_init_done(cnodeid_t cnodeid,cpu_cookie_t c)
+{
+	/* Let boot processor know that we're done. */
+}
+
+/* 
+ * Probe to see if this hub's xtalk link is active.  If so,
+ * return the Crosstalk Identification of the widget that we talk to.  
+ * This is called before any of the Crosstalk infrastructure for 
+ * this hub is set up.  It's usually called on the node that we're
+ * probing, but not always.
+ *
+ * TBD: Prom code should actually do this work, and pass through 
+ * hwid for our use.
+ */
+static void
+early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid)
+{
+	hubreg_t llp_csr_reg;
+	nasid_t nasid;
+	hubinfo_t hubinfo;
+
+	hubinfo_get(hubv, &hubinfo);
+	nasid = hubinfo->h_nasid;
+
+	llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
+	/* 
+	 * If link is up, read the widget's part number.
+	 * A direct connect widget must respond to widgetnum=0.
+	 */
+	if (llp_csr_reg & IIO_LLP_CSR_IS_UP) {
+		/* TBD: Put hub into "indirect" mode */
+		/*
+		 * We're able to read from a widget because our hub's 
+		 * WIDGET_ID was set up earlier.
+		 */
+		widgetreg_t widget_id = *(volatile widgetreg_t *)
+			(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
+
+		DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id,
+		(volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) );
+
+		hwid->part_num = XWIDGET_PART_NUM(widget_id);
+		hwid->rev_num = XWIDGET_REV_NUM(widget_id);
+		hwid->mfg_num = XWIDGET_MFG_NUM(widget_id);
+
+		/* TBD: link reset */
+	} else {
+
+		hwid->part_num = XWIDGET_PART_NUM_NONE;
+		hwid->rev_num = XWIDGET_REV_NUM_NONE;
+		hwid->mfg_num = XWIDGET_MFG_NUM_NONE;
+	}
+}
+
+/* Add inventory information to the widget vertex 
+ * Right now (module,slot,revision) is being
+ * added as inventory information.
+ */
+static void
+xwidget_inventory_add(devfs_handle_t 		widgetv,
+		      lboard_t 			*board,
+		      struct xwidget_hwid_s 	hwid)
+{
+	if (!board)
+		return;
+	/* Donot add inventory information for the baseio
+	 * on a speedo with an xbox. It has already been
+	 * taken care of in SN00_vmc.
+	 * Speedo with xbox's baseio comes in at slot io1 (widget 9)
+	 */
+	device_inventory_add(widgetv,INV_IOBD,board->brd_type,
+			     geo_module(board->brd_geoid),
+			     SLOTNUM_GETSLOT(board->brd_slot),
+			     hwid.rev_num);
+}
+
+/*
+ * io_xswitch_widget_init
+ *	
+ */
+
+void
+io_xswitch_widget_init(devfs_handle_t  	xswitchv,
+		       devfs_handle_t	hubv,
+		       xwidgetnum_t	widgetnum,
+		       async_attach_t	aa)
+{
+	xswitch_info_t		xswitch_info;
+	xwidgetnum_t		hub_widgetid;
+	devfs_handle_t		widgetv;
+	cnodeid_t		cnode;
+	widgetreg_t		widget_id;
+	nasid_t			nasid, peer_nasid;
+	struct xwidget_hwid_s 	hwid;
+	hubinfo_t		hubinfo;
+	/*REFERENCED*/
+	int			rc;
+	char 			pathname[128];
+	lboard_t		*board = NULL;
+	char			buffer[16];
+	char			bt;
+	moduleid_t		io_module;
+	slotid_t get_widget_slotnum(int xbow, int widget);
+	
+	DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum);
+
+	/*
+	 * Verify that xswitchv is indeed an attached xswitch.
+	 */
+	xswitch_info = xswitch_info_get(xswitchv);
+	ASSERT(xswitch_info != NULL);
+
+	hubinfo_get(hubv, &hubinfo);
+	nasid = hubinfo->h_nasid;
+	cnode = NASID_TO_COMPACT_NODEID(nasid);
+	hub_widgetid = hubinfo->h_widgetid;
+
+	/*
+	 * Check that the widget is an io widget and is enabled
+	 * on this nasid or the `peer' nasid.  The peer nasid
+	 * is the other hub/bedrock connected to the xbow.
+	 */
+	peer_nasid = NODEPDA(cnode)->xbow_peer;
+	if (peer_nasid == INVALID_NASID)
+		/* If I don't have a peer, use myself. */
+		peer_nasid = nasid;
+	if (!xbow_port_io_enabled(nasid, widgetnum) &&
+	    !xbow_port_io_enabled(peer_nasid, widgetnum)) {
+		return;
+	}
+
+	if (xswitch_info_link_ok(xswitch_info, widgetnum)) {
+		char			name[4];
+		lboard_t dummy;
+
+		/*
+		 * If the current hub is not supposed to be the master 
+		 * for this widgetnum, then skip this widget.
+		 */
+		if (xswitch_info_master_assignment_get(xswitch_info,
+						       widgetnum) != hubv) {
+			return;
+		}
+
+		board = find_lboard_class(
+				(lboard_t *)KL_CONFIG_INFO(nasid),
+				KLCLASS_IOBRICK);
+		if (!board && NODEPDA(cnode)->xbow_peer != INVALID_NASID) {
+		    	board = find_lboard_class(
+					(lboard_t *)KL_CONFIG_INFO( NODEPDA(cnode)->xbow_peer),
+						KLCLASS_IOBRICK);
+		}
+
+		if (board) {
+			DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type);
+		} else {
+			DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n");
+			board = &dummy;
+		}
+
+
+		/* Copy over the nodes' geoid info */
+		{
+			lboard_t *brd;
+
+			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+			if ( brd != (lboard_t *)0 ) {
+				board->brd_geoid = brd->brd_geoid;
+			}
+		}
+
+		/*
+ 		 * Make sure we really want to say xbrick, pbrick,
+		 * etc. rather than XIO, graphics, etc.
+ 		 */
+
+		memset(buffer, 0, 16);
+		format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);
+		sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%cbrick" "/%s/%d",
+			buffer,
+			geo_slab(board->brd_geoid),
+			(board->brd_type == KLTYPE_IBRICK) ? 'I' :
+			(board->brd_type == KLTYPE_PBRICK) ? 'P' :
+			(board->brd_type == KLTYPE_XBRICK) ? 'X' : '?',
+			EDGE_LBL_XTALK, widgetnum);
+		
+		DBG("io_xswitch_widget_init: path= %s\n", pathname);
+		rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
+		
+		ASSERT(rc == GRAPH_SUCCESS);
+
+		/* This is needed to let the user programs to map the
+		 * module,slot numbers to the corresponding widget numbers
+		 * on the crossbow.
+		 */
+		device_master_set(hwgraph_connectpt_get(widgetv), hubv);
+		sprintf(name, "%d", widgetnum);
+		DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv);
+		rc = hwgraph_edge_add(xswitchv, widgetv, name);
+		
+		/*
+		 * crosstalk switch code tracks which
+		 * widget is attached to each link.
+		 */
+		xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv);
+		
+		/*
+		 * Peek at the widget to get its crosstalk part and
+		 * mfgr numbers, then present it to the generic xtalk
+		 * bus provider to have its driver attach routine
+		 * called (or not).
+		 */
+		widget_id = XWIDGET_ID_READ(nasid, widgetnum);
+		hwid.part_num = XWIDGET_PART_NUM(widget_id);
+		hwid.rev_num = XWIDGET_REV_NUM(widget_id);
+		hwid.mfg_num = XWIDGET_MFG_NUM(widget_id);
+		/* Store some inventory information about
+		 * the xwidget in the hardware graph.
+		 */
+		xwidget_inventory_add(widgetv,board,hwid);
+
+		(void)xwidget_register(&hwid, widgetv, widgetnum,
+				       hubv, hub_widgetid,
+				       aa);
+
+		ia64_sn_sysctl_iobrick_module_get(nasid, &io_module);
+
+		if (io_module >= 0) {
+			char			buffer[16];
+			devfs_handle_t		to, from;
+
+			memset(buffer, 0, 16);
+			format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);
+
+			bt = toupper(MODULE_GET_BTCHAR(io_module));
+			/* Add a helper vertex so xbow monitoring
+			* can identify the brick type. It's simply
+			* an edge from the widget 0 vertex to the
+			*  brick vertex.
+			*/
+
+			sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/"
+				EDGE_LBL_SLAB "/%d/"
+				EDGE_LBL_NODE "/" EDGE_LBL_XTALK "/"
+				"0",
+				buffer, geo_slab(board->brd_geoid));
+			from = hwgraph_path_to_vertex(pathname);
+			ASSERT_ALWAYS(from);
+			sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/"
+				EDGE_LBL_SLAB "/%d/"
+				"%cbrick",
+				buffer, geo_slab(board->brd_geoid), bt);
+
+			to = hwgraph_path_to_vertex(pathname);
+			ASSERT_ALWAYS(to);
+			rc = hwgraph_edge_add(from, to,
+				EDGE_LBL_INTERCONNECT);
+			if (rc == -EEXIST)
+				goto link_done;
+			if (rc != GRAPH_SUCCESS) {
+				printk("%s: Unable to establish link"
+					" for xbmon.", pathname);
+			}
+link_done:
+		}
+
+#ifdef	SN0_USE_BTE
+		bte_bpush_war(cnode, (void *)board);
+#endif
+	}
+}
+
+
+static void
+io_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode)
+{
+	xwidgetnum_t		widgetnum;
+	async_attach_t          aa;
+
+	aa = async_attach_new();
+	
+	DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode);
+
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; 
+	     widgetnum++) {
+		io_xswitch_widget_init(xswitchv,
+				       cnodeid_to_vertex(cnode),
+				       widgetnum, aa);
+	}
+	/* 
+	 * Wait for parallel attach threads, if any, to complete.
+	 */
+	async_attach_waitall(aa);
+	async_attach_free(aa);
+}
+
+/*
+ * For each PCI bridge connected to the xswitch, add a link from the
+ * board's klconfig info to the bridge's hwgraph vertex.  This lets
+ * the FRU analyzer find the bridge without traversing the hardware
+ * graph and risking hangs.
+ */
+static void
+io_link_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnodeid)
+{
+	xwidgetnum_t		widgetnum;
+	char 			pathname[128];
+	devfs_handle_t		vhdl;
+	nasid_t			nasid, peer_nasid;
+	lboard_t		*board;
+
+
+
+	/* And its connected hub's nasids */
+	nasid = COMPACT_TO_NASID_NODEID(cnodeid);
+	peer_nasid = NODEPDA(cnodeid)->xbow_peer;
+
+	/* 
+	 * Look for paths matching "<widgetnum>/pci" under xswitchv.
+	 * For every widget, init. its lboard's hwgraph link.  If the
+	 * board has a PCI bridge, point the link to it.
+	 */
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX;
+		 widgetnum++) {
+		sprintf(pathname, "%d", widgetnum);
+		if (hwgraph_traverse(xswitchv, pathname, &vhdl) !=
+		    GRAPH_SUCCESS)
+			continue;
+
+		board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid),
+				NODEPDA(cnodeid)->geoid);
+		if (board == NULL && peer_nasid != INVALID_NASID) {
+			/*
+			 * Try to find the board on our peer
+			 */
+			board = find_lboard_module(
+				(lboard_t *)KL_CONFIG_INFO(peer_nasid),
+				NODEPDA(cnodeid)->geoid);
+		}
+		if (board == NULL) {
+			printk(KERN_WARNING  "Could not find PROM info for vertex 0x%p, "
+				"FRU analyzer may fail",
+				(void *)vhdl);
+			return;
+		}
+
+		if ( Is_pic_on_this_nasid[nasid] ) {
+			/* Check both buses */
+			sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum);
+			if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS)
+				board->brd_graph_link = vhdl;
+			else {
+				sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum);
+				if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS)
+					board->brd_graph_link = vhdl;
+				else
+					board->brd_graph_link = GRAPH_VERTEX_NONE;
+			}
+		}
+		else {
+			sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum);
+			if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS)
+				board->brd_graph_link = vhdl;
+			else
+				board->brd_graph_link = GRAPH_VERTEX_NONE;
+		}
+	}
+}
+
+/*
+ * Initialize all I/O on the specified node.
+ */
+static void
+io_init_node(cnodeid_t cnodeid)
+{
+	/*REFERENCED*/
+	devfs_handle_t hubv, switchv, widgetv;
+	struct xwidget_hwid_s hwid;
+	hubinfo_t hubinfo;
+	int is_xswitch;
+	nodepda_t	*npdap;
+	struct semaphore *peer_sema = 0;
+	uint32_t	widget_partnum;
+	nodepda_router_info_t *npda_rip;
+	cpu_cookie_t	c = 0;
+	extern int hubdev_docallouts(devfs_handle_t);
+
+	npdap = NODEPDA(cnodeid);
+
+	/*
+	 * Get the "top" vertex for this node's hardware
+	 * graph; it will carry the per-hub hub-specific
+	 * data, and act as the crosstalk provider master.
+	 * It's canonical path is probably something of the
+	 * form /hw/module/%M/slot/%d/node
+	 */
+	hubv = cnodeid_to_vertex(cnodeid);
+	DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap);
+
+	ASSERT(hubv != GRAPH_VERTEX_NONE);
+
+	hubdev_docallouts(hubv);
+
+	/*
+	 * Set up the dependent routers if we have any.
+	 */
+	npda_rip = npdap->npda_rip_first;
+
+	while(npda_rip) {
+		/* If the router info has not been initialized
+		 * then we need to do the router initialization
+		 */
+		if (!npda_rip->router_infop) {
+			router_init(cnodeid,0,npda_rip);
+		}
+		npda_rip = npda_rip->router_next;
+	}
+
+	/*
+	 * Read mfg info on this hub
+	 */
+
+	/* 
+	 * If nothing connected to this hub's xtalk port, we're done.
+	 */
+	early_probe_for_widget(hubv, &hwid);
+	if (hwid.part_num == XWIDGET_PART_NUM_NONE) {
+#ifdef PROBE_TEST
+		if ((cnodeid == 1) || (cnodeid == 2)) {
+			int index;
+
+			for (index = 0; index < 600; index++)
+				DBG("Interfering with device probing!!!\n");
+		}
+#endif
+		/* io_init_done takes cpu cookie as 2nd argument 
+		 * to do a restorenoderun for the setnoderun done 
+		 * at the start of this thread 
+		 */
+		
+		DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv);
+		return;
+		/* NOTREACHED */
+	}
+
+	/* 
+	 * attach our hub_provider information to hubv,
+	 * so we can use it as a crosstalk provider "master"
+	 * vertex.
+	 */
+	xtalk_provider_register(hubv, &hub_provider);
+	xtalk_provider_startup(hubv);
+
+	/*
+	 * Create a vertex to represent the crosstalk bus
+	 * attached to this hub, and a vertex to be used
+	 * as the connect point for whatever is out there
+	 * on the other side of our crosstalk connection.
+	 *
+	 * Crosstalk Switch drivers "climb up" from their
+	 * connection point to try and take over the switch
+	 * point.
+	 *
+	 * Of course, the edges and verticies may already
+	 * exist, in which case our net effect is just to
+	 * associate the "xtalk_" driver with the connection
+	 * point for the device.
+	 */
+
+	(void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv);
+
+	DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv);
+
+	ASSERT(switchv != GRAPH_VERTEX_NONE);
+
+	(void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO);
+
+	DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n");
+
+	/*
+	 * We need to find the widget id and update the basew_id field
+	 * accordingly. In particular, SN00 has direct connected bridge,
+	 * and hence widget id is Not 0.
+	 */
+
+	widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT;
+
+	if (widget_partnum == BRIDGE_WIDGET_PART_NUM ||
+				widget_partnum == XBRIDGE_WIDGET_PART_NUM){
+		npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
+
+		DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum);
+
+	} else if ((widget_partnum == XBOW_WIDGET_PART_NUM) ||
+			(widget_partnum == XXBOW_WIDGET_PART_NUM) ||
+			(widget_partnum == PXBOW_WIDGET_PART_NUM) ) {
+		/* 
+		 * Xbow control register does not have the widget ID field.
+		 * So, hard code the widget ID to be zero.
+		 */
+		DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum);
+		npdap->basew_id = 0;
+
+	} else {
+		npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
+
+		panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widget ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, (void *)hubv);
+
+		/*NOTREACHED*/
+	}
+	{
+		char widname[10];
+		sprintf(widname, "%x", npdap->basew_id);
+		(void)hwgraph_path_add(switchv, widname, &widgetv);
+		DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv);
+		ASSERT(widgetv != GRAPH_VERTEX_NONE);
+	}
+	
+	nodepda->basew_xc = widgetv;
+
+	is_xswitch = xwidget_hwid_is_xswitch(&hwid);
+
+	/* 
+	 * Try to become the master of the widget.  If this is an xswitch
+	 * with multiple hubs connected, only one will succeed.  Mastership
+	 * of an xswitch is used only when touching registers on that xswitch.
+	 * The slave xwidgets connected to the xswitch can be owned by various
+	 * masters.
+	 */
+	if (device_master_set(widgetv, hubv) == 0) {
+
+		/* Only one hub (thread) per Crosstalk device or switch makes
+		 * it to here.
+		 */
+
+		/* 
+		 * Initialize whatever xwidget is hanging off our hub.
+		 * Whatever it is, it's accessible through widgetnum 0.
+		 */
+		hubinfo_get(hubv, &hubinfo);
+
+		(void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL);
+
+		if (!is_xswitch) {
+			/* io_init_done takes cpu cookie as 2nd argument 
+			 * to do a restorenoderun for the setnoderun done 
+			 * at the start of this thread 
+			 */
+			io_init_done(cnodeid,c);
+			/* NOTREACHED */
+		}
+
+		/* 
+		 * Special handling for Crosstalk Switches (e.g. xbow).
+		 * We need to do things in roughly the following order:
+		 *	1) Initialize xswitch hardware (done above)
+		 *	2) Determine which hubs are available to be widget masters
+		 *	3) Discover which links are active from the xswitch
+		 *	4) Assign xwidgets hanging off the xswitch to hubs
+		 *	5) Initialize all xwidgets on the xswitch
+		 */
+
+		volunteer_for_widgets(switchv, hubv);
+
+		/* If there's someone else on this crossbow, recognize him */
+		if (npdap->xbow_peer != INVALID_NASID) {
+			nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer));
+			peer_sema = &peer_npdap->xbow_sema;
+			volunteer_for_widgets(switchv, peer_npdap->node_vertex);
+		}
+
+		assign_widgets_to_volunteers(switchv, hubv);
+
+		/* Signal that we're done */
+		if (peer_sema) {
+			mutex_unlock(peer_sema);
+		}
+		
+	}
+	else {
+	    /* Wait 'til master is done assigning widgets. */
+	    mutex_lock(&npdap->xbow_sema);
+	}
+
+#ifdef PROBE_TEST
+	if ((cnodeid == 1) || (cnodeid == 2)) {
+		int index;
+
+		for (index = 0; index < 500; index++)
+			DBG("Interfering with device probing!!!\n");
+	}
+#endif
+	/* Now both nodes can safely inititialize widgets */
+	io_init_xswitch_widgets(switchv, cnodeid);
+	io_link_xswitch_widgets(switchv, cnodeid);
+
+	/* io_init_done takes cpu cookie as 2nd argument 
+	 * to do a restorenoderun for the setnoderun done 
+	 * at the start of this thread 
+	 */
+	io_init_done(cnodeid,c);
+
+	DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid);
+}
+
+
+#define IOINIT_STKSZ	(16 * 1024)
+
+#define __DEVSTR1 	"/../.master/"
+#define __DEVSTR2 	"/target/"
+#define __DEVSTR3 	"/lun/0/disk/partition/"
+#define	__DEVSTR4	"/../ef"
+
+/*
+ * ioconfig starts numbering SCSI's at NUM_BASE_IO_SCSI_CTLR.
+ */
+#define NUM_BASE_IO_SCSI_CTLR 6
+/*
+ * This tells ioconfig where it can start numbering scsi controllers.
+ * Below this base number, platform-specific handles the numbering.
+ * XXX Irix legacy..controller numbering should be part of devfsd's job
+ */
+int num_base_io_scsi_ctlr = 2; /* used by syssgi */
+devfs_handle_t		base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR];
+static devfs_handle_t	baseio_enet_vhdl,baseio_console_vhdl;
+
+/*
+ * Put the logical controller number information in the 
+ * scsi controller vertices for each scsi controller that
+ * is in a "fixed position".
+ */
+static void
+scsi_ctlr_nums_add(devfs_handle_t pci_vhdl)
+{
+	{
+		int i;
+
+		num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR;
+
+		/* Initialize base_io_scsi_ctlr_vhdl array */
+		for (i=0; i<num_base_io_scsi_ctlr; i++)
+			base_io_scsi_ctlr_vhdl[i] = GRAPH_VERTEX_NONE;
+	}
+	{
+	/*
+	 * May want to consider changing the SN0 code, above, to work more like
+	 * the way this works.
+	 */
+	devfs_handle_t base_ibrick_xbridge_vhdl;
+	devfs_handle_t base_ibrick_xtalk_widget_vhdl;
+	devfs_handle_t scsi_ctlr_vhdl;
+	int i;
+	graph_error_t rv;
+
+	/*
+	 * This is a table of "well-known" SCSI controllers and their well-known
+	 * controller numbers.  The names in the table start from the base IBrick's
+	 * Xbridge vertex, so the first component is the xtalk widget number.
+	 */
+	static struct {
+		char	*base_ibrick_scsi_path;
+		int	controller_number;
+	} hardwired_scsi_controllers[] = {
+		{"15/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 0},
+		{"15/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 1},
+		{"15/" EDGE_LBL_PCI "/3/" EDGE_LBL_SCSI_CTLR "/0", 2},
+		{"14/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 3},
+		{"14/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 4},
+		{"15/" EDGE_LBL_PCI "/6/ohci/0/" EDGE_LBL_SCSI_CTLR "/0", 5},
+		{NULL, -1} /* must be last */
+	};
+
+	base_ibrick_xtalk_widget_vhdl = hwgraph_connectpt_get(pci_vhdl);
+	ASSERT_ALWAYS(base_ibrick_xtalk_widget_vhdl != GRAPH_VERTEX_NONE);
+
+	base_ibrick_xbridge_vhdl = hwgraph_connectpt_get(base_ibrick_xtalk_widget_vhdl);
+	ASSERT_ALWAYS(base_ibrick_xbridge_vhdl != GRAPH_VERTEX_NONE);
+	hwgraph_vertex_unref(base_ibrick_xtalk_widget_vhdl);
+
+	/*
+	 * Iterate through the list of well-known SCSI controllers.
+	 * For each controller found, set it's controller number according
+	 * to the table.
+	 */
+	for (i=0; hardwired_scsi_controllers[i].base_ibrick_scsi_path != NULL; i++) {
+		rv = hwgraph_path_lookup(base_ibrick_xbridge_vhdl,
+			hardwired_scsi_controllers[i].base_ibrick_scsi_path, &scsi_ctlr_vhdl, NULL);
+
+		if (rv != GRAPH_SUCCESS) /* No SCSI at this path */
+			continue;
+
+		ASSERT(hardwired_scsi_controllers[i].controller_number < NUM_BASE_IO_SCSI_CTLR);
+		base_io_scsi_ctlr_vhdl[hardwired_scsi_controllers[i].controller_number] = scsi_ctlr_vhdl;
+		device_controller_num_set(scsi_ctlr_vhdl, hardwired_scsi_controllers[i].controller_number);
+		hwgraph_vertex_unref(scsi_ctlr_vhdl); /* (even though we're actually keeping a reference) */
+	}
+
+	hwgraph_vertex_unref(base_ibrick_xbridge_vhdl);
+	}
+}
+
+
+#include <asm/sn/ioerror_handling.h>
+devfs_handle_t		sys_critical_graph_root = GRAPH_VERTEX_NONE;
+
+/* Define the system critical vertices and connect them through
+ * a canonical parent-child relationships for easy traversal
+ * during io error handling.
+ */
+static void
+sys_critical_graph_init(void)
+{
+	devfs_handle_t		bridge_vhdl,master_node_vhdl;
+	devfs_handle_t  		xbow_vhdl = GRAPH_VERTEX_NONE;
+	extern devfs_handle_t	hwgraph_root;
+	devfs_handle_t		pci_slot_conn;
+	int			slot;
+	devfs_handle_t		baseio_console_conn;
+
+	DBG("sys_critical_graph_init: FIXME.\n");
+	baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl);
+
+	if (baseio_console_conn == NULL) {
+		return;
+	}
+
+	/* Get the vertex handle for the baseio bridge */
+	bridge_vhdl = device_master_get(baseio_console_conn);
+
+	/* Get the master node of the baseio card */
+	master_node_vhdl = cnodeid_to_vertex(
+				master_node_get(baseio_console_vhdl));
+	
+	/* Add the "root->node" part of the system critical graph */
+
+	sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl);
+
+	/* Check if we have a crossbow */
+	if (hwgraph_traverse(master_node_vhdl,
+			     EDGE_LBL_XTALK"/0",
+			     &xbow_vhdl) == GRAPH_SUCCESS) {
+		/* We have a crossbow.Add "node->xbow" part of the system 
+		 * critical graph.
+		 */
+		sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl);
+		
+		/* Add "xbow->baseio bridge" of the system critical graph */
+		sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl);
+
+		hwgraph_vertex_unref(xbow_vhdl);
+	} else 
+		/* We donot have a crossbow. Add "node->baseio_bridge"
+		 * part of the system critical graph.
+		 */
+		sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl);
+
+	/* Add all the populated PCI slot vertices to the system critical
+	 * graph with the bridge vertex as the parent.
+	 */
+	for (slot = 0 ; slot < 8; slot++) {
+		char	slot_edge[10];
+
+		sprintf(slot_edge,"%d",slot);
+		if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn)
+		    != GRAPH_SUCCESS)
+			continue;
+		sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+
+	hwgraph_vertex_unref(bridge_vhdl);
+
+	/* Add the "ioc3 pci connection point  -> console ioc3" part 
+	 * of the system critical graph
+	 */
+
+	if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) ==
+	    GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      baseio_console_vhdl);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+
+	/* Add the "ethernet pci connection point  -> base ethernet" part of 
+	 * the system  critical graph
+	 */
+	if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) ==
+	    GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      baseio_enet_vhdl);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+
+	/* Add the "scsi controller pci connection point  -> base scsi 
+	 * controller" part of the system critical graph
+	 */
+	if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0],
+			     "../..",&pci_slot_conn) == GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      base_io_scsi_ctlr_vhdl[0]);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+	if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1],
+			     "../..",&pci_slot_conn) == GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      base_io_scsi_ctlr_vhdl[1]);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+	hwgraph_vertex_unref(baseio_console_conn);
+
+}
+
+static void
+baseio_ctlr_num_set(void)
+{
+	char 			name[MAXDEVNAME];
+	devfs_handle_t		console_vhdl, pci_vhdl, enet_vhdl;
+	devfs_handle_t		ioc3_console_vhdl_get(void);
+
+
+	DBG("baseio_ctlr_num_set; FIXME\n");
+	console_vhdl = ioc3_console_vhdl_get();
+	if (console_vhdl == GRAPH_VERTEX_NONE)
+		return;
+	/* Useful for setting up the system critical graph */
+	baseio_console_vhdl = console_vhdl;
+
+	vertex_to_name(console_vhdl,name,MAXDEVNAME);
+
+	strcat(name,__DEVSTR1);
+	pci_vhdl =  hwgraph_path_to_vertex(name);
+	scsi_ctlr_nums_add(pci_vhdl);
+	/* Unref the pci_vhdl due to the reference by hwgraph_path_to_vertex
+	 */
+	hwgraph_vertex_unref(pci_vhdl);
+
+	vertex_to_name(console_vhdl, name, MAXDEVNAME);
+	strcat(name, __DEVSTR4);
+	enet_vhdl = hwgraph_path_to_vertex(name);
+
+	/* Useful for setting up the system critical graph */
+	baseio_enet_vhdl = enet_vhdl;
+
+	device_controller_num_set(enet_vhdl, 0);
+	/* Unref the enet_vhdl due to the reference by hwgraph_path_to_vertex
+	 */
+	hwgraph_vertex_unref(enet_vhdl);
+}
+/* #endif */
+
+/*
+ * Initialize all I/O devices.  Starting closest to nodes, probe and
+ * initialize outward.
+ */
+void
+init_all_devices(void)
+{
+	/* Governor on init threads..bump up when safe 
+	 * (beware many devfs races) 
+	 */
+	cnodeid_t cnodeid, active;
+
+	active = 0;
+	for (cnodeid = 0; cnodeid < numnodes; cnodeid++) {
+                DBG("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid);
+                io_init_node(cnodeid);
+
+		DBG("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid);
+	}
+
+	for (cnodeid = 0; cnodeid < numnodes; cnodeid++)
+		/*
+	 	 * Update information generated by IO init.
+		 */
+		update_node_information(cnodeid);
+
+	baseio_ctlr_num_set();
+	/* Setup the system critical graph (which is a subgraph of the
+	 * main hwgraph). This information is useful during io error
+	 * handling.
+	 */
+	sys_critical_graph_init();
+
+#if HWG_PRINT
+	hwgraph_print();
+#endif
+
+}
+
+#define toint(x) ((int)(x) - (int)('0'))
+
+void
+devnamefromarcs(char *devnm)
+{
+	int 			val;
+	char 			tmpnm[MAXDEVNAME];
+	char 			*tmp1, *tmp2;
+	
+	val = strncmp(devnm, "dks", 3);
+	if (val != 0) 
+		return;
+	tmp1 = devnm + 3;
+	if (!isdigit(*tmp1))
+		return;
+
+	val = 0;
+	while (isdigit(*tmp1)) {
+		val = 10*val+toint(*tmp1);
+		tmp1++;
+	}
+
+	if(*tmp1 != 'd')
+		return;
+	else
+		tmp1++;
+
+	if ((val < 0) || (val >= num_base_io_scsi_ctlr)) {
+		int i;
+		int viable_found = 0;
+
+		DBG("Only controller numbers 0..%d  are supported for\n", NUM_BASE_IO_SCSI_CTLR-1);
+		DBG("prom \"root\" variables of the form dksXdXsX.\n");
+		DBG("To use another disk you must use the full hardware graph path\n\n");
+		DBG("Possible controller numbers for use in 'dksXdXsX' on this system: ");
+		for (i=0; i<NUM_BASE_IO_SCSI_CTLR; i++) {
+			if (base_io_scsi_ctlr_vhdl[i] != GRAPH_VERTEX_NONE) {
+				DBG("%d ", i);
+				viable_found=1;
+			}
+		}
+		if (viable_found)
+			DBG("\n");
+		else
+			DBG("none found!\n");
+
+		DELAY(15000000);
+		//prom_reboot();
+		panic("FIXME: devnamefromarcs: should call prom_reboot here.\n");
+		/* NOTREACHED */
+	}
+		
+	ASSERT(base_io_scsi_ctlr_vhdl[val] != GRAPH_VERTEX_NONE);
+	vertex_to_name(base_io_scsi_ctlr_vhdl[val],
+		       tmpnm,
+		       MAXDEVNAME);
+	tmp2 = 	tmpnm + strlen(tmpnm);
+	strcpy(tmp2, __DEVSTR2);
+	tmp2 += strlen(__DEVSTR2);
+	while (*tmp1 != 's') {
+		if((*tmp2++ = *tmp1++) == '\0')
+			return;
+	}	
+	tmp1++;
+	strcpy(tmp2, __DEVSTR3);
+	tmp2 += strlen(__DEVSTR3);
+	while ( (*tmp2++ = *tmp1++) )
+		;
+	tmp2--;
+	*tmp2++ = '/';
+	strcpy(tmp2, EDGE_LBL_BLOCK);
+	strcpy(devnm,tmpnm);
+}
+
+static
+struct io_brick_map_s io_brick_tab[] = {
+
+/* Ibrick widget number to PCI bus number map */
+ {      MODULE_IBRICK,                          /* Ibrick type    */ 
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        0,                                      /* 0x8            */
+        0,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        0,                                      /* 0xc            */
+        0,                                      /* 0xd            */
+        2,                                      /* 0xe            */
+        1                                       /* 0xf            */
+     }
+ },
+
+/* Pbrick widget number to PCI bus number map */
+ {      MODULE_PBRICK,                          /* Pbrick type    */ 
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        2,                                      /* 0x8            */
+        1,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        4,                                      /* 0xc            */
+        6,                                      /* 0xd            */
+        3,                                      /* 0xe            */
+        5                                       /* 0xf            */
+    }
+ },
+
+/* PXbrick widget number to PCI bus number map */
+ {      MODULE_PXBRICK,                         /* PXbrick type   */ 
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        0,                                      /* 0x8            */
+        0,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        1,                                      /* 0xc            */
+        5,                                      /* 0xd            */
+        0,                                      /* 0xe            */
+        3                                       /* 0xf            */
+    }
+ },
+
+/* Xbrick widget to XIO slot map */
+ {      MODULE_XBRICK,                          /* Xbrick type    */ 
+    /*  XIO Slot #                                 Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        1,                                      /* 0x8            */
+        3,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        2,                                      /* 0xc            */
+        4,                                      /* 0xd            */
+        0,                                      /* 0xe            */
+        0                                       /* 0xf            */
+    }
+ }
+};
+
+/*
+ * Use the brick's type to map a widget number to a meaningful int
+ */
+int
+io_brick_map_widget(int brick_type, int widget_num)
+{
+        int num_bricks, i;
+
+        /* Calculate number of bricks in table */
+        num_bricks = sizeof(io_brick_tab)/sizeof(io_brick_tab[0]);
+
+        /* Look for brick prefix in table */
+        for (i = 0; i < num_bricks; i++) {
+               if (brick_type == io_brick_tab[i].ibm_type)
+                       return(io_brick_tab[i].ibm_map_wid[widget_num]);
+        }
+
+        return 0;
+
+}
+
+/*
+ * Use the device's vertex to map the device's widget to a meaningful int
+ */
+int
+io_path_map_widget(devfs_handle_t vertex)
+{
+        char hw_path_name[MAXDEVNAME];
+        char *wp, *bp, *sp = NULL;
+        int  widget_num;
+	long atoi(char *);
+	int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen);
+
+
+        /* Get the full path name of the vertex */
+        if (GRAPH_SUCCESS != hwgraph_vertex_name_get(vertex, hw_path_name,
+                                                     MAXDEVNAME))
+                return 0;
+
+        /* Find the widget number in the path name */
+        wp = strstr(hw_path_name, "/"EDGE_LBL_XTALK"/");
+        if (wp == NULL)
+                return 0;
+        widget_num = atoi(wp+7);
+        if (widget_num < XBOW_PORT_8 || widget_num > XBOW_PORT_F)
+                return 0;
+
+        /* Find "brick" in the path name */
+        bp = strstr(hw_path_name, "brick");
+        if (bp == NULL)
+                return 0;
+
+        /* Find preceding slash */
+        sp = bp;
+        while (sp > hw_path_name) {
+                sp--;
+                if (*sp == '/')
+                        break;
+        }
+
+        /* Invalid if no preceding slash */
+        if (!sp)
+                return 0;
+
+        /* Bump slash pointer to "brick" prefix */
+        sp++;
+        /*
+         * Verify "brick" prefix length;  valid exaples:
+         * 'I' from "/Ibrick"
+         * 'P' from "/Pbrick"
+         * 'X' from "/Xbrick"
+         */
+         if ((bp - sp) != 1)
+                return 0;
+
+        return (io_brick_map_widget((int)*sp, widget_num));
+
+}
diff -Nru a/arch/ia64/sn/io/sn2/module.c b/arch/ia64/sn/io/sn2/module.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/module.c	Mon Feb 24 05:25:25 2003
@@ -0,0 +1,280 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn1/hubdev.h>
+#include <asm/sn/module.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/sn_cpuid.h>
+
+
+/* #define LDEBUG	1  */
+
+#ifdef LDEBUG
+#define DPRINTF		printk
+#define printf		printk
+#else
+#define DPRINTF(x...)
+#endif
+
+module_t	       *modules[MODULE_MAX];
+int			nummodules;
+
+#define SN00_SERIAL_FUDGE	0x3b1af409d513c2
+#define SN0_SERIAL_FUDGE	0x6e
+
+void
+encode_int_serial(uint64_t src,uint64_t *dest)
+{
+    uint64_t val;
+    int i;
+
+    val = src + SN00_SERIAL_FUDGE;
+
+
+    for (i = 0; i < sizeof(long long); i++) {
+	((char*)dest)[i] =
+	    ((char*)&val)[sizeof(long long)/2 +
+			 ((i%2) ? ((i/2 * -1) - 1) : (i/2))];
+    }
+}
+
+
+void
+decode_int_serial(uint64_t src, uint64_t *dest)
+{
+    uint64_t val;
+    int i;
+
+    for (i = 0; i < sizeof(long long); i++) {
+	((char*)&val)[sizeof(long long)/2 +
+		     ((i%2) ? ((i/2 * -1) - 1) : (i/2))] =
+	    ((char*)&src)[i];
+    }
+
+    *dest = val - SN00_SERIAL_FUDGE;
+}
+
+
+void
+encode_str_serial(const char *src, char *dest)
+{
+    int i;
+
+    for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
+
+	dest[i] = src[MAX_SERIAL_NUM_SIZE/2 +
+		     ((i%2) ? ((i/2 * -1) - 1) : (i/2))] +
+	    SN0_SERIAL_FUDGE;
+    }
+}
+
+void
+decode_str_serial(const char *src, char *dest)
+{
+    int i;
+
+    for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
+	dest[MAX_SERIAL_NUM_SIZE/2 +
+	    ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = src[i] -
+	    SN0_SERIAL_FUDGE;
+    }
+}
+
+
+module_t *module_lookup(moduleid_t id)
+{
+    int			i;
+
+    for (i = 0; i < nummodules; i++)
+	if (modules[i]->id == id) {
+	    DPRINTF("module_lookup: found m=0x%p\n", modules[i]);
+	    return modules[i];
+	}
+
+    return NULL;
+}
+
+/*
+ * module_add_node
+ *
+ *   The first time a new module number is seen, a module structure is
+ *   inserted into the module list in order sorted by module number
+ *   and the structure is initialized.
+ *
+ *   The node number is added to the list of nodes in the module.
+ */
+
+module_t *module_add_node(geoid_t geoid, cnodeid_t cnodeid)
+{
+    module_t	       *m;
+    int			i;
+    char		buffer[16];
+    moduleid_t		moduleid;
+
+    memset(buffer, 0, 16);
+    moduleid = geo_module(geoid);
+    format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF);
+    DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid);
+
+    if ((m = module_lookup(moduleid)) == 0) {
+	m = kmalloc(sizeof (module_t), GFP_KERNEL);
+	memset(m, 0 , sizeof(module_t));
+	ASSERT_ALWAYS(m);
+
+	m->id = moduleid;
+	spin_lock_init(&m->lock);
+
+	mutex_init_locked(&m->thdcnt);
+
+	/* Insert in sorted order by module number */
+
+	for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--)
+	    modules[i] = modules[i - 1];
+
+	modules[i] = m;
+	nummodules++;
+    }
+
+    m->nodes[m->nodecnt] = cnodeid;
+    m->geoid[m->nodecnt] = geoid;
+    m->nodecnt++;
+
+    DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt);
+
+    return m;
+}
+
+int module_probe_snum(module_t *m, nasid_t nasid)
+{
+    lboard_t	       *board;
+    klmod_serial_num_t *comp;
+    char * bcopy(const char * src, char * dest, int count);
+    char serial_number[16];
+
+    /*
+     * record brick serial number
+     */
+    board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+
+    if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
+    {
+#if	LDEBUG
+	printf ("module_probe_snum: no IP35 board found!\n");
+#endif
+	return 0;
+    }
+
+    board_serial_number_get( board, serial_number );
+    if( serial_number[0] != '\0' ) {
+	encode_str_serial( serial_number, m->snum.snum_str );
+	m->snum_valid = 1;
+    }
+#if	LDEBUG
+    else {
+	printf("module_probe_snum: brick serial number is null!\n");
+    }
+    printf("module_probe_snum: brick serial number == %s\n", serial_number);
+#endif /* DEBUG */
+
+    board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid),
+			KLTYPE_IOBRICK_XBOW);
+
+    if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
+	return 0;
+
+    comp = GET_SNUM_COMP(board);
+
+    if (comp) {
+#if LDEBUG
+	    int i;
+
+	    printf("********found module with id %x and string", m->id);
+
+	    for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++)
+		printf(" %x ", comp->snum.snum_str[i]);
+
+	    printf("\n");	/* Fudged string is not ASCII */
+#endif
+
+	    if (comp->snum.snum_str[0] != '\0') {
+		bcopy(comp->snum.snum_str,
+		      m->sys_snum,
+		      MAX_SERIAL_NUM_SIZE);
+		m->sys_snum_valid = 1;
+	    }
+    }
+
+    if (m->sys_snum_valid)
+	return 1;
+    else {
+	DPRINTF("Invalid serial number for module %d, "
+		"possible missing or invalid NIC.", m->id);
+	return 0;
+    }
+}
+
+void
+io_module_init(void)
+{
+    cnodeid_t		node;
+    lboard_t	       *board;
+    nasid_t		nasid;
+    int			nserial;
+    module_t	       *m;
+
+    DPRINTF("*******module_init\n");
+
+    nserial = 0;
+
+    for (node = 0; node < numnodes; node++) {
+	nasid = COMPACT_TO_NASID_NODEID(node);
+
+	board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+	ASSERT(board);
+
+	m = module_add_node(board->brd_geoid, node);
+
+	if (! m->snum_valid && module_probe_snum(m, nasid))
+	    nserial++;
+    }
+
+    DPRINTF("********found total of %d serial numbers in the system\n",
+	    nserial);
+
+    if (nserial == 0)
+	DPRINTF(KERN_WARNING  "io_module_init: No serial number found.\n");
+}
+
+int
+get_kmod_info(cmoduleid_t cmod, module_info_t *mod_info)
+{
+    if (cmod < 0 || cmod >= nummodules)
+	return -EINVAL;
+
+    mod_info->mod_num = modules[cmod]->id;
+
+    ia64_sn_sys_serial_get(mod_info->serial_str);
+    
+    mod_info->serial_num = ia64_sn_partition_serial_get();
+
+    return 0;
+}
diff -Nru a/arch/ia64/sn/io/sn2/pci_bus_cvlink.c b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c	Mon Feb 24 05:25:42 2003
@@ -0,0 +1,725 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <asm/sn/types.h>
+#include <asm/sn/hack.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/driver.h>
+#include <asm/sn/iograph.h>
+#include <asm/param.h>
+#include <asm/sn/pio.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/xtalk/xtalkaddrs.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
+#include <asm/sn/simulator.h>
+#include <asm/sn/sn_cpuid.h>
+
+extern int bridge_rev_b_data_check_disable;
+
+devfs_handle_t busnum_to_pcibr_vhdl[MAX_PCI_XWIDGET];
+nasid_t busnum_to_nid[MAX_PCI_XWIDGET];
+void * busnum_to_atedmamaps[MAX_PCI_XWIDGET];
+unsigned char num_bridges;
+static int done_probing = 0;
+
+static int pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid);
+devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn);
+
+extern unsigned char Is_pic_on_this_nasid[512];
+
+extern void sn_init_irq_desc(void);
+extern void register_pcibr_intr(int irq, pcibr_intr_t intr);
+
+
+/*
+ * For the given device, initialize whether it is a PIC device.
+ */
+static void
+set_isPIC(struct sn_device_sysdata *device_sysdata)
+{
+	pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl);
+	pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
+
+	device_sysdata->isPIC = IS_PIC_SOFT(pcibr_soft);;
+}
+
+/*
+ * pci_bus_cvlink_init() - To be called once during initialization before 
+ *	SGI IO Infrastructure init is called.
+ */
+void
+pci_bus_cvlink_init(void)
+{
+
+	extern void ioconfig_bus_init(void);
+
+	memset(busnum_to_pcibr_vhdl, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET);
+	memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET);
+
+	memset(busnum_to_atedmamaps, 0x0, sizeof(void *) * MAX_PCI_XWIDGET);
+
+	num_bridges = 0;
+
+	ioconfig_bus_init();
+}
+
+/*
+ * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated 
+ *	pci bus vertex from the SGI IO Infrastructure.
+ */
+devfs_handle_t
+pci_bus_to_vertex(unsigned char busnum)
+{
+
+	devfs_handle_t	pci_bus = NULL;
+
+
+	/*
+	 * First get the xwidget vertex.
+	 */
+	pci_bus = busnum_to_pcibr_vhdl[busnum];
+	return(pci_bus);
+}
+
+/*
+ * devfn_to_vertex() - returns the vertex of the device given the bus, slot, 
+ *	and function numbers.
+ */
+devfs_handle_t
+devfn_to_vertex(unsigned char busnum, unsigned int devfn)
+{
+
+	int slot = 0;
+	int func = 0;
+	char	name[16];
+	devfs_handle_t  pci_bus = NULL;
+	devfs_handle_t	device_vertex = (devfs_handle_t)NULL;
+
+	/*
+	 * Go get the pci bus vertex.
+	 */
+	pci_bus = pci_bus_to_vertex(busnum);
+	if (!pci_bus) {
+		/*
+		 * During probing, the Linux pci code invents non existant
+		 * bus numbers and pci_dev structures and tries to access
+		 * them to determine existance. Don't crib during probing.
+		 */
+		if (done_probing)
+			printk("devfn_to_vertex: Invalid bus number %d given.\n", busnum);
+		return(NULL);
+	}
+
+
+	/*
+	 * Go get the slot&function vertex.
+	 * Should call pciio_slot_func_to_name() when ready.
+	 */
+	slot = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+
+	/*
+	 * For a NON Multi-function card the name of the device looks like:
+	 * ../pci/1, ../pci/2 ..
+	 */
+	if (func == 0) {
+        	sprintf(name, "%d", slot);
+		if (hwgraph_traverse(pci_bus, name, &device_vertex) == 
+			GRAPH_SUCCESS) {
+			if (device_vertex) {
+				return(device_vertex);
+			}
+		}
+	}
+			
+	/*
+	 * This maybe a multifunction card.  It's names look like:
+	 * ../pci/1a, ../pci/1b, etc.
+	 */
+	sprintf(name, "%d%c", slot, 'a'+func);
+	if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) {
+		if (!device_vertex) {
+			return(NULL);
+		}
+	}
+
+	return(device_vertex);
+}
+
+/*
+ * For the given device, initialize the addresses for both the Device(x) Flush 
+ * Write Buffer register and the Xbow Flush Register for the port the PCI bus 
+ * is connected.
+ */
+static void
+set_flush_addresses(struct pci_dev *device_dev, 
+	struct sn_device_sysdata *device_sysdata)
+{
+	pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl);
+	pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+	pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
+    	bridge_t               *bridge = pcibr_soft->bs_base;
+	nasid_t			nasid;
+
+	/*
+	 * Get the nasid from the bridge.
+	 */
+	nasid = NASID_GET(device_sysdata->dma_buf_sync);
+	if (IS_PIC_DEVICE(device_dev)) {
+		device_sysdata->dma_buf_sync = (volatile unsigned int *)
+			&bridge->b_wr_req_buf[pciio_slot].reg;
+		device_sysdata->xbow_buf_sync = (volatile unsigned int *)
+			XBOW_PRIO_LINKREGS_PTR(NODE_SWIN_BASE(nasid, 0),
+			pcibr_soft->bs_xid);
+	} else {
+		/*
+		 * Accessing Xbridge and Xbow register when SHUB swapoper is on!.
+		 */
+		device_sysdata->dma_buf_sync = (volatile unsigned int *)
+			((uint64_t)&(bridge->b_wr_req_buf[pciio_slot].reg)^4);
+		device_sysdata->xbow_buf_sync = (volatile unsigned int *)
+			((uint64_t)(XBOW_PRIO_LINKREGS_PTR(
+			NODE_SWIN_BASE(nasid, 0), pcibr_soft->bs_xid)) ^ 4);
+	}
+
+#ifdef DEBUG
+	printk("set_flush_addresses: dma_buf_sync %p xbow_buf_sync %p\n", 
+		device_sysdata->dma_buf_sync, device_sysdata->xbow_buf_sync);
+
+printk("set_flush_addresses: dma_buf_sync\n");
+	while((volatile unsigned int )*device_sysdata->dma_buf_sync);
+printk("set_flush_addresses: xbow_buf_sync\n");
+	while((volatile unsigned int )*device_sysdata->xbow_buf_sync);
+#endif
+
+}
+
+/*
+ * Most drivers currently do not properly tell the arch specific pci dma
+ * interfaces whether they can handle A64. Here is where we privately
+ * keep track of this.
+ */
+static void __init
+set_sn_pci64(struct pci_dev *dev)
+{
+	unsigned short vendor = dev->vendor;
+	unsigned short device = dev->device;
+
+	if (vendor == PCI_VENDOR_ID_QLOGIC) {
+		if ((device == PCI_DEVICE_ID_QLOGIC_ISP2100) ||
+				(device == PCI_DEVICE_ID_QLOGIC_ISP2200)) {
+			SET_PCIA64(dev);
+			return;
+		}
+	}
+
+	if (vendor == PCI_VENDOR_ID_SGI) {
+		if (device == PCI_DEVICE_ID_SGI_IOC3) {
+			SET_PCIA64(dev);
+			return;
+		}
+	}
+
+}
+
+/*
+ * sn_pci_fixup() - This routine is called when platform_pci_fixup() is 
+ *	invoked at the end of pcibios_init() to link the Linux pci 
+ *	infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c
+ *
+ *	Other platform specific fixup can also be done here.
+ */
+void
+sn_pci_fixup(int arg)
+{
+	struct list_head *ln;
+	struct pci_bus *pci_bus = NULL;
+	struct pci_dev *device_dev = NULL;
+	struct sn_widget_sysdata *widget_sysdata;
+	struct sn_device_sysdata *device_sysdata;
+	pciio_intr_t intr_handle;
+	int cpuid, bit;
+	devfs_handle_t device_vertex;
+	pciio_intr_line_t lines;
+	extern void sn_pci_find_bios(void);
+	extern int numnodes;
+	int cnode;
+	extern void io_sh_swapper(int, int);
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )
+			io_sh_swapper((cnodeid_to_nasid(cnode)), 0);
+	}
+
+	if (arg == 0) {
+#ifdef CONFIG_PROC_FS
+		extern void register_sn_procfs(void);
+#endif
+
+		sn_init_irq_desc();
+		sn_pci_find_bios();
+		for (cnode = 0; cnode < numnodes; cnode++) {
+			extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int);
+			intr_init_vecblk(NODEPDA(cnode), cnode, 0);
+		} 
+
+		/*
+		 * When we return to generic Linux, Swapper is always on ..
+		 */
+		for (cnode = 0; cnode < numnodes; cnode++) {
+			if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )
+				io_sh_swapper((cnodeid_to_nasid(cnode)), 1);
+		}
+#ifdef CONFIG_PROC_FS
+		register_sn_procfs();
+#endif
+		return;
+	}
+
+
+	done_probing = 1;
+
+	/*
+	 * Initialize the pci bus vertex in the pci_bus struct.
+	 */
+	for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
+		pci_bus = pci_bus_b(ln);
+		widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), 
+					GFP_KERNEL);
+		widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number);
+		pci_bus->sysdata = (void *)widget_sysdata;
+	}
+
+	/*
+ 	 * set the root start and end so that drivers calling check_region()
+	 * won't see a conflict
+	 */
+	ioport_resource.start  = 0xc000000000000000;
+	ioport_resource.end =    0xcfffffffffffffff;
+
+	/*
+	 * Set the root start and end for Mem Resource.
+	 */
+	iomem_resource.start = 0;
+	iomem_resource.end = 0xffffffffffffffff;
+
+	/*
+	 * Initialize the device vertex in the pci_dev struct.
+	 */
+	pci_for_each_dev(device_dev) {
+		unsigned int irq;
+		int idx;
+		u16 cmd;
+		devfs_handle_t vhdl;
+		unsigned long size;
+		extern int bit_pos_to_irq(int);
+
+		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
+				device_dev->device == PCI_DEVICE_ID_SGI_IOC3) {
+			extern void pci_fixup_ioc3(struct pci_dev *d);
+			pci_fixup_ioc3(device_dev);
+		}
+
+		/* Set the device vertex */
+
+		device_sysdata = kmalloc(sizeof(struct sn_device_sysdata),
+					GFP_KERNEL);
+		device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn);
+		device_sysdata->isa64 = 0;
+		/*
+		 * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush 
+		 * register addresses.
+		 */
+		(void) set_flush_addresses(device_dev, device_sysdata);
+
+		device_dev->sysdata = (void *) device_sysdata;
+		set_sn_pci64(device_dev);
+		set_isPIC(device_sysdata);
+
+		pci_read_config_word(device_dev, PCI_COMMAND, &cmd);
+
+		/*
+		 * Set the resources address correctly.  The assumption here 
+		 * is that the addresses in the resource structure has been
+		 * read from the card and it was set in the card by our
+		 * Infrastructure ..
+		 */
+		vhdl = device_sysdata->vhdl;
+		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+			size = 0;
+			size = device_dev->resource[idx].end -
+				device_dev->resource[idx].start;
+			if (size) {
+				device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
+				device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET;
+			}
+			else
+				continue;
+
+			device_dev->resource[idx].end = 
+				device_dev->resource[idx].start + size;
+
+			if (device_dev->resource[idx].flags & IORESOURCE_IO)
+				cmd |= PCI_COMMAND_IO;
+
+			if (device_dev->resource[idx].flags & IORESOURCE_MEM)
+				cmd |= PCI_COMMAND_MEMORY;
+		}
+#if 0
+	/*
+	 * Software WAR for a Software BUG.
+	 * This is only temporary.
+	 * See PV 872791
+	 */
+
+		/*
+		 * Now handle the ROM resource ..
+		 */
+		size = device_dev->resource[PCI_ROM_RESOURCE].end -
+			device_dev->resource[PCI_ROM_RESOURCE].start;
+
+		if (size) {
+			device_dev->resource[PCI_ROM_RESOURCE].start =
+			(unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, 
+				size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
+			device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET;
+			device_dev->resource[PCI_ROM_RESOURCE].end =
+			device_dev->resource[PCI_ROM_RESOURCE].start + size;
+		}
+#endif
+
+		/*
+		 * Update the Command Word on the Card.
+		 */
+		cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */
+					   /* bit gets dropped .. no harm */
+		pci_write_config_word(device_dev, PCI_COMMAND, cmd);
+
+		pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines);
+		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
+			device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
+				lines = 1;
+		}
+ 
+		device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata;
+		device_vertex = device_sysdata->vhdl;
+ 
+		intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex);
+
+		bit = intr_handle->pi_irq;
+		cpuid = intr_handle->pi_cpu;
+		irq = bit;
+		irq = irq + (cpuid << 8);
+		pciio_intr_connect(intr_handle, (intr_func_t)0, (intr_arg_t)0);
+		device_dev->irq = irq;
+		register_pcibr_intr(irq, (pcibr_intr_t)intr_handle);
+#ifdef ajmtestintr
+		{
+			int slot = PCI_SLOT(device_dev->devfn);
+			static int timer_set = 0;
+			pcibr_intr_t	pcibr_intr = (pcibr_intr_t)intr_handle;
+			pcibr_soft_t	pcibr_soft = pcibr_intr->bi_soft;
+			extern void intr_test_handle_intr(int, void*, struct pt_regs *);
+
+			if (!timer_set) {
+				intr_test_set_timer();
+				timer_set = 1;
+			}
+			intr_test_register_irq(irq, pcibr_soft, slot);
+			request_irq(irq, intr_test_handle_intr,0,NULL, NULL);
+		}
+#endif
+
+	}
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )
+			io_sh_swapper((cnodeid_to_nasid(cnode)), 1);
+	}
+}
+
+/*
+ * linux_bus_cvlink() Creates a link between the Linux PCI Bus number 
+ *	to the actual hardware component that it represents:
+ *	/dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci
+ *
+ *	The bus vertex, when called to devfs_generate_path() returns:
+ *		hw/module/001c01/slab/0/Ibrick/xtalk/15/pci
+ *		hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/0
+ *		hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/1
+ */
+void
+linux_bus_cvlink(void)
+{
+	char name[8];
+	int index;
+	
+	for (index=0; index < MAX_PCI_XWIDGET; index++) {
+		if (!busnum_to_pcibr_vhdl[index])
+			continue;
+
+		sprintf(name, "%x", index);
+		(void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], 
+				name);
+	}
+}
+
+/*
+ * pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job.
+ *
+ *	Linux PCI Bus numbers are assigned from lowest module_id numbers
+ *	(rack/slot etc.) starting from HUB_WIDGET_ID_MAX down to 
+ *	HUB_WIDGET_ID_MIN:
+ *		widgetnum 15 gets lower Bus Number than widgetnum 14 etc.
+ *
+ *	Given 2 modules 001c01 and 001c02 we get the following mappings:
+ *		001c01, widgetnum 15 = Bus number 0
+ *		001c01, widgetnum 14 = Bus number 1
+ *		001c02, widgetnum 15 = Bus number 3
+ *		001c02, widgetnum 14 = Bus number 4
+ *		etc.
+ *
+ * The rational for starting Bus Number 0 with Widget number 15 is because 
+ * the system boot disks are always connected via Widget 15 Slot 0 of the 
+ * I-brick.  Linux creates /dev/sd* devices(naming) strating from Bus Number 0 
+ * Therefore, /dev/sda1 will be the first disk, on Widget 15 of the lowest 
+ * module id(Master Cnode) of the system.
+ *	
+ */
+static int 
+pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid)
+{
+
+	devfs_handle_t master_node_vertex = NULL;
+	devfs_handle_t xwidget = NULL;
+	devfs_handle_t pci_bus = NULL;
+	hubinfo_t hubinfo = NULL;
+	xwidgetnum_t widgetnum;
+	char pathname[128];
+	graph_error_t rv;
+	int bus;
+	int basebus_num;
+	int bus_number;
+
+	/*
+	 * Loop throught this vertex and get the Xwidgets ..
+	 */
+
+
+	/* PCI devices */
+
+	for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) {
+		sprintf(pathname, "%d", widgetnum);
+		xwidget = NULL;
+		
+		/*
+		 * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget
+		 *	     /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device
+		 */
+		rv = hwgraph_traverse(xtalk, pathname, &xwidget);
+		if ( (rv != GRAPH_SUCCESS) ) {
+			if (!xwidget) {
+				continue;
+			}
+		}
+
+		sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum);
+		pci_bus = NULL;
+		if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS)
+			if (!pci_bus) {
+				continue;
+}
+
+		/*
+		 * Assign the correct bus number and also the nasid of this 
+		 * pci Xwidget.
+		 * 
+		 * Should not be any race here ...
+		 */
+		num_bridges++;
+		busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus;
+
+		/*
+		 * Get the master node and from there get the NASID.
+		 */
+		master_node_vertex = device_master_get(xwidget);
+		if (!master_node_vertex) {
+			printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget);
+		}
+	
+		hubinfo_get(master_node_vertex, &hubinfo);
+		if (!hubinfo) {
+			printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex);
+			return(1);
+		} else {
+			busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid;
+		}
+
+		/*
+		 * Pre assign DMA maps needed for 32 Bits Page Map DMA.
+		 */
+		busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc(
+			sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL);
+		if (!busnum_to_atedmamaps[num_bridges - 1])
+			printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget);
+
+		memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, 
+			sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS);
+
+	}
+
+	/*
+	 * PCIX devices
+	 * We number busses differently for PCI-X devices.
+	 * We start from Lowest Widget on up ..
+	 */
+
+        (void) ioconfig_get_busnum((char *)io_moduleid, &basebus_num);
+
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+
+		/* Do both buses */
+		for ( bus = 0; bus < 2; bus++ ) {
+			sprintf(pathname, "%d", widgetnum);
+			xwidget = NULL;
+			
+			/*
+			 * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget
+			 *	     /hw/module/001c16/Pbrick/xtalk/8/pci-x/0 is the bus
+			 *	     /hw/module/001c16/Pbrick/xtalk/8/pci-x/0/1 is device
+			 */
+			rv = hwgraph_traverse(xtalk, pathname, &xwidget);
+			if ( (rv != GRAPH_SUCCESS) ) {
+				if (!xwidget) {
+					continue;
+				}
+			}
+	
+			if ( bus == 0 )
+				sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum);
+			else
+				sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum);
+			pci_bus = NULL;
+			if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS)
+				if (!pci_bus) {
+					continue;
+				}
+	
+			/*
+			 * Assign the correct bus number and also the nasid of this 
+			 * pci Xwidget.
+			 * 
+			 * Should not be any race here ...
+			 */
+			bus_number = basebus_num + bus + io_brick_map_widget(MODULE_PXBRICK, widgetnum);
+#ifdef DEBUG
+			printk("bus_number %d basebus_num %d bus %d io %d\n", 
+				bus_number, basebus_num, bus, 
+				io_brick_map_widget(MODULE_PXBRICK, widgetnum));
+#endif
+			busnum_to_pcibr_vhdl[bus_number] = pci_bus;
+	
+			/*
+			 * Pre assign DMA maps needed for 32 Bits Page Map DMA.
+			 */
+			busnum_to_atedmamaps[bus_number] = (void *) kmalloc(
+				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL);
+			if (!busnum_to_atedmamaps[bus_number])
+				printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget);
+	
+			memset(busnum_to_atedmamaps[bus_number], 0x0, 
+				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS);
+		}
+	}
+
+        return(0);
+}
+
+/*
+ * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure   
+ *      initialization has completed to set up the mappings between Xbridge
+ *      and logical pci bus numbers.  We also set up the NASID for each of these
+ *      xbridges.
+ *
+ *      Must be called before pci_init() is invoked.
+ */
+int
+pci_bus_to_hcl_cvlink(void) 
+{
+
+	devfs_handle_t devfs_hdl = NULL;
+	devfs_handle_t xtalk = NULL;
+	int rv = 0;
+	char name[256];
+	char tmp_name[256];
+	int i, ii;
+
+	/*
+	 * Figure out which IO Brick is connected to the Compute Bricks.
+	 */
+	for (i = 0; i < nummodules; i++) {
+		extern int iomoduleid_get(nasid_t);
+		moduleid_t iobrick_id;
+		nasid_t nasid = -1;
+		int nodecnt;
+		int n = 0;
+
+		nodecnt = modules[i]->nodecnt;
+		for ( n = 0; n < nodecnt; n++ ) {
+			nasid = cnodeid_to_nasid(modules[i]->nodes[n]);
+			iobrick_id = iomoduleid_get(nasid);
+			if ((int)iobrick_id > 0) { /* Valid module id */
+				char name[12];
+				memset(name, 0, 12);
+				format_module_id((char *)&(modules[i]->io[n].moduleid), iobrick_id, MODULE_FORMAT_BRIEF);
+			}
+		}
+	}
+				
+	devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module");
+	for (i = 0; i < nummodules ; i++) {
+		for ( ii = 0; ii < 2 ; ii++ ) {
+			memset(name, 0, 256);
+			memset(tmp_name, 0, 256);
+			format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF);
+			sprintf(tmp_name, "/slab/%d/Pbrick/xtalk", geo_slab(modules[i]->geoid[ii]));
+			strcat(name, tmp_name);
+			xtalk = NULL;
+			rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
+			pci_bus_map_create(xtalk, (char *)&(modules[i]->io[ii].moduleid));
+		}
+	}
+
+	/*
+	 * Create the Linux PCI bus number vertex link.
+	 */
+	(void)linux_bus_cvlink();
+	(void)ioconfig_bus_new_entries();
+
+	return(0);
+}
diff -Nru a/arch/ia64/sn/io/sn2/pcibr/Makefile b/arch/ia64/sn/io/sn2/pcibr/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pcibr/Makefile	Mon Feb 24 05:40:54 2003
@@ -0,0 +1,19 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# Makefile for the sn2 specific pci bridge routines.
+
+EXTRA_CFLAGS    := -DLITTLE_ENDIAN
+
+ifdef CONFIG_IA64_SGI_SN2
+EXTRA_CFLAGS    += -DSHUB_SWAP_WAR
+endif
+
+obj-$(CONFIG_IA64_SGI_SN2)	+= pcibr_dvr.o pcibr_ate.o pcibr_config.o \
+                                   pcibr_dvr.o pcibr_hints.o \
+				   pcibr_intr.o pcibr_rrb.o pcibr_slot.o \
+				   pcibr_error.o
diff -Nru a/arch/ia64/sn/io/sn2/pciio.c b/arch/ia64/sn/io/sn2/pciio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pciio.c	Mon Feb 24 05:30:35 2003
@@ -0,0 +1,1877 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#define	USRPCI	0
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/xtalk/xbow.h>	/* Must be before iograph.h to get MAX_PORT_NUM */
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/ioerror_handling.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pciio_private.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
+#include <asm/sn/ate_utils.h>
+#include <asm/sn/simulator.h>
+
+#ifdef __ia64
+#define rmallocmap atemapalloc
+#define rmfreemap atemapfree
+#define rmfree atefree
+#define rmalloc atealloc
+#endif
+
+#define DEBUG_PCIIO
+#undef DEBUG_PCIIO	/* turn this on for yet more console output */
+
+
+#define GET_NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
+#define DO_DEL(ptr)	(kfree(ptr))
+
+char                    pciio_info_fingerprint[] = "pciio_info";
+
+cdl_p                   pciio_registry = NULL;
+
+int
+badaddr_val(volatile void *addr, int len, volatile void *ptr)
+{
+	int ret = 0;
+	volatile void *new_addr;
+
+	switch (len) {
+		case 4:
+			new_addr = (void *) addr;
+			ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr);
+			break;
+		default:
+			printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len);
+	}
+
+	if (ret < 0)
+		panic("badaddr_val: unexpected status (%d) in probing", ret);
+	return(ret);
+
+}
+
+
+nasid_t
+get_console_nasid(void)
+{
+	extern nasid_t console_nasid;
+	extern nasid_t master_baseio_nasid;
+
+	if (console_nasid < 0) {
+		console_nasid = ia64_sn_get_console_nasid();
+		if (console_nasid < 0) {
+// ZZZ What do we do if we don't get a console nasid on the hardware????
+			if (IS_RUNNING_ON_SIMULATOR() )
+				console_nasid = master_baseio_nasid;
+		}
+	} 
+	return console_nasid;
+}
+
+nasid_t
+get_master_baseio_nasid(void)
+{
+	extern nasid_t master_baseio_nasid;
+	extern char master_baseio_wid;
+
+	if (master_baseio_nasid < 0) {
+		nasid_t tmp;
+
+		master_baseio_nasid = ia64_sn_get_master_baseio_nasid();
+
+		if ( master_baseio_nasid >= 0 ) {
+        		master_baseio_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_baseio_nasid)->memory_base);
+		}
+	} 
+	return master_baseio_nasid;
+}
+
+int
+hub_dma_enabled(devfs_handle_t xconn_vhdl)
+{
+	return(0);
+}
+
+int
+hub_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code)
+{
+	return(0);
+}
+
+void
+ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror)
+{
+}
+
+/******
+ ****** end hack defines ......
+ ******/
+
+
+
+
+/* =====================================================================
+ *    PCI Generic Bus Provider
+ * Implement PCI provider operations.  The pciio* layer provides a
+ * platform-independent interface for PCI devices.  This layer
+ * switches among the possible implementations of a PCI adapter.
+ */
+
+/* =====================================================================
+ *    Provider Function Location SHORTCUT
+ *
+ * On platforms with only one possible PCI provider, macros can be
+ * set up at the top that cause the table lookups and indirections to
+ * completely disappear.
+ */
+
+
+/* =====================================================================
+ *    Function Table of Contents
+ */
+
+#if !defined(DEV_FUNC)
+static pciio_provider_t *pciio_to_provider_fns(devfs_handle_t dev);
+#endif
+
+pciio_piomap_t          pciio_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned);
+void                    pciio_piomap_free(pciio_piomap_t);
+caddr_t                 pciio_piomap_addr(pciio_piomap_t, iopaddr_t, size_t);
+
+void                    pciio_piomap_done(pciio_piomap_t);
+caddr_t                 pciio_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned);
+caddr_t			pciio_pio_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned);
+
+iopaddr_t               pciio_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t);
+void                    pciio_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t);
+
+pciio_dmamap_t          pciio_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);
+void                    pciio_dmamap_free(pciio_dmamap_t);
+iopaddr_t               pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t);
+alenlist_t              pciio_dmamap_list(pciio_dmamap_t, alenlist_t, unsigned);
+void                    pciio_dmamap_done(pciio_dmamap_t);
+iopaddr_t               pciio_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);
+alenlist_t              pciio_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);
+void			pciio_dmamap_drain(pciio_dmamap_t);
+void			pciio_dmaaddr_drain(devfs_handle_t, paddr_t, size_t);
+void			pciio_dmalist_drain(devfs_handle_t, alenlist_t);
+iopaddr_t               pciio_dma_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned);
+
+pciio_intr_t            pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t);
+void                    pciio_intr_free(pciio_intr_t);
+int                     pciio_intr_connect(pciio_intr_t, intr_func_t, intr_arg_t);
+void                    pciio_intr_disconnect(pciio_intr_t);
+devfs_handle_t            pciio_intr_cpu_get(pciio_intr_t);
+
+void			pciio_slot_func_to_name(char *, pciio_slot_t, pciio_function_t);
+
+void                    pciio_provider_startup(devfs_handle_t);
+void                    pciio_provider_shutdown(devfs_handle_t);
+
+pciio_endian_t          pciio_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t);
+pciio_priority_t        pciio_priority_set(devfs_handle_t, pciio_priority_t);
+devfs_handle_t            pciio_intr_dev_get(pciio_intr_t);
+
+devfs_handle_t            pciio_pio_dev_get(pciio_piomap_t);
+pciio_slot_t            pciio_pio_slot_get(pciio_piomap_t);
+pciio_space_t           pciio_pio_space_get(pciio_piomap_t);
+iopaddr_t               pciio_pio_pciaddr_get(pciio_piomap_t);
+ulong                   pciio_pio_mapsz_get(pciio_piomap_t);
+caddr_t                 pciio_pio_kvaddr_get(pciio_piomap_t);
+
+devfs_handle_t            pciio_dma_dev_get(pciio_dmamap_t);
+pciio_slot_t            pciio_dma_slot_get(pciio_dmamap_t);
+
+pciio_info_t            pciio_info_chk(devfs_handle_t);
+pciio_info_t            pciio_info_get(devfs_handle_t);
+void                    pciio_info_set(devfs_handle_t, pciio_info_t);
+devfs_handle_t            pciio_info_dev_get(pciio_info_t);
+pciio_slot_t            pciio_info_slot_get(pciio_info_t);
+pciio_function_t        pciio_info_function_get(pciio_info_t);
+pciio_vendor_id_t       pciio_info_vendor_id_get(pciio_info_t);
+pciio_device_id_t       pciio_info_device_id_get(pciio_info_t);
+devfs_handle_t            pciio_info_master_get(pciio_info_t);
+arbitrary_info_t        pciio_info_mfast_get(pciio_info_t);
+pciio_provider_t       *pciio_info_pops_get(pciio_info_t);
+error_handler_f	       *pciio_info_efunc_get(pciio_info_t);
+error_handler_arg_t    *pciio_info_einfo_get(pciio_info_t);
+pciio_space_t		pciio_info_bar_space_get(pciio_info_t, int);
+iopaddr_t		pciio_info_bar_base_get(pciio_info_t, int);
+size_t			pciio_info_bar_size_get(pciio_info_t, int);
+iopaddr_t		pciio_info_rom_base_get(pciio_info_t);
+size_t			pciio_info_rom_size_get(pciio_info_t);
+
+void                    pciio_init(void);
+int                     pciio_attach(devfs_handle_t);
+
+void                    pciio_provider_register(devfs_handle_t, pciio_provider_t *pciio_fns);
+void                    pciio_provider_unregister(devfs_handle_t);
+pciio_provider_t       *pciio_provider_fns_get(devfs_handle_t);
+
+int                     pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned);
+void                    pciio_driver_unregister(char *driver_prefix);
+
+devfs_handle_t            pciio_device_register(devfs_handle_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
+
+void			pciio_device_unregister(devfs_handle_t);
+pciio_info_t		pciio_device_info_new(pciio_info_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
+void			pciio_device_info_free(pciio_info_t);
+devfs_handle_t		pciio_device_info_register(devfs_handle_t, pciio_info_t);
+void			pciio_device_info_unregister(devfs_handle_t, pciio_info_t);
+int                     pciio_device_attach(devfs_handle_t, int);
+int			pciio_device_detach(devfs_handle_t, int);
+void                    pciio_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t);
+
+int                     pciio_reset(devfs_handle_t);
+int                     pciio_write_gather_flush(devfs_handle_t);
+int                     pciio_slot_inuse(devfs_handle_t);
+
+/* =====================================================================
+ *    Provider Function Location
+ *
+ *      If there is more than one possible provider for
+ *      this platform, we need to examine the master
+ *      vertex of the current vertex for a provider
+ *      function structure, and indirect through the
+ *      appropriately named member.
+ */
+
+#if !defined(DEV_FUNC)
+
+static pciio_provider_t *
+pciio_to_provider_fns(devfs_handle_t dev)
+{
+    pciio_info_t            card_info;
+    pciio_provider_t       *provider_fns;
+
+    /*
+     * We're called with two types of vertices, one is
+     * the bridge vertex (ends with "pci") and the other is the
+     * pci slot vertex (ends with "pci/[0-8]").  For the first type
+     * we need to get the provider from the PFUNCS label.  For
+     * the second we get it from fastinfo/c_pops.
+     */
+    provider_fns = pciio_provider_fns_get(dev);
+    if (provider_fns == NULL) {
+	card_info = pciio_info_get(dev);
+	if (card_info != NULL) {
+		provider_fns = pciio_info_pops_get(card_info);
+	}
+    }
+
+    if (provider_fns == NULL)
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	PRINT_PANIC("%v: provider_fns == NULL", dev);
+#else
+	PRINT_PANIC("0x%p: provider_fns == NULL", (void *)dev);
+#endif
+
+    return provider_fns;
+
+}
+
+#define DEV_FUNC(dev,func)	pciio_to_provider_fns(dev)->func
+#define CAST_PIOMAP(x)		((pciio_piomap_t)(x))
+#define CAST_DMAMAP(x)		((pciio_dmamap_t)(x))
+#define CAST_INTR(x)		((pciio_intr_t)(x))
+#endif
+
+/*
+ * Many functions are not passed their vertex
+ * information directly; rather, they must
+ * dive through a resource map. These macros
+ * are available to coordinate this detail.
+ */
+#define PIOMAP_FUNC(map,func)		DEV_FUNC((map)->pp_dev,func)
+#define DMAMAP_FUNC(map,func)		DEV_FUNC((map)->pd_dev,func)
+#define INTR_FUNC(intr_hdl,func)	DEV_FUNC((intr_hdl)->pi_dev,func)
+
+/* =====================================================================
+ *          PIO MANAGEMENT
+ *
+ *      For mapping system virtual address space to
+ *      pciio space on a specified card
+ */
+
+pciio_piomap_t
+pciio_piomap_alloc(devfs_handle_t dev,	/* set up mapping for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   pciio_space_t space,	/* CFG, MEM, IO, or a device-decoded window */
+		   iopaddr_t addr,	/* lowest address (or offset in window) */
+		   size_t byte_count,	/* size of region containing our mappings */
+		   size_t byte_count_max,	/* maximum size of a mapping */
+		   unsigned flags)
+{					/* defined in sys/pio.h */
+    return (pciio_piomap_t) DEV_FUNC(dev, piomap_alloc)
+	(dev, dev_desc, space, addr, byte_count, byte_count_max, flags);
+}
+
+void
+pciio_piomap_free(pciio_piomap_t pciio_piomap)
+{
+    PIOMAP_FUNC(pciio_piomap, piomap_free)
+	(CAST_PIOMAP(pciio_piomap));
+}
+
+caddr_t
+pciio_piomap_addr(pciio_piomap_t pciio_piomap,	/* mapping resources */
+		  iopaddr_t pciio_addr,	/* map for this pciio address */
+		  size_t byte_count)
+{					/* map this many bytes */
+    pciio_piomap->pp_kvaddr = PIOMAP_FUNC(pciio_piomap, piomap_addr)
+	(CAST_PIOMAP(pciio_piomap), pciio_addr, byte_count);
+
+    return pciio_piomap->pp_kvaddr;
+}
+
+void
+pciio_piomap_done(pciio_piomap_t pciio_piomap)
+{
+    PIOMAP_FUNC(pciio_piomap, piomap_done)
+	(CAST_PIOMAP(pciio_piomap));
+}
+
+caddr_t
+pciio_piotrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    pciio_space_t space,	/* CFG, MEM, IO, or a device-decoded window */
+		    iopaddr_t addr,	/* starting address (or offset in window) */
+		    size_t byte_count,	/* map this many bytes */
+		    unsigned flags)
+{					/* (currently unused) */
+    return DEV_FUNC(dev, piotrans_addr)
+	(dev, dev_desc, space, addr, byte_count, flags);
+}
+
+caddr_t
+pciio_pio_addr(devfs_handle_t dev,	/* translate for this device */
+	       device_desc_t dev_desc,	/* device descriptor */
+	       pciio_space_t space,	/* CFG, MEM, IO, or a device-decoded window */
+	       iopaddr_t addr,		/* starting address (or offset in window) */
+	       size_t byte_count,	/* map this many bytes */
+	       pciio_piomap_t *mapp,	/* where to return the map pointer */
+	       unsigned flags)
+{					/* PIO flags */
+    pciio_piomap_t          map = 0;
+    int			    errfree = 0;
+    caddr_t                 res;
+
+    if (mapp) {
+	map = *mapp;			/* possible pre-allocated map */
+	*mapp = 0;			/* record "no map used" */
+    }
+
+    res = pciio_piotrans_addr
+	(dev, dev_desc, space, addr, byte_count, flags);
+    if (res)
+	return res;			/* pciio_piotrans worked */
+
+    if (!map) {
+	map = pciio_piomap_alloc
+	    (dev, dev_desc, space, addr, byte_count, byte_count, flags);
+	if (!map)
+	    return res;			/* pciio_piomap_alloc failed */
+	errfree = 1;
+    }
+
+    res = pciio_piomap_addr
+	(map, addr, byte_count);
+    if (!res) {
+	if (errfree)
+	    pciio_piomap_free(map);
+	return res;			/* pciio_piomap_addr failed */
+    }
+    if (mapp)
+	*mapp = map;			/* pass back map used */
+
+    return res;				/* pciio_piomap_addr succeeded */
+}
+
+iopaddr_t
+pciio_piospace_alloc(devfs_handle_t dev,	/* Device requiring space */
+		     device_desc_t dev_desc,	/* Device descriptor */
+		     pciio_space_t space,	/* MEM32/MEM64/IO */
+		     size_t byte_count,	/* Size of mapping */
+		     size_t align)
+{					/* Alignment needed */
+    if (align < NBPP)
+	align = NBPP;
+    return DEV_FUNC(dev, piospace_alloc)
+	(dev, dev_desc, space, byte_count, align);
+}
+
+void
+pciio_piospace_free(devfs_handle_t dev,	/* Device freeing space */
+		    pciio_space_t space,	/* Type of space        */
+		    iopaddr_t pciaddr,	/* starting address */
+		    size_t byte_count)
+{					/* Range of address   */
+    DEV_FUNC(dev, piospace_free)
+	(dev, space, pciaddr, byte_count);
+}
+
+/* =====================================================================
+ *          DMA MANAGEMENT
+ *
+ *      For mapping from pci space to system
+ *      physical space.
+ */
+
+pciio_dmamap_t
+pciio_dmamap_alloc(devfs_handle_t dev,	/* set up mappings for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   size_t byte_count_max,	/* max size of a mapping */
+		   unsigned flags)
+{					/* defined in dma.h */
+    return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
+	(dev, dev_desc, byte_count_max, flags);
+}
+
+void
+pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_free)
+	(CAST_DMAMAP(pciio_dmamap));
+}
+
+iopaddr_t
+pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,	/* use these mapping resources */
+		  paddr_t paddr,	/* map for this address */
+		  size_t byte_count)
+{					/* map this many bytes */
+    return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
+	(CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
+}
+
+alenlist_t
+pciio_dmamap_list(pciio_dmamap_t pciio_dmamap,	/* use these mapping resources */
+		  alenlist_t alenlist,	/* map this Address/Length List */
+		  unsigned flags)
+{
+    return DMAMAP_FUNC(pciio_dmamap, dmamap_list)
+	(CAST_DMAMAP(pciio_dmamap), alenlist, flags);
+}
+
+void
+pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_done)
+	(CAST_DMAMAP(pciio_dmamap));
+}
+
+iopaddr_t
+pciio_dmatrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    paddr_t paddr,	/* system physical address */
+		    size_t byte_count,	/* length */
+		    unsigned flags)
+{					/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_addr)
+	(dev, dev_desc, paddr, byte_count, flags);
+}
+
+alenlist_t
+pciio_dmatrans_list(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    alenlist_t palenlist,	/* system address/length list */
+		    unsigned flags)
+{					/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_list)
+	(dev, dev_desc, palenlist, flags);
+}
+
+iopaddr_t
+pciio_dma_addr(devfs_handle_t dev,	/* translate for this device */
+	       device_desc_t dev_desc,	/* device descriptor */
+	       paddr_t paddr,		/* system physical address */
+	       size_t byte_count,	/* length */
+	       pciio_dmamap_t *mapp,	/* map to use, then map we used */
+	       unsigned flags)
+{					/* PIO flags */
+    pciio_dmamap_t          map = 0;
+    int			    errfree = 0;
+    iopaddr_t               res;
+
+    if (mapp) {
+	map = *mapp;			/* possible pre-allocated map */
+	*mapp = 0;			/* record "no map used" */
+    }
+
+    res = pciio_dmatrans_addr
+	(dev, dev_desc, paddr, byte_count, flags);
+    if (res)
+	return res;			/* pciio_dmatrans worked */
+
+    if (!map) {
+	map = pciio_dmamap_alloc
+	    (dev, dev_desc, byte_count, flags);
+	if (!map)
+	    return res;			/* pciio_dmamap_alloc failed */
+	errfree = 1;
+    }
+
+    res = pciio_dmamap_addr
+	(map, paddr, byte_count);
+    if (!res) {
+	if (errfree)
+	    pciio_dmamap_free(map);
+	return res;			/* pciio_dmamap_addr failed */
+    }
+    if (mapp)
+	*mapp = map;			/* pass back map used */
+
+    return res;				/* pciio_dmamap_addr succeeded */
+}
+
+void
+pciio_dmamap_drain(pciio_dmamap_t map)
+{
+    DMAMAP_FUNC(map, dmamap_drain)
+	(CAST_DMAMAP(map));
+}
+
+void
+pciio_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size)
+{
+    DEV_FUNC(dev, dmaaddr_drain)
+	(dev, addr, size);
+}
+
+void
+pciio_dmalist_drain(devfs_handle_t dev, alenlist_t list)
+{
+    DEV_FUNC(dev, dmalist_drain)
+	(dev, list);
+}
+
+/* =====================================================================
+ *          INTERRUPT MANAGEMENT
+ *
+ *      Allow crosstalk devices to establish interrupts
+ */
+
+/*
+ * Allocate resources required for an interrupt as specified in intr_desc.
+ * Return resource handle in intr_hdl.
+ */
+pciio_intr_t
+pciio_intr_alloc(devfs_handle_t dev,	/* which Crosstalk device */
+		 device_desc_t dev_desc,	/* device descriptor */
+		 pciio_intr_line_t lines,	/* INTR line(s) to attach */
+		 devfs_handle_t owner_dev)
+{					/* owner of this interrupt */
+    return (pciio_intr_t) DEV_FUNC(dev, intr_alloc)
+	(dev, dev_desc, lines, owner_dev);
+}
+
+/*
+ * Free resources consumed by intr_alloc.
+ */
+void
+pciio_intr_free(pciio_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_free)
+	(CAST_INTR(intr_hdl));
+}
+
+/*
+ * Associate resources allocated with a previous pciio_intr_alloc call with the
+ * described handler, arg, name, etc.
+ *
+ * Returns 0 on success, returns <0 on failure.
+ */
+int
+pciio_intr_connect(pciio_intr_t intr_hdl,
+		intr_func_t intr_func, intr_arg_t intr_arg)	/* pciio intr resource handle */
+{
+    return INTR_FUNC(intr_hdl, intr_connect)
+	(CAST_INTR(intr_hdl), intr_func, intr_arg);
+}
+
+/*
+ * Disassociate handler with the specified interrupt.
+ */
+void
+pciio_intr_disconnect(pciio_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_disconnect)
+	(CAST_INTR(intr_hdl));
+}
+
+/*
+ * Return a hwgraph vertex that represents the CPU currently
+ * targeted by an interrupt.
+ */
+devfs_handle_t
+pciio_intr_cpu_get(pciio_intr_t intr_hdl)
+{
+    return INTR_FUNC(intr_hdl, intr_cpu_get)
+	(CAST_INTR(intr_hdl));
+}
+
+void
+pciio_slot_func_to_name(char		       *name,
+			pciio_slot_t		slot,
+			pciio_function_t	func)
+{
+    /*
+     * standard connection points:
+     *
+     * PCIIO_SLOT_NONE:	.../pci/direct
+     * PCIIO_FUNC_NONE: .../pci/<SLOT>			ie. .../pci/3
+     * multifunction:   .../pci/<SLOT><FUNC>		ie. .../pci/3c
+     */
+
+    if (slot == PCIIO_SLOT_NONE)
+	sprintf(name, EDGE_LBL_DIRECT);
+    else if (func == PCIIO_FUNC_NONE)
+	sprintf(name, "%d", slot);
+    else
+	sprintf(name, "%d%c", slot, 'a'+func);
+}
+
+/*
+ * pciio_cardinfo_get
+ *
+ * Get the pciio info structure corresponding to the
+ * specified PCI "slot" (we like it when the same index
+ * number is used for the PCI IDSEL, the REQ/GNT pair,
+ * and the interrupt line being used for INTA. We like
+ * it so much we call it the slot number).
+ */
+static pciio_info_t
+pciio_cardinfo_get(
+		      devfs_handle_t pciio_vhdl,
+		      pciio_slot_t pci_slot)
+{
+    char                    namebuf[16];
+    pciio_info_t	    info = 0;
+    devfs_handle_t	    conn;
+
+    pciio_slot_func_to_name(namebuf, pci_slot, PCIIO_FUNC_NONE);
+    if (GRAPH_SUCCESS ==
+	hwgraph_traverse(pciio_vhdl, namebuf, &conn)) {
+	info = pciio_info_chk(conn);
+	hwgraph_vertex_unref(conn);
+    }
+
+    return info;
+}
+
+
+/*
+ * pciio_error_handler:
+ * dispatch an error to the appropriate
+ * pciio connection point, or process
+ * it as a generic pci error.
+ * Yes, the first parameter is the
+ * provider vertex at the middle of
+ * the bus; we get to the pciio connect
+ * point using the ioerror widgetdev field.
+ *
+ * This function is called by the
+ * specific PCI provider, after it has figured
+ * out where on the PCI bus (including which slot,
+ * if it can tell) the error came from.
+ */
+/*ARGSUSED */
+int
+pciio_error_handler(
+		       devfs_handle_t pciio_vhdl,
+		       int error_code,
+		       ioerror_mode_t mode,
+		       ioerror_t *ioerror)
+{
+    pciio_info_t            pciio_info;
+    devfs_handle_t            pconn_vhdl;
+#if USRPCI
+    devfs_handle_t            usrpci_v;
+#endif
+    pciio_slot_t            slot;
+
+    int                     retval;
+#ifdef EHE_ENABLE
+    error_state_t	    e_state;
+#endif /* EHE_ENABLE */
+
+#if DEBUG && ERROR_DEBUG
+    printk("%v: pciio_error_handler\n", pciio_vhdl);
+#endif
+
+    IOERR_PRINTF(printk(KERN_NOTICE "%v: PCI Bus Error: Error code: %d Error mode: %d\n",
+			 pciio_vhdl, error_code, mode));
+
+    /* If there is an error handler sitting on
+     * the "no-slot" connection point, give it
+     * first crack at the error. NOTE: it is
+     * quite possible that this function may
+     * do further refining of the ioerror.
+     */
+    pciio_info = pciio_cardinfo_get(pciio_vhdl, PCIIO_SLOT_NONE);
+    if (pciio_info && pciio_info->c_efunc) {
+	pconn_vhdl = pciio_info_dev_get(pciio_info);
+
+#ifdef EHE_ENABLE
+	e_state = error_state_get(pciio_vhdl);
+
+	if (e_state == ERROR_STATE_ACTION)
+	    (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE);
+
+	if (error_state_set(pconn_vhdl,e_state) == ERROR_RETURN_CODE_CANNOT_SET_STATE)
+	    return(IOERROR_UNHANDLED);
+#endif 
+
+	retval = pciio_info->c_efunc
+	    (pciio_info->c_einfo, error_code, mode, ioerror);
+	if (retval != IOERROR_UNHANDLED)
+	    return retval;
+    }
+
+    /* Is the error associated with a particular slot?
+     */
+    if (IOERROR_FIELDVALID(ioerror, widgetdev)) {
+	short widgetdev;
+	/*
+	 * NOTE : 
+	 * widgetdev is a 4byte value encoded as slot in the higher order
+	 * 2 bytes and function in the lower order 2 bytes.
+	 */
+	IOERROR_GETVALUE(widgetdev, ioerror, widgetdev);
+	slot = pciio_widgetdev_slot_get(widgetdev);
+
+	/* If this slot has an error handler,
+	 * deliver the error to it.
+	 */
+	pciio_info = pciio_cardinfo_get(pciio_vhdl, slot);
+	if (pciio_info != NULL) {
+	    if (pciio_info->c_efunc != NULL) {
+
+		pconn_vhdl = pciio_info_dev_get(pciio_info);
+
+#ifdef EHE_ENABLE
+		e_state = error_state_get(pciio_vhdl);
+
+		if (e_state == ERROR_STATE_ACTION)
+		    (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE);
+
+		if (error_state_set(pconn_vhdl,e_state) ==
+		    ERROR_RETURN_CODE_CANNOT_SET_STATE)
+		    return(IOERROR_UNHANDLED);
+#endif /* EHE_ENABLE */
+
+		retval = pciio_info->c_efunc
+		    (pciio_info->c_einfo, error_code, mode, ioerror);
+		if (retval != IOERROR_UNHANDLED)
+		    return retval;
+	    }
+
+#if USRPCI
+	    /* If the USRPCI driver is available and
+	     * knows about this connection point,
+	     * deliver the error to it.
+	     *
+	     * OK to use pconn_vhdl here, even though we
+	     * have already UNREF'd it, since we know that
+	     * it is not going away.
+	     */
+	    pconn_vhdl = pciio_info_dev_get(pciio_info);
+	    if (GRAPH_SUCCESS == hwgraph_traverse(pconn_vhdl, EDGE_LBL_USRPCI, &usrpci_v)) {
+		iopaddr_t busaddr;
+		IOERROR_GETVALUE(busaddr, ioerror, busaddr);
+		retval = usrpci_error_handler (usrpci_v, error_code, busaddr);
+		hwgraph_vertex_unref(usrpci_v);
+		if (retval != IOERROR_UNHANDLED) {
+		    /*
+		     * This unref is not needed.  If this code is called often enough,
+		     * the system will crash, due to vertex reference count reaching 0,
+		     * causing vertex to be unallocated.  -jeremy
+		     * hwgraph_vertex_unref(pconn_vhdl);
+		     */
+		    return retval;
+		}
+	    }
+#endif
+	}
+    }
+
+    return (mode == MODE_DEVPROBE)
+	? IOERROR_HANDLED	/* probes are OK */
+	: IOERROR_UNHANDLED;	/* otherwise, foo! */
+}
+
+/* =====================================================================
+ *          CONFIGURATION MANAGEMENT
+ */
+
+/*
+ * Startup a crosstalk provider
+ */
+void
+pciio_provider_startup(devfs_handle_t pciio_provider)
+{
+    DEV_FUNC(pciio_provider, provider_startup)
+	(pciio_provider);
+}
+
+/*
+ * Shutdown a crosstalk provider
+ */
+void
+pciio_provider_shutdown(devfs_handle_t pciio_provider)
+{
+    DEV_FUNC(pciio_provider, provider_shutdown)
+	(pciio_provider);
+}
+
+/*
+ * Specify endianness constraints.  The driver tells us what the device
+ * does and how it would like to see things in memory.  We reply with
+ * how things will actually appear in memory.
+ */
+pciio_endian_t
+pciio_endian_set(devfs_handle_t dev,
+		 pciio_endian_t device_end,
+		 pciio_endian_t desired_end)
+{
+    ASSERT((device_end == PCIDMA_ENDIAN_BIG) || (device_end == PCIDMA_ENDIAN_LITTLE));
+    ASSERT((desired_end == PCIDMA_ENDIAN_BIG) || (desired_end == PCIDMA_ENDIAN_LITTLE));
+
+#if DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk(KERN_ALERT  "%v: pciio_endian_set is going away.\n"
+	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
+	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
+	    dev);
+#else
+    printk(KERN_ALERT  "0x%x: pciio_endian_set is going away.\n"
+	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
+	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
+	    dev);
+#endif
+#endif
+
+    return DEV_FUNC(dev, endian_set)
+	(dev, device_end, desired_end);
+}
+
+/*
+ * Specify PCI arbitration priority.
+ */
+pciio_priority_t
+pciio_priority_set(devfs_handle_t dev,
+		   pciio_priority_t device_prio)
+{
+    ASSERT((device_prio == PCI_PRIO_HIGH) || (device_prio == PCI_PRIO_LOW));
+
+    return DEV_FUNC(dev, priority_set)
+	(dev, device_prio);
+}
+
+/*
+ * Read value of configuration register
+ */
+uint64_t
+pciio_config_get(devfs_handle_t	dev,
+		 unsigned	reg,
+		 unsigned	size)
+{
+    uint64_t	value = 0;
+    unsigned	shift = 0;
+
+    /* handle accesses that cross words here,
+     * since that's common code between all
+     * possible providers.
+     */
+    while (size > 0) {
+	unsigned	biw = 4 - (reg&3);
+	if (biw > size)
+	    biw = size;
+
+	value |= DEV_FUNC(dev, config_get)
+	    (dev, reg, biw) << shift;
+
+	shift += 8*biw;
+	reg += biw;
+	size -= biw;
+    }
+    return value;
+}
+
+/*
+ * Change value of configuration register
+ */
+void
+pciio_config_set(devfs_handle_t	dev,
+		 unsigned	reg,
+		 unsigned	size,
+		 uint64_t	value)
+{
+    /* handle accesses that cross words here,
+     * since that's common code between all
+     * possible providers.
+     */
+    while (size > 0) {
+	unsigned	biw = 4 - (reg&3);
+	if (biw > size)
+	    biw = size;
+	    
+	DEV_FUNC(dev, config_set)
+	    (dev, reg, biw, value);
+	reg += biw;
+	size -= biw;
+	value >>= biw * 8;
+    }
+}
+
+/* =====================================================================
+ *          GENERIC PCI SUPPORT FUNCTIONS
+ */
+
+/*
+ * Issue a hardware reset to a card.
+ */
+int
+pciio_reset(devfs_handle_t dev)
+{
+    return DEV_FUNC(dev, reset) (dev);
+}
+
+/*
+ * flush write gather buffers
+ */
+int
+pciio_write_gather_flush(devfs_handle_t dev)
+{
+    return DEV_FUNC(dev, write_gather_flush) (dev);
+}
+
+devfs_handle_t
+pciio_intr_dev_get(pciio_intr_t pciio_intr)
+{
+    return (pciio_intr->pi_dev);
+}
+
+/****** Generic crosstalk pio interfaces ******/
+devfs_handle_t
+pciio_pio_dev_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_dev);
+}
+
+pciio_slot_t
+pciio_pio_slot_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_slot);
+}
+
+pciio_space_t
+pciio_pio_space_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_space);
+}
+
+iopaddr_t
+pciio_pio_pciaddr_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_pciaddr);
+}
+
+ulong
+pciio_pio_mapsz_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_mapsz);
+}
+
+caddr_t
+pciio_pio_kvaddr_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_kvaddr);
+}
+
+/****** Generic crosstalk dma interfaces ******/
+devfs_handle_t
+pciio_dma_dev_get(pciio_dmamap_t pciio_dmamap)
+{
+    return (pciio_dmamap->pd_dev);
+}
+
+pciio_slot_t
+pciio_dma_slot_get(pciio_dmamap_t pciio_dmamap)
+{
+    return (pciio_dmamap->pd_slot);
+}
+
+/****** Generic pci slot information interfaces ******/
+
+pciio_info_t
+pciio_info_chk(devfs_handle_t pciio)
+{
+    arbitrary_info_t        ainfo = 0;
+
+    hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo);
+    return (pciio_info_t) ainfo;
+}
+
+pciio_info_t
+pciio_info_get(devfs_handle_t pciio)
+{
+    pciio_info_t            pciio_info;
+
+    pciio_info = (pciio_info_t) hwgraph_fastinfo_get(pciio);
+
+#ifdef DEBUG_PCIIO
+    {
+	int pos;
+	char dname[256];
+	pos = devfs_generate_path(pciio, dname, 256);
+	printk("%s : path= %s\n", __FUNCTION__, &dname[pos]);
+    }
+#endif /* DEBUG_PCIIO */
+
+    if ((pciio_info != NULL) &&
+	(pciio_info->c_fingerprint != pciio_info_fingerprint)
+	&& (pciio_info->c_fingerprint != NULL)) {
+
+	return((pciio_info_t)-1); /* Should panic .. */
+    }
+	
+
+    return pciio_info;
+}
+
+void
+pciio_info_set(devfs_handle_t pciio, pciio_info_t pciio_info)
+{
+    if (pciio_info != NULL)
+	pciio_info->c_fingerprint = pciio_info_fingerprint;
+    hwgraph_fastinfo_set(pciio, (arbitrary_info_t) pciio_info);
+
+    /* Also, mark this vertex as a PCI slot
+     * and use the pciio_info, so pciio_info_chk
+     * can work (and be fairly efficient).
+     */
+    hwgraph_info_add_LBL(pciio, INFO_LBL_PCIIO,
+			 (arbitrary_info_t) pciio_info);
+}
+
+devfs_handle_t
+pciio_info_dev_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_vertex);
+}
+
+pciio_slot_t
+pciio_info_slot_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_slot);
+}
+
+pciio_function_t
+pciio_info_function_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_func);
+}
+
+pciio_vendor_id_t
+pciio_info_vendor_id_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_vendor);
+}
+
+pciio_device_id_t
+pciio_info_device_id_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_device);
+}
+
+devfs_handle_t
+pciio_info_master_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_master);
+}
+
+arbitrary_info_t
+pciio_info_mfast_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_mfast);
+}
+
+pciio_provider_t       *
+pciio_info_pops_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_pops);
+}
+
+error_handler_f	       *
+pciio_info_efunc_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_efunc);
+}
+
+error_handler_arg_t    *
+pciio_info_einfo_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_einfo);
+}
+
+pciio_space_t
+pciio_info_bar_space_get(pciio_info_t info, int win)
+{
+    return info->c_window[win].w_space;
+}
+
+iopaddr_t
+pciio_info_bar_base_get(pciio_info_t info, int win)
+{
+    return info->c_window[win].w_base;
+}
+
+size_t
+pciio_info_bar_size_get(pciio_info_t info, int win)
+{
+    return info->c_window[win].w_size;
+}
+
+iopaddr_t
+pciio_info_rom_base_get(pciio_info_t info)
+{
+    return info->c_rbase;
+}
+
+size_t
+pciio_info_rom_size_get(pciio_info_t info)
+{
+    return info->c_rsize;
+}
+
+
+/* =====================================================================
+ *          GENERIC PCI INITIALIZATION FUNCTIONS
+ */
+
+/*
+ *    pciioinit: called once during device driver
+ *      initializtion if this driver is configured into
+ *      the system.
+ */
+void
+pciio_init(void)
+{
+    cdl_p                   cp;
+
+#if DEBUG && ATTACH_DEBUG
+    printf("pciio_init\n");
+#endif
+    /* Allocate the registry.
+     * We might already have one.
+     * If we don't, go get one.
+     * MPness: someone might have
+     * set one up for us while we
+     * were not looking; use an atomic
+     * compare-and-swap to commit to
+     * using the new registry if and
+     * only if nobody else did first.
+     * If someone did get there first,
+     * toss the one we allocated back
+     * into the pool.
+     */
+    if (pciio_registry == NULL) {
+	cp = cdl_new(EDGE_LBL_PCI, "vendor", "device");
+	if (!compare_and_swap_ptr((void **) &pciio_registry, NULL, (void *) cp)) {
+	    cdl_del(cp);
+	}
+    }
+    ASSERT(pciio_registry != NULL);
+}
+
+/*
+ *    pciioattach: called for each vertex in the graph
+ *      that is a PCI provider.
+ */
+/*ARGSUSED */
+int
+pciio_attach(devfs_handle_t pciio)
+{
+#if DEBUG && ATTACH_DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk("%v: pciio_attach\n", pciio);
+#else
+    printk("0x%x: pciio_attach\n", pciio);
+#endif
+#endif
+    return 0;
+}
+
+/*
+ * Associate a set of pciio_provider functions with a vertex.
+ */
+void
+pciio_provider_register(devfs_handle_t provider, pciio_provider_t *pciio_fns)
+{
+    hwgraph_info_add_LBL(provider, INFO_LBL_PFUNCS, (arbitrary_info_t) pciio_fns);
+}
+
+/*
+ * Disassociate a set of pciio_provider functions with a vertex.
+ */
+void
+pciio_provider_unregister(devfs_handle_t provider)
+{
+    arbitrary_info_t        ainfo;
+
+    hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, (long *) &ainfo);
+}
+
+/*
+ * Obtain a pointer to the pciio_provider functions for a specified Crosstalk
+ * provider.
+ */
+pciio_provider_t       *
+pciio_provider_fns_get(devfs_handle_t provider)
+{
+    arbitrary_info_t        ainfo = 0;
+
+    (void) hwgraph_info_get_LBL(provider, INFO_LBL_PFUNCS, &ainfo);
+    return (pciio_provider_t *) ainfo;
+}
+
+/*ARGSUSED4 */
+int
+pciio_driver_register(
+			 pciio_vendor_id_t vendor_id,
+			 pciio_device_id_t device_id,
+			 char *driver_prefix,
+			 unsigned flags)
+{
+    /* a driver's init routine might call
+     * pciio_driver_register before the
+     * system calls pciio_init; so we
+     * make the init call ourselves here.
+     */
+    if (pciio_registry == NULL)
+	pciio_init();
+
+    return cdl_add_driver(pciio_registry,
+			  vendor_id, device_id,
+			  driver_prefix, flags, NULL);
+}
+
+/*
+ * Remove an initialization function.
+ */
+void
+pciio_driver_unregister(
+			   char *driver_prefix)
+{
+    /* before a driver calls unregister,
+     * it must have called register; so
+     * we can assume we have a registry here.
+     */
+    ASSERT(pciio_registry != NULL);
+
+    cdl_del_driver(pciio_registry, driver_prefix, NULL);
+}
+
+/* 
+ * Set the slot status for a device supported by the 
+ * driver being registered.
+ */
+void
+pciio_driver_reg_callback(
+                           devfs_handle_t pconn_vhdl,
+			   int key1,
+			   int key2,
+                           int error)
+{
+}
+
+/* 
+ * Set the slot status for a device supported by the 
+ * driver being unregistered.
+ */
+void
+pciio_driver_unreg_callback(
+                           devfs_handle_t pconn_vhdl,
+			   int key1,
+			   int key2,
+                           int error)
+{
+}
+
+/*
+ * Call some function with each vertex that
+ * might be one of this driver's attach points.
+ */
+void
+pciio_iterate(char *driver_prefix,
+	      pciio_iter_f * func)
+{
+    /* a driver's init routine might call
+     * pciio_iterate before the
+     * system calls pciio_init; so we
+     * make the init call ourselves here.
+     */
+    if (pciio_registry == NULL)
+	pciio_init();
+
+    ASSERT(pciio_registry != NULL);
+
+    cdl_iterate(pciio_registry, driver_prefix, (cdl_iter_f *) func);
+}
+
+devfs_handle_t
+pciio_device_register(
+		devfs_handle_t connectpt,	/* vertex for /hw/.../pciio/%d */
+		devfs_handle_t master,	/* card's master ASIC (PCI provider) */
+		pciio_slot_t slot,	/* card's slot */
+		pciio_function_t func,	/* card's func */
+		pciio_vendor_id_t vendor_id,
+		pciio_device_id_t device_id)
+{
+    return pciio_device_info_register
+	(connectpt, pciio_device_info_new (NULL, master, slot, func,
+					   vendor_id, device_id));
+}
+
+void
+pciio_device_unregister(devfs_handle_t pconn)
+{
+    DEV_FUNC(pconn,device_unregister)(pconn);
+}
+
+pciio_info_t
+pciio_device_info_new(
+		pciio_info_t pciio_info,
+		devfs_handle_t master,
+		pciio_slot_t slot,
+		pciio_function_t func,
+		pciio_vendor_id_t vendor_id,
+		pciio_device_id_t device_id)
+{
+    if (!pciio_info)
+	GET_NEW(pciio_info);
+    ASSERT(pciio_info != NULL);
+
+    pciio_info->c_slot = slot;
+    pciio_info->c_func = func;
+    pciio_info->c_vendor = vendor_id;
+    pciio_info->c_device = device_id;
+    pciio_info->c_master = master;
+    pciio_info->c_mfast = hwgraph_fastinfo_get(master);
+    pciio_info->c_pops = pciio_provider_fns_get(master);
+    pciio_info->c_efunc = 0;
+    pciio_info->c_einfo = 0;
+
+    return pciio_info;
+}
+
+void
+pciio_device_info_free(pciio_info_t pciio_info)
+{
+    /* NOTE : pciio_info is a structure within the pcibr_info
+     *	      and not a pointer to memory allocated on the heap !!
+     */
+    BZERO((char *)pciio_info,sizeof(pciio_info));
+}
+
+devfs_handle_t
+pciio_device_info_register(
+		devfs_handle_t connectpt,		/* vertex at center of bus */
+		pciio_info_t pciio_info)	/* details about the connectpt */
+{
+    char		name[32];
+    devfs_handle_t	pconn;
+    int device_master_set(devfs_handle_t, devfs_handle_t);
+
+    pciio_slot_func_to_name(name,
+			    pciio_info->c_slot,
+			    pciio_info->c_func);
+
+    if (GRAPH_SUCCESS !=
+	hwgraph_path_add(connectpt, name, &pconn))
+	return pconn;
+
+    pciio_info->c_vertex = pconn;
+    pciio_info_set(pconn, pciio_info);
+#ifdef DEBUG_PCIIO
+    {
+	int pos;
+	char dname[256];
+	pos = devfs_generate_path(pconn, dname, 256);
+	printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]);
+    }
+#endif /* DEBUG_PCIIO */
+
+    /*
+     * create link to our pci provider
+     */
+
+    device_master_set(pconn, pciio_info->c_master);
+
+#if USRPCI
+    /*
+     * Call into usrpci provider to let it initialize for
+     * the given slot.
+     */
+    if (pciio_info->c_slot != PCIIO_SLOT_NONE)
+	usrpci_device_register(pconn, pciio_info->c_master, pciio_info->c_slot);
+#endif
+
+    return pconn;
+}
+
+void
+pciio_device_info_unregister(devfs_handle_t connectpt,
+			     pciio_info_t pciio_info)
+{
+    char		name[32];
+    devfs_handle_t	pconn;
+
+    if (!pciio_info)
+	return;
+
+    pciio_slot_func_to_name(name,
+			    pciio_info->c_slot,
+			    pciio_info->c_func);
+
+    hwgraph_edge_remove(connectpt,name,&pconn);
+    pciio_info_set(pconn,0);
+
+    /* Remove the link to our pci provider */
+    hwgraph_edge_remove(pconn, EDGE_LBL_MASTER, NULL);
+
+
+    hwgraph_vertex_unref(pconn);
+    hwgraph_vertex_destroy(pconn);
+    
+}
+/* Add the pci card inventory information to the hwgraph
+ */
+static void
+pciio_device_inventory_add(devfs_handle_t pconn_vhdl)
+{
+    pciio_info_t	pciio_info = pciio_info_get(pconn_vhdl);
+
+    ASSERT(pciio_info);
+    ASSERT(pciio_info->c_vertex == pconn_vhdl);
+
+    /* Donot add inventory  for non-existent devices */
+    if ((pciio_info->c_vendor == PCIIO_VENDOR_ID_NONE)	||
+	(pciio_info->c_device == PCIIO_DEVICE_ID_NONE))
+	return;
+    device_inventory_add(pconn_vhdl,INV_IOBD,INV_PCIADAP,
+			 pciio_info->c_vendor,pciio_info->c_device,
+			 pciio_info->c_slot);
+}
+
+/*ARGSUSED */
+int
+pciio_device_attach(devfs_handle_t pconn,
+		    int          drv_flags)
+{
+    pciio_info_t            pciio_info;
+    pciio_vendor_id_t       vendor_id;
+    pciio_device_id_t       device_id;
+
+
+    pciio_device_inventory_add(pconn);
+    pciio_info = pciio_info_get(pconn);
+
+    vendor_id = pciio_info->c_vendor;
+    device_id = pciio_info->c_device;
+
+    /* we don't start attaching things until
+     * all the driver init routines (including
+     * pciio_init) have been called; so we
+     * can assume here that we have a registry.
+     */
+    ASSERT(pciio_registry != NULL);
+
+    return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn, drv_flags));
+}
+
+int
+pciio_device_detach(devfs_handle_t pconn,
+		    int          drv_flags)
+{
+    pciio_info_t            pciio_info;
+    pciio_vendor_id_t       vendor_id;
+    pciio_device_id_t       device_id;
+
+    pciio_info = pciio_info_get(pconn);
+
+    vendor_id = pciio_info->c_vendor;
+    device_id = pciio_info->c_device;
+
+    /* we don't start attaching things until
+     * all the driver init routines (including
+     * pciio_init) have been called; so we
+     * can assume here that we have a registry.
+     */
+    ASSERT(pciio_registry != NULL);
+
+    return(cdl_del_connpt(pciio_registry, vendor_id, device_id,
+		          pconn, drv_flags));
+
+}
+
+/* SN2 */
+/*
+ * Allocate (if necessary) and initialize a PCI window mapping structure.
+ */
+pciio_win_map_t
+pciio_device_win_map_new(pciio_win_map_t win_map,
+			 size_t region_size,
+			 size_t page_size)
+{
+	ASSERT((page_size & (page_size - 1)) == 0);
+	ASSERT((region_size & (page_size - 1)) == 0);
+
+	if (win_map == NULL)
+		NEW(win_map);
+
+	/*
+	 * The map array tracks the free ``pages'' in the region.  The worst
+	 * case scenario is when every other page in the region is free --
+	 * e.i. maximum fragmentation.  This leads to (max pages + 1) / 2 + 1
+	 * map entries.  The first "+1" handles the divide by 2 rounding; the
+	 * second handles the need for an end marker sentinel.
+	 */
+	win_map->wm_map = rmallocmap((region_size / page_size + 1) / 2 + 1);
+	win_map->wm_page_size = page_size;
+	ASSERT(win_map->wm_map != NULL);
+
+	return win_map;
+}
+
+/*
+ * Free resources associated with a PCI window mapping structure.
+ */
+extern void
+pciio_device_win_map_free(pciio_win_map_t win_map)
+{
+	rmfreemap(win_map->wm_map);
+	bzero(win_map, sizeof *win_map);
+}
+
+/*
+ * Populate window map with specified free range.
+ */
+void
+pciio_device_win_populate(pciio_win_map_t win_map,
+                          iopaddr_t ioaddr,
+                          size_t size)
+{
+	ASSERT((size & (win_map->wm_page_size - 1)) == 0);
+	ASSERT((ioaddr & (win_map->wm_page_size - 1)) == 0);
+
+	rmfree(win_map->wm_map,
+	       size / win_map->wm_page_size,
+	       (unsigned long)ioaddr / win_map->wm_page_size);
+	       
+}
+/*
+ * Allocate space from the specified PCI window mapping resource.  On
+ * success record information about the allocation in the supplied window
+ * allocation cookie (if non-NULL) and return the address of the allocated
+ * window.  On failure return NULL.
+ *
+ * The "size" parameter is usually from a PCI device's Base Address Register
+ * (BAR) decoder.  As such, the allocation must be aligned to be a multiple of
+ * that.  The "align" parameter acts as a ``minimum alignment'' allocation
+ * constraint.  The alignment contraint reflects system or device addressing
+ * restrictions such as the inability to share higher level ``windows''
+ * between devices, etc.  The returned PCI address allocation will be a
+ * multiple of the alignment constraint both in alignment and size.  Thus, the
+ * returned PCI address block is aligned to the maximum of the requested size
+ * and alignment.
+ */
+iopaddr_t
+pciio_device_win_alloc(pciio_win_map_t win_map,
+		       pciio_win_alloc_t win_alloc,
+		       size_t start, size_t size, size_t align)
+{
+	unsigned long base;
+
+#ifdef PIC_LATER
+	ASSERT((size & (size - 1)) == 0);
+	ASSERT((align & (align - 1)) == 0);
+
+	/*
+	 * Convert size and alignment to pages.  If size is greated than the
+	 * requested alignment, we bump the alignment up to size; otherwise
+	 * convert the size into a multiple of the alignment request.
+	 */
+	size = (size + win_map->wm_page_size - 1) / win_map->wm_page_size;
+	align = align / win_map->wm_page_size;
+	if (size > align)
+		align = size;
+	else
+		size = (size + align - 1) & ~(align - 1);
+
+	/* XXXX */
+	base = rmalloc_align(win_map->wm_map, size, align, VM_NOSLEEP);
+	if (base == RMALLOC_FAIL)
+		return((iopaddr_t)NULL);
+#else
+    int                 index_page, index_page_align;
+    int                 align_pages, size_pages;
+    int                 alloc_pages, free_pages;
+    int                 addr_align;
+
+    /* Convert PCI bus alignment from bytes to pages */
+    align_pages = align / win_map->wm_page_size;
+
+    /* Convert PCI request from bytes to pages */
+    size_pages = (size / win_map->wm_page_size) +
+                  ((size % win_map->wm_page_size) ? 1 : 0);
+
+    /* Align address with the larger of the size or the requested slot align */
+    if (size_pages > align_pages)
+        align_pages = size_pages;
+  
+    /*
+     * Avoid wasting space by aligning - 1; this will prevent crossing
+     * another alignment boundary.
+     */
+    alloc_pages = size_pages + (align_pages - 1);
+
+    /* Allocate PCI bus space in pages */
+    index_page = (int) rmalloc(win_map->wm_map,
+                               (size_t) alloc_pages);
+
+    /* Error if no PCI bus address space available */
+    if (!index_page)
+        return 0;
+
+    /* PCI bus address index starts at 0 */
+    index_page--;
+
+    /* Align the page offset as requested */
+    index_page_align = (index_page + (align_pages - 1)) -
+                       ((index_page + (align_pages - 1)) % align_pages);
+
+    free_pages = (align_pages - 1) - (index_page_align - index_page);
+
+    /* Free unused PCI bus pages adjusting the index to start at 1 */
+    rmfree(win_map->wm_map, 
+           free_pages,
+           (index_page_align + 1) + size_pages);
+
+    /* Return aligned PCI bus space in bytes */ 
+    addr_align = (index_page_align * win_map->wm_page_size); 
+    base = index_page;
+    size = alloc_pages - free_pages;
+#endif	/* PIC_LATER */
+
+	/*
+	 * If a window allocation cookie has been supplied, use it to keep
+	 * track of all the allocated space assigned to this window.
+	 */
+	if (win_alloc) {
+		win_alloc->wa_map = win_map;
+		win_alloc->wa_base = base;
+		win_alloc->wa_pages = size;
+	}
+
+	return base * win_map->wm_page_size;
+}
+
+/*
+ * Free the specified window allocation back into the PCI window mapping
+ * resource.  As noted above, we keep page addresses offset by 1 ...
+ */
+void
+pciio_device_win_free(pciio_win_alloc_t win_alloc)
+{
+	if (win_alloc->wa_pages)
+		rmfree(win_alloc->wa_map->wm_map,
+		       win_alloc->wa_pages,
+		       win_alloc->wa_base);
+}
+
+/*
+ * pciio_error_register:
+ * arrange for a function to be called with
+ * a specified first parameter plus other
+ * information when an error is encountered
+ * and traced to the pci slot corresponding
+ * to the connection point pconn.
+ *
+ * may also be called with a null function
+ * pointer to "unregister" the error handler.
+ *
+ * NOTE: subsequent calls silently overwrite
+ * previous data for this vertex. We assume that
+ * cooperating drivers, well, cooperate ...
+ */
+void
+pciio_error_register(devfs_handle_t pconn,
+		     error_handler_f *efunc,
+		     error_handler_arg_t einfo)
+{
+    pciio_info_t            pciio_info;
+
+    pciio_info = pciio_info_get(pconn);
+    ASSERT(pciio_info != NULL);
+    pciio_info->c_efunc = efunc;
+    pciio_info->c_einfo = einfo;
+}
+
+/*
+ * Check if any device has been found in this slot, and return
+ * true or false
+ * vhdl is the vertex for the slot
+ */
+int
+pciio_slot_inuse(devfs_handle_t pconn_vhdl)
+{
+    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);
+
+    ASSERT(pciio_info);
+    ASSERT(pciio_info->c_vertex == pconn_vhdl);
+    if (pciio_info->c_vendor) {
+	/*
+	 * Non-zero value for vendor indicate
+	 * a board being found in this slot.
+	 */
+	return 1;
+    }
+    return 0;
+}
+
+int
+pciio_dma_enabled(devfs_handle_t pconn_vhdl)
+{
+	return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl);
+}
+
+int
+pciio_info_type1_get(pciio_info_t pci_info)
+{
+	return(0);
+}
+
+
+/*
+ * These are complementary Linux interfaces that takes in a pci_dev * as the 
+ * first arguement instead of devfs_handle_t.
+ */
+iopaddr_t               snia_pciio_dmatrans_addr(struct pci_dev *, device_desc_t, paddr_t, size_t, unsigned);
+pciio_dmamap_t          snia_pciio_dmamap_alloc(struct pci_dev *, device_desc_t, size_t, unsigned);
+void                    snia_pciio_dmamap_free(pciio_dmamap_t);
+iopaddr_t               snia_pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t);
+void                    snia_pciio_dmamap_done(pciio_dmamap_t);
+pciio_endian_t          snia_pciio_endian_set(struct pci_dev *pci_dev, pciio_endian_t device_end,
+					      pciio_endian_t desired_end);
+
+#include <linux/module.h>
+EXPORT_SYMBOL(snia_pciio_dmatrans_addr);
+EXPORT_SYMBOL(snia_pciio_dmamap_alloc);
+EXPORT_SYMBOL(snia_pciio_dmamap_free);
+EXPORT_SYMBOL(snia_pciio_dmamap_addr);
+EXPORT_SYMBOL(snia_pciio_dmamap_done);
+EXPORT_SYMBOL(snia_pciio_endian_set);
+
+int
+snia_pcibr_rrb_alloc(struct pci_dev *pci_dev,
+	int *count_vchan0,
+	int *count_vchan1)
+{
+	devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+
+	return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1);
+}
+EXPORT_SYMBOL(snia_pcibr_rrb_alloc);
+
+pciio_endian_t
+snia_pciio_endian_set(struct pci_dev *pci_dev,
+	pciio_endian_t device_end,
+	pciio_endian_t desired_end)
+{
+	devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+	
+	return DEV_FUNC(dev, endian_set)
+		(dev, device_end, desired_end);
+}
+
+iopaddr_t
+snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */
+                    device_desc_t dev_desc,     /* device descriptor */
+                    paddr_t paddr,      /* system physical address */
+                    size_t byte_count,  /* length */
+                    unsigned flags)
+{                                       /* defined in dma.h */
+
+    devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+
+    /*
+     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be 
+     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
+     */
+    return DEV_FUNC(dev, dmatrans_addr)
+        (dev, dev_desc, paddr, byte_count, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM);
+}
+
+pciio_dmamap_t
+snia_pciio_dmamap_alloc(struct pci_dev *pci_dev,  /* set up mappings for this device */
+                   device_desc_t dev_desc,      /* device descriptor */
+                   size_t byte_count_max,       /* max size of a mapping */
+                   unsigned flags)
+{                                       /* defined in dma.h */
+
+    devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+
+    /*
+     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be
+     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
+     */
+    return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
+        (dev, dev_desc, byte_count_max, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM);
+}
+
+void
+snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_free)
+        (CAST_DMAMAP(pciio_dmamap));
+}
+
+iopaddr_t
+snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,  /* use these mapping resources */
+                  paddr_t paddr,        /* map for this address */
+                  size_t byte_count)
+{                                       /* map this many bytes */
+    return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
+        (CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
+}
+
+void
+snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_done)
+        (CAST_DMAMAP(pciio_dmamap));
+}
+
diff -Nru a/arch/ia64/sn/io/sn2/pic.c b/arch/ia64/sn/io/sn2/pic.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pic.c	Mon Feb 24 05:30:53 2003
@@ -0,0 +1,325 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/pci/pci_defs.h>
+#include <asm/sn/prio.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/ioc3.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_private.h>
+
+extern char *bcopy(const char * src, char * dest, int count);
+
+
+#define PCI_BUS_NO_1 1
+
+int pic_devflag = D_MP;
+
+extern int pcibr_attach2(devfs_handle_t, bridge_t *, devfs_handle_t, int, pcibr_soft_t *);
+extern void pcibr_driver_reg_callback(devfs_handle_t, int, int, int);
+extern void pcibr_driver_unreg_callback(devfs_handle_t, int, int, int);
+
+
+void
+pic_init(void)
+{
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pic_init()\n"));	
+
+	xwidget_driver_register(PIC_WIDGET_PART_NUM_BUS0,
+			    PIC_WIDGET_MFGR_NUM,
+			    "pic_",
+			    0);
+}
+
+/*
+ * copy inventory_t from conn_v to peer_conn_v
+ */
+int
+pic_bus1_inventory_dup(devfs_handle_t conn_v, devfs_handle_t peer_conn_v)
+{
+	inventory_t *pinv, *peer_pinv;
+
+	if (hwgraph_info_get_LBL(conn_v, INFO_LBL_INVENT,
+				(arbitrary_info_t *)&pinv) == GRAPH_SUCCESS)
+ {
+		NEW(peer_pinv);
+		bcopy(pinv, peer_pinv, sizeof(inventory_t));
+		if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_INVENT,
+			    (arbitrary_info_t)peer_pinv) != GRAPH_SUCCESS) {
+			DEL(peer_pinv);
+			return 0;
+		}
+		return 1;
+	}
+
+	printk("pic_bus1_inventory_dup: cannot get INFO_LBL_INVENT from 0x%lx\n ",
+								conn_v);
+	return 0;
+}
+
+/*
+ * copy xwidget_info_t from conn_v to peer_conn_v
+ */
+int
+pic_bus1_widget_info_dup(devfs_handle_t conn_v, devfs_handle_t peer_conn_v,
+							cnodeid_t xbow_peer)
+{
+	xwidget_info_t widget_info, peer_widget_info;
+	char peer_path[256];
+	char *p;
+	devfs_handle_t peer_hubv;
+	hubinfo_t peer_hub_info;
+
+	/* get the peer hub's widgetid */
+	peer_hubv = NODEPDA(xbow_peer)->node_vertex;
+	peer_hub_info = NULL;
+	hubinfo_get(peer_hubv, &peer_hub_info);
+	if (peer_hub_info == NULL)
+		return 0;
+
+	if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET,
+			(arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) {
+		NEW(peer_widget_info);
+		peer_widget_info->w_vertex = peer_conn_v;
+		peer_widget_info->w_id = widget_info->w_id;
+		peer_widget_info->w_master = peer_hubv;
+		peer_widget_info->w_masterid = peer_hub_info->h_widgetid;
+		/* structure copy */
+		peer_widget_info->w_hwid = widget_info->w_hwid;
+		peer_widget_info->w_efunc = 0;
+		peer_widget_info->w_einfo = 0;
+		peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL);
+		strcpy(peer_widget_info->w_name, peer_path);
+
+		if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET,
+			(arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) {
+				DEL(peer_widget_info);
+				return 0;
+		}
+
+		xwidget_info_set(peer_conn_v, peer_widget_info);
+
+		return 1;
+	}
+
+	printk("pic_bus1_widget_info_dup: "
+			"cannot get INFO_LBL_XWIDGET from 0x%lx\n", conn_v);
+	return 0;
+}
+
+/*
+ * If this PIC is attached to two Cbricks ("dual-ported") then
+ * attach each bus to opposite Cbricks.
+ *
+ * If successful, return a new vertex suitable for attaching the PIC bus.
+ * If not successful, return zero and both buses will attach to the
+ * vertex passed into pic_attach().
+ */
+devfs_handle_t
+pic_bus1_redist(nasid_t nasid, devfs_handle_t conn_v)
+{
+	cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid);
+	cnodeid_t xbow_peer = -1;
+	char pathname[256], peer_path[256], tmpbuf[256];
+	char *p;
+	int rc;
+	devfs_handle_t peer_conn_v;
+	int pos;
+	slabid_t slab;
+
+	if (NODEPDA(cnode)->xbow_peer >= 0) {			/* if dual-ported */
+		/* create a path for this widget on the peer Cbrick */
+		/* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */
+		/* sprintf(pathname, "%v", conn_v); */
+		xbow_peer = NASID_TO_COMPACT_NODEID(NODEPDA(cnode)->xbow_peer);
+		pos = devfs_generate_path(conn_v, tmpbuf, 256);
+		strcpy(pathname, &tmpbuf[pos]);
+		p = pathname + strlen("hw/module/001c01/slab/0/");
+
+		memset(tmpbuf, 0, 16);
+		format_module_id(tmpbuf, geo_module((NODEPDA(xbow_peer))->geoid), MODULE_FORMAT_BRIEF);
+		slab = geo_slab((NODEPDA(xbow_peer))->geoid);
+		sprintf(peer_path, "module/%s/slab/%d/%s", tmpbuf, (int)slab, p); 
+		
+		/* Look for vertex for this widget on the peer Cbrick.
+		 * Expect GRAPH_NOT_FOUND.
+		 */
+		rc = hwgraph_traverse(hwgraph_root, peer_path, &peer_conn_v);
+		if (GRAPH_SUCCESS == rc)
+			printk("pic_attach: found unexpected vertex: 0x%lx\n",
+								peer_conn_v);
+		else if (GRAPH_NOT_FOUND != rc) {
+			printk("pic_attach: hwgraph_traverse unexpectedly"
+					" returned 0x%x\n", rc);
+		} else {
+			/* try to add the widget vertex to the peer Cbrick */
+			rc = hwgraph_path_add(hwgraph_root, peer_path, &peer_conn_v);
+
+			if (GRAPH_SUCCESS != rc)
+			    printk("pic_attach: hwgraph_path_add"
+						" failed with 0x%x\n", rc);
+			else {
+			    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+					"pic_bus1_redist: added vertex %v\n", peer_conn_v)); 
+
+			    /* Now hang appropiate stuff off of the new
+			     * vertex.	We bail out if we cannot add something.
+			     * In that case, we don't remove the newly added
+			     * vertex but that should be safe and we don't
+			     * really expect the additions to fail anyway.
+			     */
+#if 0
+			    if (!pic_bus1_inventory_dup(conn_v, peer_conn_v))
+					return 0;
+			    pic_bus1_device_desc_dup(conn_v, peer_conn_v);
+#endif
+			    if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, xbow_peer))
+					return 0;
+
+			    return peer_conn_v;
+			}
+		}
+	}
+	return 0;
+}
+
+
+int
+pic_attach(devfs_handle_t conn_v)
+{
+	int		rc;
+	bridge_t	*bridge0, *bridge1 = (bridge_t *)0;
+	devfs_handle_t	pcibr_vhdl0, pcibr_vhdl1 = (devfs_handle_t)0;
+	pcibr_soft_t	bus0_soft, bus1_soft = (pcibr_soft_t)0;
+	devfs_handle_t  conn_v0, conn_v1, peer_conn_v;
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n"));
+
+	bridge0 = (bridge_t *) xtalk_piotrans_addr(conn_v, NULL,
+	                        0, sizeof(bridge_t), 0);
+	bridge1 = (bridge_t *)((char *)bridge0 + PIC_BUS1_OFFSET);
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+		    "pic_attach: bridge0=0x%x, bridge1=0x%x\n", 
+		    bridge0, bridge1));
+
+	conn_v0 = conn_v1 = conn_v;
+
+	/* If dual-ported then split the two PIC buses across both Cbricks */
+	if (peer_conn_v = pic_bus1_redist(NASID_GET(bridge0), conn_v))
+		conn_v1 = peer_conn_v;
+
+	/*
+	 * Create the vertex for the PCI buses, which week
+	 * will also use to hold the pcibr_soft and
+	 * which will be the "master" vertex for all the
+	 * pciio connection points we will hang off it.
+	 * This needs to happen before we call nic_bridge_vertex_info
+	 * as we are some of the *_vmc functions need access to the edges.
+	 *
+	 * Opening this vertex will provide access to
+	 * the Bridge registers themselves.
+	 */
+	/* FIXME: what should the hwgraph path look like ? */
+	rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0);
+	ASSERT(rc == GRAPH_SUCCESS);
+	rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1);
+	ASSERT(rc == GRAPH_SUCCESS);
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+		    "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n",
+		    pcibr_vhdl0, pcibr_vhdl1));
+
+	/* register pci provider array */
+	pciio_provider_register(pcibr_vhdl0, &pci_pic_provider);
+	pciio_provider_register(pcibr_vhdl1, &pci_pic_provider);
+
+	pciio_provider_startup(pcibr_vhdl0);
+	pciio_provider_startup(pcibr_vhdl1);
+
+	pcibr_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft);
+	pcibr_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft);
+
+	/* save a pointer to the PIC's other bus's soft struct */
+        bus0_soft->bs_peers_soft = bus1_soft;
+        bus1_soft->bs_peers_soft = bus0_soft;
+        bus0_soft->bs_peers_soft = (pcibr_soft_t)0;
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+		    "pic_attach: bus0_soft=0x%x, bus1_soft=0x%x\n",
+		    bus0_soft, bus1_soft));
+
+	return 0;
+}
+
+/*
+ * pci provider functions
+ *
+ * mostly in pcibr.c but if any are needed here then
+ * this might be a way to get them here.
+ */
+pciio_provider_t        pci_pic_provider =
+{
+    (pciio_piomap_alloc_f *) pcibr_piomap_alloc,
+    (pciio_piomap_free_f *) pcibr_piomap_free,
+    (pciio_piomap_addr_f *) pcibr_piomap_addr,
+    (pciio_piomap_done_f *) pcibr_piomap_done,
+    (pciio_piotrans_addr_f *) pcibr_piotrans_addr,
+    (pciio_piospace_alloc_f *) pcibr_piospace_alloc,
+    (pciio_piospace_free_f *) pcibr_piospace_free,
+
+    (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc,
+    (pciio_dmamap_free_f *) pcibr_dmamap_free,
+    (pciio_dmamap_addr_f *) pcibr_dmamap_addr,
+    (pciio_dmamap_list_f *) pcibr_dmamap_list,
+    (pciio_dmamap_done_f *) pcibr_dmamap_done,
+    (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr,
+    (pciio_dmatrans_list_f *) pcibr_dmatrans_list,
+    (pciio_dmamap_drain_f *) pcibr_dmamap_drain,
+    (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain,
+    (pciio_dmalist_drain_f *) pcibr_dmalist_drain,
+
+    (pciio_intr_alloc_f *) pcibr_intr_alloc,
+    (pciio_intr_free_f *) pcibr_intr_free,
+    (pciio_intr_connect_f *) pcibr_intr_connect,
+    (pciio_intr_disconnect_f *) pcibr_intr_disconnect,
+    (pciio_intr_cpu_get_f *) pcibr_intr_cpu_get,
+
+    (pciio_provider_startup_f *) pcibr_provider_startup,
+    (pciio_provider_shutdown_f *) pcibr_provider_shutdown,
+    (pciio_reset_f *) pcibr_reset,
+    (pciio_write_gather_flush_f *) pcibr_write_gather_flush,
+    (pciio_endian_set_f *) pcibr_endian_set,
+    (pciio_priority_set_f *) pcibr_priority_set,
+    (pciio_config_get_f *) pcibr_config_get,
+    (pciio_config_set_f *) pcibr_config_set,
+    (pciio_error_devenable_f *) 0,
+    (pciio_error_extract_f *) 0,
+    (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback,
+    (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback,
+    (pciio_device_unregister_f 	*) pcibr_device_unregister,
+    (pciio_dma_enabled_f		*) pcibr_dma_enabled,
+};
diff -Nru a/arch/ia64/sn/io/sn2/sgi_io_init.c b/arch/ia64/sn/io/sn2/sgi_io_init.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/sgi_io_init.c	Mon Feb 24 05:34:00 2003
@@ -0,0 +1,226 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/pci/pciba.h>
+#include <linux/smp.h>
+
+extern void mlreset(void);
+extern int init_hcl(void);
+extern void klgraph_hack_init(void);
+extern void hubspc_init(void);
+extern void pciio_init(void);
+extern void pcibr_init(void);
+extern void xtalk_init(void);
+extern void xbow_init(void);
+extern void xbmon_init(void);
+extern void pciiox_init(void);
+extern void pic_init(void);
+extern void usrpci_init(void);
+extern void ioc3_init(void);
+extern void initialize_io(void);
+extern void klhwg_add_all_modules(devfs_handle_t);
+extern void klhwg_add_all_nodes(devfs_handle_t);
+
+void sn_mp_setup(void);
+extern devfs_handle_t hwgraph_root;
+extern void io_module_init(void);
+extern void pci_bus_cvlink_init(void);
+extern void temp_hack(void);
+
+extern int pci_bus_to_hcl_cvlink(void);
+
+/* #define DEBUG_IO_INIT 1 */
+#ifdef DEBUG_IO_INIT
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG_IO_INIT */
+
+/*
+ * per_hub_init
+ *
+ * 	This code is executed once for each Hub chip.
+ */
+static void
+per_hub_init(cnodeid_t cnode)
+{
+	nasid_t		nasid;
+	nodepda_t	*npdap;
+	ii_icmr_u_t	ii_icmr;
+	ii_ibcr_u_t	ii_ibcr;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+	ASSERT(nasid != INVALID_NASID);
+	ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode);
+
+	npdap = NODEPDA(cnode);
+
+	REMOTE_HUB_S(nasid, IIO_IWEIM, 0x8000);
+
+	/*
+	 * Set the total number of CRBs that can be used.
+	 */
+	ii_icmr.ii_icmr_regval= 0x0;
+	ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
+	REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
+
+	/*
+	 * Set the number of CRBs that both of the BTEs combined
+	 * can use minus 1.
+	 */
+	ii_ibcr.ii_ibcr_regval= 0x0;
+	ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
+	REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
+
+	/*
+	 * Set CRB timeout to be 10ms.
+	 */
+#ifdef BRINGUP2
+	REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff );
+	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
+	//REMOTE_HUB_S(nasid, IIO_IWI, 0x00FF00FF00FFFFFF);
+#endif
+
+	/* Initialize error interrupts for this hub. */
+	hub_error_init(cnode);
+}
+
+/*
+ * This routine is responsible for the setup of all the IRIX hwgraph style
+ * stuff that's been pulled into linux.  It's called by sn_pci_find_bios which
+ * is called just before the generic Linux PCI layer does its probing (by 
+ * platform_pci_fixup aka sn_pci_fixup).
+ *
+ * It is very IMPORTANT that this call is only made by the Master CPU!
+ *
+ */
+
+void
+sgi_master_io_infr_init(void)
+{
+	int cnode;
+	extern void kdba_io_init();
+
+	/*
+	 * Do any early init stuff .. einit_tbl[] etc.
+	 */
+	init_hcl(); /* Sets up the hwgraph compatibility layer with devfs */
+
+	/*
+	 * initialize the Linux PCI to xwidget vertexes ..
+	 */
+	pci_bus_cvlink_init();
+
+	kdba_io_init();
+
+#ifdef BRINGUP
+	/*
+	 * Hack to provide statically initialzed klgraph entries.
+	 */
+	DBG("--> sgi_master_io_infr_init: calling klgraph_hack_init()\n");
+	klgraph_hack_init();
+#endif /* BRINGUP */
+
+	/*
+	 * This is the Master CPU.  Emulate mlsetup and main.c in Irix.
+	 */
+	mlreset();
+
+	/*
+	 * allowboot() is called by kern/os/main.c in main()
+	 * Emulate allowboot() ...
+	 *   per_cpu_init() - only need per_hub_init()
+	 *   cpu_io_setup() - Nothing to do.
+	 * 
+	 */
+	sn_mp_setup();
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		per_hub_init(cnode);
+	}
+
+	/* We can do headless hub cnodes here .. */
+
+	/*
+	 * io_init[] stuff.
+	 *
+	 * Get SGI IO Infrastructure drivers to init and register with 
+	 * each other etc.
+	 */
+
+	hubspc_init();
+	pciio_init();
+	pcibr_init();
+	pic_init();
+	xtalk_init();
+	xbow_init();
+	xbmon_init();
+	pciiox_init();
+	usrpci_init();
+	ioc3_init();
+
+	/*
+	 *
+	 * Our IO Infrastructure drivers are in place .. 
+	 * Initialize the whole IO Infrastructure .. xwidget/device probes.
+	 *
+	 */
+	initialize_io();
+	pci_bus_to_hcl_cvlink();
+
+#ifdef CONFIG_PCIBA
+	DBG("--> sgi_master_io_infr_init: calling pciba_init()\n");
+#ifndef BRINGUP2
+ 	pciba_init();
+#endif
+#endif
+}
+
+/*
+ * One-time setup for MP SN.
+ * Allocate per-node data, slurp prom klconfig information and
+ * convert it to hwgraph information.
+ */
+void
+sn_mp_setup(void)
+{
+	cpuid_t		cpu;
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		/* Skip holes in CPU space */
+		if (cpu_enabled(cpu)) {
+			init_platform_pda(cpu);
+		}
+	}
+
+	/*
+	 * Initialize platform-dependent vertices in the hwgraph:
+	 *	module
+	 *	node
+	 *	cpu
+	 *	memory
+	 *	slot
+	 *	hub
+	 *	router
+	 *	xbow
+	 */
+
+	io_module_init(); /* Use to be called module_init() .. */
+	klhwg_add_all_modules(hwgraph_root);
+	klhwg_add_all_nodes(hwgraph_root);
+}
diff -Nru a/arch/ia64/sn/io/sn2/shub.c b/arch/ia64/sn/io/sn2/shub.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/shub.c	Mon Feb 24 05:34:25 2003
@@ -0,0 +1,233 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#ident  "$Revision: 1.167 $"
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/smp.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn2/shub_mmr_t.h>
+#include <asm/sal.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/sndrv.h>
+
+/*
+ * Shub WAR for Xbridge Little Endian problem:
+ *	Xbridge has to run in BIG ENDIAN even with Shub.
+ */
+
+
+/*
+ * io_sh_swapper: Turn on Shub byte swapping.
+ *	All data destined to and from Shub to XIO are byte-swapped.
+ */
+void
+io_sh_swapper(nasid_t nasid, int onoff)
+{
+    ii_iwc_u_t      ii_iwc;
+
+    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
+
+    ii_iwc.ii_iwc_fld_s.i_dma_byte_swap = onoff;
+    REMOTE_HUB_S(nasid, IIO_IWC, ii_iwc.ii_iwc_regval);
+    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
+
+}
+
+/*
+ * io_get_sh_swapper: Return current Swap mode.
+ *	1 = Swap on, 0 = Swap off.
+ */
+int
+io_get_sh_swapper(nasid_t nasid)
+{
+    ii_iwc_u_t      ii_iwc;
+
+    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
+    return(ii_iwc.ii_iwc_fld_s.i_dma_byte_swap);
+
+}
+
+#define SHUB_NUM_ECF_REGISTERS 8
+
+static uint32_t	shub_perf_counts[SHUB_NUM_ECF_REGISTERS];
+
+static shubreg_t shub_perf_counts_regs[SHUB_NUM_ECF_REGISTERS] = {
+	SH_PERFORMANCE_COUNTER0,
+	SH_PERFORMANCE_COUNTER1,
+	SH_PERFORMANCE_COUNTER2,
+	SH_PERFORMANCE_COUNTER3,
+	SH_PERFORMANCE_COUNTER4,
+	SH_PERFORMANCE_COUNTER5,
+	SH_PERFORMANCE_COUNTER6,
+	SH_PERFORMANCE_COUNTER7
+};
+
+static inline void
+shub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val)
+{
+	int		   nasid = cnodeid_to_nasid(cnode);
+	volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+
+	*addr = val;
+	__ia64_mf_a();
+}
+
+static inline void
+shub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val)
+{
+	int		   nasid = cnodeid_to_nasid(cnode);
+	volatile uint32_t *addr = (uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+
+	*addr = val;
+	__ia64_mf_a();
+}
+
+static inline uint64_t
+shub_mmr_read(cnodeid_t cnode, shubreg_t reg)
+{
+	int		  nasid = cnodeid_to_nasid(cnode);
+	volatile uint64_t val;
+
+	val = *(uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+	__ia64_mf_a();
+
+	return val;
+}
+
+static inline uint32_t
+shub_mmr_read32(cnodeid_t cnode, shubreg_t reg)
+{
+	int		  nasid = cnodeid_to_nasid(cnode);
+	volatile uint32_t val;
+
+	val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+	__ia64_mf_a();
+
+	return val;
+}
+
+static int
+reset_shub_stats(cnodeid_t cnode)
+{
+	int i;
+
+	for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
+		shub_perf_counts[i] = 0;
+		shub_mmr_write32(cnode, shub_perf_counts_regs[i], 0);
+	}
+	return 0;
+}
+
+static int
+configure_shub_stats(cnodeid_t cnode, unsigned long arg)
+{
+	uint64_t	*p = (uint64_t *)arg;
+	uint64_t	i;
+	uint64_t	regcnt;
+	uint64_t	regval[2];
+
+	if (copy_from_user((void *)&regcnt, p, sizeof(regcnt)))
+	    return -EFAULT;
+
+	for (p++, i=0; i < regcnt; i++, p += 2) {
+		if (copy_from_user((void *)regval, (void *)p, sizeof(regval)))
+		    return -EFAULT;
+		if (regval[0] & 0x7) {
+		    printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]);
+		    return -EINVAL;
+		}
+		shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]);
+	}
+	return 0;
+}
+
+static int
+capture_shub_stats(cnodeid_t cnode, uint32_t *counts)
+{
+	int 		i;
+
+	for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
+		counts[i] = shub_mmr_read32(cnode, shub_perf_counts_regs[i]);
+	}
+	return 0;
+}
+
+static int
+shubstats_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+        cnodeid_t       cnode;
+        uint64_t        longarg;
+        devfs_handle_t  d;
+	int		nasid;
+
+        if ((d = devfs_get_handle_from_inode(inode)) == NULL)
+                return -ENODEV;
+        cnode = (cnodeid_t)hwgraph_fastinfo_get(d);
+
+        switch (cmd) {
+	case SNDRV_SHUB_CONFIGURE:
+		return configure_shub_stats(cnode, arg);
+		break;
+
+	case SNDRV_SHUB_RESETSTATS:
+		reset_shub_stats(cnode);
+		break;
+
+	case SNDRV_SHUB_INFOSIZE:
+		longarg = sizeof(shub_perf_counts);
+		if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) {
+		    return -EFAULT;
+		}
+		break;
+
+	case SNDRV_SHUB_GETSTATS:
+		capture_shub_stats(cnode, shub_perf_counts);
+		if (copy_to_user((void *)arg, shub_perf_counts,
+				       	sizeof(shub_perf_counts))) {
+		    return -EFAULT;
+		}
+		break;
+
+	case SNDRV_SHUB_GETNASID:
+		nasid = cnodeid_to_nasid(cnode);
+		if (copy_to_user((void *)arg, &nasid,
+				       	sizeof(nasid))) {
+		    return -EFAULT;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+struct file_operations shub_mon_fops = {
+	        ioctl:          shubstats_ioctl,
+};
diff -Nru a/arch/ia64/sn/io/sn2/shubio.c b/arch/ia64/sn/io/sn2/shubio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/shubio.c	Mon Feb 24 05:34:49 2003
@@ -0,0 +1,510 @@
+/* $Id: shubio.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000,2002-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/smp.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/ioerror_handling.h>
+#include <asm/sn/ioerror.h>
+#include <asm/sn/sn2/shubio.h>
+
+
+error_state_t error_state_get(devfs_handle_t v);
+error_return_code_t error_state_set(devfs_handle_t v,error_state_t new_state);
+
+
+/*
+ * Get the xtalk provider function pointer for the
+ * specified hub.
+ */
+
+/*ARGSUSED*/
+int
+hub_xp_error_handler(
+	devfs_handle_t 	hub_v, 
+	nasid_t		nasid, 
+	int		error_code, 
+	ioerror_mode_t	mode, 
+	ioerror_t	*ioerror)
+{
+	/*REFERENCED*/
+	hubreg_t	iio_imem;
+	devfs_handle_t	xswitch;
+	error_state_t	e_state;
+	cnodeid_t	cnode;
+
+	/*
+	 * Before walking down to the next level, check if
+	 * the I/O link is up. If it's been disabled by the 
+	 * hub ii for some reason, we can't even touch the
+	 * widget registers.
+	 */
+	iio_imem = REMOTE_HUB_L(nasid, IIO_IMEM);
+
+	if (!(iio_imem & (IIO_IMEM_B0ESD|IIO_IMEM_W0ESD))){
+		/* 
+		 * IIO_IMEM_B0ESD getting set, indicates II shutdown
+		 * on HUB0 parts.. Hopefully that's not true for 
+		 * Hub1 parts..
+		 *
+		 *
+		 * If either one of them is shut down, can't
+		 * go any further.
+		 */
+		return IOERROR_XTALKLEVEL;
+	}
+
+	/* Get the error state of the hub */
+	e_state = error_state_get(hub_v);
+
+	cnode = NASID_TO_COMPACT_NODEID(nasid);
+
+	xswitch = NODEPDA(cnode)->basew_xc;
+
+	/* Set the error state of the crosstalk device to that of
+	 * hub.
+	 */
+	if (error_state_set(xswitch , e_state) == 
+	    ERROR_RETURN_CODE_CANNOT_SET_STATE)
+		return(IOERROR_UNHANDLED);
+
+	/* Clean the error state of the hub if we are in the action handling
+	 * phase.
+	 */
+	if (e_state == ERROR_STATE_ACTION)
+		(void)error_state_set(hub_v, ERROR_STATE_NONE);
+	/* hand the error off to the switch or the directly
+	 * connected crosstalk device.
+	 */
+	return  xtalk_error_handler(xswitch,
+				    error_code, mode, ioerror);
+
+}
+
+/* 
+ * Check if the widget in error has been enabled for PIO accesses
+ */
+int
+is_widget_pio_enabled(ioerror_t *ioerror)
+{
+	cnodeid_t	src_node;
+	nasid_t		src_nasid;
+	hubreg_t	ii_iowa;
+	xwidgetnum_t	widget;
+	iopaddr_t	p;
+
+	/* Get the node where the PIO error occurred */
+	IOERROR_GETVALUE(p,ioerror, srcnode);
+	src_node = p;
+	if (src_node == CNODEID_NONE)
+		return(0);
+
+	/* Get the nasid for the cnode */
+	src_nasid = COMPACT_TO_NASID_NODEID(src_node);
+	if (src_nasid == INVALID_NASID)
+		return(0);
+
+	/* Read the Outbound widget access register for this hub */
+	ii_iowa = REMOTE_HUB_L(src_nasid, IIO_IOWA);
+	IOERROR_GETVALUE(p,ioerror, widgetnum);
+	widget = p;
+
+	/* Check if the PIOs to the widget with PIO error have been
+	 * enabled.
+	 */
+	if (ii_iowa & IIO_IOWA_WIDGET(widget))
+		return(1);
+
+	return(0);
+}
+
+/*
+ * Hub IO error handling.
+ *
+ *	Gets invoked for different types of errors found at the hub. 
+ *	Typically this includes situations from bus error or due to 
+ *	an error interrupt (mostly generated at the hub).
+ */
+int
+hub_ioerror_handler(
+	devfs_handle_t 	hub_v, 
+	int		error_code,
+	int		mode,
+	struct io_error_s	*ioerror)
+{
+	hubinfo_t 	hinfo; 		/* Hub info pointer */
+	nasid_t		nasid;
+	int		retval = 0;
+	/*REFERENCED*/
+	iopaddr_t 	p;
+
+	IOERROR_DUMP("hub_ioerror_handler", error_code, mode, ioerror);
+
+	hubinfo_get(hub_v, &hinfo);
+
+	if (!hinfo){
+		/* Print an error message and return */
+		goto end;
+	}
+	nasid = hinfo->h_nasid;
+
+	switch(error_code) {
+
+	case PIO_READ_ERROR:
+		/* 
+		 * Cpu got a bus error while accessing IO space.
+		 * hubaddr field in ioerror structure should have
+		 * the IO address that caused access error.
+		 */
+
+		/*
+		 * Identify if  the physical address in hub_error_data
+		 * corresponds to small/large window, and accordingly,
+		 * get the xtalk address.
+		 */
+
+		/*
+		 * Evaluate the widget number and the widget address that
+		 * caused the error. Use 'vaddr' if it's there.
+		 * This is typically true either during probing
+		 * or a kernel driver getting into trouble. 
+		 * Otherwise, use paddr to figure out widget details
+		 * This is typically true for user mode bus errors while
+		 * accessing I/O space.
+		 */
+		 IOERROR_GETVALUE(p,ioerror,vaddr);
+		 if (p){
+		    /* 
+		     * If neither in small window nor in large window range,
+		     * outright reject it.
+		     */
+		    IOERROR_GETVALUE(p,ioerror,vaddr);
+		    if (NODE_SWIN_ADDR(nasid, (paddr_t)p)){
+			iopaddr_t	hubaddr;
+			xwidgetnum_t	widgetnum;
+			iopaddr_t	xtalkaddr;
+
+			IOERROR_GETVALUE(p,ioerror,hubaddr);
+			hubaddr = p;
+			widgetnum = SWIN_WIDGETNUM(hubaddr);
+			xtalkaddr = SWIN_WIDGETADDR(hubaddr);
+			/* 
+			 * differentiate local register vs IO space access
+			 */
+			IOERROR_SETVALUE(ioerror,widgetnum,widgetnum);
+			IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr);
+
+
+		    } else if (NODE_BWIN_ADDR(nasid, (paddr_t)p)){
+			/* 
+			 * Address corresponds to large window space. 
+			 * Convert it to xtalk address.
+			 */
+			int		bigwin;
+			hub_piomap_t    bw_piomap;
+			xtalk_piomap_t	xt_pmap = NULL;
+			iopaddr_t	hubaddr;
+			xwidgetnum_t	widgetnum;
+			iopaddr_t	xtalkaddr;
+
+			IOERROR_GETVALUE(p,ioerror,hubaddr);
+			hubaddr = p;
+
+			/*
+			 * Have to loop to find the correct xtalk_piomap 
+			 * because the're not allocated on a one-to-one
+			 * basis to the window number.
+			 */
+			for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
+				bw_piomap = hubinfo_bwin_piomap_get(hinfo,
+								    bigwin);
+
+				if (bw_piomap->hpio_bigwin_num ==
+				    (BWIN_WINDOWNUM(hubaddr) - 1)) {
+					xt_pmap = hub_piomap_xt_piomap(bw_piomap);
+					break;
+				}
+			}
+
+			ASSERT(xt_pmap);
+
+			widgetnum = xtalk_pio_target_get(xt_pmap);
+			xtalkaddr = xtalk_pio_xtalk_addr_get(xt_pmap) + BWIN_WIDGETADDR(hubaddr);
+
+			IOERROR_SETVALUE(ioerror,widgetnum,widgetnum);
+			IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr);
+
+			/* 
+			 * Make sure that widgetnum doesnot map to hub 
+			 * register widget number, as we never use
+			 * big window to access hub registers. 
+			 */
+			ASSERT(widgetnum != HUB_REGISTER_WIDGET);
+		    }
+		} else if (IOERROR_FIELDVALID(ioerror,hubaddr)) {
+			iopaddr_t	hubaddr;
+			xwidgetnum_t	widgetnum;
+			iopaddr_t	xtalkaddr;
+
+			IOERROR_GETVALUE(p,ioerror,hubaddr);
+			hubaddr = p;
+			if (BWIN_WINDOWNUM(hubaddr)){
+				int 	window = BWIN_WINDOWNUM(hubaddr) - 1;
+				hubreg_t itte;
+				itte = (hubreg_t)HUB_L(IIO_ITTE_GET(nasid, window));
+				widgetnum =  (itte >> IIO_ITTE_WIDGET_SHIFT) & 
+						IIO_ITTE_WIDGET_MASK;
+				xtalkaddr = (((itte >> IIO_ITTE_OFFSET_SHIFT) &
+					IIO_ITTE_OFFSET_MASK) << 
+					     BWIN_SIZE_BITS) +
+					BWIN_WIDGETADDR(hubaddr);
+			} else {
+				widgetnum = SWIN_WIDGETNUM(hubaddr);
+				xtalkaddr = SWIN_WIDGETADDR(hubaddr);
+			}
+			IOERROR_SETVALUE(ioerror,widgetnum,widgetnum);
+			IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr);
+		} else {
+			IOERROR_DUMP("hub_ioerror_handler", error_code, 
+						mode, ioerror);
+			IOERR_PRINTF(printk(
+				"hub_ioerror_handler: Invalid address passed"));
+
+			return IOERROR_INVALIDADDR;
+		}
+
+
+		IOERROR_GETVALUE(p,ioerror,widgetnum);
+		if ((p) == HUB_REGISTER_WIDGET) {
+			/* 
+			 * Error in accessing Hub local register
+			 * This should happen mostly in SABLE mode..
+			 */
+			retval = 0;
+		} else {
+			/* Make sure that the outbound widget access for this
+			 * widget is enabled.
+			 */
+			if (!is_widget_pio_enabled(ioerror)) {
+				if (error_state_get(hub_v) == 
+				    ERROR_STATE_ACTION)
+					ioerror_dump("No outbound widget"
+						     " access - ", 
+						     error_code, mode, ioerror);
+				return(IOERROR_HANDLED);
+			}
+		  
+
+			retval = hub_xp_error_handler(
+				hub_v, nasid, error_code, mode, ioerror);
+
+		}
+
+		IOERR_PRINTF(printk(
+			"hub_ioerror_handler:PIO_READ_ERROR return: %d",
+				retval));
+
+		break;
+
+	case PIO_WRITE_ERROR:
+		/*
+		 * This hub received an interrupt indicating a widget 
+		 * attached to this hub got a timeout. 
+		 * widgetnum field should be filled to indicate the
+		 * widget that caused error.
+		 *
+		 * NOTE: This hub may have nothing to do with this error.
+		 * We are here since the widget attached to the xbow 
+		 * gets its PIOs through this hub.
+		 *
+		 * There is nothing that can be done at this level. 
+		 * Just invoke the xtalk error handling mechanism.
+		 */
+		IOERROR_GETVALUE(p,ioerror,widgetnum);
+		if ((p) == HUB_REGISTER_WIDGET) {
+		} else {
+			/* Make sure that the outbound widget access for this
+			 * widget is enabled.
+			 */
+
+			if (!is_widget_pio_enabled(ioerror)) {
+				if (error_state_get(hub_v) == 
+				    ERROR_STATE_ACTION)
+					ioerror_dump("No outbound widget"
+						     " access - ", 
+						     error_code, mode, ioerror);
+				return(IOERROR_HANDLED);
+			}
+		  
+			retval = hub_xp_error_handler(
+				hub_v, nasid, error_code, mode, ioerror);
+		}
+		break;
+	
+	case DMA_READ_ERROR:
+		/* 
+		 * DMA Read error always ends up generating an interrupt
+		 * at the widget level, and never at the hub level. So,
+		 * we don't expect to come here any time
+		 */
+		ASSERT(0);
+		retval = IOERROR_UNHANDLED;
+		break;
+
+	case DMA_WRITE_ERROR:
+		/*
+		 * DMA Write error is generated when a write by an I/O 
+		 * device could not be completed. Problem is, device is
+		 * totally unaware of this problem, and would continue
+		 * writing to system memory. So, hub has a way to send
+		 * an error interrupt on the first error, and bitbucket
+		 * all further write transactions.
+		 * Coming here indicates that hub detected one such error,
+		 * and we need to handle it.
+		 *
+		 * Hub interrupt handler would have extracted physaddr, 
+		 * widgetnum, and widgetdevice from the CRB 
+		 *
+		 * There is nothing special to do here, since gathering
+		 * data from crb's is done elsewhere. Just pass the 
+		 * error to xtalk layer.
+		 */
+		retval = hub_xp_error_handler(hub_v, nasid, error_code, mode,
+					      ioerror);
+		break;
+	
+	default:
+		ASSERT(0);
+		return IOERROR_BADERRORCODE;
+	
+	}
+	
+	/*
+	 * If error was not handled, we may need to take certain action
+	 * based on the error code.
+	 * For e.g. in case of PIO_READ_ERROR, we may need to release the
+	 * PIO Read entry table (they are sticky after errors).
+	 * Similarly other cases. 
+	 *
+	 * Further Action TBD 
+	 */
+end:	
+	if (retval == IOERROR_HWGRAPH_LOOKUP) {
+		/*
+		 * If we get errors very early, we can't traverse
+		 * the path using hardware graph. 
+		 * To handle this situation, we need a functions
+		 * which don't depend on the hardware graph vertex to 
+		 * handle errors. This break the modularity of the
+		 * existing code. Instead we print out the reason for
+		 * not handling error, and return. On return, all the
+		 * info collected would be dumped. This should provide 
+		 * sufficient info to analyse the error.
+		 */
+		printk("Unable to handle IO error: hardware graph not setup\n");
+	}
+
+	return retval;
+}
+
+#define L_BITSMINOR 18
+#define L_MAXMAJ 0x1ff
+#define emajor(x) (int )(((unsigned )(x)>>L_BITSMINOR) & L_MAXMAJ)
+#define dev_is_vertex(dev) (emajor((dev_t)(dev)) == 0)
+
+#define INFO_LBL_ERROR_STATE    "error_state"
+
+#define v_error_state_get(v,s)                                          \
+(hwgraph_info_get_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t *)&s))
+
+#define v_error_state_set(v,s,replace)                                  \
+(replace ?                                                              \
+hwgraph_info_replace_LBL(v,INFO_LBL_ERROR_STATE,(arbitrary_info_t)s,0) :\
+hwgraph_info_add_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t)s))
+
+
+#define v_error_state_clear(v)                                          \
+(hwgraph_info_remove_LBL(v,INFO_LBL_ERROR_STATE,0))
+
+/*
+ * error_state_get
+ *              Get the state of the vertex.
+ *              Returns ERROR_STATE_INVALID on failure
+ *                      current state otherwise
+ */
+error_state_t
+error_state_get(devfs_handle_t v)
+{
+        error_state_t   s;
+
+        /* Check if we have a valid hwgraph vertex */
+        if (!dev_is_vertex(v))
+                return(ERROR_STATE_NONE);
+
+        /* Get the labelled info hanging off the vertex which corresponds
+         * to the state.
+         */
+        if (v_error_state_get(v, s) != GRAPH_SUCCESS) {
+                return(ERROR_STATE_NONE);
+        }
+        return(s);
+}
+
+
+/*
+ * error_state_set
+ *              Set the state of the vertex
+ *              Returns ERROR_RETURN_CODE_CANNOT_SET_STATE on failure
+ *                      ERROR_RETURN_CODE_SUCCESS otherwise
+ */
+error_return_code_t
+error_state_set(devfs_handle_t v,error_state_t new_state)
+{
+        error_state_t   old_state;
+        boolean_t       replace = B_TRUE;
+
+        /* Check if we have a valid hwgraph vertex */
+        if (!dev_is_vertex(v))
+                return(ERROR_RETURN_CODE_GENERAL_FAILURE);
+
+
+        /* This means that the error state needs to be cleaned */
+        if (new_state == ERROR_STATE_NONE) {
+                /* Make sure that we have an error state */
+                if (v_error_state_get(v,old_state) == GRAPH_SUCCESS)
+                        v_error_state_clear(v);
+                return(ERROR_RETURN_CODE_SUCCESS);
+        }
+
+        /* Check if the state information has been set at least once
+         * for this vertex.
+         */
+        if (v_error_state_get(v,old_state) != GRAPH_SUCCESS)
+                replace = B_FALSE;
+
+        if (v_error_state_set(v,new_state,replace) != GRAPH_SUCCESS) {
+                return(ERROR_RETURN_CODE_CANNOT_SET_STATE);
+        }
+        return(ERROR_RETURN_CODE_SUCCESS);
+}
diff -Nru a/arch/ia64/sn/io/sn2/xbow.c b/arch/ia64/sn/io/sn2/xbow.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/xbow.c	Mon Feb 24 05:39:15 2003
@@ -0,0 +1,1681 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn2/sn_private.h>
+#include <asm/sn/sn2/shubio.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/hack.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/xtalk/xtalk_private.h>
+#include <asm/sn/simulator.h>
+
+/* #define DEBUG		1 */
+/* #define XBOW_DEBUG	1 */
+/* #define DEBUG_ERROR	1 */
+
+
+/*
+ * Files needed to get the device driver entry points
+ */
+
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/xtalk/xwidget.h>
+
+#include <asm/sn/prio.h>
+#include <asm/sn/hcl_util.h>
+
+
+#define NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
+#define DEL(ptr)	(kfree(ptr))
+
+int                     xbow_devflag = D_MP;
+
+/*
+ * This file supports the Xbow chip.  Main functions: initializtion,
+ * error handling, and GBR.
+ */
+
+/*
+ * each vertex corresponding to an xbow chip
+ * has a "fastinfo" pointer pointing at one
+ * of these things.
+ */
+typedef struct xbow_soft_s *xbow_soft_t;
+
+struct xbow_soft_s {
+    devfs_handle_t            conn;	/* our connection point */
+    devfs_handle_t            vhdl;	/* xbow's private vertex */
+    devfs_handle_t            busv;	/* the xswitch vertex */
+    xbow_t                 *base;	/* PIO pointer to crossbow chip */
+    char                   *name;	/* hwgraph name */
+
+    xbow_perf_t             xbow_perfcnt[XBOW_PERF_COUNTERS];
+    xbow_perf_link_t        xbow_perflink[MAX_XBOW_PORTS];
+    xbow_link_status_t      xbow_link_status[MAX_XBOW_PORTS];
+    spinlock_t              xbow_perf_lock;
+    int                     link_monitor;
+    widget_cfg_t	   *wpio[MAX_XBOW_PORTS];	/* cached PIO pointer */
+
+    /* Bandwidth allocation state. Bandwidth values are for the
+     * destination port since contention happens there.
+     * Implicit mapping from xbow ports (8..f) -> (0..7) array indices.
+     */
+    spinlock_t		    xbow_bw_alloc_lock;		/* bw allocation lock */
+    unsigned long long	    bw_hiwm[MAX_XBOW_PORTS];	/* hiwater mark values */
+    unsigned long long      bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */
+};
+
+#define xbow_soft_set(v,i)	hwgraph_fastinfo_set((v), (arbitrary_info_t)(i))
+#define xbow_soft_get(v)	((xbow_soft_t)hwgraph_fastinfo_get((v)))
+
+/*
+ * Function Table of Contents
+ */
+
+void                    xbow_mlreset(xbow_t *);
+void                    xbow_init(void);
+int                     xbow_attach(devfs_handle_t);
+
+int                     xbow_open(devfs_handle_t *, int, int, cred_t *);
+int                     xbow_close(devfs_handle_t, int, int, cred_t *);
+
+int                     xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint);
+int                     xbow_unmap(devfs_handle_t, vhandl_t *);
+int                     xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *);
+
+int                     xbow_widget_present(xbow_t *, int);
+static int              xbow_link_alive(xbow_t *, int);
+devfs_handle_t            xbow_widget_lookup(devfs_handle_t, int);
+
+void                    xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
+
+
+
+void                    xbow_update_perf_counters(devfs_handle_t);
+xbow_perf_link_t       *xbow_get_perf_counters(devfs_handle_t);
+int                     xbow_enable_perf_counter(devfs_handle_t, int, int, int);
+xbow_link_status_t     *xbow_get_llp_status(devfs_handle_t);
+void                    xbow_update_llp_status(devfs_handle_t);
+
+int                     xbow_disable_llp_monitor(devfs_handle_t);
+int                     xbow_enable_llp_monitor(devfs_handle_t);
+int                     xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t,
+                                unsigned long long, unsigned long long);
+static void		xbow_setwidint(xtalk_intr_t);
+void                    idbg_xbowregs(int64_t);
+
+xswitch_reset_link_f    xbow_reset_link;
+
+xswitch_provider_t      xbow_provider =
+{
+    xbow_reset_link,
+};
+
+/*
+ * This is the file operation table for the pcibr driver.
+ * As each of the functions are implemented, put the
+ * appropriate function name below.
+ */
+static int xbow_mmap(struct file * file, struct vm_area_struct * vma);
+struct file_operations xbow_fops = {
+        owner:  THIS_MODULE,
+        llseek: NULL,
+        read: NULL,
+        write: NULL,
+        readdir: NULL,
+        poll: NULL,
+        ioctl: NULL,
+        mmap: xbow_mmap,
+        open: xbow_open,
+        flush: NULL,
+        release: NULL,
+        fsync: NULL,
+        fasync: NULL,
+        lock: NULL,
+        readv: NULL,
+        writev: NULL,
+        sendpage: NULL,
+        get_unmapped_area: NULL
+};
+
+static int
+xbow_mmap(struct file * file, struct vm_area_struct * vma)
+{
+        unsigned long           phys_addr;
+        int                     error = 0;
+
+        phys_addr = (unsigned long)file->private_data & ~0xc000000000000000; /* Mask out the Uncache bits */
+        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+        vma->vm_flags |= VM_RESERVED | VM_IO;
+        error = io_remap_page_range(vma, vma->vm_start, phys_addr,
+                                   vma->vm_end - vma->vm_start,
+                                   vma->vm_page_prot);
+        return(error);
+}
+
+
+/*
+ *    xbow_mlreset: called at mlreset time if the
+ *      platform specific code determines that there is
+ *      a crossbow in a critical path that must be
+ *      functional before the driver would normally get
+ *      the device properly set up.
+ *
+ *      what do we need to do, that the boot prom can
+ *      not be counted on to have already done, that is
+ *      generic across all platforms using crossbows?
+ */
+/*ARGSUSED */
+void
+xbow_mlreset(xbow_t * xbow)
+{
+}
+
+/*
+ *    xbow_init: called with the rest of the device
+ *      driver XXX_init routines. This platform *might*
+ *      have a Crossbow chip, or even several, but it
+ *      might have none. Register with the crosstalk
+ *      generic provider so when we encounter the chip
+ *      the right magic happens.
+ */
+void
+xbow_init(void)
+{
+
+#if DEBUG && ATTACH_DEBUG
+    printk("xbow_init\n");
+#endif
+
+    xwidget_driver_register(PXBOW_WIDGET_PART_NUM,
+			    0, /* XXBOW_WIDGET_MFGR_NUM, */
+			    "xbow_",
+			    CDL_PRI_HI);	/* attach before friends */
+
+
+    xwidget_driver_register(XXBOW_WIDGET_PART_NUM,
+			    0, /* XXBOW_WIDGET_MFGR_NUM, */
+			    "xbow_",
+			    CDL_PRI_HI);	/* attach before friends */
+
+    xwidget_driver_register(XBOW_WIDGET_PART_NUM,
+			    XBOW_WIDGET_MFGR_NUM,
+			    "xbow_",
+			    CDL_PRI_HI);	/* attach before friends */
+}
+
+#ifdef XBRIDGE_REGS_SIM
+/*    xbow_set_simulated_regs: sets xbow regs as needed
+ *	for powering through the boot
+ */
+void
+xbow_set_simulated_regs(xbow_t *xbow, int port)
+{
+    /*
+     * turn on link
+     */
+    xbow->xb_link(port).link_status = (1<<31);
+    /*
+     * and give it a live widget too
+     */
+    xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT;
+    /*
+     * zero the link control reg
+     */
+    xbow->xb_link(port).link_control = 0x0;
+}
+#endif /* XBRIDGE_REGS_SIM */
+
+/*
+ *    xbow_attach: the crosstalk provider has
+ *      determined that there is a crossbow widget
+ *      present, and has handed us the connection
+ *      point for that vertex.
+ *
+ *      We not only add our own vertex, but add
+ *      some "xtalk switch" data to the switch
+ *      vertex (at the connect point's parent) if
+ *      it does not have any.
+ */
+
+/*ARGSUSED */
+int
+xbow_attach(devfs_handle_t conn)
+{
+    /*REFERENCED */
+    devfs_handle_t            vhdl;
+    devfs_handle_t            busv;
+    xbow_t                 *xbow;
+    xbow_soft_t             soft;
+    int                     port;
+    xswitch_info_t          info;
+    xtalk_intr_t            intr_hdl;
+    char                    devnm[MAXDEVNAME], *s;
+    xbowreg_t               id;
+    int                     rev;
+    int			    i;
+    int			    xbow_num;
+    static void xbow_errintr_handler(int, void *, struct pt_regs *);
+
+	
+#if DEBUG && ATTACH_DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk("%v: xbow_attach\n", conn);
+#else
+    printk("0x%x: xbow_attach\n", conn);
+#endif
+#endif
+
+    /*
+     * Get a PIO pointer to the base of the crossbow
+     * chip.
+     */
+#ifdef XBRIDGE_REGS_SIM
+    printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_s\n", sizeof(xbow_t));
+    xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL);
+    /*
+     * turn on ports e and f like in a real live ibrick
+     */
+    xbow_set_simulated_regs(xbow, 0xe);
+    xbow_set_simulated_regs(xbow, 0xf);
+#else
+    xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0);
+#endif /* XBRIDGE_REGS_SIM */
+
+    /*
+     * Locate the "switch" vertex: it is the parent
+     * of our connection point.
+     */
+    busv = hwgraph_connectpt_get(conn);
+#if DEBUG && ATTACH_DEBUG
+    printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow);
+#endif
+
+    ASSERT(busv != GRAPH_VERTEX_NONE);
+
+    /*
+     * Create our private vertex, and connect our
+     * driver information to it. This makes it possible
+     * for diagnostic drivers to open the crossbow
+     * vertex for access to registers.
+     */
+
+    /*
+     * Register a xbow driver with devfs.
+     * file ops.
+     */
+    vhdl = NULL;
+    vhdl = devfs_register(conn, EDGE_LBL_XBOW,
+		DEVFS_FL_AUTO_DEVNUM, 0, 0,
+		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+		&xbow_fops, (void *)xbow);
+    if (!vhdl) {
+        printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n",
+                (void *)conn);
+    }
+
+    /*
+     * Allocate the soft state structure and attach
+     * it to the xbow's vertex
+     */
+    NEW(soft);
+    soft->conn = conn;
+    soft->vhdl = vhdl;
+    soft->busv = busv;
+    soft->base = xbow;
+    /* does the universe really need another macro?  */
+    /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */
+    /* hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); */
+
+#define XBOW_NUM_SUFFIX_FORMAT	"[xbow# %d]"
+
+    /* Add xbow number as a suffix to the hwgraph name of the xbow.
+     * This is helpful while looking at the error/warning messages.
+     */
+    xbow_num = 0;
+
+    /*
+     * get the name of this xbow vertex and keep the info.
+     * This is needed during errors and interupts, but as
+     * long as we have it, we can use it elsewhere.
+     */
+    s = dev_to_name(vhdl, devnm, MAXDEVNAME);
+    soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, 
+			    GFP_KERNEL);
+    sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num);
+
+#ifdef XBRIDGE_REGS_SIM
+    /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined
+     * as 0xd000, so I'm using that for the partnum bitfield.
+     */
+    printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!\n");
+    id = 0x2d000049;
+#else
+    id = xbow->xb_wid_id;
+#endif /* XBRIDGE_REGS_SIM */
+    rev = XWIDGET_PART_REV_NUM(id);
+
+    mutex_spinlock_init(&soft->xbow_perf_lock);
+    soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;
+    soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;
+
+    /* Initialization for GBR bw allocation */
+    mutex_spinlock_init(&soft->xbow_bw_alloc_lock);
+
+#define	XBOW_8_BIT_PORT_BW_MAX		(400 * 1000 * 1000)	/* 400 MB/s */
+#define XBOW_16_BIT_PORT_BW_MAX		(800 * 1000 * 1000)	/* 800 MB/s */
+
+    /* Set bandwidth hiwatermark and current values */
+    for (i = 0; i < MAX_XBOW_PORTS; i++) {
+	soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX;	/* for now */
+	soft->bw_cur_used[i] = 0;
+    }
+
+     /*
+      * attach the crossbow error interrupt.
+      */
+     intr_hdl = xtalk_intr_alloc(conn, (device_desc_t)0, vhdl);
+     ASSERT(intr_hdl != NULL);
+ 
+     xtalk_intr_connect(intr_hdl,
+                        (intr_func_t) xbow_errintr_handler,
+                        (intr_arg_t) soft,
+                        (xtalk_intr_setfunc_t) xbow_setwidint,
+                        (void *) xbow);
+
+     request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid,
+			((hub_intr_t)intr_hdl)->i_bit),
+			(intr_func_t)xbow_errintr_handler, 0, "XBOW error",
+			(intr_arg_t) soft);
+
+#ifdef BUS_INT_WAR_NOT_YET
+    {
+	void sn_add_polled_interrupt(int, int);
+        sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid,
+                                ((hub_intr_t)intr_hdl)->i_bit), 5000);
+    }
+#endif
+
+ 
+    /*
+     * Enable xbow error interrupts
+     */
+    xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE | XB_WID_CTRL_XTALK_IE);
+
+    /*
+     * take a census of the widgets present,
+     * leaving notes at the switch vertex.
+     */
+    info = xswitch_info_new(busv);
+
+    for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
+	 port < MAX_PORT_NUM; ++port) {
+	if (!xbow_link_alive(xbow, port)) {
+#if DEBUG && XBOW_DEBUG
+	    printk(KERN_INFO "0x%p link %d is not alive\n",
+		    (void *)busv, port);
+#endif
+	    continue;
+	}
+	if (!xbow_widget_present(xbow, port)) {
+#if DEBUG && XBOW_DEBUG
+	    printk(KERN_INFO "0x%p link %d is alive but no widget is present\n", (void *)busv, port);
+#endif
+	    continue;
+	}
+#if DEBUG && XBOW_DEBUG
+	printk(KERN_INFO "0x%p link %d has a widget\n",
+		(void *)busv, port);
+#endif
+
+	xswitch_info_link_is_ok(info, port);
+	/*
+	 * Turn some error interrupts on
+	 * and turn others off. The PROM has
+	 * some things turned on we don't
+	 * want to see (bandwidth allocation
+	 * errors for instance); so if it
+	 * is not listed here, it is not on.
+	 */
+	xbow->xb_link(port).link_control =
+	    ( (xbow->xb_link(port).link_control
+	/*
+	 * Turn off these bits; they are non-fatal,
+	 * but we might want to save some statistics
+	 * on the frequency of these errors.
+	 * XXX FIXME XXX
+	 */
+	    & ~XB_CTRL_RCV_CNT_OFLOW_IE
+	    & ~XB_CTRL_XMT_CNT_OFLOW_IE
+	    & ~XB_CTRL_BNDWDTH_ALLOC_IE
+	    & ~XB_CTRL_RCV_IE)
+	/*
+	 * These are the ones we want to turn on.
+	 */
+	    | (XB_CTRL_ILLEGAL_DST_IE
+	    | XB_CTRL_OALLOC_IBUF_IE
+	    | XB_CTRL_XMT_MAX_RTRY_IE
+	    | XB_CTRL_MAXREQ_TOUT_IE
+	    | XB_CTRL_XMT_RTRY_IE
+	    | XB_CTRL_SRC_TOUT_IE) );
+    }
+
+    xswitch_provider_register(busv, &xbow_provider);
+
+    return 0;				/* attach successful */
+}
+
+/*ARGSUSED */
+int
+xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp)
+{
+    return 0;
+}
+
+/*ARGSUSED */
+int
+xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp)
+{
+    return 0;
+}
+
+/*ARGSUSED */
+int
+xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot)
+{
+    devfs_handle_t            vhdl = dev_to_vhdl(dev);
+    xbow_soft_t             soft = xbow_soft_get(vhdl);
+    int                     error;
+
+    ASSERT(soft);
+    len = ctob(btoc(len));
+    /* XXX- this ignores the offset!!! */
+    error = v_mapphys(vt, (void *) soft->base, len);
+    return error;
+}
+
+/*ARGSUSED */
+int
+xbow_unmap(devfs_handle_t dev, vhandl_t *vt)
+{
+    return 0;
+}
+
+/* This contains special-case code for grio. There are plans to make
+ * this general sometime in the future, but till then this should
+ * be good enough.
+ */
+xwidgetnum_t
+xbow_widget_num_get(devfs_handle_t dev)
+{
+	devfs_handle_t	tdev;
+	char		devname[MAXDEVNAME];
+	xwidget_info_t	xwidget_info;
+	int		i;
+
+	vertex_to_name(dev, devname, MAXDEVNAME);
+
+	/* If this is a pci controller vertex, traverse up using
+	 * the ".." links to get to the widget.
+	 */
+	if (strstr(devname, EDGE_LBL_PCI) &&
+			strstr(devname, EDGE_LBL_CONTROLLER)) {
+		tdev = dev;
+		for (i=0; i< 2; i++) {
+			if (hwgraph_edge_get(tdev,
+				HWGRAPH_EDGELBL_DOTDOT, &tdev) !=
+					GRAPH_SUCCESS)
+				return XWIDGET_NONE;
+		}
+
+		if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) {
+			return (xwidget_info_id_get(xwidget_info));
+		} else {
+			return XWIDGET_NONE;
+		}
+	}
+
+	return XWIDGET_NONE;
+}
+
+int
+xbow_ioctl(devfs_handle_t dev,
+	   int cmd,
+	   void *arg,
+	   int flag,
+	   struct cred *cr,
+	   int *rvalp)
+{
+    devfs_handle_t            vhdl;
+    int                     error = 0;
+
+#if defined (DEBUG)
+    int                     rc;
+    devfs_handle_t            conn;
+    struct xwidget_info_s  *xwidget_info;
+    xbow_soft_t             xbow_soft;
+#endif
+    *rvalp = 0;
+
+    vhdl = dev_to_vhdl(dev);
+#if defined (DEBUG)
+    xbow_soft = xbow_soft_get(vhdl);
+    conn = xbow_soft->conn;
+
+    xwidget_info = xwidget_info_get(conn);
+    ASSERT_ALWAYS(xwidget_info != NULL);
+
+    rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid);
+    ASSERT_ALWAYS(rc != 0);
+#endif
+    switch (cmd) {
+
+    case XBOWIOC_LLP_ERROR_ENABLE:
+	if ((error = xbow_enable_llp_monitor(vhdl)) != 0)
+	    error = EINVAL;
+
+	break;
+
+    case XBOWIOC_LLP_ERROR_DISABLE:
+
+	if ((error = xbow_disable_llp_monitor(vhdl)) != 0)
+	    error = EINVAL;
+
+	break;
+
+    default:
+	break;
+
+    }
+    return error;
+}
+
+/*
+ * xbow_widget_present: See if a device is present
+ * on the specified port of this crossbow.
+ */
+int
+xbow_widget_present(xbow_t *xbow, int port)
+{
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		if ( (port == 14) || (port == 15) ) {
+			return 1;
+		}
+		else {
+			return 0;
+		}
+	}
+	else {
+		/* WAR: port 0xf on PIC is missing present bit */
+		if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&
+					IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) {
+			return 1;
+		}
+		return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT;
+	}
+}
+
+static int
+xbow_link_alive(xbow_t * xbow, int port)
+{
+    xbwX_stat_t             xbow_linkstat;
+
+    xbow_linkstat.linkstatus = xbow->xb_link(port).link_status;
+    return (xbow_linkstat.link_alive);
+}
+
+/*
+ * xbow_widget_lookup
+ *      Lookup the edges connected to the xbow specified, and
+ *      retrieve the handle corresponding to the widgetnum
+ *      specified.
+ *      If not found, return 0.
+ */
+devfs_handle_t
+xbow_widget_lookup(devfs_handle_t vhdl,
+		   int widgetnum)
+{
+    xswitch_info_t          xswitch_info;
+    devfs_handle_t            conn;
+
+    xswitch_info = xswitch_info_get(vhdl);
+    conn = xswitch_info_vhdl_get(xswitch_info, widgetnum);
+    return conn;
+}
+
+/*
+ * xbow_setwidint: called when xtalk
+ * is establishing or migrating our
+ * interrupt service.
+ */
+static void
+xbow_setwidint(xtalk_intr_t intr)
+{
+    xwidgetnum_t            targ = xtalk_intr_target_get(intr);
+    iopaddr_t               addr = xtalk_intr_addr_get(intr);
+    xtalk_intr_vector_t     vect = xtalk_intr_vector_get(intr);
+    xbow_t                 *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr);
+
+    xbow_intr_preset((void *) xbow, 0, targ, addr, vect);
+}
+
+/*
+ * xbow_intr_preset: called during mlreset time
+ * if the platform specific code needs to route
+ * an xbow interrupt before the xtalk infrastructure
+ * is available for use.
+ *
+ * Also called from xbow_setwidint, so we don't
+ * replicate the guts of the routine.
+ *
+ * XXX- probably should be renamed xbow_wid_intr_set or
+ * something to reduce confusion.
+ */
+/*ARGSUSED3 */
+void
+xbow_intr_preset(void *which_widget,
+		 int which_widget_intr,
+		 xwidgetnum_t targ,
+		 iopaddr_t addr,
+		 xtalk_intr_vector_t vect)
+{
+    xbow_t                 *xbow = (xbow_t *) which_widget;
+
+    xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) |
+			      (0x000F0000 & (targ << 16)) |
+			      XTALK_ADDR_TO_UPPER(addr));
+    xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
+
+}
+
+#define	XEM_ADD_STR(s)		printk("%s", (s))
+#define	XEM_ADD_NVAR(n,v)	printk("\t%20s: 0x%llx\n", (n), ((unsigned long long)v))
+#define	XEM_ADD_VAR(v)		XEM_ADD_NVAR(#v,(v))
+#define XEM_ADD_IOEF(p,n)	if (IOERROR_FIELDVALID(ioe,n)) {	\
+				    IOERROR_GETVALUE(p,ioe,n);		\
+				    XEM_ADD_NVAR("ioe." #n, p);		\
+				}
+
+#ifdef LATER
+static void
+xem_add_ioe(ioerror_t *ioe)
+{
+    union tmp {
+	ushort stmp;
+	unsigned long long lltmp;
+	cpuid_t cputmp;
+	cnodeid_t cntmp;
+	iopaddr_t iotmp;
+	caddr_t catmp;
+	paddr_t patmp;
+    } tmp;
+
+    XEM_ADD_IOEF(tmp.stmp, errortype);
+    XEM_ADD_IOEF(tmp.stmp, widgetnum);
+    XEM_ADD_IOEF(tmp.stmp, widgetdev);
+    XEM_ADD_IOEF(tmp.cputmp, srccpu);
+    XEM_ADD_IOEF(tmp.cntmp, srcnode);
+    XEM_ADD_IOEF(tmp.cntmp, errnode);
+    XEM_ADD_IOEF(tmp.iotmp, sysioaddr);
+    XEM_ADD_IOEF(tmp.iotmp, xtalkaddr);
+    XEM_ADD_IOEF(tmp.iotmp, busspace);
+    XEM_ADD_IOEF(tmp.iotmp, busaddr);
+    XEM_ADD_IOEF(tmp.catmp, vaddr);
+    XEM_ADD_IOEF(tmp.patmp, memaddr);
+    XEM_ADD_IOEF(tmp.catmp, epc);
+    XEM_ADD_IOEF(tmp.catmp, ef);
+    XEM_ADD_IOEF(tmp.stmp, tnum);
+}
+
+#define XEM_ADD_IOE()   (xem_add_ioe(ioe))
+#endif	/* LATER */
+
+int                     xbow_xmit_retry_errors = 0;
+
+int
+xbow_xmit_retry_error(xbow_soft_t soft,
+		      int port)
+{
+    xswitch_info_t          info;
+    devfs_handle_t            vhdl;
+    widget_cfg_t           *wid;
+    widgetreg_t             id;
+    int                     part;
+    int                     mfgr;
+
+    wid = soft->wpio[port - BASE_XBOW_PORT];
+    if (wid == NULL) {
+	/* If we can't track down a PIO
+	 * pointer to our widget yet,
+	 * leave our caller knowing that
+	 * we are interested in this
+	 * interrupt if it occurs in
+	 * the future.
+	 */
+	info = xswitch_info_get(soft->busv);
+	if (!info)
+	    return 1;
+	vhdl = xswitch_info_vhdl_get(info, port);
+	if (vhdl == GRAPH_VERTEX_NONE)
+	    return 1;
+	wid = (widget_cfg_t *) xtalk_piotrans_addr
+	    (vhdl, 0, 0, sizeof *wid, 0);
+	if (!wid)
+	    return 1;
+	soft->wpio[port - BASE_XBOW_PORT] = wid;
+    }
+    id = wid->w_id;
+    part = XWIDGET_PART_NUM(id);
+    mfgr = XWIDGET_MFG_NUM(id);
+
+    /* If this thing is not a Bridge,
+     * do not activate the WAR, and
+     * tell our caller we do not need
+     * to be called again.
+     */
+    if ((part != BRIDGE_WIDGET_PART_NUM) ||
+	(mfgr != BRIDGE_WIDGET_MFGR_NUM)) {
+		/* FIXME: add Xbridge to the WAR.
+		 * Shouldn't hurt anything.  Later need to
+		 * check if we can remove this.
+                 */
+    		if ((part != XBRIDGE_WIDGET_PART_NUM) ||
+		    (mfgr != XBRIDGE_WIDGET_MFGR_NUM))
+			return 0;
+    }
+
+    /* count how many times we
+     * have picked up after
+     * LLP Transmit problems.
+     */
+    xbow_xmit_retry_errors++;
+
+    /* rewrite the control register
+     * to fix things up.
+     */
+    wid->w_control = wid->w_control;
+    wid->w_control;
+
+    return 1;
+}
+
+/*
+ * xbow_errintr_handler will be called if the xbow
+ * sends an interrupt request to report an error.
+ */
+static void
+xbow_errintr_handler(int irq, void *arg, struct pt_regs *ep)
+{
+    ioerror_t               ioe[1];
+    xbow_soft_t             soft = (xbow_soft_t) arg;
+    xbow_t                 *xbow = soft->base;
+    xbowreg_t               wid_control;
+    xbowreg_t               wid_stat;
+    xbowreg_t               wid_err_cmdword;
+    xbowreg_t               wid_err_upper;
+    xbowreg_t               wid_err_lower;
+    w_err_cmd_word_u        wid_err;
+    unsigned long long      wid_err_addr;
+
+    int                     fatal = 0;
+    int                     dump_ioe = 0;
+    static int xbow_error_handler(void *, int, ioerror_mode_t, ioerror_t *);
+
+    wid_control = xbow->xb_wid_control;
+    wid_stat = xbow->xb_wid_stat_clr;
+    wid_err_cmdword = xbow->xb_wid_err_cmdword;
+    wid_err_upper = xbow->xb_wid_err_upper;
+    wid_err_lower = xbow->xb_wid_err_lower;
+    xbow->xb_wid_err_cmdword = 0;
+
+    wid_err_addr = wid_err_lower | (((iopaddr_t) wid_err_upper & WIDGET_ERR_UPPER_ADDR_ONLY) << 32);
+
+    if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) {
+	int                     port;
+
+	wid_err.r = wid_err_cmdword;
+
+	for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
+	     port < MAX_PORT_NUM; port++) {
+	    if (wid_stat & XB_WID_STAT_LINK_INTR(port)) {
+		xb_linkregs_t          *link = &(xbow->xb_link(port));
+		xbowreg_t               link_control = link->link_control;
+		xbowreg_t               link_status = link->link_status_clr;
+		xbowreg_t               link_aux_status = link->link_aux_status;
+		xbowreg_t               link_pend;
+
+		link_pend = link_status & link_control &
+		    (XB_STAT_ILLEGAL_DST_ERR
+		     | XB_STAT_OALLOC_IBUF_ERR
+		     | XB_STAT_RCV_CNT_OFLOW_ERR
+		     | XB_STAT_XMT_CNT_OFLOW_ERR
+		     | XB_STAT_XMT_MAX_RTRY_ERR
+		     | XB_STAT_RCV_ERR
+		     | XB_STAT_XMT_RTRY_ERR
+		     | XB_STAT_MAXREQ_TOUT_ERR
+		     | XB_STAT_SRC_TOUT_ERR
+		    );
+
+		if (link_pend & XB_STAT_ILLEGAL_DST_ERR) {
+		    if (wid_err.f.sidn == port) {
+			IOERROR_INIT(ioe);
+			IOERROR_SETVALUE(ioe, widgetnum, port);
+			IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr);
+			if (IOERROR_HANDLED ==
+			    xbow_error_handler(soft,
+					       IOECODE_DMA,
+					       MODE_DEVERROR,
+					       ioe)) {
+			    link_pend &= ~XB_STAT_ILLEGAL_DST_ERR;
+			} else {
+			    dump_ioe++;
+			}
+		    }
+		}
+		/* Xbow/Bridge WAR:
+		 * if the bridge signals an LLP Transmitter Retry,
+		 * rewrite its control register.
+		 * If someone else triggers this interrupt,
+		 * ignore (and disable) the interrupt.
+		 */
+		if (link_pend & XB_STAT_XMT_RTRY_ERR) {
+		    if (!xbow_xmit_retry_error(soft, port)) {
+			link_control &= ~XB_CTRL_XMT_RTRY_IE;
+			link->link_control = link_control;
+			link->link_control;	/* stall until written */
+		    }
+		    link_pend &= ~XB_STAT_XMT_RTRY_ERR;
+		}
+		if (link_pend) {
+		    devfs_handle_t	xwidget_vhdl;
+		    char		*xwidget_name;
+		    
+		    /* Get the widget name corresponding to the current
+		     * xbow link.
+		     */
+		    xwidget_vhdl = xbow_widget_lookup(soft->busv,port);
+		    xwidget_name = xwidget_name_get(xwidget_vhdl);
+
+		    printk("%s port %X[%s] XIO Bus Error",
+			    soft->name, port, xwidget_name);
+		    if (link_status & XB_STAT_MULTI_ERR)
+			XEM_ADD_STR("\tMultiple Errors\n");
+		    if (link_status & XB_STAT_ILLEGAL_DST_ERR)
+			XEM_ADD_STR("\tInvalid Packet Destination\n");
+		    if (link_status & XB_STAT_OALLOC_IBUF_ERR)
+			XEM_ADD_STR("\tInput Overallocation Error\n");
+		    if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR)
+			XEM_ADD_STR("\tLLP receive error counter overflow\n");
+		    if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR)
+			XEM_ADD_STR("\tLLP transmit retry counter overflow\n");
+		    if (link_status & XB_STAT_XMT_MAX_RTRY_ERR)
+			XEM_ADD_STR("\tLLP Max Transmitter Retry\n");
+		    if (link_status & XB_STAT_RCV_ERR)
+			XEM_ADD_STR("\tLLP Receiver error\n");
+		    if (link_status & XB_STAT_XMT_RTRY_ERR)
+			XEM_ADD_STR("\tLLP Transmitter Retry\n");
+		    if (link_status & XB_STAT_MAXREQ_TOUT_ERR)
+			XEM_ADD_STR("\tMaximum Request Timeout\n");
+		    if (link_status & XB_STAT_SRC_TOUT_ERR)
+			XEM_ADD_STR("\tSource Timeout Error\n");
+
+		    {
+			int                     other_port;
+
+			for (other_port = 8; other_port < 16; ++other_port) {
+			    if (link_aux_status & (1 << other_port)) {
+				/* XXX- need to go to "other_port"
+				 * and clean up after the timeout?
+				 */
+				XEM_ADD_VAR(other_port);
+			    }
+			}
+		    }
+
+#if !DEBUG
+		    if (kdebug) {
+#endif
+			XEM_ADD_VAR(link_control);
+			XEM_ADD_VAR(link_status);
+			XEM_ADD_VAR(link_aux_status);
+
+#ifdef LATER
+			if (dump_ioe) {
+			    XEM_ADD_IOE();
+			    dump_ioe = 0;
+			}
+#endif
+#if !DEBUG
+		    }
+#endif
+		    fatal++;
+		}
+	    }
+	}
+    }
+    if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) {
+	/* we have a "widget zero" problem */
+
+	if (wid_stat & (XB_WID_STAT_MULTI_ERR
+			| XB_WID_STAT_XTALK_ERR
+			| XB_WID_STAT_REG_ACC_ERR)) {
+
+	    printk("%s Port 0 XIO Bus Error",
+		    soft->name);
+	    if (wid_stat & XB_WID_STAT_MULTI_ERR)
+		XEM_ADD_STR("\tMultiple Error\n");
+	    if (wid_stat & XB_WID_STAT_XTALK_ERR)
+		XEM_ADD_STR("\tXIO Error\n");
+	    if (wid_stat & XB_WID_STAT_REG_ACC_ERR)
+		XEM_ADD_STR("\tRegister Access Error\n");
+
+	    fatal++;
+	}
+    }
+    if (fatal) {
+	XEM_ADD_VAR(wid_stat);
+	XEM_ADD_VAR(wid_control);
+	XEM_ADD_VAR(wid_err_cmdword);
+	XEM_ADD_VAR(wid_err_upper);
+	XEM_ADD_VAR(wid_err_lower);
+	XEM_ADD_VAR(wid_err_addr);
+	PRINT_PANIC("XIO Bus Error");
+    }
+}
+
+/*
+ * XBOW ERROR Handling routines.
+ * These get invoked as part of walking down the error handling path
+ * from hub/heart towards the I/O device that caused the error.
+ */
+
+/*
+ * xbow_error_handler
+ *      XBow error handling dispatch routine.
+ *      This is the primary interface used by external world to invoke
+ *      in case of an error related to a xbow.
+ *      Only functionality in this layer is to identify the widget handle
+ *      given the widgetnum. Otherwise, xbow does not gathers any error
+ *      data.
+ */
+static int
+xbow_error_handler(
+		      void *einfo,
+		      int error_code,
+		      ioerror_mode_t mode,
+		      ioerror_t *ioerror)
+{
+    int                     retval = IOERROR_WIDGETLEVEL;
+
+    xbow_soft_t             soft = (xbow_soft_t) einfo;
+    int                     port;
+    devfs_handle_t          conn;
+    devfs_handle_t          busv;
+
+    xbow_t                 *xbow = soft->base;
+    xbowreg_t               wid_stat;
+    xbowreg_t               wid_err_cmdword;
+    xbowreg_t               wid_err_upper;
+    xbowreg_t               wid_err_lower;
+    unsigned long long      wid_err_addr;
+
+    xb_linkregs_t          *link;
+    xbowreg_t               link_control;
+    xbowreg_t               link_status;
+    xbowreg_t               link_aux_status;
+
+    ASSERT(soft != 0);
+    busv = soft->busv;
+
+#if DEBUG && ERROR_DEBUG
+    printk("%s: xbow_error_handler\n", soft->name, busv);
+#endif
+
+    IOERROR_GETVALUE(port, ioerror, widgetnum);
+
+    if (port == 0) {
+	/* error during access to xbow:
+	 * do NOT attempt to access xbow regs.
+	 */
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	if (error_code & IOECODE_DMA) {
+	    printk(KERN_ALERT
+		    "DMA error blamed on Crossbow at %s\n"
+		    "\tbut Crosbow never initiates DMA!",
+		    soft->name);
+	}
+	if (error_code & IOECODE_PIO) {
+	    iopaddr_t tmp;
+	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	    printk(KERN_ALERT "PIO Error on XIO Bus %s\n"
+		    "\tattempting to access XIO controller\n"
+		    "\twith offset 0x%lx",
+		    soft->name, tmp);
+	}
+	/* caller will dump contents of ioerror
+	 * in DEBUG and kdebug kernels.
+	 */
+
+	return retval;
+    }
+    /*
+     * error not on port zero:
+     * safe to read xbow registers.
+     */
+    wid_stat = xbow->xb_wid_stat;
+    wid_err_cmdword = xbow->xb_wid_err_cmdword;
+    wid_err_upper = xbow->xb_wid_err_upper;
+    wid_err_lower = xbow->xb_wid_err_lower;
+
+    wid_err_addr =
+	wid_err_lower
+	| (((iopaddr_t) wid_err_upper
+	    & WIDGET_ERR_UPPER_ADDR_ONLY)
+	   << 32);
+
+    if ((port < BASE_XBOW_PORT) ||
+	(port >= MAX_PORT_NUM)) {
+
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	if (error_code & IOECODE_DMA) {
+	    printk(KERN_ALERT
+		    "DMA error blamed on XIO port at %s/%d\n"
+		    "\tbut Crossbow does not support that port",
+		    soft->name, port);
+	}
+	if (error_code & IOECODE_PIO) {
+	    iopaddr_t tmp;
+	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	    printk(KERN_ALERT
+		    "PIO Error on XIO Bus %s\n"
+		    "\tattempting to access XIO port %d\n"
+		    "\t(which Crossbow does not support)"
+		    "\twith offset 0x%lx",
+		    soft->name, port, tmp);
+	}
+#if !DEBUG
+	if (kdebug) {
+#endif
+	    XEM_ADD_STR("Raw status values for Crossbow:\n");
+	    XEM_ADD_VAR(wid_stat);
+	    XEM_ADD_VAR(wid_err_cmdword);
+	    XEM_ADD_VAR(wid_err_upper);
+	    XEM_ADD_VAR(wid_err_lower);
+	    XEM_ADD_VAR(wid_err_addr);
+#if !DEBUG
+	}
+#endif
+
+	/* caller will dump contents of ioerror
+	 * in DEBUG and kdebug kernels.
+	 */
+
+	return retval;
+    }
+    /* access to valid port:
+     * ok to check port status.
+     */
+
+    link = &(xbow->xb_link(port));
+    link_control = link->link_control;
+    link_status = link->link_status;
+    link_aux_status = link->link_aux_status;
+
+    /* Check that there is something present
+     * in that XIO port.
+     */
+    /* WAR: PIC widget 0xf is missing prescense bit */
+    if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&
+		IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xf))
+		;
+    else
+    if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {
+	/* nobody connected. */
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	if (error_code & IOECODE_DMA) {
+	    printk(KERN_ALERT
+		    "DMA error blamed on XIO port at %s/%d\n"
+		    "\tbut there is no device connected there.",
+		    soft->name, port);
+	}
+	if (error_code & IOECODE_PIO) {
+	    iopaddr_t tmp;
+	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	    printk(KERN_ALERT
+		    "PIO Error on XIO Bus %s\n"
+		    "\tattempting to access XIO port %d\n"
+		    "\t(which has no device connected)"
+		    "\twith offset 0x%lx",
+		    soft->name, port, tmp);
+	}
+#if !DEBUG
+	if (kdebug) {
+#endif
+	    XEM_ADD_STR("Raw status values for Crossbow:\n");
+	    XEM_ADD_VAR(wid_stat);
+	    XEM_ADD_VAR(wid_err_cmdword);
+	    XEM_ADD_VAR(wid_err_upper);
+	    XEM_ADD_VAR(wid_err_lower);
+	    XEM_ADD_VAR(wid_err_addr);
+	    XEM_ADD_VAR(port);
+	    XEM_ADD_VAR(link_control);
+	    XEM_ADD_VAR(link_status);
+	    XEM_ADD_VAR(link_aux_status);
+#if !DEBUG
+	}
+#endif
+	return retval;
+
+    }
+    /* Check that the link is alive.
+     */
+    if (!(link_status & XB_STAT_LINKALIVE)) {
+	iopaddr_t tmp;
+	/* nobody connected. */
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	printk(KERN_ALERT
+		"%s%sError on XIO Bus %s port %d",
+		(error_code & IOECODE_DMA) ? "DMA " : "",
+		(error_code & IOECODE_PIO) ? "PIO " : "",
+		soft->name, port);
+
+	IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	if ((error_code & IOECODE_PIO) &&
+	    (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
+		printk("\tAccess attempted to offset 0x%lx\n", tmp);
+	}
+	if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD)
+	    XEM_ADD_STR("\tLink never came out of reset\n");
+	else
+	    XEM_ADD_STR("\tLink failed while transferring data\n");
+
+    }
+    /* get the connection point for the widget
+     * involved in this error; if it exists and
+     * is not our connectpoint, cycle back through
+     * xtalk_error_handler to deliver control to
+     * the proper handler (or to report a generic
+     * crosstalk error).
+     *
+     * If the downstream handler won't handle
+     * the problem, we let our upstream caller
+     * deal with it, after (in DEBUG and kdebug
+     * kernels) dumping the xbow state for this
+     * port.
+     */
+    conn = xbow_widget_lookup(busv, port);
+    if ((conn != GRAPH_VERTEX_NONE) &&
+	(conn != soft->conn)) {
+	retval = xtalk_error_handler(conn, error_code, mode, ioerror);
+	if (retval == IOERROR_HANDLED)
+	    return IOERROR_HANDLED;
+    }
+    if (mode == MODE_DEVPROBE)
+	return IOERROR_HANDLED;
+
+    if (retval == IOERROR_UNHANDLED) {
+	iopaddr_t tmp;
+	retval = IOERROR_PANIC;
+
+	printk(KERN_ALERT
+		"%s%sError on XIO Bus %s port %d",
+		(error_code & IOECODE_DMA) ? "DMA " : "",
+		(error_code & IOECODE_PIO) ? "PIO " : "",
+		soft->name, port);
+
+	IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	if ((error_code & IOECODE_PIO) &&
+	    (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
+	    printk("\tAccess attempted to offset 0x%lx\n", tmp);
+	}
+    }
+
+#if !DEBUG
+    if (kdebug) {
+#endif
+	XEM_ADD_STR("Raw status values for Crossbow:\n");
+	XEM_ADD_VAR(wid_stat);
+	XEM_ADD_VAR(wid_err_cmdword);
+	XEM_ADD_VAR(wid_err_upper);
+	XEM_ADD_VAR(wid_err_lower);
+	XEM_ADD_VAR(wid_err_addr);
+	XEM_ADD_VAR(port);
+	XEM_ADD_VAR(link_control);
+	XEM_ADD_VAR(link_status);
+	XEM_ADD_VAR(link_aux_status);
+#if !DEBUG
+    }
+#endif
+    /* caller will dump raw ioerror data
+     * in DEBUG and kdebug kernels.
+     */
+
+    return retval;
+}
+
+void
+xbow_update_perf_counters(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
+    xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;
+    xbow_perfcount_t        perf_reg;
+    unsigned long           s;
+    int                     link, i;
+
+    for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {
+	if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)
+	    continue;
+
+	s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
+
+	perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
+
+	link = perf_reg.xb_perf.link_select;
+
+	(xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] +=
+	    ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK);
+	xbow_perf->xp_current = perf_reg.xb_perf.count;
+
+	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+    }
+}
+
+xbow_perf_link_t       *
+xbow_get_perf_counters(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_perf_link_t       *xbow_perf_link = xbow_soft->xbow_perflink;
+
+    return xbow_perf_link;
+}
+
+int
+xbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
+    xbow_linkctrl_t         xbow_link_ctrl;
+    xbow_t                 *xbow = xbow_soft->base;
+    xbow_perfcount_t        perf_reg;
+    unsigned long           s;
+    int                     i;
+
+    link -= BASE_XBOW_PORT;
+    if ((link < 0) || (link >= MAX_XBOW_PORTS))
+	return -1;
+
+    if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK))
+	return -1;
+
+    if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS))
+	return -1;
+
+    s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
+
+    if ((xbow_perf + counter)->xp_mode && mode) {
+	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+	return -1;
+    }
+    for (i = 0; i < XBOW_PERF_COUNTERS; i++) {
+	if (i == counter)
+	    continue;
+	if (((xbow_perf + i)->xp_link == link) &&
+	    ((xbow_perf + i)->xp_mode)) {
+	    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+	    return -1;
+	}
+    }
+    xbow_perf += counter;
+
+    xbow_perf->xp_curlink = xbow_perf->xp_link = link;
+    xbow_perf->xp_curmode = xbow_perf->xp_mode = mode;
+
+    xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control;
+    xbow_link_ctrl.xb_linkcontrol.perf_mode = mode;
+    xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword;
+
+    perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
+    perf_reg.xb_perf.link_select = link;
+    *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;
+    xbow_perf->xp_current = perf_reg.xb_perf.count;
+
+    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+    return 0;
+}
+
+xbow_link_status_t     *
+xbow_get_llp_status(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
+
+    return xbow_llp_status;
+}
+
+void
+xbow_update_llp_status(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
+    xbow_t                 *xbow;
+    xbwX_stat_t             lnk_sts;
+    xbow_aux_link_status_t  aux_sts;
+    int                     link;
+    devfs_handle_t	    xwidget_vhdl;
+    char		   *xwidget_name;	
+
+    xbow = (xbow_t *) xbow_soft->base;
+    for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) {
+	/* Get the widget name corresponding the current link.
+	 * Note : 0 <= link < MAX_XBOW_PORTS(8).
+	 * 	  BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10)
+	 */
+	xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT);
+	xwidget_name = xwidget_name_get(xwidget_vhdl);
+	aux_sts.aux_linkstatus
+	    = xbow->xb_link_raw[link].link_aux_status;
+	lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr;
+
+	if (lnk_sts.link_alive == 0)
+	    continue;
+
+	xbow_llp_status->rx_err_count +=
+	    aux_sts.xb_aux_linkstatus.rx_err_cnt;
+
+	xbow_llp_status->tx_retry_count +=
+	    aux_sts.xb_aux_linkstatus.tx_retry_cnt;
+
+	if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) {
+#ifdef	LATER
+	    printk(KERN_WARNING  "link %d[%s]: bad status 0x%x\n",
+		    link, xwidget_name, lnk_sts.linkstatus);
+#endif
+	}
+    }
+}
+
+int
+xbow_disable_llp_monitor(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    int                     port;
+
+    for (port = 0; port < MAX_XBOW_PORTS; port++) {
+	xbow_soft->xbow_link_status[port].rx_err_count = 0;
+	xbow_soft->xbow_link_status[port].tx_retry_count = 0;
+    }
+
+    xbow_soft->link_monitor = 0;
+    return 0;
+}
+
+int
+xbow_enable_llp_monitor(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+
+    xbow_soft->link_monitor = 1;
+    return 0;
+}
+
+
+int
+xbow_reset_link(devfs_handle_t xconn_vhdl)
+{
+    xwidget_info_t          widget_info;
+    xwidgetnum_t            port;
+    xbow_t                 *xbow;
+    xbowreg_t               ctrl;
+    xbwX_stat_t             stat;
+    unsigned                itick;
+    unsigned                dtick;
+    static int              ticks_per_ms = 0;
+
+    if (!ticks_per_ms) {
+	itick = get_timestamp();
+	us_delay(1000);
+	ticks_per_ms = get_timestamp() - itick;
+    }
+    widget_info = xwidget_info_get(xconn_vhdl);
+    port = xwidget_info_id_get(widget_info);
+
+#ifdef XBOW_K1PTR			/* defined if we only have one xbow ... */
+    xbow = XBOW_K1PTR;
+#else
+    {
+	devfs_handle_t            xbow_vhdl;
+	xbow_soft_t             xbow_soft;
+
+	hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl);
+	xbow_soft = xbow_soft_get(xbow_vhdl);
+	xbow = xbow_soft->base;
+    }
+#endif
+
+    /*
+     * This requires three PIOs (reset the link, check for the
+     * reset, restore the control register for the link) plus
+     * 10us to wait for the reset. We allow up to 1ms for the
+     * widget to come out of reset before giving up and
+     * returning a failure.
+     */
+    ctrl = xbow->xb_link(port).link_control;
+    xbow->xb_link(port).link_reset = 0;
+    itick = get_timestamp();
+    while (1) {
+	stat.linkstatus = xbow->xb_link(port).link_status;
+	if (stat.link_alive)
+	    break;
+	dtick = get_timestamp() - itick;
+	if (dtick > ticks_per_ms) {
+	    return -1;			/* never came out of reset */
+	}
+	DELAY(2);			/* don't beat on link_status */
+    }
+    xbow->xb_link(port).link_control = ctrl;
+    return 0;
+}
+
+/*
+ * Dump xbow registers.
+ * input parameter is either a pointer to
+ * the xbow chip or the vertex handle for
+ * an xbow vertex.
+ */
+void
+idbg_xbowregs(int64_t regs)
+{
+    xbow_t                 *xbow;
+    int                     i;
+    xb_linkregs_t          *link;
+
+    xbow = (xbow_t *) regs;
+
+#ifdef LATER
+    qprintf("Printing xbow registers starting at 0x%x\n", xbow);
+    qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n",
+	    xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper,
+	    xbow->xb_wid_err_lower, xbow->xb_wid_control,
+	    xbow->xb_wid_req_timeout);
+    qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %x\n",
+	    xbow->xb_wid_int_upper, xbow->xb_wid_int_lower,
+	    xbow->xb_wid_err_cmdword, xbow->xb_wid_llp,
+	    xbow->xb_wid_arb_reload);
+#endif
+
+    for (i = 8; i <= 0xf; i++) {
+	link = &xbow->xb_link(i);
+#ifdef LATER
+	qprintf("Link %d registers\n", i);
+	qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n",
+		link->link_control, link->link_status,
+		link->link_arb_upper, link->link_arb_lower,
+		link->link_aux_status);
+#endif
+    }
+}
+
+
+#define XBOW_ARB_RELOAD_TICKS		25
+					/* granularity: 4 MB/s, max: 124 MB/s */
+#define GRANULARITY			((100 * 1000000) / XBOW_ARB_RELOAD_TICKS)
+
+#define XBOW_BYTES_TO_GBR(BYTES_per_s)	(int) (BYTES_per_s / GRANULARITY)
+
+#define XBOW_GBR_TO_BYTES(cnt)		(bandwidth_t) ((cnt) * GRANULARITY)
+
+#define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec)	\
+			((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr)
+
+#define XBOW_ARB_GBR_MAX		31
+
+#define ABS(x)				((x > 0) ? (x) : (-1 * x))
+					/* absolute value */
+
+int
+xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec)
+{
+    int                     gbr_granted;
+    int                     new_total_gbr;
+    int                     change_gbr;
+    bandwidth_t             new_total_bw;
+
+#ifdef GRIO_DEBUG
+    printk("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lld\n",
+		old_bytes_per_sec, bytes_per_sec);
+#endif	/* GRIO_DEBUG */
+
+    gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)),
+			old_bytes_per_sec);
+    new_total_bw = old_bytes_per_sec + bytes_per_sec;
+    new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)),
+			new_total_bw);
+
+    change_gbr = new_total_gbr - gbr_granted;
+
+#ifdef GRIO_DEBUG
+    printk("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %d\n",
+		gbr_granted, new_total_gbr, change_gbr);
+#endif	/* GRIO_DEBUG */
+
+    return (change_gbr);
+}
+
+/* Conversion from GBR to bytes */
+bandwidth_t
+xbow_gbr_to_bytes(int gbr)
+{
+    return (XBOW_GBR_TO_BYTES(gbr));
+}
+
+/* Given the vhdl for the desired xbow, the src and dest. widget ids
+ * and the req_bw value, this xbow driver entry point accesses the
+ * xbow registers and allocates the desired bandwidth if available.
+ *
+ * If bandwidth allocation is successful, return success else return failure.
+ */
+int
+xbow_prio_bw_alloc(devfs_handle_t vhdl,
+		xwidgetnum_t src_wid,
+		xwidgetnum_t dest_wid,
+		unsigned long long old_alloc_bw,
+		unsigned long long req_bw)
+{
+    xbow_soft_t             soft = xbow_soft_get(vhdl);
+    volatile xbowreg_t     *xreg;
+    xbowreg_t               mask;
+    unsigned long           s;
+    int                     error = 0;
+    bandwidth_t             old_bw_BYTES, req_bw_BYTES;
+    xbowreg_t               old_xreg;
+    int                     old_bw_GBR, req_bw_GBR, new_bw_GBR;
+
+#ifdef GRIO_DEBUG
+    printk("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lld\n",
+		(int) vhdl, (int) src_wid, (int) dest_wid, req_bw);
+#endif
+
+    ASSERT(XBOW_WIDGET_IS_VALID(src_wid));
+    ASSERT(XBOW_WIDGET_IS_VALID(dest_wid));
+
+    s = mutex_spinlock(&soft->xbow_bw_alloc_lock);
+
+    /* Get pointer to the correct register */
+    xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid);
+
+    /* Get mask for GBR count value */
+    mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid);
+
+    req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw);
+    req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR)))
+		: xbow_gbr_to_bytes(req_bw_GBR);
+
+#ifdef GRIO_DEBUG
+    printk("req_bw %lld req_bw_BYTES %lld req_bw_GBR %d\n",
+		req_bw, req_bw_BYTES, req_bw_GBR);
+#endif	/* GRIO_DEBUG */
+
+    old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS];
+    old_xreg = *xreg;
+    old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid));
+
+#ifdef GRIO_DEBUG
+    ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR);
+
+    printk("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR);
+
+    printk("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lld\n",
+		req_bw_BYTES, old_bw_BYTES,
+		soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]);
+	   
+#endif				/* GRIO_DEBUG */
+
+    /* Accept the request only if we don't exceed the destination
+     * port HIWATER_MARK *AND* the max. link GBR arbitration count
+     */
+    if (((old_bw_BYTES + req_bw_BYTES) <=
+		soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) &&
+		(req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) {
+
+	new_bw_GBR = (old_bw_GBR + req_bw_GBR);
+
+	/* Set this in the xbow link register */
+	*xreg = (old_xreg & ~mask) | \
+	    (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask);
+
+	soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] =
+			xbow_gbr_to_bytes(new_bw_GBR);
+    } else {
+	error = 1;
+    }
+
+    mutex_spinunlock(&soft->xbow_bw_alloc_lock, s);
+
+    return (error);
+}
diff -Nru a/arch/ia64/sn/io/sn2/xtalk.c b/arch/ia64/sn/io/sn2/xtalk.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/xtalk.c	Mon Feb 24 05:35:59 2003
@@ -0,0 +1,1087 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/driver.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/xtalk/xtalk_private.h>
+
+/*
+ * Implement crosstalk provider operations.  The xtalk* layer provides a
+ * platform-independent interface for crosstalk devices.  This layer
+ * switches among the possible implementations of a crosstalk adapter.
+ *
+ * On platforms with only one possible xtalk provider, macros can be
+ * set up at the top that cause the table lookups and indirections to
+ * completely disappear.
+ */
+
+#define	NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
+#define	DEL(ptr)	(kfree(ptr))
+
+char                    widget_info_fingerprint[] = "widget_info";
+
+cdl_p                   xtalk_registry = NULL;
+
+#define	DEV_FUNC(dev,func)	hub_##func
+#define	CAST_PIOMAP(x)		((hub_piomap_t)(x))
+#define	CAST_DMAMAP(x)		((hub_dmamap_t)(x))
+#define	CAST_INTR(x)		((hub_intr_t)(x))
+
+/* =====================================================================
+ *            Function Table of Contents
+ */
+xtalk_piomap_t          xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned);
+void                    xtalk_piomap_free(xtalk_piomap_t);
+caddr_t                 xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t);
+void                    xtalk_piomap_done(xtalk_piomap_t);
+caddr_t                 xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned);
+caddr_t                 xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned);
+void                    xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *);
+caddr_t                 xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
+static caddr_t          null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
+xtalk_dmamap_t          xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);
+void                    xtalk_dmamap_free(xtalk_dmamap_t);
+iopaddr_t               xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t);
+alenlist_t              xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned);
+void                    xtalk_dmamap_done(xtalk_dmamap_t);
+iopaddr_t               xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);
+alenlist_t              xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);
+void			xtalk_dmamap_drain(xtalk_dmamap_t);
+void			xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t);
+void			xtalk_dmalist_drain(devfs_handle_t, alenlist_t);
+xtalk_intr_t            xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t);
+xtalk_intr_t            xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t);
+void                    xtalk_intr_free(xtalk_intr_t);
+int                     xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *);
+void                    xtalk_intr_disconnect(xtalk_intr_t);
+devfs_handle_t            xtalk_intr_cpu_get(xtalk_intr_t);
+int                     xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *);
+int                     xtalk_error_devenable(devfs_handle_t, int, int);
+void                    xtalk_provider_startup(devfs_handle_t);
+void                    xtalk_provider_shutdown(devfs_handle_t);
+devfs_handle_t            xtalk_intr_dev_get(xtalk_intr_t);
+xwidgetnum_t            xtalk_intr_target_get(xtalk_intr_t);
+xtalk_intr_vector_t     xtalk_intr_vector_get(xtalk_intr_t);
+iopaddr_t               xtalk_intr_addr_get(struct xtalk_intr_s *);
+void                   *xtalk_intr_sfarg_get(xtalk_intr_t);
+devfs_handle_t            xtalk_pio_dev_get(xtalk_piomap_t);
+xwidgetnum_t            xtalk_pio_target_get(xtalk_piomap_t);
+iopaddr_t               xtalk_pio_xtalk_addr_get(xtalk_piomap_t);
+ulong                   xtalk_pio_mapsz_get(xtalk_piomap_t);
+caddr_t                 xtalk_pio_kvaddr_get(xtalk_piomap_t);
+devfs_handle_t            xtalk_dma_dev_get(xtalk_dmamap_t);
+xwidgetnum_t            xtalk_dma_target_get(xtalk_dmamap_t);
+xwidget_info_t          xwidget_info_chk(devfs_handle_t);
+xwidget_info_t          xwidget_info_get(devfs_handle_t);
+void                    xwidget_info_set(devfs_handle_t, xwidget_info_t);
+devfs_handle_t            xwidget_info_dev_get(xwidget_info_t);
+xwidgetnum_t            xwidget_info_id_get(xwidget_info_t);
+devfs_handle_t            xwidget_info_master_get(xwidget_info_t);
+xwidgetnum_t            xwidget_info_masterid_get(xwidget_info_t);
+xwidget_part_num_t      xwidget_info_part_num_get(xwidget_info_t);
+xwidget_mfg_num_t       xwidget_info_mfg_num_get(xwidget_info_t);
+char 			*xwidget_info_name_get(xwidget_info_t);
+void                    xtalk_init(void);
+void                    xtalk_provider_register(devfs_handle_t, xtalk_provider_t *);
+void                    xtalk_provider_unregister(devfs_handle_t);
+xtalk_provider_t       *xtalk_provider_fns_get(devfs_handle_t);
+int                     xwidget_driver_register(xwidget_part_num_t, 
+						xwidget_mfg_num_t, 
+						char *, unsigned);
+void                    xwidget_driver_unregister(char *);
+int                     xwidget_register(xwidget_hwid_t, devfs_handle_t, 
+					 xwidgetnum_t, devfs_handle_t, 
+					 xwidgetnum_t, async_attach_t);
+int			xwidget_unregister(devfs_handle_t);
+void                    xwidget_reset(devfs_handle_t);
+char			*xwidget_name_get(devfs_handle_t);
+#if !defined(DEV_FUNC)
+/*
+ * There is more than one possible provider
+ * for this platform. We need to examine the
+ * master vertex of the current vertex for
+ * a provider function structure, and indirect
+ * through the appropriately named member.
+ */
+#define	DEV_FUNC(dev,func)	xwidget_to_provider_fns(dev)->func
+#define	CAST_PIOMAP(x)		((xtalk_piomap_t)(x))
+#define	CAST_DMAMAP(x)		((xtalk_dmamap_t)(x))
+#define	CAST_INTR(x)		((xtalk_intr_t)(x))
+
+static xtalk_provider_t *
+xwidget_to_provider_fns(devfs_handle_t xconn)
+{
+    xwidget_info_t          widget_info;
+    xtalk_provider_t       *provider_fns;
+
+    widget_info = xwidget_info_get(xconn);
+    ASSERT(widget_info != NULL);
+
+    provider_fns = xwidget_info_pops_get(widget_info);
+    ASSERT(provider_fns != NULL);
+
+    return (provider_fns);
+}
+#endif
+
+/*
+ * Many functions are not passed their vertex
+ * information directly; rather, they must
+ * dive through a resource map. These macros
+ * are available to coordinate this detail.
+ */
+#define	PIOMAP_FUNC(map,func)	DEV_FUNC(map->xp_dev,func)
+#define	DMAMAP_FUNC(map,func)	DEV_FUNC(map->xd_dev,func)
+#define	INTR_FUNC(intr,func)	DEV_FUNC(intr_hdl->xi_dev,func)
+
+/* =====================================================================
+ *                    PIO MANAGEMENT
+ *
+ *      For mapping system virtual address space to
+ *      xtalk space on a specified widget
+ */
+
+xtalk_piomap_t
+xtalk_piomap_alloc(devfs_handle_t dev,	/* set up mapping for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   iopaddr_t xtalk_addr,	/* map for this xtalk_addr range */
+		   size_t byte_count,
+		   size_t byte_count_max,	/* maximum size of a mapping */
+		   unsigned flags)
+{				/* defined in sys/pio.h */
+    return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc)
+	(dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags);
+}
+
+
+void
+xtalk_piomap_free(xtalk_piomap_t xtalk_piomap)
+{
+    PIOMAP_FUNC(xtalk_piomap, piomap_free)
+	(CAST_PIOMAP(xtalk_piomap));
+}
+
+
+caddr_t
+xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap,	/* mapping resources */
+		  iopaddr_t xtalk_addr,		/* map for this xtalk address */
+		  size_t byte_count)
+{				/* map this many bytes */
+    return PIOMAP_FUNC(xtalk_piomap, piomap_addr)
+	(CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count);
+}
+
+
+void
+xtalk_piomap_done(xtalk_piomap_t xtalk_piomap)
+{
+    PIOMAP_FUNC(xtalk_piomap, piomap_done)
+	(CAST_PIOMAP(xtalk_piomap));
+}
+
+
+caddr_t
+xtalk_piotrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    iopaddr_t xtalk_addr,	/* Crosstalk address */
+		    size_t byte_count,	/* map this many bytes */
+		    unsigned flags)
+{				/* (currently unused) */
+    return DEV_FUNC(dev, piotrans_addr)
+	(dev, dev_desc, xtalk_addr, byte_count, flags);
+}
+
+caddr_t
+xtalk_pio_addr(devfs_handle_t dev,	/* translate for this device */
+	       device_desc_t dev_desc,	/* device descriptor */
+	       iopaddr_t addr,		/* starting address (or offset in window) */
+	       size_t byte_count,	/* map this many bytes */
+	       xtalk_piomap_t *mapp,	/* where to return the map pointer */
+	       unsigned flags)
+{					/* PIO flags */
+    xtalk_piomap_t          map = 0;
+    caddr_t                 res;
+
+    if (mapp)
+	*mapp = 0;			/* record "no map used" */
+
+    res = xtalk_piotrans_addr
+	(dev, dev_desc, addr, byte_count, flags);
+    if (res)
+	return res;			/* xtalk_piotrans worked */
+
+    map = xtalk_piomap_alloc
+	(dev, dev_desc, addr, byte_count, byte_count, flags);
+    if (!map)
+	return res;			/* xtalk_piomap_alloc failed */
+
+    res = xtalk_piomap_addr
+	(map, addr, byte_count);
+    if (!res) {
+	xtalk_piomap_free(map);
+	return res;			/* xtalk_piomap_addr failed */
+    }
+    if (mapp)
+	*mapp = map;			/* pass back map used */
+
+    return res;				/* xtalk_piomap_addr succeeded */
+}
+
+/* =====================================================================
+ *            EARLY PIOTRANS SUPPORT
+ *
+ *      There are places where drivers (mgras, for instance)
+ *      need to get PIO translations before the infrastructure
+ *      is extended to them (setting up textports, for
+ *      instance). These drivers should call
+ *      xtalk_early_piotrans_addr with their xtalk ID
+ *      information, a sequence number (so we can use the second
+ *      mgras for instance), and the usual piotrans parameters.
+ *
+ *      Machine specific code should provide an implementation
+ *      of early_piotrans_addr, and present a pointer to this
+ *      function to xtalk_set_early_piotrans_addr so it can be
+ *      used by clients without the clients having to know what
+ *      platform or what xtalk provider is in use.
+ */
+
+static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr;
+
+xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr;
+
+/* xtalk_set_early_piotrans_addr:
+ * specify the early_piotrans_addr implementation function.
+ */
+void
+xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl)
+{
+    impl_early_piotrans_addr = impl;
+}
+
+/* xtalk_early_piotrans_addr:
+ * figure out a PIO address for the "nth" crosstalk widget that
+ * matches the specified part and mfgr number. Returns NULL if
+ * there is no such widget, or if the requested mapping can not
+ * be constructed.
+ * Limitations on which crosstalk slots (and busses) are
+ * checked, and definitions of the ordering of the search across
+ * the crosstalk slots, are defined by the platform.
+ */
+caddr_t
+xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
+			  xwidget_mfg_num_t mfg_num,
+			  int which,
+			  iopaddr_t xtalk_addr,
+			  size_t byte_count,
+			  unsigned flags)
+{
+    return impl_early_piotrans_addr
+	(part_num, mfg_num, which, xtalk_addr, byte_count, flags);
+}
+
+/* null_xtalk_early_piotrans_addr:
+ * used as the early_piotrans_addr implementation until and
+ * unless a real implementation is provided. In DEBUG kernels,
+ * we want to know who is calling before the implementation is
+ * registered; in non-DEBUG kernels, return NULL representing
+ * lack of mapping support.
+ */
+/*ARGSUSED */
+static caddr_t
+null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
+			       xwidget_mfg_num_t mfg_num,
+			       int which,
+			       iopaddr_t xtalk_addr,
+			       size_t byte_count,
+			       unsigned flags)
+{
+#if DEBUG
+    PRINT_PANIC("null_xtalk_early_piotrans_addr");
+#endif
+    return NULL;
+}
+
+/* =====================================================================
+ *                    DMA MANAGEMENT
+ *
+ *      For mapping from crosstalk space to system
+ *      physical space.
+ */
+
+xtalk_dmamap_t
+xtalk_dmamap_alloc(devfs_handle_t dev,	/* set up mappings for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   size_t byte_count_max,	/* max size of a mapping */
+		   unsigned flags)
+{				/* defined in dma.h */
+    return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
+	(dev, dev_desc, byte_count_max, flags);
+}
+
+
+void
+xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap)
+{
+    DMAMAP_FUNC(xtalk_dmamap, dmamap_free)
+	(CAST_DMAMAP(xtalk_dmamap));
+}
+
+
+iopaddr_t
+xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap,	/* use these mapping resources */
+		  paddr_t paddr,	/* map for this address */
+		  size_t byte_count)
+{				/* map this many bytes */
+    return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr)
+	(CAST_DMAMAP(xtalk_dmamap), paddr, byte_count);
+}
+
+
+alenlist_t
+xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap,	/* use these mapping resources */
+		  alenlist_t alenlist,	/* map this Address/Length List */
+		  unsigned flags)
+{
+    return DMAMAP_FUNC(xtalk_dmamap, dmamap_list)
+	(CAST_DMAMAP(xtalk_dmamap), alenlist, flags);
+}
+
+
+void
+xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap)
+{
+    DMAMAP_FUNC(xtalk_dmamap, dmamap_done)
+	(CAST_DMAMAP(xtalk_dmamap));
+}
+
+
+iopaddr_t
+xtalk_dmatrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    paddr_t paddr,	/* system physical address */
+		    size_t byte_count,	/* length */
+		    unsigned flags)
+{				/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_addr)
+	(dev, dev_desc, paddr, byte_count, flags);
+}
+
+
+alenlist_t
+xtalk_dmatrans_list(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    alenlist_t palenlist,	/* system address/length list */
+		    unsigned flags)
+{				/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_list)
+	(dev, dev_desc, palenlist, flags);
+}
+
+void
+xtalk_dmamap_drain(xtalk_dmamap_t map)
+{
+    DMAMAP_FUNC(map, dmamap_drain)
+	(CAST_DMAMAP(map));
+}
+
+void
+xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size)
+{
+    DEV_FUNC(dev, dmaaddr_drain)
+	(dev, addr, size);
+}
+
+void
+xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list)
+{
+    DEV_FUNC(dev, dmalist_drain)
+	(dev, list);
+}
+
+/* =====================================================================
+ *                    INTERRUPT MANAGEMENT
+ *
+ *      Allow crosstalk devices to establish interrupts
+ */
+
+/*
+ * Allocate resources required for an interrupt as specified in intr_desc.
+ * Return resource handle in intr_hdl.
+ */
+xtalk_intr_t
+xtalk_intr_alloc(devfs_handle_t dev,	/* which Crosstalk device */
+		 device_desc_t dev_desc,	/* device descriptor */
+		 devfs_handle_t owner_dev)
+{				/* owner of this interrupt */
+    return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc)
+	(dev, dev_desc, owner_dev);
+}
+
+/*
+ * Allocate resources required for an interrupt as specified in dev_desc.
+ * Unconditionally setup resources to be non-threaded.
+ * Return resource handle in intr_hdl.
+ */
+xtalk_intr_t
+xtalk_intr_alloc_nothd(devfs_handle_t dev,	/* which Crosstalk device */
+		 	device_desc_t dev_desc,	/* device descriptor */
+		 	devfs_handle_t owner_dev)	/* owner of this interrupt */
+{
+    return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd)
+	(dev, dev_desc, owner_dev);
+}
+
+/*
+ * Free resources consumed by intr_alloc.
+ */
+void
+xtalk_intr_free(xtalk_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_free)
+	(CAST_INTR(intr_hdl));
+}
+
+
+/*
+ * Associate resources allocated with a previous xtalk_intr_alloc call with the
+ * described handler, arg, name, etc.
+ *
+ * Returns 0 on success, returns <0 on failure.
+ */
+int
+xtalk_intr_connect(xtalk_intr_t intr_hdl,	/* xtalk intr resource handle */
+		   intr_func_t intr_func,       /* xtalk intr handler */
+		   intr_arg_t intr_arg,         /* arg to intr handler */
+		   xtalk_intr_setfunc_t setfunc,	/* func to set intr hw */
+		   void *setfunc_arg)	/* arg to setfunc */
+{
+    return INTR_FUNC(intr_hdl, intr_connect)
+	(CAST_INTR(intr_hdl), intr_func, intr_arg, setfunc, setfunc_arg);
+}
+
+
+/*
+ * Disassociate handler with the specified interrupt.
+ */
+void
+xtalk_intr_disconnect(xtalk_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_disconnect)
+	(CAST_INTR(intr_hdl));
+}
+
+
+/*
+ * Return a hwgraph vertex that represents the CPU currently
+ * targeted by an interrupt.
+ */
+devfs_handle_t
+xtalk_intr_cpu_get(xtalk_intr_t intr_hdl)
+{
+    return INTR_FUNC(intr_hdl, intr_cpu_get)
+	(CAST_INTR(intr_hdl));
+}
+
+
+/*
+ * =====================================================================
+ *                      ERROR MANAGEMENT
+ */
+
+/*
+ * xtalk_error_handler:
+ * pass this error on to the handler registered
+ * at the specified xtalk connecdtion point,
+ * or complain about it here if there is no handler.
+ *
+ * This routine plays two roles during error delivery
+ * to most widgets: first, the external agent (heart,
+ * hub, or whatever) calls in with the error and the
+ * connect point representing the crosstalk switch,
+ * or whatever crosstalk device is directly connected
+ * to the agent.
+ *
+ * If there is a switch, it will generally look at the
+ * widget number stashed in the ioerror structure; and,
+ * if the error came from some widget other than the
+ * switch, it will call back into xtalk_error_handler
+ * with the connection point of the offending port.
+ */
+int
+xtalk_error_handler(
+		       devfs_handle_t xconn,
+		       int error_code,
+		       ioerror_mode_t mode,
+		       ioerror_t *ioerror)
+{
+    xwidget_info_t          xwidget_info;
+
+    xwidget_info = xwidget_info_get(xconn);
+    /* Make sure that xwidget_info is a valid pointer before derefencing it.
+     * We could come in here during very early initialization. 
+     */
+    if (xwidget_info && xwidget_info->w_efunc)
+	return xwidget_info->w_efunc
+	    (xwidget_info->w_einfo,
+	     error_code, mode, ioerror);
+    /*
+     * no error handler registered for
+     * the offending port. it's not clear
+     * what needs to be done, but reporting
+     * it would be a good thing, unless it
+     * is a mode that requires nothing.
+     */
+    if ((mode == MODE_DEVPROBE) || (mode == MODE_DEVUSERERROR) ||
+	(mode == MODE_DEVREENABLE))
+	return IOERROR_HANDLED;
+
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk(KERN_WARNING "Xbow at %v encountered Fatal error", xconn);
+#else
+    printk(KERN_WARNING "Xbow at 0x%p encountered Fatal error", xconn);
+#endif
+    ioerror_dump("xtalk", error_code, mode, ioerror);
+
+    return IOERROR_UNHANDLED;
+}
+
+int
+xtalk_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code)
+{
+    return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code);
+}
+
+
+/* =====================================================================
+ *                    CONFIGURATION MANAGEMENT
+ */
+
+/*
+ * Startup a crosstalk provider
+ */
+void
+xtalk_provider_startup(devfs_handle_t xtalk_provider)
+{
+    DEV_FUNC(xtalk_provider, provider_startup)
+	(xtalk_provider);
+}
+
+
+/*
+ * Shutdown a crosstalk provider
+ */
+void
+xtalk_provider_shutdown(devfs_handle_t xtalk_provider)
+{
+    DEV_FUNC(xtalk_provider, provider_shutdown)
+	(xtalk_provider);
+}
+
+/* 
+ * Enable a device on a xtalk widget 
+ */
+void
+xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum)
+{
+    DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum);
+}
+
+/* 
+ * Shutdown a device on a xtalk widget 
+ */
+void
+xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum)
+{
+    DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum);
+}
+
+int
+xtalk_dma_enabled(devfs_handle_t xconn_vhdl)
+{
+    return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl);
+}
+/*
+ * Generic crosstalk functions, for use with all crosstalk providers
+ * and all crosstalk devices.
+ */
+
+/****** Generic crosstalk interrupt interfaces ******/
+devfs_handle_t
+xtalk_intr_dev_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_dev);
+}
+
+xwidgetnum_t
+xtalk_intr_target_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_target);
+}
+
+xtalk_intr_vector_t
+xtalk_intr_vector_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_vector);
+}
+
+iopaddr_t
+xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr)
+{
+    return (xtalk_intr->xi_addr);
+}
+
+void                   *
+xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_sfarg);
+}
+
+/****** Generic crosstalk pio interfaces ******/
+devfs_handle_t
+xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_dev);
+}
+
+xwidgetnum_t
+xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_target);
+}
+
+iopaddr_t
+xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_xtalk_addr);
+}
+
+ulong
+xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_mapsz);
+}
+
+caddr_t
+xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_kvaddr);
+}
+
+
+/****** Generic crosstalk dma interfaces ******/
+devfs_handle_t
+xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap)
+{
+    return (xtalk_dmamap->xd_dev);
+}
+
+xwidgetnum_t
+xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap)
+{
+    return (xtalk_dmamap->xd_target);
+}
+
+
+/****** Generic crosstalk widget information interfaces ******/
+
+/* xwidget_info_chk:
+ * check to see if this vertex is a widget;
+ * if so, return its widget_info (if any).
+ * if not, return NULL.
+ */
+xwidget_info_t
+xwidget_info_chk(devfs_handle_t xwidget)
+{
+    arbitrary_info_t        ainfo = 0;
+
+    hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo);
+    return (xwidget_info_t) ainfo;
+}
+
+
+xwidget_info_t
+xwidget_info_get(devfs_handle_t xwidget)
+{
+    xwidget_info_t          widget_info;
+
+    widget_info = (xwidget_info_t)
+	hwgraph_fastinfo_get(xwidget);
+
+#ifdef	LATER
+    if ((widget_info != NULL) &&
+	(widget_info->w_fingerprint != widget_info_fingerprint))
+#ifdef SUPPORT_PRINTING_V_FORMAT
+	PRINT_PANIC("%v bad xwidget_info", xwidget);
+#else
+	PRINT_PANIC("%x bad xwidget_info", xwidget);
+#endif
+#endif	/* LATER */
+
+    return (widget_info);
+}
+
+void
+xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info)
+{
+    if (widget_info != NULL)
+	widget_info->w_fingerprint = widget_info_fingerprint;
+
+    hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info);
+
+    /* Also, mark this vertex as an xwidget,
+     * and use the widget_info, so xwidget_info_chk
+     * can work (and be fairly efficient).
+     */
+    hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET,
+			 (arbitrary_info_t) widget_info);
+}
+
+devfs_handle_t
+xwidget_info_dev_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_vertex);
+}
+
+xwidgetnum_t
+xwidget_info_id_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_id);
+}
+
+
+devfs_handle_t
+xwidget_info_master_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_master);
+}
+
+xwidgetnum_t
+xwidget_info_masterid_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_masterid);
+}
+
+xwidget_part_num_t
+xwidget_info_part_num_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_hwid.part_num);
+}
+
+xwidget_mfg_num_t
+xwidget_info_mfg_num_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_hwid.mfg_num);
+}
+/* Extract the widget name from the widget information
+ * for the xtalk widget.
+ */
+char *
+xwidget_info_name_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget info");
+    return(xwidget_info->w_name);
+}
+/****** Generic crosstalk initialization interfaces ******/
+
+/*
+ * One-time initialization needed for systems that support crosstalk.
+ */
+void
+xtalk_init(void)
+{
+    cdl_p                   cp;
+
+#if DEBUG && ATTACH_DEBUG
+    printf("xtalk_init\n");
+#endif
+    /* Allocate the registry.
+     * We might already have one.
+     * If we don't, go get one.
+     * MPness: someone might have
+     * set one up for us while we
+     * were not looking; use an atomic
+     * compare-and-swap to commit to
+     * using the new registry if and
+     * only if nobody else did first.
+     * If someone did get there first,
+     * toss the one we allocated back
+     * into the pool.
+     */
+    if (xtalk_registry == NULL) {
+	cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr");
+	if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) {
+	    cdl_del(cp);
+	}
+    }
+    ASSERT(xtalk_registry != NULL);
+}
+
+/*
+ * Associate a set of xtalk_provider functions with a vertex.
+ */
+void
+xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns)
+{
+    hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns);
+}
+
+/*
+ * Disassociate a set of xtalk_provider functions with a vertex.
+ */
+void
+xtalk_provider_unregister(devfs_handle_t provider)
+{
+    hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL);
+}
+
+/*
+ * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk
+ * provider.
+ */
+xtalk_provider_t       *
+xtalk_provider_fns_get(devfs_handle_t provider)
+{
+    return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider));
+}
+
+/*
+ * Announce a driver for a particular crosstalk part.
+ * Returns 0 on success or -1 on failure.  Failure occurs if the
+ * specified hardware already has a driver.
+ */
+/*ARGSUSED4 */
+int
+xwidget_driver_register(xwidget_part_num_t part_num,
+			xwidget_mfg_num_t mfg_num,
+			char *driver_prefix,
+			unsigned flags)
+{
+    /* a driver's init routine could call
+     * xwidget_driver_register before the
+     * system calls xtalk_init; so, we
+     * make the call here.
+     */
+    if (xtalk_registry == NULL)
+	xtalk_init();
+
+    return cdl_add_driver(xtalk_registry,
+			  part_num, mfg_num,
+			  driver_prefix, flags, NULL);
+}
+
+/*
+ * Inform xtalk infrastructure that a driver is no longer available for
+ * handling any widgets.
+ */
+void
+xwidget_driver_unregister(char *driver_prefix)
+{
+    /* before a driver calls unregister,
+     * it must have called registger; so we
+     * can assume we have a registry here.
+     */
+    ASSERT(xtalk_registry != NULL);
+
+    cdl_del_driver(xtalk_registry, driver_prefix, NULL);
+}
+
+/*
+ * Call some function with each vertex that
+ * might be one of this driver's attach points.
+ */
+void
+xtalk_iterate(char *driver_prefix,
+	      xtalk_iter_f *func)
+{
+    ASSERT(xtalk_registry != NULL);
+
+    cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func);
+}
+
+/*
+ * xwidget_register:
+ *	Register a xtalk device (xwidget) by doing the following.
+ *      -allocate and initialize xwidget_info data
+ *      -allocate a hwgraph vertex with name based on widget number (id)
+ *      -look up the widget's initialization function and call it,
+ *      or remember the vertex for later initialization.
+ *
+ */
+int
+xwidget_register(xwidget_hwid_t hwid,		/* widget's hardware ID */
+		 devfs_handle_t 	widget,		/* widget to initialize */
+		 xwidgetnum_t 	id,		/* widget's target id (0..f) */
+		 devfs_handle_t 	master,		/* widget's master vertex */
+		 xwidgetnum_t 	targetid,	/* master's target id (9/a) */
+		 async_attach_t aa)
+{			
+    xwidget_info_t          widget_info;
+    char		    *s,devnm[MAXDEVNAME];
+
+    /* Allocate widget_info and associate it with widget vertex */
+    NEW(widget_info);
+
+    /* Initialize widget_info */
+    widget_info->w_vertex = widget;
+    widget_info->w_id = id;
+    widget_info->w_master = master;
+    widget_info->w_masterid = targetid;
+    widget_info->w_hwid = *hwid;	/* structure copy */
+    widget_info->w_efunc = 0;
+    widget_info->w_einfo = 0;
+    /*
+     * get the name of this xwidget vertex and keep the info.
+     * This is needed during errors and interupts, but as
+     * long as we have it, we can use it elsewhere.
+     */
+    s = dev_to_name(widget,devnm,MAXDEVNAME);
+    widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
+    strcpy(widget_info->w_name,s);
+    
+    xwidget_info_set(widget, widget_info);
+
+    device_master_set(widget, master);
+
+    /* All the driver init routines (including
+     * xtalk_init) are called before we get into
+     * attaching devices, so we can assume we
+     * have a registry here.
+     */
+    ASSERT(xtalk_registry != NULL);
+
+    /* 
+     * Add pointer to async attach info -- tear down will be done when
+     * the particular descendant is done with the info.
+     */
+    if (aa)
+	    async_attach_add_info(widget, aa);
+
+    return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
+                          widget, 0);
+}
+
+/*
+ * xwidget_unregister :
+ *	Unregister the xtalk device and detach all its hwgraph namespace.
+ */
+int
+xwidget_unregister(devfs_handle_t widget)
+{
+    xwidget_info_t	widget_info;
+    xwidget_hwid_t	hwid;
+
+    /* Make sure that we have valid widget information initialized */
+    if (!(widget_info = xwidget_info_get(widget)))
+	return(1);
+
+    /* Remove the inventory information associated
+     * with the widget.
+     */
+    hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1);
+    
+    hwid = &(widget_info->w_hwid);
+
+    cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
+                   widget, 0);
+
+    /* Clean out the xwidget information */
+    (void)kfree(widget_info->w_name);
+    BZERO((void *)widget_info, sizeof(widget_info));
+    DEL(widget_info);
+    
+    return(0);
+}
+
+void
+xwidget_error_register(devfs_handle_t xwidget,
+		       error_handler_f *efunc,
+		       error_handler_arg_t einfo)
+{
+    xwidget_info_t          xwidget_info;
+
+    xwidget_info = xwidget_info_get(xwidget);
+    ASSERT(xwidget_info != NULL);
+    xwidget_info->w_efunc = efunc;
+    xwidget_info->w_einfo = einfo;
+}
+
+/*
+ * Issue a link reset to a widget.
+ */
+void
+xwidget_reset(devfs_handle_t xwidget)
+{
+    xswitch_reset_link(xwidget);
+
+}
+
+
+void
+xwidget_gfx_reset(devfs_handle_t xwidget)
+{
+    xwidget_info_t info;
+
+    xswitch_reset_link(xwidget);
+    info = xwidget_info_get(xwidget);
+#ifdef LATER
+    ASSERT_ALWAYS(info != NULL);
+#endif
+
+    /*
+     * Enable this for other architectures once we add widget_reset to the
+     * xtalk provider interface.
+     */
+    DEV_FUNC(xtalk_provider, widget_reset)
+	(xwidget_info_master_get(info), xwidget_info_id_get(info));
+}
+
+#define ANON_XWIDGET_NAME	"No Name"	/* Default Widget Name */
+
+/* Get the canonical hwgraph  name of xtalk widget */
+char *
+xwidget_name_get(devfs_handle_t xwidget_vhdl)
+{
+	xwidget_info_t  info;
+
+	/* If we have a bogus widget handle then return
+	 * a default anonymous widget name.
+	 */
+	if (xwidget_vhdl == GRAPH_VERTEX_NONE)
+	    return(ANON_XWIDGET_NAME);
+	/* Read the widget name stored in the widget info
+	 * for the widget setup during widget initialization.
+	 */
+	info = xwidget_info_get(xwidget_vhdl);
+	ASSERT(info != NULL);
+	return(xwidget_info_name_get(info));
+}
diff -Nru a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/kernel/iomv.c	Mon Feb 24 04:47:33 2003
@@ -0,0 +1,115 @@
+/* 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <asm/io.h>
+#include <linux/module.h>
+
+extern void * sn_io_addr(unsigned long port); /* defined in sn[12]/iomv.c */
+
+/**
+ * sn_inb - read a byte from a port
+ * @port: port to read from
+ *
+ * Reads a byte from @port and returns it to the caller.
+ */
+unsigned int
+sn_inb (unsigned long port)
+{
+	volatile unsigned char *addr = sn_io_addr(port);
+	unsigned char ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+/**
+ * sn_inw - read a word from a port
+ * @port: port to read from
+ *
+ * Reads a word from @port and returns it to the caller.
+ */
+unsigned int
+sn_inw (unsigned long port)
+{
+	volatile unsigned short *addr = sn_io_addr(port);
+	unsigned short ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+/**
+ * sn_inl - read a word from a port
+ * @port: port to read from
+ *
+ * Reads a word from @port and returns it to the caller.
+ */
+unsigned int
+sn_inl (unsigned long port)
+{
+	volatile unsigned int *addr = sn_io_addr(port);
+	unsigned int ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+/**
+ * sn_outb - write a byte to a port
+ * @port: port to write to
+ * @val: value to write
+ *
+ * Writes @val to @port.
+ */
+void
+sn_outb (unsigned char val, unsigned long port)
+{
+	volatile unsigned char *addr = sn_io_addr(port);
+
+	*addr = val;
+}
+
+/**
+ * sn_outw - write a word to a port
+ * @port: port to write to
+ * @val: value to write
+ *
+ * Writes @val to @port.
+ */
+void
+sn_outw (unsigned short val, unsigned long port)
+{
+	volatile unsigned short *addr = sn_io_addr(port);
+
+	*addr = val;
+}
+
+/**
+ * sn_outl - write a word to a port
+ * @port: port to write to
+ * @val: value to write
+ *
+ * Writes @val to @port.
+ */
+void
+sn_outl (unsigned int val, unsigned long port)
+{
+	volatile unsigned int *addr = sn_io_addr(port);
+
+	*addr = val;
+}
+
+EXPORT_SYMBOL(sn_inb);
+EXPORT_SYMBOL(sn_inw);
+EXPORT_SYMBOL(sn_inl);
+EXPORT_SYMBOL(sn_outb);
+EXPORT_SYMBOL(sn_outw);
+EXPORT_SYMBOL(sn_outl);
diff -Nru a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
--- a/arch/ia64/sn/kernel/mca.c	Tue Nov  5 06:25:20 2002
+++ b/arch/ia64/sn/kernel/mca.c	Mon Feb 24 04:50:23 2003
@@ -40,7 +40,10 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/smp_lock.h>
+#include <linux/acpi.h>
+#ifdef CONFIG_KDB
 #include <linux/kdb.h>
+#endif
 
 #include <asm/machvec.h>
 #include <asm/page.h>
@@ -53,7 +56,6 @@
 
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
-#include <asm/acpi-ext.h>
 #include <asm/smp.h>
 #include <asm/sn/sn_cpuid.h>
 
diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	Tue Feb 25 02:08:11 2003
+++ b/arch/ia64/sn/kernel/setup.c	Thu Mar  6 11:40:52 2003
@@ -267,7 +267,7 @@
 	/* PROM has wrong value on SN1 */
 	sn_rtc_cycles_per_second = 990177;
 #endif
-	sn_rtc_usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
+	sn_rtc_usec_per_cyc = ((1000000000UL<<IA64_NSEC_PER_CYC_SHIFT)
 			       + sn_rtc_cycles_per_second/2) / sn_rtc_cycles_per_second;
 		
 	for (i=0;i<NR_CPUS;i++)
diff -Nru a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
--- a/arch/ia64/sn/kernel/sn2/Makefile	Mon Dec 16 15:47:54 2002
+++ b/arch/ia64/sn/kernel/sn2/Makefile	Mon Feb 24 05:15:44 2003
@@ -32,5 +32,7 @@
 # http://oss.sgi.com/projects/GenInfo/NoticeExplan
 #
 
-
 EXTRA_CFLAGS    := -DLITTLE_ENDIAN
+
+obj-y += cache.o iomv.o ptc_deadlock.o sn2_smp.o \
+         sn_proc_fs.o
diff -Nru a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S	Mon Feb 24 05:16:29 2003
@@ -0,0 +1,82 @@
+/* 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <asm/sn/sn2/shub_mmr.h>
+
+#define ZEROVAL		0x3f		// "zero" value for outstanding PIO requests
+#define DEADLOCKBIT	SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT
+#define WRITECOUNT	SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_SHFT
+#define ALIAS_OFFSET	(SH_PIO_WRITE_STATUS_0_ALIAS-SH_PIO_WRITE_STATUS_0)
+
+
+	.global	sn2_ptc_deadlock_recovery_core
+	.proc  	sn2_ptc_deadlock_recovery_core
+
+sn2_ptc_deadlock_recovery_core:
+	.regstk 5,0,0,0
+
+	ptc0  	 = in0
+	data0 	 = in1
+	ptc1  	 = in2
+	data1 	 = in3
+	piowc 	 = in4
+	piowcphy = r30
+	psrsave  = r2
+	zeroval  = r3
+	scr1	 = r16
+	scr2	 = r17
+
+
+	extr.u	piowcphy=piowc,0,61;;	// Convert piowc to uncached physical address
+	dep	piowcphy=-1,piowcphy,63,1
+
+	mov	zeroval=ZEROVAL		// "zero" value for PIO write count
+
+1:
+	add	scr2=ALIAS_OFFSET,piowc	// Address of WRITE_STATUS alias register 
+	mov	scr1=7;;		// Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR
+	st8.rel	[scr2]=scr1;;
+
+5:	ld8.acq	scr1=[piowc];;		// Wait for PIOs to complete.
+	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	cmp.ne	p6,p0=zeroval,scr2
+(p6)	br.cond.sptk 5b
+	
+
+
+	////////////// BEGIN PHYSICAL MODE ////////////////////
+	mov psrsave=psr			// Disable IC (no PMIs)
+	rsm psr.i | psr.dt | psr.ic;;
+	srlz.i;;
+
+	st8.rel [ptc0]=data0		// Write PTC0 & wait for completion.
+
+5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
+	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	cmp.ne	p6,p0=zeroval,scr2
+(p6)	br.cond.sptk 5b;;
+
+	tbit.nz	p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK
+	
+(p7)	st8.rel [ptc1]=data1;;		// Now write PTC1.
+
+5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
+	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	cmp.ne	p6,p0=zeroval,scr2
+(p6)	br.cond.sptk 5b
+	
+	tbit.nz	p8,p0=scr1,DEADLOCKBIT;;// Test for DEADLOCK
+
+	mov psr.l=psrsave;;		// Reenable IC
+	srlz.i;;
+	////////////// END   PHYSICAL MODE ////////////////////
+
+(p8)	br.cond.spnt 1b;;		// Repeat if DEADLOCK occurred.
+
+	br.ret.sptk	rp
+	.endp sn2_ptc_deadlock_recovery_core
diff -Nru a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	Mon Feb 24 05:17:16 2003
@@ -0,0 +1,145 @@
+/*
+ *
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <asm/sn/sn_sal.h>
+
+
+static int partition_id_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+
+	return sprintf(page, "%d\n", sn_local_partid());
+}
+
+struct proc_dir_entry * sgi_proc_dir = NULL;
+
+void
+register_sn_partition_id(void) {
+	struct proc_dir_entry *entry;
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+	entry = create_proc_entry("partition_id", 0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = partition_id_read_proc;
+		entry->write_proc = NULL;
+	}
+}
+
+static int
+system_serial_number_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+	return sprintf(page, "%s\n", sn_system_serial_number());
+}
+
+static int
+licenseID_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+	return sprintf(page, "0x%lx\n",sn_partition_serial_number_val());
+}
+
+void
+register_sn_serial_numbers(void) {
+	struct proc_dir_entry *entry;
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+	entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = system_serial_number_read_proc;
+		entry->write_proc = NULL;
+	}
+	entry = create_proc_entry("licenseID", 0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = licenseID_read_proc;
+		entry->write_proc = NULL;
+	}
+}
+
+// Disable forced interrupts, but leave the code in, just in case.
+int sn_force_interrupt_flag = 0;
+
+static int
+sn_force_interrupt_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+	if (sn_force_interrupt_flag) {
+		return sprintf(page, "Force interrupt is enabled\n");
+	}
+	return sprintf(page, "Force interrupt is disabled\n");
+}
+
+static int 
+sn_force_interrupt_write_proc(struct file *file, const char *buffer,
+                                        unsigned long count, void *data)
+{
+	if (*buffer == '0') {
+		sn_force_interrupt_flag = 0;
+	} else {
+		sn_force_interrupt_flag = 1;
+	}
+	return 1;
+}
+
+void
+register_sn_force_interrupt(void) {
+	struct proc_dir_entry *entry;
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+	entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = sn_force_interrupt_read_proc;
+		entry->write_proc = sn_force_interrupt_write_proc;
+	}
+}
+void
+register_sn_procfs(void) {
+	register_sn_partition_id();
+	register_sn_serial_numbers();
+	register_sn_force_interrupt();
+}
+
+#endif /* CONFIG_PROC_FS */
diff -Nru a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c
--- a/arch/ia64/tools/print_offsets.c	Wed Jan 29 22:16:51 2003
+++ b/arch/ia64/tools/print_offsets.c	Fri Feb 28 15:27:56 2003
@@ -10,7 +10,7 @@
  * gets translated into an assembly file which, in turn, is processed
  * by awk to generate offsets.h.  So if you make any changes to this
  * file, be sure to verify that the awk procedure still works (see
- * prin_offsets.awk).
+ * print_offsets.awk).
  */
 #include <linux/config.h>
 
@@ -170,6 +170,12 @@
     /* for assembly files which can't include sched.h: */
     { "IA64_CLONE_VFORK",		CLONE_VFORK },
     { "IA64_CLONE_VM",			CLONE_VM },
+    /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
+    { "IA64_CPUINFO_ITM_DELTA_OFFSET", 		offsetof (struct cpuinfo_ia64, itm_delta) },
+    { "IA64_CPUINFO_ITM_NEXT_OFFSET", 		offsetof (struct cpuinfo_ia64, itm_next) },
+    { "IA64_CPUINFO_NSEC_PER_CYC_OFFSET",	offsetof (struct cpuinfo_ia64, nsec_per_cyc) },
+    { "IA64_TIMESPEC_TV_NSEC_OFFSET", 		offsetof (struct timespec, tv_nsec) },
+
 };
 
 static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S
--- a/arch/ia64/vmlinux.lds.S	Wed Jan 29 22:16:51 2003
+++ b/arch/ia64/vmlinux.lds.S	Fri Feb 14 15:08:44 2003
@@ -133,6 +133,10 @@
 	  *(.initcall7.init)
 	  __initcall_end = .;
 	}
+   __con_initcall_start = .;
+  .con_initcall.init : AT(ADDR(.con_initcall.init) - PAGE_OFFSET)
+	{ *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig
--- a/arch/m68k/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/m68k/Kconfig	Sat Mar  8 14:50:37 2003
@@ -10,10 +10,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
--- a/arch/m68k/atari/stram.c	Mon Jan 13 17:54:26 2003
+++ b/arch/m68k/atari/stram.c	Sat Mar  8 14:50:21 2003
@@ -1052,8 +1052,7 @@
 	if (!stram_disk)
 		return -ENOMEM;
 
-	if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) {
-		printk(KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR);
+	if (register_blkdev(STRAM_MAJOR, "stram")) {
 		put_disk(stram_disk);
 		return -ENXIO;
 	}
diff -Nru a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
--- a/arch/m68k/kernel/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/m68k/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -3,9 +3,9 @@
 #
 
 ifndef CONFIG_SUN3
-  EXTRA_TARGETS := head.o
+  extra-y := head.o
 else
-  EXTRA_TARGETS := sun3-head.o
+  extra-y := sun3-head.o
 endif 
 
 obj-y		:= entry.o process.o traps.o ints.o signal.o ptrace.o \
diff -Nru a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds
--- a/arch/m68k/vmlinux-std.lds	Wed Jan 15 09:48:42 2003
+++ b/arch/m68k/vmlinux-std.lds	Fri Feb 14 15:09:22 2003
@@ -60,6 +60,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(8192);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
--- a/arch/m68k/vmlinux-sun3.lds	Wed Jan 15 09:48:42 2003
+++ b/arch/m68k/vmlinux-sun3.lds	Fri Feb 14 15:09:22 2003
@@ -53,6 +53,9 @@
 		*(.initcall7.init)
 	}
 	__initcall_end = .;
+	__con_initcall_start = .;
+	.con_initcall.init : { *(.con_initcall.init) }
+	__con_initcall_end = .;
 	. = ALIGN(8192);
 	__initramfs_start = .;
 	.init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
--- a/arch/m68knommu/Kconfig	Tue Feb 18 02:27:38 2003
+++ b/arch/m68knommu/Kconfig	Wed Mar  5 15:33:01 2003
@@ -9,10 +9,6 @@
 	bool
 	default n
 
-config SWAP
-	bool
-	default n
-
 config FPU
 	bool
 	default n
@@ -106,7 +102,7 @@
 	  really need to know, so you can select the AUTO option. On some
 	  boards you need to know the real clock frequency to determine other
 	  system timing (for example baud rate dividors, etc). Some processors
-	  have an internal PLL and you can seletc a frequency to set that too.
+	  have an internal PLL and you can select a frequency to run at.
 	  You need to know a little about the internals of your processor to
 	  set this. If in doubt choose the AUTO option.
 
@@ -679,11 +675,12 @@
 config MAGIC_SYSRQ
 	bool "Magic SysRq key"
 	help
-	  Enables console device to interprent special characters as
+	  Enables console device to interpret special characters as
 	  commands to dump state information.
 
 config HIGHPROFILE
 	bool "Use fast second timer for profiling"
+	depends on COLDFIRE
 	help
 	  Use a fast secondary clock to produce profiling information.
 
@@ -703,7 +700,7 @@
 	bool "Disable BDM signals"
 	depends on (EXPERIMENTAL && COLDFIRE)
 	help
-	  Disable the CPU's BDM signals.
+	  Disable the ColdFire CPU's BDM signals.
 
 endmenu
 
diff -Nru a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
--- a/arch/m68knommu/Makefile	Sun Jan 26 11:13:05 2003
+++ b/arch/m68knommu/Makefile	Fri Mar  7 13:28:49 2003
@@ -86,8 +86,7 @@
 
 head-y := arch/m68knommu/platform/$(platform-y)/$(board-y)/crt0_$(model-y).o
 
-CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h.tmp \
-	       include/asm-$(ARCH)/asm-offsets.h \
+CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h \
 	       arch/$(ARCH)/kernel/asm-offsets.s
 
 core-y	+= arch/m68knommu/kernel/ \
@@ -104,6 +103,4 @@
 include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
 				   include/asm include/linux/version.h \
 				   include/config/MARKER
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
diff -Nru a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c
--- a/arch/m68knommu/kernel/comempci.c	Tue Jan 14 03:33:15 2003
+++ b/arch/m68knommu/kernel/comempci.c	Mon Mar 17 03:25:37 2003
@@ -3,7 +3,7 @@
 /*
  *	comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller.
  *
- *	(C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
+ *	(C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com).
  *	(C) Copyright 2000, Lineo (www.lineo.com)
  */
 
@@ -60,8 +60,8 @@
  *	really assign any resources we like to devices, as long as
  *	they do not clash with other PCI devices.
  */
-unsigned int	pci_iobase = 0x100;		/* Arbitary start address */
-unsigned int	pci_membase = 0x00010000;	/* Arbitary start address */
+unsigned int	pci_iobase = PCIBIOS_MIN_IO;	/* Arbitrary start address */
+unsigned int	pci_membase = PCIBIOS_MIN_MEM;	/* Arbitrary start address */
 
 #define	PCI_MINIO	0x100			/* 256 byte minimum I/O */
 #define	PCI_MINMEM	0x00010000		/* 64k minimum chunk */
@@ -75,7 +75,7 @@
 
 /*****************************************************************************/
 
-void 		pci_interrupt(int irq, void *id, struct pt_regs *fp);
+void	pci_interrupt(int irq, void *id, struct pt_regs *fp);
 
 /*****************************************************************************/
 
@@ -105,7 +105,7 @@
 
 /*****************************************************************************/
 
-int pcibios_assignres(int slot)
+int pcibios_assign_resource_slot(int slot)
 {
 	volatile unsigned long	*rp;
 	volatile unsigned char	*ip;
@@ -113,7 +113,7 @@
 	int			bar;
 
 #ifdef DEBUGPCI
-	printk("pcibios_assignres(slot=%x)\n", slot);
+	printk("pcibios_assign_resource_slot(slot=%x)\n", slot);
 #endif
 
 	rp = (volatile unsigned long *) COMEM_BASE;
@@ -224,7 +224,7 @@
 
 /*****************************************************************************/
 
-int pcibios_enable(int slot)
+int pcibios_enable_slot(int slot)
 {
 	volatile unsigned long	*rp;
 	volatile unsigned short	*wp;
@@ -232,7 +232,7 @@
 	unsigned short		cmd;
 
 #ifdef DEBUGPCI
-	printk("pcibios_enbale(slot=%x)\n", slot);
+	printk("pcibios_enbale_slot(slot=%x)\n", slot);
 #endif
 
 	rp = (volatile unsigned long *) COMEM_BASE;
@@ -256,7 +256,34 @@
 
 /*****************************************************************************/
 
-unsigned long pcibios_init(unsigned long mem_start, unsigned long mem_end)
+void pcibios_assign_resources(void)
+{
+	volatile unsigned long	*rp;
+	unsigned long		sel, id;
+	int			slot;
+
+	rp = (volatile unsigned long *) COMEM_BASE;
+
+	/*
+	 *	Do a quick scan of the PCI bus and see what is here.
+	 */
+	for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) {
+		sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
+		rp[LREG(COMEM_DAHBASE)] = sel;
+		rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
+		id = rp[LREG(COMEM_PCIBUS)];
+		if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) {
+			printk("PCI: slot=%d id=%08x\n", slot, (int) id);
+			pci_slotmask |= 0x1 << slot;
+			pcibios_assign_resource_slot(slot);
+			pcibios_enable_slot(slot);
+		}
+	}
+}
+
+/*****************************************************************************/
+
+int pcibios_init(void)
 {
 	volatile unsigned long	*rp;
 	unsigned long		sel, id;
@@ -276,7 +303,7 @@
 	rp = (volatile unsigned long *) COMEM_BASE;
 	if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) {
 		printk("PCI: no PCI bus present\n");
-		return(mem_start);
+		return(0);
 	}
 
 #ifdef COMEM_BRIDGEDEV
@@ -291,34 +318,18 @@
 	id = rp[LREG(COMEM_PCIBUS)];
 	if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) {
 		printk("PCI: no PCI bus bridge present\n");
-		return(mem_start);
+		return(0);
 	}
 
 	printk("PCI: bridge device at slot=%d id=%08x\n", slot, (int) id);
 	pci_slotmask |= 0x1 << slot;
 	pci_shmemaddr = pci_membase;
-	pcibios_assignres(slot);
-	pcibios_enable(slot);
+	pcibios_assign_resource_slot(slot);
+	pcibios_enable_slot(slot);
 #endif
 
 	pci_bus_is_present = 1;
 
-	/*
-	 *	Do a quick scan of the PCI bus and see what is here.
-	 */
-	for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) {
-		sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
-		rp[LREG(COMEM_DAHBASE)] = sel;
-		rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
-		id = rp[LREG(COMEM_PCIBUS)];
-		if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) {
-			printk("PCI: slot=%d id=%08x\n", slot, (int) id);
-			pci_slotmask |= 0x1 << slot;
-			pcibios_assignres(slot);
-			pcibios_enable(slot);
-		}
-	}
-
 	/* Get PCI irq for local vectoring */
 	if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) {
 		printk("PCI: failed to acquire interrupt %d\n", COMEM_IRQ);
@@ -326,18 +337,55 @@
 		mcf_autovector(COMEM_IRQ);
 	}
 
-	return(mem_start);
+	pcibios_assign_resources();
+
+	return(0);
 }
 
 /*****************************************************************************/
 
-unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
+char *pcibios_setup(char *option)
+{
+	/* Nothing for us to handle. */
+	return(option);
+}
+/*****************************************************************************/
+
+struct pci_fixup pcibios_fixups[] = { { 0 } };
+
+void pcibios_fixup_bus(struct pci_bus *b)
 {
-	return(mem_start);
 }
 
 /*****************************************************************************/
 
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align)
+{
+}
+
+/*****************************************************************************/
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	int slot;
+
+	slot = PCI_SLOT(dev->devfn);
+	if ((dev->bus == 0) && (pci_slotmask & (1 << slot)))
+		pcibios_enable_slot(slot);
+	return(0);
+}
+
+/*****************************************************************************/
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *r, int resource)
+{
+	printk("%s(%d): no support for changing PCI resources...\n",
+		__FILE__, __LINE__);
+}
+
+
+/*****************************************************************************/
+
 /*
  *	Local routines to interrcept the standard I/O and vector handling
  *	code. Don't include this 'till now - initialization code above needs
@@ -918,6 +966,26 @@
 	}
 	printk("\n");
 #endif
+}
+
+/*****************************************************************************/
+
+void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addr)
+{
+	void *mp;
+	if ((mp = pci_bmalloc(size)) != NULL) {
+		dma_addr = mp - (COMEM_BASE + COMEM_SHMEM);
+		return(mp);
+	}
+	*dma_addr = (dma_addr_t) NULL;
+	return(NULL);
+}
+
+/*****************************************************************************/
+
+void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr)
+{
+	pci_bmfree(cpu_addr, size);
 }
 
 /*****************************************************************************/
diff -Nru a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S
--- a/arch/m68knommu/kernel/entry.S	Tue Jan 14 03:33:15 2003
+++ b/arch/m68knommu/kernel/entry.S	Wed Mar  5 15:33:01 2003
@@ -84,6 +84,9 @@
 	jmp	schedule
 
 ENTRY(ret_from_fork)
+	movel	%d1,%sp@-
+	jsr	schedule_tail
+	addql	#4,%sp
 	jra	ret_from_exception
 
 ENTRY(sys_fork)
diff -Nru a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
--- a/arch/m68knommu/kernel/signal.c	Tue Feb 18 02:27:38 2003
+++ b/arch/m68knommu/kernel/signal.c	Mon Mar 17 03:25:37 2003
@@ -16,7 +16,7 @@
  * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
  *
  * mathemu support by Roman Zippel
- *  (Note: fpstate in the signal context is completly ignored for the emulator
+ *  (Note: fpstate in the signal context is completely ignored for the emulator
  *         and the internal floating point format is put on stack)
  */
 
diff -Nru a/arch/m68knommu/platform/5206/Makefile b/arch/m68knommu/platform/5206/Makefile
--- a/arch/m68knommu/platform/5206/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/5206/Makefile	Sun Mar  9 14:15:54 2003
@@ -18,4 +18,4 @@
 
 obj-y := config.o
 
-EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/crt0_$(MODEL).o
diff -Nru a/arch/m68knommu/platform/5206/config.c b/arch/m68knommu/platform/5206/config.c
--- a/arch/m68knommu/platform/5206/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5206/config.c	Thu Mar  6 03:12:30 2003
@@ -25,6 +25,14 @@
 
 /***************************************************************************/
 
+void coldfire_tick(void);
+void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+/***************************************************************************/
+
 /*
  *	DMA channel base address table.
  */
@@ -33,47 +41,8 @@
         MCF_MBAR + MCFDMA_BASE1,
 };
 
-unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
-/***************************************************************************/
-
-void coldfire_tick(void)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-}
-
-/***************************************************************************/
-
-void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	/* Set up TIMER 1 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR);
-
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3;
-	request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1);
-}
-
 /***************************************************************************/
 
-/*
- *	Program the vector to be an auto-vectored.
- */
-
 void mcf_autovector(unsigned int vec)
 {
 	volatile unsigned char  *mbar;
@@ -91,65 +60,35 @@
 
 /***************************************************************************/
 
-extern e_vector	*_ramvec;
-
-void set_evector(int vecnum, void (*handler)(void))
-{
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
-/* assembler routines */
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void system_call(void);
-asmlinkage void inthandler(void);
-
-void coldfire_trap_init(void)
+void mcf_settimericr(unsigned int timer, unsigned int level)
 {
-	int i;
-
-#ifndef ENABLE_dBUG
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-#endif
+	volatile unsigned char *icrp;
+	unsigned int icr, imr;
 
-	/*
-	 *	There is a common trap handler and common interrupt
-	 *	handler that handle almost every vector. We treat
-	 *	the system call and bus error special, they get their
-	 *	own first level handlers.
-	 */
-#ifndef ENABLE_dBUG
-	for (i = 3; (i <= 23); i++)
-		_ramvec[i] = trap;
-	for (i = 33; (i <= 63); i++)
-		_ramvec[i] = trap;
-#endif
-
-	for (i = 24; (i <= 30); i++)
-		_ramvec[i] = inthandler;
-#ifndef ENABLE_dBUG
-	_ramvec[31] = inthandler;  // Disables the IRQ7 button
-#endif
-
-	for (i = 64; (i < 255); i++)
-		_ramvec[i] = inthandler;
-	_ramvec[255] = 0;
-
-	_ramvec[2] = buserr;
-	_ramvec[32] = system_call;
+	if (timer <= 2) {
+		switch (timer) {
+		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
+		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
+		}
+
+		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
+		mcf_setimr(mcf_getimr() & ~imr);
+	}
 }
 
 /***************************************************************************/
 
 void config_BSP(char *commandp, int size)
 {
+	mcf_setimr(MCFSIM_IMR_MASKALL);
 	memset(commandp, 0, size);
+
 	mach_sched_init = coldfire_timer_init;
 	mach_tick = coldfire_tick;
+	mach_gettimeoffset = coldfire_timer_offset;
 	mach_trap_init = coldfire_trap_init;
+	mach_reset = coldfire_reset;
 }
 
 /***************************************************************************/
diff -Nru a/arch/m68knommu/platform/5206e/Makefile b/arch/m68knommu/platform/5206e/Makefile
--- a/arch/m68knommu/platform/5206e/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/5206e/Makefile	Sun Mar  9 14:15:54 2003
@@ -18,4 +18,4 @@
 
 obj-y := config.o
 
-EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/crt0_$(MODEL).o
diff -Nru a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
--- a/arch/m68knommu/platform/5206e/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5206e/config.c	Thu Mar  6 03:12:30 2003
@@ -20,17 +20,16 @@
 #include <asm/mcftimer.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfdma.h>
-
-#ifdef CONFIG_NETtel
 #include <asm/irq.h>
 #include <asm/delay.h>
-#endif
 
 /***************************************************************************/
 
-#ifdef CONFIG_NETtel
-void	reset_setupbutton(void);
-#endif
+void coldfire_tick(void);
+void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
 
 /***************************************************************************/
 
@@ -42,53 +41,8 @@
         MCF_MBAR + MCFDMA_BASE1,
 };
 
-unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
-/***************************************************************************/
-
-void coldfire_tick(void)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-}
-
 /***************************************************************************/
 
-void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	/* Set up TIMER 1 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR);
-
-#ifdef CONFIG_NETtel
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3;
-	request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-	reset_setupbutton();
-#else
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3;
-	request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-#endif
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1);
-}
-
-/***************************************************************************/
-
-/*
- *	Program the vector to be an auto-vectored.
- */
-
 void mcf_autovector(unsigned int vec)
 {
 	volatile unsigned char  *mbar;
@@ -106,117 +60,29 @@
 
 /***************************************************************************/
 
-extern e_vector	*_ramvec;
-
-void set_evector(int vecnum, void (*handler)(void))
-{
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
-/* assembler routines */
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void system_call(void);
-asmlinkage void inthandler(void);
-
-void coldfire_trap_init(void)
+void mcf_settimericr(unsigned int timer, unsigned int level)
 {
-	int i;
-#ifdef MCF_MEMORY_PROTECT
-	extern unsigned long _end;
-	extern unsigned long memory_end;
-#endif
-
-#ifndef ENABLE_dBUG
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-#endif
-
-	/*
-	 *	There is a common trap handler and common interrupt
-	 *	handler that handle almost every vector. We treat
-	 *	the system call and bus error special, they get their
-	 *	own first level handlers.
-	 */
-#ifndef ENABLE_dBUG
-	for (i = 3; (i <= 23); i++)
-		_ramvec[i] = trap;
-	for (i = 33; (i <= 63); i++)
-		_ramvec[i] = trap;
-#endif
-
-	for (i = 24; (i <= 30); i++)
-		_ramvec[i] = inthandler;
-#ifndef ENABLE_dBUG
-	_ramvec[31] = inthandler;  // Disables the IRQ7 button
-#endif
-
-	for (i = 64; (i < 255); i++)
-		_ramvec[i] = inthandler;
-	_ramvec[255] = 0;
-
-	_ramvec[2] = buserr;
-	_ramvec[32] = system_call;
-}
-
-/***************************************************************************/
+	volatile unsigned char *icrp;
+	unsigned int icr, imr;
 
-#ifdef CONFIG_NETtel
-
-/*
- *	Routines to support the NETtel software reset button.
- */
-void reset_button(int irq, void *dev_id, struct pt_regs *regs)
-{
-	extern void	flash_eraseconfig(void);
-	static int	inbutton = 0;
-
-	/*
-	 *	IRQ7 is not maskable by the CPU core. It is possible
-	 *	that switch bounce may get us back here before we have
-	 *	really serviced the interrupt.
-	 */
-	if (inbutton)
-		return;
-	inbutton = 1;
-	/* Disable interrupt at SIM - best we can do... */
-	mcf_setimr(mcf_getimr() | MCFSIM_IMR_EINT7);
-	/* Try and de-bounce the switch a little... */
-	udelay(10000);
-
-	flash_eraseconfig();
-
-	/* Don't leave here 'till button is no longer pushed! */
-	for (;;) {
-		if ((mcf_getipr() & MCFSIM_IMR_EINT7) == 0)
-			break;
+	if (timer <= 2) {
+		switch (timer) {
+		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
+		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
+		}
+
+		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
+		mcf_setimr(mcf_getimr() & ~imr);
 	}
-
-	HARD_RESET_NOW();
-	/* Should never get here... */
-
-	inbutton = 0;
-	/* Interrupt service done, enable it again */
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7);
 }
 
 /***************************************************************************/
 
-void reset_setupbutton(void)
-{
-	mcf_autovector(31);
-	request_irq(31, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST),
-		"Reset Button", NULL);
-}
-
-#endif /* CONFIG_NETtel */
-
-/***************************************************************************/
-
 void config_BSP(char *commandp, int size)
 {
+	mcf_setimr(MCFSIM_IMR_MASKALL);
+
 #ifdef CONFIG_NETtel
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
@@ -227,7 +93,9 @@
 
 	mach_sched_init = coldfire_timer_init;
 	mach_tick = coldfire_tick;
+	mach_gettimeoffset = coldfire_timer_offset;
 	mach_trap_init = coldfire_trap_init;
+	mach_reset = coldfire_reset;
 }
 
 /***************************************************************************/
diff -Nru a/arch/m68knommu/platform/5249/Makefile b/arch/m68knommu/platform/5249/Makefile
--- a/arch/m68knommu/platform/5249/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/5249/Makefile	Sun Mar  9 14:15:54 2003
@@ -18,4 +18,4 @@
 
 obj-y := config.o
 
-EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/crt0_$(MODEL).o
diff -Nru a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c
--- a/arch/m68knommu/platform/5249/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5249/config.c	Thu Mar  6 03:12:30 2003
@@ -25,7 +25,11 @@
 
 /***************************************************************************/
 
-void	coldfire_profile_init(void);
+void coldfire_tick(void);
+void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
 
 /***************************************************************************/
 
@@ -39,105 +43,8 @@
         MCF_MBAR + MCFDMA_BASE3,
 };
 
-unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
-/***************************************************************************/
-
-void coldfire_tick(void)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-}
-
-/***************************************************************************/
-
-void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	/* Set up TIMER 1 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR);
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3;
-	request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-
-#ifdef CONFIG_HIGHPROFILE
-	coldfire_profile_init();
-#endif
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1);
-}
-
-/***************************************************************************/
-#ifdef CONFIG_HIGHPROFILE
 /***************************************************************************/
 
-#define	PROFILEHZ	1013
-
-/*
- *	Use the other timer to provide high accuracy profiling info.
- */
-
-void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer2 */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-
-        if (!user_mode(regs)) {
-                if (prof_buffer && current->pid) {
-                        extern int _stext;
-                        unsigned long ip = instruction_pointer(regs);
-                        ip -= (unsigned long) &_stext;
-                        ip >>= prof_shift;
-                        if (ip < prof_len)
-                                prof_buffer[ip]++;
-                }
-        }
-}
-
-void coldfire_profile_init(void)
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ);
-
-	/* Set up TIMER 2 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR);
-
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3;
-	request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST),
-		"Profile Timer", NULL);
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2);
-}
-
-/***************************************************************************/
-#endif	/* CONFIG_HIGHPROFILE */
-/***************************************************************************/
-
-/*
- *	Program the vector to be an auto-vectored.
- */
-
 void mcf_autovector(unsigned int vec)
 {
 	volatile unsigned char  *mbar;
@@ -152,78 +59,35 @@
 
 /***************************************************************************/
 
-extern e_vector	*_ramvec;
-
-void set_evector(int vecnum, void (*handler)(void))
-{
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
-/* assembler routines */
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void system_call(void);
-asmlinkage void inthandler(void);
-
-void __init coldfire_trap_init(void)
+void mcf_settimericr(unsigned int timer, unsigned int level)
 {
-	int i;
+	volatile unsigned char *icrp;
+	unsigned int icr, imr;
 
-#ifndef ENABLE_dBUG
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-#endif
-
-	/*
-	 *	There is a common trap handler and common interrupt
-	 *	handler that handle almost every vector. We treat
-	 *	the system call and bus error special, they get their
-	 *	own first level handlers.
-	 */
-#ifndef ENABLE_dBUG
-	for (i = 3; (i <= 23); i++)
-		_ramvec[i] = trap;
-	for (i = 33; (i <= 63); i++)
-		_ramvec[i] = trap;
-#endif
-
-	for (i = 24; (i <= 30); i++)
-		_ramvec[i] = inthandler;
-#ifndef ENABLE_dBUG
-	_ramvec[31] = inthandler;  // Disables the IRQ7 button
-#endif
-
-	for (i = 64; (i < 255); i++)
-		_ramvec[i] = inthandler;
-	_ramvec[255] = 0;
-
-	_ramvec[2] = buserr;
-	_ramvec[32] = system_call;
+	if (timer <= 2) {
+		switch (timer) {
+		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
+		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
+		}
+
+		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
+		mcf_setimr(mcf_getimr() & ~imr);
+	}
 }
 
 /***************************************************************************/
 
 void config_BSP(char *commandp, int size)
 {
+	mcf_setimr(MCFSIM_IMR_MASKALL);
 	memset(commandp, 0, size);
 
 	mach_sched_init = coldfire_timer_init;
 	mach_tick = coldfire_tick;
+	mach_gettimeoffset = coldfire_timer_offset;
 	mach_trap_init = coldfire_trap_init;
+	mach_reset = coldfire_reset;
 }
 
-/***************************************************************************/
-#ifdef TRAP_DBG_INTERRUPT
-
-asmlinkage void dbginterrupt_c(struct frame *fp)
-{
-	extern void dump(struct pt_regs *fp);
-	printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__);
-        dump((struct pt_regs *) fp);
-	asm("halt");
-}
-
-#endif
 /***************************************************************************/
diff -Nru a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile
--- a/arch/m68knommu/platform/5272/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/5272/Makefile	Sun Mar  9 14:15:54 2003
@@ -18,4 +18,4 @@
 
 obj-y := config.o
 
-EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/crt0_$(MODEL).o
diff -Nru a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
--- a/arch/m68knommu/platform/5272/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5272/config.c	Thu Mar  6 03:12:30 2003
@@ -26,7 +26,15 @@
 
 /***************************************************************************/
 
-void	reset_setupbutton(void);
+void coldfire_tick(void);
+void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+extern unsigned int mcf_timervector;
+extern unsigned int mcf_profilevector;
+extern unsigned int mcf_timerlevel;
 
 /***************************************************************************/
 
@@ -37,50 +45,21 @@
         MCF_MBAR + MCFDMA_BASE0,
 };
 
-unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
 /***************************************************************************/
 
-void coldfire_tick(void)
+void mcf_disableall(void)
 {
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE4);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-}
-
-/***************************************************************************/
-
-void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
-{
-	volatile unsigned short	*timerp;
 	volatile unsigned long	*icrp;
 
-	/* Set up TIMER 4 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE4);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
 	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = 0x0000000d; /* TMR4 with priority 5 */
-	request_irq(72, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-
-#ifdef CONFIG_RESETSWITCH
-	/* This is not really the right place to do this... */
-	reset_setupbutton();
-#endif
+	icrp[0] = 0x88888888;
+	icrp[1] = 0x88888888;
+	icrp[2] = 0x88888888;
+	icrp[3] = 0x88888888;
 }
 
 /***************************************************************************/
 
-/*
- *	Program the vector to be an auto-vectored.
- */
-
 void mcf_autovector(unsigned int vec)
 {
 	/* Everything is auto-vectored on the 5272 */
@@ -88,68 +67,20 @@
 
 /***************************************************************************/
 
-extern e_vector	*_ramvec;
-
-void set_evector(int vecnum, void (*handler)(void))
+void mcf_settimericr(int timer, int level)
 {
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
-/* assembler routines */
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void system_call(void);
-asmlinkage void inthandler(void);
-
-void coldfire_trap_init(void)
-{
-	int i;
-
-#ifndef ENABLE_dBUG
-	volatile unsigned long	*icrp;
-
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	icrp[0] = 0x88888888;
-	icrp[1] = 0x88888888;
-	icrp[2] = 0x88888888;
-	icrp[3] = 0x88888888;
-#endif
-
-	/*
-	 *	There is a common trap handler and common interrupt
-	 *	handler that handle almost every vector. We treat
-	 *	the system call and bus error special, they get their
-	 *	own first level handlers.
-	 */
-#ifndef ENABLE_dBUG
-	for (i = 3; (i <= 23); i++)
-		_ramvec[i] = trap;
-	for (i = 33; (i <= 63); i++)
-		_ramvec[i] = trap;
-#endif
+	volatile unsigned long *icrp;
+	unsigned int icr;
 
-	for (i = 24; (i <= 30); i++)
-		_ramvec[i] = inthandler;
-#ifndef ENABLE_dBUG
-	_ramvec[31] = inthandler;  // Disables the IRQ7 button
-#endif
-
-	for (i = 64; (i < 255); i++)
-		_ramvec[i] = inthandler;
-	_ramvec[255] = 0;
-
-	_ramvec[2] = buserr;
-	_ramvec[32] = system_call;
-}
-
-/***************************************************************************/
+	switch (timer) {
+	case 2:  icr = MCFSIM_ICR2; break;
+	case 3:  icr = MCFSIM_ICR3; break;
+	case 4:  icr = MCFSIM_ICR4; break;
+	default: icr = MCFSIM_ICR1; break;
+	}
 
-void coldfire_reset(void)
-{
-	HARD_RESET_NOW();
+	icrp = (volatile unsigned long *) (MCF_MBAR + icr);
+	*icrp = (0x8 | level) << ((4 - timer) * 4);
 }
 
 /***************************************************************************/
@@ -164,8 +95,9 @@
 	*pivrp = 0x40;
 #endif
 
-#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
-    defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3)
+	mcf_disableall();
+
+#if defined(CONFIG_NETtel)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
 	commandp[size-1] = 0;
@@ -177,71 +109,13 @@
 	memset(commandp, 0, size);
 #endif
 
+	mcf_timervector = 69;
+	mcf_profilevector = 70;
 	mach_sched_init = coldfire_timer_init;
 	mach_tick = coldfire_tick;
+	mach_gettimeoffset = coldfire_timer_offset;
 	mach_trap_init = coldfire_trap_init;
 	mach_reset = coldfire_reset;
 }
 
-/***************************************************************************/
-#ifdef CONFIG_RESETSWITCH
-/***************************************************************************/
-
-/*
- *	Routines to support the NETtel software reset button.
- */
-void reset_button(int irq, void *dev_id, struct pt_regs *regs)
-{
-	volatile unsigned long	*icrp, *isrp;
-	extern void		flash_eraseconfig(void);
-	static int		inbutton = 0;
-
-	/*
-	 *	IRQ7 is not maskable by the CPU core. It is possible
-	 *	that switch bounce mey get us back here before we have
-	 *	really serviced the interrupt.
-	 */
-	if (inbutton)
-		return;
-	inbutton = 1;
-
-	/* Disable interrupt at SIM - best we can do... */
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = (*icrp & 0x07777777) | 0x80000000;
-
-	/* Try and de-bounce the switch a little... */
-	udelay(10000);
-
-	flash_eraseconfig();
-
-	/* Don't leave here 'till button is no longer pushed! */
-	isrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ISR);
-	for (;;) {
-		if (*isrp & 0x80000000)
-			break;
-	}
-
-	HARD_RESET_NOW();
-	/* Should never get here... */
-
-	inbutton = 0;
-	/* Interrupt service done, acknowledge it */
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = (*icrp & 0x07777777) | 0xf0000000;
-}
-
-/***************************************************************************/
-
-void reset_setupbutton(void)
-{
-	volatile unsigned long	*icrp;
-
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = (*icrp & 0x07777777) | 0xf0000000;
-	request_irq(65, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST),
-		"Reset Button", NULL);
-}
-
-/***************************************************************************/
-#endif /* CONFIG_RESETSWITCH */
 /***************************************************************************/
diff -Nru a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
--- a/arch/m68knommu/platform/5307/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/5307/Makefile	Sat Mar 15 21:52:29 2003
@@ -16,9 +16,9 @@
 AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
 endif
 
-obj-$(CONFIG_COLDFIRE)	+= entry.o
+obj-$(CONFIG_COLDFIRE)	+= entry.o timers.o vectors.o
 obj-$(CONFIG_M5307)	+= config.o
 
 ifeq ($(CONFIG_M5307),y)
-EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/crt0_$(MODEL).o
 endif
diff -Nru a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
--- a/arch/m68knommu/platform/5307/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5307/config.c	Thu Mar  6 03:12:30 2003
@@ -23,17 +23,19 @@
 #include <asm/mcfsim.h>
 #include <asm/mcfdma.h>
 #include <asm/delay.h>
-
-#if defined(CONFIG_eLIA)
-#include <asm/elia.h>
-#endif
-
 #include <asm/mcfwdebug.h>
 
 /***************************************************************************/
 
-void	reset_setupbutton(void);
-void	coldfire_profile_init(void);
+void coldfire_tick(void);
+void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+extern unsigned int mcf_timervector;
+extern unsigned int mcf_profilevector;
+extern unsigned int mcf_timerlevel;
 
 /***************************************************************************/
 
@@ -47,118 +49,8 @@
         MCF_MBAR + MCFDMA_BASE3,
 };
 
-unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
 /***************************************************************************/
 
-void coldfire_tick(void)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-}
-
-/***************************************************************************/
-
-void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	/* Set up TIMER 1 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR);
-
-#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
-		defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
-		defined(CONFIG_CLEOPATRA) 
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3;
-	request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-#else
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3;
-	request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-#endif
-
-#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
-		defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3)
-	/* This is not really the right place to do this... */
-	reset_setupbutton();
-#endif
-#ifdef CONFIG_HIGHPROFILE
-	coldfire_profile_init();
-#endif
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1);
-}
-
-/***************************************************************************/
-#ifdef CONFIG_HIGHPROFILE
-/***************************************************************************/
-
-#define	PROFILEHZ	1013
-
-/*
- *	Use the other timer to provide high accuracy profiling info.
- */
-
-void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer2 */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-
-        if (!user_mode(regs)) {
-                if (prof_buffer && current->pid) {
-                        extern int _stext;
-                        unsigned long ip = instruction_pointer(regs);
-                        ip -= (unsigned long) &_stext;
-                        ip >>= prof_shift;
-                        if (ip < prof_len)
-                                prof_buffer[ip]++;
-                }
-        }
-}
-
-void coldfire_profile_init(void)
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ);
-
-	/* Set up TIMER 2 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR);
-
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3;
-	request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST),
-		"Profile Timer", NULL);
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2);
-}
-
-/***************************************************************************/
-#endif	/* CONFIG_HIGHPROFILE */
-/***************************************************************************/
-
-/*
- *	Program the vector to be an auto-vectored.
- */
-
 void mcf_autovector(unsigned int vec)
 {
 	volatile unsigned char  *mbar;
@@ -173,165 +65,57 @@
 
 /***************************************************************************/
 
-extern e_vector	*_ramvec;
-
-void set_evector(int vecnum, void (*handler)(void))
-{
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
-/* assembler routines */
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void system_call(void);
-asmlinkage void inthandler(void);
-
-#ifdef TRAP_DBG_INTERRUPT
-asmlinkage void dbginterrupt(void);
-#endif
-
-void __init coldfire_trap_init(void)
-{
-	int i;
-
-#ifndef ENABLE_dBUG
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-#endif
-
-	/*
-	 *	There is a common trap handler and common interrupt
-	 *	handler that handle almost every vector. We treat
-	 *	the system call and bus error special, they get their
-	 *	own first level handlers.
-	 */
-#ifndef ENABLE_dBUG
-	for (i = 3; (i <= 23); i++)
-		_ramvec[i] = trap;
-	for (i = 33; (i <= 63); i++)
-		_ramvec[i] = trap;
-#endif
-#ifdef TRAP_DBG_INTERRUPT
-	_ramvec[12] = dbginterrupt;
-#endif
-
-	for (i = 24; (i <= 30); i++)
-		_ramvec[i] = inthandler;
-#ifndef ENABLE_dBUG
-	_ramvec[31] = inthandler;  // Disables the IRQ7 button
-#endif
-
-	for (i = 64; (i < 255); i++)
-		_ramvec[i] = inthandler;
-	_ramvec[255] = 0;
-
-	_ramvec[2] = buserr;
-	_ramvec[32] = system_call;
-#ifdef MCF_BDM_DISABLE
-	/* Disable the BDM clocking.  This also turns off most of the rest of
-	 * the BDM device.  This is good for EMC reasons.  This option is not
-	 * incompatible with the memory protection option.
-	 */
-	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
-#endif
-
-}
-
-/***************************************************************************/
-
-#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
-	defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3)
-
-/*
- *	Routines to support the NETtel software reset button.
- */
-void reset_button(int irq, void *dev_id, struct pt_regs *regs)
+void mcf_settimericr(unsigned int timer, unsigned int level)
 {
-	extern void	flash_eraseconfig(void);
-	static int	inbutton = 0;
+	volatile unsigned char *icrp;
+	unsigned int icr, imr;
 
-	/*
-	 *	IRQ7 is not maskable by the CPU core. It is possible
-	 *	that switch bounce mey get us back here before we have
-	 *	really serviced the interrupt.
-	 */
-	if (inbutton)
-		return;
-	inbutton = 1;
-	/* Disable interrupt at SIM - best we can do... */
-	mcf_setimr(mcf_getimr() | MCFSIM_IMR_EINT7);
-	/* Try and de-bounce the switch a little... */
-	udelay(10000);
-
-	flash_eraseconfig();
-
-	/* Don't leave here 'till button is no longer pushed! */
-	for (;;) {
-		if ((mcf_getipr() & MCFSIM_IMR_EINT7) == 0)
-			break;
+	if (timer <= 2) {
+		switch (timer) {
+		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
+		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
+		}
+
+		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
+		mcf_setimr(mcf_getimr() & ~imr);
 	}
-
-	HARD_RESET_NOW();
-	/* Should never get here... */
-
-	inbutton = 0;
-	/* Interrupt service done, enable it again */
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7);
-}
-
-/***************************************************************************/
-
-void reset_setupbutton(void)
-{
-	volatile unsigned char	*mbar;
-
-	mbar = (volatile unsigned char *) MCF_MBAR;
-	*(mbar + MCFSIM_AVR) |= MCFSIM_IMR_EINT7;
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7);
-	request_irq(31, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST),
-		"Reset Button", NULL);
-}
-
-#endif /* CONFIG_NETtel || CONFIG_eLIA || CONFIG_DISKtel || CONFIG_SECUREEDGEMP3 */
-
-/***************************************************************************/
-
-void coldfire_reset(void)
-{
-	HARD_RESET_NOW();
 }
 
 /***************************************************************************/
 
 void config_BSP(char *commandp, int size)
 {
+	mcf_setimr(MCFSIM_IMR_MASKALL);
+
 #if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
-    defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3)
+    defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
+    defined(CONFIG_CLEOPATRA)
 	/* Copy command line from FLASH to local buffer... */
 	memcpy(commandp, (char *) 0xf0004000, size);
 	commandp[size-1] = 0;
+	/* Different timer setup - to prevent device clash */
+	mcf_timervector = 30;
+	mcf_profilevector = 31;
+	mcf_timerlevel = 6;
 #else
 	memset(commandp, 0, size);
-#endif /* CONFIG_NETtel || CONFIG_eLIA || CONFIG_DISKtel || CONFIG_SECUREEDGEMP3 */
+#endif
 
 	mach_sched_init = coldfire_timer_init;
 	mach_tick = coldfire_tick;
+	mach_gettimeoffset = coldfire_timer_offset;
 	mach_trap_init = coldfire_trap_init;
 	mach_reset = coldfire_reset;
-}
 
-/***************************************************************************/
-#ifdef TRAP_DBG_INTERRUPT
-
-asmlinkage void dbginterrupt_c(struct frame *fp)
-{
-	extern void dump(struct pt_regs *fp);
-	printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__);
-	dump((struct pt_regs *) fp);
-	asm("halt");
+#ifdef MCF_BDM_DISABLE
+	/*
+	 * Disable the BDM clocking.  This also turns off most of the rest of
+	 * the BDM device.  This is good for EMC reasons. This option is not
+	 * incompatible with the memory protection option.
+	 */
+	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
+#endif
 }
 
-#endif
 /***************************************************************************/
diff -Nru a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/m68knommu/platform/5307/timers.c	Thu Mar  6 03:12:30 2003
@@ -0,0 +1,127 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5307/timers.c
+ *
+ *	Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+/*
+ *	Default the timer and vector to use for ColdFire. Some ColdFire
+ *	CPU's and some boards may want different. Their sub-architecture
+ *	startup code (in config.c) can change these if they want.
+ */
+unsigned int	mcf_timervector = 29;
+unsigned int	mcf_profilevector = 31;
+unsigned int	mcf_timerlevel = 5;
+
+static volatile struct mcftimer *mcf_timerp;
+
+/***************************************************************************/
+
+void coldfire_tick(void)
+{
+	/* Reset the ColdFire timer */
+	mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+}
+
+void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
+{
+	/* Set up an internal TIMER as poll clock */
+	mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1);
+	mcf_timerp->tmr = MCFTIMER_TMR_DISABLE;
+
+	mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ);
+	mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+
+	request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL);
+	mcf_settimericr(1, mcf_timerlevel);
+
+#ifdef CONFIG_HIGHPROFILE
+	coldfire_profile_init();
+#endif
+}
+
+/***************************************************************************/
+
+unsigned long coldfire_timer_offset(void)
+{
+	unsigned long trr, tcn;
+
+	/* Get the values as longs for accurate calculation. */
+	tcn = mcf_timerp->tcn;
+	trr = mcf_timerp->trr;
+	return((tcn * (1000000 / HZ)) / trr);
+}
+
+/***************************************************************************/
+#ifdef CONFIG_HIGHPROFILE
+/***************************************************************************/
+
+/*
+ *	Choose a reasonably fast profile timer. Make it an odd value to
+ *	try and get good coverage of kernal operations.
+ */
+#define	PROFILEHZ	1013
+
+static volatile struct mcftimer *mcf_proftp;
+
+/*
+ *	Use the other timer to provide high accuracy profiling info.
+ */
+
+void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
+{
+	/* Reset ColdFire timer2 */
+	mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+
+        if (!user_mode(regs)) {
+                if (prof_buffer && current->pid) {
+                        extern int _stext;
+                        unsigned long ip = instruction_pointer(regs);
+                        ip -= (unsigned long) &_stext;
+                        ip >>= prof_shift;
+                        if (ip < prof_len)
+                                prof_buffer[ip]++;
+                }
+        }
+}
+
+void coldfire_profile_init(void)
+{
+	printk("PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ);
+
+	/* Set up TIMER 2 as high speed profile clock */
+	mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2);
+	mcf_proftp->tmr = MCFTIMER_TMR_DISABLE;
+
+	mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ);
+	mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+
+	request_irq(mcf_profilevector, coldfire_profile_tick,
+		(SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL);
+	mcf_settimericr(2, 7);
+}
+
+/***************************************************************************/
+#endif	/* CONFIG_HIGHPROFILE */
+/***************************************************************************/
diff -Nru a/arch/m68knommu/platform/5407/Makefile b/arch/m68knommu/platform/5407/Makefile
--- a/arch/m68knommu/platform/5407/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/5407/Makefile	Sun Mar  9 14:15:54 2003
@@ -18,4 +18,4 @@
 
 obj-y := config.o
 
-EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/crt0_$(MODEL).o
diff -Nru a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c
--- a/arch/m68knommu/platform/5407/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5407/config.c	Thu Mar  6 03:12:30 2003
@@ -26,7 +26,15 @@
 
 /***************************************************************************/
 
-void	coldfire_profile_init(void);
+void coldfire_tick(void);
+void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+extern unsigned int mcf_timervector;
+extern unsigned int mcf_profilevector;
+extern unsigned int mcf_timerlevel;
 
 /***************************************************************************/
 
@@ -40,111 +48,8 @@
         MCF_MBAR + MCFDMA_BASE3,
 };
 
-unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
-/***************************************************************************/
-
-void coldfire_tick(void)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-}
-
-/***************************************************************************/
-
-void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	/* Set up TIMER 1 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR);
-
-#if defined(CONFIG_CLEOPATRA)
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3;
-	request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-#else
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3;
-	request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
-#endif
-
-#ifdef CONFIG_HIGHPROFILE
-	coldfire_profile_init();
-#endif
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1);
-}
-
-/***************************************************************************/
-#ifdef CONFIG_HIGHPROFILE
-/***************************************************************************/
-
-#define	PROFILEHZ	1013
-
-/*
- *	Use the other timer to provide high accuracy profiling info.
- */
-
-void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
-{
-	volatile unsigned char	*timerp;
-
-	/* Reset the ColdFire timer2 */
-	timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2);
-	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-
-        if (!user_mode(regs)) {
-                if (prof_buffer && current->pid) {
-                        extern int _stext;
-                        unsigned long ip = instruction_pointer(regs);
-                        ip -= (unsigned long) &_stext;
-                        ip >>= prof_shift;
-                        if (ip < prof_len)
-                                prof_buffer[ip]++;
-                }
-        }
-}
-
-void coldfire_profile_init(void)
-{
-	volatile unsigned short	*timerp;
-	volatile unsigned char	*icrp;
-
-	printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ);
-
-	/* Set up TIMER 2 as poll clock */
-	timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
-
-	timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ);
-	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
-
-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR);
-
-	*icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3;
-	request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST),
-		"Profile Timer", NULL);
-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2);
-}
-
-/***************************************************************************/
-#endif	/* CONFIG_HIGHPROFILE */
 /***************************************************************************/
 
-/*
- *	Program the vector to be an auto-vectored.
- */
-
 void mcf_autovector(unsigned int vec)
 {
 	volatile unsigned char  *mbar;
@@ -159,78 +64,42 @@
 
 /***************************************************************************/
 
-extern e_vector	*_ramvec;
-
-void set_evector(int vecnum, void (*handler)(void))
+void mcf_settimericr(unsigned int timer, unsigned int level)
 {
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
-/* assembler routines */
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void system_call(void);
-asmlinkage void inthandler(void);
-
-void __init coldfire_trap_init(void)
-{
-	int i;
-
-#ifndef ENABLE_dBUG
-	mcf_setimr(MCFSIM_IMR_MASKALL);
-#endif
-
-	/*
-	 *	There is a common trap handler and common interrupt
-	 *	handler that handle almost every vector. We treat
-	 *	the system call and bus error special, they get their
-	 *	own first level handlers.
-	 */
-#ifndef ENABLE_dBUG
-	for (i = 3; (i <= 23); i++)
-		_ramvec[i] = trap;
-	for (i = 33; (i <= 63); i++)
-		_ramvec[i] = trap;
-#endif
-
-	for (i = 24; (i <= 30); i++)
-		_ramvec[i] = inthandler;
-#ifndef ENABLE_dBUG
-	_ramvec[31] = inthandler;  // Disables the IRQ7 button
-#endif
+	volatile unsigned char *icrp;
+	unsigned int icr, imr;
 
-	for (i = 64; (i < 255); i++)
-		_ramvec[i] = inthandler;
-	_ramvec[255] = 0;
-
-	_ramvec[2] = buserr;
-	_ramvec[32] = system_call;
+	if (timer <= 2) {
+		switch (timer) {
+		case 2:  icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
+		default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
+		}
+
+		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+		*icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
+		mcf_setimr(mcf_getimr() & ~imr);
+	}
 }
 
 /***************************************************************************/
 
 void config_BSP(char *commandp, int size)
 {
+	mcf_setimr(MCFSIM_IMR_MASKALL);
 	memset(commandp, 0, size);
 
+#if defined(CONFIG_CLEOPATRA)
+	/* Different timer setup - to prevent device clash */
+	mcf_timervector = 30;
+	mcf_profilevector = 31;
+	mcf_timerlevel = 6;
+#endif
+
 	mach_sched_init = coldfire_timer_init;
 	mach_tick = coldfire_tick;
+	mach_gettimeoffset = coldfire_timer_offset;
 	mach_trap_init = coldfire_trap_init;
+	mach_reset = coldfire_reset;
 }
 
-/***************************************************************************/
-#ifdef TRAP_DBG_INTERRUPT
-
-asmlinkage void dbginterrupt_c(struct frame *fp)
-{
-	extern void dump(struct pt_regs *fp);
-	printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__);
-        dump((struct pt_regs *) fp);
-	asm("halt");
-}
-
-#endif
 /***************************************************************************/
diff -Nru a/arch/m68knommu/platform/68328/Makefile b/arch/m68knommu/platform/68328/Makefile
--- a/arch/m68knommu/platform/68328/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/68328/Makefile	Sun Mar  9 14:15:54 2003
@@ -7,7 +7,7 @@
 obj-$(CONFIG_M68VZ328)	+= entry.o ints.o
 
 ifeq ($(CONFIG_M68328),y)
-EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o
 endif
 
 $(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h
diff -Nru a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S
--- a/arch/m68knommu/platform/68328/entry.S	Tue Feb 18 10:31:36 2003
+++ b/arch/m68knommu/platform/68328/entry.S	Mon Mar 10 16:25:35 2003
@@ -14,6 +14,7 @@
 #include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
+#include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/setup.h>
 #include <asm/segment.h>
diff -Nru a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
--- a/arch/m68knommu/platform/68328/ints.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/68328/ints.c	Mon Mar 10 16:25:35 2003
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
+#include <linux/errno.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
diff -Nru a/arch/m68knommu/platform/68360/Makefile b/arch/m68knommu/platform/68360/Makefile
--- a/arch/m68knommu/platform/68360/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/68360/Makefile	Sun Mar  9 14:15:54 2003
@@ -4,4 +4,4 @@
 
 obj-y := config.o commproc.o entry.o ints.o
 
-EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/crt0_$(MODEL).o
diff -Nru a/arch/m68knommu/platform/68360/commproc.c b/arch/m68knommu/platform/68360/commproc.c
--- a/arch/m68knommu/platform/68360/commproc.c	Tue Feb 18 10:31:36 2003
+++ b/arch/m68knommu/platform/68360/commproc.c	Mon Mar 10 16:25:35 2003
@@ -71,7 +71,7 @@
 static	void	cpm_error_interrupt(void *);
 
 /* prototypes: */
-void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id);
+void cpm_install_handler(int vec, void (*handler)(), void *dev_id);
 void m360_cpm_reset(void);
 
 
@@ -207,7 +207,7 @@
 /* Install a CPM interrupt handler.
 */
 void
-cpm_install_handler(int vec, void (*handler)(void *), void *dev_id)
+cpm_install_handler(int vec, void (*handler)(), void *dev_id)
 {
 
 	request_irq(vec, handler, IRQ_FLG_LOCK, "timer", dev_id);
diff -Nru a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S
--- a/arch/m68knommu/platform/68360/entry.S	Tue Feb 18 10:31:36 2003
+++ b/arch/m68knommu/platform/68360/entry.S	Mon Mar 10 16:25:35 2003
@@ -16,6 +16,7 @@
 #include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
+#include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/setup.h>
 #include <asm/segment.h>
diff -Nru a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c
--- a/arch/m68knommu/platform/68360/ints.c	Tue Feb 25 10:44:00 2003
+++ b/arch/m68knommu/platform/68360/ints.c	Mon Mar 10 16:25:35 2003
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
+#include <linux/errno.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
diff -Nru a/arch/m68knommu/platform/68EZ328/Makefile b/arch/m68knommu/platform/68EZ328/Makefile
--- a/arch/m68knommu/platform/68EZ328/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/68EZ328/Makefile	Sun Mar  9 14:15:54 2003
@@ -4,7 +4,7 @@
 
 obj-y := config.o
 
-EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o
+extra-y := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o
 
 $(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h
 	perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \
diff -Nru a/arch/m68knommu/platform/68VZ328/Makefile b/arch/m68knommu/platform/68VZ328/Makefile
--- a/arch/m68knommu/platform/68VZ328/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/m68knommu/platform/68VZ328/Makefile	Sat Mar 15 21:54:00 2003
@@ -2,11 +2,5 @@
 # Makefile for arch/m68knommu/platform/68VZ328.
 #
 
-obj-y := $(BOARD)/config.o
-
-EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o
-
-$(obj)/$(BOARD)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h
-	perl $(src)/../68328/bootlogo.pl < $(src)/../68EZ328/bootlogo.h \
-		> $(obj)/$(BOARD)/bootlogo.rh
+obj-y := $(BOARD)/
 
diff -Nru a/arch/m68knommu/platform/68VZ328/de2/Makefile b/arch/m68knommu/platform/68VZ328/de2/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/m68knommu/platform/68VZ328/de2/Makefile	Mon Mar 10 16:25:35 2003
@@ -0,0 +1,12 @@
+#
+# Makefile for arch/m68knommu/platform/68VZ328/de2.
+#
+
+obj-y := config.o
+
+EXTRA_TARGETS := bootlogo.rh crt0_$(MODEL).o
+
+$(obj)/bootlogo.rh: $(src)/../../68EZ328/bootlogo.h
+	perl $(src)/../../68328/bootlogo.pl < $(src)/../../68EZ328/bootlogo.h \
+		> $(obj)/bootlogo.rh
+
diff -Nru a/arch/m68knommu/platform/68VZ328/de2/config.c b/arch/m68knommu/platform/68VZ328/de2/config.c
--- a/arch/m68knommu/platform/68VZ328/de2/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/68VZ328/de2/config.c	Mon Mar 10 16:25:35 2003
@@ -147,5 +147,5 @@
 	mach_reset           = dragen2_reset;
 	mach_gettod          = dragen2_gettod;
 
-	config_M68VZ328_irq();
+	config_M68328_irq();
 }
diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/Makefile b/arch/m68knommu/platform/68VZ328/ucdimm/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/m68knommu/platform/68VZ328/ucdimm/Makefile	Mon Mar 10 16:25:36 2003
@@ -0,0 +1,12 @@
+#
+# Makefile for arch/m68knommu/platform/68VZ328/ucdimm.
+#
+
+obj-y := config.o
+
+EXTRA_TARGETS := bootlogo.rh crt0_$(MODEL).o
+
+$(obj)/bootlogo.rh: $(src)/../../68EZ328/bootlogo.h
+	perl $(src)/../../68328/bootlogo.pl < $(src)/../../68EZ328/bootlogo.h \
+		> $(obj)/bootlogo.rh
+
diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/config.c b/arch/m68knommu/platform/68VZ328/ucdimm/config.c
--- a/arch/m68knommu/platform/68VZ328/ucdimm/config.c	Tue Feb 18 02:27:40 2003
+++ b/arch/m68knommu/platform/68VZ328/ucdimm/config.c	Mon Mar 10 16:25:35 2003
@@ -115,5 +115,5 @@
 	mach_gettod          = BSP_gettod;
 	mach_reset           = BSP_reset;
 
-	config_M68VZ328_irq();
+	config_M68328_irq();
 }
diff -Nru a/arch/m68knommu/vmlinux.lds.S b/arch/m68knommu/vmlinux.lds.S
--- a/arch/m68knommu/vmlinux.lds.S	Tue Feb 18 02:27:38 2003
+++ b/arch/m68knommu/vmlinux.lds.S	Mon Mar 17 03:25:37 2003
@@ -126,7 +126,7 @@
 
 /*
  *	The standard Arnewsh 5206 board only has 1MiB of ram. Not normally
- *	enough to be usefull. Assume the user has fitted something larger,
+ *	enough to be useful. Assume the user has fitted something larger,
  *	at least 4MiB in size. No point in not letting the kernel completely
  *	link, it will be obvious if it is too big when they go to load it.
  */
@@ -300,6 +300,9 @@
 		*(.initcall6.init)
 		*(.initcall7.init)
 		__initcall_end = .;
+		__con_initcall_start = .;
+		*(.con_initcall.init)
+		__con_initcall_end = .;
 		. = ALIGN(4);
 		__initramfs_start = .;
 		*(.init.ramfs)
diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig
--- a/arch/mips/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/mips/Kconfig	Sat Mar  8 14:50:37 2003
@@ -10,10 +10,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config SMP
 	bool
 	---help---
diff -Nru a/arch/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c
--- a/arch/mips/arc/arc_con.c	Tue Feb  5 10:12:45 2002
+++ b/arch/mips/arc/arc_con.c	Fri Feb 14 15:09:50 2003
@@ -63,7 +63,8 @@
  *    Register console.
  */
 
-void __init arc_console_init(void)
+static void __init arc_console_init(void)
 {
 	register_console(&arc_cons);
 }
+console_initcall(arc_console_init);
diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c
--- a/arch/mips/au1000/common/serial.c	Mon Feb 24 10:28:52 2003
+++ b/arch/mips/au1000/common/serial.c	Thu Mar  6 09:10:40 2003
@@ -3054,10 +3054,11 @@
 /*
  *	Register console.
  */
-void __init au1000_serial_console_init(void)
+static void __init au1000_serial_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(au1000_serial_console_init);
 #endif
 
 /*
diff -Nru a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c
--- a/arch/mips/baget/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/baget/irq.c	Sat Mar  8 14:50:43 2003
@@ -146,11 +146,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < BAGET_IRQ_NR ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -161,6 +163,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips/ddb5074/pci.c b/arch/mips/ddb5074/pci.c
--- a/arch/mips/ddb5074/pci.c	Fri Nov  1 09:33:01 2002
+++ b/arch/mips/ddb5074/pci.c	Sun Mar 16 14:16:30 2003
@@ -297,11 +297,6 @@
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
-					 struct pbus_set_ranges_data *ranges)
-{
-}
-
 int pcibios_enable_resources(struct pci_dev *dev)
 {
 	u16 cmd, old_cmd;
@@ -339,37 +334,6 @@
 int pcibios_enable_device(struct pci_dev *dev)
 {
 	return pcibios_enable_resources(dev);
-}
-
-void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			     struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-
-	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4 * resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/*
-		 * Somebody might have asked allocation of a non-standard
-		 * resource
-		 */
-		return;
-	}
-
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) &
-	    ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
-	     PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
 }
 
 void pcibios_align_resource(void *data, struct resource *res,
diff -Nru a/arch/mips/ddb5476/pci.c b/arch/mips/ddb5476/pci.c
--- a/arch/mips/ddb5476/pci.c	Fri Nov  1 09:33:01 2002
+++ b/arch/mips/ddb5476/pci.c	Sun Mar 16 14:16:30 2003
@@ -341,8 +341,10 @@
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
-					 struct pbus_set_ranges_data *ranges)
+#if 0	/*  original DDB5074 code */
+void __devinit
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res)
 {
 	/*
 	 * our caller figure out range by going through the dev structures.  
@@ -350,15 +352,14 @@
 	 * different view of the addressing space.
 	 */
 
-#if 0	/*  original DDB5074 code */
 	   if (bus->number == 0) {
 	   ranges->io_start -= bus->resource[0]->start;
 	   ranges->io_end -= bus->resource[0]->start;
 	   ranges->mem_start -= bus->resource[1]->start;
 	   ranges->mem_end -= bus->resource[1]->start;
 	   }
-#endif
 }
+#endif
 
 int pcibios_enable_resources(struct pci_dev *dev)
 {
@@ -397,37 +398,6 @@
 int pcibios_enable_device(struct pci_dev *dev)
 {
 	return pcibios_enable_resources(dev);
-}
-
-void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			     struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-
-	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4 * resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/*
-		 * Somebody might have asked allocation of a non-standard
-		 * resource
-		 */
-		return;
-	}
-
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) &
-	    ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
-	     PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
 }
 
 void pcibios_align_resource(void *data, struct resource *res,
diff -Nru a/arch/mips/ddb5xxx/common/pci.c b/arch/mips/ddb5xxx/common/pci.c
--- a/arch/mips/ddb5xxx/common/pci.c	Mon Feb 24 12:51:23 2003
+++ b/arch/mips/ddb5xxx/common/pci.c	Sun Mar 16 14:16:30 2003
@@ -170,11 +170,3 @@
 	/* this should not be called */
 	MIPS_ASSERT(1 == 0);
 }
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                             struct resource *res, int resource)
-{
-	/* this should not be called */
-	MIPS_ASSERT(1 == 0);
-}
diff -Nru a/arch/mips/dec/irq.c b/arch/mips/dec/irq.c
--- a/arch/mips/dec/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/dec/irq.c	Sat Mar  8 14:50:43 2003
@@ -97,11 +97,13 @@
 {
 	int i;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 32; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 				i, kstat_cpu(0).irqs[i],
 				(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -112,6 +114,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips/gt64120/common/pci.c b/arch/mips/gt64120/common/pci.c
--- a/arch/mips/gt64120/common/pci.c	Fri Aug 30 06:59:50 2002
+++ b/arch/mips/gt64120/common/pci.c	Sun Mar 16 14:16:31 2003
@@ -785,39 +785,6 @@
 	return pcibios_enable_resources(dev);
 }
 
-void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			     struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-
-	return;
-
-	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4 * resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/*
-		 * Somebody might have asked allocation of a non-standard
-		 * resource
-		 */
-		return;
-	}
-
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) &
-	    ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
-	     PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
-}
-
 void pcibios_align_resource(void *data, struct resource *res,
 			    unsigned long size, unsigned long align)
 {
diff -Nru a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
--- a/arch/mips/ite-boards/generic/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/ite-boards/generic/irq.c	Sat Mar  8 14:50:43 2003
@@ -222,6 +222,7 @@
 {
         int i, j;
         struct irqaction * action;
+	unsigned long flags;
 
         seq_printf(p, "           ");
         for (j=0; j<smp_num_cpus; j++)
@@ -229,20 +230,25 @@
 	seq_putc(p, '\n');
 
         for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
                 action = irq_desc[i].action;
+
                 if ( !action || !action->handler )
-                        continue;
+                        goto skip;
                 seq_printf(p, "%3d: ", i);		
                 seq_printf(p, "%10u ", kstat_irqs(i));
                 if ( irq_desc[i].handler )		
                         seq_printf(p, " %s ", irq_desc[i].handler->typename );
                 else
                         seq_puts(p, "  None      ");
+
                 seq_printf(p, "    %s",action->name);
                 for (action=action->next; action; action = action->next) {
                         seq_printf(p, ", %s", action->name);
                 }
                 seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
         }
         seq_printf(p, "BAD: %10lu\n", spurious_count);
         return 0;
@@ -437,6 +443,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &it8172_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 	/*
diff -Nru a/arch/mips/ite-boards/generic/it8172_pci.c b/arch/mips/ite-boards/generic/it8172_pci.c
--- a/arch/mips/ite-boards/generic/it8172_pci.c	Fri Aug 30 06:59:50 2002
+++ b/arch/mips/ite-boards/generic/it8172_pci.c	Sun Mar 16 14:16:31 2003
@@ -196,19 +196,7 @@
 	return str;
 }
 
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                        struct resource *res, int resource)
-{
-	unsigned long where, size;
-	u32 reg;
-
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
-	size = res->end - res->start;
-	pci_read_config_dword(dev, where, &reg);
-	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-	pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
 
 void __init pcibios_fixup_bus(struct pci_bus *b)
 {
diff -Nru a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
--- a/arch/mips/kernel/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/mips/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -4,7 +4,7 @@
 
 # EXTRA_AFLAGS = -mips3 -mcpu=r4000 # not used?
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y				:= head.o init_task.o
 obj-y				+= branch.o process.o signal.o entry.o \
 				   traps.o ptrace.o vm86.o ioport.o reset.o \
 				   semaphore.o setup.o syscall.o sysmips.o \
diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
--- a/arch/mips/kernel/irq.c	Tue Feb 25 01:38:35 2003
+++ b/arch/mips/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -73,17 +73,19 @@
 int show_interrupts(struct seq_file *p, void *v)
 {
 	struct irqaction * action;
+	unsigned long flags;
 	int i;
-
+	
 	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
 		seq_printf(p, "CPU%d       ", i);
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -92,6 +94,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -Nru a/arch/mips/kernel/old-irq.c b/arch/mips/kernel/old-irq.c
--- a/arch/mips/kernel/old-irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/kernel/old-irq.c	Sat Mar  8 14:50:43 2003
@@ -128,11 +128,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 32 ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -143,6 +145,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c
--- a/arch/mips/kernel/pci.c	Mon Feb 24 12:51:23 2003
+++ b/arch/mips/kernel/pci.c	Sun Mar 16 14:16:31 2003
@@ -166,10 +166,3 @@
 {
 	/* this should not be called */
 }
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-	/* this should not be called */
-}
diff -Nru a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
--- a/arch/mips/mips-boards/atlas/atlas_int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/mips-boards/atlas/atlas_int.c	Sat Mar  8 14:50:43 2003
@@ -99,11 +99,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -114,6 +116,8 @@
 				action->name);
 		}
 		seq_printf(p, " [hw0]\n");
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -243,6 +247,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -Nru a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
--- a/arch/mips/mips-boards/generic/pci.c	Mon Feb 24 10:14:10 2003
+++ b/arch/mips/mips-boards/generic/pci.c	Sun Mar 16 14:16:31 2003
@@ -248,19 +248,7 @@
 	{ 0 }
 };
 
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                        struct resource *res, int resource)
-{
-	unsigned long where, size;
-	u32 reg;
-
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
-	size = res->end - res->start;
-	pci_read_config_dword(dev, where, &reg);
-	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-	pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
 
 /*
  *  Called after each bus is probed, but before its children
diff -Nru a/arch/mips/philips/nino/irq.c b/arch/mips/philips/nino/irq.c
--- a/arch/mips/philips/nino/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/philips/nino/irq.c	Sat Mar  8 14:50:43 2003
@@ -119,11 +119,13 @@
 {
     int i;
     struct irqaction *action;
+    unsigned long flags;
 
     for (i = 0; i < NR_IRQS; i++) {
+	local_irq_save(flags);
 	action = irq_action[i];
 	if (!action)
-	    continue;
+	    goto skip;
 	seq_printf(p, "%2d: %8d %c %s",
 		       i, kstat_cpu(0).irqs[i],
 		       (action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -134,6 +136,8 @@
 			   action->name);
 	}
 	seq_putc(p, '\n');
+skip:
+	local_irq_restore(flags);
     }
     return 0;
 }
diff -Nru a/arch/mips/sni/pci.c b/arch/mips/sni/pci.c
--- a/arch/mips/sni/pci.c	Fri Aug 30 06:59:50 2002
+++ b/arch/mips/sni/pci.c	Sun Mar 16 14:16:31 2003
@@ -137,34 +137,6 @@
 {
 }
 
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-
-	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		new |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
-		return;
-	}
-	
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
-}
-
 void __init pcibios_init(void)
 {
 	struct pci_ops *ops = &sni_pci_ops;
diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S
--- a/arch/mips/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/mips/vmlinux.lds.S	Fri Feb 14 15:09:55 2003
@@ -51,6 +51,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);	/* Align double page for init_task_union */
   __init_end = .;
 
diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig
--- a/arch/mips64/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/mips64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 source "init/Kconfig"
 
 
diff -Nru a/arch/mips64/kernel/Makefile b/arch/mips64/kernel/Makefile
--- a/arch/mips64/kernel/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/mips64/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the Linux/MIPS kernel.
 #
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y	:= head.o init_task.o
 
 obj-y	:= branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \
 	   r4k_genex.o r4k_switch.o r4k_tlb.o r4k_tlb_debug.o r4k_tlb_glue.o \
diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c
--- a/arch/mips64/kernel/linux32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/mips64/kernel/linux32.c	Thu Mar  6 11:06:44 2003
@@ -729,12 +729,10 @@
 	return sys_llseek(fd, offset_high, offset_low, result, origin);
 }
 
-struct iovec32 { unsigned int iov_base; int iov_len; };
-
 typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
 
 static long
-do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
+do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector,
 		  u32 count)
 {
 	unsigned long tot_len;
@@ -749,7 +747,7 @@
 	 */
 	if (!count)
 		return 0;
-	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		return -EFAULT;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
@@ -835,7 +833,7 @@
 }
 
 asmlinkage long
-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -855,7 +853,7 @@
 }
 
 asmlinkage long
-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -1155,48 +1153,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER) {
-		struct sock_fprog32 {
-			__u16 len;
-			__u32 filter;
-		} *fprog32 = (struct sock_fprog32 *)optval;
-		struct sock_fprog kfprog;
-		struct sock_filter *kfilter;
-		unsigned int fsize;
-		mm_segment_t old_fs;
-		__u32 uptr;
-		int ret;
-
-		if (get_user(kfprog.len, &fprog32->len) ||
-		    __get_user(uptr, &fprog32->filter))
-			return -EFAULT;
-		kfprog.filter = (struct sock_filter *)A(uptr);
-		fsize = kfprog.len * sizeof(struct sock_filter);
-		kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-		if (kfilter == NULL)
-			return -ENOMEM;
-		if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-			kfree(kfilter);
-			return -EFAULT;
-		}
-		kfprog.filter = kfilter;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		ret = sys_setsockopt(fd, level, optname,
-				     (char *)&kfprog, sizeof(kfprog));
-		set_fs(old_fs);
-		kfree(kfilter);
-		return ret;
-	}
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
 struct flock32 {
 	short l_type;
 	short l_whence;
@@ -1873,256 +1829,3 @@
 	return ret;
 }
 
-/*
- *  Declare the 32-bit version of the msghdr
- */
- 
-struct msghdr32 {
-	unsigned int    msg_name;	/* Socket name			*/
-	int		msg_namelen;	/* Length of name		*/
-	unsigned int    msg_iov;	/* Data blocks			*/
-	unsigned int	msg_iovlen;	/* Number of blocks		*/
-	unsigned int    msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
-	unsigned int	msg_controllen;	/* Length of cmsg list */
-	unsigned	msg_flags;
-};
-
-static inline int
-shape_msg(struct msghdr *mp, struct msghdr32 *mp32)
-{
-	int ret;
-	unsigned int i;
-
-	if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
-		return(-EFAULT);
-	ret = __get_user(i, &mp32->msg_name);
-	mp->msg_name = (void *)A(i);
-	ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
-	ret |= __get_user(i, &mp32->msg_iov);
-	mp->msg_iov = (struct iovec *)A(i);
-	ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
-	ret |= __get_user(i, &mp32->msg_control);
-	mp->msg_control = (void *)A(i);
-	ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
-	ret |= __get_user(mp->msg_flags, &mp32->msg_flags);
-	return(ret ? -EFAULT : 0);
-}
-
-/*
- *	Verify & re-shape IA32 iovec. The caller must ensure that the
- *      iovec is big enough to hold the re-shaped message iovec.
- *
- *	Save time not doing verify_area. copy_*_user will make this work
- *	in any case.
- *
- *	Don't need to check the total size for overflow (cf net/core/iovec.c),
- *	32-bit sizes can't overflow a 64-bit count.
- */
-
-static inline int
-verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode)
-{
-	int size, err, ct;
-	struct iovec32 *iov32;
-	
-	if(m->msg_namelen)
-	{
-		if(mode==VERIFY_READ)
-		{
-			err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
-			if(err<0)
-				goto out;
-		}
-		
-		m->msg_name = address;
-	} else
-		m->msg_name = NULL;
-
-	err = -EFAULT;
-	size = m->msg_iovlen * sizeof(struct iovec32);
-	if (copy_from_user(iov, m->msg_iov, size))
-		goto out;
-	m->msg_iov=iov;
-
-	err = 0;
-	iov32 = (struct iovec32 *)iov;
-	for (ct = m->msg_iovlen; ct-- > 0; ) {
-		iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
-		iov[ct].iov_base = (void *) A(iov32[ct].iov_base);
-		err += iov[ct].iov_len;
-	}
-out:
-	return err;
-}
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-/*
- *	BSD sendmsg interface
- */
-
-int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */
-	unsigned char *ctl_buf = ctl;
-	struct msghdr msg_sys;
-	int err, ctl_len, iov_size, total_len;
-	
-	err = -EFAULT;
-	if (shape_msg(&msg_sys, msg))
-		goto out; 
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock) 
-		goto out;
-
-	/* do not move before msg_sys is valid */
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/* This will also move the address data into kernel space */
-	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
-	if (err < 0) 
-		goto out_freeiov;
-	total_len = err;
-
-	err = -ENOBUFS;
-
-	if (msg_sys.msg_controllen > INT_MAX)
-		goto out_freeiov;
-	ctl_len = msg_sys.msg_controllen; 
-	if (ctl_len) 
-	{
-		if (ctl_len > sizeof(ctl))
-		{
-			err = -ENOBUFS;
-			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
-			if (ctl_buf == NULL) 
-				goto out_freeiov;
-		}
-		err = -EFAULT;
-		if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len))
-			goto out_freectl;
-		msg_sys.msg_control = ctl_buf;
-	}
-	msg_sys.msg_flags = flags;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		msg_sys.msg_flags |= MSG_DONTWAIT;
-	err = sock_sendmsg(sock, &msg_sys, total_len);
-
-out_freectl:
-	if (ctl_buf != ctl)    
-		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:       
-	return err;
-}
-
-/*
- *	BSD recvmsg interface
- */
-
-int
-sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
-{
-	struct socket *sock;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov=iovstack;
-	struct msghdr msg_sys;
-	unsigned long cmsg_ptr;
-	int err, iov_size, total_len, len;
-
-	/* kernel mode address */
-	char addr[MAX_SOCK_ADDR];
-
-	/* user mode address pointers */
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	
-	err=-EFAULT;
-	if (shape_msg(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-	
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/*
-	 *	Save the user-mode address (verify_iovec will change the
-	 *	kernel msghdr to use the kernel address space)
-	 */
-	 
-	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out_freeiov;
-	total_len=err;
-
-	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-	
-	if (sock->file->f_flags & O_NONBLOCK)
-		flags |= MSG_DONTWAIT;
-	err = sock_recvmsg(sock, &msg_sys, total_len, flags);
-	if (err < 0)
-		goto out_freeiov;
-	len = err;
-
-	if (uaddr != NULL) {
-		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
-		if (err < 0)
-			goto out_freeiov;
-	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
-	if (err)
-		goto out_freeiov;
-	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
-							 &msg->msg_controllen);
-	if (err)
-		goto out_freeiov;
-	err = len;
-
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:
-	return err;
-}
diff -Nru a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S
--- a/arch/mips64/kernel/scall_o32.S	Wed Dec 11 16:14:42 2002
+++ b/arch/mips64/kernel/scall_o32.S	Thu Mar  6 11:06:44 2003
@@ -378,8 +378,8 @@
 	sys	sys32_select	5
 	sys	sys_flock	2
 	sys	sys_msync	3
-	sys	sys32_readv	3			/* 4145 */
-	sys	sys32_writev	3
+	sys	compat_sys_readv	3			/* 4145 */
+	sys	compat_sys_writev	3
 	sys	sys_cacheflush	3
 	sys	sys_cachectl	3
 	sys	sys_sysmips	4
@@ -410,11 +410,11 @@
 	sys	sys_listen	2
 	sys	sys_recv	4			/* 4175 */
 	sys	sys_recvfrom	6
-	sys	sys32_recvmsg	3
+	sys	compat_sys_recvmsg	3
 	sys	sys_send	4
-	sys	sys32_sendmsg	3
+	sys	compat_sys_sendmsg	3
 	sys	sys_sendto	6			/* 4180 */
-	sys	sys32_setsockopt	5
+	sys	compat_sys_setsockopt	5
 	sys	sys_shutdown	2
 	sys	sys_socket	3
 	sys	sys_socketpair	4
diff -Nru a/arch/mips64/mips-boards/atlas/atlas_int.c b/arch/mips64/mips-boards/atlas/atlas_int.c
--- a/arch/mips64/mips-boards/atlas/atlas_int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/mips-boards/atlas/atlas_int.c	Sat Mar  8 14:50:43 2003
@@ -95,11 +95,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -110,6 +112,8 @@
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -239,6 +243,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -Nru a/arch/mips64/mips-boards/generic/pci.c b/arch/mips64/mips-boards/generic/pci.c
--- a/arch/mips64/mips-boards/generic/pci.c	Mon Feb 24 10:14:12 2003
+++ b/arch/mips64/mips-boards/generic/pci.c	Sun Mar 16 14:16:31 2003
@@ -307,19 +307,7 @@
 	{ 0 }
 };
 
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                        struct resource *res, int resource)
-{
-	unsigned long where, size;
-	u32 reg;
-
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
-	size = res->end - res->start;
-	pci_read_config_dword(dev, where, &reg);
-	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-	pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
 
 unsigned __init int pcibios_assign_all_busses(void)
 {
diff -Nru a/arch/mips64/mips-boards/malta/malta_int.c b/arch/mips64/mips-boards/malta/malta_int.c
--- a/arch/mips64/mips-boards/malta/malta_int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/mips-boards/malta/malta_int.c	Sat Mar  8 14:50:43 2003
@@ -125,11 +125,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 8; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -140,11 +142,14 @@
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0; i < MALTAINT_END; i++, num++) {
+		local_irq_save(flags);
 		action = hw0_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -155,6 +160,8 @@
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c
--- a/arch/mips64/sgi-ip22/ip22-int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/sgi-ip22/ip22-int.c	Sat Mar  8 14:50:43 2003
@@ -237,11 +237,13 @@
 	int i;
 	int num = 0;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 16 ; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -252,11 +254,14 @@
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0 ; i < 24 ; i++, num++) {
+		local_irq_save(flags);
 		action = local_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -267,6 +272,8 @@
 				action->name);
 		}
 		seq_puts(p, " [local]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c
--- a/arch/mips64/sgi-ip27/ip27-irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/sgi-ip27/ip27-irq.c	Sat Mar  8 14:50:43 2003
@@ -141,11 +141,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i],
 		               (action->flags & SA_INTERRUPT) ? '+' : ' ',
 		               action->name);
@@ -156,6 +158,8 @@
 			                action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips64/sgi-ip27/ip27-pci.c b/arch/mips64/sgi-ip27/ip27-pci.c
--- a/arch/mips64/sgi-ip27/ip27-pci.c	Fri Nov  1 09:33:01 2002
+++ b/arch/mips64/sgi-ip27/ip27-pci.c	Sun Mar 16 14:16:32 2003
@@ -214,30 +214,12 @@
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                        struct resource *res, int resource)
-{
-	unsigned long where, size;
-	u32 reg;
-
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
-	size = res->end - res->start;
-	pci_read_config_dword(dev, where, &reg);
-	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-	pci_write_config_dword(dev, where, reg);
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
 
 void __init
 pcibios_fixup_bus(struct pci_bus *b)
 {
 	pci_fixup_irqs(pci_swizzle, pci_map_irq);
-}
-
-void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus * bus,
-                          struct pbus_set_ranges_data * ranges)
-{
 }
 
 int __init
diff -Nru a/arch/mips64/sgi-ip32/Makefile b/arch/mips64/sgi-ip32/Makefile
--- a/arch/mips64/sgi-ip32/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/mips64/sgi-ip32/Makefile	Sun Mar  9 14:15:54 2003
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-EXTRA_TARGETS	:= ip32-irq-glue.o
+extra-y		:= ip32-irq-glue.o
 
 obj-y		+= ip32-irq.o ip32-rtc.o ip32-setup.o ip32-irq-glue.o \
 	 	   ip32-berr.o ip32-timer.o crime.o
diff -Nru a/arch/mips64/sgi-ip32/ip32-pci.c b/arch/mips64/sgi-ip32/ip32-pci.c
--- a/arch/mips64/sgi-ip32/ip32-pci.c	Fri Nov  1 09:33:01 2002
+++ b/arch/mips64/sgi-ip32/ip32-pci.c	Sun Mar 16 14:16:32 2003
@@ -333,11 +333,6 @@
 {
 }
 
-void __init pcibios_update_resource (struct pci_dev *dev, struct resource *root,
-				     struct resource *res, int resource)
-{
-}
-
 void __init pcibios_update_irq (struct pci_dev *dev, int irq)
 {
 	pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
@@ -346,12 +341,6 @@
 void __init pcibios_fixup_bus (struct pci_bus *b)
 {
 	pci_fixup_irqs (macepci_swizzle, macepci_map_irq);
-}
-
-/* XXX anybody know what this is supposed to do? */
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus * bus,
-					 struct pbus_set_ranges_data * ranges)
-{
 }
 
 /*
diff -Nru a/arch/mips64/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S
--- a/arch/mips64/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/mips64/vmlinux.lds.S	Fri Feb 14 15:10:00 2003
@@ -50,6 +50,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);	/* Align double page for init_task_union */
   __init_end = .;
 
diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig
--- a/arch/parisc/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/parisc/Kconfig	Sat Mar  8 14:50:37 2003
@@ -18,10 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config STACK_GROWSUP
 	bool
 	default y
diff -Nru a/arch/parisc/Makefile b/arch/parisc/Makefile
--- a/arch/parisc/Makefile	Mon Feb  3 21:32:53 2003
+++ b/arch/parisc/Makefile	Fri Mar  7 13:28:49 2003
@@ -91,12 +91,9 @@
 				   include/config/MARKER
 
 include/asm-parisc/offsets.h: arch/parisc/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
 
-CLEAN_FILES	+= palo.conf lifimage include/asm-parisc/offsets.h \
-		include/asm-parisc/offsets.h.tmp
+CLEAN_FILES	+= palo.conf lifimage include/asm-parisc/offsets.h
 
 define archhelp
 	@echo  '* vmlinux	- Uncompressed kernel image (./vmlinux)'
diff -Nru a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
--- a/arch/parisc/kernel/Makefile	Tue Feb 18 18:59:01 2003
+++ b/arch/parisc/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -4,7 +4,8 @@
 
 head-y			:= head.o
 head-$(CONFIG_PARISC64)	:= head64.o
-EXTRA_TARGETS	:= init_task.o pdc_cons.o process.o unaligned.o $(head-y)
+extra-y			:= init_task.o pdc_cons.o process.o
+			   unaligned.o $(head-y)
 
 AFLAGS_entry.o	:= -traditional
 AFLAGS_pacache.o := -traditional
diff -Nru a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
--- a/arch/parisc/kernel/pci.c	Sun Jan  5 03:16:45 2003
+++ b/arch/parisc/kernel/pci.c	Sun Mar 16 14:16:32 2003
@@ -192,74 +192,6 @@
 }
 
 
-/* ------------------------------------
-**
-** Program one BAR in PCI config space.
-**
-** ------------------------------------
-** PAT PDC systems need this routine. PA legacy PDC does not.
-**
-** When BAR's are configured by linux, this routine will update
-** configuration space with the "normalized" address. "root" indicates
-** where the range starts and res is some portion of that range.
-**
-** VCLASS: For all PA-RISC systems except V-class, root->start would be zero.
-**
-** PAT PDC can tell us which MMIO ranges are available or already in use.
-** I/O port space and such are not memory mapped anyway for PA-Risc.
-*/
-void __devinit
-pcibios_update_resource(
-	struct pci_dev *dev,
-	struct resource *root,
-	struct resource *res,
-	int barnum
-	)
-{
-	int where;
-	u32 barval = 0;
-
-	DBG_RES("pcibios_update_resource(%s, ..., %d) [%lx,%lx]/%x\n",
-		dev->slot_name,
-		barnum, res->start, res->end, (int) res->flags);
-
-	if (barnum >= PCI_BRIDGE_RESOURCES) {
-		/* handled in PCI-PCI bridge specific support */
-		return;
-	}
-
-	if (barnum == PCI_ROM_RESOURCE) {
-		where = PCI_ROM_ADDRESS;
-	} else {
-		/* 0-5  standard PCI "regions" */
-		where = PCI_BASE_ADDRESS_0 + (barnum * 4);
-	}
-
-	if (res->flags & IORESOURCE_IO) {
-		barval = PCI_PORT_ADDR(res->start);
-	} else if (res->flags & IORESOURCE_MEM) {
-		barval = PCI_BUS_ADDR(HBA_DATA(dev->bus->dev->platform_data), res->start);
-	} else {
-		panic("pcibios_update_resource() WTF? flags not IO or MEM");
-	}
-
-	pci_write_config_dword(dev, where, barval);
-
-/* XXX FIXME - Elroy does support 64-bit (dual cycle) addressing.
-** But at least one device (Symbios 53c896) which has 64-bit BAR
-** doesn't actually work right with dual cycle addresses.
-** So ignore the whole mess for now.
-*/
-
-	if ((res->flags & (PCI_BASE_ADDRESS_SPACE
-			   | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
-	    == (PCI_BASE_ADDRESS_SPACE_MEMORY
-		| PCI_BASE_ADDRESS_MEM_TYPE_64)) {
-		pci_write_config_dword(dev, where+4, 0);
-		DBGC("PCIBIOS: dev %s type 64-bit\n", dev->name);
-	}
-}
-
 /*
 ** Called by pci_set_master() - a driver interface.
 **
@@ -345,30 +277,34 @@
 /*
 ** called by drivers/pci/setup-res.c:pci_setup_bridge().
 */
-void __devinit pcibios_fixup_pbus_ranges(
-	struct pci_bus *bus,
-	struct pbus_set_ranges_data *ranges
+void __devinit pcibios_resource_to_bus(
+ 	struct pci_dev *dev,
+	struct pci_bus_region *region,
+	struct resource *res
 	)
 {
+	struct pci_bus *bus = dev->bus;
 	struct pci_hba_data *hba = HBA_DATA(bus->dev->platform_data);
 
-	/*
-	** I/O space may see busnumbers here. Something
-	** in the form of 0xbbxxxx where bb is the bus num
-	** and xxxx is the I/O port space address.
-	** Remaining address translation are done in the
-	** PCI Host adapter specific code - ie dino_out8.
-	*/
-	ranges->io_start = PCI_PORT_ADDR(ranges->io_start);
-	ranges->io_end   = PCI_PORT_ADDR(ranges->io_end);
+	if (res->flags & IORESOURCE_IO) {
+		/*
+		** I/O space may see busnumbers here. Something
+		** in the form of 0xbbxxxx where bb is the bus num
+		** and xxxx is the I/O port space address.
+		** Remaining address translation are done in the
+		** PCI Host adapter specific code - ie dino_out8.
+		*/
+		region->start = PCI_PORT_ADDR(res->start);
+		region->end   = PCI_PORT_ADDR(res->end);
+	} else if (res->flags & IORESOURCE_MEM) {
+		/* Convert MMIO addr to PCI addr (undo global virtualization) */
+		region->start = PCI_BUS_ADDR(hba, res->start);
+		region->end   = PCI_BUS_ADDR(hba, res->end);
+	}
 
-	/* Convert MMIO addr to PCI addr (undo global virtualization) */
-	ranges->mem_start = PCI_BUS_ADDR(hba, ranges->mem_start);
-	ranges->mem_end   = PCI_BUS_ADDR(hba, ranges->mem_end);
-
-	DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number,
-		ranges->io_start, ranges->io_end,
-		ranges->mem_start, ranges->mem_end);
+	DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n",
+		bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM",
+		region->start, region->end);
 
 	/* KLUGE ALERT
 	** if this resource isn't linked to a "parent", then it seems
@@ -377,6 +313,10 @@
 	pcibios_link_hba_resources(&hba->io_space, bus->resource[0]);
 	pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]);
 }
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
 
 #define MAX(val1, val2)   ((val1) > (val2) ? (val1) : (val2))
 
diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c	Sat Feb 15 19:30:17 2003
+++ b/arch/parisc/kernel/sys_parisc32.c	Sun Mar  9 01:34:44 2003
@@ -316,35 +316,6 @@
     return -ENOSYS;
 }
 
-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
-asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case F_GETLK:
-	case F_SETLK:
-	case F_SETLKW:
-		{
-			struct flock f;
-			long ret;
-			
-			if (get_compat_flock(&f, (struct compat_flock *)arg))
-				return -EFAULT;
-			KERNEL_SYSCALL(ret, sys_fcntl, fd, cmd, (unsigned long)&f);
-			if (ret) return ret;
-			if (f.l_start >= 0x7fffffffUL ||
-			    f.l_len >= 0x7fffffffUL ||
-			    f.l_start + f.l_len >= 0x7fffffffUL)
-				return -EOVERFLOW;
-			if (put_compat_flock(&f, (struct compat_flock *)arg))
-				return -EFAULT;
-			return 0;
-		}
-	default:
-		return sys_fcntl(fd, cmd, (unsigned long)arg);
-	}
-}
-
 #ifdef CONFIG_SYSCTL
 
 struct __sysctl_args32 {
@@ -919,12 +890,10 @@
 
 
 /* readv/writev stolen from mips64 */
-struct iovec32 { unsigned int iov_base; int iov_len; };
-
 typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
 
 static long
-do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
+do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector,
 		  u32 count)
 {
 	unsigned long tot_len;
@@ -939,7 +908,7 @@
 	 */
 	if (!count)
 		return 0;
-	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		return -EFAULT;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
@@ -1025,7 +994,7 @@
 }
 
 asmlinkage long
-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -1045,7 +1014,7 @@
 }
 
 asmlinkage long
-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -1063,747 +1032,6 @@
 	return ret;
 }
 
-/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/
-#include <linux/net.h>
-#include <net/scm.h>
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-extern struct socket *sockfd_lookup(int fd, int *err);
-
-struct msghdr32 {
-	u32		msg_name;
-	int		msg_namelen;
-	u32		msg_iov;
-	compat_size_t	msg_iovlen;
-	u32		msg_control;
-	compat_size_t	msg_controllen;
-	unsigned	msg_flags;
-};
-
-struct cmsghdr32 {
-	compat_size_t	cmsg_len;
-	int		cmsg_level;
-	int		cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-					     struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-	if(uaddr != NULL && err >= 0)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	return len;
-}
-
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-
-static int do_ipv4_set_replace(int fd, int level, int optname,
-				char *optval, int optlen)
-#if 1
-/* Fields happen to be padded such that this works.
-** Don't need to change iptables.h:struct ipt_replace
-*/
-{
-	struct ipt_replace *repl = (struct ipt_replace *) optval;
-	unsigned long ptr64;
-	unsigned int ptr32;
-	int ret;
-
-	if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32)))
-		return -EFAULT;
-	ptr64 = (unsigned long) ptr32;
-	if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64)))
-		return -EFAULT;
-
-	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);
-
-	/* Restore 32-bit ptr */
-	if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32)))
-		return -EFAULT;
-
-	return ret;
-}
-#else
-/* This version tries to "do it right". ie allocate kernel buffers for
-** everything and copy data in/out. Way too complicated.
-** NOT TESTED for correctness!
-*/
-{
-	struct ipt_replace  *kern_repl;
-	struct ipt_counters *kern_counters;
-	unsigned int user_counters;
-	mm_segment_t old_fs;
-	int ret = 0;
-
-	kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL);
-	if (!kern_repl)
-		return -ENOMEM;
-
-	if (copy_from_user(kern_repl, optval, optlen)) {
-		ret = -EFAULT;
-		goto err02;
-	}
-
-	/* 32-bit ptr is in the MSB's */
-	user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32);
-	/*
-	** We are going to set_fs() to kernel space - and thus need
-	** "relocate" the counters buffer to the kernel space.
-	*/
-	kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL);
-	if (!user_counters) {
-		ret = -ENOMEM;
-		goto err02;
-	}
-
-	if (copy_from_user(kern_counters, (char *) user_counters, optlen)) {
-		ret = -EFAULT;
-		goto err01;
-	}
-
-	/* We can update the kernel ptr now that we have the data. */
-	kern_repl->counters = kern_counters;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);
-
-	set_fs(old_fs);
-
-	/* Copy counters back out to user space */
-	if (copy_to_user((char *) user_counters, kern_counters,
-			kern_repl->num_counters * sizeof(struct ipt_counters)))
-	{
-		ret = -EFAULT;
-		goto err01;
-	}
-
-	/* restore counters so userspace can consume it */
-	kern_repl->counters = NULL;
-	(unsigned int) kern_repl->counters = user_counters;
-
-	/* Copy repl back out to user space */
-	if (copy_to_user(optval, kern_repl, optlen))
-	{
-		ret = -EFAULT;
-	}
-
-err01:
-	kfree(kern_counters);
-err02:
-	kfree(kern_repl);
-	return ret;
-}
-#endif
-
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname, optval, optlen);
-
-	if (level == SOL_ICMPV6   && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname, optval, optlen);
-
-	/*
-	** Beware:    IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE
-	*/
-	if (level == IPPROTO_IP   && optname == IPT_SO_SET_REPLACE)
-		return do_ipv4_set_replace(fd, level, optname, optval, optlen);
-
-	if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE)
-#if 0
-		/* FIXME: I don't (yet) use IPV6. -ggg */
-		return do_ipv6_set_replace(fd, level, optname, optval, optlen);
-#else
-	{
-		BUG();
-		return -ENXIO;
-	}
-#endif
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
-
 /*** copied from mips64 ***/
 /*
  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
@@ -2041,28 +1269,6 @@
 
 	kfree(mb);
 	return err;
-}
-
-/* LFS */
-
-extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
-
-asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-		case F_GETLK64:
-			cmd = F_GETLK;
-			break;
-		case F_SETLK64:
-			cmd = F_SETLK;
-			break;
-		case F_SETLKW64:
-			cmd = F_SETLKW;
-			break;
-		default:
-			break;
-	}
-	return sys32_fcntl(fd, cmd, arg);
 }
 
 /* EXPORT/UNEXPORT */
diff -Nru a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
--- a/arch/parisc/kernel/syscall.S	Sat Feb 15 04:39:48 2003
+++ b/arch/parisc/kernel/syscall.S	Sun Mar  9 01:34:44 2003
@@ -409,8 +409,7 @@
 	ENTRY_SAME(getpeername)
 	/* This one's a huge ugly mess */
 	ENTRY_DIFF(ioctl)
-	/* struct flock? */
-	ENTRY_DIFF(fcntl)		/* 55 */
+	ENTRY_COMP(fcntl)		/* 55 */
 	ENTRY_SAME(socketpair)
 	ENTRY_SAME(setpgid)
 	ENTRY_SAME(send)
@@ -589,7 +588,7 @@
 	ENTRY_OURS(truncate64)
 	ENTRY_OURS(ftruncate64)		/* 200 */
 	ENTRY_SAME(getdents64)
-	ENTRY_DIFF(fcntl64)
+	ENTRY_COMP(fcntl64)
 	ENTRY_SAME(ni_syscall)
 	ENTRY_SAME(ni_syscall)
 	ENTRY_SAME(ni_syscall)		/* 205 */
diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S
--- a/arch/parisc/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/parisc/vmlinux.lds.S	Fri Feb 14 15:10:04 2003
@@ -73,6 +73,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
--- a/arch/ppc/8xx_io/uart.c	Mon Feb  3 05:47:46 2003
+++ b/arch/ppc/8xx_io/uart.c	Mon Mar  3 11:33:06 2003
@@ -2522,12 +2522,11 @@
 /*
  *	Register console.
  */
-long __init console_8xx_init(long kmem_start, long kmem_end)
+static void __init console_8xx_init(long kmem_start, long kmem_end)
 {
 	register_console(&sercons);
-	return kmem_start;
 }
-
+console_initcall(console_8xx_init);
 #endif
 
 /* Index in baud rate table of the default console baud rate.
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/ppc/Kconfig	Sat Mar  8 14:50:37 2003
@@ -1126,22 +1126,6 @@
 config PIN_TLB
 	bool "Pinned Kernel TLBs (860 ONLY)"
 	depends on ADVANCED_OPTIONS && 8xx
-
-config SWAP
-	bool "Enable support for swap"
-	depends on ADVANCED_OPTIONS
-	help
-	  This option allows you to turn off support for swapfiles in
-	  the kernel.  This can be useful if you know that your system
-	  will never have swap.
-
-	  Say Y here unless you know what you are doing.
-
-config SWAP
-	bool
-	depends on !ADVANCED_OPTIONS
-	default y
-
 endmenu
 
 source "drivers/mtd/Kconfig"
diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile
--- a/arch/ppc/Makefile	Sun Jan 26 11:13:05 2003
+++ b/arch/ppc/Makefile	Fri Mar  7 13:28:49 2003
@@ -80,12 +80,8 @@
 arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
 				   include/config/MARKER
 
-include/asm-$(ARCH)/offsets.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
-	@$(generate-asm-offsets.h) < $< > $@
-
-include/asm-$(ARCH)/offsets.h: include/asm-$(ARCH)/offsets.h.tmp
-	@echo -n '  Generating $@'
-	@$(update-if-changed)
+include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s 
+	$(call filechk,gen-asm-offsets)
 
 ifdef CONFIG_6xx
 # Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later
@@ -106,6 +102,5 @@
 	@true
 endif
 
-CLEAN_FILES +=	include/asm-$(ARCH)/offsets.h.tmp \
-		include/asm-$(ARCH)/offsets.h \
+CLEAN_FILES +=	include/asm-$(ARCH)/offsets.h \
 		arch/$(ARCH)/kernel/asm-offsets.s
diff -Nru a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
--- a/arch/ppc/boot/common/util.S	Tue Feb 11 15:48:52 2003
+++ b/arch/ppc/boot/common/util.S	Tue Feb 25 11:37:43 2003
@@ -14,7 +14,7 @@
  *	   trini@mvista.com
  * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-2003 (c) MontaVista, Software, Inc.  This file is licensed under
  * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
@@ -98,7 +98,7 @@
 	isync
 	mfspr	r8,L2CR
 	rlwinm	r8,r8,0,1,31
-	oris	r8,r8,0x0020
+	oris	r8,r8,L2CR_L2I@h
 	sync
 	isync
 	mtspr	L2CR,r8
@@ -106,14 +106,55 @@
 	isync
 
 	/* Wait for the invalidation to complete */
-1:	mfspr	r8,L2CR
-	rlwinm.	r9,r8,0,31,31
+	mfspr   r8,PVR
+	srwi    r8,r8,16
+	cmpli	cr0,r8,0x8000			/* 7450 */
+	cmpli	cr1,r8,0x8001			/* 7455 */
+	cmpli	cr2,r8,0x8002			/* 7457 */
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq	/* Now test if any are true. */
+	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
+	bne     2f
+
+1:	mfspr	r8,L2CR		/* On 745x, poll L2I bit (bit 10) */
+	rlwinm.	r9,r8,0,10,10
 	bne	1b
+	b	3f
+
+2:      mfspr   r8,L2CR		/* On 75x & 74[01]0, poll L2IP bit (bit 31) */
+	rlwinm. r9,r8,0,31,31
+	bne     2b
 
-	rlwinm	r8,r8,0,11,9		/* Turn off L2I bit */
+3:	rlwinm	r8,r8,0,11,9	/* Turn off L2I bit */
 	sync
 	isync
 	mtspr	L2CR,r8
+	sync
+	isync
+	blr
+
+	.globl	_setup_L3CR
+_setup_L3CR:
+	/* Invalidate/disable L3 cache */
+	sync
+	isync
+	mfspr	r8,L3CR
+	rlwinm	r8,r8,0,1,31
+	ori	r8,r8,L3CR_L3I@l
+	sync
+	isync
+	mtspr	L3CR,r8
+	sync
+	isync
+
+	/* Wait for the invalidation to complete */
+1:	mfspr	r8,L3CR
+	rlwinm.	r9,r8,0,21,21
+	bne	1b
+
+	rlwinm	r8,r8,0,22,20		/* Turn off L3I bit */
+	sync
+	isync
+	mtspr	L3CR,r8
 	sync
 	isync
 	blr
diff -Nru a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
--- a/arch/ppc/boot/images/Makefile	Wed Nov 20 03:10:01 2002
+++ b/arch/ppc/boot/images/Makefile	Sun Mar  9 13:47:41 2003
@@ -2,9 +2,8 @@
 # This dir holds all of the images for PPC machines.
 # Tom Rini	January 2001
 
-EXTRA_TARGETS	:= vmlinux.gz
-
-GZIP_FLAGS = -v9f
+targets		:= vmlinux.gz
+GZIP_FLAGS	:= -v9f
 
 $(obj)/vmlinux.gz: vmlinux
 	$(OBJCOPY) -O binary $< $(@:.gz=)
diff -Nru a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S
--- a/arch/ppc/boot/simple/head.S	Tue Feb 11 15:48:52 2003
+++ b/arch/ppc/boot/simple/head.S	Tue Feb 25 11:37:43 2003
@@ -7,7 +7,7 @@
  *	   trini@mvista.com
  * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-2003 (c) MontaVista, Software, Inc.  This file is licensed under
  * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
@@ -74,6 +74,17 @@
 #if defined(CONFIG_FORCE) || defined(CONFIG_K2)		\
 		|| defined(CONFIG_EV64260) || defined(CONFIG_PAL4)
 	bl	_setup_L2CR
+
+	/* If 745x, turn off L3CR as well */
+	mfspr	r8,PVR
+	srwi	r8,r8,16
+
+	cmpli	cr0,r8,0x8000			/* 7450 */
+	cmpli	cr1,r8,0x8001			/* 7455 */
+	cmpli	cr2,r8,0x8002			/* 7457 */
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq	/* Now test if any are true. */
+	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
+	beql	_setup_L3CR
 #endif
 #endif
 
diff -Nru a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h
--- a/arch/ppc/boot/simple/rw4/ppc_40x.h	Fri Feb 14 15:10:29 2003
+++ b/arch/ppc/boot/simple/rw4/ppc_40x.h	Wed Feb 19 07:23:15 2003
@@ -42,7 +42,7 @@
 #define dccr            0x3fa               /* data cache control reg.       */
 #define dcwr            0x3ba               /* data cache write-thru reg     */
 #define dear            0x3d5               /* data exception address reg    */
-#define esr             0x3d4               /* exception syndrome registe    */
+#define esr             0x3d4               /* exception syndrome register   */
 #define evpr            0x3d6               /* exception vector prefix reg   */
 #define iccr            0x3fb               /* instruction cache cntrl re    */
 #define icdbdr          0x3d3               /* instr cache dbug data reg     */
diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
--- a/arch/ppc/kernel/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/ppc/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -15,7 +15,7 @@
 HEAD-$(CONFIG_8xx)		:= head_8xx.o
 HEAD-$(CONFIG_6xx)		+= idle_6xx.o
 
-EXTRA_TARGETS	:= $(HEAD-y)
+extra-y	:= $(HEAD-y)
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
 					process.o signal.o ptrace.o align.o \
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	Sat Feb 15 13:50:01 2003
+++ b/arch/ppc/kernel/irq.c	Sat Mar 15 03:37:31 2003
@@ -346,6 +346,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -354,9 +355,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if ( !action || !action->handler )
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++)
@@ -375,6 +377,8 @@
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #ifdef CONFIG_TAU_INT
 	if (tau_initialized){
@@ -680,7 +684,7 @@
 	struct proc_dir_entry *entry;
 	char name [MAX_NAMELEN];
 
-	if (!root_irq_dir || (irq_desc[irq].handler == NULL))
+	if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq])
 		return;
 
 	memset(name, 0, MAX_NAMELEN);
diff -Nru a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
--- a/arch/ppc/kernel/pci.c	Fri Feb  7 00:20:34 2003
+++ b/arch/ppc/kernel/pci.c	Sun Mar 16 14:16:32 2003
@@ -93,46 +93,6 @@
 	}
 }
 
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-	struct pci_controller* hose = dev->sysdata;
-	unsigned long io_offset;
-	
-	new = res->start;
-	res->flags &= ~IORESOURCE_UNSET;
-	if (hose && res->flags & IORESOURCE_IO) {
-		io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
-		new -= io_offset;
-	}
-	if (hose && res->flags & IORESOURCE_MEM)
-		new -= hose->pci_mem_offset;
-	new |= (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
-		return;
-	}
-
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
-	printk(KERN_INFO "PCI: moved device %s resource %d (%lx) to %x\n",
-	       dev->slot_name, resource, res->flags,
-	       new & ~PCI_REGION_FLAG_MASK);
-}
-
 static void
 pcibios_fixup_resources(struct pci_dev *dev)
 {
@@ -1105,11 +1065,6 @@
 		/* The slot is the idsel of the last bridge. */
 	}
 	return PCI_SLOT(dev->devfn);
-}
-
-void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
-{
 }
 
 unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
diff -Nru a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
--- a/arch/ppc/kernel/ppc-stub.c	Sat Jan  4 00:44:11 2003
+++ b/arch/ppc/kernel/ppc-stub.c	Wed Mar 12 11:52:59 2003
@@ -420,18 +420,6 @@
 	flush_instruction_cache();
 }
 
-static inline int get_msr(void)
-{
-	int msr;
-	asm volatile("mfmsr %0" : "=r" (msr):);
-	return msr;
-}
-
-static inline void set_msr(int msr)
-{
-	asm volatile("mtmsr %0" : : "r" (msr));
-}
-
 /* Set up exception handlers for tracing and breakpoints
  * [could be called kgdb_init()]
  */
@@ -598,8 +586,8 @@
 
 	kgdb_interruptible(0);
 	lock_kernel();
-	msr = get_msr();
-	set_msr(msr & ~MSR_EE);	/* disable interrupts */
+	msr = mfmsr();
+	mtmsr(msr & ~MSR_EE);	/* disable interrupts */
 
 	if (regs->nip == (unsigned long)breakinst) {
 		/* Skip over breakpoint trap insn */
@@ -626,7 +614,7 @@
 	*ptr++ = hexchars[SP_REGNUM >> 4];
 	*ptr++ = hexchars[SP_REGNUM & 0xf];
 	*ptr++ = ':';
-	ptr = mem2hex(((char *)&regs) + SP_REGNUM*4, ptr, 4);
+	ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
 	*ptr++ = ';';
 #endif
 
@@ -786,7 +774,7 @@
 			strcpy(remcomOutBuffer, "OK");
 			putpacket(remcomOutBuffer);
 #endif
-			set_msr(msr);
+			mtmsr(msr);
 
 			kgdb_interruptible(1);
 			unlock_kernel();
@@ -802,10 +790,9 @@
 #if defined(CONFIG_40x)
 			regs->msr |= MSR_DE;
 			regs->dbcr0 |= (DBCR0_IDM | DBCR0_IC);
-			set_msr(msr);
+			mtmsr(msr);
 #else
 			regs->msr |= MSR_SE;
-			set_msr(msr | MSR_SE);
 #endif
 			unlock_kernel();
 			kgdb_active = 0;
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	Fri Feb 21 17:28:50 2003
+++ b/arch/ppc/kernel/process.c	Wed Mar 12 03:28:50 2003
@@ -321,6 +321,24 @@
 }
 
 /*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+	struct pt_regs *regs = tsk->thread.regs;
+
+	if (regs == NULL)
+		return;
+	if (regs->msr & MSR_FP)
+		giveup_fpu(current);
+#ifdef CONFIG_ALTIVEC
+	if (regs->msr & MSR_VEC)
+		giveup_altivec(current);
+#endif /* CONFIG_ALTIVEC */
+}
+
+/*
  * Copy a thread..
  */
 int
@@ -348,6 +366,8 @@
 	} else {
 		childregs->gpr[1] = usp;
 		p->thread.regs = childregs;
+		if (clone_flags & CLONE_SETTLS)
+			childregs->gpr[2] = childregs->gpr[6];
 	}
 	childregs->gpr[3] = 0;  /* Result from fork() */
 	sp -= STACK_FRAME_OVERHEAD;
@@ -367,29 +387,6 @@
 	p->thread.ksp = sp;
 	kregs->nip = (unsigned long)ret_from_fork;
 
-	/*
-	 * copy fpu info - assume lazy fpu switch now always
-	 *  -- Cort
-	 */
-	if (regs->msr & MSR_FP) {
-		giveup_fpu(current);
-		childregs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
-	}
-	memcpy(&p->thread.fpr, &current->thread.fpr, sizeof(p->thread.fpr));
-	p->thread.fpscr = current->thread.fpscr;
-
-#ifdef CONFIG_ALTIVEC
-	/*
-	 * copy altiVec info - assume lazy altiVec switch
-	 * - kumar
-	 */
-	if (regs->msr & MSR_VEC)
-		giveup_altivec(current);
-	memcpy(&p->thread.vr, &current->thread.vr, sizeof(p->thread.vr));
-	p->thread.vscr = current->thread.vscr;
-	childregs->msr &= ~MSR_VEC;
-#endif /* CONFIG_ALTIVEC */
-
 	p->thread.last_syscall = -1;
 
 	return 0;
@@ -444,15 +441,17 @@
 	return put_user(val, (unsigned int *) adr);
 }
 
-int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
+int sys_clone(unsigned long clone_flags, unsigned long usp, int *parent_tidp,
+	      void *child_threadptr, int *child_tidp, int p6,
 	      struct pt_regs *regs)
 {
  	struct task_struct *p;
 
 	CHECK_FULL_REGS(regs);
-	if (p2 == 0)
-		p2 = regs->gpr[1];	/* stack pointer for child */
- 	p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3, (int *)p4);
+	if (usp == 0)
+		usp = regs->gpr[1];	/* stack pointer for child */
+ 	p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
+		    parent_tidp, child_tidp);
  	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
diff -Nru a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
--- a/arch/ppc/mm/fault.c	Thu Jan  2 23:55:27 2003
+++ b/arch/ppc/mm/fault.c	Sat Mar 15 03:33:11 2003
@@ -57,6 +57,41 @@
 extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
 
 /*
+ * Check whether the instruction at regs->nip is a store using
+ * an update addressing form which will update r1.
+ */
+static int store_updates_sp(struct pt_regs *regs)
+{
+	unsigned int inst;
+
+	if (get_user(inst, (unsigned int *)regs->nip))
+		return 0;
+	/* check for 1 in the rA field */
+	if (((inst >> 16) & 0x1f) != 1)
+		return 0;
+	/* check major opcode */
+	switch (inst >> 26) {
+	case 37:	/* stwu */
+	case 39:	/* stbu */
+	case 45:	/* sthu */
+	case 53:	/* stfsu */
+	case 55:	/* stfdu */
+		return 1;
+	case 31:
+		/* check minor opcode */
+		switch ((inst >> 1) & 0x3ff) {
+		case 183:	/* stwux */
+		case 247:	/* stbux */
+		case 439:	/* sthux */
+		case 695:	/* stfsux */
+		case 759:	/* stfdux */
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
  * For 600- and 800-family processors, the error_code parameter is DSISR
  * for a data fault, SRR1 for an instruction fault. For 400-family processors
  * the error_code parameter is ESR for a data fault, 0 for an instruction
@@ -112,6 +147,40 @@
 		goto good_area;
 	if (!(vma->vm_flags & VM_GROWSDOWN))
 		goto bad_area;
+	if (!is_write)
+                goto bad_area;
+
+	/*
+	 * N.B. The rs6000/xcoff ABI allows programs to access up to
+	 * a few hundred bytes below the stack pointer.
+	 * The kernel signal delivery code writes up to about 1.5kB
+	 * below the stack pointer (r1) before decrementing it.
+	 * The exec code can write slightly over 640kB to the stack
+	 * before setting the user r1.  Thus we allow the stack to
+	 * expand to 1MB without further checks.
+	 */
+	if (address + 0x100000 < vma->vm_end) {
+		/* get user regs even if this fault is in kernel mode */
+		struct pt_regs *uregs = current->thread.regs;
+		if (uregs == NULL)
+			goto bad_area;
+
+		/*
+		 * A user-mode access to an address a long way below
+		 * the stack pointer is only valid if the instruction
+		 * is one which would update the stack pointer to the
+		 * address accessed if the instruction completed,
+		 * i.e. either stwu rs,n(r1) or stwux rs,r1,rb
+		 * (or the byte, halfword, float or double forms).
+		 *
+		 * If we don't check this then any write to the area
+		 * between the last mapped region and the stack will
+		 * expand the stack rather than segfaulting.
+		 */
+		if (address + 2048 < uregs->gpr[1]
+		    && (!user_mode(regs) || !store_updates_sp(regs)))
+			goto bad_area;
+	}
 	if (expand_stack(vma, address))
 		goto bad_area;
 
diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
--- a/arch/ppc/mm/init.c	Wed Jan  8 12:37:27 2003
+++ b/arch/ppc/mm/init.c	Sat Mar 15 03:34:49 2003
@@ -338,6 +338,7 @@
 
 	min_low_pfn = start >> PAGE_SHIFT;
 	max_low_pfn = (PPC_MEMSTART + total_lowmem) >> PAGE_SHIFT;
+	max_pfn = (PPC_MEMSTART + total_memory) >> PAGE_SHIFT;
 	boot_mapsize = init_bootmem_node(&contig_page_data, min_low_pfn,
 					 PPC_MEMSTART >> PAGE_SHIFT,
 					 max_low_pfn);
diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c
--- a/arch/ppc/platforms/lopec_setup.c	Tue Feb 11 15:48:53 2003
+++ b/arch/ppc/platforms/lopec_setup.c	Mon Mar 10 14:16:12 2003
@@ -324,7 +324,7 @@
         	ROOT_DEV = Root_SDA1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
+#ifdef CONFIG_VT
 	conswitchp = &dummy_con;
 #endif
 #ifdef CONFIG_PPCBUG_NVRAM
@@ -378,7 +378,7 @@
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_ID_MODULE)
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 	ppc_ide_md.default_irq = lopec_ide_default_irq;
 	ppc_ide_md.default_io_base = lopec_ide_default_io_base;
 	ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
--- a/arch/ppc/syslib/open_pic.c	Tue Nov 19 19:46:02 2002
+++ b/arch/ppc/syslib/open_pic.c	Sat Mar 15 03:35:56 2003
@@ -580,14 +580,19 @@
 	if (OpenPIC == NULL)
 		return;
 
+	/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
 	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset,
-		    openpic_ipi_action, 0, "IPI0 (call function)", 0);
+		    openpic_ipi_action, SA_INTERRUPT,
+		    "IPI0 (call function)", 0);
 	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1,
-		    openpic_ipi_action, 0, "IPI1 (reschedule)", 0);
+		    openpic_ipi_action, SA_INTERRUPT,
+		    "IPI1 (reschedule)", 0);
 	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2,
-		    openpic_ipi_action, 0, "IPI2 (invalidate tlb)", 0);
+		    openpic_ipi_action, SA_INTERRUPT,
+		    "IPI2 (invalidate tlb)", 0);
 	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3,
-		    openpic_ipi_action, 0, "IPI3 (xmon break)", 0);
+		    openpic_ipi_action, SA_INTERRUPT,
+		    "IPI3 (xmon break)", 0);
 
 	for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
 		openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i);
diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S
--- a/arch/ppc/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/ppc/vmlinux.lds.S	Fri Feb 14 15:10:39 2003
@@ -107,6 +107,10 @@
   }
   __initcall_end = .;
 
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+
   __start___ftr_fixup = .;
   __ftr_fixup : { *(__ftr_fixup) }
   __stop___ftr_fixup = .;
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	Thu Feb 13 00:47:26 2003
+++ b/arch/ppc64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 
diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile
--- a/arch/ppc64/Makefile	Fri Feb  7 12:40:55 2003
+++ b/arch/ppc64/Makefile	Sat Mar 15 21:52:29 2003
@@ -18,9 +18,8 @@
 LDFLAGS		:= -m elf64ppc
 LDFLAGS_vmlinux	= -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
 LDFLAGS_BLOB	:= --format binary --oformat elf64-powerpc
-CFLAGS		+= -msoft-float -pipe \
-		-Wno-uninitialized -mminimal-toc -mtraceback=full \
-		-finline-limit-2000 -mcpu=power4
+CFLAGS		+= -msoft-float -pipe -Wno-uninitialized -mminimal-toc \
+		-mtraceback=full -mcpu=power4
 
 head-y := arch/ppc64/kernel/head.o
 
@@ -52,10 +51,6 @@
 				   include/config/MARKER
 
 include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
-
-CLEAN_FILES += include/asm-ppc64/offsets.h.tmp \
-	       include/asm-ppc64/offsets.h
+	$(call filechk,gen-asm-offsets)
 
+CLEAN_FILES += include/asm-ppc64/offsets.h
diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
--- a/arch/ppc64/boot/Makefile	Fri Feb  7 13:36:10 2003
+++ b/arch/ppc64/boot/Makefile	Sun Mar  9 14:15:54 2003
@@ -59,12 +59,12 @@
 gz-sec  = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
 
 host-progs		:= piggy addnote addSystemMap addRamDisk
-EXTRA_TARGETS 		+= zImage zImage.initrd imagesize.c \
+targets 		+= zImage zImage.initrd imagesize.c \
 			   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
 			   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
 			   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
-			   vmlinux.sm vmlinux.initrd vmlinux.sminitrd \
-			   sysmap.o initrd.o
+			   vmlinux.sm vmlinux.initrd vmlinux.sminitrd
+extra-y			:= sysmap.o initrd.o
 
 quiet_cmd_sysmap = SYSMAP   $@
       cmd_sysmap = $(obj)/addSystemMap System.map $< $@
diff -Nru a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
--- a/arch/ppc64/boot/main.c	Sat Feb 22 01:44:59 2003
+++ b/arch/ppc64/boot/main.c	Sun Mar  2 19:21:25 2003
@@ -12,11 +12,10 @@
 #include "ppc32-types.h"
 #include "zlib.h"
 #include <linux/elf.h>
+#include <linux/string.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/bootinfo.h>
-
-void memmove(void *dst, void *im, int len);
 
 extern void *finddevice(const char *);
 extern int getprop(void *, const char *, void *, int);
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	Tue Feb 18 18:59:01 2003
+++ b/arch/ppc64/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -3,7 +3,7 @@
 #
 
 EXTRA_CFLAGS	+= -mno-minimal-toc
-EXTRA_TARGETS	:= head.o
+extra-y		:= head.o
 obj-y               :=	setup.o entry.o traps.o irq.o idle.o \
 			time.o process.o signal.o syscalls.o misc.o ptrace.o \
 			align.o semaphore.o bitops.o stab.o htab.o pacaData.o \
diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c
--- a/arch/ppc64/kernel/chrp_setup.c	Sun Dec 15 17:20:25 2002
+++ b/arch/ppc64/kernel/chrp_setup.c	Tue Mar  4 09:23:43 2003
@@ -72,6 +72,7 @@
 
 extern void find_and_init_phbs(void);
 extern void pSeries_pcibios_fixup(void);
+extern void pSeries_pcibios_fixup_bus(struct pci_bus *bus);
 extern void iSeries_pcibios_fixup(void);
 
 extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
@@ -245,6 +246,7 @@
 
  	#ifndef CONFIG_PPC_ISERIES
  		ppc_md.pcibios_fixup = pSeries_pcibios_fixup;
+ 		ppc_md.pcibios_fixup_bus = pSeries_pcibios_fixup_bus;
  	#else 
  		ppc_md.pcibios_fixup = NULL;
  		// ppc_md.pcibios_fixup = iSeries_pcibios_fixup;
diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
--- a/arch/ppc64/kernel/eeh.c	Fri Dec  6 23:04:33 2002
+++ b/arch/ppc64/kernel/eeh.c	Mon Mar  3 22:26:29 2003
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/bootmem.h>
+#include <linux/mm.h>
 #include <asm/paca.h>
 #include <asm/processor.h>
 #include <asm/naca.h>
diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
--- a/arch/ppc64/kernel/entry.S	Sat Feb 22 01:05:26 2003
+++ b/arch/ppc64/kernel/entry.S	Sat Feb 22 18:35:54 2003
@@ -344,8 +344,8 @@
 recheck:
 	mfmsr	r10		/* Get current interrupt state */
 	li	r4,0
-	ori	r4,r4,MSR_EE|MSR_RI
-	andc	r10,r10,r4	/* clear MSR_EE and MSR_RI */
+	ori	r4,r4,MSR_EE
+	andc	r10,r10,r4	/* clear MSR_EE */
 	mtmsrd	r10,1		/* Update machine state */
 
 #ifdef CONFIG_PPC_ISERIES
@@ -396,7 +396,7 @@
 	mfmsr	r0
 	li	r2, MSR_RI
 	andc	r0,r0,r2
-	mtmsrd	r0
+	mtmsrd	r0,1
 
 	ld	r0,_MSR(r1)
 	mtspr	SRR1,r0
@@ -422,7 +422,7 @@
 /* Note: this must change if we start using the  TIF_NOTIFY_RESUME bit */
 do_work:
 	/* Enable interrupts */
-	ori	r10,r10,MSR_EE|MSR_RI
+	ori	r10,r10,MSR_EE
 	mtmsrd	r10,1
 
 	andi.	r0,r3,_TIF_NEED_RESCHED
diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S	Tue Feb 25 10:27:16 2003
+++ b/arch/ppc64/kernel/head.S	Sun Mar  2 14:39:15 2003
@@ -562,7 +562,7 @@
 	mfmsr	r20
 	li	r21, MSR_RI
 	andc	r20,r20,r21
-	mtmsrd	r20
+	mtmsrd	r20,1
 
 	mtspr   SRR1,r23
 	mtspr   SRR0,r22
@@ -989,7 +989,7 @@
 	mfmsr	r22
 	li	r23, MSR_RI
 	andc	r22,r22,r23
-	mtmsrd	r22
+	mtmsrd	r22,1
 
 	ld	r22,EX_SRR0(r21)	/* Get SRR0 from exc. frame */
 	ld	r23,EX_SRR1(r21)	/* Get SRR1 from exc. frame */
@@ -1094,7 +1094,7 @@
 	mfmsr	r22
 	li	r23, MSR_RI
 	andc	r22,r22,r23
-	mtmsrd	r22
+	mtmsrd	r22,1
 
 	ld	r22,EX_SRR0(r21)	/* Get SRR0 from exc. frame */
 	ld	r23,EX_SRR1(r21)	/* Get SRR1 from exc. frame */
diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c
--- a/arch/ppc64/kernel/htab.c	Sun Feb 16 20:11:50 2003
+++ b/arch/ppc64/kernel/htab.c	Wed Mar 12 15:19:15 2003
@@ -18,7 +18,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	Mon Dec 16 19:26:01 2002
+++ b/arch/ppc64/kernel/irq.c	Sun Mar  9 13:11:22 2003
@@ -341,6 +341,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++) {
@@ -350,9 +351,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action || !action->handler)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++) {
@@ -371,6 +373,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
 	return 0;
@@ -394,81 +398,6 @@
 	local_irq_disable();
 }
 
-#ifdef CONFIG_SMP
-extern unsigned long irq_affinity [NR_IRQS];
-
-typedef struct {
-	unsigned long cpu;
-	unsigned long timestamp;
-} ____cacheline_aligned irq_balance_t;
-
-static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned
-			= { [ 0 ... NR_IRQS-1 ] = { 0, 0 } };
-
-#define IDLE_ENOUGH(cpu,now) \
-		(idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
-
-#define IRQ_ALLOWED(cpu,allowed_mask) \
-		((1UL << cpu) & (allowed_mask))
-
-#define IRQ_BALANCE_INTERVAL (HZ/50)
-
-static unsigned long move(unsigned long curr_cpu, unsigned long allowed_mask,
-			  unsigned long now, int direction)
-{
-	int search_idle = 1;
-	int cpu = curr_cpu;
-
-	goto inside;
-
-	do {
-		if (unlikely(cpu == curr_cpu))
-			search_idle = 0;
-inside:
-		if (direction == 1) {
-			cpu++;
-			if (cpu >= NR_CPUS)
-				cpu = 0;
-		} else {
-			cpu--;
-			if (cpu == -1)
-				cpu = NR_CPUS-1;
-		}
-	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
-			(search_idle && !IDLE_ENOUGH(cpu,now)));
-
-	return cpu;
-}
-
-static inline void balance_irq(int irq)
-{
-	irq_balance_t *entry = irq_balance + irq;
-	unsigned long now = jiffies;
-
-	if (unlikely(time_after(now, entry->timestamp + IRQ_BALANCE_INTERVAL))) {
-		unsigned long allowed_mask;
-		unsigned int new_cpu;
-		unsigned long random_number;
-
-		if (!irq_desc[irq].handler->set_affinity)
-			return;
-
-		random_number = mftb();
-		random_number &= 1;
-
-		allowed_mask = cpu_online_map & irq_affinity[irq];
-		entry->timestamp = now;
-		new_cpu = move(entry->cpu, allowed_mask, now, random_number);
-		if (entry->cpu != new_cpu) {
-			entry->cpu = new_cpu;
-			irq_desc[irq].handler->set_affinity(irq, 1UL << new_cpu);
-		}
-	}
-}
-#else
-#define balance_irq(irq) do { } while (0)
-#endif
-
 /*
  * Eventually, this should take an array of interrupts and an array size
  * so it can dispatch multiple interrupts.
@@ -479,10 +408,6 @@
 	struct irqaction *action;
 	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
-
-	/* XXX This causes bad performance and lockups on XICS - Anton */
-	if (naca->interrupt_controller == IC_OPEN_PIC)
-		balance_irq(irq);
 
 	kstat_cpu(cpu).irqs[irq]++;
 	spin_lock(&desc->lock);
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Sat Feb 22 00:17:10 2003
+++ b/arch/ppc64/kernel/misc.S	Thu Mar 13 21:26:25 2003
@@ -557,7 +557,7 @@
 	.llong .sys32_umount
 	.llong .sys_ni_syscall		/* old lock syscall */
 	.llong .sys32_ioctl
-	.llong .sys32_fcntl		/* 55 */
+	.llong .compat_sys_fcntl	/* 55 */
 	.llong .sys_ni_syscall		/* old mpx syscall */
 	.llong .sys32_setpgid
 	.llong .sys_ni_syscall		/* old ulimit syscall */
@@ -604,7 +604,7 @@
 	.llong .compat_sys_statfs
 	.llong .compat_sys_fstatfs		/* 100 */
 	.llong .sys_ioperm
-	.llong .sys32_socketcall
+	.llong .compat_sys_socketcall
 	.llong .sys32_syslog
 	.llong .compat_sys_setitimer
 	.llong .compat_sys_getitimer		/* 105 */
@@ -706,7 +706,7 @@
 	.llong .sys_ni_syscall		/* reserved for MacOnLinux */
 	.llong .sys_getdents64
 	.llong .sys_pivot_root
-	.llong .sys32_fcntl64
+	.llong .compat_sys_fcntl64
 	.llong .sys_madvise		/* 205 */
 	.llong .sys_mincore
 	.llong .sys_gettid
diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
--- a/arch/ppc64/kernel/pSeries_pci.c	Sun Dec 15 17:17:37 2002
+++ b/arch/ppc64/kernel/pSeries_pci.c	Tue Mar  4 09:37:25 2003
@@ -43,12 +43,6 @@
 #include "open_pic.h"
 #include "pci.h"
 
-/*******************************************************************
- * Forward declares of prototypes. 
- *******************************************************************/
-struct pci_controller *alloc_phb(struct device_node *dev, char *model,
-				 unsigned int addr_size_words) ;
-
 /* RTAS tokens */
 static int read_pci_config;
 static int write_pci_config;
@@ -144,242 +138,173 @@
  * openfirmware and sets it in the pci_dev and pci_config line.
  *
  ******************************************************************/
-int 
-pci_read_irq_line(struct pci_dev *Pci_Dev)
+int pci_read_irq_line(struct pci_dev *pci_dev)
 {
-	u8 InterruptPin;
-	struct device_node *Node;
+	u8 intpin;
+	struct device_node *node;
+
+    	pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin);
 
-    	pci_read_config_byte(Pci_Dev, PCI_INTERRUPT_PIN, &InterruptPin);
-	if (InterruptPin == 0) {
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",Pci_Dev->slot_name);
+	if (intpin == 0) {
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n", pci_dev->slot_name);
 		return 0;	
 	}
-	Node = pci_device_to_OF_node(Pci_Dev);
-	if ( Node == NULL) { 
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",Pci_Dev->slot_name);
+
+	node = pci_device_to_OF_node(pci_dev);
+	if (node == NULL) { 
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",
+		       pci_dev->slot_name);
 		return -1;	
 	}
-	if (Node->n_intrs == 0) 	{
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",Pci_Dev->slot_name);
+	if (node->n_intrs == 0) 	{
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n", pci_dev->slot_name);
 		return -1;	
 	}
-	Pci_Dev->irq = Node->intrs[0].line;
+	pci_dev->irq = node->intrs[0].line;
 
 	if (s7a_workaround) {
-		if (Pci_Dev->irq > 16)
-			Pci_Dev->irq -= 3;
+		if (pci_dev->irq > 16)
+			pci_dev->irq -= 3;
 	}
 
-	pci_write_config_byte(Pci_Dev, PCI_INTERRUPT_LINE, Pci_Dev->irq);
+	pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
 	
-	PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",Pci_Dev->slot_name,Pci_Dev->irq);
+	PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",
+	       pci_dev->slot_name, pci_dev->irq);
 	return 0;
 }
 
-/******************************************************************
- * Find all PHBs in the system and initialize a set of data 
- * structures to represent them.
- ******************************************************************/
-unsigned long __init
-find_and_init_phbs(void)
-{
-        struct device_node *Pci_Node;
-        struct pci_controller *phb;
-        unsigned int root_addr_size_words = 0, this_addr_size_words = 0;
-	unsigned int this_addr_count = 0, range_stride;
-        unsigned int *ui_ptr = NULL, *ranges;
-        char *model;
-	struct pci_range64 range;
+static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose,
+						struct device_node *dev,
+						int primary)
+{
+	unsigned int *ranges;
+	unsigned long size;
+	int rlen = 0;
+	int memno = 0;
 	struct resource *res;
-	unsigned int memno, rlen, i, index;
-	unsigned int *opprop;
-	int has_isa = 0;
-        PPCDBG(PPCDBG_PHBINIT, "find_and_init_phbs\n"); 
+	int np, na = prom_n_addr_cells(dev);
+	unsigned long pci_addr, cpu_phys_addr;
 
-	read_pci_config = rtas_token("read-pci-config");
-	write_pci_config = rtas_token("write-pci-config");
-	ibm_read_pci_config = rtas_token("ibm,read-pci-config");
-	ibm_write_pci_config = rtas_token("ibm,write-pci-config");
+	np = na + 5;
 
-	if (naca->interrupt_controller == IC_OPEN_PIC) {
-		opprop = (unsigned int *)get_property(find_path_device("/"),
-				"platform-open-pic", NULL);
-	}
+	/*
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 2:	a PCI address
+	 *   cells 3 or 3+4:	a CPU physical address
+	 *			(size depending on dev->n_addr_cells)
+	 *   cells 4+5 or 5+6:	the size of the range
+	 */
+	rlen = 0;
+	hose->io_base_phys = 0;
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+		res = NULL;
+		pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
+
+		cpu_phys_addr = ranges[3];
+		if (na == 2)
+			cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
+
+		size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
+
+		switch (ranges[0] >> 24) {
+		case 1:		/* I/O space */
+			hose->io_base_phys = cpu_phys_addr;
+			hose->io_base_virt = __ioremap(hose->io_base_phys,
+						       size, _PAGE_NO_CACHE);
+			if (primary) {
+				pci_io_base = (unsigned long)hose->io_base_virt;
+				if (find_type_devices("isa"))
+					isa_io_base = pci_io_base;
+			}
 
-	/* Get the root address word size. */
-	ui_ptr = (unsigned int *) get_property(find_path_device("/"), 
-					       "#size-cells", NULL);
-	if (ui_ptr) {
-		root_addr_size_words = *ui_ptr;
-	} else {
-		PPCDBG(PPCDBG_PHBINIT, "\tget #size-cells failed.\n"); 
-		return(-1);
+			res = &hose->io_resource;
+			res->flags = IORESOURCE_IO;
+			res->start = pci_addr;
+			res->start += (unsigned long)hose->io_base_virt -
+				pci_io_base;
+			break;
+		case 2:		/* memory space */
+			memno = 0;
+			while (memno < 3 && hose->mem_resources[memno].flags)
+				++memno;
+
+			if (memno == 0)
+				hose->pci_mem_offset = cpu_phys_addr - pci_addr;
+			if (memno < 3) {
+				res = &hose->mem_resources[memno];
+				res->flags = IORESOURCE_MEM;
+				res->start = cpu_phys_addr;
+			}
+			break;
+		}
+		if (res != NULL) {
+			res->name = dev->full_name;
+			res->end = res->start + size - 1;
+			res->parent = NULL;
+			res->sibling = NULL;
+			res->child = NULL;
+		}
+		ranges += np;
 	}
+}
 
-	if (find_type_devices("isa")) {
-		has_isa = 1;
-		PPCDBG(PPCDBG_PHBINIT, "\tFound an ISA bus.\n"); 
-	}
+static void python_countermeasures(unsigned long addr)
+{
+	void *chip_regs;
+	volatile u32 *tmp, i;
 
-	index = 0;
+	/* Python's register file is 1 MB in size. */
+	chip_regs = ioremap(addr & ~(0xfffffUL), 0x100000); 
 
-	/******************************************************************
-	* Find all PHB devices and create an object for them.
-	******************************************************************/
-	for (Pci_Node = find_devices("pci"); Pci_Node != NULL; Pci_Node = Pci_Node->next) {
-		model = (char *) get_property(Pci_Node, "model", NULL);
-		if (model != NULL)  {
-			phb = alloc_phb(Pci_Node, model, root_addr_size_words);
-			if (phb == NULL) return(-1);
-		}
-		else {
-         		continue;
-		}
-		
-		/* Get this node's address word size. */
-		ui_ptr = (unsigned int *) get_property(Pci_Node, "#size-cells", NULL);
-		if (ui_ptr)
-			this_addr_size_words = *ui_ptr;
-		else
-			this_addr_size_words = 1;
-		/* Get this node's address word count. */
-		ui_ptr = (unsigned int *) get_property(Pci_Node, "#address-cells", NULL);
-		if (ui_ptr)
-			this_addr_count = *ui_ptr;
-		else
-			this_addr_count = 3;
-		
-		range_stride = this_addr_count + root_addr_size_words + this_addr_size_words;
-	      
-		memno = 0;
-		phb->io_base_phys = 0;
-         
-		ranges = (unsigned int *) get_property(Pci_Node, "ranges", &rlen);
-		PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen);
-                
-		for (i = 0; i < (rlen/sizeof(*ranges)); i+=range_stride) {
-		  	/* Put the PCI addr part of the current element into a 
-			 * '64' struct. 
-			 */
-		  	range = *((struct pci_range64 *)(ranges + i));
-
-			/* If this is a '32' element, map into a 64 struct. */
-			if ((range_stride * sizeof(int)) == 
-			   sizeof(struct pci_range32)) {
-				range.parent_addr = 
-					(unsigned long)(*(ranges + i + 3));
-				range.size = 
-					(((unsigned long)(*(ranges + i + 4)))<<32) | 
-					(*(ranges + i + 5));
-			} else {
-				range.parent_addr = 
-					(((unsigned long)(*(ranges + i + 3)))<<32) | 
-					(*(ranges + i + 4));
-				range.size = 
-					(((unsigned long)(*(ranges + i + 5)))<<32) | 
-					(*(ranges + i + 6));
-			}
-			
-			PPCDBG(PPCDBG_PHBINIT, "\trange.parent_addr    = 0x%lx\n", 
-			       range.parent_addr);
-			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.hi  = 0x%lx\n", 
-			       range.child_addr.a_hi);
-			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.mid = 0x%lx\n", 
-			       range.child_addr.a_mid);
-			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.lo  = 0x%lx\n", 
-			       range.child_addr.a_lo);
-			PPCDBG(PPCDBG_PHBINIT, "\trange.size           = 0x%lx\n", 
-			       range.size);
-
-			res = NULL;
-		        switch ((range.child_addr.a_hi >> 24) & 0x3) {
-			case 1:		/* I/O space */
-				PPCDBG(PPCDBG_PHBINIT, "\tIO Space\n");
-				phb->io_base_phys = range.parent_addr;
-				res = &phb->io_resource;
-				res->name = Pci_Node->full_name;
-				res->flags = IORESOURCE_IO;
-				phb->io_base_virt = __ioremap(phb->io_base_phys, range.size, _PAGE_NO_CACHE);
-				if (!pci_io_base) {
-					pci_io_base = (unsigned long)phb->io_base_virt;
-					if (has_isa)
-						isa_io_base = pci_io_base;
-				}
-				res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo));
-				res->start += (unsigned long)phb->io_base_virt - pci_io_base;
-				res->end =   res->start + range.size - 1;
-				res->parent = NULL;
-				res->sibling = NULL;
-				res->child = NULL;
-				phb->pci_io_offset = range.parent_addr - 
-					((((unsigned long)
-					   range.child_addr.a_mid) << 32) | 
-					 (range.child_addr.a_lo));
-				PPCDBG(PPCDBG_PHBINIT, "\tpci_io_offset  = 0x%lx\n", 
-				       phb->pci_io_offset);
-			  	break;
-			case 2:		/* mem space */
-				PPCDBG(PPCDBG_PHBINIT, "\tMem Space\n");
-				phb->pci_mem_offset = range.parent_addr - 
-					((((unsigned long)
-					   range.child_addr.a_mid) << 32) | 
-					 (range.child_addr.a_lo));
-				PPCDBG(PPCDBG_PHBINIT, "\tpci_mem_offset = 0x%lx\n", 
-				       phb->pci_mem_offset);
-				if (memno < sizeof(phb->mem_resources)/sizeof(phb->mem_resources[0])) {
-					res = &(phb->mem_resources[memno]);
-					++memno;
-					res->name = Pci_Node->full_name;
-					res->flags = IORESOURCE_MEM;
-					res->start = range.parent_addr;
-					res->end =   range.parent_addr + range.size - 1;
-					res->parent = NULL;
-					res->sibling = NULL;
-					res->child = NULL;
-				}
-			  	break;
-			}
-		}
-		PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys   = 0x%lx\n", 
-		       phb->io_base_phys); 
-		PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n", 
-		       phb->pci_mem_offset); 
+	/* 
+	 * Firmware doesn't always clear this bit which is critical
+	 * for good performance - Anton
+	 */
 
-		if (naca->interrupt_controller == IC_OPEN_PIC) {
-			int addr = root_addr_size_words * (index + 2) - 1;
-			openpic_setup_ISU(index, opprop[addr]); 
-		}
-		index++;
+#define PRG_CL_RESET_VALID 0x00010000
+
+	tmp = (u32 *)((unsigned long)chip_regs + 0xf6030);
+
+	if (*tmp & PRG_CL_RESET_VALID) {
+		printk(KERN_INFO "Python workaround: ");
+		*tmp &= ~PRG_CL_RESET_VALID;
+		/*
+		 * We must read it back for changes to
+		 * take effect
+		 */
+		i = *tmp;
+		printk("reg0: %x\n", i);
 	}
-	pci_devs_phb_init();
-	return 0;	 /*Success */
+
+	iounmap(chip_regs);
 }
 
-/******************************************************************
- *
- * Allocate and partially initialize a structure to represent a PHB.
- *
- ******************************************************************/
-struct pci_controller *
-alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words)
+struct pci_controller *alloc_phb(struct device_node *dev,
+				 unsigned int addr_size_words)
 {
 	struct pci_controller *phb;
 	unsigned int *ui_ptr = NULL, len;
 	struct reg_property64 reg_struct;
 	int *bus_range;
 	int *buid_vals;
+	char *model;
+	enum phb_types phb_type;
+
+	model = (char *)get_property(dev, "model", NULL);
+
+	if (!model) {
+		printk(KERN_ERR "alloc_phb: phb has no model property\n");
+		model = "<empty>";
+	}
 
-	PPCDBG(PPCDBG_PHBINIT, "alloc_phb: %s\n", dev->full_name); 
-	PPCDBG(PPCDBG_PHBINIT, "\tdev             = 0x%lx\n", dev); 
-	PPCDBG(PPCDBG_PHBINIT, "\tmodel           = 0x%lx\n", model); 
-	PPCDBG(PPCDBG_PHBINIT, "\taddr_size_words = 0x%lx\n", addr_size_words); 
-  
 	/* Found a PHB, now figure out where his registers are mapped. */
 	ui_ptr = (unsigned int *) get_property(dev, "reg", &len);
 	if (ui_ptr == NULL) {
 		PPCDBG(PPCDBG_PHBINIT, "\tget reg failed.\n"); 
-		return(NULL);
+		return NULL;
 	}
 
 	if (addr_size_words == 1) {
@@ -389,83 +314,30 @@
 		reg_struct = *((struct reg_property64 *)ui_ptr);
 	}
 
-	PPCDBG(PPCDBG_PHBINIT, "\treg_struct.address = 0x%lx\n", reg_struct.address);
-	PPCDBG(PPCDBG_PHBINIT, "\treg_struct.size    = 0x%lx\n", reg_struct.size); 
-
-	/***************************************************************
-	* Set chip specific data in the phb, including types & 
-	* register pointers.
-	***************************************************************/
-
-	/****************************************************************
-	* Python
-	***************************************************************/
 	if (strstr(model, "Python")) {
-		void *chip_regs;
-		volatile u32 *tmp, i;
-
-		PPCDBG(PPCDBG_PHBINIT, "\tCreate python\n");
-
-		phb = pci_alloc_pci_controller("PHB PY", phb_type_python);
-		if (phb == NULL)
-			return NULL;
-
-		/* Python's register file is 1 MB in size. */
-		chip_regs = ioremap(reg_struct.address & ~(0xfffffUL),
-				    0x100000); 
-
-		/* 
-		 * Firmware doesn't always clear this bit which is critical
-		 * for good performance - Anton
-		 */
-
-#define PRG_CL_RESET_VALID 0x00010000
-
-		tmp = (u32 *)((unsigned long)chip_regs + 0xf6030);
-
-		if (*tmp & PRG_CL_RESET_VALID) {
-			printk("Python workaround: ");
-			*tmp &= ~PRG_CL_RESET_VALID;
-			/*
-			 * We must read it back for changes to
-			 * take effect
-			 */
-			i = *tmp;
-			printk("reg0: %x\n", i);
-		}
+		phb_type = phb_type_python;
+	} else if (strstr(model, "Speedwagon")) {
+		phb_type = phb_type_speedwagon;
+	} else if (strstr(model, "Winnipeg")) {
+		phb_type = phb_type_winnipeg;
+	} else {
+		printk(KERN_ERR "alloc_phb: unknown PHB %s\n", model);
+		phb_type = phb_type_unknown;
+	}
 
-	/***************************************************************
-	* Speedwagon
-	*   include Winnipeg as well for the time being.
-	***************************************************************/
-	} else if ((strstr(model, "Speedwagon")) || 
-		   (strstr(model, "Winnipeg"))) {
-		PPCDBG(PPCDBG_PHBINIT, "\tCreate speedwagon\n");
-	        phb = pci_alloc_pci_controller("PHB SW", phb_type_speedwagon);
-		if (phb == NULL)
-			return NULL;
-
-		phb->local_number = ((reg_struct.address >> 12) & 0xf) - 0x8;
-
-	/***************************************************************
-	* Trying to build a known just gets the code in trouble.
-	***************************************************************/
-	} else { 
-		PPCDBG(PPCDBG_PHBINIT, "\tUnknown PHB Type!\n");
-		printk("PCI: Unknown Phb Type!\n");
+	phb = pci_alloc_pci_controller(phb_type);
+	if (phb == NULL)
 		return NULL;
-	}
+
+	if (phb_type == phb_type_python)
+		python_countermeasures(reg_struct.address);
 
 	bus_range = (int *) get_property(dev, "bus-range", &len);
 	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		PPCDBG(PPCDBG_PHBINIT, "Can't get bus-range for %s\n", dev->full_name);
 		kfree(phb);
-		return(NULL);
+		return NULL;
 	}
 
-	/***************************************************************
-	* Finished with the initialization
-	***************************************************************/
 	phb->first_busno =  bus_range[0];
 	phb->last_busno  =  bus_range[1];
 
@@ -473,7 +345,7 @@
 	phb->ops = &rtas_pci_ops;
 
 	buid_vals = (int *) get_property(dev, "ibm,fw-phb-id", &len);
-	
+
 	if (buid_vals == NULL) {
 		phb->buid = 0;
 	} else {
@@ -486,24 +358,71 @@
 			panic("pSeries_pci:  this system has large bus numbers and the kernel was not\n"
 			      "built with the patch that fixes include/linux/pci.h struct pci_bus so\n"
 			      "number, primary, secondary and subordinate are ints.\n");
-    }
-    
-	if (len < 2 * sizeof(int))
-		phb->buid = (unsigned long)buid_vals[0];  // Support for new OF that only has 1 integer for buid.
-	else
-		phb->buid = (((unsigned long)buid_vals[0]) << 32UL) |
-			(((unsigned long)buid_vals[1]) & 0xffffffff);
-  	
+		}
+
+		if (len < 2 * sizeof(int))
+			// Support for new OF that only has 1 integer for buid.
+			phb->buid = (unsigned long)buid_vals[0];
+		else
+			phb->buid = (((unsigned long)buid_vals[0]) << 32UL) |
+				(((unsigned long)buid_vals[1]) & 0xffffffff);
+
 		phb->first_busno += (phb->global_number << 8);
 		phb->last_busno += (phb->global_number << 8);
 	}
 
 	/* Dump PHB information for Debug */
-	PPCDBGCALL(PPCDBG_PHBINIT,dumpPci_Controller(phb) );
+	PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Controller(phb));
 
 	return phb;
 }
 
+unsigned long __init find_and_init_phbs(void)
+{
+	struct device_node *node;
+	struct pci_controller *phb;
+	unsigned int root_size_cells = 0;
+	unsigned int index;
+	unsigned int *opprop;
+	struct device_node *root = find_path_device("/");
+
+	read_pci_config = rtas_token("read-pci-config");
+	write_pci_config = rtas_token("write-pci-config");
+	ibm_read_pci_config = rtas_token("ibm,read-pci-config");
+	ibm_write_pci_config = rtas_token("ibm,write-pci-config");
+
+	if (naca->interrupt_controller == IC_OPEN_PIC) {
+		opprop = (unsigned int *)get_property(root,
+				"platform-open-pic", NULL);
+	}
+
+	root_size_cells = prom_n_size_cells(root);
+
+	index = 0;
+
+	for (node = root->child; node != NULL; node = node->sibling) {
+		if (node->type == NULL || strcmp(node->type, "pci") != 0)
+			continue;
+
+		phb = alloc_phb(node, root_size_cells);
+		if (!phb)
+			continue;
+
+		pci_process_bridge_OF_ranges(phb, node, index == 0);
+
+		if (naca->interrupt_controller == IC_OPEN_PIC) {
+			int addr = root_size_cells * (index + 2) - 1;
+			openpic_setup_ISU(index, opprop[addr]); 
+		}
+
+		index++;
+	}
+
+	pci_devs_phb_init();
+
+	return 0;
+}
+
 void 
 fixup_resources(struct pci_dev *dev)
 {
@@ -581,6 +500,55 @@
  	}
 }   
 
+void __init pSeries_pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_controller *phb = PCI_GET_PHB_PTR(bus);
+	struct resource *res;
+	int i;
+
+	if (bus->parent == NULL) {
+		/* This is a host bridge - fill in its resources */
+		phb->bus = bus;
+		bus->resource[0] = res = &phb->io_resource;
+		if (!res->flags)
+			BUG();	/* No I/O resource for this PHB? */
+
+		for (i = 0; i < 3; ++i) {
+			res = &phb->mem_resources[i];
+			if (!res->flags) {
+				if (i == 0)
+					BUG();	/* No memory resource for this PHB? */
+			}
+			bus->resource[i+1] = res;
+		}
+	} else {
+		/* This is a subordinate bridge */
+		pci_read_bridge_bases(bus);
+
+		for (i = 0; i < 4; ++i) {
+			if ((res = bus->resource[i]) == NULL)
+				continue;
+			if (!res->flags)
+				continue;
+			if (res == pci_find_parent_resource(bus->self, res)) {
+				/* Transparent resource -- don't try to "fix" it. */
+				continue;
+			}
+			if (res->flags & IORESOURCE_IO) {
+				unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base;
+				res->start += offset;
+				res->end += offset;
+			} else if (phb->pci_mem_offset
+				   && (res->flags & IORESOURCE_MEM)) {
+				if (res->start < phb->pci_mem_offset) {
+					res->start += phb->pci_mem_offset;
+					res->end += phb->pci_mem_offset;
+				}
+			}
+		}
+	}
+}
+
 static void check_s7a(void)
 {
 	struct device_node *root;
@@ -627,17 +595,6 @@
 		node=node->parent;
 	}
 	return NULL;
-}
-
-/*********************************************************************** 
- * ppc64_pcibios_init
- *  
- * Chance to initialize and structures or variable before PCI Bus walk.
- *  
- ***********************************************************************/
-void 
-pSeries_pcibios_init(void)
-{
 }
 
 /*
diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c	Fri Feb  7 00:20:34 2003
+++ b/arch/ppc64/kernel/pci.c	Sun Mar 16 14:16:32 2003
@@ -49,7 +49,6 @@
 void fixup_resources(struct pci_dev* dev);
 
 void   iSeries_pcibios_init(void);
-void   pSeries_pcibios_init(void);
 
 struct pci_controller* hose_head;
 struct pci_controller** hose_tail = &hose_head;
@@ -128,42 +127,6 @@
 	return NULL;
 }
 
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
-					 struct pbus_set_ranges_data *pranges)
-{
-}
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			     struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-	struct pci_controller* hose = PCI_GET_PHB_PTR(dev);
-	
-	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) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
-		return;
-	}
-
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
-}
-
 static void
 pcibios_fixup_resources(struct pci_dev* dev)
 {
@@ -363,16 +326,33 @@
  * Allocate pci_controller(phb) initialized common variables. 
  */
 struct pci_controller * __init
-pci_alloc_pci_controller(char *model, enum phb_types controller_type)
+pci_alloc_pci_controller(enum phb_types controller_type)
 {
         struct pci_controller *hose;
-        PPCDBG(PPCDBG_PHBINIT, "PCI: Allocate pci_controller for %s\n",model);
+	char *model;
+
         hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller));
         if(hose == NULL) {
                 printk(KERN_ERR "PCI: Allocate pci_controller failed.\n");
                 return NULL;
         }
         memset(hose, 0, sizeof(struct pci_controller));
+
+	switch(controller_type) {
+	case phb_type_python:
+		model = "PHB PY";
+		break;
+	case phb_type_speedwagon:
+		model = "PHB SW";
+		break;
+	case phb_type_winnipeg:
+		model = "PHB WP";
+		break;
+	default:
+		model = "PHB UK";
+		break;
+	}
+
         if(strlen(model) < 8)
 		strcpy(hose->what,model);
         else
@@ -393,9 +373,7 @@
 	struct pci_bus *bus;
 	int next_busno;
 
-#ifndef CONFIG_PPC_ISERIES
-	pSeries_pcibios_init();
-#else
+#ifdef CONFIG_PPC_ISERIES
 	iSeries_pcibios_init(); 
 #endif
 
@@ -450,54 +428,7 @@
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-#ifndef CONFIG_PPC_ISERIES
-	struct pci_controller *phb = PCI_GET_PHB_PTR(bus);
-	struct resource *res;
-	int i;
-
-	if (bus->parent == NULL) {
-		/* This is a host bridge - fill in its resources */
-		phb->bus = bus;
-		bus->resource[0] = res = &phb->io_resource;
-		if (!res->flags)
-			BUG();	/* No I/O resource for this PHB? */
-
-		for (i = 0; i < 3; ++i) {
-			res = &phb->mem_resources[i];
-			if (!res->flags) {
-				if (i == 0)
-					BUG();	/* No memory resource for this PHB? */
-			}
-			bus->resource[i+1] = res;
-		}
-	} else {
-		/* This is a subordinate bridge */
-		pci_read_bridge_bases(bus);
-
-		for (i = 0; i < 4; ++i) {
-			if ((res = bus->resource[i]) == NULL)
-				continue;
-			if (!res->flags)
-				continue;
-			if (res == pci_find_parent_resource(bus->self, res)) {
-				/* Transparent resource -- don't try to "fix" it. */
-				continue;
-			}
-			if (res->flags & IORESOURCE_IO) {
-				unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base;
-				res->start += offset;
-				res->end += offset;
-			} else if (phb->pci_mem_offset
-				   && (res->flags & IORESOURCE_MEM)) {
-				if (res->start < phb->pci_mem_offset) {
-					res->start += phb->pci_mem_offset;
-					res->end += phb->pci_mem_offset;
-				}
-			}
-		}
-	}
-#endif	
-	if ( ppc_md.pcibios_fixup_bus )
+	if (ppc_md.pcibios_fixup_bus)
 		ppc_md.pcibios_fixup_bus(bus);
 }
 
diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
--- a/arch/ppc64/kernel/pci.h	Sat Dec  7 21:26:49 2002
+++ b/arch/ppc64/kernel/pci.h	Mon Mar  3 22:12:45 2003
@@ -14,7 +14,7 @@
 
 extern unsigned long isa_io_base;
 
-extern struct pci_controller* pci_alloc_pci_controller(char *model, enum phb_types controller_type);
+extern struct pci_controller* pci_alloc_pci_controller(enum phb_types controller_type);
 extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node);
 
 extern struct pci_controller* hose_head;
diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c
--- a/arch/ppc64/kernel/pci_dma.c	Sun Dec 15 17:35:20 2002
+++ b/arch/ppc64/kernel/pci_dma.c	Wed Mar 12 15:19:15 2003
@@ -21,6 +21,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/slab.h>
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	Sun Dec 15 17:38:18 2002
+++ b/arch/ppc64/kernel/prom.c	Sun Mar  2 19:21:25 2003
@@ -2040,11 +2040,11 @@
 	if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
 		return NULL;
 
-	last = (struct bi_record *)bi_recs->data[0];
+	last = (struct bi_record *)(long)bi_recs->data[0];
 	if ( last == NULL || last->tag != BI_LAST )
 		return NULL;
 
-	first = (struct bi_record *)last->data[0];
+	first = (struct bi_record *)(long)last->data[0];
 	if ( first == NULL || first != bi_recs )
 		return NULL;
 
diff -Nru a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
--- a/arch/ppc64/kernel/rtc.c	Sun Jan  5 19:10:54 2003
+++ b/arch/ppc64/kernel/rtc.c	Wed Mar 12 15:19:15 2003
@@ -21,6 +21,7 @@
 
 #define RTC_VERSION		"1.1"
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff -Nru a/arch/ppc64/kernel/sys32.S b/arch/ppc64/kernel/sys32.S
--- a/arch/ppc64/kernel/sys32.S	Tue Feb 18 10:25:13 2003
+++ b/arch/ppc64/kernel/sys32.S	Thu Mar 13 21:26:25 2003
@@ -25,287 +25,3 @@
 	extsw		r4,r4		/* sign extend off_t offset parm */
 	b		.sys_lseek
 
-_GLOBAL(sys32_socketcall)	/* r3=call, r4=args */
-	cmpwi		r3, 1
-	blt-		.do_einval
-	cmpwi		r3, 17
-	bgt-		.do_einval
-	subi		r3, r3, 1	/* index into socketcall_table vectors and jmp */
-	sldi		r3, r3, 3	/* each entry is 8 bytes */
-	LOADADDR(r10,.socketcall_table_begin)
-	ldx		r10, r10, r3
-	mtctr		r10
-	bctr
-
-/* Socket function vectored fix ups for 32 bit */
-_STATIC(do_sys_socket) /* sys_socket(int, int, int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwa		r4,4(r10)
-3:	lwa		r5,8(r10)
-	b		.sys_socket
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_sys_bind) /* sys_bind(int fd, struct sockaddr *, int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwa		r5,8(r10)
-	b		.sys_bind
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_sys_connect) /* sys_connect(int, struct sockaddr *, int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwa		r5,8(r10)
-	b		.sys_connect
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_sys_listen) /* sys_listen(int, int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwa		r4,4(r10)
-	b		.sys_listen
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.previous
-
-_STATIC(do_sys_accept) /* sys_accept(int, struct sockaddr *, int *) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwz		r5,8(r10)
-	b		.sys_accept
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_sys_getsockname) /* sys_getsockname(int, struct sockaddr *, int *) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwz		r5,8(r10)
-	b		.sys_getsockname
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_sys_getpeername) /* sys_getpeername(int, struct sockaddr *, int *) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwz		r5,8(r10)
-	b		.sys_getpeername
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_sys_socketpair) /* sys_socketpair(int, int, int, int *) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwa		r4,4(r10)
-3:	lwa		r5,8(r10)
-4:	lwz		r6,12(r10)
-	b		.sys_socketpair
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.llong		4b,.do_efault
-	.previous
-
-_STATIC(do_sys_send) /* sys_send(int, void *, size_t, unsigned int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwz		r5,8(r10)
-4:	lwz		r6,12(r10)
-	b		.sys_send
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.llong		4b,.do_efault
-	.previous
-
-_STATIC(do_sys_recv) /* sys_recv(int, void *, size_t, unsigned int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwz		r5,8(r10)
-4:	lwz		r6,12(r10)
-	b		.sys_recv
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.llong		4b,.do_efault
-	.previous
-
-_STATIC(do_sys_sendto) /* sys32_sendto(int, u32, compat_size_t, unsigned int, u32, int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwz		r5,8(r10)
-4:	lwz		r6,12(r10)
-5:	lwz		r7,16(r10)
-6:	lwz		r8,20(r10)
-	b		.sys_sendto
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.llong		4b,.do_efault
-	.llong		5b,.do_efault
-	.llong		6b,.do_efault
-	.previous
-
-_STATIC(do_sys_recvfrom) /* sys32_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwz		r5,8(r10)
-4:	lwz		r6,12(r10)
-5:	lwz		r7,16(r10)
-6:	lwz		r8,20(r10)
-	b		.sys_recvfrom
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.llong		4b,.do_efault
-	.llong		5b,.do_efault
-	.llong		6b,.do_efault
-	.previous
-
-_STATIC(do_sys_shutdown) /* sys_shutdown(int, int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwa		r4,4(r10)
-	b		.sys_shutdown
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.previous
-
-_STATIC(do_sys_setsockopt) /* sys32_setsockopt(int, int, int, char *, int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwa		r4,4(r10)
-3:	lwa		r5,8(r10)
-4:	lwz		r6,12(r10)
-5:	lwa		r7,16(r10)
-	b		.sys32_setsockopt
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.llong		4b,.do_efault
-	.llong		5b,.do_efault
-	.previous
-
-_STATIC(do_sys_getsockopt) /* sys32_getsockopt(int, int, int, u32, u32) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwa		r4,4(r10)
-3:	lwa		r5,8(r10)
-4:	lwz		r6,12(r10)
-5:	lwz		r7,16(r10)
-	b		.sys32_getsockopt
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.llong		4b,.do_efault
-	.llong		5b,.do_efault
-	.previous
-
-_STATIC(do_sys_sendmsg) /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwa		r5,8(r10)
-	b		.sys32_sendmsg
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_sys_recvmsg) /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */
-	mr		r10,r4
-1:	lwa		r3,0(r10)
-2:	lwz		r4,4(r10)
-3:	lwa		r5,8(r10)
-	b		.sys32_recvmsg
-	.section	__ex_table,"a"
-	.align		3
-	.llong		1b,.do_efault
-	.llong		2b,.do_efault
-	.llong		3b,.do_efault
-	.previous
-
-_STATIC(do_einval)
-	li	r3,-EINVAL
-	blr
-
-_STATIC(do_efault)
-	li	r3,-EFAULT
-	blr
-
-	.balign	8
-_GLOBAL(socketcall_table_begin)
-	.llong		.do_sys_socket
-	.llong		.do_sys_bind
-	.llong		.do_sys_connect
-	.llong		.do_sys_listen
-	.llong		.do_sys_accept
-	.llong		.do_sys_getsockname
-	.llong		.do_sys_getpeername
-	.llong		.do_sys_socketpair
-	.llong		.do_sys_send
-	.llong		.do_sys_recv
-	.llong		.do_sys_sendto
-	.llong		.do_sys_recvfrom
-	.llong		.do_sys_shutdown
-	.llong		.do_sys_setsockopt
-	.llong		.do_sys_getsockopt
-	.llong		.do_sys_sendmsg
-	.llong		.do_sys_recvmsg
-_GLOBAL(socketcall_table_end)
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/ppc64/kernel/sys_ppc32.c	Sat Mar 15 10:25:46 2003
@@ -15,7 +15,6 @@
  */
 
 #include <asm/ptrace.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/fs.h> 
@@ -74,13 +73,11 @@
 #include <asm/ppc32.h>
 #include <asm/mmu_context.h>
 
-struct iovec32 { u32 iov_base; compat_size_t iov_len; };
-
 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
-			      const struct iovec32 *vector, u32 count)
+			      const struct compat_iovec *vector, u32 count)
 {
 	compat_ssize_t tot_len;
 	struct iovec iovstack[UIO_FASTIOV];
@@ -114,7 +111,7 @@
 			goto out;
 	}
 	retval = -EFAULT;
-	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		goto out;
 
 	/*
@@ -206,7 +203,7 @@
 	return retval;
 }
 
-asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret = -EBADF;
@@ -227,7 +224,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret = -EBADF;
@@ -248,32 +245,6 @@
 	return ret;
 }
 
-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
-asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case F_GETLK:
-	case F_SETLK:
-	case F_SETLKW:
-	{
-		struct flock f;
-		mm_segment_t old_fs;
-		long ret;
-
-		if(get_compat_flock(&f, (struct compat_flock *)arg))
-			return -EFAULT;
-		old_fs = get_fs(); set_fs (KERNEL_DS);
-		ret = sys_fcntl(fd, cmd, (unsigned long)&f);
-		set_fs (old_fs);
-		if(put_compat_flock(&f, (struct compat_flock *)arg))
-			return -EFAULT;
-		return ret;
-	}
-	default:
-		return sys_fcntl(fd, cmd, (unsigned long)arg);
-	}
-}
-
 struct ncp_mount_data32_v3 {
         int version;
         unsigned int ncp_fd;
@@ -2135,708 +2106,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int err;
-
-	if (optlen < sizeof(*up))
-		return -EINVAL;
-	if (get_user(ktime.tv_sec, &up->tv_sec) ||
-	    __get_user(ktime.tv_usec, &up->tv_usec))
-		return -EFAULT;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
-	set_fs(old_fs);
-
-	return err;
-}
-
-asmlinkage long sys32_setsockopt(int fd, int level, int optname, char* optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_set_sock_timeout(fd, level, optname, optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				      char *optval, int *optlen);
-
-static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int len, err;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-	if (len < sizeof(*up))
-		return -EINVAL;
-	len = sizeof(ktime);
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
-	set_fs(old_fs);
-
-	if (!err) {
-		if (put_user(sizeof(*up), optlen) ||
-		    put_user(ktime.tv_sec, &up->tv_sec) ||
-		    __put_user(ktime.tv_usec, &up->tv_usec))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-asmlinkage int sys32_getsockopt(int fd, int level, int optname,
-				char *optval, int *optlen)
-{
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_get_sock_timeout(fd, level, optname, optval, optlen);
-	return sys_getsockopt(fd, level, optname, optval, optlen);
-}
-
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain -  16 for IP, 16 for IPX, 24 for IPv6, about 80 for AX.25 */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-struct msghdr32
-{
-	u32               msg_name;
-	int               msg_namelen;
-	u32               msg_iov;
-	compat_size_t msg_iovlen;
-	u32               msg_control;
-	compat_size_t msg_controllen;
-	unsigned          msg_flags;
-};
-
-struct cmsghdr32
-{
-	compat_size_t cmsg_len;
-	int               cmsg_level;
-	int               cmsg_type;
-};
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					     struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if (kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if (kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if (kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while (ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-asmlinkage long sys32_sendmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-	
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if (kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if (copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		if (kcmsg32->cmsg_level == SOL_SOCKET &&
-		    kcmsg32->cmsg_type == SO_TIMESTAMP) {
-			struct timeval tv;
-			struct compat_timeval *tv32;
-
-			if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
-				kfree(workbuf);
-				goto fail;
-			}
-			copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
-			tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32);
-			tv32->tv_sec = tv.tv_sec;
-			tv32->tv_usec = tv.tv_usec;
-			clen32 = sizeof(*tv32) +
-				CMSG32_ALIGN(sizeof(struct cmsghdr32));
-		} else {
-			copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-				       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-			clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-				  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		}
-		kcmsg32->cmsg_len = clen32;
-
-		switch (kcmsg32->cmsg_type) {
-			/*
-			 * The timestamp type's data needs to be converted
-			 * from 64-bit time values to 32-bit time values
-			 */
-		case SO_TIMESTAMP: {
-			compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32);
-			__kernel_time_t*   ptr_time   = CMSG_DATA(ucmsg);
-			*ptr_time32     = *ptr_time;
-			*(ptr_time32+1) = *(ptr_time+1);
-			kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) -
-						sizeof(compat_time_t));
-		}
-		default:;
-		}
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage long sys32_recvmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-	
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-  if (uaddr != NULL && err >= 0 && kern_msg.msg_namelen)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	
-	return len;
-}
-
 /*
  * count32() counts the number of arguments/envelopes
  */
@@ -3550,13 +2819,6 @@
 asmlinkage long sys32_umount(char * name, u32 flags)
 {
 	return sys_umount(name, (int)flags);
-}
-
-asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
-		return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
-	return sys32_fcntl(fd, cmd, arg);
 }
 
 struct __sysctl_args32 {
diff -Nru a/arch/ppc64/mm/extable.c b/arch/ppc64/mm/extable.c
--- a/arch/ppc64/mm/extable.c	Tue Jan 14 00:54:31 2003
+++ b/arch/ppc64/mm/extable.c	Wed Mar 12 15:19:15 2003
@@ -9,7 +9,6 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S
--- a/arch/ppc64/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/ppc64/vmlinux.lds.S	Fri Feb 14 15:10:57 2003
@@ -97,6 +97,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	Tue Feb 25 02:42:32 2003
+++ b/arch/ppc64/xmon/xmon.c	Sun Mar  9 15:17:38 2003
@@ -1381,16 +1381,23 @@
 	char *p, *q;
 
 	n = 0;
-	if( setjmp(bus_error_jmp) == 0 ){
+	if (setjmp(bus_error_jmp) == 0) {
 		debugger_fault_handler = handle_fault;
 		sync();
-		p = (char *) adrs;
-		q = (char *) buf;
+		p = (char *)adrs;
+		q = (char *)buf;
 		switch (size) {
-		case 2: *(short *)q = *(short *)p;	break;
-		case 4: *(int *)q = *(int *)p;		break;
+		case 2:
+			*(short *)q = *(short *)p;
+			break;
+		case 4:
+			*(int *)q = *(int *)p;
+			break;
+		case 8:
+			*(long *)q = *(long *)p;
+			break;
 		default:
-			for( ; n < size; ++n ) {
+			for( ; n < size; ++n) {
 				*q++ = *p++;
 				sync();
 			}
@@ -1411,16 +1418,23 @@
 	char *p, *q;
 
 	n = 0;
-	if( setjmp(bus_error_jmp) == 0 ){
+	if (setjmp(bus_error_jmp) == 0) {
 		debugger_fault_handler = handle_fault;
 		sync();
 		p = (char *) adrs;
 		q = (char *) buf;
 		switch (size) {
-		case 2: *(short *)p = *(short *)q;	break;
-		case 4: *(int *)p = *(int *)q;		break;
+		case 2:
+			*(short *)p = *(short *)q;
+			break;
+		case 4:
+			*(int *)p = *(int *)q;
+			break;
+		case 8:
+			*(long *)p = *(long *)q;
+			break;
 		default:
-			for( ; n < size; ++n ) {
+			for ( ; n < size; ++n) {
 				*p++ = *q++;
 				sync();
 			}
diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig
--- a/arch/s390/Kconfig	Mon Feb 24 10:24:34 2003
+++ b/arch/s390/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/s390/Makefile b/arch/s390/Makefile
--- a/arch/s390/Makefile	Mon Feb 24 10:24:21 2003
+++ b/arch/s390/Makefile	Fri Mar  7 13:28:49 2003
@@ -48,9 +48,6 @@
 				   include/config/MARKER
 
 include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
 
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \
-	       include/asm-$(ARCH)/offsets.h
+CLEAN_FILES += include/asm-$(ARCH)/offsets.h
diff -Nru a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
--- a/arch/s390/boot/Makefile	Sun Dec 15 12:06:35 2002
+++ b/arch/s390/boot/Makefile	Sun Mar  9 13:47:41 2003
@@ -2,8 +2,8 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-EXTRA_TARGETS := image listing
-EXTRA_AFLAGS  := -traditional
+targets		:= image listing
+EXTRA_AFLAGS	:= -traditional
 quiet_cmd_listing = OBJDUMP $@
       cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \
 			       --disassemble-zeroes --reloc vmlinux > $@
diff -Nru a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
--- a/arch/s390/kernel/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/s390/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y		:= head.o init_task.o
 EXTRA_AFLAGS	:= -traditional
 
 obj-y	:= entry.o bitmap.o traps.o time.o process.o \
diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S
--- a/arch/s390/vmlinux.lds.S	Mon Feb 24 10:24:21 2003
+++ b/arch/s390/vmlinux.lds.S	Mon Mar  3 11:37:38 2003
@@ -78,6 +78,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(256);
   __initramfs_start = .;
   .init.ramfs : { *(.init.initramfs) }
diff -Nru a/arch/s390x/Kconfig b/arch/s390x/Kconfig
--- a/arch/s390x/Kconfig	Mon Feb 24 10:24:34 2003
+++ b/arch/s390x/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
diff -Nru a/arch/s390x/Makefile b/arch/s390x/Makefile
--- a/arch/s390x/Makefile	Mon Feb 24 10:24:21 2003
+++ b/arch/s390x/Makefile	Fri Mar  7 13:28:49 2003
@@ -48,9 +48,6 @@
 				   include/config/MARKER
 
 include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
 
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \
-	       include/asm-$(ARCH)/offsets.h
+CLEAN_FILES += include/asm-$(ARCH)/offsets.h
diff -Nru a/arch/s390x/boot/Makefile b/arch/s390x/boot/Makefile
--- a/arch/s390x/boot/Makefile	Sun Dec 15 12:06:35 2002
+++ b/arch/s390x/boot/Makefile	Sun Mar  9 13:47:41 2003
@@ -2,8 +2,8 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-EXTRA_TARGETS := image listing
-EXTRA_AFLAGS  := -traditional
+targets		:= image listing
+EXTRA_AFLAGS	:= -traditional
 
 quiet_cmd_listing = OBJDUMP $@
       cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \
diff -Nru a/arch/s390x/kernel/Makefile b/arch/s390x/kernel/Makefile
--- a/arch/s390x/kernel/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/s390x/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y		:= head.o init_task.o
 EXTRA_AFLAGS	:= -traditional
 
 obj-y		:= entry.o bitmap.o traps.o time.o process.o \
diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
--- a/arch/s390x/kernel/entry.S	Mon Feb 24 10:25:00 2003
+++ b/arch/s390x/kernel/entry.S	Sun Mar  9 01:34:44 2003
@@ -452,7 +452,7 @@
         .long  SYSCALL(sys_umount,sys32_umount_wrapper)
         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old lock syscall */
         .long  SYSCALL(sys_ioctl,sys32_ioctl_wrapper)
-        .long  SYSCALL(sys_fcntl,sys32_fcntl_wrapper)   /* 55 */
+        .long  SYSCALL(sys_fcntl,compat_sys_fcntl_wrapper)   /* 55 */
         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* intel mpx syscall */
         .long  SYSCALL(sys_setpgid,sys32_setpgid_wrapper)
         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old ulimit syscall */
@@ -499,7 +499,7 @@
         .long  SYSCALL(sys_statfs,compat_sys_statfs_wrapper)
         .long  SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper)   /* 100 */
         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
-        .long  SYSCALL(sys_socketcall,sys32_socketcall_wrapper)
+        .long  SYSCALL(sys_socketcall,compat_sys_socketcall_wrapper)
         .long  SYSCALL(sys_syslog,sys32_syslog_wrapper)
         .long  SYSCALL(sys_setitimer,compat_sys_setitimer_wrapper)
         .long  SYSCALL(sys_getitimer,compat_sys_getitimer_wrapper)   /* 105 */
@@ -618,7 +618,7 @@
         .long  SYSCALL(sys_mincore,sys32_mincore_wrapper)
         .long  SYSCALL(sys_madvise,sys32_madvise_wrapper)
 	.long  SYSCALL(sys_getdents64,sys32_getdents64_wrapper)/* 220 */
-	.long  SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
+	.long  SYSCALL(sys_ni_syscall,compat_sys_fcntl64_wrapper)
 	.long  SYSCALL(sys_readahead,sys32_readahead)
 	.long  SYSCALL(sys_ni_syscall,sys32_sendfile64)
 	.long  SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	Mon Feb 24 10:25:00 2003
+++ b/arch/s390x/kernel/linux32.c	Sun Mar  9 01:34:44 2003
@@ -834,57 +834,6 @@
 	return err;
 }
 
-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
-asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case F_GETLK:
-		{
-			struct flock f;
-			mm_segment_t old_fs;
-			long ret;
-			
-			if(get_compat_flock(&f, (struct compat_flock *)A(arg)))
-				return -EFAULT;
-			old_fs = get_fs(); set_fs (KERNEL_DS);
-			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
-			set_fs (old_fs);
-			if (ret) return ret;
-			if (f.l_start >= 0x7fffffffUL ||
-			    f.l_start + f.l_len >= 0x7fffffffUL)
-				return -EOVERFLOW;
-			if(put_compat_flock(&f, (struct compat_flock *)A(arg)))
-				return -EFAULT;
-			return 0;
-		}
-	case F_SETLK:
-	case F_SETLKW:
-		{
-			struct flock f;
-			mm_segment_t old_fs;
-			long ret;
-			
-			if(get_compat_flock(&f, (struct compat_flock *)A(arg)))
-				return -EFAULT;
-			old_fs = get_fs(); set_fs (KERNEL_DS);
-			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
-			set_fs (old_fs);
-			if (ret) return ret;
-			return 0;
-		}
-	default:
-		return sys_fcntl(fd, cmd, (unsigned long)arg);
-	}
-}
-
-asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
-		return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
-	return sys32_fcntl(fd, cmd, arg);
-}
-
 extern asmlinkage long sys_truncate(const char * path, unsigned long length);
 extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
 
@@ -904,13 +853,11 @@
 		return sys_ftruncate(fd, (high << 32) | low);
 }
 
-struct iovec32 { u32 iov_base; compat_size_t iov_len; };
-
 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
-			      const struct iovec32 *vector, u32 count)
+			      const struct compat_iovec *vector, u32 count)
 {
 	unsigned long tot_len;
 	struct iovec iovstack[UIO_FASTIOV];
@@ -925,7 +872,7 @@
 	 */
 	if (!count)
 		return 0;
-	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		return -EFAULT;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
@@ -996,7 +943,7 @@
 	return retval;
 }
 
-asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	long ret = -EBADF;
@@ -1014,7 +961,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret = -EBADF;
@@ -1867,740 +1814,6 @@
 	return ret;
 }
 
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-struct msghdr32 {
-        u32               msg_name;
-        int               msg_namelen;
-        u32               msg_iov;
-        compat_size_t msg_iovlen;
-        u32               msg_control;
-        compat_size_t msg_controllen;
-        unsigned          msg_flags;
-};
-
-struct cmsghdr32 {
-        compat_size_t cmsg_len;
-        int               cmsg_level;
-        int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-					     struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		switch (kcmsg32->cmsg_type) {
-			/*
-			 * The timestamp type's data needs to be converted
-			 * from 64-bit time values to 32-bit time values
-			*/
-		case SO_TIMESTAMP: {
-			compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32);
-			__kernel_time_t*   ptr_time   = CMSG_DATA(ucmsg);
-			get_user(*ptr_time32, ptr_time);
-			get_user(*(ptr_time32+1), ptr_time+1);
-			kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) -
-						sizeof(compat_time_t));
-		}
-		default:;
-		}
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-/*
- *	BSD sendmsg interface
- */
-
-int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */
-	unsigned char *ctl_buf = ctl;
-	struct msghdr msg_sys;
-	int err, ctl_len, iov_size, total_len;
-	
-	err = -EFAULT;
-	if (msghdr_from_user32_to_kern(&msg_sys, msg))
-		goto out; 
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock) 
-		goto out;
-
-	/* do not move before msg_sys is valid */
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/* This will also move the address data into kernel space */
-	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
-	if (err < 0) 
-		goto out_freeiov;
-	total_len = err;
-
-	err = -ENOBUFS;
-
-	if (msg_sys.msg_controllen > INT_MAX)
-		goto out_freeiov;
-	ctl_len = msg_sys.msg_controllen; 
-	if (ctl_len) 
-	{
-		if (ctl_len > sizeof(ctl))
-		{
-			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
-			if (ctl_buf == NULL) 
-				goto out_freeiov;
-		}
-		else if (ctl_len < sizeof(struct cmsghdr))
-		{
-			/* to get same error message as on 31 bit native */
-			err = EOPNOTSUPP;
-			goto out_freeiov;
-		}
-		err = -EFAULT;
-		if (cmsghdr_from_user32_to_kern(&msg_sys, ctl_buf, ctl_len))
-			goto out_freectl;
-//		msg_sys.msg_control = ctl_buf;
-	}
-	msg_sys.msg_flags = flags;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		msg_sys.msg_flags |= MSG_DONTWAIT;
-	err = sock_sendmsg(sock, &msg_sys, total_len);
-
-out_freectl:
-	if (ctl_buf != ctl)    
-		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:       
-	return err;
-}
-
-static __inline__ void
-scm_recv32(struct socket *sock, struct msghdr *msg,
-		struct scm_cookie *scm, int flags, unsigned long cmsg_ptr)
-{
-	if(!msg->msg_control)
-	{
-		if(sock->passcred || scm->fp)
-			msg->msg_flags |= MSG_CTRUNC;
-		scm_destroy(scm);
-		return;
-	}
-	/* If recvmsg processing itself placed some
-	 * control messages into user space, it's is
-	 * using 64-bit CMSG processing, so we need
-	 * to fix it up before we tack on more stuff.
-	 */
-	if((unsigned long) msg->msg_control != cmsg_ptr)
-		cmsg32_recvmsg_fixup(msg, cmsg_ptr);
-	/* Wheee... */
-	if(sock->passcred)
-		put_cmsg32(msg,
-			SOL_SOCKET, SCM_CREDENTIALS,
-			sizeof(scm->creds), &scm->creds);
-	if(!scm->fp)
-		return;
-
-	scm_detach_fds32(msg, scm);
-}
-
-static int  
-sock_recvmsg32(struct socket *sock, struct msghdr *msg, int size, int flags,
-               unsigned long cmsg_ptr)
-{
-	struct sock_iocb *si;
-	struct kiocb iocb;
-
-	init_sync_kiocb(&iocb, NULL);
-
-	si = kiocb_to_siocb(&iocb);
-	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->msg = msg;
-	si->size = size;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	size = sock->ops->recvmsg(&iocb, sock, msg, size, flags, si->scm);
-	if (size >= 0)
-		scm_recv32(sock, msg, si->scm, flags, cmsg_ptr);
-
-	if (-EIOCBQUEUED == size)
-		size = wait_on_sync_kiocb(&iocb);
-
-	return size;
-}
-
-/*
- *	BSD recvmsg interface
- */
-
-int
-sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
-{
-	struct socket *sock;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov=iovstack;
-	struct msghdr msg_sys;
-	unsigned long cmsg_ptr;
-	int err, iov_size, total_len, len;
-
-	/* kernel mode address */
-	char addr[MAX_SOCK_ADDR];
-
-	/* user mode address pointers */
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	
-	err=-EFAULT;
-	if (msghdr_from_user32_to_kern(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-	
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/*
-	 *	Save the user-mode address (verify_iovec will change the
-	 *	kernel msghdr to use the kernel address space)
-	 */
-	 
-	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out_freeiov;
-	total_len=err;
-
-	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-	
-	if (sock->file->f_flags & O_NONBLOCK)
-		flags |= MSG_DONTWAIT;
-	err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr);
-	if (err < 0)
-		goto out_freeiov;
-	len = err;
-
-	if (uaddr != NULL && 
-	/* in order to get same error message as on native 31 bit */
-		msg_sys.msg_namelen > 0) {
-		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
-		if (err < 0)
-			goto out_freeiov;
-	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
-	if (err)
-		goto out_freeiov;
-	err = __put_user((compat_size_t) ((unsigned long)msg_sys.msg_control - cmsg_ptr), &msg->msg_controllen);
-	if (err)
-		goto out_freeiov;
-	err = len;
-
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:
-	return err;
-}
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-	if (level == SOL_SOCKET && 
-	    (optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)) {
-		long ret;
-		struct timeval tmp;
-		mm_segment_t old_fs;
-
-		if (get_tv32(&tmp, (struct compat_timeval *)optval ))
-			return -EFAULT;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		ret = sys_setsockopt(fd, level, optname, (char *) &tmp, sizeof(struct timeval));
-		set_fs(old_fs);
-		return ret; 
-	}
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
 extern void check_pending(int signum);
 
 /*
@@ -3663,104 +2876,6 @@
 	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
 out:
 	return error;
-}
-
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
-extern asmlinkage long sys_listen(int fd, int backlog);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen);
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]);
-extern asmlinkage long sys_send(int fd, void * buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags,
-                           struct sockaddr *addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void * ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags,
-                             struct sockaddr *addr, int *addr_len);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int * optlen);
-
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18] = {AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-asmlinkage long sys32_socketcall(int call, u32 *args)
-{
-	int ret;
-	u32 a[6];
-				 
-	if (call < SYS_SOCKET || call > SYS_RECVMSG)
-		return -EINVAL;
-	if (copy_from_user(a, args, nas[call]))
-		return -EFAULT;
-	switch(call) {
-	case SYS_SOCKET:
-		ret = sys_socket(a[0], a[1], a[2]);
-		break;
-	case SYS_BIND:
-		ret = sys_bind(a[0], (struct sockaddr *) A(a[1]), a[2]);
-		break;
-	case SYS_CONNECT:
-		ret = sys_connect(a[0], (struct sockaddr *) A(a[1]), a[2]);
-		break;
-	case SYS_LISTEN:
-		ret = sys_listen(a[0], a[1]);
-		break;
-	case SYS_ACCEPT:
-		ret = sys_accept(a[0], (struct sockaddr *) A(a[1]),
-				 (int *) A(a[2]));
-		break;
-	case SYS_GETSOCKNAME:
-		ret = sys_getsockname(a[0], (struct sockaddr *) A(a[1]),
-				      (int *) A(a[2]));
-		break;
-	case SYS_GETPEERNAME:
-		ret = sys_getpeername(a[0], (struct sockaddr *) A(a[1]),
-				      (int *) A(a[2]));
-		break;
-	case SYS_SOCKETPAIR:
-		ret = sys_socketpair(a[0], a[1], a[2], (int *) A(a[3]));
-		break;
-	case SYS_SEND:
-		ret = sys_send(a[0], (void *) A(a[1]), a[2], a[3]);
-		break;
-	case SYS_SENDTO:
-		ret = sys_sendto(a[0], (void*) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), a[5]);
-		break;
-	case SYS_RECV:
-		ret = sys_recv(a[0], (void *) A(a[1]), a[2], a[3]);
-		break;
-	case SYS_RECVFROM:
-		ret = sys_recvfrom(a[0], (void *) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), (int *) A(a[5]) );
-		break;
-	case SYS_SHUTDOWN:
-		ret = sys_shutdown(a[0], a[1]);
-		break;
-	case SYS_SETSOCKOPT:
-		ret = sys32_setsockopt(a[0], a[1], a[2], (char *) A(a[3]),
-				     a[4]);
-		break;
-	case SYS_GETSOCKOPT:
-		ret = sys_getsockopt(a[0], a[1], a[2], (char *) A(a[3]), (int *) A(a[4]) );
-		break;
-	case SYS_SENDMSG:
-		ret = sys32_sendmsg(a[0], (struct msghdr32 *) A(a[1]),
-				    a[2]);
-		break;
-	case SYS_RECVMSG:
-		ret = sys32_recvmsg(a[0], (struct msghdr32 *) A(a[1]),
-				    a[2]);
-		break;
-	default:
-		ret = EINVAL;
-		break;
-	}
-	return ret;
 }
 
 extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
diff -Nru a/arch/s390x/kernel/linux32.h b/arch/s390x/kernel/linux32.h
--- a/arch/s390x/kernel/linux32.h	Tue Jan 14 21:23:14 2003
+++ b/arch/s390x/kernel/linux32.h	Sun Mar  9 01:34:45 2003
@@ -21,10 +21,6 @@
         __s32   msgtyp;
 };
 
-#define F_GETLK64       12
-#define F_SETLK64       13
-#define F_SETLKW64      14    
-
 struct old_sigaction32 {
        __u32			sa_handler;	/* Really a pointer, but need to deal with 32 bits */
        compat_old_sigset_t	sa_mask;	/* A 32 bit mask */
diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S
--- a/arch/s390x/kernel/wrapper32.S	Mon Feb 24 10:25:00 2003
+++ b/arch/s390x/kernel/wrapper32.S	Sun Mar  9 01:34:45 2003
@@ -227,12 +227,12 @@
 	llgfr	%r4,%r4			# unsigned int
 	jg	sys32_ioctl		# branch to system call
 
-	.globl  sys32_fcntl_wrapper 
-sys32_fcntl_wrapper:
+	.globl  compat_sys_fcntl_wrapper 
+compat_sys_fcntl_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int 
 	llgfr	%r4,%r4			# unsigned long
-	jg	sys32_fcntl		# branch to system call
+	jg	compat_sys_fcntl	# branch to system call
 
 	.globl  sys32_setpgid_wrapper 
 sys32_setpgid_wrapper:
@@ -452,11 +452,11 @@
 	llgtr	%r3,%r3			# struct compat_statfs *
 	jg	compat_sys_fstatfs	# branch to system call
 
-	.globl  sys32_socketcall_wrapper 
-sys32_socketcall_wrapper:
+	.globl  compat_sys_socketcall_wrapper 
+compat_sys_socketcall_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# u32 *
-	jg	sys32_socketcall	# branch to system call
+	jg	compat_sys_socketcall	# branch to system call
 
 	.globl  sys32_syslog_wrapper 
 sys32_syslog_wrapper:
@@ -1050,12 +1050,12 @@
 	llgfr	%r4,%r4			# unsigned int
 	jg	sys_getdents64		# branch to system call
 
-	.globl  sys32_fcntl64_wrapper 
-sys32_fcntl64_wrapper:
+	.globl  compat_sys_fcntl64_wrapper 
+compat_sys_fcntl64_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int 
 	llgfr	%r4,%r4			# unsigned long
-	jg	sys32_fcntl64		# branch to system call
+	jg	compat_sys_fcntl64	# branch to system call
 
 	.globl	sys32_stat64_wrapper
 sys32_stat64_wrapper:
diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S
--- a/arch/s390x/vmlinux.lds.S	Mon Feb 24 10:24:21 2003
+++ b/arch/s390x/vmlinux.lds.S	Mon Mar  3 11:44:26 2003
@@ -78,6 +78,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(256);
   __initramfs_start = .;
   .init.ramfs : { *(.init.initramfs) }
diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig
--- a/arch/sh/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/sh/Kconfig	Sat Mar  8 14:50:37 2003
@@ -18,10 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
--- a/arch/sh/kernel/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/sh/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the Linux/SuperH kernel.
 #
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y	:= head.o init_task.o
 
 obj-y	:= process.o signal.o entry.o traps.o irq.o irq_ipr.o \
 	ptrace.o setup.o time.o sys_sh.o semaphore.o \
diff -Nru a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
--- a/arch/sh/kernel/irq.c	Tue Feb 25 01:38:48 2003
+++ b/arch/sh/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -90,6 +90,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
@@ -97,9 +98,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
-		if (!action) 
-			continue;
+		if (!action)
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -108,6 +110,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
diff -Nru a/arch/sh/kernel/pci-dc.c b/arch/sh/kernel/pci-dc.c
--- a/arch/sh/kernel/pci-dc.c	Fri Nov  1 09:33:01 2002
+++ b/arch/sh/kernel/pci-dc.c	Sun Mar 16 13:55:57 2003
@@ -113,10 +113,6 @@
 }
 
 
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-}                                                                                
-
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct list_head *ln;
diff -Nru a/arch/sh/kernel/pci-sh7751.c b/arch/sh/kernel/pci-sh7751.c
--- a/arch/sh/kernel/pci-sh7751.c	Mon Feb 24 09:55:51 2003
+++ b/arch/sh/kernel/pci-sh7751.c	Sun Mar 16 13:55:57 2003
@@ -250,12 +250,6 @@
 	{ 0 }
 };
 
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *b,
-					 struct pbus_set_ranges_data *range)
-{
-	/* No fixups needed */
-}
-
 /*
  *  Called after each bus is probed, but before its children
  *  are examined.
diff -Nru a/arch/sh/kernel/pci_st40.c b/arch/sh/kernel/pci_st40.c
--- a/arch/sh/kernel/pci_st40.c	Fri Nov  1 09:33:01 2002
+++ b/arch/sh/kernel/pci_st40.c	Sun Mar 16 13:55:57 2003
@@ -380,12 +380,6 @@
 }
 
 
-void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus *bus,
-			  struct pbus_set_ranges_data *ranges)
-{
-}
-
 void __init pcibios_init(void)
 {
 	extern unsigned long memory_start, memory_end;
diff -Nru a/arch/sh/kernel/pcibios.c b/arch/sh/kernel/pcibios.c
--- a/arch/sh/kernel/pcibios.c	Mon May  6 14:23:52 2002
+++ b/arch/sh/kernel/pcibios.c	Sun Mar 16 14:16:32 2003
@@ -6,7 +6,6 @@
  * This is GPL'd.
  *
  * Provided here are generic versions of:
- *	pcibios_update_resource()
  *	pcibios_align_resource()
  *	pcibios_enable_device()
  *	pcibios_set_master()
@@ -19,40 +18,11 @@
  *	pcibios_fixup_bus()
  *	pcibios_init()
  *	pcibios_setup()
- *	pcibios_fixup_pbus_ranges()
  */
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-
-	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		new |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
-		return;
-	}
-	
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
-}
 
 /*
  * We need to avoid collisions with `mirrored' VGA ports
diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
--- a/arch/sh/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/sh/vmlinux.lds.S	Fri Feb 14 15:11:24 2003
@@ -68,6 +68,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   __machvec_start = .;
   .machvec.init : { *(.machvec.init) }
   __machvec_end = .;
diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig
--- a/arch/sparc/Kconfig	Mon Mar  3 00:33:45 2003
+++ b/arch/sparc/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/sparc/Makefile b/arch/sparc/Makefile
--- a/arch/sparc/Makefile	Tue Feb 11 03:40:52 2003
+++ b/arch/sparc/Makefile	Fri Mar  7 13:28:49 2003
@@ -68,10 +68,7 @@
 				   include/config/MARKER
 
 include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
 
-CLEAN_FILES +=	include/asm-$(ARCH)/asm_offsets.h.tmp	\
-		include/asm-$(ARCH)/asm_offsets.h	\
+CLEAN_FILES +=	include/asm-$(ARCH)/asm_offsets.h	\
 		arch/$(ARCH)/kernel/asm-offsets.s
diff -Nru a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
--- a/arch/sparc/boot/Makefile	Tue Feb 11 03:40:52 2003
+++ b/arch/sparc/boot/Makefile	Sun Mar  9 13:47:41 2003
@@ -8,7 +8,7 @@
 ELFTOAOUT	:= elftoaout
 
 host-progs	:= piggyback btfixupprep
-EXTRA_TARGETS	:= tftpboot.img btfix.o btfix.s image
+targets		:= tftpboot.img btfix.o btfix.s image
 
 quiet_cmd_elftoaout	= ELFTOAOUT $@
       cmd_elftoaout	= $(ELFTOAOUT) $(obj)/image -o $@
diff -Nru a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
--- a/arch/sparc/kernel/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/sparc/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y		:= head.o init_task.o
 
 EXTRA_AFLAGS	:= -ansi
 
diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
--- a/arch/sparc/kernel/irq.c	Sun Dec  8 14:33:46 2002
+++ b/arch/sparc/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -104,6 +104,7 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 #ifdef CONFIG_SMP
 	int j;
 #endif
@@ -114,9 +115,10 @@
 		return show_sun4d_interrupts(p, v);
 	}
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 	        action = *(i + irq_action);
 		if (!action) 
-		        continue;
+		        goto skip;
 		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -136,6 +138,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
--- a/arch/sparc/kernel/pcic.c	Wed Feb  5 05:04:38 2003
+++ b/arch/sparc/kernel/pcic.c	Sun Mar 16 14:16:33 2003
@@ -854,13 +854,6 @@
 	return str;
 }
 
-/*
- */
-void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,
-			     struct resource *res2, int index)
-{
-}
-
 void pcibios_align_resource(void *data, struct resource *res,
 			    unsigned long size, unsigned long align)
 {
diff -Nru a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
--- a/arch/sparc/kernel/sys_sunos.c	Fri Feb  7 07:59:17 2003
+++ b/arch/sparc/kernel/sys_sunos.c	Sat Mar  8 11:39:01 2003
@@ -1107,38 +1107,16 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-asmlinkage int sunos_socket(int family, int type, int protocol)
-{
-	int ret, one = 1;
-
-	ret = sys_socket(family, type, protocol);
-	if (ret < 0)
-		goto out;
-
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
-	return ret;
-}
-
 asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen)
 {
-	int ret, one = 1;
+	int ret;
 
 	while (1) {
 		ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);	
 		if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
 			break;
 	}
-	if (ret < 0)
-		goto out;
 
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
 	return ret;
 }
 
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Sun Dec  8 12:19:41 2002
+++ b/arch/sparc/kernel/systbls.S	Sat Mar  8 11:39:01 2003
@@ -110,7 +110,7 @@
 	.long sys_getitimer, sys_gethostname, sys_sethostname
 	.long sunos_getdtablesize, sys_dup2, sunos_nop
 	.long sys_fcntl, sunos_select, sunos_nop
-	.long sys_fsync, sys_setpriority, sunos_socket
+	.long sys_fsync, sys_setpriority, sys_socket
 	.long sys_connect, sunos_accept
 /*100*/	.long sys_getpriority, sunos_send, sunos_recv
 	.long sunos_nosys, sys_bind, sunos_setsockopt
diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
--- a/arch/sparc/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/sparc/vmlinux.lds.S	Fri Feb 14 15:11:32 2003
@@ -55,6 +55,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
--- a/arch/sparc64/Kconfig	Mon Mar  3 00:34:40 2003
+++ b/arch/sparc64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 source "init/Kconfig"
 
 
@@ -151,9 +147,14 @@
 	  If in doubt, say N.
 
 config CPU_FREQ_TABLE
-       tristate
+       tristate "CPU frequency table helpers"
+       depends on CPU_FREQ
        default y
+       help
+         Many CPUFreq drivers use these helpers, so only say N here if
+	 the CPUFreq driver of your choice doesn't need these helpers.
 
+	 If in doubt, say Y.
 
 config US3_FREQ
 	tristate "UltraSPARC-III CPU Frequency driver"
diff -Nru a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile
--- a/arch/sparc64/boot/Makefile	Mon Dec 30 23:14:33 2002
+++ b/arch/sparc64/boot/Makefile	Sun Mar  9 13:47:41 2003
@@ -7,8 +7,8 @@
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
 
-host-progs    := piggyback
-EXTRA_TARGETS := tftpboot.img vmlinux.aout
+host-progs	:= piggyback
+targets		:= tftpboot.img vmlinux.aout
 
 quiet_cmd_elftoaout = ELT2AOUT $@
       cmd_elftoaout = $(ELFTOAOUT) vmlinux -o $@
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	Sun Mar  2 23:23:54 2003
+++ b/arch/sparc64/defconfig	Fri Mar  7 19:26:39 2003
@@ -39,9 +39,11 @@
 # CONFIG_PREEMPT is not set
 CONFIG_NR_CPUS=4
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_PROC_INTF=y
 CONFIG_CPU_FREQ_TABLE=y
 CONFIG_US3_FREQ=m
+CONFIG_CPU_FREQ_PROC_INTF=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+# CONFIG_CPU_FREQ_24_API is not set
 CONFIG_SPARC64=y
 CONFIG_HOTPLUG=y
 CONFIG_HAVE_DEC_LOCK=y
@@ -354,6 +356,8 @@
 CONFIG_XFRM_USER=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -872,6 +876,7 @@
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
 CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_XPAD is not set
 
@@ -928,6 +933,7 @@
 # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
 CONFIG_USB_SERIAL_KEYSPAN_PDA=m
 CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
@@ -938,6 +944,7 @@
 # CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
 CONFIG_USB_SERIAL_KLSI=m
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 CONFIG_USB_SERIAL_MCT_U232=m
diff -Nru a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
--- a/arch/sparc64/kernel/Makefile	Mon Mar  3 00:49:24 2003
+++ b/arch/sparc64/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -5,7 +5,7 @@
 EXTRA_AFLAGS := -ansi
 EXTRA_CFLAGS := -Werror
 
-EXTRA_TARGETS	:= head.o init_task.o
+extra-y		:= head.o init_task.o
 
 obj-y		:= process.o setup.o cpu.o idprom.o \
 		   traps.o devices.o auxio.o \
diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
--- a/arch/sparc64/kernel/ioctl32.c	Tue Feb 25 10:47:17 2003
+++ b/arch/sparc64/kernel/ioctl32.c	Fri Mar  7 23:00:48 2003
@@ -38,6 +38,7 @@
 #include <linux/cdrom.h>
 #include <linux/loop.h>
 #include <linux/auto_fs.h>
+#include <linux/auto_fs4.h>
 #include <linux/devfs_fs.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
@@ -4850,6 +4851,7 @@
 COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
 COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
 COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
 /* DEVFS */
 COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
diff -Nru a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
--- a/arch/sparc64/kernel/pci.c	Mon Nov 18 11:56:35 2002
+++ b/arch/sparc64/kernel/pci.c	Sun Mar 16 14:16:33 2003
@@ -470,17 +470,7 @@
 	return err;
 }
 
-void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,
-			     struct resource *res2, int index)
-{
-}
-
 void pcibios_update_irq(struct pci_dev *pdev, int irq)
-{
-}
-
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
-					 struct pbus_set_ranges_data *pranges)
 {
 }
 
diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
--- a/arch/sparc64/kernel/pci_common.c	Tue Feb 25 10:47:17 2003
+++ b/arch/sparc64/kernel/pci_common.c	Fri Mar  7 19:08:16 2003
@@ -78,20 +78,6 @@
 	return 0;
 }
 
-/* Remove a PCI device from the device trees, then
- * free it up.  Note that this must run before
- * the device's resources are registered because we
- * do not handle unregistering them here.
- */
-static void pci_device_delete(struct pci_dev *pdev)
-{
-	list_del(&pdev->global_list);
-	list_del(&pdev->bus_list);
-
-	/* Ok, all references are gone, free it up. */
-	kfree(pdev);
-}
-
 /* Older versions of OBP on PCI systems encode 64-bit MEM
  * space assignments incorrectly, this fixes them up.  We also
  * take the opportunity here to hide other kinds of bogus
@@ -164,7 +150,7 @@
 		 * second EBUS/HappyMeal pair if the external
 		 * connector for it is not present.
 		 */
-		pci_device_delete(pdev);
+		pci_remove_bus_device(pdev);
 		return;
 	}
 
diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
--- a/arch/sparc64/kernel/smp.c	Sat Feb 22 00:03:07 2003
+++ b/arch/sparc64/kernel/smp.c	Sat Mar  8 07:52:56 2003
@@ -1137,16 +1137,16 @@
 	do {
 		sparc64_do_profile(regs);
 		if (!--prof_counter(cpu)) {
-			if (cpu == boot_cpu_id) {
-				irq_enter();
+			irq_enter();
 
+			if (cpu == boot_cpu_id) {
 				kstat_cpu(cpu).irqs[0]++;
 				timer_tick_interrupt(regs);
-
-				irq_exit();
 			}
 
 			update_process_times(user);
+
+			irq_exit();
 
 			prof_counter(cpu) = prof_multiplier(cpu);
 		}
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	Thu Feb 27 05:46:56 2003
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	Tue Mar 11 16:12:15 2003
@@ -20,6 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/fs_struct.h>
 #include <linux/mm.h>
+#include <linux/socket.h>
 
 #include <asm/oplib.h>
 #include <asm/delay.h>
@@ -136,6 +137,11 @@
 EXPORT_SYMBOL_NOVERS(mcount);
 #endif
 
+/* Uniprocessor clock frequency */
+#ifndef CONFIG_SMP
+EXPORT_SYMBOL(up_clock_tick);
+#endif
+
 /* Per-CPU information table */
 EXPORT_SYMBOL(cpu_data);
 
@@ -243,6 +249,7 @@
 
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(_sigpause_common);
+EXPORT_SYMBOL(verify_compat_iovec);
 
 /* Should really be in linux/kernel/ksyms.c */
 EXPORT_SYMBOL(dump_thread);
diff -Nru a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
--- a/arch/sparc64/kernel/sys32.S	Tue Feb 18 10:25:13 2003
+++ b/arch/sparc64/kernel/sys32.S	Thu Mar  6 11:06:44 2003
@@ -202,38 +202,38 @@
 	nop
 	nop
 	nop
-do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */
+do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_setsockopt), %g1
+	sethi		%hi(compat_sys_setsockopt), %g1
 	ldswa		[%o1 + 0x8] %asi, %o2
 	lduwa		[%o1 + 0xc] %asi, %o3
 	ldswa		[%o1 + 0x10] %asi, %o4
-	jmpl		%g1 + %lo(sys32_setsockopt), %g0
+	jmpl		%g1 + %lo(compat_sys_setsockopt), %g0
 	 ldswa		[%o1 + 0x4] %asi, %o1
 	nop
-do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */
+do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_getsockopt), %g1
+	sethi		%hi(compat_sys_getsockopt), %g1
 	ldswa		[%o1 + 0x8] %asi, %o2
 	lduwa		[%o1 + 0xc] %asi, %o3
 	lduwa		[%o1 + 0x10] %asi, %o4
-	jmpl		%g1 + %lo(sys32_getsockopt), %g0
+	jmpl		%g1 + %lo(compat_sys_getsockopt), %g0
 	 ldswa		[%o1 + 0x4] %asi, %o1
 	nop
-do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */
+do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_sendmsg), %g1
+	sethi		%hi(compat_sys_sendmsg), %g1
 	lduwa		[%o1 + 0x8] %asi, %o2
-	jmpl		%g1 + %lo(sys32_sendmsg), %g0
+	jmpl		%g1 + %lo(compat_sys_sendmsg), %g0
 	 lduwa		[%o1 + 0x4] %asi, %o1
 	nop
 	nop
 	nop
-do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */
+do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_recvmsg), %g1
+	sethi		%hi(compat_sys_recvmsg), %g1
 	lduwa		[%o1 + 0x8] %asi, %o2
-	jmpl		%g1 + %lo(sys32_recvmsg), %g0
+	jmpl		%g1 + %lo(compat_sys_recvmsg), %g0
 	 lduwa		[%o1 + 0x4] %asi, %o1
 	nop
 	nop
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/sparc64/kernel/sys_sparc32.c	Tue Mar 11 15:41:39 2003
@@ -63,8 +63,6 @@
 #include <asm/semaphore.h>
 #include <asm/mmu_context.h>
 
-#include <net/scm.h>
-
 /* Use this to get at 32-bit user passed pointers. */
 /* Things to consider: the low-level assembly stub does
    srl x, 0, x for first four arguments, so if you have
@@ -806,41 +804,6 @@
 	return err;
 }
 
-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
-asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case F_GETLK:
-	case F_SETLK:
-	case F_SETLKW:
-		{
-			struct flock f;
-			mm_segment_t old_fs;
-			long ret;
-			
-			if (get_compat_flock(&f, (struct compat_flock *)arg))
-				return -EFAULT;
-			old_fs = get_fs(); set_fs (KERNEL_DS);
-			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
-			set_fs (old_fs);
-			if (ret) return ret;
-			if (put_compat_flock(&f, (struct compat_flock *)arg))
-				return -EFAULT;
-			return 0;
-		}
-	default:
-		return sys_fcntl(fd, cmd, (unsigned long)arg);
-	}
-}
-
-asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
-		return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
-	return sys32_fcntl(fd, cmd, arg);
-}
-
 extern asmlinkage long sys_truncate(const char * path, unsigned long length);
 extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
 
@@ -860,13 +823,11 @@
 		return sys_ftruncate(fd, (high << 32) | low);
 }
 
-struct iovec32 { u32 iov_base; compat_size_t iov_len; };
-
 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
-			      const struct iovec32 *vector, u32 count)
+			      const struct compat_iovec *vector, u32 count)
 {
 	compat_ssize_t tot_len;
 	struct iovec iovstack[UIO_FASTIOV];
@@ -900,7 +861,7 @@
 			goto out;
 	}
 	retval = -EFAULT;
-	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		goto out;
 
 	/*
@@ -992,7 +953,7 @@
 	return retval;
 }
 
-asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret;
@@ -1015,7 +976,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret;
@@ -1905,773 +1866,6 @@
 	set_fs (old_fs);
 	if (put_rusage (ru, &r)) return -EFAULT;
 	return ret;
-}
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-struct msghdr32 {
-        u32               msg_name;
-        int               msg_namelen;
-        u32               msg_iov;
-        compat_size_t msg_iovlen;
-        u32               msg_control;
-        compat_size_t msg_controllen;
-        unsigned          msg_flags;
-};
-
-struct cmsghdr32 {
-        compat_size_t cmsg_len;
-        int               cmsg_level;
-        int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-				      struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		if (kcmsg32->cmsg_level == SOL_SOCKET &&
-		    kcmsg32->cmsg_type == SO_TIMESTAMP) {
-			struct timeval tv;
-			struct compat_timeval *tv32;
-
-			if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
-				kfree(workbuf);
-				goto fail;
-			}
-			copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
-			tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32);
-			tv32->tv_sec = tv.tv_sec;
-			tv32->tv_usec = tv.tv_usec;
-			clen32 = sizeof(*tv32) +
-				CMSG32_ALIGN(sizeof(struct cmsghdr32));
-		} else {
-			copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-				       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-			clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-				  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		}
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-	if(uaddr != NULL && err >= 0)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	return len;
-}
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_netfilter_replace(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct ipt_replace32 {
-		char name[IPT_TABLE_MAXNAMELEN];
-		__u32 valid_hooks;
-		__u32 num_entries;
-		__u32 size;
-		__u32 hook_entry[NF_IP_NUMHOOKS];
-		__u32 underflow[NF_IP_NUMHOOKS];
-		__u32 num_counters;
-		__u32 counters;
-		struct ipt_entry entries[0];
-	} *repl32 = (struct ipt_replace32 *)optval;
-	struct ipt_replace *krepl;
-	struct ipt_counters *counters32;
-	__u32 origsize;
-	unsigned int kreplsize, kcountersize;
-	mm_segment_t old_fs;
-	int ret;
-
-	if (optlen < sizeof(repl32))
-		return -EINVAL;
-
-	if (copy_from_user(&origsize,
-			&repl32->size,
-			sizeof(origsize)))
-		return -EFAULT;
-
-	kreplsize = sizeof(*krepl) + origsize;
-	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
-
-	/* Hack: Causes ipchains to give correct error msg --RR */
-	if (optlen != kreplsize)
-		return -ENOPROTOOPT;
-
-	krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
-	if (krepl == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(krepl, optval, kreplsize)) {
-		kfree(krepl);
-		return -EFAULT;
-	}
-
-	counters32 = (struct ipt_counters *)AA(
-		((struct ipt_replace32 *)krepl)->counters);
-
-	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
-	krepl->counters = (struct ipt_counters *)kmalloc(
-					kcountersize, GFP_KERNEL);
-	if (krepl->counters == NULL) {
-		kfree(krepl);
-		return -ENOMEM;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)krepl, kreplsize);
-	set_fs(old_fs);
-
-	if (ret == 0 &&
-		copy_to_user(counters32, krepl->counters, kcountersize))
-			ret = -EFAULT;
-
-	kfree(krepl->counters);
-	kfree(krepl);
-
-	return ret;
-}
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int err;
-
-	if (optlen < sizeof(*up))
-		return -EINVAL;
-	if (get_user(ktime.tv_sec, &up->tv_sec) ||
-	    __get_user(ktime.tv_usec, &up->tv_usec))
-		return -EFAULT;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
-	set_fs(old_fs);
-
-	return err;
-}
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == IPT_SO_SET_REPLACE)
-		return do_netfilter_replace(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_set_sock_timeout(fd, level, optname, optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				      char *optval, int *optlen);
-
-static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int len, err;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-	if (len < sizeof(*up))
-		return -EINVAL;
-	len = sizeof(ktime);
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
-	set_fs(old_fs);
-
-	if (!err) {
-		if (put_user(sizeof(*up), optlen) ||
-		    put_user(ktime.tv_sec, &up->tv_sec) ||
-		    __put_user(ktime.tv_usec, &up->tv_usec))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-asmlinkage int sys32_getsockopt(int fd, int level, int optname,
-				char *optval, int *optlen)
-{
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_get_sock_timeout(fd, level, optname, optval, optlen);
-	return sys_getsockopt(fd, level, optname, optval, optlen);
 }
 
 extern void check_pending(int signum);
diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
--- a/arch/sparc64/kernel/sys_sunos32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/sparc64/kernel/sys_sunos32.c	Sat Mar  8 11:39:01 2003
@@ -54,6 +54,7 @@
 #include <linux/personality.h>
 
 /* For SOCKET_I */
+#include <linux/socket.h>
 #include <net/sock.h>
 
 /* Use this to get at 32-bit user passed pointers. */
@@ -1253,26 +1254,9 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-asmlinkage int sunos_socket(int family, int type, int protocol)
-{
-	int ret, one = 1;
-
-	ret = sys_socket(family, type, protocol);
-	if (ret < 0)
-		goto out;
-
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
-	return ret;
-}
-
 asmlinkage int sunos_accept(int fd, u32 sa, u32 addrlen)
 {
-	int ret, one = 1;
+	int ret;
 
 	while (1) {
 		ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa),
@@ -1280,12 +1264,6 @@
 		if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
 			break;
 	}
-	if (ret < 0)
-		goto out;
-
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
 	return ret;
 }
 
@@ -1324,8 +1302,6 @@
 
 extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
 				     char *optval, int optlen);
-extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
-				     u32 optval, u32 optlen);
 
 asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval,
 				int optlen)
@@ -1353,6 +1329,6 @@
 		if (tr_opt >=2 && tr_opt <= 6)
 			tr_opt += 30;
 	}
-	ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen);
+	ret = compat_sys_getsockopt(fd, level, tr_opt, (void*)(unsigned long)optval, (void*)(unsigned long)optlen);
 	return ret;
 }
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Tue Feb 18 23:56:15 2003
+++ b/arch/sparc64/kernel/systbls.S	Tue Mar 11 15:41:39 2003
@@ -37,7 +37,7 @@
 	.word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16
 /*80*/	.word sys32_setgroups16, sys_getpgrp, sys_setgroups, compat_sys_setitimer, sys32_ftruncate64
 	.word sys_swapon, compat_sys_getitimer, sys_setuid, sys_sethostname, sys_setgid
-/*90*/	.word sys_dup2, sys_setfsuid, sys32_fcntl, sys32_select, sys_setfsgid
+/*90*/	.word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
 	.word sys_fsync, sys_setpriority32, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
 	.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
@@ -50,7 +50,7 @@
 /*140*/	.word sys32_sendfile64, sys_nis_syscall, compat_sys_futex, sys_gettid, sys32_getrlimit
 	.word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
 /*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
-	.word sys32_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
+	.word compat_sys_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
 /*160*/	.word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 	.word sys_quotactl, sys_set_tid_address, sys32_mount, sys_ustat, sys_setxattr
 /*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
@@ -172,14 +172,14 @@
 	.word compat_sys_setitimer, sunos_nosys, sys_swapon
 	.word compat_sys_getitimer, sys_gethostname, sys_sethostname
 	.word sunos_getdtablesize, sys_dup2, sunos_nop
-	.word sys32_fcntl, sunos_select, sunos_nop
-	.word sys_fsync, sys_setpriority32, sunos_socket
+	.word compat_sys_fcntl, sunos_select, sunos_nop
+	.word sys_fsync, sys_setpriority32, sys_socket
 	.word sys_connect, sunos_accept
 /*100*/	.word sys_getpriority, sunos_send, sunos_recv
 	.word sunos_nosys, sys_bind, sunos_setsockopt
 	.word sys_listen, sunos_nosys, sunos_sigaction
 	.word sunos_sigblock, sunos_sigsetmask, sys_sigpause
-	.word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
+	.word sys32_sigstack, compat_sys_recvmsg, compat_sys_sendmsg
 	.word sunos_nosys, sys32_gettimeofday, sys32_getrusage
 	.word sunos_getsockopt, sunos_nosys, sunos_readv
 	.word sunos_writev, sys32_settimeofday, sys32_fchown16
diff -Nru a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c
--- a/arch/sparc64/kernel/us3_cpufreq.c	Mon Mar  3 00:34:40 2003
+++ b/arch/sparc64/kernel/us3_cpufreq.c	Tue Mar 11 16:10:22 2003
@@ -79,9 +79,9 @@
 				void *data)
 {
 	struct cpufreq_freqs *freq = data;
+#ifdef CONFIG_SMP
 	unsigned int cpu = freq->cpu;
 
-#ifdef CONFIG_SMP
 	if (!us3_freq_table[cpu].ref_freq) {
 		us3_freq_table[cpu].ref_freq = freq->old;
 		us3_freq_table[cpu].udelay_val_ref = cpu_data[cpu].udelay_val;
@@ -276,6 +276,7 @@
 		driver->target = us3freq_target;
 		driver->init = us3freq_cpu_init;
 		driver->exit = us3freq_cpu_exit;
+		driver->owner = THIS_MODULE,
 		strcpy(driver->name, "UltraSPARC-III");
 
 		cpufreq_us3_driver = driver;
diff -Nru a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
--- a/arch/sparc64/solaris/socket.c	Wed Dec  4 11:05:21 2002
+++ b/arch/sparc64/solaris/socket.c	Thu Mar  6 12:08:45 2003
@@ -267,35 +267,6 @@
 	unsigned char	cmsg_data[0];
 };
 
-struct iovec32 {
-	u32		iov_base;
-	u32 iov_len;
-};
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
 static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
 					     struct sol_nmsghdr *umsg)
 {
@@ -321,42 +292,6 @@
 	return err;
 }
 
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
 asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned user_flags)
 {
 	struct socket *sock;
@@ -371,7 +306,7 @@
 		return -EFAULT;
 	if(kern_msg.msg_iovlen > UIO_MAXIOV)
 		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+	err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ);
 	if (err < 0)
 		goto out;
 	total_len = err;
@@ -439,7 +374,7 @@
 
 	uaddr = kern_msg.msg_name;
 	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+	err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE);
 	if (err < 0)
 		goto out;
 	total_len = err;
diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
--- a/arch/sparc64/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/sparc64/vmlinux.lds.S	Fri Feb 14 15:11:44 2003
@@ -61,6 +61,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(8192); 
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig
--- a/arch/um/Kconfig	Wed Feb  5 20:16:01 2003
+++ b/arch/um/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 mainmenu "Linux/Usermode Kernel Configuration"
 
 config ISA
diff -Nru a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
--- a/arch/um/drivers/stdio_console.c	Sat Dec 28 12:28:00 2002
+++ b/arch/um/drivers/stdio_console.c	Fri Feb 14 15:11:51 2003
@@ -214,12 +214,13 @@
 					       console_device, console_setup,
 					       CON_PRINTBUFFER);
 
-void stdio_console_init(void)
+static void __init stdio_console_init(void)
 {
 	INIT_LIST_HEAD(&vts[0].chan_list);
 	list_add(&init_console_chan.list, &vts[0].chan_list);
 	register_console(&stdiocons);
 }
+console_initcall(stdio_console_init);
 
 static int console_chan_setup(char *str)
 {
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	Wed Feb  5 20:16:02 2003
+++ b/arch/um/drivers/ubd_kern.c	Sat Mar  8 14:50:21 2003
@@ -673,7 +673,7 @@
 static int ubd_mc_init(void)
 {
 	mconsole_register_dev(&ubd_mc);
-	return(0);
+	return 0;
 }
 
 __initcall(ubd_mc_init);
@@ -682,29 +682,24 @@
 {
         int i;
 
-	ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL);
-	if(register_blkdev(MAJOR_NR, "ubd", &ubd_blops)){
-		printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
+	ubd_dir_handle = devfs_mk_dir(NULL, "ubd", NULL);
+	if (register_blkdev(MAJOR_NR, "ubd"))
 		return -1;
-	}
 
 	blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock);
 	elevator_init(&ubd_queue, &elevator_noop);
 
-	if(fake_major != 0){
+	if (fake_major != 0) {
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
 		ubd_fake_dir_handle = devfs_mk_dir(NULL, name, NULL);
-		if(register_blkdev(fake_major, "ubd", &ubd_blops)){
-			printk(KERN_ERR "ubd: unable to get major %d\n",
-			       fake_major);
+		if (register_blkdev(fake_major, "ubd"))
 			return -1;
-		}
 	}
-	for(i = 0; i < MAX_DEV; i++) 
+	for (i = 0; i < MAX_DEV; i++) 
 		ubd_add(i);
-	return(0);
+	return 0;
 }
 
 late_initcall(ubd_init);
diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
--- a/arch/um/kernel/mem.c	Wed Feb  5 20:16:02 2003
+++ b/arch/um/kernel/mem.c	Thu Mar  6 08:19:07 2003
@@ -154,8 +154,8 @@
 	unsigned long vaddr;
 
 	vaddr = start;
-	i = __pgd_offset(vaddr);
-	j = __pmd_offset(vaddr);
+	i = pgd_index(vaddr);
+	j = pmd_index(vaddr);
 	pgd = pgd_base + i;
 
 	for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
@@ -257,7 +257,7 @@
 	vaddr = PKMAP_BASE;
 	fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
 
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	pmd = pmd_offset(pgd, vaddr);
 	pte = pte_offset_kernel(pmd, vaddr);
 	pkmap_page_table = pte;
diff -Nru a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
--- a/arch/um/kernel/tt/Makefile	Wed Feb  5 20:16:02 2003
+++ b/arch/um/kernel/tt/Makefile	Sun Mar  9 14:15:54 2003
@@ -3,7 +3,7 @@
 # Licensed under the GPL
 #
 
-EXTRA_TARGETS := unmap_fin.o
+extra-y := unmap_fin.o
 
 obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
 	syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
diff -Nru a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile
--- a/arch/um/sys-i386/util/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/um/sys-i386/util/Makefile	Mon Mar 10 13:03:32 2003
@@ -1,6 +1,7 @@
-EXTRA_TARGETS	:= mk_sc mk_thread mk_thread_kern.o
 
 host-progs	:= mk_sc
+always		:= $(host-progs) mk_thread
+targets		:= mk_thread_kern.o mk_thread_user.o
 
 mk_sc-objs	:= mk_sc.o
 
@@ -11,6 +12,6 @@
 	$(CC) $(USER_CFLAGS) -c -o $@ $<
 
 clean :
-	$(RM) -f $(EXTRA_TARGETS)
+	$(RM) -f $(build-targets)
 
 archmrproper : clean
diff -Nru a/arch/um/util/Makefile b/arch/um/util/Makefile
--- a/arch/um/util/Makefile	Mon Dec 16 23:54:52 2002
+++ b/arch/um/util/Makefile	Mon Mar 10 13:03:33 2003
@@ -1,4 +1,6 @@
-EXTRA_TARGETS := mk_task mk_constants
+always		:= mk_task mk_constants
+targets		:= mk_task_user.o mk_task_kern.o \
+		   mk_constants_user.o mk_constants_kern.o
 
 $(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o
 	$(CC) -o $@ $^
@@ -16,6 +18,6 @@
 	$(CC) $(CFLAGS) -c $< -o $@
 
 clean:
-	$(RM) $(EXTRA_TARGETS)
+	$(RM) $(build-targets)
 
 archmrproper:
diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig
--- a/arch/v850/Kconfig	Tue Feb 18 18:40:02 2003
+++ b/arch/v850/Kconfig	Sat Mar  8 14:50:37 2003
@@ -10,9 +10,6 @@
 config MMU
        	bool
 	default n
-config SWAP
-	bool
-	default n
 config UID16
 	bool
 	default n
diff -Nru a/arch/v850/Makefile b/arch/v850/Makefile
--- a/arch/v850/Makefile	Sun Jan 26 11:13:05 2003
+++ b/arch/v850/Makefile	Fri Mar  7 13:28:49 2003
@@ -55,14 +55,10 @@
 # Generate constants from C code for use by asm files
 arch/$(ARCH)/kernel/asm-consts.s: include/asm include/linux/version.h \
 				   include/config/MARKER
-include/asm-$(ARCH)/asm-consts.h.tmp: arch/$(ARCH)/kernel/asm-consts.s
-	@$(generate-asm-offsets.h) < $< > $@
-include/asm-$(ARCH)/asm-consts.h: include/asm-$(ARCH)/asm-consts.h.tmp
-	@echo -n '  Generating $@'
-	@$(update-if-changed)
 
+include/asm-$(ARCH)/asm-consts.h: arch/$(ARCH)/kernel/asm-consts.s
+	$(call filechk,gen-asm-offsets)
 
-CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h.tmp \
-	       include/asm-$(ARCH)/asm-consts.h \
+CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h \
 	       arch/$(ARCH)/kernel/asm-consts.s \
 	       root_fs_image.o
diff -Nru a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
--- a/arch/v850/kernel/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/v850/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -9,7 +9,7 @@
 # for more details.
 #
 
-EXTRA_TARGETS := head.o init_task.o
+extra-y := head.o init_task.o
 
 obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
 	 signal.o irq.o mach.o ptrace.o bug.o
diff -Nru a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
--- a/arch/v850/kernel/irq.c	Tue Feb 25 01:38:52 2003
+++ b/arch/v850/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -78,6 +78,7 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
@@ -87,10 +88,10 @@
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		int j, count, num;
 		const char *type_name = irq_desc[i].handler->typename;
-
+		spin_lock_irqsave(&irq_desc[j].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 
 		count = 0;
 		num = -1;
@@ -108,11 +109,13 @@
 			seq_printf(p, " %*s%d", 14 - prec, type_name, num);
 		} else
 			seq_printf(p, " %14s", type_name);
+		
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[j].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -Nru a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
--- a/arch/v850/kernel/rte_mb_a_pci.c	Fri Feb  7 00:20:33 2003
+++ b/arch/v850/kernel/rte_mb_a_pci.c	Sun Mar 16 14:16:33 2003
@@ -287,44 +287,20 @@
 	pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
 }
 
-void __nomods_init
-pcibios_update_resource (struct pci_dev *dev, struct resource *root,
-			 struct resource *r, int resource)
+void __devinit
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			struct resource *res)
 {
-	u32 new, check;
-	int reg;
+	unsigned long offset = 0;
 
-	if (r->flags & IORESOURCE_IO)
-		new = (((r->start - MB_A_PCI_IO_ADDR)
-			& PCI_BASE_ADDRESS_IO_MASK)
-		       | PCI_BASE_ADDRESS_SPACE_IO);
-	else if (r->flags & IORESOURCE_MEM)
-		new = (((r->start - MB_A_PCI_MEM_ADDR)
-			& PCI_BASE_ADDRESS_MEM_MASK)
-		       | PCI_BASE_ADDRESS_MEM_TYPE_32
-		       | ((r->flags & IORESOURCE_PREFETCH)
-			  ? PCI_BASE_ADDRESS_MEM_PREFETCH
-			  : 0)
-		       | PCI_BASE_ADDRESS_SPACE_MEMORY);
-	else
-		panic ("pcibios_update_resource: unknown resource type");
-
-	if (resource < 6)
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
-	else if (resource == PCI_ROM_RESOURCE) {
-		r->flags |= PCI_ROM_ADDRESS_ENABLE;
-		new |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else
-		return;
-	
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk (KERN_ERR "PCI: Error while updating region "
-			"%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-			new, check);
+	if (res->flags & IORESOURCE_IO) {
+		offset = MB_A_PCI_IO_ADDR;
+	} else if (res->flags & IORESOURCE_MEM) {
+		offset = MB_A_PCI_MEM_ADDR;
 	}
+
+	region->start = res->start - offset;
+	region->end = res->end - offset;
 }
 
 
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	Wed Feb 12 05:38:20 2003
+++ b/arch/x86_64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -24,10 +24,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config ISA
 	bool
 
diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile
--- a/arch/x86_64/Makefile	Tue Feb 11 02:06:58 2003
+++ b/arch/x86_64/Makefile	Fri Mar  7 13:28:49 2003
@@ -86,15 +86,10 @@
 arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
 				   include/config/MARKER
 
-include/asm-$(ARCH)/offset.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
-
 include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/asm-offsets.s
-	@echo -n '  Generating $@'
-	@$(generate-asm-offsets.h) < $< > $@.tmp
-	@$(update-if-changed)
+	$(call filechk,gen-asm-offsets)
 
-CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \
-	       include/asm-$(ARCH)/offset.h
+CLEAN_FILES += include/asm-$(ARCH)/offset.h
 
 define archhelp
   echo  '* bzImage	- Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
diff -Nru a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
--- a/arch/x86_64/boot/Makefile	Wed Jan 29 20:41:18 2003
+++ b/arch/x86_64/boot/Makefile	Sat Mar 15 21:52:29 2003
@@ -25,8 +25,8 @@
 
 #RAMDISK := -DRAMDISK=512
 
-EXTRA_TARGETS	:= vmlinux.bin bootsect bootsect.o \
-		   setup setup.o bzImage
+targets		:= vmlinux.bin bootsect bootsect.o \
+		   setup setup.o bzImage mtools.conf
 
 EXTRA_CFLAGS := -m32
 
@@ -62,33 +62,33 @@
 # Set this if you want to pass append arguments to the zdisk/fdimage kernel
 FDARGS = 
 
-$(obj)/mtools.conf: $(obj)/mtools.conf.in
+$(obj)/mtools.conf: $(src)/mtools.conf.in
 	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
 
 # This requires write access to /dev/fd0
 zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
-	MTOOLSRC=$(src)/mtools.conf mformat a:			; sync
+	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
 	syslinux /dev/fd0					; sync
 	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
-	MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
+		MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
 
-# These require being root or having syslinux run setuid
-fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf
+# These require being root or having syslinux 2.02 or higher installed
+fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
 	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
-	MTOOLSRC=$(src)/mtools.conf mformat v:			; sync
+	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
 	syslinux $(obj)/fdimage					; sync
 	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(src)/mtools.conf mcopy - v:syslinux.cfg
-	MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
+		MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
 
-fdimage288: $(BOOTIMAGE) $(src)/mtools.conf
+fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
 	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
-	MTOOLSRC=$(src)/mtools.conf mformat w:			; sync
+	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
 	syslinux $(obj)/fdimage					; sync
 	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(src)/mtools.conf mcopy - w:syslinux.cfg
-	MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
+		MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
 
 zlilo: $(BOOTIMAGE)
 	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
diff -Nru a/arch/x86_64/boot/compressed/Makefile b/arch/x86_64/boot/compressed/Makefile
--- a/arch/x86_64/boot/compressed/Makefile	Mon Jan 13 14:57:27 2003
+++ b/arch/x86_64/boot/compressed/Makefile	Sun Mar  9 13:47:41 2003
@@ -6,7 +6,7 @@
 # Note all the files here are compiled/linked as 32bit executables.
 #
 
-EXTRA_TARGETS	:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
 EXTRA_AFLAGS	:= -traditional -m32
 
 # cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
--- a/arch/x86_64/boot/setup.S	Fri May 10 14:10:51 2002
+++ b/arch/x86_64/boot/setup.S	Wed Mar  5 01:43:54 2003
@@ -829,13 +829,6 @@
 	.word	0x9200				# data read/write
 	.word	0x00CF				# granularity = 4096, 386
 						#  (+5th nibble of limit)
-# this is 64bit descriptor for code
-	.word	0xFFFF
-	.word	0
-	.word	0x9A00				# code read/exec
-	.word	0x00AF				# as above, but it is long mode and with D=0
-						# it does not seem to do the trick.
-
 idt_48:
 	.word	0				# idt limit = 0
 	.word	0, 0				# idt base = 0L
diff -Nru a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
--- a/arch/x86_64/ia32/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/x86_64/ia32/Makefile	Tue Mar 11 02:37:33 2003
@@ -3,5 +3,5 @@
 #
 
 obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \
-	ia32_signal.o \
-	ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o syscall32.o
+	ia32_signal.o tls32.o \
+	ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o
diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
--- a/arch/x86_64/ia32/ia32_signal.c	Mon Feb 10 17:21:29 2003
+++ b/arch/x86_64/ia32/ia32_signal.c	Sat Mar  8 18:05:09 2003
@@ -106,20 +106,24 @@
 	stack_t uss,uoss; 
 	int ret;
 	mm_segment_t seg; 
+	if (uss_ptr) { 
+		u32 ptr;
 	if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) ||
-	    __get_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) ||
-	    __get_user((u32)uss.ss_flags, &uss_ptr->ss_flags) ||
-	    __get_user((u32)uss.ss_size, &uss_ptr->ss_size))
+		    __get_user(ptr, &uss_ptr->ss_sp) ||
+		    __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
+		    __get_user(uss.ss_size, &uss_ptr->ss_size))
 		return -EFAULT;
+		uss.ss_sp = (void *)(u64)ptr;
+	}
 	seg = get_fs(); 
 	set_fs(KERNEL_DS); 
-	ret = do_sigaltstack(&uss, &uoss, regs.rsp);
+	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp);
 	set_fs(seg); 
 	if (ret >= 0 && uoss_ptr)  {
-		if (!access_ok(VERIFY_WRITE,uss_ptr,sizeof(stack_ia32_t)) ||
-		    __put_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) ||
-		    __put_user((u32)uss.ss_flags, &uss_ptr->ss_flags) ||
-		    __put_user((u32)uss.ss_size, &uss_ptr->ss_size))
+		if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) ||
+		    __put_user((u32)(u64)uss.ss_sp, &uoss_ptr->ss_sp) ||
+		    __put_user(uss.ss_flags, &uoss_ptr->ss_flags) ||
+		    __put_user(uss.ss_size, &uoss_ptr->ss_size))
 			ret = -EFAULT;
 	} 	
 	return ret;	
diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	Sat Feb 15 04:39:48 2003
+++ b/arch/x86_64/ia32/ia32entry.S	Sun Mar  9 01:34:45 2003
@@ -255,7 +255,7 @@
 	.quad sys_umount			/* new_umount */
 	.quad ni_syscall			/* old lock syscall holder */
 	.quad sys32_ioctl
-	.quad sys32_fcntl64		/* 55 */
+	.quad compat_sys_fcntl64		/* 55 */
 	.quad ni_syscall			/* old mpx syscall holder */
 	.quad sys_setpgid
 	.quad ni_syscall			/* old ulimit syscall holder */
@@ -302,7 +302,7 @@
 	.quad compat_sys_statfs
 	.quad compat_sys_fstatfs		/* 100 */
 	.quad sys_ioperm
-	.quad sys32_socketcall
+	.quad compat_sys_socketcall
 	.quad sys_syslog
 	.quad compat_sys_setitimer
 	.quad compat_sys_getitimer	/* 105 */
@@ -421,7 +421,7 @@
 	.quad sys_mincore
 	.quad sys_madvise
 	.quad sys_getdents64	/* 220 getdents64 */ 
-	.quad sys32_fcntl64	
+	.quad compat_sys_fcntl64	
 	.quad sys_ni_syscall	/* tux */
 	.quad sys_ni_syscall    /* security */
 	.quad sys_gettid	
@@ -443,8 +443,8 @@
 	.quad compat_sys_futex		/* 240 */
         .quad sys32_sched_setaffinity
         .quad sys32_sched_getaffinity
-	.quad sys_set_thread_area
-	.quad sys_get_thread_area
+	.quad sys32_set_thread_area
+	.quad sys32_get_thread_area
 	.quad sys32_io_setup
 	.quad sys_io_destroy
 	.quad sys32_io_getevents
diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
--- a/arch/x86_64/ia32/ptrace32.c	Sat Oct 26 14:02:33 2002
+++ b/arch/x86_64/ia32/ptrace32.c	Sat Mar  8 17:56:51 2003
@@ -22,6 +22,8 @@
 #include <asm/errno.h>
 #include <asm/debugreg.h>
 #include <asm/i387.h>
+#include <asm/desc.h>
+#include <asm/ldt.h>
 #include <asm/fpu32.h>
 #include <linux/mm.h>
 #include <linux/ptrace.h>
diff -Nru a/arch/x86_64/ia32/socket32.c b/arch/x86_64/ia32/socket32.c
--- a/arch/x86_64/ia32/socket32.c	Fri Dec 20 16:51:21 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,756 +0,0 @@
-/* 
- * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c.
- *
- * Copyright (C) 2000		VA Linux Co
- * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
- * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com>
- * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 2000		Hewlett-Packard Co.
- * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs 
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/file.h>
-#include <linux/icmpv6.h>
-#include <linux/socket.h>
-#include <linux/filter.h>
-#include <linux/compat.h>
-
-#include <net/scm.h>
-#include <net/sock.h>
-#include <asm/ia32.h>
-#include <asm/uaccess.h>
-#include <asm/socket32.h>
-
-#define A(__x)		((unsigned long)(__x))
-#define AA(__x)		((unsigned long)(__x))
-
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				       void * optval, int *optlen);
-
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-					     struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage long sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-asmlinkage long sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-	if(uaddr != NULL && err >= 0)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	return len;
-}
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int err;
-
-	if (optlen < sizeof(*up))
-		return -EINVAL;
-	if (get_user(ktime.tv_sec, &up->tv_sec) ||
-	    __get_user(ktime.tv_usec, &up->tv_usec))
-		return -EFAULT;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
-	set_fs(old_fs);
-
-	return err;
-}
-
-asmlinkage long sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_set_sock_timeout(fd, level, optname, optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
-static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int len, err;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-	if (len < sizeof(*up))
-		return -EINVAL;
-	len = sizeof(ktime);
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
-	set_fs(old_fs);
-
-	if (!err) {
-		if (put_user(sizeof(*up), optlen) ||
-		    put_user(ktime.tv_sec, &up->tv_sec) ||
-		    __put_user(ktime.tv_usec, &up->tv_usec))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-asmlinkage long sys32_getsockopt(int fd, int level, int optname,
-				char *optval, int *optlen)
-{
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_get_sock_timeout(fd, level, optname, optval, optlen);
-	return sys_getsockopt(fd, level, optname, optval, optlen);
-}
-
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
-				  int addrlen);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
-				 int *upeer_addrlen); 
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
-				   unsigned flags, u32 addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
-				     unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol,
-				     int usockvec[2]);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_listen(int fd, int backlog);
-
-asmlinkage long sys32_socketcall(int call, u32 *args)
-{
-	int ret;
-	u32 a[6];
-	u32 a0,a1;
-				 
-	if (call<SYS_SOCKET||call>SYS_RECVMSG)
-		return -EINVAL;
-	if (copy_from_user(a, args, nas[call]))
-		return -EFAULT;
-	a0=a[0];
-	a1=a[1];
-	
-	switch(call) 
-	{
-		case SYS_SOCKET:
-			ret = sys_socket(a0, a1, a[2]);
-			break;
-		case SYS_BIND:
-			ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_CONNECT:
-			ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_LISTEN:
-			ret = sys_listen(a0, a1);
-			break;
-		case SYS_ACCEPT:
-			ret = sys_accept(a0, (struct sockaddr *)A(a1),
-					  (int *)A(a[2]));
-			break;
-		case SYS_GETSOCKNAME:
-			ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
-					       (int *)A(a[2]));
-			break;
-		case SYS_GETPEERNAME:
-			ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
-					       (int *)A(a[2]));
-			break;
-		case SYS_SOCKETPAIR:
-			ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
-			break;
-		case SYS_SEND:
-			ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_SENDTO:
-			ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_RECV:
-			ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_RECVFROM:
-			ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_SHUTDOWN:
-			ret = sys_shutdown(a0,a1);
-			break;
-		case SYS_SETSOCKOPT:
-			ret = sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]),
-					      a[4]);
-			break;
-		case SYS_GETSOCKOPT:
-			ret = sys32_getsockopt(a0, a1, a[2], (char *)(u64)a[3], (int *)(u64)a[4]);
-			break;
-		case SYS_SENDMSG:
-			ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1),
-					     a[2]);
-			break;
-		case SYS_RECVMSG:
-			ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1),
-					     a[2]);
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-	}
-	return ret;
-}
diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/x86_64/ia32/sys_ia32.c	Sun Mar  9 01:34:45 2003
@@ -738,7 +738,7 @@
 asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
 
 static struct iovec *
-get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp)
+get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type, int *errp)
 {
 	int i;
 	u32 buf, len;
@@ -751,7 +751,7 @@
 		return 0;
 	if (count > UIO_MAXIOV)
 		return(struct iovec *)0;
-	if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+	if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count))
 		return(struct iovec *)0;
 	if (count > UIO_FASTIOV) {
 		*errp = -ENOMEM; 
@@ -792,14 +792,14 @@
 }
 
 asmlinkage long
-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
-	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL)
+	if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL)
 		return ret;
 	set_fs(KERNEL_DS);
 	ret = sys_readv(fd, iov, count);
@@ -810,14 +810,14 @@
 }
 
 asmlinkage long
-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
-	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL)
+	if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ, &ret)) == NULL)
 		return ret;
 	set_fs(KERNEL_DS);
 	ret = sys_writev(fd, iov, count);
@@ -1016,102 +1016,6 @@
 	return ret;
 }
 
-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
-asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);
-
-
-asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case F_GETLK:
-	case F_SETLK:
-	case F_SETLKW:
-		{
-			struct flock f;
-			mm_segment_t old_fs;
-			long ret;
-			
-			if (get_compat_flock(&f, (struct compat_flock *)arg))
-				return -EFAULT;
-			old_fs = get_fs(); set_fs (KERNEL_DS);
-			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
-			set_fs (old_fs);
-			if (ret) return ret;
-			if (put_compat_flock(&f, (struct compat_flock *)arg))
-				return -EFAULT;
-			return 0;
-		}
-	case F_GETLK64: 
-	case F_SETLK64: 
-	case F_SETLKW64: 
-		return sys32_fcntl64(fd,cmd,arg); 
-
-	default:
-		return sys_fcntl(fd, cmd, (unsigned long)arg);
-	}
-}
-
-static inline int get_flock64(struct ia32_flock64 *fl32, struct flock *fl64)
-{
-	if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) {
-		int ret = __get_user(fl64->l_type, &fl32->l_type); 
-		ret |= __get_user(fl64->l_whence, &fl32->l_whence);
-		ret |= __get_user(fl64->l_start, &fl32->l_start); 
-		ret |= __get_user(fl64->l_len, &fl32->l_len); 
-		ret |= __get_user(fl64->l_pid, &fl32->l_pid); 
-		return ret; 
-		}
-	return -EFAULT; 
-}
-
-static inline int put_flock64(struct ia32_flock64 *fl32, struct flock *fl64)
-{
-	if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) {
-		int ret = __put_user(fl64->l_type, &fl32->l_type); 
-		ret |= __put_user(fl64->l_whence, &fl32->l_whence);
-		ret |= __put_user(fl64->l_start, &fl32->l_start); 
-		ret |= __put_user(fl64->l_len, &fl32->l_len); 
-		ret |= __put_user(fl64->l_pid, &fl32->l_pid); 
-		return ret; 
-	}
-	return -EFAULT; 
-}
-
-asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct flock fl64;  
-	mm_segment_t oldfs = get_fs(); 
-	int ret = 0; 
-	int oldcmd = cmd;
-	unsigned long oldarg = arg;
-
-	switch (cmd) {
-	case F_GETLK64: 
-		cmd = F_GETLK; 
-		goto cnv;
-	case F_SETLK64: 
-		cmd = F_SETLK; 
-		goto cnv; 
-	case F_SETLKW64:
-		cmd = F_SETLKW; 
-	cnv:
-		ret = get_flock64((struct ia32_flock64 *)arg, &fl64); 
-		arg = (unsigned long)&fl64; 
-		set_fs(KERNEL_DS); 
-		break; 
-	case F_GETLK:
-	case F_SETLK:
-	case F_SETLKW:
-		return sys32_fcntl(fd,cmd,arg); 
-	}
-	if (!ret)
-		ret = sys_fcntl(fd, cmd, arg);
-	set_fs(oldfs); 
-	if (oldcmd == F_GETLK64 && !ret)
-		ret = put_flock64((struct ia32_flock64 *)oldarg, &fl64); 
-	return ret; 
-}
-
 int sys32_ni_syscall(int call)
 { 
 	printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", call,
@@ -1261,8 +1165,8 @@
 	if (s->si_signo >= SIGRTMIN) {
 		d->si_pid = s->si_pid;
 		d->si_uid = s->si_uid;
-		/* XXX: Ouch, how to find this out??? */
-		d->si_int = s->si_int;
+		memcpy(&d->si_int, &s->si_int, 
+                       sizeof(siginfo_t) - offsetof(siginfo_t,si_int));
 	} else switch (s->si_signo) {
 	/* XXX: What about POSIX1.b timers */
 	case SIGCHLD:
@@ -1299,8 +1203,9 @@
 	if (s->si_signo >= SIGRTMIN) {
 		d->si_pid = s->si_pid;
 		d->si_uid = s->si_uid;
-		/* XXX: Ouch, how to find this out??? */
-		d->si_int = s->si_int;
+		memcpy(&d->si_int,
+                       &s->si_int,
+                       sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); 
 	} else switch (s->si_signo) {
 	/* XXX: What about POSIX1.b timers */
 	case SIGCHLD:
diff -Nru a/arch/x86_64/ia32/tls32.c b/arch/x86_64/ia32/tls32.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/x86_64/ia32/tls32.c	Sun Mar  9 07:30:05 2003
@@ -0,0 +1,162 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/user.h>
+
+#include <asm/uaccess.h>
+#include <asm/desc.h>
+#include <asm/system.h>
+#include <asm/ldt.h>
+#include <asm/processor.h>
+#include <asm/proto.h>
+
+/*
+ * sys_alloc_thread_area: get a yet unused TLS descriptor index.
+ */
+static int get_free_idx(void)
+{
+	struct thread_struct *t = &current->thread;
+	int idx;
+
+	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+		if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx))
+			return idx + GDT_ENTRY_TLS_MIN;
+	return -ESRCH;
+}
+
+/*
+ * Set a given TLS descriptor:
+ * When you want addresses > 32bit use arch_prctl() 
+ */
+int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info)
+{
+	struct user_desc info;
+	struct n_desc_struct *desc;
+	int cpu, idx;
+
+	if (copy_from_user(&info, u_info, sizeof(info)))
+		return -EFAULT;
+
+	idx = info.entry_number;
+
+	/*
+	 * index -1 means the kernel should try to find and
+	 * allocate an empty descriptor:
+	 */
+	if (idx == -1) {
+		idx = get_free_idx();
+		if (idx < 0)
+			return idx;
+		if (put_user(idx, &u_info->entry_number))
+			return -EFAULT;
+	}
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
+
+	/*
+	 * We must not get preempted while modifying the TLS.
+	 */
+	cpu = get_cpu();
+
+	if (LDT_empty(&info)) {
+		desc->a = 0;
+		desc->b = 0;
+	} else {
+		desc->a = LDT_entry_a(&info);
+		desc->b = LDT_entry_b(&info);
+	}
+	if (t == &current->thread)
+		load_TLS(t, cpu);
+
+	put_cpu();
+	return 0;
+}
+
+asmlinkage long sys32_set_thread_area(struct user_desc *u_info)
+{ 
+	return do_set_thread_area(&current->thread, u_info); 
+} 
+
+
+/*
+ * Get the current Thread-Local Storage area:
+ */
+
+#define GET_BASE(desc) ( \
+	(((desc)->a >> 16) & 0x0000ffff) | \
+	(((desc)->b << 16) & 0x00ff0000) | \
+	( (desc)->b        & 0xff000000)   )
+
+#define GET_LIMIT(desc) ( \
+	((desc)->a & 0x0ffff) | \
+	 ((desc)->b & 0xf0000) )
+	
+#define GET_32BIT(desc)		(((desc)->b >> 23) & 1)
+#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
+#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
+#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
+#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
+#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+#define GET_LONGMODE(desc)	(((desc)->b >> 21) & 1)
+
+int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info)
+{
+	struct user_desc info;
+	struct n_desc_struct *desc;
+	int idx;
+
+	if (get_user(idx, &u_info->entry_number))
+		return -EFAULT;
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
+
+	memset(&info, 0, sizeof(struct user_desc));
+	info.entry_number = idx;
+	info.base_addr = GET_BASE(desc);
+	info.limit = GET_LIMIT(desc);
+	info.seg_32bit = GET_32BIT(desc);
+	info.contents = GET_CONTENTS(desc);
+	info.read_exec_only = !GET_WRITABLE(desc);
+	info.limit_in_pages = GET_LIMIT_PAGES(desc);
+	info.seg_not_present = !GET_PRESENT(desc);
+	info.useable = GET_USEABLE(desc);
+	info.lm = GET_LONGMODE(desc);
+
+	if (copy_to_user(u_info, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+asmlinkage long sys32_get_thread_area(struct user_desc *u_info)
+{
+	return do_get_thread_area(&current->thread, u_info);
+} 
+
+
+int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs)
+{
+	struct n_desc_struct *desc;
+	struct user_desc info, *cp;
+	int idx;
+	
+	cp = (void *)childregs->rsi;
+	if (copy_from_user(&info, cp, sizeof(info)))
+		return -EFAULT;
+	if (LDT_empty(&info))
+		return -EINVAL;
+	
+	idx = info.entry_number;
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+	
+	desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN;
+	desc->a = LDT_entry_a(&info);
+	desc->b = LDT_entry_b(&info);
+
+	return 0;
+}
diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
--- a/arch/x86_64/kernel/Makefile	Tue Feb 18 18:59:01 2003
+++ b/arch/x86_64/kernel/Makefile	Sun Mar  9 14:15:54 2003
@@ -2,8 +2,8 @@
 # Makefile for the linux kernel.
 #
 
-EXTRA_TARGETS 	:= head.o head64.o init_task.o
-EXTRA_AFLAGS  := -traditional
+extra-y 	:= head.o head64.o init_task.o
+EXTRA_AFLAGS	:= -traditional
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
 		pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \
diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
--- a/arch/x86_64/kernel/apic.c	Tue Feb 25 10:47:30 2003
+++ b/arch/x86_64/kernel/apic.c	Sat Mar  8 18:01:10 2003
@@ -981,9 +981,6 @@
 asmlinkage void smp_spurious_interrupt(void)
 {
 	unsigned int v;
-	static unsigned long last_warning; 
-	static unsigned long skipped; 
-
 	irq_enter();
 	/*
 	 * Check if this really is a spurious interrupt and ACK it
@@ -994,8 +991,12 @@
 	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
 		ack_APIC_irq();
 
+#if 0
+	static unsigned long last_warning; 
+	static unsigned long skipped; 
+
 	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
-	if (last_warning+30*HZ < jiffies) { 
+	if (time_before(last_warning+30*HZ,jiffies)) { 
 		printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
 		       smp_processor_id(), skipped);
 		last_warning = jiffies; 
@@ -1003,6 +1004,7 @@
 	} else { 
 		skipped++; 
 	} 
+#endif 
 	irq_exit();
 }
 
diff -Nru a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
--- a/arch/x86_64/kernel/head64.c	Tue Feb 11 06:03:03 2003
+++ b/arch/x86_64/kernel/head64.c	Sun Mar  9 08:28:23 2003
@@ -79,6 +79,9 @@
 	clear_bss();
 	pda_init(0);
 	copy_bootdata(real_mode_data);
+	/* default console: */
+	if (!strstr(saved_command_line, "console="))
+		strcat(saved_command_line, " console=tty0"); 
 	s = strstr(saved_command_line, "earlyprintk="); 
 	if (s != NULL)
 		setup_early_printk(s+12); 
diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
--- a/arch/x86_64/kernel/io_apic.c	Sun Mar  2 18:13:32 2003
+++ b/arch/x86_64/kernel/io_apic.c	Sat Mar  8 18:03:40 2003
@@ -1110,7 +1110,7 @@
  */
 static int __init timer_irq_works(void)
 {
-	unsigned int t1 = jiffies;
+	unsigned long t1 = jiffies;
 
 	local_irq_enable();
 	/* Let ten ticks pass... */
@@ -1123,6 +1123,8 @@
 	 * might have cached one ExtINT interrupt.  Finally, at
 	 * least one tick may be lost due to delays.
 	 */
+
+	/* jiffies wrap? */
 	if (jiffies - t1 > 4)
 		return 1;
 	return 0;
diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
--- a/arch/x86_64/kernel/irq.c	Tue Feb 25 01:39:01 2003
+++ b/arch/x86_64/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -135,6 +135,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -143,9 +144,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -156,11 +158,13 @@
 				kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
-		seq_printf(p, "  %s", action->name);
 
+		seq_printf(p, "  %s", action->name);
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
--- a/arch/x86_64/kernel/process.c	Sat Feb 22 08:39:06 2003
+++ b/arch/x86_64/kernel/process.c	Sun Mar  9 16:22:16 2003
@@ -19,46 +19,37 @@
 #define __KERNEL_SYSCALLS__
 #include <stdarg.h>
 
-#include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/elfcore.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/stddef.h>
 #include <linux/unistd.h>
-#include <linux/ptrace.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/user.h>
 #include <linux/module.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
-#include <linux/config.h>
 #include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ctype.h>
-#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/ptrace.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
-#include <asm/desc.h>
 #include <asm/mmu_context.h>
 #include <asm/pda.h>
 #include <asm/prctl.h>
 #include <asm/kdebug.h>
-
-#include <linux/irq.h>
+#include <asm/desc.h>
+#include <asm/proto.h>
+#include <asm/ia32.h>
 
 asmlinkage extern void ret_from_fork(void);
-int sys_arch_prctl(int code, unsigned long addr);
 
 unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
 
@@ -245,10 +236,36 @@
 	}
 }
 
+static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
+{
+	struct user_desc ud = { 
+		.base_addr = addr,
+		.limit = 0xfffff,
+		.seg_32bit = 1,
+		.limit_in_pages = 1,
+		.useable = 1,
+	};
+	struct n_desc_struct *desc = (void *)t->thread.tls_array;
+	desc += tls;
+	desc->a = LDT_entry_a(&ud); 
+	desc->b = LDT_entry_b(&ud); 
+}
+
+static inline u32 read_32bit_tls(struct task_struct *t, int tls)
+{
+	struct desc_struct *desc = (void *)t->thread.tls_array;
+	desc += tls;
+	return desc->base0 | 
+		(((u32)desc->base1) << 16) | 
+		(((u32)desc->base2) << 24);
+}
+
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, 
 		unsigned long unused,
 	struct task_struct * p, struct pt_regs * regs)
 {
+	int err;
 	struct pt_regs * childregs;
 	struct task_struct *me = current;
 
@@ -265,7 +282,7 @@
 
 	p->thread.rsp = (unsigned long) childregs;
 	p->thread.rsp0 = (unsigned long) (childregs+1);
-	p->thread.userrsp = current->thread.userrsp; 
+	p->thread.userrsp = me->thread.userrsp; 
 
 	p->thread.rip = (unsigned long) ret_from_fork;
 
@@ -277,8 +294,8 @@
 	asm("movl %%es,%0" : "=m" (p->thread.es));
 	asm("movl %%ds,%0" : "=m" (p->thread.ds));
 
-	unlazy_fpu(current);	
-	p->thread.i387 = current->thread.i387;
+	unlazy_fpu(me);	
+	p->thread.i387 = me->thread.i387;
 
 	if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
 		p->thread.io_bitmap_ptr = kmalloc((IO_BITMAP_SIZE+1)*4, GFP_KERNEL);
@@ -292,27 +309,20 @@
 	 * Set a new TLS for the child thread?
 	 */
 	if (clone_flags & CLONE_SETTLS) {
-		struct n_desc_struct *desc;
-		struct user_desc info;
-		int idx;
-
-		if (copy_from_user(&info, test_thread_flag(TIF_IA32) ? 
-								  (void *)childregs->rsi : 
-								  (void *)childregs->rdx, sizeof(info)))
-			return -EFAULT;
-		if (LDT_empty(&info))
-			return -EINVAL;
-
-		idx = info.entry_number;
-		if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-			return -EINVAL;
-
-		desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN;
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
-	}
-
-	return 0;
+#ifdef CONFIG_IA32_EMULATION
+		if (test_thread_flag(TIF_IA32))
+			err = ia32_child_tls(p, childregs); 
+		else 			
+#endif	 
+			err = do_arch_prctl(p, ARCH_SET_FS, childregs->r10); 
+		if (err) 
+			goto out;
+	}
+	err = 0;
+out:
+	if (err && p->thread.io_bitmap_ptr)
+		kfree(p->thread.io_bitmap_ptr);
+	return err;
 }
 
 /*
@@ -422,7 +432,7 @@
 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
 		if (next->io_bitmap_ptr) {
 			/*
-			 * 4 cachelines copy ... not good, but not that
+			 * 2 cachelines copy ... not good, but not that
 			 * bad either. Anyone got something better?
 			 * This only affects processes which use ioperm().
 			 */
@@ -537,19 +547,35 @@
 #undef last_sched
 #undef first_sched
 
-int sys_arch_prctl(int code, unsigned long addr)
+long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 { 
 	int ret = 0; 
+	int doit = task == current;
+	int cpu;
 
 	switch (code) { 
 	case ARCH_SET_GS:
 		if (addr >= TASK_SIZE) 
 			return -EPERM; 
-		get_cpu();
+		cpu = get_cpu();
+		/* handle small bases via the GDT because that's faster to 
+		   switch. */
+		if (addr <= 0xffffffff) {  
+			set_32bit_tls(task, GS_TLS, addr); 
+			if (doit) { 
+				load_TLS(&task->thread, cpu);
+				load_gs_index(GS_TLS_SEL); 
+			}
+			task->thread.gsindex = GS_TLS_SEL; 
+			task->thread.gs = 0;
+		} else { 
+			task->thread.gsindex = 0;
+			task->thread.gs = addr;
+			if (doit) {
 		load_gs_index(0);
-		current->thread.gsindex = 0;
-		current->thread.gs = addr;
 		ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); 
+			} 
+		}
 		put_cpu();
 		break;
 	case ARCH_SET_FS:
@@ -557,22 +583,51 @@
 		   with gs */
 		if (addr >= TASK_SIZE)
 			return -EPERM; 
-		get_cpu();
+		cpu = get_cpu();
+		/* handle small bases via the GDT because that's faster to 
+		   switch. */
+		if (addr <= 0xffffffff) { 
+			set_32bit_tls(task, FS_TLS, addr);
+			if (doit) { 
+				load_TLS(&task->thread, cpu); 
+				asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL));
+			}
+			task->thread.fsindex = FS_TLS_SEL;
+			task->thread.fs = 0;
+		} else { 
+			task->thread.fsindex = 0;
+			task->thread.fs = addr;
+			if (doit) {
+				/* set the selector to 0 to not confuse
+				   __switch_to */
 		asm volatile("movl %0,%%fs" :: "r" (0));
-		current->thread.fsindex = 0;
-		current->thread.fs = addr;
 		ret = checking_wrmsrl(MSR_FS_BASE, addr); 
+			}
+		}
 		put_cpu();
 		break;
-
-		/* Returned value may not be correct when the user changed fs/gs */ 
-	case ARCH_GET_FS:
-		ret = put_user(current->thread.fs, (unsigned long *)addr); 
+	case ARCH_GET_FS: { 
+		unsigned long base; 
+		if (task->thread.fsindex == FS_TLS_SEL)
+			base = read_32bit_tls(task, FS_TLS);
+		else if (doit) {
+			rdmsrl(MSR_FS_BASE, base);
+		} else
+			base = task->thread.fs;
+		ret = put_user(base, (unsigned long *)addr); 
 		break; 
-
-	case ARCH_GET_GS: 
-		ret = put_user(current->thread.gs, (unsigned long *)addr); 
+	}
+	case ARCH_GET_GS: { 
+		unsigned long base;
+		if (task->thread.gsindex == GS_TLS_SEL)
+			base = read_32bit_tls(task, GS_TLS);
+		else if (doit) {
+			rdmsrl(MSR_KERNEL_GS_BASE, base);
+		} else
+			base = task->thread.gs;
+		ret = put_user(base, (unsigned long *)addr); 
 		break;
+	}
 
 	default:
 		ret = -EINVAL;
@@ -582,131 +637,9 @@
 	return ret;	
 } 
 
-/*
- * sys_alloc_thread_area: get a yet unused TLS descriptor index.
- */
-static int get_free_idx(void)
-{
-	struct thread_struct *t = &current->thread;
-	int idx;
-
-	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
-		if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx))
-			return idx + GDT_ENTRY_TLS_MIN;
-	return -ESRCH;
-}
-
-/*
- * Set a given TLS descriptor:
- * When you want addresses > 32bit use arch_prctl() 
- */
-int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info)
-{
-	struct user_desc info;
-	struct n_desc_struct *desc;
-	int cpu, idx;
-
-	if (copy_from_user(&info, u_info, sizeof(info)))
-		return -EFAULT;
-
-	idx = info.entry_number;
-
-	/*
-	 * index -1 means the kernel should try to find and
-	 * allocate an empty descriptor:
-	 */
-	if (idx == -1) {
-		idx = get_free_idx();
-		if (idx < 0)
-			return idx;
-		if (put_user(idx, &u_info->entry_number))
-			return -EFAULT;
-	}
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
-
-	/*
-	 * We must not get preempted while modifying the TLS.
-	 */
-	cpu = get_cpu();
-
-	if (LDT_empty(&info)) {
-		desc->a = 0;
-		desc->b = 0;
-	} else {
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
-	}
-	if (t == &current->thread)
-	load_TLS(t, cpu);
-
-	put_cpu();
-	return 0;
-}
-
-asmlinkage int sys_set_thread_area(struct user_desc *u_info)
-{ 
-	return do_set_thread_area(&current->thread, u_info); 
-} 
-
-
-/*
- * Get the current Thread-Local Storage area:
- */
-
-#define GET_BASE(desc) ( \
-	(((desc)->a >> 16) & 0x0000ffff) | \
-	(((desc)->b << 16) & 0x00ff0000) | \
-	( (desc)->b        & 0xff000000)   )
-
-#define GET_LIMIT(desc) ( \
-	((desc)->a & 0x0ffff) | \
-	 ((desc)->b & 0xf0000) )
-	
-#define GET_32BIT(desc)		(((desc)->b >> 23) & 1)
-#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
-#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
-#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
-#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
-#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
-#define GET_LONGMODE(desc)	(((desc)->b >> 21) & 1)
-
-int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info)
-{
-	struct user_desc info;
-	struct n_desc_struct *desc;
-	int idx;
-
-	if (get_user(idx, &u_info->entry_number))
-		return -EFAULT;
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
-
-	memset(&info, 0, sizeof(struct user_desc));
-	info.entry_number = idx;
-	info.base_addr = GET_BASE(desc);
-	info.limit = GET_LIMIT(desc);
-	info.seg_32bit = GET_32BIT(desc);
-	info.contents = GET_CONTENTS(desc);
-	info.read_exec_only = !GET_WRITABLE(desc);
-	info.limit_in_pages = GET_LIMIT_PAGES(desc);
-	info.seg_not_present = !GET_PRESENT(desc);
-	info.useable = GET_USEABLE(desc);
-	info.lm = GET_LONGMODE(desc);
-
-	if (copy_to_user(u_info, &info, sizeof(info)))
-		return -EFAULT;
-	return 0;
-}
-
-asmlinkage int sys_get_thread_area(struct user_desc *u_info)
+long sys_arch_prctl(int code, unsigned long addr)
 {
-	return do_get_thread_area(&current->thread, u_info);
+	return do_arch_prctl(current, code, addr);
 } 
 
 /* 
diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
--- a/arch/x86_64/kernel/ptrace.c	Sat Feb 15 01:42:03 2003
+++ b/arch/x86_64/kernel/ptrace.c	Sun Mar  9 04:38:18 2003
@@ -26,6 +26,7 @@
 #include <asm/ldt.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
+#include <asm/ia32.h>
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -322,6 +323,13 @@
 		wake_up_process(child);
 		ret = 0;
 		break;
+	}
+
+#ifdef CONFIG_IA32_EMULATION
+		/* This makes only sense with 32bit programs. Allow a
+		   64bit debugger to fully examine them too. Better
+		   don't use it against 64bit processes, use
+		   PTRACE_ARCH_PRCTL instead. */
 	case PTRACE_SET_THREAD_AREA: {
 		int old; 
 		get_user(old,  &((struct user_desc *)data)->entry_number); 
@@ -338,7 +346,13 @@
 		put_user(old,  &((struct user_desc *)data)->entry_number); 
 		break;
 	} 
-	}
+#endif
+		/* normal 64bit interface to access TLS data. 
+		   Works just like arch_prctl, except that the arguments
+		   are reversed. */
+	case PTRACE_ARCH_PRCTL: 
+		ret = do_arch_prctl(child, data, addr);
+		break;
 
 /*
  * make the child exit.  Best I can do is send it a sigkill. 
diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
--- a/arch/x86_64/kernel/setup64.c	Fri Feb 21 08:55:38 2003
+++ b/arch/x86_64/kernel/setup64.c	Wed Mar  5 01:43:54 2003
@@ -22,6 +22,7 @@
 #include <asm/i387.h>
 #include <asm/percpu.h>
 #include <asm/mtrr.h>
+#include <asm/proto.h>
 
 char x86_boot_params[2048] __initdata = {0,};
 
@@ -29,9 +30,6 @@
 
 struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; 
 
-extern void system_call(void); 
-extern void ia32_cstar_target(void); 
-
 extern struct task_struct init_task;
 
 extern unsigned char __per_cpu_start[], __per_cpu_end[]; 
@@ -130,6 +128,24 @@
 #define EXCEPTION_STK_ORDER 0 /* >= N_EXCEPTION_STACKS*EXCEPTION_STKSZ */
 char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ];
 
+void syscall_init(void)
+{
+	/* 
+	 * LSTAR and STAR live in a bit strange symbiosis.
+	 * They both write to the same internal register. STAR allows to set CS/DS
+	 * but only a 32bit target. LSTAR sets the 64bit rip. 	 
+	 */ 
+	wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32); 
+	wrmsrl(MSR_LSTAR, system_call); 
+
+#ifdef CONFIG_IA32_EMULATION   		
+	wrmsrl(MSR_CSTAR, ia32_cstar_target); 
+#endif
+
+	/* Flags to clear on syscall */
+	wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); 
+}
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -188,20 +204,7 @@
 
 	asm volatile("pushfq ; popq %%rax ; btr $14,%%rax ; pushq %%rax ; popfq" ::: "eax");
 
-	/* 
-	 * LSTAR and STAR live in a bit strange symbiosis.
-	 * They both write to the same internal register. STAR allows to set CS/DS
-	 * but only a 32bit target. LSTAR sets the 64bit rip. 	 
-	 */ 
-	wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32); 
-	wrmsrl(MSR_LSTAR, system_call); 
-
-#ifdef CONFIG_IA32_EMULATION   		
-	wrmsrl(MSR_CSTAR, ia32_cstar_target); 
-#endif
-
-	/* Flags to clear on syscall */
-	wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); 
+	syscall_init();
 
 	wrmsrl(MSR_FS_BASE, 0);
 	wrmsrl(MSR_KERNEL_GS_BASE, 0);
diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
--- a/arch/x86_64/kernel/signal.c	Tue Feb 11 02:37:45 2003
+++ b/arch/x86_64/kernel/signal.c	Wed Mar  5 01:43:54 2003
@@ -96,14 +96,6 @@
 
 #define COPY(x)		err |= __get_user(regs->x, &sc->x)
 
-	{ 
-		unsigned int seg; 
-		err |= __get_user(seg, &sc->gs); 
-		load_gs_index(seg); 
-		err |= __get_user(seg, &sc->fs);
-		loadsegment(fs,seg);
-	}
-
 	COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx);
 	COPY(rdx); COPY(rcx); COPY(rip);
 	COPY(r8);
@@ -189,13 +181,10 @@
 static inline int
 setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me)
 {
-	int tmp, err = 0;
+	int err = 0;
 
-	tmp = 0;
-	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
-	err |= __put_user(tmp, (unsigned int *)&sc->gs);
-	__asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
-	err |= __put_user(tmp, (unsigned int *)&sc->fs);
+	err |= __put_user(0, &sc->gs);
+	err |= __put_user(0, &sc->fs);
 
 	err |= __put_user(regs->rdi, &sc->rdi);
 	err |= __put_user(regs->rsi, &sc->rsi);
diff -Nru a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
--- a/arch/x86_64/kernel/suspend.c	Fri Dec 20 21:36:57 2002
+++ b/arch/x86_64/kernel/suspend.c	Wed Mar  5 01:43:54 2003
@@ -26,6 +26,7 @@
 #include <asm/acpi.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
+#include <asm/proto.h>
 
 static struct saved_context saved_context;
 
@@ -58,10 +59,9 @@
 	asm volatile ("movw %%gs, %0" : "=m" (saved_context.gs));
 	asm volatile ("movw %%ss, %0" : "=m" (saved_context.ss));
 
-	asm volatile ("swapgs");
-	rdmsrl(0xc0000100, saved_context.fs_base);
-	rdmsrl(0xc0000101, saved_context.gs_base);
-	asm volatile ("swapgs");
+	rdmsrl(MSR_FS_BASE, saved_context.fs_base);
+	rdmsrl(MSR_GS_BASE, saved_context.gs_base);
+	rdmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base);
 
 	/*
 	 * control registers 
@@ -99,10 +99,9 @@
 	load_gs_index(saved_context.gs);
 	asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss));
 
-	asm volatile ("swapgs");
-	wrmsrl(0xc0000100, saved_context.fs_base);
-	wrmsrl(0xc0000101, saved_context.gs_base);
-	asm volatile ("swapgs");
+	wrmsrl(MSR_FS_BASE, saved_context.fs_base);
+	wrmsrl(MSR_GS_BASE, saved_context.gs_base);
+	wrmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base);
 
 	/*
 	 * now restore the descriptor tables to their proper values
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c	Mon Feb 24 23:13:09 2003
+++ b/arch/x86_64/kernel/time.c	Sun Mar  9 04:26:46 2003
@@ -30,7 +30,7 @@
 #include <asm/apic.h>
 #endif
 
-u64 jiffies_64;
+u64 jiffies_64 = INITIAL_JIFFIES;
 
 extern int using_apic_timer;
 
@@ -47,8 +47,8 @@
 
 struct hpet_data __hpet __section_hpet;			/* address, quotient, trigger, hz */
 
-volatile unsigned long __jiffies __section_jiffies;
-unsigned long __wall_jiffies __section_wall_jiffies;
+volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
 struct timespec __xtime __section_xtime;
 struct timezone __sys_tz __section_sys_tz;
 
diff -Nru a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S
--- a/arch/x86_64/lib/getuser.S	Mon Feb 11 00:16:29 2002
+++ b/arch/x86_64/lib/getuser.S	Sun Mar  9 16:12:06 2003
@@ -30,7 +30,7 @@
 #include <asm/thread_info.h>
 
 	.text
-	.p2align
+	.p2align 4
 .globl __get_user_1
 __get_user_1:	
 	GET_THREAD_INFO(%rbx)
@@ -40,7 +40,7 @@
 	xorq %rax,%rax
 	ret
 
-	.p2align	
+	.p2align 4
 .globl __get_user_2
 __get_user_2:
 	GET_THREAD_INFO(%rbx) 
@@ -52,7 +52,7 @@
 	xorq %rax,%rax
 	ret
 
-	.p2align
+	.p2align 4
 .globl __get_user_4
 __get_user_4:
 	GET_THREAD_INFO(%rbx) 
@@ -64,7 +64,7 @@
 	xorq %rax,%rax
 	ret
 
-	.p2align
+	.p2align 4
 .globl __get_user_8
 __get_user_8:
 	GET_THREAD_INFO(%rbx) 
diff -Nru a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
--- a/arch/x86_64/mm/pageattr.c	Sun Mar  2 18:13:32 2003
+++ b/arch/x86_64/mm/pageattr.c	Wed Mar  5 03:08:42 2003
@@ -53,7 +53,7 @@
 
 static void flush_kernel_map(void *address) 
 {
-	if (address && cpu_has_clflush) {
+	if (0 && address && cpu_has_clflush) {
 		/* is this worth it? */ 
 		int i;
 		for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) 
diff -Nru a/arch/x86_64/pci/direct.c b/arch/x86_64/pci/direct.c
--- a/arch/x86_64/pci/direct.c	Fri Aug 30 06:59:56 2002
+++ b/arch/x86_64/pci/direct.c	Wed Mar  5 03:01:42 2003
@@ -196,21 +196,35 @@
 static int __devinit pci_sanity_check(struct pci_ops *o)
 {
 	u32 x = 0;
-	struct pci_bus bus;		/* Fake bus and device */
-	struct pci_dev dev;
+	int retval = 0;
+	struct pci_bus *bus;		/* Fake bus and device */
+	struct pci_dev *dev;
 
 	if (pci_probe & PCI_NO_CHECKS)
 		return 1;
-	bus.number = 0;
-	dev.bus = &bus;
-	for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++)
-		if ((!o->read(&bus, dev.devfn, PCI_CLASS_DEVICE, 2, &x) &&
+
+	bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
+	dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+	if (!bus || !dev) {
+		printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
+		goto exit;
+	}
+
+	bus->number = 0;
+	dev->bus = bus;
+	for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++)
+		if ((!o->read(bus, dev->devfn, PCI_CLASS_DEVICE, 2, &x) &&
 		     (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
-		    (!o->read(&bus, dev.devfn, PCI_VENDOR_ID, 2, &x) &&
-		     (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
-			return 1;
+		    (!o->read(bus, dev->devfn, PCI_VENDOR_ID, 2, &x) &&
+		     (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) {
+			retval = 1;
+			goto exit;
+		}
 	DBG("PCI: Sanity check failed\n");
-	return 0;
+exit:
+	kfree(dev);
+	kfree(bus);
+	return retval;
 }
 
 static int __init pci_direct_init(void)
@@ -218,7 +232,7 @@
 	unsigned int tmp;
 	unsigned long flags;
 
-	local_save_flags(flags); local_irq_disable();
+	local_irq_save(flags);
 
 	/*
 	 * Check if configuration type 1 works.
@@ -261,7 +275,6 @@
 	}
 
 	local_irq_restore(flags);
-	pci_root_ops = NULL;
 	return 0;
 }
 
diff -Nru a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c
--- a/arch/x86_64/pci/irq.c	Fri Nov 15 01:01:33 2002
+++ b/arch/x86_64/pci/irq.c	Wed Mar  5 03:54:28 2003
@@ -109,7 +109,7 @@
 		 */
 		if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL))
 			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
-	pcibios_last_bus = -1;
+	//pcibios_last_bus = -1;
 }
 
 /*
@@ -291,14 +291,14 @@
 	{
 		irq = read_config_nybble(router, 0x56, pirq - 1);
 	}
-	printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d get irq : %2d\n",
+	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
 		dev->vendor, dev->device, pirq, irq);
 	return irq;
 }
 
 static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
+	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
 		dev->vendor, dev->device, pirq, irq);
 	if (pirq <= 4)
 	{
diff -Nru a/arch/x86_64/pci/legacy.c b/arch/x86_64/pci/legacy.c
--- a/arch/x86_64/pci/legacy.c	Wed Oct 30 02:51:28 2002
+++ b/arch/x86_64/pci/legacy.c	Wed Mar  5 03:55:39 2003
@@ -1,8 +1,8 @@
 /*
  * legacy.c - traditional, old school PCI bus probing
  */
-#include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/pci.h>
 #include "pci.h"
 
 /*
@@ -12,28 +12,39 @@
 void __devinit pcibios_fixup_peer_bridges(void)
 {
 	int n;
-	struct pci_bus bus;
-	struct pci_dev dev;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
 	u16 l;
 
-	if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff)
+	if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
 		return;
 	DBG("PCI: Peer bridge fixup\n");
+
+	bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
+	dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+	if (!bus || !dev) {
+		printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
+		goto exit;
+	}
+
 	for (n=0; n <= pcibios_last_bus; n++) {
 		if (pci_bus_exists(&pci_root_buses, n))
 			continue;
-		bus.number = n;
-		bus.ops = pci_root_ops;
-		dev.bus = &bus;
-		for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
-			if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
+		bus->number = n;
+		bus->ops = pci_root_ops;
+		dev->bus = bus;
+		for (dev->devfn=0; dev->devfn<256; dev->devfn += 8)
+			if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
 			    l != 0x0000 && l != 0xffff) {
-				DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
+				DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l);
 				printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
 				pci_scan_bus(n, pci_root_ops, NULL);
 				break;
 			}
 	}
+exit:
+	kfree(dev);
+	kfree(bus);
 }
 
 static int __init pci_legacy_init(void)
diff -Nru a/arch/x86_64/pci/pci.h b/arch/x86_64/pci/pci.h
--- a/arch/x86_64/pci/pci.h	Wed Oct 30 02:47:30 2002
+++ b/arch/x86_64/pci/pci.h	Wed Mar  5 03:53:36 2003
@@ -67,7 +67,6 @@
 extern int pcibios_scanned;
 extern spinlock_t pci_config_lock;
 
-void pcibios_fixup_irqs(void);
 int pirq_enable_irq(struct pci_dev *dev);
 
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
diff -Nru a/arch/x86_64/pci/x86-64.c b/arch/x86_64/pci/x86-64.c
--- a/arch/x86_64/pci/x86-64.c	Fri Oct 11 16:52:38 2002
+++ b/arch/x86_64/pci/x86-64.c	Sun Mar 16 14:16:33 2003
@@ -33,34 +33,6 @@
 
 #include "pci.h"
 
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			struct resource *res, int resource)
-{
-	u32 new, check;
-	int reg;
-
-	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
-	} else if (resource == PCI_ROM_RESOURCE) {
-		res->flags |= PCI_ROM_ADDRESS_ENABLE;
-		new |= PCI_ROM_ADDRESS_ENABLE;
-		reg = dev->rom_base_reg;
-	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
-		return;
-	}
-	
-	pci_write_config_dword(dev, reg, new);
-	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
-		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
-		       new, check);
-	}
-}
-
 /*
  * We need to avoid collisions with `mirrored' VGA ports
  * and other strange ISA hardware, so we always want the
diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S
--- a/arch/x86_64/vmlinux.lds.S	Tue Feb 11 03:00:35 2003
+++ b/arch/x86_64/vmlinux.lds.S	Fri Feb 14 17:50:07 2003
@@ -98,6 +98,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/crypto/api.c b/crypto/api.c
--- a/crypto/api.c	Mon Dec 30 13:39:58 2002
+++ b/crypto/api.c	Sat Mar  8 11:46:18 2003
@@ -128,8 +128,6 @@
 
 	memset(tfm, 0, sizeof(*tfm));
 	
-	tfm->crt_ctx = (void*) &tfm[1];
-
 	tfm->__crt_alg = alg;
 	
 	if (crypto_init_flags(tfm, flags))
diff -Nru a/crypto/cipher.c b/crypto/cipher.c
--- a/crypto/cipher.c	Sun Feb  2 23:34:59 2003
+++ b/crypto/cipher.c	Sat Mar  8 11:46:18 2003
@@ -23,7 +23,8 @@
 #include "internal.h"
 
 typedef void (cryptfn_t)(void *, u8 *, const u8 *);
-typedef void (procfn_t)(struct crypto_tfm *, u8 *, u8*, cryptfn_t, int enc);
+typedef void (procfn_t)(struct crypto_tfm *, u8 *,
+                        u8*, cryptfn_t, int enc, void *);
 
 struct scatter_walk {
 	struct scatterlist	*sg;
@@ -34,6 +35,13 @@
 	unsigned int		offset;
 };
 
+enum km_type crypto_km_types[] = {
+	KM_USER0,
+	KM_USER1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+};
+
 static inline void xor_64(u8 *a, const u8 *b)
 {
 	((u32 *)a)[0] ^= ((u32 *)b)[0];
@@ -159,7 +167,8 @@
 static int crypt(struct crypto_tfm *tfm,
 		 struct scatterlist *dst,
 		 struct scatterlist *src,
-                 unsigned int nbytes, cryptfn_t crfn, procfn_t prfn, int enc)
+                 unsigned int nbytes, cryptfn_t crfn,
+                 procfn_t prfn, int enc, void *info)
 {
 	struct scatter_walk walk_in, walk_out;
 	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
@@ -189,7 +198,7 @@
 
 		copy_chunks(src_p, &walk_in, bsize, 0);
 
-		prfn(tfm, dst_p, src_p, crfn, enc);
+		prfn(tfm, dst_p, src_p, crfn, enc, info);
 
 		scatter_done(&walk_in, 0, nbytes);
 
@@ -204,35 +213,35 @@
 }
 
 static void cbc_process(struct crypto_tfm *tfm,
-                        u8 *dst, u8 *src, cryptfn_t fn, int enc)
+                        u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info)
 {
+	u8 *iv = info;
+	
 	/* Null encryption */
-	if (!tfm->crt_cipher.cit_iv)
+	if (!iv)
 		return;
 		
 	if (enc) {
-		tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src);
-		fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv);
-		memcpy(tfm->crt_cipher.cit_iv, dst,
-		       crypto_tfm_alg_blocksize(tfm));
+		tfm->crt_u.cipher.cit_xor_block(iv, src);
+		fn(crypto_tfm_ctx(tfm), dst, iv);
+		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
 	} else {
 		const int need_stack = (src == dst);
 		u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0];
 		u8 *buf = need_stack ? stack : dst;
 		
-		fn(tfm->crt_ctx, buf, src);
-		tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv);
-		memcpy(tfm->crt_cipher.cit_iv, src,
-		       crypto_tfm_alg_blocksize(tfm));
+		fn(crypto_tfm_ctx(tfm), buf, src);
+		tfm->crt_u.cipher.cit_xor_block(buf, iv);
+		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
 		if (buf != dst)
 			memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
 	}
 }
 
 static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-                        cryptfn_t fn, int enc)
+                        cryptfn_t fn, int enc, void *info)
 {
-	fn(tfm->crt_ctx, dst, src);
+	fn(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
@@ -243,7 +252,7 @@
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 		return -EINVAL;
 	} else
-		return cia->cia_setkey(tfm->crt_ctx, key, keylen,
+		return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen,
 		                       &tfm->crt_flags);
 }
 
@@ -252,7 +261,8 @@
                        struct scatterlist *src, unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1);
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             ecb_process, 1, NULL);
 }
 
 static int ecb_decrypt(struct crypto_tfm *tfm,
@@ -261,7 +271,8 @@
 		       unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1);
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             ecb_process, 1, NULL);
 }
 
 static int cbc_encrypt(struct crypto_tfm *tfm,
@@ -270,7 +281,18 @@
 		       unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1);
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             cbc_process, 1, tfm->crt_cipher.cit_iv);
+}
+
+static int cbc_encrypt_iv(struct crypto_tfm *tfm,
+                          struct scatterlist *dst,
+                          struct scatterlist *src,
+                          unsigned int nbytes, u8 *iv)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             cbc_process, 1, iv);
 }
 
 static int cbc_decrypt(struct crypto_tfm *tfm,
@@ -279,7 +301,18 @@
 		       unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0);
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             cbc_process, 0, tfm->crt_cipher.cit_iv);
+}
+
+static int cbc_decrypt_iv(struct crypto_tfm *tfm,
+                          struct scatterlist *dst,
+                          struct scatterlist *src,
+                          unsigned int nbytes, u8 *iv)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             cbc_process, 0, iv);
 }
 
 static int nocrypt(struct crypto_tfm *tfm,
@@ -290,6 +323,14 @@
 	return -ENOSYS;
 }
 
+static int nocrypt_iv(struct crypto_tfm *tfm,
+                      struct scatterlist *dst,
+                      struct scatterlist *src,
+                      unsigned int nbytes, u8 *iv)
+{
+	return -ENOSYS;
+}
+
 int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
 {
 	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
@@ -318,16 +359,22 @@
 	case CRYPTO_TFM_MODE_CBC:
 		ops->cit_encrypt = cbc_encrypt;
 		ops->cit_decrypt = cbc_decrypt;
+		ops->cit_encrypt_iv = cbc_encrypt_iv;
+		ops->cit_decrypt_iv = cbc_decrypt_iv;
 		break;
 		
 	case CRYPTO_TFM_MODE_CFB:
 		ops->cit_encrypt = nocrypt;
 		ops->cit_decrypt = nocrypt;
+		ops->cit_encrypt_iv = nocrypt_iv;
+		ops->cit_decrypt_iv = nocrypt_iv;
 		break;
 	
 	case CRYPTO_TFM_MODE_CTR:
 		ops->cit_encrypt = nocrypt;
 		ops->cit_decrypt = nocrypt;
+		ops->cit_encrypt_iv = nocrypt_iv;
+		ops->cit_decrypt_iv = nocrypt_iv;
 		break;
 
 	default:
diff -Nru a/crypto/digest.c b/crypto/digest.c
--- a/crypto/digest.c	Sun Feb  2 23:34:59 2003
+++ b/crypto/digest.c	Sat Mar  8 11:46:18 2003
@@ -19,7 +19,7 @@
 
 static void init(struct crypto_tfm *tfm)
 {
-	tfm->__crt_alg->cra_digest.dia_init(tfm->crt_ctx);
+	tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm));
 }
 
 static void update(struct crypto_tfm *tfm,
@@ -29,7 +29,7 @@
 	
 	for (i = 0; i < nsg; i++) {
 		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
+		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
 		                                      p, sg[i].length);
 		crypto_kunmap(p, 0);
 		crypto_yield(tfm);
@@ -38,7 +38,7 @@
 
 static void final(struct crypto_tfm *tfm, u8 *out)
 {
-	tfm->__crt_alg->cra_digest.dia_final(tfm->crt_ctx, out);
+	tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
 }
 
 static void digest(struct crypto_tfm *tfm,
@@ -50,7 +50,7 @@
 		
 	for (i = 0; i < nsg; i++) {
 		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
+		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
 		                                      p, sg[i].length);
 		crypto_kunmap(p, 0);
 		crypto_yield(tfm);
diff -Nru a/crypto/internal.h b/crypto/internal.h
--- a/crypto/internal.h	Sun Feb  2 23:34:59 2003
+++ b/crypto/internal.h	Sat Mar  8 11:46:18 2003
@@ -18,18 +18,12 @@
 #include <asm/softirq.h>
 #include <asm/kmap_types.h>
 
-static enum km_type km_types[] = {
-	KM_USER0,
-	KM_USER1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-};
+extern enum km_type crypto_km_types[];
 
 static inline enum km_type crypto_kmap_type(int out)
 {
-	return km_types[(in_softirq() ? 2 : 0) + out];
+	return crypto_km_types[(in_softirq() ? 2 : 0) + out];
 }
-	
 
 static inline void *crypto_kmap(struct page *page, int out)
 {
@@ -50,6 +44,11 @@
 static inline u32 crypto_cipher_flags(u32 flags)
 {
 	return flags & (CRYPTO_TFM_MODE_MASK|CRYPTO_TFM_REQ_WEAK_KEY);
+}
+
+static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
+{
+	return (void *)&tfm[1];
 }
 
 struct crypto_alg *crypto_alg_lookup(const char *name);
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Sat Feb 15 01:15:00 2003
+++ b/drivers/Makefile	Mon Mar 10 22:34:21 2003
@@ -11,9 +11,13 @@
 # PnP must come after ACPI since it will eventually need to check if acpi
 # was used and do nothing if so
 obj-$(CONFIG_PNP)		+= pnp/
+
+# char/ comes before serial/ etc so that the VT console is the boot-time
+# default.
+obj-y				+= char/
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
-obj-y				+= base/ char/ block/ misc/ net/ media/
+obj-y				+= base/ block/ misc/ net/ media/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_IDE)		+= ide/
diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
--- a/drivers/acorn/block/fd1772.c	Tue Feb 25 10:27:18 2003
+++ b/drivers/acorn/block/fd1772.c	Sat Mar  8 14:50:21 2003
@@ -1539,11 +1539,9 @@
 			goto err_disk;
 	}
 
-	err = register_blkdev(MAJOR_NR, "fd", &floppy_fops);
-	if (err) {
-		printk("Unable to get major %d for floppy\n", MAJOR_NR);
+	err = register_blkdev(MAJOR_NR, "fd");
+	if (err)
 		goto err_disk;
-	}
 
 	err = -EBUSY;
 	if (request_dma(FLOPPY_DMA, "fd1772")) {
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Tue Feb 25 10:27:22 2003
+++ b/drivers/acorn/block/mfmhd.c	Sat Mar  8 14:50:21 2003
@@ -1267,11 +1267,9 @@
 	if (!request_region (mfm_addr, 10, "mfm"))
 		goto out1;
 
-	ret = register_blkdev(MAJOR_NR, "mfm", &mfm_fops);
-	if (ret) {
-		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
+	ret = register_blkdev(MAJOR_NR, "mfm");
+	if (ret)
 		goto out2;
-	}
 
 	/* Stuff for the assembler routines to get to */
 	hdc63463_baseaddress	= ioaddr(mfm_addr);
diff -Nru a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c
--- a/drivers/acorn/net/ether1.c	Sun Nov 17 13:36:31 2002
+++ b/drivers/acorn/net/ether1.c	Thu Mar  6 05:00:32 2003
@@ -973,23 +973,6 @@
 	return &priv->stats;
 }
 
-static int
-ether1_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	/*
-	 * We'll set the MAC address on the chip when we open it.
-	 */
-
-	return 0;
-}
-
 /*
  * Set or clear the multicast filter for this adaptor.
  * num_addrs == -1	Promiscuous mode, receive all packets.
@@ -1062,7 +1045,6 @@
 	dev->hard_start_xmit    = ether1_sendpacket;
 	dev->get_stats		= ether1_getstats;
 	dev->set_multicast_list = ether1_setmulticastlist;
-	dev->set_mac_address	= ether1_set_mac_address;
 	dev->tx_timeout		= ether1_timeout;
 	dev->watchdog_timeo	= 5 * HZ / 100;
 
diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c
--- a/drivers/acorn/net/ether3.c	Tue Feb 25 10:47:06 2003
+++ b/drivers/acorn/net/ether3.c	Thu Mar  6 05:00:32 2003
@@ -461,23 +461,6 @@
 	return &priv->stats;
 }
 
-static int
-ether3_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	/*
-	 * We'll set the MAC address on the chip when we open it.
-	 */
-
-	return 0;
-}
-
 /*
  * Set or clear promiscuous/multicast mode filter for this adaptor.
  *
@@ -903,7 +886,6 @@
 	dev->hard_start_xmit	= ether3_sendpacket;
 	dev->get_stats		= ether3_getstats;
 	dev->set_multicast_list	= ether3_setmulticastlist;
-	dev->set_mac_address	= ether3_set_mac_address;
 	dev->tx_timeout		= ether3_timeout;
 	dev->watchdog_timeo	= 5 * HZ / 100;
 
diff -Nru a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c
--- a/drivers/acorn/net/etherh.c	Sun Nov 17 13:36:32 2002
+++ b/drivers/acorn/net/etherh.c	Thu Mar  6 05:00:33 2003
@@ -482,23 +482,6 @@
 	return 0;
 }
 
-static int
-etherh_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	/*
-	 * We'll set the MAC address on the chip when we open it.
-	 */
-
-	return 0;
-}
-
 /*
  * Initialisation
  */
@@ -585,7 +568,6 @@
 
 	dev->open		= etherh_open;
 	dev->stop		= etherh_close;
-	dev->set_mac_address	= etherh_set_mac_address;
 	dev->set_config		= etherh_set_config;
 	dev->irq		= ec->irq;
 	dev->base_addr		= ecard_address(ec, ECARD_MEMC, 0);
diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile
--- a/drivers/atm/Makefile	Mon Feb  3 14:19:36 2003
+++ b/drivers/atm/Makefile	Sat Mar  8 13:46:23 2003
@@ -46,7 +46,7 @@
 ifeq ($(CONFIG_ATM_FORE200E_SBA),y)
   fore_200e-objs		+= fore200e_sba_fw.o
   ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y)
-    CONFIG_ATM_FORE200E_SBA_FW	:= sba200e_ecd.bin2
+    CONFIG_ATM_FORE200E_SBA_FW	:= $(obj)/sba200e_ecd.bin2
   endif
 endif
 
diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c
--- a/drivers/atm/firestream.c	Tue Feb 25 10:47:34 2003
+++ b/drivers/atm/firestream.c	Thu Mar  6 09:14:50 2003
@@ -1792,7 +1792,7 @@
 		write_fs (dev, RAC, 0);
 
 		/* Manual (AN9, page 6) says ASF1=0 means compare Utopia address
-		 * too.  I can't find ASF1 anywhere. Anyway, we AND with just hte
+		 * too.  I can't find ASF1 anywhere. Anyway, we AND with just the
 		 * other bits, then compare with 0, which is exactly what we
 		 * want. */
 		write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1);
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	Tue Mar  4 08:13:43 2003
+++ b/drivers/base/bus.c	Tue Mar 11 14:00:28 2003
@@ -282,23 +282,25 @@
  *	Walk the list of drivers that the bus has and call bus_match() 
  *	for each pair. If a compatible pair is found, break out and return.
  */
-static void device_attach(struct device * dev)
+static int device_attach(struct device * dev)
 {
  	struct bus_type * bus = dev->bus;
 	struct list_head * entry;
 
 	if (dev->driver) {
 		device_bind_driver(dev);
-		return;
+		return 1;
 	}
 
 	if (bus->match) {
 		list_for_each(entry,&bus->drivers.list) {
 			struct device_driver * drv = to_drv(entry);
 			if (!bus_match(dev,drv))
-				break;
+				return 1;
 		}
 	}
+
+	return 0;
 }
 
 
@@ -476,6 +478,38 @@
 	}
 }
 
+
+/* Helper for bus_rescan_devices's iter */
+static int bus_rescan_devices_helper(struct device *dev, void *data)
+{
+	int *count = data;
+
+	if (!dev->driver && device_attach(dev))
+		(*count)++;
+
+	return 0;
+}
+
+
+/**
+ *	bus_rescan_devices - rescan devices on the bus for possible drivers
+ *	@bus:	the bus to scan.
+ *
+ *	This function will look for devices on the bus with no driver
+ *	attached and rescan it against existing drivers to see if it
+ *	matches any. Calls device_attach(). Returns the number of devices
+ *	that were sucessfully bound to a driver.
+ */
+int bus_rescan_devices(struct bus_type * bus)
+{
+	int count = 0;
+
+	bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
+
+	return count;
+}
+
+
 struct bus_type * get_bus(struct bus_type * bus)
 {
 	return bus ? container_of(subsys_get(&bus->subsys),struct bus_type,subsys) : NULL;
@@ -560,6 +594,7 @@
 EXPORT_SYMBOL(bus_remove_device);
 EXPORT_SYMBOL(bus_register);
 EXPORT_SYMBOL(bus_unregister);
+EXPORT_SYMBOL(bus_rescan_devices);
 EXPORT_SYMBOL(get_bus);
 EXPORT_SYMBOL(put_bus);
 EXPORT_SYMBOL(find_bus);
diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	Tue Mar  4 08:20:34 2003
+++ b/drivers/base/platform.c	Fri Mar 14 19:52:55 2003
@@ -9,7 +9,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-static struct device legacy_bus = {
+struct device legacy_bus = {
 	.name		= "legacy bus",
 	.bus_id		= "legacy",
 };
@@ -59,12 +59,9 @@
 
 static int platform_match(struct device * dev, struct device_driver * drv)
 {
-	char name[BUS_ID_SIZE];
+	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
 
-	if (sscanf(dev->bus_id,"%s",name))
-		return (strcmp(name,drv->name) == 0);
-
-	return 0;
+	return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
 }
 
 struct bus_type platform_bus_type = {
@@ -78,5 +75,7 @@
 	return bus_register(&platform_bus_type);
 }
 
+EXPORT_SYMBOL(legacy_bus);
+EXPORT_SYMBOL(platform_bus_type);
 EXPORT_SYMBOL(platform_device_register);
 EXPORT_SYMBOL(platform_device_unregister);
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Mon Feb 10 19:20:39 2003
+++ b/drivers/block/DAC960.c	Sat Mar  8 14:50:22 2003
@@ -13,9 +13,6 @@
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for complete details.
 
-  The author respectfully requests that any modifications to this software be
-  sent directly to him for evaluation and testing.
-
 */
 
 
@@ -2381,13 +2378,9 @@
   /*
     Register the Block Device Major Number for this DAC960 Controller.
   */
-  if (register_blkdev(MajorNumber, "dac960",
-			    &DAC960_BlockDeviceOperations) < 0)
-    {
-      DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
-		   Controller, MajorNumber);
+  if (register_blkdev(MajorNumber, "dac960") < 0)
       return false;
-    }
+
   /*
     Initialize the I/O Request Queue.
   */
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Thu Nov  7 15:02:52 2002
+++ b/drivers/block/acsi.c	Sat Mar  8 14:50:22 2003
@@ -1613,7 +1613,6 @@
 
 
 int acsi_init( void )
-
 {
 	int err = 0;
 	int i, target, lun;
@@ -1623,8 +1622,7 @@
 #endif
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
 		return 0;
-	if (register_blkdev( ACSI_MAJOR, "ad", &acsi_fops )) {
-		printk( KERN_ERR "Unable to get major %d for ACSI\n", ACSI_MAJOR );
+	if (register_blkdev(ACSI_MAJOR, "ad")) {
 		err = -EBUSY;
 		goto out1;
 	}
diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c
--- a/drivers/block/amiflop.c	Mon Nov 18 07:04:31 2002
+++ b/drivers/block/amiflop.c	Sat Mar  8 14:50:22 2003
@@ -1754,10 +1754,9 @@
 	if (!AMIGAHW_PRESENT(AMI_FLOPPY))
 		return -ENXIO;
 
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk("fd: Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd"))
 		return -EBUSY;
-	}
+
 	/*
 	 *  We request DSKPTR, DSKLEN and DSKDATA only, because the other
 	 *  floppy registers are too spreaded over the custom register space
diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c
--- a/drivers/block/ataflop.c	Mon Nov 11 05:05:00 2002
+++ b/drivers/block/ataflop.c	Sat Mar  8 14:50:22 2003
@@ -1929,10 +1929,8 @@
 		/* Hades doesn't have Atari-compatible floppy */
 		return -ENXIO;
 
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk(KERN_ERR "Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd"))
 		return -EBUSY;
-	}
 
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].disk = alloc_disk(1);
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Thu Feb 27 17:05:57 2003
+++ b/drivers/block/cciss.c	Sat Mar  8 14:50:22 2003
@@ -2064,7 +2064,7 @@
 	unchar cache_line_size, latency_timer;
 	unchar irq, revision;
 	uint addr[6];
-	__u32 board_id;
+	__u32 board_id, scratchpad = 0;
 	int cfg_offset;
 	int cfg_base_addr;
 	int cfg_base_addr_index;
@@ -2156,6 +2156,20 @@
 #endif /* CCISS_DEBUG */ 
 	c->vaddr = remap_pci_mem(c->paddr, 200);
 
+	/* Wait for the board to become ready.  (PCI hotplug needs this.)
+	 * We poll for up to 120 secs, once per 100ms. */
+	for (i=0; i < 1200; i++) {
+		scratchpad = readl(c->vaddr + SA5_SCRATCHPAD_OFFSET);
+		if (scratchpad == CCISS_FIRMWARE_READY)
+			break;
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ / 10); /* wait 100ms */
+	}
+	if (scratchpad != CCISS_FIRMWARE_READY) {
+		printk(KERN_WARNING "cciss: Board not ready.  Timed out.\n");
+		return -1;
+	}
+
 	/* get the address index number */
 	cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET);
 	/* I am not prepared to deal with a 64 bit address value */
@@ -2437,14 +2451,12 @@
 		return -ENODEV;
 	}
 
-	if( register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname, &cciss_fops))
-	{
-		printk(KERN_ERR "cciss:  Unable to get major number "
-			"%d for %s\n", COMPAQ_CISS_MAJOR+i, hba[i]->devname);
+	if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) {
 		release_io_mem(hba[i]);
 		free_hba(i);
-		return(-1);
+		return -1;
 	}
+
 	/* make sure the board interrupts are off */
 	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
 	if( request_irq(hba[i]->intr, do_cciss_intr, 
diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h
--- a/drivers/block/cciss.h	Thu Dec  5 08:03:43 2002
+++ b/drivers/block/cciss.h	Mon Mar  3 13:52:06 2003
@@ -95,6 +95,7 @@
 #define SA5_REPLY_INTR_MASK_OFFSET	0x34
 #define SA5_REPLY_PORT_OFFSET		0x44
 #define SA5_INTR_STATUS		0x30
+#define SA5_SCRATCHPAD_OFFSET	0xB0
 
 #define SA5_CTCFG_OFFSET	0xB4
 #define SA5_CTMEM_OFFSET	0xB8
@@ -104,6 +105,7 @@
 #define SA5_INTR_PENDING	0x08
 #define SA5B_INTR_PENDING	0x04
 #define FIFO_EMPTY		0xffffffff	
+#define CCISS_FIRMWARE_READY	0xffff0000 /* value in scratchpad register */
 
 #define  CISS_ERROR_BIT		0x02
 
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Tue Feb 25 11:05:27 2003
+++ b/drivers/block/cpqarray.c	Sat Mar  8 14:50:22 2003
@@ -339,11 +339,9 @@
 	for(i=0; i < nr_ctlr; i++) {
 	  	/* If this successful it should insure that we are the only */
 		/* instance of the driver */	
-		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname, &ida_fops)) {
-                        printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n",
-                                COMPAQ_SMART2_MAJOR+i);
+		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname))
                         continue;
-                }
+
 		hba[i]->access.set_intr_mask(hba[i], 0);
 		if (request_irq(hba[i]->intr, do_ida_intr,
 			SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Tue Feb 18 10:44:43 2003
+++ b/drivers/block/floppy.c	Sat Mar  8 14:50:22 2003
@@ -4232,8 +4232,7 @@
 	}
 
 	devfs_mk_dir (NULL, "floppy", NULL);
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk("Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd")) {
 		err = -EBUSY;
 		goto out;
 	}
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Mon Feb 24 23:13:25 2003
+++ b/drivers/block/genhd.c	Mon Mar 10 11:47:07 2003
@@ -14,10 +14,16 @@
 #include <linux/slab.h>
 #include <linux/kmod.h>
 
+#define MAX_PROBE_HASH 255	/* random */
 
 static struct subsystem block_subsys;
 
-#define MAX_PROBE_HASH 23	/* random */
+/* Can be merged with blk_probe or deleted altogether. Later. */
+static struct blk_major_name {
+	struct blk_major_name *next;
+	int major;
+	char name[16];
+} *major_names[MAX_PROBE_HASH];
 
 static struct blk_probe {
 	struct blk_probe *next;
@@ -30,9 +36,125 @@
 } *probes[MAX_PROBE_HASH];
 
 /* index in the above - for now: assume no multimajor ranges */
+static inline int major_to_index(int major)
+{
+	return major % MAX_PROBE_HASH;
+}
+
 static inline int dev_to_index(dev_t dev)
 {
-	return MAJOR(dev) % MAX_PROBE_HASH;
+	return major_to_index(MAJOR(dev));
+}
+
+const char *__bdevname(dev_t dev)
+{
+	static char buffer[40];
+	char *name = "unknown-block";
+	unsigned int major = MAJOR(dev);
+	unsigned int minor = MINOR(dev);
+	int index = major_to_index(major);
+	struct blk_major_name *n;
+
+	down_read(&block_subsys.rwsem);
+	for (n = major_names[index]; n; n = n->next)
+		if (n->major == major)
+			break;
+	if (n)
+		name = &(n->name[0]);
+	sprintf(buffer, "%s(%u,%u)", name, major, minor);
+	up_read(&block_subsys.rwsem);
+
+	return buffer;
+}
+
+/* get block device names in somewhat random order */
+int get_blkdev_list(char *p)
+{
+	struct blk_major_name *n;
+	int i, len;
+
+	len = sprintf(p, "\nBlock devices:\n");
+
+	down_read(&block_subsys.rwsem);
+	for (i = 0; i < ARRAY_SIZE(major_names); i++) {
+		for (n = major_names[i]; n; n = n->next)
+			len += sprintf(p+len, "%3d %s\n",
+				       n->major, n->name);
+	}
+	up_read(&block_subsys.rwsem);
+
+	return len;
+}
+
+int register_blkdev(unsigned int major, const char *name)
+{
+	struct blk_major_name **n, *p;
+	int index, ret = 0;
+
+	/* temporary */
+	if (major == 0) {
+		down_read(&block_subsys.rwsem);
+		for (index = ARRAY_SIZE(major_names)-1; index > 0; index--)
+			if (major_names[index] == NULL)
+				break;
+		up_read(&block_subsys.rwsem);
+
+		if (index == 0) {
+			printk("register_blkdev: failed to get major for %s\n",
+			       name);
+			return -EBUSY;
+		}
+		ret = major = index;
+	}
+
+	p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL);
+	if (p == NULL)
+		return -ENOMEM;
+
+	p->major = major;
+	strncpy(p->name, name, sizeof(p->name)-1);
+	p->name[sizeof(p->name)-1] = 0;
+	p->next = 0;
+	index = major_to_index(major);
+
+	down_write(&block_subsys.rwsem);
+	for (n = &major_names[index]; *n; n = &(*n)->next)
+		if ((*n)->major == major)
+			break;
+	if (!*n)
+		*n = p;
+	else
+		ret = -EBUSY;
+	up_write(&block_subsys.rwsem);
+
+	if (ret < 0)
+		printk("register_blkdev: cannot get major %d for %s\n",
+		       major, name);
+
+	return ret;
+}
+
+/* todo: make void - error printk here */
+int unregister_blkdev(unsigned int major, const char *name)
+{
+	struct blk_major_name **n, *p;
+	int index = major_to_index(major);
+	int ret = 0;
+
+	down_write(&block_subsys.rwsem);
+	for (n = &major_names[index]; *n; n = &(*n)->next)
+		if ((*n)->major == major)
+			break;
+	if (!*n || strcmp((*n)->name, name))
+		ret = -EINVAL;
+	else {
+		p = *n;
+		*n = p->next;
+		kfree(p);
+	}
+	up_write(&block_subsys.rwsem);
+
+	return ret;
 }
 
 /*
@@ -48,6 +170,9 @@
 	struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
 	struct blk_probe **s;
 
+	if (p == NULL)
+		return;
+
 	p->owner = module;
 	p->get = probe;
 	p->lock = lock;
@@ -98,9 +223,9 @@
 
 /**
  * add_gendisk - add partitioning information to kernel list
- * @gp: per-device partitioning information
+ * @disk: per-device partitioning information
  *
- * This function registers the partitioning information in @gp
+ * This function registers the partitioning information in @disk
  * with the kernel.
  */
 void add_disk(struct gendisk *disk)
@@ -318,7 +443,7 @@
 	return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ;
 #endif
 }
-static ssize_t disk_stat_read(struct gendisk * disk, char *page)
+static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
 	disk_round_stats(disk);
 	return sprintf(page,
@@ -326,14 +451,16 @@
 		"%8u %8u %8llu %8u "
 		"%8u %8u %8u"
 		"\n",
-		disk->reads, disk->read_merges,
-		(unsigned long long)disk->read_sectors,
-		jiffies_to_msec(disk->read_ticks),
-		disk->writes, disk->write_merges,
-		(unsigned long long)disk->write_sectors,
-		jiffies_to_msec(disk->write_ticks),
-		disk->in_flight, jiffies_to_msec(disk->io_ticks),
-		jiffies_to_msec(disk->time_in_queue));
+		disk_stat_read(disk, reads), disk_stat_read(disk, read_merges),
+		(unsigned long long)disk_stat_read(disk, read_sectors),
+		jiffies_to_msec(disk_stat_read(disk, read_ticks)),
+		disk_stat_read(disk, writes), 
+		disk_stat_read(disk, write_merges),
+		(unsigned long long)disk_stat_read(disk, write_sectors),
+		jiffies_to_msec(disk_stat_read(disk, write_ticks)),
+		disk_stat_read(disk, in_flight), 
+		jiffies_to_msec(disk_stat_read(disk, io_ticks)),
+		jiffies_to_msec(disk_stat_read(disk, time_in_queue)));
 }
 static struct disk_attribute disk_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
@@ -349,7 +476,7 @@
 };
 static struct disk_attribute disk_attr_stat = {
 	.attr = {.name = "stat", .mode = S_IRUGO },
-	.show	= disk_stat_read
+	.show	= disk_stats_read
 };
 
 static struct attribute * default_attrs[] = {
@@ -365,6 +492,7 @@
 	struct gendisk *disk = to_disk(kobj);
 	kfree(disk->random);
 	kfree(disk->part);
+	free_disk_stats(disk);
 	kfree(disk);
 }
 
@@ -384,6 +512,10 @@
 	struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
 	if (disk) {
 		memset(disk, 0, sizeof(struct gendisk));
+		if (!init_disk_stats(disk)) {
+			kfree(disk);
+			return NULL;
+		}
 		if (minors > 1) {
 			int size = (minors - 1) * sizeof(struct hd_struct);
 			disk->part = kmalloc(size, GFP_KERNEL);
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Tue Feb 25 10:47:06 2003
+++ b/drivers/block/ll_rw_blk.c	Tue Mar 11 07:04:00 2003
@@ -1040,7 +1040,8 @@
 
 static void blk_unplug_work(void *data)
 {
-	generic_unplug_device(data);
+	request_queue_t *q = data;
+	q->unplug_fn(q);
 }
 
 static void blk_unplug_timeout(unsigned long data)
@@ -1475,17 +1476,17 @@
 		return;
 
 	if (rw == READ) {
-		rq->rq_disk->read_sectors += nr_sectors;
+		disk_stat_add(rq->rq_disk, read_sectors, nr_sectors);
 		if (!new_io)
-			rq->rq_disk->read_merges++;
+			disk_stat_inc(rq->rq_disk, read_merges);
 	} else if (rw == WRITE) {
-		rq->rq_disk->write_sectors += nr_sectors;
+		disk_stat_add(rq->rq_disk, write_sectors, nr_sectors);
 		if (!new_io)
-			rq->rq_disk->write_merges++;
+			disk_stat_inc(rq->rq_disk, write_merges);
 	}
 	if (new_io) {
 		disk_round_stats(rq->rq_disk);
-		rq->rq_disk->in_flight++;
+		disk_stat_inc(rq->rq_disk, in_flight);
 	}
 }
 
@@ -1525,11 +1526,12 @@
 {
 	unsigned long now = jiffies;
 
-	disk->time_in_queue += disk->in_flight * (now - disk->stamp);
+	disk_stat_add(disk, time_in_queue, 
+			disk_stat_read(disk, in_flight) * (now - disk->stamp));
 	disk->stamp = now;
 
-	if (disk->in_flight)
-		disk->io_ticks += (now - disk->stamp_idle);
+	if (disk_stat_read(disk, in_flight))
+		disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
 	disk->stamp_idle = now;
 }
 
@@ -1647,7 +1649,7 @@
 
 		if (req->rq_disk) {
 			disk_round_stats(req->rq_disk);
-			req->rq_disk->in_flight--;
+			disk_stat_dec(req->rq_disk, in_flight);
 		}
 
 		__blk_put_request(q, next);
@@ -2199,16 +2201,16 @@
 		unsigned long duration = jiffies - req->start_time;
 		switch (rq_data_dir(req)) {
 		    case WRITE:
-			disk->writes++;
-			disk->write_ticks += duration;
+			disk_stat_inc(disk, writes);
+			disk_stat_add(disk, write_ticks, duration);
 			break;
 		    case READ:
-			disk->reads++;
-			disk->read_ticks += duration;
+			disk_stat_inc(disk, reads);
+			disk_stat_add(disk, read_ticks, duration);
 			break;
 		}
 		disk_round_stats(disk);
-		disk->in_flight--;
+		disk_stat_dec(disk, in_flight);
 	}
 	__blk_put_request(req->q, req);
 }
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Sun Mar  2 18:13:25 2003
+++ b/drivers/block/loop.c	Sat Mar  8 14:50:22 2003
@@ -1017,11 +1017,8 @@
 		max_loop = 8;
 	}
 
-	if (register_blkdev(LOOP_MAJOR, "loop", &lo_fops)) {
-		printk(KERN_WARNING "Unable to get major number %d for loop"
-				    " device\n", LOOP_MAJOR);
+	if (register_blkdev(LOOP_MAJOR, "loop"))
 		return -EIO;
-	}
 
 	devfs_mk_dir(NULL, "loop", NULL);
 
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Thu Feb 13 09:34:46 2003
+++ b/drivers/block/nbd.c	Sat Mar  8 14:50:22 2003
@@ -564,9 +564,7 @@
 		nbd_dev[i].disk = disk;
 	}
 
-	if (register_blkdev(NBD_MAJOR, "nbd", &nbd_fops)) {
-		printk("Unable to get major number %d for NBD\n",
-		       NBD_MAJOR);
+	if (register_blkdev(NBD_MAJOR, "nbd")) {
 		err = -EIO;
 		goto out;
 	}
diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
--- a/drivers/block/paride/pcd.c	Thu Dec  5 08:07:02 2002
+++ b/drivers/block/paride/pcd.c	Sat Mar  8 14:50:22 2003
@@ -942,8 +942,7 @@
 	/* get the atapi capabilities page */
 	pcd_probe_capabilities();
 
-	if (register_blkdev(major, name, &pcd_bdops)) {
-		printk("pcd: unable to get major number %d\n", major);
+	if (register_blkdev(major, name)) {
 		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 			put_disk(cd->disk);
 		return -1;
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	Thu Dec  5 08:07:21 2002
+++ b/drivers/block/paride/pd.c	Sat Mar  8 14:50:22 2003
@@ -890,10 +890,9 @@
 {
 	if (disable)
 		return -1;
-	if (register_blkdev(major, name, &pd_fops)) {
-		printk("%s: unable to get major number %d\n", name, major);
+	if (register_blkdev(major, name))
 		return -1;
-	}
+
 	blk_init_queue(&pd_queue, do_pd_request, &pd_lock);
 	blk_queue_max_sectors(&pd_queue, cluster);
 
diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
--- a/drivers/block/paride/pf.c	Thu Dec  5 08:06:39 2002
+++ b/drivers/block/paride/pf.c	Sat Mar  8 14:50:22 2003
@@ -957,8 +957,7 @@
 		return -1;
 	pf_busy = 0;
 
-	if (register_blkdev(major, name, &pf_fops)) {
-		printk("pf_init: unable to get major number %d\n", major);
+	if (register_blkdev(major, name)) {
 		for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
 			put_disk(pf->disk);
 		return -1;
@@ -969,6 +968,7 @@
 
 	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
 		struct gendisk *disk = pf->disk;
+
 		if (!pf->present)
 			continue;
 		disk->private_data = pf;
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Thu Dec  5 07:58:13 2002
+++ b/drivers/block/ps2esdi.c	Sat Mar  8 14:50:22 2003
@@ -146,13 +146,10 @@
 
 	int error = 0;
 
-	/* register the device - pass the name, major number and operations
-	   vector .                                                 */
-	if (register_blkdev(PS2ESDI_MAJOR, "ed", &ps2esdi_fops)) {
-		printk("%s: Unable to get major number %d\n", DEVICE_NAME,
-				PS2ESDI_MAJOR);
+	/* register the device - pass the name and major number */
+	if (register_blkdev(PS2ESDI_MAJOR, "ed"))
 		return -1;
-	}
+
 	/* set up some global information - indicating device specific info */
 	blk_init_queue(&ps2esdi_queue, do_ps2esdi_request, &ps2esdi_lock);
 
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Sat Dec 14 09:40:55 2002
+++ b/drivers/block/rd.c	Sat Mar  8 14:50:22 2003
@@ -409,8 +409,7 @@
 			goto out;
 	}
 
-	if (register_blkdev(RAMDISK_MAJOR, "ramdisk", &rd_bd_op)) {
-		printk("RAMDISK: Could not get major %d", RAMDISK_MAJOR);
+	if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) {
 		err = -EIO;
 		goto out;
 	}
diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c
--- a/drivers/block/swim3.c	Thu Dec  5 07:57:01 2002
+++ b/drivers/block/swim3.c	Sat Mar  8 14:50:22 2003
@@ -1004,9 +1004,7 @@
 			goto out;
 	}
 
-	if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) {
-		printk(KERN_ERR"Unable to get major %d for floppy\n",
-				FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR, "fd")) {
 		err = -EBUSY;
 		goto out;
 	}
diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
--- a/drivers/block/swim_iop.c	Mon Nov 11 03:13:21 2002
+++ b/drivers/block/swim_iop.c	Sat Mar  8 14:50:22 2003
@@ -137,13 +137,12 @@
 	current_req = NULL;
 	floppy_count = 0;
 
-	if (!iop_ism_present) return -ENODEV;
+	if (!iop_ism_present)
+		return -ENODEV;
 
-	if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) {
-		printk(KERN_ERR "SWIM-IOP: Unable to get major %d for floppy\n",
-		       FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR, "fd"))
 		return -EBUSY;
-	}
+
 	blk_init_queue(&swim_queue, do_fd_request, &swim_iop_lock);
 	printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
 		DRIVER_VERSION);
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Fri Jan 10 17:00:19 2003
+++ b/drivers/block/umem.c	Sat Mar  8 14:50:22 2003
@@ -1145,11 +1145,9 @@
 	if (retval)
 		return -ENOMEM;
 
-	err = major_nr = register_blkdev(0, "umem", &mm_fops);
-	if (err < 0) {
-		printk(KERN_ERR "MM: Could not register block device\n");
+	err = major_nr = register_blkdev(0, "umem");
+	if (err < 0)
 		return -EIO;
-	}
 
 	for (i = 0; i < num_cards; i++) {
 		mm_gendisk[i] = alloc_disk(1 << MM_SHIFT);
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Thu Dec  5 07:53:02 2002
+++ b/drivers/block/xd.c	Sat Mar  8 14:50:22 2003
@@ -154,9 +154,9 @@
 
 #ifdef MODULE
 	for (i = 4; i > 0; i--)
-		if(((xd[i] = xd[i-1]) >= 0) && !count)
+		if (((xd[i] = xd[i-1]) >= 0) && !count)
 			count = i;
-	if((xd[0] = count))
+	if ((xd[0] = count))
 		do_xd_setup(xd);
 #endif
 
@@ -170,10 +170,9 @@
 	}
 
 	err = -EBUSY;
-	if (register_blkdev(XT_DISK_MAJOR,"xd",&xd_fops)) {
-		printk("xd: Unable to get major number %d\n",XT_DISK_MAJOR);
+	if (register_blkdev(XT_DISK_MAJOR, "xd"))
 		goto out1;
-	}
+
 	devfs_mk_dir(NULL, "xd", NULL);
 	blk_init_queue(&xd_queue, do_xd_request, &xd_lock);
 	if (xd_detect(&controller,&address)) {
diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c
--- a/drivers/block/z2ram.c	Wed Nov  6 08:13:59 2002
+++ b/drivers/block/z2ram.c	Sat Mar  8 14:50:22 2003
@@ -331,21 +331,18 @@
 static struct request_queue z2_queue;
 
 int __init 
-z2_init( void )
+z2_init(void)
 {
 
-    if ( !MACH_IS_AMIGA )
+    if (!MACH_IS_AMIGA)
 	return -ENXIO;
 
-    if ( register_blkdev( Z2RAM_MAJOR, DEVICE_NAME, &z2_fops ) )
-    {
-	printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n",
-	    Z2RAM_MAJOR );
+    if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
 	return -EBUSY;
-    }
+
     z2ram_gendisk = alloc_disk(1);
     if (!z2ram_gendisk) {
-	unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME );
+	unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
 	return -ENOMEM;
     }
     z2ram_gendisk->major = Z2RAM_MAJOR;
diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Tue Dec  3 09:50:14 2002
+++ b/drivers/cdrom/aztcd.c	Sat Mar  8 14:50:22 2003
@@ -1910,12 +1910,12 @@
 	azt_disk = alloc_disk(1);
 	if (!azt_disk)
 		goto err_out;
-	if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) {
-		printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech"
-		       " CD-ROM\n", MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR, "aztcd")) {
 		ret = -EIO;
 		goto err_out2;
 	}
+
 	blk_init_queue(&azt_queue, do_aztcd_request, &aztSpin);
 	blk_queue_hardsect_size(&azt_queue, 2048);
 	azt_disk->major = MAJOR_NR;
@@ -1931,7 +1931,7 @@
 	azt_invalidate_buffers();
 	aztPresent = 1;
 	aztCloseDoor();
-	return (0);
+	return 0;
 err_out2:
 	put_disk(azt_disk);
 err_out:
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Fri Oct 18 03:55:37 2002
+++ b/drivers/cdrom/cdu31a.c	Sat Mar  8 14:50:22 2003
@@ -3368,11 +3368,8 @@
 	if (!request_region(cdu31a_port, 4, "cdu31a"))
 		goto errout3;
 
-	if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) {
-		printk("Unable to get major %d for CDU-31a\n",
-		       MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "cdu31a"))
 		goto errout2;
-	}
 
 	disk = alloc_disk(1);
 	if (!disk)
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Mon Nov 11 05:59:04 2002
+++ b/drivers/cdrom/cm206.c	Sat Mar  8 14:50:22 2003
@@ -1489,10 +1489,10 @@
 		goto out_probe;
 	}
 	printk(".\n");
-	if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) {
-		printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR, "cm206"))
 		goto out_blkdev;
-	}
+
 	disk = alloc_disk(1);
 	if (!disk)
 		goto out_disk;
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Sat Dec  7 18:57:27 2002
+++ b/drivers/cdrom/gscd.c	Sat Mar  8 14:50:22 2003
@@ -959,12 +959,11 @@
 	gscd_disk->fops = &gscd_fops;
 	sprintf(gscd_disk->disk_name, "gscd");
 
-	if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
-		printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar "
-		       "CD-ROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "gscd")) {
 		ret = -EIO;
 		goto err_out2;
 	}
+
 	devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 		       S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
 
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	Sun Nov 17 11:28:18 2002
+++ b/drivers/cdrom/mcd.c	Sat Mar  8 14:50:22 2003
@@ -1068,8 +1068,7 @@
 		put_disk(disk);
 		return -EIO;
 	}
-	if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) {
-		printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "mcd")) {
 		put_disk(disk);
 		return -EIO;
 	}
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Mon Nov 18 06:04:22 2002
+++ b/drivers/cdrom/mcdx.c	Sat Mar  8 14:50:22 2003
@@ -1193,11 +1193,9 @@
 	}
 
 	xtrace(INIT, "init() register blkdev\n");
-	if (register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) {
+	if (register_blkdev(MAJOR_NR, "mcdx")) {
 		release_region((unsigned long) stuffp->wreg_data,
 			       MCDX_IO_SIZE);
-		xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR);
 		kfree(stuffp);
 		put_disk(disk);
 		return 1;
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Sun Nov 17 23:09:33 2002
+++ b/drivers/cdrom/optcd.c	Sat Mar  8 14:50:22 2003
@@ -2047,8 +2047,7 @@
 		put_disk(optcd_disk);
 		return -EIO;
 	}
-	if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) {
-		printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "optcd")) {
 		release_region(optcd_port, 4);
 		put_disk(optcd_disk);
 		return -EIO;
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Mon Feb 24 12:16:14 2003
+++ b/drivers/cdrom/sbpcd.c	Sat Mar  8 14:50:22 2003
@@ -5795,15 +5795,14 @@
 	OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
 #endif /* SOUND_BASE */
 
-	if (register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0)
-	{
-		msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, major_name)) {
 #ifdef MODULE
 		return -EIO;
 #else
 		goto init_done;
 #endif /* MODULE */
 	}
+
 	blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock);
 
 	devfs_mk_dir (NULL, "sbp", NULL);
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Fri Nov 15 11:38:00 2002
+++ b/drivers/cdrom/sjcd.c	Sat Mar  8 14:50:22 2003
@@ -1677,11 +1677,8 @@
 	printk("SJCD: sjcd=0x%x: ", sjcd_base);
 #endif
 
-	if (register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
-		printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n",
-		       MAJOR_NR);
-		return (-EIO);
-	}
+	if (register_blkdev(MAJOR_NR, "sjcd"))
+		return -EIO;
 
 	blk_init_queue(&sjcd_queue, do_sjcd_request, &sjcd_lock);
 	blk_queue_hardsect_size(&sjcd_queue, 2048);
diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
--- a/drivers/cdrom/sonycd535.c	Mon Dec 30 20:26:12 2002
+++ b/drivers/cdrom/sonycd535.c	Sat Mar  8 14:50:22 2003
@@ -1546,9 +1546,7 @@
 		printk("IRQ%d, ", tmp_irq);
 	printk("using %d byte buffer\n", sony_buffer_size);
 
-	if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
-		printk("Unable to get major %d for %s\n",
-				MAJOR_NR, CDU535_MESSAGE_NAME);
+	if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
 		err = -EIO;
 		goto out1;
 	}
diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
--- a/drivers/char/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/drivers/char/Kconfig	Thu Mar 13 15:51:14 2003
@@ -709,39 +709,20 @@
 
 	  If you're not sure, say N.
 
-config INTEL_RNG
-	tristate "Intel i8x0 Random Number Generator support"
+config HW_RANDOM
+	tristate "Intel/AMD/VIA HW Random Number Generator support"
 	depends on (X86 || IA64) && PCI
 	---help---
 	  This driver provides kernel-side support for the Random Number
-	  Generator hardware found on Intel i8xx-based motherboards.
+	  Generator hardware found on Intel i8xx-based motherboards,
+	  AMD 76x-based motherboards, and Via Nehemiah CPUs.
 
-	  Both a character driver, used to read() entropy data, and a timer
-	  function which automatically adds entropy directly into the
-	  kernel pool, are exported by this driver.
+	  Provides a character driver, used to read() entropy data.
 
 	  To compile this driver as a module ( = code which can be inserted in
 	  and removed from the running kernel whenever you want), say M here
 	  and read <file:Documentation/modules.txt>. The module will be called
-	  i810_rng.
-
-	  If unsure, say N.
-
-config AMD_RNG
-	tristate "AMD 768 Random Number Generator support"
-	depends on X86 && PCI
-	---help---
-	  This driver provides kernel-side support for the Random Number
-	  Generator hardware found on AMD 76x based motherboards.
-
-	  Both a character driver, used to read() entropy data, and a timer
-	  function which automatically adds entropy directly into the
-	  kernel pool, are exported by this driver.
-
-	  To compile this driver as a module ( = code which can be inserted in
-	  and removed from the running kernel whenever you want), say M here
-	  and read <file:Documentation/modules.txt>. The module will be called
-	  amd768_rng.
+	  hw_random.
 
 	  If unsure, say N.
 
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Mon Feb 24 18:26:01 2003
+++ b/drivers/char/Makefile	Thu Mar 13 15:24:01 2003
@@ -59,8 +59,7 @@
 obj-$(CONFIG_TOSHIBA) += toshiba.o
 obj-$(CONFIG_I8K) += i8k.o
 obj-$(CONFIG_DS1620) += ds1620.o
-obj-$(CONFIG_INTEL_RNG) += i810_rng.o
-obj-$(CONFIG_AMD_RNG) += amd768_rng.o
+obj-$(CONFIG_HW_RANDOM) += hw_random.o
 obj-$(CONFIG_QIC02_TAPE) += tpqic02.o
 obj-$(CONFIG_FTAPE) += ftape/
 obj-$(CONFIG_H8) += h8.o
diff -Nru a/drivers/char/amd768_rng.c b/drivers/char/amd768_rng.c
--- a/drivers/char/amd768_rng.c	Tue Nov  5 07:39:53 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,295 +0,0 @@
-/*
- 	Hardware driver for the AMD 768 Random Number Generator (RNG)
-	(c) Copyright 2001 Red Hat Inc <alan@redhat.com>
- 
- 	derived from
- 
-	Hardware driver for Intel i810 Random Number Generator (RNG)
-	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
-	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
-
-	Please read Documentation/i810_rng.txt for details on use.
-
-	----------------------------------------------------------
-	This software may be used and distributed according to the terms
-        of the GNU General Public License, incorporated herein by reference.
-
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/random.h>
-#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-
-/*
- * core module and version information
- */
-#define RNG_VERSION "0.1.0"
-#define RNG_MODULE_NAME "amd768_rng"
-#define RNG_DRIVER_NAME   RNG_MODULE_NAME " hardware driver " RNG_VERSION
-#define PFX RNG_MODULE_NAME ": "
-
-
-/*
- * debugging macros
- */
-#undef RNG_DEBUG /* define to enable copious debugging info */
-
-#ifdef RNG_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#undef RNG_NDEBUG        /* define to disable lightweight runtime checks */
-#ifdef RNG_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
-        if(!(expr)) {                                   \
-        printk( "Assertion failed! %s,%s,%s,line=%d\n", \
-        #expr,__FILE__,__FUNCTION__,__LINE__);          \
-        }
-#endif
-
-#define RNG_MISCDEV_MINOR		183 /* official */
-
-/*
- * various RNG status variables.  they are globals
- * as we only support a single RNG device
- */
-
-static u32 pmbase;			/* PMxx I/O base */
-static struct semaphore rng_open_sem;	/* Semaphore for serializing rng_open/release */
-
-
-/*
- * inlined helper functions for accessing RNG registers
- */
-
-static inline int rng_data_present (void)
-{
-      	return inl(pmbase+0xF4) & 1;
-}
-
-
-static inline int rng_data_read (void)
-{
-	return inl(pmbase+0xF0);
-}
-
-static int rng_dev_open (struct inode *inode, struct file *filp)
-{
-	if ((filp->f_mode & FMODE_READ) == 0)
-		return -EINVAL;
-	if (filp->f_mode & FMODE_WRITE)
-		return -EINVAL;
-
-	/* wait for device to become free */
-	if (filp->f_flags & O_NONBLOCK) {
-		if (down_trylock (&rng_open_sem))
-			return -EAGAIN;
-	} else {
-		if (down_interruptible (&rng_open_sem))
-			return -ERESTARTSYS;
-	}
-	return 0;
-}
-
-
-static int rng_dev_release (struct inode *inode, struct file *filp)
-{
-	up(&rng_open_sem);
-	return 0;
-}
-
-
-static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size,
-			     loff_t * offp)
-{
-	static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED;
-	int have_data;
-	u32 data = 0;
-	ssize_t ret = 0;
-
-	while (size) {
-		spin_lock(&rng_lock);
-
-		have_data = 0;
-		if (rng_data_present()) {
-			data = rng_data_read();
-			have_data = 4;
-		}
-
-		spin_unlock (&rng_lock);
-
-		while (have_data > 0) {
-			if (put_user((u8)data, buf++)) {
-				ret = ret ? : -EFAULT;
-				break;
-			}
-			size--;
-			ret++;
-			have_data--;
-			data>>=8;
-		}
-
-		if (filp->f_flags & O_NONBLOCK)
-			return ret ? : -EAGAIN;
-
-		if(need_resched())
-		{
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
-		}
-		else
-			udelay(200);	/* FIXME: We could poll for 250uS ?? */
-
-		if (signal_pending (current))
-			return ret ? : -ERESTARTSYS;
-	}
-	return ret;
-}
-
-
-static struct file_operations rng_chrdev_ops = {
-	.owner		= THIS_MODULE,
-	.open		= rng_dev_open,
-	.release	= rng_dev_release,
-	.read		= rng_dev_read,
-};
-
-
-static struct miscdevice rng_miscdev = {
-	RNG_MISCDEV_MINOR,
-	RNG_MODULE_NAME,
-	&rng_chrdev_ops,
-};
-
-
-/*
- * rng_init_one - look for and attempt to init a single RNG
- */
-static int __init rng_init_one (struct pci_dev *dev)
-{
-	int rc;
-	u8 rnen;
-
-	DPRINTK ("ENTER\n");
-
-	rc = misc_register (&rng_miscdev);
-	if (rc) {
-		printk (KERN_ERR PFX "cannot register misc device\n");
-		DPRINTK ("EXIT, returning %d\n", rc);
-		goto err_out;
-	}
-
-	pci_read_config_dword(dev, 0x58, &pmbase);
-
-	pmbase&=0x0000FF00;
-
-	if(pmbase == 0)
-	{
-		printk (KERN_ERR PFX "power management base not set\n");
-		DPRINTK ("EXIT, returning %d\n", rc);
-		goto err_out_free_miscdev;
-	}
-
-	pci_read_config_byte(dev, 0x40, &rnen);
-	rnen|=(1<<7);	/* RNG on */
-	pci_write_config_byte(dev, 0x40, rnen);
-
-	pci_read_config_byte(dev, 0x41, &rnen);
-	rnen|=(1<<7);	/* PMIO enable */
-	pci_write_config_byte(dev, 0x41, rnen);
-
-	printk(KERN_INFO PFX "AMD768 system management I/O registers at 0x%X.\n", pmbase);
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out_free_miscdev:
-	misc_deregister (&rng_miscdev);
-err_out:
-	return rc;
-}
-
-
-/*
- * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
- */
-static struct pci_device_id rng_pci_tbl[] __initdata = {
-	{ 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, },
-};
-MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
-
-
-MODULE_AUTHOR("Alan Cox, Jeff Garzik, Philipp Rumpf, Matt Sottek");
-MODULE_DESCRIPTION("AMD 768 Random Number Generator (RNG) driver");
-MODULE_LICENSE("GPL");
-
-
-/*
- * rng_init - initialize RNG module
- */
-static int __init rng_init (void)
-{
-	int rc;
-	struct pci_dev *pdev;
-
-	DPRINTK ("ENTER\n");
-
-	init_MUTEX (&rng_open_sem);
-
-	pci_for_each_dev(pdev) {
-		if (pci_match_device (rng_pci_tbl, pdev) != NULL)
-			goto match;
-	}
-
-	DPRINTK ("EXIT, returning -ENODEV\n");
-	return -ENODEV;
-
-match:
-	rc = rng_init_one (pdev);
-	if (rc)
-		return rc;
-
-	printk (KERN_INFO RNG_DRIVER_NAME " loaded\n");
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/*
- * rng_init - shutdown RNG module
- */
-static void __exit rng_cleanup (void)
-{
-	DPRINTK ("ENTER\n");
-	misc_deregister (&rng_miscdev);
-	DPRINTK ("EXIT\n");
-}
-
-
-module_init (rng_init);
-module_exit (rng_cleanup);
diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c
--- a/drivers/char/amiserial.c	Mon Feb  3 05:47:46 2003
+++ b/drivers/char/amiserial.c	Mon Mar  3 12:04:08 2003
@@ -2320,10 +2320,11 @@
 /*
  *	Register console.
  */
-void __init serial_console_init(void)
+static void __init amiserial_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(amiserial_console_init);
 #endif
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/decserial.c b/drivers/char/decserial.c
--- a/drivers/char/decserial.c	Mon Feb  4 23:45:05 2002
+++ b/drivers/char/decserial.c	Fri Feb 14 15:14:03 2003
@@ -75,7 +75,7 @@
 /* serial_console_init handles the special case of starting
  *   up the console on the serial port
  */
-void __init serial_console_init(void)
+static void __init decserial_console_init(void)
 {
 #if defined(CONFIG_ZS) && defined(CONFIG_DZ)
     if (IOASIC)
@@ -94,5 +94,6 @@
 
 #endif
 }
+console_initcall(decserial_console_init);
 
 #endif
diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
--- a/drivers/char/hvc_console.c	Tue Feb 11 14:57:50 2003
+++ b/drivers/char/hvc_console.c	Fri Feb 14 15:14:16 2003
@@ -346,11 +346,12 @@
 	.index		= -1,
 };
 
-int __init hvc_console_init(void)
+static int __init hvc_console_init(void)
 {
 	register_console(&hvc_con_driver);
 	return 0;
 }
+console_initcall(hvc_console_init);
 
 module_init(hvc_init);
 module_exit(hvc_exit);
diff -Nru a/drivers/char/hw_random.c b/drivers/char/hw_random.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/hw_random.c	Thu Mar 13 15:51:14 2003
@@ -0,0 +1,630 @@
+/*
+ 	Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+	(c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ 
+ 	derived from
+ 
+        Hardware driver for the AMD 768 Random Number Generator (RNG)
+        (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+
+ 	derived from
+ 
+	Hardware driver for Intel i810 Random Number Generator (RNG)
+	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+
+	Please read Documentation/hw_random.txt for details on use.
+
+	----------------------------------------------------------
+	This software may be used and distributed according to the terms
+        of the GNU General Public License, incorporated herein by reference.
+
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/miscdevice.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#ifdef __i386__
+#include <asm/msr.h>
+#include <asm/cpufeature.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+/*
+ * core module and version information
+ */
+#define RNG_VERSION "0.9.0"
+#define RNG_MODULE_NAME "hw_random"
+#define RNG_DRIVER_NAME   RNG_MODULE_NAME " hardware driver " RNG_VERSION
+#define PFX RNG_MODULE_NAME ": "
+
+
+/*
+ * debugging macros
+ */
+#undef RNG_DEBUG /* define to enable copious debugging info */
+
+#ifdef RNG_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define RNG_NDEBUG        /* define to disable lightweight runtime checks */
+#ifdef RNG_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+        if(!(expr)) {                                   \
+        printk( "Assertion failed! %s,%s,%s,line=%d\n", \
+        #expr,__FILE__,__FUNCTION__,__LINE__);          \
+        }
+#endif
+
+#define RNG_MISCDEV_MINOR		183 /* official */
+
+static int rng_dev_open (struct inode *inode, struct file *filp);
+static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size,
+			     loff_t * offp);
+
+static int __init intel_init (struct pci_dev *dev);
+static void intel_cleanup(void);
+static unsigned int intel_data_present (void);
+static u32 intel_data_read (void);
+
+static int __init amd_init (struct pci_dev *dev);
+static void amd_cleanup(void);
+static unsigned int amd_data_present (void);
+static u32 amd_data_read (void);
+
+static int __init via_init(struct pci_dev *dev);
+static void via_cleanup(void);
+static unsigned int via_data_present (void);
+static u32 via_data_read (void);
+
+struct rng_operations {
+	int (*init) (struct pci_dev *dev);
+	void (*cleanup) (void);
+	unsigned int (*data_present) (void);
+	u32 (*data_read) (void);
+	unsigned int n_bytes; /* number of bytes per ->data_read */
+};
+static struct rng_operations *rng_ops;
+
+static struct file_operations rng_chrdev_ops = {
+	.owner		= THIS_MODULE,
+	.open		= rng_dev_open,
+	.read		= rng_dev_read,
+};
+
+
+static struct miscdevice rng_miscdev = {
+	RNG_MISCDEV_MINOR,
+	RNG_MODULE_NAME,
+	&rng_chrdev_ops,
+};
+
+enum {
+	rng_hw_none,
+	rng_hw_intel,
+	rng_hw_amd,
+	rng_hw_via,
+};
+
+static struct rng_operations rng_vendor_ops[] __initdata = {
+	/* rng_hw_none */
+	{ },
+
+	/* rng_hw_intel */
+	{ intel_init, intel_cleanup, intel_data_present,
+	  intel_data_read, 1 },
+
+	/* rng_hw_amd */
+	{ amd_init, amd_cleanup, amd_data_present, amd_data_read, 4 },
+
+	/* rng_hw_via */
+	{ via_init, via_cleanup, via_data_present, via_data_read, 1 },
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id rng_pci_tbl[] __initdata = {
+	{ 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
+
+	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+
+	{ 0, },	/* terminate list */
+};
+MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
+
+
+/***********************************************************************
+ *
+ * Intel RNG operations
+ *
+ */
+
+/*
+ * RNG registers (offsets from rng_mem)
+ */
+#define INTEL_RNG_HW_STATUS			0
+#define         INTEL_RNG_PRESENT		0x40
+#define         INTEL_RNG_ENABLED		0x01
+#define INTEL_RNG_STATUS			1
+#define         INTEL_RNG_DATA_PRESENT		0x01
+#define INTEL_RNG_DATA				2
+
+/*
+ * Magic address at which Intel PCI bridges locate the RNG
+ */
+#define INTEL_RNG_ADDR				0xFFBC015F
+#define INTEL_RNG_ADDR_LEN			3
+
+/* token to our ioremap'd RNG register area */
+static void *rng_mem;
+
+static inline u8 intel_hwstatus (void)
+{
+	assert (rng_mem != NULL);
+	return readb (rng_mem + INTEL_RNG_HW_STATUS);
+}
+
+static inline u8 intel_hwstatus_set (u8 hw_status)
+{
+	assert (rng_mem != NULL);
+	writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS);
+	return intel_hwstatus ();
+}
+
+static unsigned int intel_data_present(void)
+{
+	assert (rng_mem != NULL);
+
+	return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ?
+		1 : 0;
+}
+
+static u32 intel_data_read(void)
+{
+	assert (rng_mem != NULL);
+
+	return readb (rng_mem + INTEL_RNG_DATA);
+}
+
+static int __init intel_init (struct pci_dev *dev)
+{
+	int rc;
+	u8 hw_status;
+
+	DPRINTK ("ENTER\n");
+
+	rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
+	if (rng_mem == NULL) {
+		printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");
+		rc = -EBUSY;
+		goto err_out;
+	}
+
+	/* Check for Intel 82802 */
+	hw_status = intel_hwstatus ();
+	if ((hw_status & INTEL_RNG_PRESENT) == 0) {
+		printk (KERN_ERR PFX "RNG not detected\n");
+		rc = -ENODEV;
+		goto err_out_free_map;
+	}
+
+	/* turn RNG h/w on, if it's off */
+	if ((hw_status & INTEL_RNG_ENABLED) == 0)
+		hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED);
+	if ((hw_status & INTEL_RNG_ENABLED) == 0) {
+		printk (KERN_ERR PFX "cannot enable RNG, aborting\n");
+		rc = -EIO;
+		goto err_out_free_map;
+	}
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+
+err_out_free_map:
+	iounmap (rng_mem);
+	rng_mem = NULL;
+err_out:
+	DPRINTK ("EXIT, returning %d\n", rc);
+	return rc;
+}
+
+static void intel_cleanup(void)
+{
+	u8 hw_status;
+
+	hw_status = intel_hwstatus ();
+	if (hw_status & INTEL_RNG_ENABLED)
+		intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED);
+	else
+		printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
+	iounmap(rng_mem);
+	rng_mem = NULL;
+}
+
+/***********************************************************************
+ *
+ * AMD RNG operations
+ *
+ */
+
+static u32 pmbase;			/* PMxx I/O base */
+static struct pci_dev *amd_dev;
+
+static unsigned int amd_data_present (void)
+{
+      	return inl(pmbase + 0xF4) & 1;
+}
+
+
+static u32 amd_data_read (void)
+{
+	return inl(pmbase + 0xF0);
+}
+
+static int __init amd_init (struct pci_dev *dev)
+{
+	int rc;
+	u8 rnen;
+
+	DPRINTK ("ENTER\n");
+
+	pci_read_config_dword(dev, 0x58, &pmbase);
+
+	pmbase &= 0x0000FF00;
+
+	if (pmbase == 0)
+	{
+		printk (KERN_ERR PFX "power management base not set\n");
+		rc = -EIO;
+		goto err_out;
+	}
+
+	pci_read_config_byte(dev, 0x40, &rnen);
+	rnen |= (1 << 7);	/* RNG on */
+	pci_write_config_byte(dev, 0x40, rnen);
+
+	pci_read_config_byte(dev, 0x41, &rnen);
+	rnen |= (1 << 7);	/* PMIO enable */
+	pci_write_config_byte(dev, 0x41, rnen);
+
+	printk(KERN_INFO PFX "AMD768 system management I/O registers at 0x%X.\n", pmbase);
+
+	amd_dev = dev;
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+
+err_out:
+	DPRINTK ("EXIT, returning %d\n", rc);
+	return rc;
+}
+
+static void amd_cleanup(void)
+{
+	u8 rnen;
+
+	pci_read_config_byte(amd_dev, 0x40, &rnen);
+	rnen &= ~(1 << 7);	/* RNG off */
+	pci_write_config_byte(amd_dev, 0x40, rnen);
+
+	/* FIXME: twiddle pmio, also? */
+}
+
+/***********************************************************************
+ *
+ * VIA RNG operations
+ *
+ */
+
+enum {
+	VIA_STRFILT_CNT_SHIFT	= 16,
+	VIA_STRFILT_FAIL	= (1 << 15),
+	VIA_STRFILT_ENABLE	= (1 << 14),
+	VIA_RAWBITS_ENABLE	= (1 << 13),
+	VIA_RNG_ENABLE		= (1 << 6),
+	VIA_XSTORE_CNT_MASK	= 0x0F,
+
+	VIA_RNG_CHUNK_8		= 0x00,	/* 64 rand bits, 64 stored bits */
+	VIA_RNG_CHUNK_4		= 0x01,	/* 32 rand bits, 32 stored bits */
+	VIA_RNG_CHUNK_4_MASK	= 0xFFFFFFFF,
+	VIA_RNG_CHUNK_2		= 0x02,	/* 16 rand bits, 32 stored bits */
+	VIA_RNG_CHUNK_2_MASK	= 0xFFFF,
+	VIA_RNG_CHUNK_1		= 0x03,	/* 8 rand bits, 32 stored bits */
+	VIA_RNG_CHUNK_1_MASK	= 0xFF,
+};
+
+u32 via_rng_datum;
+
+/*
+ * Investigate using the 'rep' prefix to obtain 32 bits of random data
+ * in one insn.  The upside is potentially better performance.  The
+ * downside is that the instruction becomes no longer atomic.  Due to
+ * this, just like familiar issues with /dev/random itself, the worst
+ * case of a 'rep xstore' could potentially pause a cpu for an
+ * unreasonably long time.  In practice, this condition would likely
+ * only occur when the hardware is failing.  (or so we hope :))
+ *
+ * Another possible performance boost may come from simply buffering
+ * until we have 4 bytes, thus returning a u32 at a time,
+ * instead of the current u8-at-a-time.
+ */
+
+static inline u32 xstore(u32 *addr, u32 edx_in)
+{
+	u32 eax_out;
+
+	asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
+		:"=m"(*addr), "=a"(eax_out)
+		:"D"(addr), "d"(edx_in));
+
+	return eax_out;
+}
+
+static unsigned int via_data_present(void)
+{
+	u32 bytes_out;
+
+	/* We choose the recommended 1-byte-per-instruction RNG rate,
+	 * for greater randomness at the expense of speed.  Larger
+	 * values 2, 4, or 8 bytes-per-instruction yield greater
+	 * speed at lesser randomness.
+	 *
+	 * If you change this to another VIA_CHUNK_n, you must also
+	 * change the ->n_bytes values in rng_vendor_ops[] tables.
+	 * VIA_CHUNK_8 requires further code changes.
+	 *
+	 * A copy of MSR_VIA_RNG is placed in eax_out when xstore
+	 * completes.
+	 */
+	via_rng_datum = 0; /* paranoia, not really necessary */
+	bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK;
+	if (bytes_out == 0)
+		return 0;
+
+	return 1;
+}
+
+static u32 via_data_read(void)
+{
+	return via_rng_datum;
+}
+
+static int __init via_init(struct pci_dev *dev)
+{
+	u32 lo, hi, old_lo;
+
+	/* Control the RNG via MSR.  Tread lightly and pay very close
+	 * close attention to values written, as the reserved fields
+	 * are documented to be "undefined and unpredictable"; but it
+	 * does not say to write them as zero, so I make a guess that
+	 * we restore the values we find in the register.
+	 */
+	rdmsr(MSR_VIA_RNG, lo, hi);
+
+	old_lo = lo;
+	lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
+	lo &= ~VIA_XSTORE_CNT_MASK;
+	lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
+	lo |= VIA_RNG_ENABLE;
+
+	if (lo != old_lo)
+		wrmsr(MSR_VIA_RNG, lo, hi);
+
+	/* perhaps-unnecessary sanity check; remove after testing if
+	   unneeded */
+	rdmsr(MSR_VIA_RNG, lo, hi);
+	if ((lo & VIA_RNG_ENABLE) == 0) {
+		printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void via_cleanup(void)
+{
+	u32 lo, hi;
+
+	rdmsr(MSR_VIA_RNG, lo, hi);
+	lo &= ~VIA_RNG_ENABLE;
+	wrmsr(MSR_VIA_RNG, lo, hi);
+}
+
+
+/***********************************************************************
+ *
+ * /dev/hwrandom character device handling (major 10, minor 183)
+ *
+ */
+
+static int rng_dev_open (struct inode *inode, struct file *filp)
+{
+	/* enforce read-only access to this chrdev */
+	if ((filp->f_mode & FMODE_READ) == 0)
+		return -EINVAL;
+	if (filp->f_mode & FMODE_WRITE)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size,
+			     loff_t * offp)
+{
+	static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED;
+	unsigned int have_data;
+	u32 data = 0;
+	ssize_t ret = 0;
+
+	while (size) {
+		spin_lock(&rng_lock);
+
+		have_data = 0;
+		if (rng_ops->data_present()) {
+			data = rng_ops->data_read();
+			have_data = rng_ops->n_bytes;
+		}
+
+		spin_unlock (&rng_lock);
+
+		while (have_data > 0) {
+			if (put_user((u8)data, buf++)) {
+				ret = ret ? : -EFAULT;
+				break;
+			}
+			size--;
+			ret++;
+			have_data--;
+			data>>=8;
+		}
+
+		if (filp->f_flags & O_NONBLOCK)
+			return ret ? : -EAGAIN;
+
+		if(need_resched())
+		{
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(1);
+		}
+		else
+			udelay(200);	/* FIXME: We could poll for 250uS ?? */
+
+		if (signal_pending (current))
+			return ret ? : -ERESTARTSYS;
+	}
+	return ret;
+}
+
+
+
+/*
+ * rng_init_one - look for and attempt to init a single RNG
+ */
+static int __init rng_init_one (struct pci_dev *dev)
+{
+	int rc;
+
+	DPRINTK ("ENTER\n");
+
+	assert(rng_ops != NULL);
+
+	rc = rng_ops->init(dev);
+	if (rc)
+		goto err_out;
+
+	rc = misc_register (&rng_miscdev);
+	if (rc) {
+		printk (KERN_ERR PFX "misc device register failed\n");
+		goto err_out_cleanup_hw;
+	}
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+
+err_out_cleanup_hw:
+	rng_ops->cleanup();
+err_out:
+	DPRINTK ("EXIT, returning %d\n", rc);
+	return rc;
+}
+
+
+
+MODULE_AUTHOR("The Linux Kernel team");
+MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL");
+
+
+/*
+ * rng_init - initialize RNG module
+ */
+static int __init rng_init (void)
+{
+	int rc;
+	struct pci_dev *pdev;
+	const struct pci_device_id *ent;
+
+	DPRINTK ("ENTER\n");
+
+	/* Probe for Intel, AMD RNGs */
+	pci_for_each_dev(pdev) {
+		ent = pci_match_device (rng_pci_tbl, pdev);
+		if (ent) {
+			rng_ops = &rng_vendor_ops[ent->driver_data];
+			goto match;
+		}
+	}
+
+#ifdef __i386__
+	/* Probe for VIA RNG */
+	if (cpu_has_xstore) {
+		rng_ops = &rng_vendor_ops[rng_hw_via];
+		pdev = NULL;
+		goto match;
+	}
+#endif
+
+	DPRINTK ("EXIT, returning -ENODEV\n");
+	return -ENODEV;
+
+match:
+	rc = rng_init_one (pdev);
+	if (rc)
+		return rc;
+
+	printk (KERN_INFO RNG_DRIVER_NAME " loaded\n");
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+/*
+ * rng_init - shutdown RNG module
+ */
+static void __exit rng_cleanup (void)
+{
+	DPRINTK ("ENTER\n");
+
+	misc_deregister (&rng_miscdev);
+
+	if (rng_ops->cleanup)
+		rng_ops->cleanup();
+
+	DPRINTK ("EXIT\n");
+}
+
+
+module_init (rng_init);
+module_exit (rng_cleanup);
diff -Nru a/drivers/char/i810_rng.c b/drivers/char/i810_rng.c
--- a/drivers/char/i810_rng.c	Tue Nov  5 07:39:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,404 +0,0 @@
-/*
-
-	Hardware driver for Intel i810 Random Number Generator (RNG)
-	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
-	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
-
-	Driver Web site:  http://sourceforge.net/projects/gkernel/
-
-	Please read Documentation/i810_rng.txt for details on use.
-
-	----------------------------------------------------------
-
-	This software may be used and distributed according to the terms
-        of the GNU General Public License, incorporated herein by reference.
-
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/random.h>
-#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-
-/*
- * core module and version information
- */
-#define RNG_VERSION "0.9.8"
-#define RNG_MODULE_NAME "i810_rng"
-#define RNG_DRIVER_NAME   RNG_MODULE_NAME " hardware driver " RNG_VERSION
-#define PFX RNG_MODULE_NAME ": "
-
-
-/*
- * debugging macros
- */
-#undef RNG_DEBUG /* define to enable copious debugging info */
-
-#ifdef RNG_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#undef RNG_NDEBUG        /* define to disable lightweight runtime checks */
-#ifdef RNG_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
-        if(!(expr)) {                                   \
-        printk( "Assertion failed! %s,%s,%s,line=%d\n", \
-        #expr,__FILE__,__FUNCTION__,__LINE__);          \
-        }
-#endif
-
-
-/*
- * RNG registers (offsets from rng_mem)
- */
-#define RNG_HW_STATUS			0
-#define		RNG_PRESENT		0x40
-#define		RNG_ENABLED		0x01
-#define RNG_STATUS			1
-#define		RNG_DATA_PRESENT	0x01
-#define RNG_DATA			2
-
-/*
- * Magic address at which Intel PCI bridges locate the RNG
- */
-#define RNG_ADDR			0xFFBC015F
-#define RNG_ADDR_LEN			3
-
-#define RNG_MISCDEV_MINOR		183 /* official */
-
-/*
- * various RNG status variables.  they are globals
- * as we only support a single RNG device
- */
-static void *rng_mem;			/* token to our ioremap'd RNG register area */
-static struct semaphore rng_open_sem;	/* Semaphore for serializing rng_open/release */
-
-
-/*
- * inlined helper functions for accessing RNG registers
- */
-static inline u8 rng_hwstatus (void)
-{
-	assert (rng_mem != NULL);
-	return readb (rng_mem + RNG_HW_STATUS);
-}
-
-static inline u8 rng_hwstatus_set (u8 hw_status)
-{
-	assert (rng_mem != NULL);
-	writeb (hw_status, rng_mem + RNG_HW_STATUS);
-	return rng_hwstatus ();
-}
-
-
-static inline int rng_data_present (void)
-{
-	assert (rng_mem != NULL);
-
-	return (readb (rng_mem + RNG_STATUS) & RNG_DATA_PRESENT) ? 1 : 0;
-}
-
-
-static inline int rng_data_read (void)
-{
-	assert (rng_mem != NULL);
-
-	return readb (rng_mem + RNG_DATA);
-}
-
-/*
- * rng_enable - enable the RNG hardware
- */
-
-static int rng_enable (void)
-{
-	int rc = 0;
-	u8 hw_status, new_status;
-
-	DPRINTK ("ENTER\n");
-
-	hw_status = rng_hwstatus ();
-
-	if ((hw_status & RNG_ENABLED) == 0) {
-		new_status = rng_hwstatus_set (hw_status | RNG_ENABLED);
-
-		if (new_status & RNG_ENABLED)
-			printk (KERN_INFO PFX "RNG h/w enabled\n");
-		else {
-			printk (KERN_ERR PFX "Unable to enable the RNG\n");
-			rc = -EIO;
-		}
-	}
-
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-/*
- * rng_disable - disable the RNG hardware
- */
-
-static void rng_disable(void)
-{
-	u8 hw_status, new_status;
-
-	DPRINTK ("ENTER\n");
-
-	hw_status = rng_hwstatus ();
-
-	if (hw_status & RNG_ENABLED) {
-		new_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED);
-	
-		if ((new_status & RNG_ENABLED) == 0)
-			printk (KERN_INFO PFX "RNG h/w disabled\n");
-		else {
-			printk (KERN_ERR PFX "Unable to disable the RNG\n");
-		}
-	}
-
-	DPRINTK ("EXIT\n");
-}
-
-static int rng_dev_open (struct inode *inode, struct file *filp)
-{
-	int rc;
-
-	if ((filp->f_mode & FMODE_READ) == 0)
-		return -EINVAL;
-	if (filp->f_mode & FMODE_WRITE)
-		return -EINVAL;
-
-	/* wait for device to become free */
-	if (filp->f_flags & O_NONBLOCK) {
-		if (down_trylock (&rng_open_sem))
-			return -EAGAIN;
-	} else {
-		if (down_interruptible (&rng_open_sem))
-			return -ERESTARTSYS;
-	}
-
-	rc = rng_enable ();
-	if (rc) {
-		up (&rng_open_sem);
-		return rc;
-	}
-
-	return 0;
-}
-
-
-static int rng_dev_release (struct inode *inode, struct file *filp)
-{
-	rng_disable ();
-	up (&rng_open_sem);
-	return 0;
-}
-
-
-static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size,
-			     loff_t * offp)
-{
-	static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED;
-	int have_data;
-	u8 data = 0;
-	ssize_t ret = 0;
-
-	while (size) {
-		spin_lock (&rng_lock);
-
-		have_data = 0;
-		if (rng_data_present ()) {
-			data = rng_data_read ();
-			have_data = 1;
-		}
-
-		spin_unlock (&rng_lock);
-
-		if (have_data) {
-			if (put_user (data, buf++)) {
-				ret = ret ? : -EFAULT;
-				break;
-			}
-			size--;
-			ret++;
-		}
-
-		if (filp->f_flags & O_NONBLOCK)
-			return ret ? : -EAGAIN;
-
-		if (need_resched())
-		{
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
-		}
-		else
-			udelay(200);
-
-		if (signal_pending (current))
-			return ret ? : -ERESTARTSYS;
-	}
-
-	return ret;
-}
-
-
-static struct file_operations rng_chrdev_ops = {
-	.owner		= THIS_MODULE,
-	.open		= rng_dev_open,
-	.release	= rng_dev_release,
-	.read		= rng_dev_read,
-};
-
-
-static struct miscdevice rng_miscdev = {
-	RNG_MISCDEV_MINOR,
-	RNG_MODULE_NAME,
-	&rng_chrdev_ops,
-};
-
-
-/*
- * rng_init_one - look for and attempt to init a single RNG
- */
-static int __init rng_init_one (struct pci_dev *dev)
-{
-	int rc;
-	u8 hw_status;
-
-	DPRINTK ("ENTER\n");
-
-	rc = misc_register (&rng_miscdev);
-	if (rc) {
-		printk (KERN_ERR PFX "cannot register misc device\n");
-		DPRINTK ("EXIT, returning %d\n", rc);
-		goto err_out;
-	}
-
-	rng_mem = ioremap (RNG_ADDR, RNG_ADDR_LEN);
-	if (rng_mem == NULL) {
-		printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");
-		DPRINTK ("EXIT, returning -EBUSY\n");
-		rc = -EBUSY;
-		goto err_out_free_miscdev;
-	}
-
-	/* Check for Intel 82802 */
-	hw_status = rng_hwstatus ();
-	if ((hw_status & RNG_PRESENT) == 0) {
-		printk (KERN_ERR PFX "RNG not detected\n");
-		DPRINTK ("EXIT, returning -ENODEV\n");
-		rc = -ENODEV;
-		goto err_out_free_map;
-	}
-
-	/* turn RNG h/w off, if it's on */
-	if (hw_status & RNG_ENABLED)
-		hw_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED);
-	if (hw_status & RNG_ENABLED) {
-		printk (KERN_ERR PFX "cannot disable RNG, aborting\n");
-		goto err_out_free_map;
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out_free_map:
-	iounmap (rng_mem);
-err_out_free_miscdev:
-	misc_deregister (&rng_miscdev);
-err_out:
-	return rc;
-}
-
-
-/*
- * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
- */
-static struct pci_device_id rng_pci_tbl[] __initdata = {
-	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, },
-};
-MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
-
-
-MODULE_AUTHOR("Jeff Garzik, Philipp Rumpf, Matt Sottek");
-MODULE_DESCRIPTION("Intel i8xx chipset Random Number Generator (RNG) driver");
-MODULE_LICENSE("GPL");
-
-
-/*
- * rng_init - initialize RNG module
- */
-static int __init rng_init (void)
-{
-	int rc;
-	struct pci_dev *pdev;
-
-	DPRINTK ("ENTER\n");
-
-	init_MUTEX (&rng_open_sem);
-
-	pci_for_each_dev(pdev) {
-		if (pci_match_device (rng_pci_tbl, pdev) != NULL)
-			goto match;
-	}
-
-	DPRINTK ("EXIT, returning -ENODEV\n");
-	return -ENODEV;
-
-match:
-	rc = rng_init_one (pdev);
-	if (rc)
-		return rc;
-
-	printk (KERN_INFO RNG_DRIVER_NAME " loaded\n");
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/*
- * rng_init - shutdown RNG module
- */
-static void __exit rng_cleanup (void)
-{
-	DPRINTK ("ENTER\n");
-
-	misc_deregister (&rng_miscdev);
-
-	iounmap (rng_mem);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-module_init (rng_init);
-module_exit (rng_cleanup);
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	Mon Feb 17 14:45:20 2003
+++ b/drivers/char/random.c	Mon Mar  3 04:08:26 2003
@@ -1228,10 +1228,8 @@
  * at which point we do a "catastrophic reseeding".
  */
 static inline void xfer_secondary_pool(struct entropy_store *r,
-				       size_t nbytes)
+				       size_t nbytes, __u32 *tmp)
 {
-	__u32	tmp[TMP_BUF_SIZE];
-
 	if (r->entropy_count < nbytes * 8 &&
 	    r->entropy_count < r->poolinfo.POOLBITS) {
 		int nwords = min_t(int,
@@ -1284,7 +1282,7 @@
 		r->entropy_count = r->poolinfo.POOLBITS;
 
 	if (flags & EXTRACT_ENTROPY_SECONDARY)
-		xfer_secondary_pool(r, nbytes);
+		xfer_secondary_pool(r, nbytes, tmp);
 
 	DEBUG_ENT("%s has %d bits, want %d bits\n",
 		  r == sec_random_state ? "secondary" :
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	Tue Jan  7 14:52:26 2003
+++ b/drivers/char/raw.c	Sat Mar  8 14:50:48 2003
@@ -19,14 +19,16 @@
 
 #include <asm/uaccess.h>
 
+#define MAX_RAW_MINORS	256
+
 struct raw_device_data {
 	struct block_device *binding;
 	int inuse;
 };
 
-static struct raw_device_data raw_devices[256];
+static struct raw_device_data raw_devices[MAX_RAW_MINORS];
 static DECLARE_MUTEX(raw_mutex);
-static struct file_operations raw_ctl_fops;
+static struct file_operations raw_ctl_fops;	     /* forward declaration */
 
 /*
  * Open/close code for raw IO.
@@ -85,11 +87,16 @@
 {
 	const int minor= minor(inode->i_rdev);
 	struct block_device *bdev;
-	
+
 	down(&raw_mutex);
 	bdev = raw_devices[minor].binding;
 	raw_devices[minor].inuse--;
 	up(&raw_mutex);
+
+	/* Here  inode->i_mapping == bdev->bd_inode->i_mapping  */
+	inode->i_mapping = &inode->i_data;
+	inode->i_mapping->backing_dev_info = &default_backing_dev_info;
+	
 	bd_release(bdev);
 	blkdev_put(bdev, BDEV_RAW);
 	return 0;
@@ -130,11 +137,13 @@
 			goto out;
 		
 		err = -EINVAL;
-		if (rq.raw_minor < 0 || rq.raw_minor > MINORMASK)
+		if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS)
 			goto out;
 		rawdev = &raw_devices[rq.raw_minor];
 
 		if (command == RAW_SETBIND) {
+			dev_t dev;
+
 			/*
 			 * This is like making block devices, so demand the
 			 * same capability
@@ -151,9 +160,10 @@
 			 */
 
 			err = -EINVAL;
+			dev = MKDEV(rq.block_major, rq.block_minor);
 			if ((rq.block_major == 0 && rq.block_minor != 0) ||
-					rq.block_major > MAX_BLKDEV ||
-					rq.block_minor > MINORMASK)
+			    MAJOR(dev) != rq.block_major ||
+			    MINOR(dev) != rq.block_minor)
 				goto out;
 			
 			down(&raw_mutex);
@@ -170,10 +180,7 @@
 				/* unbind */
 				rawdev->binding = NULL;
 			} else {
-				kdev_t kdev;
-
-				kdev = mk_kdev(rq.block_major, rq.block_minor);
-				rawdev->binding = bdget(kdev_t_to_nr(kdev));
+				rawdev->binding = bdget(dev);
 				MOD_INC_USE_COUNT;
 			}
 			up(&raw_mutex);
diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
--- a/drivers/char/rio/rio_linux.c	Tue Feb 25 02:08:22 2003
+++ b/drivers/char/rio/rio_linux.c	Thu Mar  6 09:17:26 2003
@@ -59,7 +59,6 @@
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 #if BITS_PER_LONG != 32
@@ -725,14 +724,14 @@
   switch (cmd) {
 #if 0
   case TIOCGSOFTCAR:
-    rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+    rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
                   (unsigned int *) arg);
     break;
 #endif
   case TIOCSSOFTCAR:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       tty->termios->c_cflag =
         (tty->termios->c_cflag & ~CLOCAL) |
         (ival ? CLOCAL : 0);
@@ -784,7 +783,7 @@
   case TIOCMBIS:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(unsigned int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
                            ((ival & TIOCM_RTS) ? 1 : -1));
     }
@@ -792,7 +791,7 @@
   case TIOCMBIC:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(unsigned int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
                            ((ival & TIOCM_RTS) ? 0 : -1));
     }
@@ -800,7 +799,7 @@
   case TIOCMSET:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(unsigned int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
                            ((ival & TIOCM_RTS) ? 1 : 0));
     }
@@ -1126,7 +1125,7 @@
             t, CNTRL_REG_GOODVALUE); 
     writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);  
   }
-  my_iounmap (hwbase, rebase);
+  iounmap((char*) rebase);
 }
 #endif
 
@@ -1201,7 +1200,7 @@
 
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
-      hp->Ivec = get_irq (pdev);
+      hp->Ivec = pdev->irq;
       if (((1 << hp->Ivec) & rio_irqmask) == 0)
               hp->Ivec = 0;
       hp->CardP	= (struct DpRam *)
@@ -1234,8 +1233,7 @@
               p->RIONumHosts++;
               found++;
       } else {
-              my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
-                          p->RIOHosts[p->RIONumHosts].Caddr);
+              iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
       }
       
 #ifdef TWO_ZERO
@@ -1272,7 +1270,7 @@
 
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
-      hp->Ivec = get_irq (pdev);
+      hp->Ivec = pdev->irq;
       if (((1 << hp->Ivec) & rio_irqmask) == 0) 
       	hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
@@ -1307,8 +1305,7 @@
         p->RIONumHosts++;
         found++;
       } else {
-        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
-                    p->RIOHosts[p->RIONumHosts].Caddr);
+        iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
       }
 #else
       printk (KERN_ERR "Found an older RIO PCI card, but the driver is not "
@@ -1361,7 +1358,7 @@
       }
 
     if (!okboard)
-      my_iounmap (hp->PaddrP, hp->Caddr);
+      iounmap ((char*) (hp->Caddr));
     }
   }
 
diff -Nru a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
--- a/drivers/char/rio/rioboot.c	Sat Feb 15 13:50:01 2003
+++ b/drivers/char/rio/rioboot.c	Sun Feb 16 16:15:30 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
--- a/drivers/char/rio/riocmd.c	Thu Nov 21 09:58:01 2002
+++ b/drivers/char/rio/riocmd.c	Sun Feb 16 16:15:30 2003
@@ -47,7 +47,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 #include "linux_compat.h"
diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
--- a/drivers/char/rio/rioctrl.c	Tue Dec  3 13:17:27 2002
+++ b/drivers/char/rio/rioctrl.c	Sun Feb 16 16:15:30 2003
@@ -47,7 +47,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
--- a/drivers/char/rio/rioinit.c	Tue Feb 25 09:44:30 2003
+++ b/drivers/char/rio/rioinit.c	Thu Mar  6 09:17:26 2003
@@ -47,7 +47,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
--- a/drivers/char/rio/riointr.c	Mon Feb  4 23:45:07 2002
+++ b/drivers/char/rio/riointr.c	Sun Feb 16 16:15:30 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 #include <linux/delay.h>
diff -Nru a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
--- a/drivers/char/rio/rioparam.c	Mon Feb 24 12:42:23 2003
+++ b/drivers/char/rio/rioparam.c	Thu Mar  6 09:17:26 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
--- a/drivers/char/rio/rioroute.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/char/rio/rioroute.c	Thu Mar  6 09:17:26 2003
@@ -46,7 +46,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
--- a/drivers/char/rio/riotable.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/char/rio/riotable.c	Thu Mar  6 09:17:26 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
--- a/drivers/char/rio/riotty.c	Tue Feb 25 02:17:56 2003
+++ b/drivers/char/rio/riotty.c	Thu Mar  6 09:17:26 2003
@@ -51,7 +51,6 @@
 
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	Sat Feb 15 04:17:36 2003
+++ b/drivers/char/rtc.c	Thu Mar  6 08:17:53 2003
@@ -152,6 +152,9 @@
 static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
 
 #if RTC_IRQ
+/*
+ * rtc_task_lock nests inside rtc_lock.
+ */
 static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
 static rtc_task_t *rtc_callback = NULL;
 #endif
@@ -746,13 +749,15 @@
 #else
 	unsigned char tmp;
 
-	spin_lock_irq(&rtc_task_lock);
+	spin_lock_irq(&rtc_lock);
+	spin_lock(&rtc_task_lock);
 	if (rtc_callback != task) {
-		spin_unlock_irq(&rtc_task_lock);
+		spin_unlock(&rtc_task_lock);
+		spin_unlock_irq(&rtc_lock);
 		return -ENXIO;
 	}
 	rtc_callback = NULL;
-	spin_lock(&rtc_lock);
+	
 	/* disable controls */
 	tmp = CMOS_READ(RTC_CONTROL);
 	tmp &= ~RTC_PIE;
@@ -765,8 +770,8 @@
 		del_timer(&rtc_irq_timer);
 	}
 	rtc_status &= ~RTC_IS_OPEN;
-	spin_unlock(&rtc_lock);
-	spin_unlock_irq(&rtc_task_lock);
+	spin_unlock(&rtc_task_lock);
+	spin_unlock_irq(&rtc_lock);
 	return 0;
 #endif
 }
diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c
--- a/drivers/char/serial167.c	Mon Nov 11 03:13:26 2002
+++ b/drivers/char/serial167.c	Fri Feb 14 15:16:47 2003
@@ -2836,7 +2836,7 @@
 };
 
 
-void __init serial167_console_init(void)
+static void __init serial167_console_init(void)
 {
 	if (vme_brdtype == VME_TYPE_MVME166 ||
 			vme_brdtype == VME_TYPE_MVME167 ||
@@ -2845,6 +2845,7 @@
 		register_console(&sercons);
 	}
 }
+console_initcall(serial167_console_init);
 
 #ifdef CONFIG_REMOTE_DEBUG
 void putDebugChar (int c)
diff -Nru a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c
--- a/drivers/char/serial_tx3912.c	Tue Nov  5 07:39:55 2002
+++ b/drivers/char/serial_tx3912.c	Fri Feb 14 15:16:47 2003
@@ -1054,9 +1054,10 @@
 	.index    = -1
 };
 
-void __init tx3912_console_init(void)
+static void __init tx3912_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(tx3912_console_init);
 
 #endif
diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c
--- a/drivers/char/sh-sci.c	Tue Nov  5 07:39:53 2002
+++ b/drivers/char/sh-sci.c	Fri Feb 14 15:16:47 2003
@@ -1275,7 +1275,7 @@
 extern void sh_console_unregister (void);
 #endif
 
-void __init sci_console_init(void)
+static void __init sci_console_init(void)
 {
 	register_console(&sercons);
 #ifdef CONFIG_SH_EARLY_PRINTK
@@ -1285,4 +1285,6 @@
 	sh_console_unregister();
 #endif
 }
+console_initcall(sci_console_init);
+
 #endif /* CONFIG_SERIAL_CONSOLE */
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Mon Mar  3 08:49:44 2003
+++ b/drivers/char/tty_io.c	Sat Mar 15 02:33:56 2003
@@ -113,7 +113,15 @@
 #define TTY_PARANOIA_CHECK 1
 #define CHECK_TTY_COUNT 1
 
-struct termios tty_std_termios;		/* for the benefit of tty drivers  */
+struct termios tty_std_termios = {	/* for the benefit of tty drivers  */
+	.c_iflag = ICRNL | IXON,
+	.c_oflag = OPOST | ONLCR,
+	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
+	.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
+		   ECHOCTL | ECHOKE | IEXTEN,
+	.c_cc = INIT_C_CC
+};
+
 LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
 struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
 
@@ -141,26 +149,13 @@
 	      unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
 extern int vme_scc_init (void);
-extern long vme_scc_console_init(void);
 extern int serial167_init(void);
-extern long serial167_console_init(void);
-extern void console_8xx_init(void);
 extern int rs_8xx_init(void);
-extern void mac_scc_console_init(void);
-extern void sclp_console_init(void);
-extern void sclp_tty_init(void);
-extern void con3215_init(void);
-extern void tub3270_con_init(void);
+extern void hwc_tty_init(void);
+extern void tty3215_init(void);
 extern void tub3270_init(void);
-extern void uart_console_init(void);
-extern void sgi_serial_console_init(void);
-extern void sci_console_init(void);
-extern void m68328_console_init(void);
-extern void mcfrs_console_init(void);
 extern void rs_360_init(void);
-extern void tx3912_console_init(void);
 extern void tx3912_rs_init(void);
-extern void hvc_console_init(void);
 
 static struct tty_struct *alloc_tty_struct(void)
 {
@@ -306,13 +301,9 @@
 	if (tty->ldisc.open)
 		retval = (tty->ldisc.open)(tty);
 	if (retval < 0) {
-		module_put(tty->ldisc.owner);
-		
 		tty->ldisc = o_ldisc;
 		tty->termios->c_line = tty->ldisc.num;
 		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
-			module_put(tty->ldisc.owner);
-
 			tty->ldisc = ldiscs[N_TTY];
 			tty->termios->c_line = N_TTY;
 			if (tty->ldisc.open) {
@@ -2206,91 +2197,28 @@
  */
 void __init console_init(void)
 {
+	initcall_t *call;
+
 	/* Setup the default TTY line discipline. */
-	memset(ldiscs, 0, sizeof(ldiscs));
 	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
 
 	/*
-	 * Set up the standard termios.  Individual tty drivers may 
-	 * deviate from this; this is used as a template.
-	 */
-	memset(&tty_std_termios, 0, sizeof(struct termios));
-	memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS);
-	tty_std_termios.c_iflag = ICRNL | IXON;
-	tty_std_termios.c_oflag = OPOST | ONLCR;
-	tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;
-	tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
-		ECHOCTL | ECHOKE | IEXTEN;
-
-	/*
 	 * set up the console device so that later boot sequences can 
 	 * inform about problems etc..
 	 */
 #ifdef CONFIG_EARLY_PRINTK
 	disable_early_printk();
 #endif
-#ifdef CONFIG_VT
-	con_init();
-#endif
-#ifdef CONFIG_AU1000_SERIAL_CONSOLE
-	au1000_serial_console_init();
-#endif
-#ifdef CONFIG_SERIAL_CONSOLE
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
-	console_8xx_init();
-#elif defined(CONFIG_MAC_SERIAL)
- 	mac_scc_console_init();
-#elif defined(CONFIG_PARISC)
-	pdc_console_init();
-#elif defined(CONFIG_SERIAL)
-	serial_console_init();
-#endif /* CONFIG_8xx */
-#ifdef CONFIG_SGI_SERIAL
-	sgi_serial_console_init();
-#endif
-#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
-	vme_scc_console_init();
-#endif
-#if defined(CONFIG_SERIAL167)
-	serial167_console_init();
-#endif
-#if defined(CONFIG_SH_SCI)
-	sci_console_init();
-#endif
-#endif
-#ifdef CONFIG_TN3270_CONSOLE
-	tub3270_con_init();
-#endif
-#ifdef CONFIG_TN3215_CONSOLE
-	con3215_init();
-#endif
-#ifdef CONFIG_SCLP_CONSOLE
-        sclp_console_init();
-#endif
-#ifdef CONFIG_STDIO_CONSOLE
-	stdio_console_init();
-#endif
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-	uart_console_init();
-#endif
-#ifdef CONFIG_ARC_CONSOLE
-	arc_console_init();
-#endif
-#ifdef CONFIG_SERIAL_68328
-	m68328_console_init();
-#endif
-#ifdef CONFIG_SERIAL_COLDFIRE
-	mcfrs_console_init();
-#endif
 #ifdef CONFIG_SERIAL_68360
-	rs_360_init();
-#endif
-#ifdef CONFIG_SERIAL_TX3912_CONSOLE
-	tx3912_console_init();
-#endif
-#ifdef CONFIG_HVC_CONSOLE
-	hvc_console_init();
-#endif
+ 	/* This is not a console initcall. I know not what it's doing here.
+	   So I haven't moved it. dwmw2 */
+        rs_360_init();
+#endif
+	call = &__con_initcall_start;
+	while (call < &__con_initcall_end) {
+		(*call)();
+		call++;
+	}
 }
 
 static struct tty_driver dev_tty_driver, dev_syscons_driver;
@@ -2307,14 +2235,19 @@
 };
 EXPORT_SYMBOL(tty_devclass);
 
+static int __init tty_devclass_init(void)
+{
+	return devclass_register(&tty_devclass);
+}
+
+postcore_initcall(tty_devclass_init);
+
 /*
  * Ok, now we can initialize the rest of the tty devices and can count
  * on memory allocations, interrupts etc..
  */
 void __init tty_init(void)
 {
-	devclass_register(&tty_devclass);
-
 	/*
 	 * dev_tty_driver and dev_console_driver are actually magic
 	 * devices which get redirected at open time.  Nevertheless,
diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
--- a/drivers/char/vme_scc.c	Thu Nov  7 15:06:42 2002
+++ b/drivers/char/vme_scc.c	Fri Feb 14 15:18:33 2003
@@ -1091,7 +1091,7 @@
 };
 
 
-void __init vme_scc_console_init(void)
+static void __init vme_scc_console_init(void)
 {
 	if (vme_brdtype == VME_TYPE_MVME147 ||
 			vme_brdtype == VME_TYPE_MVME162 ||
@@ -1100,4 +1100,4 @@
 			vme_brdtype == VME_TYPE_BVME6000)
 		register_console(&sercons);
 }
-
+console_initcall(vme_scc_console_init);
diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c
--- a/drivers/char/vt.c	Tue Feb 25 09:17:44 2003
+++ b/drivers/char/vt.c	Fri Mar  7 11:25:45 2003
@@ -747,8 +747,10 @@
 	screenbuf_size = new_screen_size;
 
 	err = resize_screen(currcons, new_cols, new_rows);
-	if (err)
+	if (err) {
+		kfree(newscreen);
 		return err;
+	}
 
 	rlth = min(old_row_size, new_row_size);
 	rrem = new_row_size - rlth;
@@ -2443,7 +2445,7 @@
 struct tty_driver console_driver;
 static int console_refcount;
 
-void __init con_init(void)
+static int __init con_init(void)
 {
 	const char *display_desc = NULL;
 	unsigned int currcons = 0;
@@ -2452,7 +2454,7 @@
 		display_desc = conswitchp->con_startup();
 	if (!display_desc) {
 		fg_console = 0;
-		return;
+		return 0;
 	}
 
 	init_timer(&console_timer);
@@ -2491,7 +2493,9 @@
 #ifdef CONFIG_VT_CONSOLE
 	register_console(&vt_console_driver);
 #endif
+	return 0;
 }
+console_initcall(con_init);
 
 int __init vty_init(void)
 {
diff -Nru a/drivers/char/watchdog/amd7xx_tco.c b/drivers/char/watchdog/amd7xx_tco.c
--- a/drivers/char/watchdog/amd7xx_tco.c	Thu Feb 27 17:28:13 2003
+++ b/drivers/char/watchdog/amd7xx_tco.c	Sat Mar  8 02:46:43 2003
@@ -1,6 +1,6 @@
 /*
  *	AMD 766/768 TCO Timer Driver
- *	(c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
+ *	(c) Copyright 2002 Zwane Mwaikambo <zwane@holomorphy.com>
  *	All Rights Reserved.
  *
  *	Parts from;
@@ -34,35 +34,48 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 
-#define AMDTCO_MODULE_VER	"build 20020601"
+#define AMDTCO_MODULE_VER	"build 20021116"
 #define AMDTCO_MODULE_NAME	"amd7xx_tco"
 #define PFX			AMDTCO_MODULE_NAME ": "
 
-#define	MAX_TIMEOUT	38	/* max of 38 seconds */
+#define	MAX_TIMEOUT	38	/* max of 38 seconds, although the system will only
+				 * reset itself after the second timeout */
 
 /* pmbase registers */
-#define GLOBAL_SMI_REG	0x2a
-#define TCO_EN		(1 << 1)	/* bit 1 in global SMI register */
 #define TCO_RELOAD_REG	0x40		/* bits 0-5 are current count, 6-7 are reserved */
 #define TCO_INITVAL_REG	0x41		/* bits 0-5 are value to load, 6-7 are reserved */
 #define TCO_TIMEOUT_MASK	0x3f
+#define TCO_STATUS1_REG 0x44
 #define TCO_STATUS2_REG	0x46
 #define NDTO_STS2	(1 << 1)	/* we're interested in the second timeout */ 
 #define BOOT_STS	(1 << 2)	/* will be set if NDTO_STS2 was set before reboot */
 #define TCO_CTRL1_REG	0x48
 #define TCO_HALT	(1 << 11)
+#define NO_REBOOT	(1 << 10)	/* in DevB:3x48 */
 
-static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER;
-static int timeout = 38;
+static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n";
+static int timeout = MAX_TIMEOUT;
 static u32 pmbase;		/* PMxx I/O base */
 static struct pci_dev *dev;
 static struct semaphore open_sem;
-spinlock_t amdtco_lock;	/* only for device access */
+static spinlock_t amdtco_lock;	/* only for device access */
 static int expect_close = 0;
 
 MODULE_PARM(timeout, "i");
 MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38");
 
+static inline u8 seconds_to_ticks(int seconds)
+{
+	/* the internal timer is stored as ticks which decrement
+	 * every 0.6 seconds */
+	return (seconds * 10) / 6;
+}
+
+static inline int ticks_to_seconds(u8 ticks)
+{
+	return (ticks * 6) / 10;
+}
+
 static inline int amdtco_status(void)
 {
 	u16 reg;
@@ -81,28 +94,19 @@
 
 static inline void amdtco_ping(void)
 {
-	u8 reg;
-
-	spin_lock(&amdtco_lock);
-	reg = inb(pmbase+TCO_RELOAD_REG);
-	outb(1 | reg, pmbase+TCO_RELOAD_REG);
-	spin_unlock(&amdtco_lock);
+	outb(1, pmbase+TCO_RELOAD_REG);
 }
 
 static inline int amdtco_gettimeout(void)
 {
-	return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+	u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+	return ticks_to_seconds(reg);
 }
 
 static inline void amdtco_settimeout(unsigned int timeout)
 {
-	u8 reg;
-
-	spin_lock(&amdtco_lock);
-	reg = inb(pmbase+TCO_INITVAL_REG);
-	reg |= timeout & TCO_TIMEOUT_MASK;
+	u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK;
 	outb(reg, pmbase+TCO_INITVAL_REG);
-	spin_unlock(&amdtco_lock);
 }
 
 static inline void amdtco_global_enable(void)
@@ -110,9 +114,12 @@
 	u16 reg;
 
 	spin_lock(&amdtco_lock);
-	reg = inw(pmbase+GLOBAL_SMI_REG);
-	reg |= TCO_EN;
-	outw(reg, pmbase+GLOBAL_SMI_REG);
+
+	/* clear NO_REBOOT on DevB:3x48 p97 */
+	pci_read_config_word(dev, 0x48, &reg);
+	reg &= ~NO_REBOOT;
+	pci_write_config_word(dev, 0x48, reg);
+
 	spin_unlock(&amdtco_lock);
 }
 
@@ -146,10 +153,12 @@
 	if (timeout > MAX_TIMEOUT)
 		timeout = MAX_TIMEOUT;
 
+	amdtco_disable();
 	amdtco_settimeout(timeout);	
 	amdtco_global_enable();
+	amdtco_enable();
 	amdtco_ping();
-	printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds",
+	printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n",
 		amdtco_gettimeout(), timeout);
 	
 	return 0;
@@ -198,7 +207,7 @@
 
 		case WDIOC_GETTIMEOUT:
 			return put_user(amdtco_gettimeout(), (int *)arg);
-	
+		
 		case WDIOC_SETOPTIONS:
 			if (copy_from_user(&tmp, (int *)arg, sizeof tmp))
                                 return -EFAULT;
@@ -221,7 +230,7 @@
 		printk(KERN_INFO PFX "Watchdog disabled\n");
 	} else {
 		amdtco_ping();
-		printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout);
+		printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout);
 	}	
 	
 	up(&open_sem);
@@ -249,10 +258,9 @@
 		}
 #endif
 		amdtco_ping();
-		return len;
 	}
 
-	return 0;
+	return len;
 }
 
 
@@ -357,6 +365,9 @@
 	if (ints[0] > 0)
 		timeout = ints[1];
 
+	if (!timeout || timeout > MAX_TIMEOUT)
+		timeout = MAX_TIMEOUT;
+
 	return 1;
 }
 
@@ -366,8 +377,7 @@
 module_init(amdtco_init);
 module_exit(amdtco_exit);
 
-MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>");
+MODULE_AUTHOR("Zwane Mwaikambo <zwane@holomorphy.com>");
 MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver");
 MODULE_LICENSE("GPL");
-EXPORT_NO_SYMBOLS;
 
diff -Nru a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
--- a/drivers/cpufreq/freq_table.c	Sat Feb 15 01:16:27 2003
+++ b/drivers/cpufreq/freq_table.c	Sat Mar  8 01:39:17 2003
@@ -77,56 +77,6 @@
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 
 
-int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
-				      struct cpufreq_frequency_table *table,
-				      unsigned int *index)
-{
-	struct cpufreq_frequency_table optimal = { .index = ~0, };
-	unsigned int i;
-
-	switch (policy->policy) {
-	case CPUFREQ_POLICY_PERFORMANCE:
-		optimal.frequency = 0;
-		break;
-	case CPUFREQ_POLICY_POWERSAVE:
-		optimal.frequency = ~0;
-		break;
-	}
-
-	if (!cpu_online(policy->cpu))
-		return -EINVAL;
-
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		unsigned int freq = table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		if ((freq < policy->min) || (freq > policy->max))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_PERFORMANCE:
-			if (optimal.frequency <= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (optimal.frequency >= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		}
-	}
-	if (optimal.index > i)
-		return -EINVAL;
-
-	*index = optimal.index;
-	
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
-
-
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table,
 				   unsigned int target_freq,
@@ -196,6 +146,56 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
+
+static struct cpufreq_frequency_table *show_table[NR_CPUS];
+/**
+ * show_scaling_governor - show the current policy for the specified CPU
+ */
+static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
+{
+	unsigned int i = 0;
+	unsigned int cpu = policy->cpu;
+	ssize_t count = 0;
+	struct cpufreq_frequency_table *table;
+
+	if (!show_table[cpu])
+		return -ENODEV;
+
+	table = show_table[cpu];
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
+			continue;
+		count += sprintf(&buf[count], "%d ", table[i].frequency);
+	}
+	count += sprintf(&buf[count], "\n");
+
+	return count;
+
+}
+
+struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
+	.attr = { .name = "scaling_available_frequencies", .mode = 0444 },
+	.show = show_available_freqs,
+};
+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
+
+/*
+ * if you use these, you must assure that the frequency table is valid
+ * all the time between get_attr and put_attr!
+ */
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 
+				      unsigned int cpu)
+{
+	show_table[cpu] = table;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
+
+void cpufreq_frequency_table_put_attr(unsigned int cpu)
+{
+	show_table[cpu] = NULL;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
 
 
 MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
diff -Nru a/drivers/cpufreq/userspace.c b/drivers/cpufreq/userspace.c
--- a/drivers/cpufreq/userspace.c	Sun Feb 16 05:23:39 2003
+++ b/drivers/cpufreq/userspace.c	Sat Mar  8 01:37:35 2003
@@ -23,6 +23,7 @@
 #include <linux/sysctl.h>
 #include <linux/types.h>
 #include <linux/fs.h>
+#include <linux/sysfs.h>
 
 #include <asm/uaccess.h>
 
@@ -112,7 +113,7 @@
 	if (freq > cpu_max_freq[cpu])
 		freq = cpu_max_freq[cpu];
 
-	ret = cpufreq_driver_target_l(&current_policy[cpu], freq, 
+	ret = cpufreq_driver_target(&current_policy[cpu], freq, 
 	      CPUFREQ_RELATION_L);
 
  err:
@@ -465,23 +466,14 @@
 
 
 /************************** sysfs interface ************************/
-static inline int to_cpu_nr (struct device *dev)
+static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
 {
-	struct sys_device * cpu_sys_dev = container_of(dev, struct sys_device, dev);
-	return (cpu_sys_dev->id);
-}
-
-static ssize_t show_speed (struct device *dev, char *buf)
-{
-	unsigned int cpu = to_cpu_nr(dev);
-
-	return sprintf (buf, "%u\n", cpu_cur_freq[cpu]);
+	return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
 }
 
 static ssize_t 
-store_speed (struct device *dev, const char *buf, size_t count) 
+store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) 
 {
-	unsigned int cpu = to_cpu_nr(dev);
 	unsigned int freq = 0;
 	unsigned int ret;
 
@@ -489,13 +481,16 @@
 	if (ret != 1)
 		return -EINVAL;
 
-	cpufreq_set(freq, cpu);
+	cpufreq_set(freq, policy->cpu);
 
 	return count;
 }
 
-static DEVICE_ATTR(scaling_setspeed, (S_IRUGO | S_IWUSR), show_speed, store_speed);
-
+static struct freq_attr freq_attr_scaling_setspeed = {
+	.attr = { .name = "scaling_setspeed", .mode = 0644 },
+	.show = show_speed,
+	.store = store_speed,
+};
 
 static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
 				   unsigned int event)
@@ -511,7 +506,7 @@
 		cpu_min_freq[cpu] = policy->min;
 		cpu_max_freq[cpu] = policy->max;
 		cpu_cur_freq[cpu] = policy->cur;
-		device_create_file (policy->intf.dev, &dev_attr_scaling_setspeed);
+		sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
 		memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
 		up(&userspace_sem);
 		break;
@@ -520,7 +515,7 @@
 		cpu_is_managed[cpu] = 0;
 		cpu_min_freq[cpu] = 0;
 		cpu_max_freq[cpu] = 0;
-		device_remove_file (policy->intf.dev, &dev_attr_scaling_setspeed);
+		sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
 		up(&userspace_sem);
 		module_put(THIS_MODULE);
 		break;
diff -Nru a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
--- a/drivers/eisa/eisa-bus.c	Sat Feb 15 04:56:07 2003
+++ b/drivers/eisa/eisa-bus.c	Wed Mar  5 07:11:17 2003
@@ -83,8 +83,10 @@
 		return 0;
 
 	while (strlen (eids->sig)) {
-		if (!strcmp (eids->sig, edev->id.sig))
+		if (!strcmp (eids->sig, edev->id.sig)) {
+			edev->id.driver_data = eids->driver_data;
 			return 1;
+		}
 
 		eids++;
 	}
diff -Nru a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
--- a/drivers/eisa/virtual_root.c	Sat Feb 15 04:56:07 2003
+++ b/drivers/eisa/virtual_root.c	Wed Mar  5 07:11:17 2003
@@ -13,14 +13,19 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-/* The default EISA device parent (virtual root device). */
-static struct device eisa_root_dev = {
-       .name        = "Virtual EISA Bridge",
-       .bus_id      = "eisa",
+/* The default EISA device parent (virtual root device).
+ * Now use a platform device, since that's the obvious choice. */
+
+static struct platform_device eisa_root_dev = {
+	.name = "eisa",
+	.id   = 0,
+	.dev  = {
+		.name = "Virtual EISA Bridge",
+	},
 };
 
 static struct eisa_root_device eisa_bus_root = {
-	.dev           = &eisa_root_dev,
+	.dev           = &eisa_root_dev.dev,
 	.bus_base_addr = 0,
 	.res	       = &ioport_resource,
 	.slots	       = EISA_MAX_SLOTS,
@@ -30,16 +35,16 @@
 {
 	int r;
 	
-        if ((r = device_register (&eisa_root_dev))) {
+        if ((r = platform_device_register (&eisa_root_dev))) {
                 return r;
         }
 
-	eisa_root_dev.driver_data = &eisa_bus_root;
+	eisa_root_dev.dev.driver_data = &eisa_bus_root;
 
 	if (eisa_root_register (&eisa_bus_root)) {
 		/* A real bridge may have been registered before
 		 * us. So quietly unregister. */
-		device_unregister (&eisa_root_dev);
+		platform_device_unregister (&eisa_root_dev);
 		return -1;
 	}
 
diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c
--- a/drivers/hotplug/acpiphp_glue.c	Thu Feb 27 16:27:27 2003
+++ b/drivers/hotplug/acpiphp_glue.c	Mon Feb 24 03:28:46 2003
@@ -801,7 +801,7 @@
 static int enable_device (struct acpiphp_slot *slot)
 {
 	u8 bus;
-	struct pci_dev dev0, *dev;
+	struct pci_dev *dev;
 	struct pci_bus *child;
 	struct list_head *l;
 	struct acpiphp_func *func;
@@ -824,16 +824,8 @@
 	if (retval)
 		goto err_exit;
 
-	memset(&dev0, 0, sizeof (struct pci_dev));
-
-	dev0.bus = slot->bridge->pci_bus;
-	dev0.devfn = PCI_DEVFN(slot->device, 0);
-	dev0.sysdata = dev0.bus->sysdata;
-	dev0.dev.parent = dev0.bus->dev;
-	dev0.dev.bus = &pci_bus_type;
-
 	/* returned `dev' is the *first function* only! */
-	dev = pci_scan_slot (&dev0);
+	dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
 
 	if (!dev) {
 		err("No new device found\n");
diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c
--- a/drivers/hotplug/cpci_hotplug_pci.c	Mon Feb 24 08:17:14 2003
+++ b/drivers/hotplug/cpci_hotplug_pci.c	Mon Feb 24 03:29:36 2003
@@ -574,19 +574,13 @@
 
 	/* Still NULL? Well then scan for it! */
 	if(slot->dev == NULL) {
-		struct pci_dev dev0;
-
 		dbg("pci_dev still null");
-		memset(&dev0, 0, sizeof (struct pci_dev));
-		dev0.bus = slot->bus;
-		dev0.devfn = slot->devfn;
-		dev0.sysdata = slot->bus->self->sysdata;
 
 		/*
 		 * This will generate pci_dev structures for all functions, but
 		 * we will only call this case when lookup fails.
 		 */
-		slot->dev = pci_scan_slot(&dev0);
+		slot->dev = pci_scan_slot(slot->bus, slot->devfn);
 		if(slot->dev == NULL) {
 			err("Could not find PCI device for slot %02x", slot->number);
 			return 0;
diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c
--- a/drivers/hotplug/cpqphp_pci.c	Mon Feb 24 08:17:34 2003
+++ b/drivers/hotplug/cpqphp_pci.c	Mon Feb 24 03:31:07 2003
@@ -84,24 +84,19 @@
 int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  
 {
 	unsigned char bus;
-	struct pci_dev dev0;
 	struct pci_bus *child;
 	int rc = 0;
 
-	memset(&dev0, 0, sizeof(struct pci_dev));
-
 	if (func->pci_dev == NULL)
 		func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7));
 
 	//Still NULL ? Well then scan for it !
 	if (func->pci_dev == NULL) {
 		dbg("INFO: pci_dev still null\n");
-		dev0.bus = ctrl->pci_dev->bus;
-		dev0.devfn = (func->device << 3) + (func->function & 0x7);
-		dev0.sysdata = ctrl->pci_dev->sysdata;
 
 		//this will generate pci_dev structures for all functions, but we will only call this case when lookup fails
-		func->pci_dev = pci_scan_slot(&dev0);
+		func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus,
+				 (func->device << 3) + (func->function & 0x7));
 		if (func->pci_dev == NULL) {
 			dbg("ERROR: pci_dev still null\n");
 			return 0;
diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c
--- a/drivers/hotplug/ibmphp_core.c	Thu Feb 27 13:49:39 2003
+++ b/drivers/hotplug/ibmphp_core.c	Mon Feb 24 03:32:11 2003
@@ -845,26 +845,22 @@
 static int ibm_configure_device (struct pci_func *func)
 {
 	unsigned char bus;
-	struct pci_dev dev0;
 	struct pci_bus *child;
 	int rc = 0;
 	int flag = 0;	/* this is to make sure we don't double scan the bus, for bridged devices primarily */
 
-	memset (&dev0, 0, sizeof (struct pci_dev));
-
 	if (!(bus_structure_fixup (func->busno)))
 		flag = 1;
 	if (func->dev == NULL)
 		func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7));
 
 	if (func->dev == NULL) {
-		dev0.bus = ibmphp_find_bus (func->busno);
-		if (!dev0.bus)
+		struct pci_bus *bus = ibmphp_find_bus (func->busno);
+		if (!bus)
 			return 0;
-		dev0.devfn = ((func->device << 3) + (func->function & 0x7));
-		dev0.sysdata = dev0.bus->sysdata;
 
-		func->dev = pci_scan_slot (&dev0);
+		func->dev = pci_scan_slot(bus,
+				 (func->device << 3) + (func->function & 0x7));
 
 		if (func->dev == NULL) {
 			err ("ERROR... : pci_dev still NULL \n");
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/drivers/i2c/busses/Kconfig	Thu Mar 13 11:52:16 2003
@@ -5,6 +5,20 @@
 
 menu "I2C Hardware Sensors Mainboard support"
 
+config I2C_ALI15X3
+	tristate "  ALI 15x3"
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the
+	  Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
+
+	  This can also be built as a module.  If so, the module will be
+	  called i2c-ali15x3.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at
+	  http://www.lm-sensors.nu
+
 config I2C_AMD756
 	tristate "  AMD 756/766"
 	depends on I2C && I2C_PROC
@@ -34,6 +48,52 @@
 	  say M here and read <file:Documentation/modules.txt>.
 
 	  The module will be called i2c-amd8111.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at 
+	  http://www.lm-sensors.nu
+
+config I2C_I801
+	tristate "  Intel 801"
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the Intel
+	  801 family of mainboard I2C interfaces.  Specifically, the following
+	  versions of the chipset is supported:
+	    82801AA
+	    82801AB
+	    82801BA
+	    82801CA/CAM
+	    82801DB
+
+	  This can also be built as a module which can be inserted and removed 
+	  while the kernel is running.  If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  The module will be called i2c-i801.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at 
+	  http://www.lm-sensors.nu
+
+config I2C_PIIX4
+	tristate "  Intel PIIX4"
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the Intel
+	  PIIX4 family of mainboard I2C interfaces.  Specifically, the following
+	  versions of the chipset is supported:
+	    Intel PIIX4
+	    Intel 440MX
+	    Serverworks OSB4
+	    Serverworks CSB5
+	    SMSC Victory66
+
+	  This can also be built as a module which can be inserted and removed 
+	  while the kernel is running.  If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  The module will be called i2c-piix4.
 
 	  You will also need the latest user-space utilties: you can find them
 	  in the lm_sensors package, which you can download at 
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Sun Dec 29 10:10:44 2002
+++ b/drivers/i2c/busses/Makefile	Thu Mar 13 11:52:16 2003
@@ -2,5 +2,8 @@
 # Makefile for the kernel hardware sensors bus drivers.
 #
 
+obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
+obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
+obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:39:32 2003
@@ -0,0 +1,575 @@
+/*
+    ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1999  Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com> and
+    Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+    This is the driver for the SMB Host controller on
+    Acer Labs Inc. (ALI) M1541 and M1543C South Bridges.
+
+    The M1543C is a South bridge for desktop systems.
+    The M1533 is a South bridge for portable systems.
+    They are part of the following ALI chipsets:
+       "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge
+       with AGP and 100MHz CPU Front Side bus
+       "Aladdin V": Includes the M1541 Socket 7 North bridge
+       with AGP and 100MHz CPU Front Side bus
+       "Aladdin IV": Includes the M1541 Socket 7 North bridge
+       with host bus up to 83.3 MHz.
+    For an overview of these chips see http://www.acerlabs.com
+
+    The M1533/M1543C devices appear as FOUR separate devices
+    on the PCI bus. An output of lspci will show something similar
+    to the following:
+
+	00:02.0 USB Controller: Acer Laboratories Inc. M5237
+	00:03.0 Bridge: Acer Laboratories Inc. M7101
+	00:07.0 ISA bridge: Acer Laboratories Inc. M1533
+	00:0f.0 IDE interface: Acer Laboratories Inc. M5229
+
+    The SMB controller is part of the 7101 device, which is an
+    ACPI-compliant Power Management Unit (PMU).
+
+    The whole 7101 device has to be enabled for the SMB to work.
+    You can't just enable the SMB alone.
+    The SMB and the ACPI have separate I/O spaces.
+    We make sure that the SMB is enabled. We leave the ACPI alone.
+
+    This driver controls the SMB Host only.
+    The SMB Slave controller on the M15X3 is not enabled.
+
+    This driver does not use interrupts.
+*/
+
+/* Note: we assume there can only be one ALI15X3, with one SMBus interface */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+/* ALI15X3 SMBus address offsets */
+#define SMBHSTSTS (0 + ali15x3_smba)
+#define SMBHSTCNT (1 + ali15x3_smba)
+#define SMBHSTSTART (2 + ali15x3_smba)
+#define SMBHSTCMD (7 + ali15x3_smba)
+#define SMBHSTADD (3 + ali15x3_smba)
+#define SMBHSTDAT0 (4 + ali15x3_smba)
+#define SMBHSTDAT1 (5 + ali15x3_smba)
+#define SMBBLKDAT (6 + ali15x3_smba)
+
+/* PCI Address Constants */
+#define SMBCOM    0x004
+#define SMBBA     0x014
+#define SMBATPC   0x05B		/* used to unlock xxxBA registers */
+#define SMBHSTCFG 0x0E0
+#define SMBSLVC   0x0E1
+#define SMBCLK    0x0E2
+#define SMBREV    0x008
+
+/* Other settings */
+#define MAX_TIMEOUT 200		/* times 1/100 sec */
+#define ALI15X3_SMB_IOSIZE 32
+
+/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB.
+   We don't use these here. If the bases aren't set to some value we
+   tell user to upgrade BIOS and we fail.
+*/
+#define ALI15X3_SMB_DEFAULTBASE 0xE800
+
+/* ALI15X3 address lock bits */
+#define ALI15X3_LOCK	0x06
+
+/* ALI15X3 command constants */
+#define ALI15X3_ABORT      0x02
+#define ALI15X3_T_OUT      0x04
+#define ALI15X3_QUICK      0x00
+#define ALI15X3_BYTE       0x10
+#define ALI15X3_BYTE_DATA  0x20
+#define ALI15X3_WORD_DATA  0x30
+#define ALI15X3_BLOCK_DATA 0x40
+#define ALI15X3_BLOCK_CLR  0x80
+
+/* ALI15X3 status register bits */
+#define ALI15X3_STS_IDLE	0x04
+#define ALI15X3_STS_BUSY	0x08
+#define ALI15X3_STS_DONE	0x10
+#define ALI15X3_STS_DEV		0x20	/* device error */
+#define ALI15X3_STS_COLL	0x40	/* collision or no response */
+#define ALI15X3_STS_TERM	0x80	/* terminated by abort */
+#define ALI15X3_STS_ERR		0xE0	/* all the bad error bits */
+
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the device at the given address. */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Initialize the base address of the i2c controller");
+
+
+static void ali15x3_do_pause(unsigned int amount);
+static int ali15x3_transaction(void);
+
+static unsigned short ali15x3_smba = 0;
+
+int ali15x3_setup(struct pci_dev *ALI15X3_dev)
+{
+	u16 a;
+	unsigned char temp;
+
+/* Check the following things:
+	- SMB I/O address is initialized
+	- Device is enabled
+	- We can use the addresses
+*/
+
+/* Unlock the register.
+   The data sheet says that the address registers are read-only
+   if the lock bits are 1, but in fact the address registers
+   are zero unless you clear the lock bits.
+*/
+	pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
+	if (temp & ALI15X3_LOCK) {
+		temp &= ~ALI15X3_LOCK;
+		pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
+	}
+
+/* Determine the address of the SMBus area */
+	pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
+	ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
+	if (ali15x3_smba == 0 && force_addr == 0) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+		return -ENODEV;
+	}
+
+	if(force_addr)
+		ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
+
+	if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n",
+		     ali15x3_smba);
+		return -ENODEV;
+	}
+
+	if(force_addr) {
+		printk("i2c-ali15x3.o: forcing ISA address 0x%04X\n", ali15x3_smba);
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba))
+			return -ENODEV;
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_read_config_word(ALI15X3_dev, SMBBA, &a))
+			return -ENODEV;
+		if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {
+			/* make sure it works */
+			printk("i2c-ali15x3.o: force address failed - not supported?\n");
+			return -ENODEV;
+		}
+	}
+/* check if whole device is enabled */
+	pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
+	if ((temp & 1) == 0) {
+		printk("i2c-ali15x3: enabling SMBus device\n");
+		pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);
+	}
+
+/* Is SMB Host controller enabled? */
+	pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
+	if ((temp & 1) == 0) {
+		printk("i2c-ali15x3: enabling SMBus controller\n");
+		pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);
+	}
+
+/* set SMB clock to 74KHz as recommended in data sheet */
+	pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
+
+	/* Everything is happy, let's grab the memory and set things up. */
+	request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb");
+
+#ifdef DEBUG
+/*
+  The interrupt routing for SMB is set up in register 0x77 in the
+  1533 ISA Bridge device, NOT in the 7101 device.
+  Don't bother with finding the 1533 device and reading the register.
+  if ((....... & 0x0F) == 1)
+     printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n");
+*/
+	pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
+	printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp);
+	printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba);
+#endif				/* DEBUG */
+
+	return 0;
+}
+
+
+/* Internally used pause function */
+void ali15x3_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+/* Another internally used function */
+int ali15x3_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+	     inb_p(SMBHSTDAT1));
+#endif
+
+	/* get status */
+	temp = inb_p(SMBHSTSTS);
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	/* Check the busy bit first */
+	if (temp & ALI15X3_STS_BUSY) {
+/*
+   If the host controller is still busy, it may have timed out in the previous transaction,
+   resulting in a "SMBus Timeout" printk.
+   I've tried the following to reset a stuck busy bit.
+	1. Reset the controller with an ABORT command.
+	   (this doesn't seem to clear the controller if an external device is hung)
+	2. Reset the controller and the other SMBus devices with a T_OUT command.
+	   (this clears the host busy bit if an external device is hung,
+	   but it comes back upon a new access to a device)
+	3. Disable and reenable the controller in SMBHSTCFG
+   Worst case, nothing seems to work except power reset.
+*/
+/* Abort - reset the host controller */
+/*
+#ifdef DEBUG
+    printk("i2c-ali15x3.o: Resetting host controller to clear busy condition\n",temp);
+#endif
+    outb_p(ALI15X3_ABORT, SMBHSTCNT);
+    temp = inb_p(SMBHSTSTS);
+    if (temp & ALI15X3_STS_BUSY) {
+*/
+
+/*
+   Try resetting entire SMB bus, including other devices -
+   This may not work either - it clears the BUSY bit but
+   then the BUSY bit may come back on when you try and use the chip again.
+   If that's the case you are stuck.
+*/
+		printk
+		    ("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",
+		     temp);
+		outb_p(ALI15X3_T_OUT, SMBHSTCNT);
+		temp = inb_p(SMBHSTSTS);
+	}
+/*
+  }
+*/
+
+	/* now check the error bits and the busy bit */
+	if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
+		/* do a clear-on-write */
+		outb_p(0xFF, SMBHSTSTS);
+		if ((temp = inb_p(SMBHSTSTS)) &
+		    (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
+			/* this is probably going to be correctable only by a power reset
+			   as one of the bits now appears to be stuck */
+			/* This may be a bus or device with electrical problems. */
+			printk
+			    ("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n",
+			     temp);
+			return -1;
+		}
+	} else {
+		/* check and clear done bit */
+		if (temp & ALI15X3_STS_DONE) {
+			outb_p(temp, SMBHSTSTS);
+		}
+	}
+
+	/* start the transaction by writing anything to the start register */
+	outb_p(0xFF, SMBHSTSTART);
+
+	/* We will always wait for a fraction of a second! */
+	timeout = 0;
+	do {
+		ali15x3_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
+		 && (timeout++ < MAX_TIMEOUT));
+
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+		result = -1;
+		printk("i2c-ali15x3.o: SMBus Timeout!\n");
+	}
+
+	if (temp & ALI15X3_STS_TERM) {
+		result = -1;
+#ifdef DEBUG
+		printk("i2c-ali15x3.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+/*
+  Unfortunately the ALI SMB controller maps "no response" and "bus collision"
+  into a single bit. No reponse is the usual case so don't
+  do a printk.
+  This means that bus collisions go unreported.
+*/
+	if (temp & ALI15X3_STS_COLL) {
+		result = -1;
+#ifdef DEBUG
+		printk
+		    ("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n",
+		     inb_p(SMBHSTADD));
+#endif
+	}
+
+/* haven't ever seen this */
+	if (temp & ALI15X3_STS_DEV) {
+		result = -1;
+		printk("i2c-ali15x3.o: Error: device error\n");
+	}
+#ifdef DEBUG
+	printk
+	    ("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+	     inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* Return -1 on error. */
+s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
+		   unsigned short flags, char read_write, u8 command,
+		   int size, union i2c_smbus_data * data)
+{
+	int i, len;
+	int temp;
+	int timeout;
+
+/* clear all the bits (clear-on-write) */
+	outb_p(0xFF, SMBHSTSTS);
+/* make sure SMBus is idle */
+	temp = inb_p(SMBHSTSTS);
+	for (timeout = 0;
+	     (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
+	     timeout++) {
+		ali15x3_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	}
+	if (timeout >= MAX_TIMEOUT) {
+		printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n",
+		       temp);
+	}
+
+	switch (size) {
+	case I2C_SMBUS_PROC_CALL:
+		printk
+		    ("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n");
+		return -1;
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		size = ALI15X3_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		size = ALI15X3_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		size = ALI15X3_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		size = ALI15X3_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			len = data->block[0];
+			if (len < 0) {
+				len = 0;
+				data->block[0] = len;
+			}
+			if (len > 32) {
+				len = 32;
+				data->block[0] = len;
+			}
+			outb_p(len, SMBHSTDAT0);
+			outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);	/* Reset SMBBLKDAT */
+			for (i = 1; i <= len; i++)
+				outb_p(data->block[i], SMBBLKDAT);
+		}
+		size = ALI15X3_BLOCK_DATA;
+		break;
+	}
+
+	outb_p(size, SMBHSTCNT);	/* output command */
+
+	if (ali15x3_transaction())	/* Error in transaction */
+		return -1;
+
+	if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
+		return 0;
+
+
+	switch (size) {
+	case ALI15X3_BYTE:	/* Result put in SMBHSTDAT0 */
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case ALI15X3_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case ALI15X3_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	case ALI15X3_BLOCK_DATA:
+		len = inb_p(SMBHSTDAT0);
+		if (len > 32)
+			len = 32;
+		data->block[0] = len;
+		outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);	/* Reset SMBBLKDAT */
+		for (i = 1; i <= data->block[0]; i++) {
+			data->block[i] = inb_p(SMBBLKDAT);
+#ifdef DEBUG
+			printk
+			    ("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n",
+			     len, i, data->block[i]);
+#endif	/* DEBUG */
+		}
+		break;
+	}
+	return 0;
+}
+
+
+u32 ali15x3_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= ali15x3_access,
+	.functionality	= ali15x3_func,
+};
+
+static struct i2c_adapter ali15x3_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id ali15x3_ids[] __devinitdata = {
+	{
+	.vendor =	PCI_VENDOR_ID_AL,
+	.device =	PCI_DEVICE_ID_AL_M7101,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+	},
+	{ 0, }
+};
+
+static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	if (ali15x3_setup(dev)) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n");
+
+		return -ENODEV;
+	}
+
+	/* set up the driverfs linkage to our parent device */
+	ali15x3_adapter.dev.parent = &dev->dev;
+
+	sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
+		ali15x3_smba);
+	return i2c_add_adapter(&ali15x3_adapter);
+}
+
+static void __devexit ali15x3_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&ali15x3_adapter);
+}
+
+static struct pci_driver ali15x3_driver = {
+	.name		= "ali15x3 smbus",
+	.id_table	= ali15x3_ids,
+	.probe		= ali15x3_probe,
+	.remove		= __devexit_p(ali15x3_remove),
+};
+
+static int __init i2c_ali15x3_init(void)
+{
+	printk("i2c-ali15x3.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&ali15x3_driver);
+}
+
+
+static void __exit i2c_ali15x3_exit(void)
+{
+	pci_unregister_driver(&ali15x3_driver);
+	release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("ALI15X3 SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_ali15x3_init);
+module_exit(i2c_ali15x3_exit);
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c	Mon Dec 30 03:32:34 2002
+++ b/drivers/i2c/busses/i2c-amd756.c	Thu Mar 13 16:39:32 2003
@@ -375,6 +375,9 @@
 	printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport);
 #endif
 
+	/* set up the driverfs linkage to our parent device */
+	amd756_adapter.dev.parent = &pdev->dev;
+
 	sprintf(amd756_adapter.name,
 		"SMBus AMD75x adapter at %04x", amd756_ioport);
 
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c	Thu Feb 20 11:48:02 2003
+++ b/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:39:32 2003
@@ -363,6 +363,9 @@
 	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
 
+	/* set up the driverfs linkage to our parent device */
+	smbus->adapter.dev.parent = &dev->dev;
+
 	error = i2c_add_adapter(&smbus->adapter);
 	if (error)
 		goto out_release_region;
@@ -389,7 +392,7 @@
 }
 
 static struct pci_driver amd8111_driver = {
-	.name		= "amd8111 smbus 2.0",
+	.name		= "amd8111 smbus",
 	.id_table	= amd8111_ids,
 	.probe		= amd8111_probe,
 	.remove		= __devexit_p(amd8111_remove),
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:39:32 2003
@@ -0,0 +1,715 @@
+/*
+    i801.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
+    <mdsxyz123@yahoo.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+    SUPPORTED DEVICES	PCI ID
+    82801AA		2413           
+    82801AB		2423           
+    82801BA		2443           
+    82801CA/CAM		2483           
+    82801DB		24C3   (HW PEC supported, 32 byte buffer not supported)
+
+    This driver supports several versions of Intel's I/O Controller Hubs (ICH).
+    For SMBus support, they are similar to the PIIX4 and are part
+    of Intel's '810' and other chipsets.
+    See the doc/busses/i2c-i801 file for details.
+    I2C Block Read and Process Call are not supported.
+*/
+
+/* Note: we assume there can only be one I801, with one SMBus interface */
+
+/* #define DEBUG 1 */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
+
+MODULE_LICENSE("GPL");
+
+#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
+#define HAVE_PEC
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS
+#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS	0x2483
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS
+#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS	0x24C3
+#endif
+
+static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3,
+                          PCI_DEVICE_ID_INTEL_82801AB_3,
+                          PCI_DEVICE_ID_INTEL_82801BA_2,
+			  PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
+			  PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
+                          0 };
+
+/* I801 SMBus address offsets */
+#define SMBHSTSTS (0 + i801_smba)
+#define SMBHSTCNT (2 + i801_smba)
+#define SMBHSTCMD (3 + i801_smba)
+#define SMBHSTADD (4 + i801_smba)
+#define SMBHSTDAT0 (5 + i801_smba)
+#define SMBHSTDAT1 (6 + i801_smba)
+#define SMBBLKDAT (7 + i801_smba)
+#define SMBPEC    (8 + i801_smba)	/* ICH4 only */
+#define SMBAUXSTS (12 + i801_smba)	/* ICH4 only */
+#define SMBAUXCTL (13 + i801_smba)	/* ICH4 only */
+
+/* PCI Address Constants */
+#define SMBBA     0x020
+#define SMBHSTCFG 0x040
+#define SMBREV    0x008
+
+/* Host configuration bits for SMBHSTCFG */
+#define SMBHSTCFG_HST_EN      1
+#define SMBHSTCFG_SMB_SMI_EN  2
+#define SMBHSTCFG_I2C_EN      4
+
+/* Other settings */
+#define MAX_TIMEOUT 100
+#define ENABLE_INT9 0	/* set to 0x01 to enable - untested */
+
+/* I801 command constants */
+#define I801_QUICK          0x00
+#define I801_BYTE           0x04
+#define I801_BYTE_DATA      0x08
+#define I801_WORD_DATA      0x0C
+#define I801_PROC_CALL      0x10	/* later chips only, unimplemented */
+#define I801_BLOCK_DATA     0x14
+#define I801_I2C_BLOCK_DATA 0x18	/* unimplemented */
+#define I801_BLOCK_LAST     0x34
+#define I801_I2C_BLOCK_LAST 0x38	/* unimplemented */
+#define I801_START          0x40
+#define I801_PEC_EN         0x80	/* ICH4 only */
+
+/* insmod parameters */
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the I801 at the given address. VERY DANGEROUS! */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Forcibly enable the I801 at the given address. "
+		 "EXTREMELY DANGEROUS!");
+
+
+
+
+
+static void i801_do_pause(unsigned int amount);
+static int i801_transaction(void);
+static int i801_block_transaction(union i2c_smbus_data *data,
+				  char read_write, int command);
+
+static unsigned short i801_smba;
+static struct pci_dev *I801_dev;
+static int isich4;
+
+static int i801_setup(struct pci_dev *dev)
+{
+	int error_return = 0;
+	int *num = supported;
+	unsigned char temp;
+
+	/* Note: we keep on searching until we have found 'function 3' */
+	if(PCI_FUNC(dev->devfn) != 3)
+		return -ENODEV;
+
+	I801_dev = dev;
+	isich4 = *num == PCI_DEVICE_ID_INTEL_82801DB_SMBUS;
+
+/* Determine the address of the SMBus areas */
+	if (force_addr) {
+		i801_smba = force_addr & 0xfff0;
+	} else {
+		pci_read_config_word(I801_dev, SMBBA, &i801_smba);
+		i801_smba &= 0xfff0;
+		if(i801_smba == 0) {
+			printk(KERN_ERR "i2c-i801.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+			return -ENODEV;
+		}
+	}
+
+	if (check_region(i801_smba, (isich4 ? 16 : 8))) {
+		printk
+		    (KERN_ERR "i2c-i801.o: I801_smb region 0x%x already in use!\n",
+		     i801_smba);
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
+	temp &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
+	pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
+/* If force_addr is set, we program the new address here. Just to make
+   sure, we disable the device first. */
+	if (force_addr) {
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
+		pci_write_config_word(I801_dev, SMBBA, i801_smba);
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
+		printk
+		    (KERN_WARNING "i2c-i801.o: WARNING: I801 SMBus interface set to new "
+		     "address %04x!\n", i801_smba);
+	} else if ((temp & 1) == 0) {
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
+		printk(KERN_WARNING "i2c-i801.o: enabling SMBus device\n");
+	}
+
+	request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus");
+
+#ifdef DEBUG
+	if (temp & 0x02)
+		printk
+		    (KERN_DEBUG "i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
+	else
+		printk
+		    (KERN_DEBUG "i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
+
+	pci_read_config_byte(I801_dev, SMBREV, &temp);
+	printk(KERN_DEBUG "i2c-i801.o: SMBREV = 0x%X\n", temp);
+	printk(KERN_DEBUG "i2c-i801.o: I801_smba = 0x%X\n", i801_smba);
+#endif				/* DEBUG */
+
+      END:
+	return error_return;
+}
+
+
+void i801_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+int i801_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
+	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n",
+		       temp);
+#endif
+		outb_p(temp, SMBHSTSTS);
+		if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Failed! (%02x)\n", temp);
+#endif
+			return -1;
+		} else {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Successfull!\n");
+#endif
+		}
+	}
+
+	outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+
+	/* We will always wait for a fraction of a second! */
+	do {
+		i801_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
+		result = -1;
+#endif
+	}
+
+	if (temp & 0x10) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+	if (temp & 0x08) {
+		result = -1;
+		printk
+		    (KERN_ERR "i2c-i801.o: Bus collision! SMBus may be locked until next hard\n"
+		     "reset. (sorry!)\n");
+		/* Clock stops and slave is stuck in mid-transmission */
+	}
+
+	if (temp & 0x04) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
+#endif
+	}
+
+	if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
+		outb_p(inb(SMBHSTSTS), SMBHSTSTS);
+
+	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Failed reset at end of transaction (%02x)\n",
+		     temp);
+#endif
+	}
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* All-inclusive block transaction function */
+int i801_block_transaction(union i2c_smbus_data *data, char read_write, 
+                           int command)
+{
+	int i, len;
+	int smbcmd;
+	int temp;
+	int result = 0;
+	int timeout;
+        unsigned char hostc, errmask;
+
+        if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+                if (read_write == I2C_SMBUS_WRITE) {
+                        /* set I2C_EN bit in configuration register */
+                        pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
+                        pci_write_config_byte(I801_dev, SMBHSTCFG, 
+                                              hostc | SMBHSTCFG_I2C_EN);
+                } else {
+                        printk("i2c-i801.o: "
+                               "I2C_SMBUS_I2C_BLOCK_READ not supported!\n");
+                        return -1;
+                }
+        }
+
+	if (read_write == I2C_SMBUS_WRITE) {
+		len = data->block[0];
+		if (len < 1)
+			len = 1;
+		if (len > 32)
+			len = 32;
+		outb_p(len, SMBHSTDAT0);
+		outb_p(data->block[1], SMBBLKDAT);
+	} else {
+		len = 32;	/* max for reads */
+	}
+
+	if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+		/* set 32 byte buffer */
+	}
+
+	for (i = 1; i <= len; i++) {
+		if (i == len && read_write == I2C_SMBUS_READ)
+			smbcmd = I801_BLOCK_LAST;
+		else
+			smbcmd = I801_BLOCK_DATA;
+#if 0 /* now using HW PEC */
+		if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC)
+			smbcmd |= I801_PEC_EN;
+#endif
+		outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
+
+#ifdef DEBUG
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Block (pre %d): CNT=%02x, CMD=%02x, ADD=%02x, "
+		     "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT),
+		     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		     inb_p(SMBBLKDAT));
+#endif
+
+		/* Make sure the SMBus host is ready to start transmitting */
+		temp = inb_p(SMBHSTSTS);
+                if (i == 1) {
+                    /* Erronenous conditions before transaction: 
+                     * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
+                    errmask=0x9f; 
+                } else {
+                    /* Erronenous conditions during transaction: 
+                     * Failed, Bus_Err, Dev_Err, Intr */
+                    errmask=0x1e; 
+                }
+		if (temp & errmask) {
+#ifdef DEBUG
+			printk
+			    (KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n",
+			     temp);
+#endif
+			outb_p(temp, SMBHSTSTS);
+			if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
+				printk
+				    (KERN_ERR "i2c-i801.o: Reset failed! (%02x)\n",
+				     temp);
+				result = -1;
+                                goto END;
+			}
+			if (i != 1) {
+                                result = -1;  /* if die in middle of block transaction, fail */
+                                goto END;
+                        }
+		}
+
+		if (i == 1) {
+#if 0 /* #ifdef HAVE_PEC (now using HW PEC) */
+			if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
+				if(read_write == I2C_SMBUS_WRITE)
+					outb_p(data->block[len + 1], SMBPEC);
+			}
+#endif
+			outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+		}
+
+		/* We will always wait for a fraction of a second! */
+		timeout = 0;
+		do {
+			temp = inb_p(SMBHSTSTS);
+			i801_do_pause(1);
+		}
+		    while ((!(temp & 0x80))
+			   && (timeout++ < MAX_TIMEOUT));
+
+		/* If the SMBus is still busy, we give up */
+		if (timeout >= MAX_TIMEOUT) {
+			result = -1;
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
+#endif
+		}
+
+		if (temp & 0x10) {
+			result = -1;
+#ifdef DEBUG
+			printk
+			    (KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
+#endif
+		} else if (temp & 0x08) {
+			result = -1;
+			printk(KERN_ERR "i2c-i801.o: Bus collision!\n");
+		} else if (temp & 0x04) {
+			result = -1;
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
+#endif
+		}
+
+		if (i == 1 && read_write == I2C_SMBUS_READ) {
+			len = inb_p(SMBHSTDAT0);
+			if (len < 1)
+				len = 1;
+			if (len > 32)
+				len = 32;
+			data->block[0] = len;
+		}
+
+                /* Retrieve/store value in SMBBLKDAT */
+		if (read_write == I2C_SMBUS_READ)
+			data->block[i] = inb_p(SMBBLKDAT);
+		if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
+			outb_p(data->block[i+1], SMBBLKDAT);
+		if ((temp & 0x9e) != 0x00)
+			outb_p(temp, SMBHSTSTS);  /* signals SMBBLKDAT ready */
+
+#ifdef DEBUG
+		if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
+			printk
+			    (KERN_DEBUG "i2c-i801.o: Bad status (%02x) at end of transaction\n",
+			     temp);
+		}
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Block (post %d): CNT=%02x, CMD=%02x, ADD=%02x, "
+		     "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT),
+		     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		     inb_p(SMBBLKDAT));
+#endif
+
+		if (result < 0)
+			goto END;
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
+		/* wait for INTR bit as advised by Intel */
+		timeout = 0;
+		do {
+			temp = inb_p(SMBHSTSTS);
+			i801_do_pause(1);
+		} while ((!(temp & 0x02))
+			   && (timeout++ < MAX_TIMEOUT));
+
+		if (timeout >= MAX_TIMEOUT) {
+			printk(KERN_DEBUG "i2c-i801.o: PEC Timeout!\n");
+		}
+#if 0 /* now using HW PEC */
+		if(read_write == I2C_SMBUS_READ) {
+			data->block[len + 1] = inb_p(SMBPEC);
+		}
+#endif
+		outb_p(temp, SMBHSTSTS); 
+	}
+#endif
+        result = 0;
+END:
+        if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+                /* restore saved configuration register value */
+		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
+        }
+	return result;
+}
+
+/* Return -1 on error. */
+s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
+		char read_write, u8 command, int size,
+		union i2c_smbus_data * data)
+{
+	int hwpec = 0;
+	int block = 0;
+	int ret, xact = 0;
+
+#ifdef HAVE_PEC
+	if(isich4)
+		hwpec = (flags & I2C_CLIENT_PEC) != 0;
+#endif
+
+	switch (size) {
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		xact = I801_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		xact = I801_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		xact = I801_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		xact = I801_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+#ifdef HAVE_PEC
+	case I2C_SMBUS_BLOCK_DATA_PEC:
+		if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
+			size = I2C_SMBUS_BLOCK_DATA_PEC;
+#endif
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		block = 1;
+		break;
+	case I2C_SMBUS_PROC_CALL:
+	default:
+		printk(KERN_ERR "i2c-i801.o: Unsupported transaction %d\n", size);
+		return -1;
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && hwpec) {
+		if(size != I2C_SMBUS_QUICK &&
+		   size != I2C_SMBUS_I2C_BLOCK_DATA)
+			outb_p(1, SMBAUXCTL);	/* enable HW PEC */
+	}
+#endif
+	if(block)
+		ret = i801_block_transaction(data, read_write, size);
+	else {
+		outb_p(xact | ENABLE_INT9, SMBHSTCNT);
+		ret = i801_transaction();
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && hwpec) {
+		if(size != I2C_SMBUS_QUICK &&
+		   size != I2C_SMBUS_I2C_BLOCK_DATA)
+			outb_p(0, SMBAUXCTL);
+	}
+#endif
+
+	if(block)
+		return ret;
+	if(ret)
+		return -1;
+	if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
+		return 0;
+
+	switch (xact & 0x7f) {
+	case I801_BYTE:	/* Result put in SMBHSTDAT0 */
+	case I801_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case I801_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	}
+	return 0;
+}
+
+
+u32 i801_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
+#ifdef HAVE_PEC
+	     | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
+	                 I2C_FUNC_SMBUS_HWPEC_CALC
+	               : 0)
+#endif
+	    ;
+}
+
+static struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= i801_access,
+	.functionality	= i801_func,
+};
+
+static struct i2c_adapter i801_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id i801_ids[] __devinitdata = {
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801AA_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801AB_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801BA_2,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{ 0, }
+};
+
+static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+
+	if (i801_setup(dev)) {
+		printk
+		    (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n");
+		return -ENODEV;
+	}
+
+	/* set up the driverfs linkage to our parent device */
+	i801_adapter.dev.parent = &dev->dev;
+
+	sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
+		i801_smba);
+	return i2c_add_adapter(&i801_adapter);
+}
+
+static void __devexit i801_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&i801_adapter);
+}
+
+static struct pci_driver i801_driver = {
+	.name		= "i801 smbus",
+	.id_table	= i801_ids,
+	.probe		= i801_probe,
+	.remove		= __devexit_p(i801_remove),
+};
+
+static int __init i2c_i801_init(void)
+{
+	printk(KERN_INFO "i2c-i801.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&i801_driver);
+}
+
+
+static void __exit i2c_i801_exit(void)
+{
+	pci_unregister_driver(&i801_driver);
+	release_region(i801_smba, (isich4 ? 16 : 8));
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("I801 SMBus driver");
+
+module_init(i2c_i801_init);
+module_exit(i2c_i801_exit);
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:39:32 2003
@@ -0,0 +1,521 @@
+/*
+    piix4.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+   Supports:
+	Intel PIIX4, 440MX
+	Serverworks OSB4, CSB5
+	SMSC Victory66
+
+   Note: we assume there can only be one device, with one SMBus interface.
+*/
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/apm_bios.h>
+#include <asm/io.h>
+
+
+struct sd {
+	const unsigned short mfr;
+	const unsigned short dev;
+	const unsigned char fn;
+	const char *name;
+};
+
+/* PIIX4 SMBus address offsets */
+#define SMBHSTSTS (0 + piix4_smba)
+#define SMBHSLVSTS (1 + piix4_smba)
+#define SMBHSTCNT (2 + piix4_smba)
+#define SMBHSTCMD (3 + piix4_smba)
+#define SMBHSTADD (4 + piix4_smba)
+#define SMBHSTDAT0 (5 + piix4_smba)
+#define SMBHSTDAT1 (6 + piix4_smba)
+#define SMBBLKDAT (7 + piix4_smba)
+#define SMBSLVCNT (8 + piix4_smba)
+#define SMBSHDWCMD (9 + piix4_smba)
+#define SMBSLVEVT (0xA + piix4_smba)
+#define SMBSLVDAT (0xC + piix4_smba)
+
+/* PCI Address Constants */
+#define SMBBA     0x090
+#define SMBHSTCFG 0x0D2
+#define SMBSLVC   0x0D3
+#define SMBSHDW1  0x0D4
+#define SMBSHDW2  0x0D5
+#define SMBREV    0x0D6
+
+/* Other settings */
+#define MAX_TIMEOUT 500
+#define  ENABLE_INT9 0
+
+/* PIIX4 constants */
+#define PIIX4_QUICK      0x00
+#define PIIX4_BYTE       0x04
+#define PIIX4_BYTE_DATA  0x08
+#define PIIX4_WORD_DATA  0x0C
+#define PIIX4_BLOCK_DATA 0x14
+
+/* insmod parameters */
+
+/* If force is set to anything different from 0, we forcibly enable the
+   PIIX4. DANGEROUS! */
+static int force = 0;
+MODULE_PARM(force, "i");
+MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the PIIX4 at the given address. VERY DANGEROUS! */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Forcibly enable the PIIX4 at the given address. "
+		 "EXTREMELY DANGEROUS!");
+
+static void piix4_do_pause(unsigned int amount);
+static int piix4_transaction(void);
+
+
+static unsigned short piix4_smba = 0;
+
+/*
+ * Get DMI information.
+ */
+static int ibm_dmi_probe(void)
+{
+#ifdef CONFIG_X86
+	extern int is_unsafe_smbus;
+	return is_unsafe_smbus;
+#else
+	return 0;
+#endif
+}
+
+static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id)
+{
+	int error_return = 0;
+	unsigned char temp;
+
+	/* match up the function */
+	if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
+		return -ENODEV;
+
+	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name);
+
+	if(ibm_dmi_probe()) {
+		printk
+		  (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n");
+		printk
+		  (KERN_ERR "             your serial eeprom! Refusing to load module!\n");
+		 error_return = -EPERM;
+		 goto END;
+	}
+
+/* Determine the address of the SMBus areas */
+	if (force_addr) {
+		piix4_smba = force_addr & 0xfff0;
+		force = 0;
+	} else {
+		pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
+		piix4_smba &= 0xfff0;
+		if(piix4_smba == 0) {
+			printk(KERN_ERR "i2c-piix4.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+			return -ENODEV;
+		}
+	}
+
+	if (check_region(piix4_smba, 8)) {
+		printk
+		    (KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n",
+		     piix4_smba);
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
+/* If force_addr is set, we program the new address here. Just to make
+   sure, we disable the PIIX4 first. */
+	if (force_addr) {
+		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
+		pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
+		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
+		printk
+		    (KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to new "
+		     "address %04x!\n", piix4_smba);
+	} else if ((temp & 1) == 0) {
+		if (force) {
+/* This should never need to be done, but has been noted that
+   many Dell machines have the SMBus interface on the PIIX4
+   disabled!? NOTE: This assumes I/O space and other allocations WERE
+   done by the Bios!  Don't complain if your hardware does weird 
+   things after enabling this. :') Check for Bios updates before
+   resorting to this.  */
+			pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
+					      temp | 1);
+			printk
+			    (KERN_NOTICE "i2c-piix4.o: WARNING: SMBus interface has been FORCEFULLY "
+			     "ENABLED!\n");
+		} else {
+			printk
+			    (KERN_ERR "i2c-piix4.o: Host SMBus controller not enabled!\n");
+			error_return = -ENODEV;
+			goto END;
+		}
+	}
+
+	/* Everything is happy, let's grab the memory and set things up. */
+	request_region(piix4_smba, 8, "piix4-smbus");
+
+#ifdef DEBUG
+	if ((temp & 0x0E) == 8)
+		printk
+		    (KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for SMBus.\n");
+	else if ((temp & 0x0E) == 0)
+		printk
+		    (KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# for SMBus.\n");
+	else
+		printk
+		    (KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration (or code out "
+		     "of date)!\n");
+
+	pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
+	printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp);
+	printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba);
+#endif				/* DEBUG */
+
+      END:
+	return error_return;
+}
+
+
+/* Internally used pause function */
+static void piix4_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+/* Another internally used function */
+static int piix4_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n",
+		       temp);
+#endif
+		outb_p(temp, SMBHSTSTS);
+		if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+#ifdef DEBUG
+			printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp);
+#endif
+			return -1;
+		} else {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n");
+#endif
+		}
+	}
+
+	/* start the transaction by setting bit 6 */
+	outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
+
+	/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
+	do {
+		piix4_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+
+#ifdef DEBUG
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+		printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n");
+		result = -1;
+	}
+#endif
+
+	if (temp & 0x10) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+	if (temp & 0x08) {
+		result = -1;
+		printk
+		    (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n"
+		     "reset. (sorry!)\n");
+		/* Clock stops and slave is stuck in mid-transmission */
+	}
+
+	if (temp & 0x04) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_ERR "i2c-piix4.o: Error: no response!\n");
+#endif
+	}
+
+	if (inb_p(SMBHSTSTS) != 0x00)
+		outb_p(inb(SMBHSTSTS), SMBHSTSTS);
+
+#ifdef DEBUG
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+		printk
+		    (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n",
+		     temp);
+	}
+	printk
+	    (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* Return -1 on error. */
+static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
+		 unsigned short flags, char read_write,
+		 u8 command, int size, union i2c_smbus_data * data)
+{
+	int i, len;
+
+	switch (size) {
+	case I2C_SMBUS_PROC_CALL:
+		printk
+		    (KERN_ERR "i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n");
+		return -1;
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		size = PIIX4_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		size = PIIX4_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		size = PIIX4_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		size = PIIX4_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			len = data->block[0];
+			if (len < 0)
+				len = 0;
+			if (len > 32)
+				len = 32;
+			outb_p(len, SMBHSTDAT0);
+			i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+			for (i = 1; i <= len; i++)
+				outb_p(data->block[i], SMBBLKDAT);
+		}
+		size = PIIX4_BLOCK_DATA;
+		break;
+	}
+
+	outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
+
+	if (piix4_transaction())	/* Error in transaction */
+		return -1;
+
+	if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
+		return 0;
+
+
+	switch (size) {
+	case PIIX4_BYTE:	/* Where is the result put? I assume here it is in
+				   SMBHSTDAT0 but it might just as well be in the
+				   SMBHSTCMD. No clue in the docs */
+
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case PIIX4_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case PIIX4_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	case PIIX4_BLOCK_DATA:
+		data->block[0] = inb_p(SMBHSTDAT0);
+		i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+		for (i = 1; i <= data->block[0]; i++)
+			data->block[i] = inb_p(SMBBLKDAT);
+		break;
+	}
+	return 0;
+}
+
+
+static u32 piix4_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= piix4_access,
+	.functionality	= piix4_func,
+};
+
+static struct i2c_adapter piix4_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id piix4_ids[] __devinitdata = {
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82371AB_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	3
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_SERVERWORKS,
+		.device =	PCI_DEVICE_ID_SERVERWORKS_OSB4,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_SERVERWORKS,
+		.device =	PCI_DEVICE_ID_SERVERWORKS_CSB5,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82443MX_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	3,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_EFAR,
+		.device =	PCI_DEVICE_ID_EFAR_SLC90E66_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
+	{ 0, }
+};
+
+static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int retval;
+	
+	retval = piix4_setup(dev, id);
+	if (retval)
+		return retval;
+
+	/* set up the driverfs linkage to our parent device */
+	piix4_adapter.dev.parent = &dev->dev;
+
+	sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
+		piix4_smba);
+
+	retval = i2c_add_adapter(&piix4_adapter);
+
+	return retval;
+}
+
+static void __devexit piix4_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&piix4_adapter);
+}
+
+
+static struct pci_driver piix4_driver = {
+	.name		= "piix4 smbus",
+	.id_table	= piix4_ids,
+	.probe		= piix4_probe,
+	.remove		= __devexit_p(piix4_remove),
+};
+
+static int __init i2c_piix4_init(void)
+{
+	printk("i2c-piix4.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&piix4_driver);
+}
+
+
+static void __exit i2c_piix4_exit(void)
+{
+	pci_unregister_driver(&piix4_driver);
+	release_region(piix4_smba, 8);
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
+MODULE_DESCRIPTION("PIIX4 SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_piix4_init);
+module_exit(i2c_piix4_exit);
diff -Nru a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c
--- a/drivers/i2c/i2c-algo-bit.c	Tue Feb  4 12:58:09 2003
+++ b/drivers/i2c/i2c-algo-bit.c	Tue Mar 11 12:21:11 2003
@@ -41,27 +41,13 @@
 #define DEBPROTO(x) if (i2c_debug>=9) { x; }
  	/* debug the protocol by showing transferred bits */
 
-/* debugging - slow down transfer to have a look at the data .. 	*/
-/* I use this with two leds&resistors, each one connected to sda,scl 	*/
-/* respectively. This makes sure that the algorithm works. Some chips   */
-/* might not like this, as they have an internal timeout of some mils	*/
-/*
-#define SLO_IO      jif=jiffies;while(time_before_eq(jiffies, jif+i2c_table[minor].veryslow))\
-                        cond_resched();
-*/
-
 
 /* ----- global variables ---------------------------------------------	*/
 
-#ifdef SLO_IO
-	int jif;
-#endif
-
 /* module parameters:
  */
 static int i2c_debug;
 static int bit_test;	/* see if the line-setting functions work	*/
-static int bit_scan;	/* have a look at what's hanging 'round		*/
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -86,9 +72,6 @@
 {
 	setscl(adap,0);
 	udelay(adap->udelay);
-#ifdef SLO_IO
-	SLO_IO
-#endif
 }
 
 /*
@@ -97,32 +80,28 @@
  */
 static inline int sclhi(struct i2c_algo_bit_data *adap)
 {
-	int start=jiffies;
+	unsigned long start;
 
 	setscl(adap,1);
 
-	udelay(adap->udelay);
-
 	/* Not all adapters have scl sense line... */
 	if (adap->getscl == NULL )
 		return 0;
 
- 	while (! getscl(adap) ) {	
+	start=jiffies;
+	while (! getscl(adap) ) {	
  		/* the hw knows how to read the clock line,
  		 * so we wait until it actually gets high.
  		 * This is safer as some chips may hold it low
  		 * while they are processing data internally. 
  		 */
-		setscl(adap,1);
 		if (time_after_eq(jiffies, start+adap->timeout)) {
 			return -ETIMEDOUT;
 		}
 		cond_resched();
 	}
 	DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
-#ifdef SLO_IO
-	SLO_IO
-#endif
+	udelay(adap->udelay);
 	return 0;
 } 
 
@@ -175,7 +154,6 @@
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 
 	/* assert: scl is low */
-	DEB2(printk(KERN_DEBUG " i2c_outb:%2.2X\n",c&0xff));
 	for ( i=7 ; i>=0 ; i-- ) {
 		sb = c & ( 1 << i );
 		setsda(adap,sb);
@@ -183,6 +161,7 @@
 		DEBPROTO(printk(KERN_DEBUG "%d",sb!=0));
 		if (sclhi(adap)<0) { /* timed out */
 			sdahi(adap); /* we don't want to block the net */
+			DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i));
 			return -ETIMEDOUT;
 		};
 		/* do arbitration here: 
@@ -193,11 +172,12 @@
 	}
 	sdahi(adap);
 	if (sclhi(adap)<0){ /* timeout */
-		return -ETIMEDOUT;
+	    DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff));
+	    return -ETIMEDOUT;
 	};
 	/* read ack: SDA should be pulled down by slave */
 	ack=getsda(adap);	/* ack: sda is pulled low ->success.	 */
-	DEB2(printk(KERN_DEBUG " i2c_outb: getsda() =  0x%2.2x\n", ~ack ));
+	DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack));
 
 	DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) );
 	DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") );
@@ -216,11 +196,10 @@
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 
 	/* assert: scl is low */
-	DEB2(printk(KERN_DEBUG "i2c_inb.\n"));
-
 	sdahi(adap);
 	for (i=0;i<8;i++) {
 		if (sclhi(adap)<0) { /* timeout */
+			DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i));
 			return -ETIMEDOUT;
 		};
 		indata *= 2;
@@ -229,7 +208,9 @@
 		scllo(adap);
 	}
 	/* assert: scl is low */
-	DEBPROTO(printk(KERN_DEBUG " %2.2x", indata & 0xff));
+	DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff));
+
+	DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff));
 	return (int) (indata & 0xff);
 }
 
@@ -337,30 +318,35 @@
 		i2c_start(adap);
 		udelay(adap->udelay);
 	}
-	DEB2(if (i) printk(KERN_DEBUG "i2c-algo-bit.o: needed %d retries for %d\n",
-	                   i,addr));
+	DEB2(if (i)
+	     printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n",
+		    i+1, addr & 1 ? "read" : "write", addr>>1,
+		    ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" )
+	    );
 	return ret;
 }
 
-static int sendbytes(struct i2c_adapter *i2c_adap,const char *buf, int count)
+static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 	char c;
-	const char *temp = buf;
+	const char *temp = msg->buf;
+	int count = msg->len;
+	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 
 	int retval;
 	int wrcount=0;
 
 	while (count > 0) {
 		c = *temp;
-		DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s i2c_write: writing %2.2X\n",
+		DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s sendbytes: writing %2.2X\n",
 			    i2c_adap->name, c&0xff));
 		retval = i2c_outb(i2c_adap,c);
-		if (retval>0) {
+		if ((retval>0) || (nak_ok && (retval==0)))  { /* ok or ignored NAK */
 			count--; 
 			temp++;
 			wrcount++;
 		} else { /* arbitration or no acknowledge */
-			printk(KERN_ERR "i2c-algo-bit.o: %s i2c_write: error - bailout.\n",
+			printk(KERN_ERR "i2c-algo-bit.o: %s sendbytes: error - bailout.\n",
 			       i2c_adap->name);
 			i2c_stop(adap);
 			return (retval<0)? retval : -EFAULT;
@@ -374,12 +360,13 @@
 	return wrcount;
 }
 
-static inline int readbytes(struct i2c_adapter *i2c_adap,char *buf,int count)
+static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
-	char *temp = buf;
 	int inval;
 	int rdcount=0;   	/* counts bytes read */
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+	char *temp = msg->buf;
+	int count = msg->len;
 
 	while (count > 0) {
 		inval = i2c_inb(i2c_adap);
@@ -388,7 +375,7 @@
 			*temp = inval;
 			rdcount++;
 		} else {   /* read timed out */
-			printk(KERN_ERR "i2c-algo-bit.o: i2c_read: i2c_inb timed out.\n");
+			printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n");
 			break;
 		}
 
@@ -401,7 +388,7 @@
 		}
 		if (sclhi(adap)<0) {	/* timeout */
 			sdahi(adap);
-			printk(KERN_ERR "i2c-algo-bit.o: i2c_read: Timeout at ack\n");
+			printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n");
 			return -ETIMEDOUT;
 		};
 		scllo(adap);
@@ -416,31 +403,34 @@
  * try_address) and transmits the address in the necessary format to handle
  * reads, writes as well as 10bit-addresses.
  * returns:
- *  0 everything went okay, the chip ack'ed
+ *  0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set
  * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
  *	-ETIMEDOUT, for example if the lines are stuck...) 
  */
-static inline int bit_doAddress(struct i2c_adapter *i2c_adap,
-                                struct i2c_msg *msg, int retries) 
+static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) 
 {
 	unsigned short flags = msg->flags;
+	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 
 	unsigned char addr;
-	int ret;
+	int ret, retries;
+
+	retries = nak_ok ? 0 : i2c_adap->retries;
+	
 	if ( (flags & I2C_M_TEN)  ) { 
 		/* a ten bit address */
 		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
 		DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
 		/* try extended address code...*/
 		ret = try_address(i2c_adap, addr, retries);
-		if (ret!=1) {
+		if ((ret != 1) && !nak_ok)  {
 			printk(KERN_ERR "died at extended address code.\n");
 			return -EREMOTEIO;
 		}
 		/* the remaining 8 bit address */
 		ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
-		if (ret != 1) {
+		if ((ret != 1) && !nak_ok) {
 			/* the chip did not ack / xmission error occurred */
 			printk(KERN_ERR "died at 2nd address code.\n");
 			return -EREMOTEIO;
@@ -450,7 +440,7 @@
 			/* okay, now switch into reading mode */
 			addr |= 0x01;
 			ret = try_address(i2c_adap, addr, retries);
-			if (ret!=1) {
+			if ((ret!=1) && !nak_ok) {
 				printk(KERN_ERR "died at extended address code.\n");
 				return -EREMOTEIO;
 			}
@@ -462,10 +452,10 @@
 		if (flags & I2C_M_REV_DIR_ADDR )
 			addr ^= 1;
 		ret = try_address(i2c_adap, addr, retries);
-		if (ret!=1) {
+		if ((ret!=1) && !nak_ok)
 			return -EREMOTEIO;
-		}
 	}
+
 	return 0;
 }
 
@@ -476,31 +466,33 @@
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 	
 	int i,ret;
+	unsigned short nak_ok;
 
 	i2c_start(adap);
 	for (i=0;i<num;i++) {
 		pmsg = &msgs[i];
+		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 
 		if (!(pmsg->flags & I2C_M_NOSTART)) {
 			if (i) {
 				i2c_repstart(adap);
 			}
-			ret = bit_doAddress(i2c_adap,pmsg,i2c_adap->retries);
-			if (ret != 0) {
-				DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device adr %#2x msg #%d\n"
-				       ,msgs[i].addr,i));
-				return (ret<0) ? ret : -EREMOTEIO;
+			ret = bit_doAddress(i2c_adap, pmsg);
+			if ((ret != 0) && !nak_ok) {
+			    DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n"
+					,msgs[i].addr,i));
+			    return (ret<0) ? ret : -EREMOTEIO;
 			}
 		}
 		if (pmsg->flags & I2C_M_RD ) {
 			/* read bytes into buffer*/
-			ret = readbytes(i2c_adap,pmsg->buf,pmsg->len);
+			ret = readbytes(i2c_adap, pmsg);
 			DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret));
 			if (ret < pmsg->len ) {
 				return (ret<0)? ret : -EREMOTEIO;
 			}
 		} else {
 			/* write bytes from buffer */
-			ret = sendbytes(i2c_adap,pmsg->buf,pmsg->len);
+			ret = sendbytes(i2c_adap, pmsg);
 			DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret));
 			if (ret < pmsg->len ) {
 				return (ret<0) ? ret : -EREMOTEIO;
@@ -511,12 +503,6 @@
 	return num;
 }
 
-static int algo_control(struct i2c_adapter *adapter, 
-	unsigned int cmd, unsigned long arg)
-{
-	return 0;
-}
-
 static u32 bit_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
@@ -530,7 +516,6 @@
 	.name		= "Bit-shift algorithm",
 	.id		= I2C_ALGO_BIT,
 	.master_xfer	= bit_xfer,
-	.algo_control	= algo_control,
 	.functionality	= bit_func,
 };
 
@@ -539,7 +524,6 @@
  */
 int i2c_bit_add_bus(struct i2c_adapter *adap)
 {
-	int i;
 	struct i2c_algo_bit_data *bit_adap = adap->algo_data;
 
 	if (bit_test) {
@@ -559,23 +543,6 @@
 	adap->timeout = 100;	/* default values, should	*/
 	adap->retries = 3;	/* be replaced by defines	*/
 
-	/* scan bus */
-	if (bit_scan) {
-		int ack;
-		printk(KERN_INFO " i2c-algo-bit.o: scanning bus %s.\n",
-		       adap->name);
-		for (i = 0x00; i < 0xff; i+=2) {
-			i2c_start(bit_adap);
-			ack = i2c_outb(adap,i);
-			i2c_stop(bit_adap);
-			if (ack>0) {
-				printk("(%02x)",i>>1); 
-			} else 
-				printk("."); 
-		}
-		printk("\n");
-	}
-
 	i2c_add_adapter(adap);
 	return 0;
 }
@@ -583,14 +550,7 @@
 
 int i2c_bit_del_bus(struct i2c_adapter *adap)
 {
-	int res;
-
-	if ((res = i2c_del_adapter(adap)) < 0)
-		return res;
-
-	DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: adapter unregistered: %s\n",adap->name));
-
-	return 0;
+	return i2c_del_adapter(adap);
 }
 
 EXPORT_SYMBOL(i2c_bit_add_bus);
@@ -601,10 +561,8 @@
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(bit_test, "i");
-MODULE_PARM(bit_scan, "i");
 MODULE_PARM(i2c_debug,"i");
 
 MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
-MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
 MODULE_PARM_DESC(i2c_debug,
-            "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
+		 "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
diff -Nru a/drivers/i2c/i2c-algo-ibm_ocp.c b/drivers/i2c/i2c-algo-ibm_ocp.c
--- a/drivers/i2c/i2c-algo-ibm_ocp.c	Mon Feb 24 12:42:23 2003
+++ b/drivers/i2c/i2c-algo-ibm_ocp.c	Tue Mar 11 12:21:11 2003
@@ -55,20 +55,12 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
-
 #include <linux/i2c.h>
-#include "i2c-algo-ibm_ocp.h"
-//ACC#include <asm/ocp.h>
-
-#ifdef MODULE_LICENSE
-MODULE_LICENSE("GPL");
-#endif
+#include <linux/i2c-algo-ibm_ocp.h>
+#include <asm/ocp.h>
 
 
 /* ----- global defines ----------------------------------------------- */
@@ -79,26 +71,13 @@
  	/* debug the protocol by showing transferred bits */
 #define DEF_TIMEOUT 5
 
-/* debugging - slow down transfer to have a look at the data .. 	*/
-/* I use this with two leds&resistors, each one connected to sda,scl 	*/
-/* respectively. This makes sure that the algorithm works. Some chips   */
-/* might not like this, as they have an internal timeout of some mils	*/
-/*
-#define SLO_IO      jif=jiffies;while(time_before_eq(jiffies,jif+i2c_table[minor].veryslow))\
-                        if (need_resched) schedule();
-*/
-
 
 /* ----- global variables ---------------------------------------------	*/
 
-#ifdef SLO_IO
-	int jif;
-#endif
 
 /* module parameters:
  */
 static int i2c_debug=0;
-static int iic_scan=0;	/* have a look at what's hanging 'round		*/
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -758,7 +737,7 @@
         // Check to see if the bus is busy
         //
         ret = iic_inb(adap, iic->extsts);
-        // Mask off the irrelevant bits
+        // Mask off the irrelevent bits
         ret = ret & 0x70;
         // When the bus is free, the BCS bits in the EXTSTS register are 0b100
         if(ret != 0x40) return IIC_ERR_LOST_ARB;
@@ -858,17 +837,13 @@
 /* -----exported algorithm data: -------------------------------------	*/
 
 static struct i2c_algorithm iic_algo = {
-	"IBM on-chip IIC algorithm",
-	I2C_ALGO_OCP,
-	iic_xfer,
-	NULL,
-	NULL,				/* slave_xmit		*/
-	NULL,				/* slave_recv		*/
-	algo_control,			/* ioctl		*/
-	iic_func,			/* functionality	*/
+	.name		= "IBM on-chip IIC algorithm",
+	.id		= I2C_ALGO_OCP,
+	.master_xfer	= iic_xfer,
+	.algo_control	= algo_control,
+	.functionality	= iic_func,
 };
 
-
 /* 
  * registering functions to load algorithms at runtime 
  */
@@ -892,19 +867,8 @@
 	adap->timeout = 100;	/* default values, should	*/
 	adap->retries = 3;		/* be replaced by defines	*/
 
-#ifdef MODULE
-	MOD_INC_USE_COUNT;
-#endif
-
 	iic_init(iic_adap);
 	i2c_add_adapter(adap);
-
-	/* scan bus */
-	/* By default scanning the bus is turned off. */
-	if (iic_scan) {
-		printk(KERN_INFO " i2c-algo-iic.o: scanning bus %s.\n",
-		       adap->name);
-	}
 	return 0;
 }
 
@@ -914,31 +878,7 @@
 //
 int i2c_ocp_del_bus(struct i2c_adapter *adap)
 {
-	int res;
-	if ((res = i2c_del_adapter(adap)) < 0)
-		return res;
-	DEB2(printk(KERN_DEBUG "i2c-algo-iic.o: adapter unregistered: %s\n",adap->name));
-
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
-	return 0;
-}
-
-
-//
-// Done
-//
-int __init i2c_algo_iic_init (void)
-{
-	printk(KERN_INFO "IBM On-chip iic (i2c) algorithm module 2002.27.03\n");
-	return 0;
-}
-
-
-void i2c_algo_iic_exit(void)
-{
-	return;
+	return i2c_del_adapter(adap);
 }
 
 
@@ -951,16 +891,10 @@
 //
 MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
 MODULE_DESCRIPTION("PPC 405 iic algorithm");
+MODULE_LICENSE("GPL");
 
-MODULE_PARM(iic_test, "i");
-MODULE_PARM(iic_scan, "i");
 MODULE_PARM(i2c_debug,"i");
 
-MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
-MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus");
 MODULE_PARM_DESC(i2c_debug,
         "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
 
-
-module_init(i2c_algo_iic_init);
-module_exit(i2c_algo_iic_exit);
diff -Nru a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c
--- a/drivers/i2c/i2c-algo-pcf.c	Tue Feb  4 12:58:09 2003
+++ b/drivers/i2c/i2c-algo-pcf.c	Tue Mar 11 12:21:11 2003
@@ -49,7 +49,6 @@
 /* module parameters:
  */
 static int i2c_debug=0;
-static int pcf_scan=0;	/* have a look at what's hanging 'round		*/
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -423,12 +422,6 @@
 	return (i);
 }
 
-static int algo_control(struct i2c_adapter *adapter, 
-	unsigned int cmd, unsigned long arg)
-{
-	return 0;
-}
-
 static u32 pcf_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
@@ -438,14 +431,10 @@
 /* -----exported algorithm data: -------------------------------------	*/
 
 static struct i2c_algorithm pcf_algo = {
-	"PCF8584 algorithm",
-	I2C_ALGO_PCF,
-	pcf_xfer,
-	NULL,
-	NULL,				/* slave_xmit		*/
-	NULL,				/* slave_recv		*/
-	algo_control,			/* ioctl		*/
-	pcf_func,			/* functionality	*/
+	.name		= "PCF8584 algorithm",
+	.id		= I2C_ALGO_PCF,
+	.master_xfer	= pcf_xfer,
+	.functionality	= pcf_func,
 };
 
 /* 
@@ -453,8 +442,8 @@
  */
 int i2c_pcf_add_bus(struct i2c_adapter *adap)
 {
-	int i, status;
 	struct i2c_algo_pcf_data *pcf_adap = adap->algo_data;
+	int rval;
 
 	DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: hw routines for %s registered.\n",
 	            adap->name));
@@ -467,36 +456,10 @@
 	adap->timeout = 100;		/* default values, should	*/
 	adap->retries = 3;		/* be replaced by defines	*/
 
-	if ((i = pcf_init_8584(pcf_adap))) {
-		return i;
-	}
-
-	i2c_add_adapter(adap);
-
-	/* scan bus */
-	if (pcf_scan) {
-		printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s.\n",
-		       adap->name);
-		for (i = 0x00; i < 0xff; i+=2) {
-			if (wait_for_bb(pcf_adap)) {
-    			printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s - TIMEOUTed.\n",
-		           adap->name);
-			    break;
-			}
-			i2c_outb(pcf_adap, i);
-			i2c_start(pcf_adap);
-			if ((wait_for_pin(pcf_adap, &status) >= 0) && 
-			    ((status & I2C_PCF_LRB) == 0)) { 
-				printk("(%02x)",i>>1); 
-			} else {
-				printk("."); 
-			}
-			i2c_stop(pcf_adap);
-			udelay(pcf_adap->udelay);
-		}
-		printk("\n");
-	}
-	return 0;
+	rval = pcf_init_8584(pcf_adap);
+	if (!rval)
+		i2c_add_adapter(adap);
+	return rval;
 }
 
 
@@ -512,9 +475,6 @@
 MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(pcf_scan, "i");
 MODULE_PARM(i2c_debug,"i");
-
-MODULE_PARM_DESC(pcf_scan, "Scan for active chips on the bus");
 MODULE_PARM_DESC(i2c_debug,
         "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	Thu Feb 20 11:58:55 2003
+++ b/drivers/i2c/i2c-core.c	Fri Mar 14 19:51:45 2003
@@ -21,69 +21,35 @@
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
    SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com>                */
 
-/* $Id: i2c-core.c,v 1.89 2002/11/03 16:47:16 mds Exp $ */
+/* $Id: i2c-core.c,v 1.95 2003/01/22 05:25:08 kmalkki Exp $ */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
-#include <linux/config.h>
 #include <linux/i2c.h>
-
-/* ----- compatibility stuff ----------------------------------------------- */
-
-#include <linux/version.h>
 #include <linux/init.h>
-
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 
-/* ----- global defines ---------------------------------------------------- */
-
-/* exclusive access to the bus */
-#define I2C_LOCK(adap) down(&adap->lock)
-#define I2C_UNLOCK(adap) up(&adap->lock) 
-
-#define ADAP_LOCK()	down(&adap_lock)
-#define ADAP_UNLOCK()	up(&adap_lock)
-
-#define DRV_LOCK()	down(&driver_lock)
-#define DRV_UNLOCK()	up(&driver_lock)
 
 #define DEB(x) if (i2c_debug>=1) x;
 #define DEB2(x) if (i2c_debug>=2) x;
 
-/* ----- global variables -------------------------------------------------- */
-
-/**** lock for writing to global variables: the adapter & driver list */
-static DECLARE_MUTEX(adap_lock);
-static DECLARE_MUTEX(driver_lock);
-
-/**** adapter list */
 static struct i2c_adapter *adapters[I2C_ADAP_MAX];
-
-/**** drivers list */
 static struct i2c_driver *drivers[I2C_DRIVER_MAX];
+static DECLARE_MUTEX(core_lists);
 
 /**** debug level */
 static int i2c_debug;
 
-/* ---------------------------------------------------
- * /proc entry declarations
- *----------------------------------------------------
- */
-
 #ifdef CONFIG_PROC_FS
-static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, 
-                                loff_t *ppos);
-static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
-                           int *eof , void *private);
-
-/* To implement the dynamic /proc/bus/i2c-? files, we need our own 
-   implementation of the read hook */
-static struct file_operations i2cproc_operations = {
-	.read		= i2cproc_bus_read,
-};
+static int i2cproc_register(struct i2c_adapter *adap, int bus);
+static void i2cproc_remove(int bus);
+#else
+# define i2cproc_register(adap, bus)	0
+# define i2cproc_remove(bus)		do { } while (0)
 #endif /* CONFIG_PROC_FS */
 
 
@@ -99,9 +65,9 @@
  */
 int i2c_add_adapter(struct i2c_adapter *adap)
 {
-	int i,j,res;
+	int res = 0, i, j;
 
-	ADAP_LOCK();
+	down(&core_lists);
 	for (i = 0; i < I2C_ADAP_MAX; i++)
 		if (NULL == adapters[i])
 			break;
@@ -110,66 +76,50 @@
 		       " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
 			adap->name);
 		res = -ENOMEM;
-		goto ERROR0;
+		goto out_unlock;
 	}
 
-	adapters[i] = adap;
-	ADAP_UNLOCK();
-	
-	/* init data types */
-	init_MUTEX(&adap->lock);
+	res = i2cproc_register(adap, i);
+	if (res)
+		goto out_unlock;
 
-#ifdef CONFIG_PROC_FS
-	{
-		char name[8];
-		struct proc_dir_entry *proc_entry;
-
-		sprintf(name,"i2c-%d", i);
+	adapters[i] = adap;
 
-		proc_entry = create_proc_entry(name,0,proc_bus);
-		if (! proc_entry) {
-			printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n",
-			       name);
-			res = -ENOENT;
-			goto ERROR1;
-		}
+	init_MUTEX(&adap->bus);
+	init_MUTEX(&adap->list);
 
-		proc_entry->proc_fops = &i2cproc_operations;
-		proc_entry->owner = THIS_MODULE;
-		adap->inode = proc_entry->low_ino;
-	}
-#endif /* def CONFIG_PROC_FS */
+	/* Add the adapter to the driver core.
+	 * If the parent pointer is not set up,
+	 * we add this adapter to the legacy bus.
+	 */
+	if (adap->dev.parent == NULL)
+		adap->dev.parent = &legacy_bus;
+	sprintf(adap->dev.bus_id, "i2c-%d", i);
+	strcpy(adap->dev.name, "i2c controller");
+	device_register(&adap->dev);
 
 	/* inform drivers of new adapters */
-	DRV_LOCK();	
 	for (j=0;j<I2C_DRIVER_MAX;j++)
 		if (drivers[j]!=NULL && 
 		    (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY)))
 			/* We ignore the return code; if it fails, too bad */
 			drivers[j]->attach_adapter(adap);
-	DRV_UNLOCK();
+	up(&core_lists);
 	
 	DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
 	           adap->name,i));
 
-	return 0;	
-
-
-ERROR1:
-	ADAP_LOCK();
-	adapters[i] = NULL;
-ERROR0:
-	ADAP_UNLOCK();
-	return res;
+ out_unlock:
+	up(&core_lists);
+	return res;;
 }
 
 
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
-	int i,j,res;
-
-	ADAP_LOCK();
+	int res = 0, i, j;
 
+	down(&core_lists);
 	for (i = 0; i < I2C_ADAP_MAX; i++)
 		if (adap == adapters[i])
 			break;
@@ -177,7 +127,7 @@
 		printk( KERN_WARNING "i2c-core.o: unregister_adapter adap [%s] not found.\n",
 			adap->name);
 		res = -ENODEV;
-		goto ERROR0;
+		goto out_unlock;
 	}
 
 	/* DUMMY drivers do not register their clients, so we have to
@@ -185,23 +135,20 @@
 	 * *detach* it! Of course, each dummy driver should know about
 	 * this or hell will break loose...
 	 */
-	DRV_LOCK();
 	for (j = 0; j < I2C_DRIVER_MAX; j++) 
 		if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
 			if ((res = drivers[j]->attach_adapter(adap))) {
 				printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
 				       "while detaching driver %s: driver not "
 				       "detached!",adap->name,drivers[j]->name);
-				goto ERROR1;	
+				goto out_unlock;
 			}
-	DRV_UNLOCK();
-
 
 	/* detach any active clients. This must be done first, because
 	 * it can fail; in which case we give upp. */
 	for (j=0;j<I2C_CLIENT_MAX;j++) {
 		struct i2c_client *client = adap->clients[j];
-		if (client!=NULL)
+		if (client!=NULL) {
 		    /* detaching devices is unconditional of the set notify
 		     * flag, as _all_ clients that reside on the adapter
 		     * must be deleted, as this would cause invalid states.
@@ -211,28 +158,22 @@
 					"unregistered, because client at "
 					"address %02x can't be detached. ",
 					adap->name, client->addr);
-				goto ERROR0;
+				goto out_unlock;
 			}
+		}
 	}
-#ifdef CONFIG_PROC_FS
-	{
-		char name[8];
-		sprintf(name,"i2c-%d", i);
-		remove_proc_entry(name, proc_bus);
-	}
-#endif /* def CONFIG_PROC_FS */
+
+	i2cproc_remove(i);
+
+	/* clean up the sysfs representation */
+	device_unregister(&adap->dev);
 
 	adapters[i] = NULL;
-	
-	ADAP_UNLOCK();	
+
 	DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
-	return 0;
 
-ERROR0:
-	ADAP_UNLOCK();
-	return res;
-ERROR1:
-	DRV_UNLOCK();
+ out_unlock:
+	up(&core_lists);
 	return res;
 }
 
@@ -245,8 +186,9 @@
 
 int i2c_add_driver(struct i2c_driver *driver)
 {
-	int i;
-	DRV_LOCK();
+	int res = 0, i;
+
+	down(&core_lists);
 	for (i = 0; i < I2C_DRIVER_MAX; i++)
 		if (NULL == drivers[i])
 			break;
@@ -255,35 +197,34 @@
 		       " i2c-core.o: register_driver(%s) "
 		       "- enlarge I2C_DRIVER_MAX.\n",
 			driver->name);
-		DRV_UNLOCK();
-		return -ENOMEM;
+		res = -ENOMEM;
+		goto out_unlock;
 	}
 
 	drivers[i] = driver;
 	
-	DRV_UNLOCK();	/* driver was successfully added */
-	
 	DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name));
 	
-	ADAP_LOCK();
-
 	/* now look for instances of driver on our adapters
 	 */
 	if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) {
-		for (i=0;i<I2C_ADAP_MAX;i++)
+		for (i=0;i<I2C_ADAP_MAX;i++) {
 			if (adapters[i]!=NULL)
 				/* Ignore errors */
 				driver->attach_adapter(adapters[i]);
+		}
 	}
-	ADAP_UNLOCK();
-	return 0;
+
+ out_unlock:
+	up(&core_lists);
+	return res;
 }
 
 int i2c_del_driver(struct i2c_driver *driver)
 {
-	int i,j,k,res;
+	int res = 0, i, j, k;
 
-	DRV_LOCK();
+	down(&core_lists);
 	for (i = 0; i < I2C_DRIVER_MAX; i++)
 		if (driver == drivers[i])
 			break;
@@ -291,19 +232,20 @@
 		printk(KERN_WARNING " i2c-core.o: unregister_driver: "
 				    "[%s] not found\n",
 			driver->name);
-		DRV_UNLOCK();
-		return -ENODEV;
+		res = -ENODEV;
+		goto out_unlock;
 	}
+
 	/* Have a look at each adapter, if clients of this driver are still
 	 * attached. If so, detach them to be able to kill the driver 
 	 * afterwards.
 	 */
 	DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n"));
+
 	/* removing clients does not depend on the notify flag, else 
 	 * invalid operation might (will!) result, when using stale client
 	 * pointers.
 	 */
-	ADAP_LOCK(); /* should be moved inside the if statement... */
 	for (k=0;k<I2C_ADAP_MAX;k++) {
 		struct i2c_adapter *adap = adapters[k];
 		if (adap == NULL) /* skip empty entries. */
@@ -322,8 +264,7 @@
 				       "not be detached properly; driver "
 				       "not unloaded!",driver->name,
 				       adap->name);
-				ADAP_UNLOCK();
-				return res;
+				goto out_unlock;
 			}
 		} else {
 			for (j=0;j<I2C_CLIENT_MAX;j++) { 
@@ -346,62 +287,84 @@
 						       driver->name,
 						       client->addr,
 						       adap->name);
-						ADAP_UNLOCK();
-						return res;
+						goto out_unlock;
 					}
 				}
 			}
 		}
 	}
-	ADAP_UNLOCK();
 	drivers[i] = NULL;
-	DRV_UNLOCK();
 	
 	DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name));
+
+ out_unlock:
+	up(&core_lists);
 	return 0;
 }
 
-int i2c_check_addr (struct i2c_adapter *adapter, int addr)
+static int __i2c_check_addr(struct i2c_adapter *adapter, int addr)
 {
 	int i;
-	for (i = 0; i < I2C_CLIENT_MAX ; i++) 
+
+	for (i = 0; i < I2C_CLIENT_MAX ; i++)
 		if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
 			return -EBUSY;
+
 	return 0;
 }
 
+int i2c_check_addr(struct i2c_adapter *adapter, int addr)
+{
+	int rval;
+
+	down(&adapter->list);
+	rval = __i2c_check_addr(adapter, addr);
+	up(&adapter->list);
+
+	return rval;
+}
+
 int i2c_attach_client(struct i2c_client *client)
 {
 	struct i2c_adapter *adapter = client->adapter;
 	int i;
 
-	if (i2c_check_addr(client->adapter,client->addr))
-		return -EBUSY;
+	down(&adapter->list);
+	if (__i2c_check_addr(client->adapter, client->addr))
+		goto out_unlock_list;
 
-	for (i = 0; i < I2C_CLIENT_MAX; i++)
-		if (NULL == adapter->clients[i])
-			break;
-	if (I2C_CLIENT_MAX == i) {
-		printk(KERN_WARNING 
-		       " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
-			client->name);
-		return -ENOMEM;
+	for (i = 0; i < I2C_CLIENT_MAX; i++) {
+		if (!adapter->clients[i])
+			goto free_slot;
 	}
 
+	printk(KERN_WARNING 
+	       " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
+	       client->name);
+
+ out_unlock_list:
+	up(&adapter->list);
+	return -EBUSY;
+
+ free_slot:
 	adapter->clients[i] = client;
-	adapter->client_count++;
+	up(&adapter->list);
 	
-	if (adapter->client_register) 
-		if (adapter->client_register(client)) 
-			printk(KERN_DEBUG "i2c-core.o: warning: client_register seems "
+	if (adapter->client_register)  {
+		if (adapter->client_register(client))  {
+			printk(KERN_DEBUG
+			       "i2c-core.o: warning: client_register seems "
 			       "to have failed for client %02x at adapter %s\n",
-			       client->addr,adapter->name);
-	DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] registered to adapter [%s](pos. %d).\n",
-		client->name, adapter->name,i));
+			       client->addr, adapter->name);
+		}
+	}
 
-	if(client->flags & I2C_CLIENT_ALLOW_USE)
+	DEB(printk(KERN_DEBUG
+		   "i2c-core.o: client [%s] registered to adapter [%s] "
+		   "(pos. %d).\n", client->name, adapter->name, i));
+
+	if (client->flags & I2C_CLIENT_ALLOW_USE)
 		client->usage_count = 0;
-	
 	return 0;
 }
 
@@ -409,34 +372,38 @@
 int i2c_detach_client(struct i2c_client *client)
 {
 	struct i2c_adapter *adapter = client->adapter;
-	int i,res;
-
-	for (i = 0; i < I2C_CLIENT_MAX; i++)
-		if (client == adapter->clients[i])
-			break;
-	if (I2C_CLIENT_MAX == i) {
-		printk(KERN_WARNING " i2c-core.o: unregister_client "
-				    "[%s] not found\n",
-			client->name);
-		return -ENODEV;
-	}
+	int res = 0, i;
 	
-	if( (client->flags & I2C_CLIENT_ALLOW_USE) && 
-	    (client->usage_count>0))
+	if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0))
 		return -EBUSY;
-	
-	if (adapter->client_unregister != NULL) 
-		if ((res = adapter->client_unregister(client))) {
-			printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, "
-			       "client not detached",client->name);
-			return res;
+
+	if (adapter->client_unregister)  {
+		res = adapter->client_unregister(client);
+		if (res) {
+			printk(KERN_ERR
+			       "i2c-core.o: client_unregister [%s] failed, "
+			       "client not detached", client->name);
+			goto out;
 		}
+	}
 
-	adapter->clients[i] = NULL;
-	adapter->client_count--;
+	down(&adapter->list);
+	for (i = 0; i < I2C_CLIENT_MAX; i++) {
+		if (client == adapter->clients[i]) {
+			adapter->clients[i] = NULL;
+			goto out_unlock;
+		}
+	}
 
-	DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] unregistered.\n",client->name));
-	return 0;
+	printk(KERN_WARNING
+	       " i2c-core.o: unregister_client [%s] not found\n",
+	       client->name);
+	res = -ENODEV;
+
+ out_unlock:
+	up(&adapter->list);
+ out:
+	return res;
 }
 
 static int i2c_inc_use_client(struct i2c_client *client)
@@ -495,44 +462,12 @@
 	return 0;
 }
 
-/* ----------------------------------------------------
- * The /proc functions
- * ----------------------------------------------------
- */
-
 #ifdef CONFIG_PROC_FS
-
-/* This function generates the output for /proc/bus/i2c */
-int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, 
-                 void *private)
-{
-	int i;
-	int nr = 0;
-	/* Note that it is safe to write a `little' beyond len. Yes, really. */
-	for (i = 0; (i < I2C_ADAP_MAX) && (nr < len); i++)
-		if (adapters[i]) {
-			nr += sprintf(buf+nr, "i2c-%d\t", i);
-			if (adapters[i]->algo->smbus_xfer) {
-				if (adapters[i]->algo->master_xfer)
-					nr += sprintf(buf+nr,"smbus/i2c");
-				else
-					nr += sprintf(buf+nr,"smbus    ");
-			} else if (adapters[i]->algo->master_xfer)
-				nr += sprintf(buf+nr,"i2c       ");
-			else
-				nr += sprintf(buf+nr,"dummy     ");
-			nr += sprintf(buf+nr,"\t%-32s\t%-32s\n",
-			              adapters[i]->name,
-			              adapters[i]->algo->name);
-		}
-	return nr;
-}
-
 /* This function generates the output for /proc/bus/i2c-? */
-ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, 
-                         loff_t *ppos)
+static ssize_t i2cproc_bus_read(struct file *file, char *buf,
+				size_t count, loff_t *ppos)
 {
-	struct inode * inode = file->f_dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	char *kbuf;
 	struct i2c_client *client;
 	int i,j,k,order_nr,len=0;
@@ -593,31 +528,133 @@
 	return -ENOENT;
 }
 
-static int i2cproc_init(void)
+static struct file_operations i2cproc_operations = {
+	.read		= i2cproc_bus_read,
+};
+
+/* This function generates the output for /proc/bus/i2c */
+static int bus_i2c_show(struct seq_file *s, void *p)
 {
+	int i;
 
-	struct proc_dir_entry *proc_bus_i2c;
+	down(&core_lists);
+	for (i = 0; i < I2C_ADAP_MAX; i++) {
+		struct i2c_adapter *adapter = adapters[i];
+
+		if (!adapter)
+			continue;
 
-	proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
-	if (!proc_bus_i2c) {
-		printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
-		return -ENOENT;
- 	}
+		seq_printf(s, "i2c-%d\t", i);
+
+		if (adapter->algo->smbus_xfer) {
+			if (adapter->algo->master_xfer)
+				seq_printf(s, "smbus/i2c");
+			else
+				seq_printf(s, "smbus    ");
+		} else if (adapter->algo->master_xfer)
+			seq_printf(s ,"i2c       ");
+		else
+			seq_printf(s, "dummy     ");
+
+		seq_printf(s, "\t%-32s\t%-32s\n",
+			      adapter->name, adapter->algo->name);
+	}
+	up(&core_lists);
 
-	proc_bus_i2c->read_proc = &read_bus_i2c;
-	proc_bus_i2c->owner = THIS_MODULE;
 	return 0;
 }
 
-static void __exit i2cproc_cleanup(void)
+static int bus_i2c_open(struct inode *inode, struct file *file)
 {
+	return single_open(file, bus_i2c_show, NULL);
+}
+
+static struct file_operations bus_i2c_fops = {
+	.open		= bus_i2c_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+ };
+
+static int i2cproc_register(struct i2c_adapter *adap, int bus)
+{
+	struct proc_dir_entry *proc_entry;
+	char name[8];
+
+	sprintf(name, "i2c-%d", bus);
+
+	proc_entry = create_proc_entry(name, 0, proc_bus);
+	if (!proc_entry)
+		goto fail;
+
+	proc_entry->proc_fops = &i2cproc_operations;
+	proc_entry->owner = adap->owner;
+	adap->inode = proc_entry->low_ino;
+	return 0;
+ fail:
+	printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", name);
+	return -ENOENT;
+}
+
+static void i2cproc_remove(int bus)
+{
+	char name[8];
+
+	sprintf(name,"i2c-%d", bus);
+	remove_proc_entry(name, proc_bus);
+}
+
+static int __init i2cproc_init(void)
+{
+	struct proc_dir_entry *proc_bus_i2c;
+
+	proc_bus_i2c = create_proc_entry("i2c", 0, proc_bus);
+	if (!proc_bus_i2c)
+		goto fail;
+	proc_bus_i2c->proc_fops = &bus_i2c_fops;
+ 	proc_bus_i2c->owner = THIS_MODULE;
+ 	return 0;
 
+ fail:
+	printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
+	return -ENOENT;
+}
+
+static void __exit i2cproc_cleanup(void)
+{
 	remove_proc_entry("i2c",proc_bus);
 }
+#else
+static int __init i2cproc_init(void) { return 0; }
+static void __exit i2cproc_cleanup(void) { }
+#endif /* CONFIG_PROC_FS */
+
+/* match always succeeds, as we want the probe() to tell if we really accept this match */
+static int i2c_device_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+struct bus_type i2c_bus_type = {
+	.name =		"i2c",
+	.match =	i2c_device_match,
+};
+
+
+static int __init i2c_init(void)
+{
+	bus_register(&i2c_bus_type);
+	return i2cproc_init();
+}
+
+static void __exit i2c_exit(void)
+{
+	i2cproc_cleanup();
+	bus_unregister(&i2c_bus_type);
+}
 
-module_init(i2cproc_init);
-module_exit(i2cproc_cleanup);
-#endif /* def CONFIG_PROC_FS */
+module_init(i2c_init);
+module_exit(i2c_exit);
 
 /* ----------------------------------------------------
  * the functional interface to the i2c busses.
@@ -632,9 +669,9 @@
  	 	DEB2(printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with %d msgs.\n",
 		            adap->name,num));
 
-		I2C_LOCK(adap);
+		down(&adap->bus);
 		ret = adap->algo->master_xfer(adap,msgs,num);
-		I2C_UNLOCK(adap);
+		up(&adap->bus);
 
 		return ret;
 	} else {
@@ -659,9 +696,9 @@
 		DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
 			count,client->adapter->name));
 	
-		I2C_LOCK(adap);
+		down(&adap->bus);
 		ret = adap->algo->master_xfer(adap,&msg,1);
-		I2C_UNLOCK(adap);
+		up(&adap->bus);
 
 		/* if everything went ok (i.e. 1 msg transmitted), return #bytes
 		 * transmitted, else error code.
@@ -689,9 +726,9 @@
 		DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
 			count,client->adapter->name));
 	
-		I2C_LOCK(adap);
+		down(&adap->bus);
 		ret = adap->algo->master_xfer(adap,&msg,1);
-		I2C_UNLOCK(adap);
+		up(&adap->bus);
 	
 		DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",
 			ret, count, client->addr));
@@ -1306,10 +1343,10 @@
 	}
 
 	if (adapter->algo->smbus_xfer) {
-		I2C_LOCK(adapter);
+		down(&adapter->bus);
 		res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
 		                                command,size,data);
-		I2C_UNLOCK(adapter);
+		up(&adapter->bus);
 	} else
 		res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
 	                                      command,size,data);
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c	Thu Feb 20 12:02:00 2003
+++ b/drivers/i2c/i2c-proc.c	Wed Mar 12 07:37:16 2003
@@ -35,8 +35,6 @@
 #include <linux/i2c-proc.h>
 #include <asm/uaccess.h>
 
-static int i2c_create_name(char **name, const char *prefix,
-			       struct i2c_adapter *adapter, int addr);
 static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
 			       long *results, int magnitude);
 static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
@@ -54,15 +52,6 @@
 
 static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
 
-static ctl_table sysctl_table[] = {
-	{CTL_DEV, "dev", NULL, 0, 0555},
-	{0},
-	{DEV_SENSORS, "sensors", NULL, 0, 0555},
-	{0},
-	{0, NULL, NULL, 0, 0555},
-	{0}
-};
-
 static ctl_table i2c_proc_dev_sensors[] = {
 	{SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips,
 	 &i2c_sysctl_chips},
@@ -87,36 +76,40 @@
    (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for
    a LM75 chip on the third i2c bus at address 0x4e).  
    name is allocated first. */
-static int i2c_create_name(char **name, const char *prefix,
-			struct i2c_adapter *adapter, int addr)
+static char *generate_name(struct i2c_client *client, const char *prefix)
 {
-	char name_buffer[50];
-	int id, i, end;
-	if (i2c_is_isa_adapter(adapter))
+	struct i2c_adapter *adapter = client->adapter;
+	int addr = client->addr;
+	char name_buffer[50], *name;
+
+	if (i2c_is_isa_adapter(adapter)) {
 		sprintf(name_buffer, "%s-isa-%04x", prefix, addr);
-	else if (!adapter->algo->smbus_xfer && !adapter->algo->master_xfer) {
-		/* dummy adapter, generate prefix */
+	} else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) {
+		int id = i2c_adapter_id(adapter);
+		if (id < 0)
+			return ERR_PTR(-ENOENT);
+		sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
+	} else {	/* dummy adapter, generate prefix */
+		int end, i;
+
 		sprintf(name_buffer, "%s-", prefix);
 		end = strlen(name_buffer);
-		for(i = 0; i < 32; i++) {
-			if(adapter->algo->name[i] == ' ')
+
+		for (i = 0; i < 32; i++) {
+			if (adapter->algo->name[i] == ' ')
 				break;
 			name_buffer[end++] = tolower(adapter->algo->name[i]);
 		}
+
 		name_buffer[end] = 0;
 		sprintf(name_buffer + end, "-%04x", addr);
-	} else {
-		if ((id = i2c_adapter_id(adapter)) < 0)
-			return -ENOENT;
-		sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
-	}
-	*name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
-	if (!*name) {
-		printk (KERN_WARNING "i2c_create_name: not enough memory\n");
-		return -ENOMEM;
 	}
-	strcpy(*name, name_buffer);
-	return 0;
+
+	name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
+	if (unlikely(!name))
+		return ERR_PTR(-ENOMEM);
+	strcpy(name, name_buffer);
+	return name;
 }
 
 /* This rather complex function must be called when you want to add an entry
@@ -127,93 +120,80 @@
    If any driver wants subdirectories within the newly created directory,
    this function must be updated!  */
 int i2c_register_entry(struct i2c_client *client, const char *prefix,
-			   ctl_table * ctl_template)
+		       struct ctl_table *leaf)
 {
-	int i, res, len, id;
-	ctl_table *new_table, *client_tbl, *tbl;
-	char *name;
-	struct ctl_table_header *new_header;
-
-	if ((res = i2c_create_name(&name, prefix, client->adapter,
-				       client->addr))) return res;
-
-	for (id = 0; id < SENSORS_ENTRY_MAX; id++)
-		if (!i2c_entries[id]) {
-			break;
-		}
-	if (id == SENSORS_ENTRY_MAX) {
-		kfree(name);
-		return -ENOMEM;
-	}
-
-	id += 256;
-	
-	len = 0;
-	while (ctl_template[len].procname)
-		len++;
-	if (!(new_table = kmalloc(sizeof(sysctl_table) + sizeof(ctl_table) * (len + 1), 
-				  GFP_KERNEL))) {
-		kfree(name);
-		return -ENOMEM;
-	}
-
-	memcpy(new_table, sysctl_table, sizeof(sysctl_table));
-	tbl = new_table; /* sys/ */
-	tbl = tbl->child = tbl + 2; /* dev/ */
-	tbl = tbl->child = tbl + 2; /* sensors/ */	
-       	client_tbl = tbl->child = tbl + 2; /* XX-chip-YY-ZZ/ */
-
-	client_tbl->procname = name;
-	client_tbl->ctl_name = id;
-	client_tbl->child = client_tbl + 2;
-
-	/* Next the client sysctls. --km */
-	tbl = client_tbl->child;
-	memcpy(tbl, ctl_template, sizeof(ctl_table) * (len+1));
-	for (i = 0; i < len; i++)
-		tbl[i].extra2 = client;
-
-	if (!(new_header = register_sysctl_table(new_table, 0))) {
-		printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n");
-		kfree(new_table);
-		kfree(name);
-		return -EPERM;
-	}
-
- 	i2c_entries[id - 256] = new_header;
-
-	i2c_clients[id - 256] = client;
-
-#ifdef DEBUG
-	if (!new_header || !new_header->ctl_table ||
-	    !new_header->ctl_table->child ||
-	    !new_header->ctl_table->child->child ||
-	    !new_header->ctl_table->child->child->de ) {
-		printk
-		    (KERN_ERR "i2c-proc.o: NULL pointer when trying to install fill_inode fix!\n");
-		return id;
-	}
-#endif				/* DEBUG */
-	client_tbl->de->owner = client->driver->owner;
-	return id;
+	struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl;
+	struct ctl_table_header *hdr;
+	struct ctl_table *tmp;
+	const char *name;
+	int id;
+
+	name = generate_name(client, prefix);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
+
+	for (id = 0; id < SENSORS_ENTRY_MAX; id++) {
+		if (!i2c_entries[id])
+			goto free_slot;
+	}
+
+	goto out_free_name;
+
+ free_slot:
+	tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+	if (unlikely(!tbl))
+		goto out_free_name;
+	memset(tbl, 0, sizeof(*tbl));
+
+	for (tmp = leaf; tmp->ctl_name; tmp++)
+		tmp->extra2 = client;
+
+	tbl->sensors->ctl_name = id+256;
+	tbl->sensors->procname = name;
+	tbl->sensors->mode = 0555;
+	tbl->sensors->child = leaf;
+
+	tbl->dev->ctl_name = DEV_SENSORS;
+	tbl->dev->procname = "sensors";
+	tbl->dev->mode = 0555;
+	tbl->dev->child = tbl->sensors;
+
+	tbl->root->ctl_name = CTL_DEV;
+	tbl->root->procname = "dev";
+	tbl->root->mode = 0555;
+	tbl->root->child = tbl->dev;
+
+	hdr = register_sysctl_table(tbl->root, 0);
+	if (unlikely(!hdr))
+		goto out_free_tbl;
+
+	i2c_entries[id] = hdr;
+	i2c_clients[id] = client;
+
+	return (id + 256);	/* XXX(hch) why?? */
+
+ out_free_tbl:
+	kfree(tbl);
+ out_free_name:
+	kfree(name);
+	return -ENOMEM;
 }
 
 void i2c_deregister_entry(int id)
 {
-	ctl_table *table;
-	char *temp;
+	id -= 256;
 
-	id -= 256;	
 	if (i2c_entries[id]) {
-		table = i2c_entries[id]->ctl_table;
-		unregister_sysctl_table(i2c_entries[id]);
-		/* 2-step kfree needed to keep gcc happy about const points */
-		(const char *) temp = table[4].procname;
-		kfree(temp);
-		kfree(table);
-		i2c_entries[id] = NULL;
-		i2c_clients[id] = NULL;
+		struct ctl_table_header *hdr = i2c_entries[id];
+		struct ctl_table *tbl = hdr->ctl_table;
+
+		unregister_sysctl_table(hdr);
+		kfree(tbl->child->child->procname);
+		kfree(tbl); /* actually the whole anonymous struct */
 	}
+
+	i2c_entries[id] = NULL;
+	i2c_clients[id] = NULL;
 }
 
 static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile
--- a/drivers/ide/Makefile	Wed Feb 19 09:48:49 2003
+++ b/drivers/ide/Makefile	Mon Mar  3 12:06:45 2003
@@ -28,3 +28,4 @@
 endif
 
 obj-$(CONFIG_BLK_DEV_IDE)		+= legacy/ ppc/ arm/
+obj-$(CONFIG_BLK_DEV_HD)		+= legacy/
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	Wed Nov 13 14:49:14 2002
+++ b/drivers/ide/ide-disk.c	Tue Feb 18 10:06:17 2003
@@ -38,9 +38,11 @@
  * Version 1.15		convert all calls to ide_raw_taskfile
  *				since args will return register content.
  * Version 1.16		added suspend-resume-checkpower
+ * Version 1.17		do flush on standy, do flush on ATA < ATA6
+ *			fix wcache setup.
  */
 
-#define IDEDISK_VERSION	"1.16"
+#define IDEDISK_VERSION	"1.17"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
@@ -140,7 +142,7 @@
 static ide_startstop_t read_intr (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	int i = 0, nsect	= 0, msect = drive->mult_count;
+	u32 i = 0, nsect	= 0, msect = drive->mult_count;
 	struct request *rq;
 	unsigned long flags;
 	u8 stat;
@@ -157,7 +159,7 @@
 		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
 		return ide_started;
 	}
-
+	
 read_next:
 	rq = HWGROUP(drive)->rq;
 	if (msect) {
@@ -203,7 +205,7 @@
 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct request *rq	= hwgroup->rq;
-	int i = 0;
+	u32 i = 0;
 	u8 stat;
 
 	if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),
@@ -506,14 +508,10 @@
 		if (drive->using_dma && !hwif->ide_dma_read(drive))
 			return ide_started;
 
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
-		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
-
 		command = ((drive->mult_count) ?
 			   ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) :
 			   ((lba48) ? WIN_READ_EXT : WIN_READ));
-		hwif->OUTB(command, IDE_COMMAND_REG);
+		ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL);
 		return ide_started;
 	} else if (rq_data_dir(rq) == WRITE) {
 		ide_startstop_t startstop;
@@ -628,11 +626,7 @@
 
 static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
 {
-	int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
-
-#if 1
-	lba48bit = (drive->addressing == 1) ? 1 : 0;
-#endif
+	int lba48bit = (drive->addressing == 1) ? 1 : 0;
 
 	if ((cmd == READ) && drive->using_tcq)
 		return lba48bit ? WIN_READDMA_QUEUED_EXT : WIN_READDMA_QUEUED;
@@ -1412,32 +1406,6 @@
 	return call_idedisk_standby(drive, 0);
 }
 
-#if 0
-static int call_idedisk_checkpower (ide_drive_t *drive, int arg)
-{
-	ide_task_t args;
-	u8 ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1;
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_COMMAND_OFFSET]	= ckpw;
-	args.command_type			= ide_cmd_type_parser(&args);
-	ide_raw_taskfile(drive, &args, NULL);
-#if 0
-if (errno != EIO || args[0] != 0 || args[1] != 0)
-   state = "unknown";
-else
-   state = "sleeping";
-} else {
-   state = (args[2] == 255) ? "active/idle" : "standby";
-#endif
-	return 0;
-}
-
-static int do_idedisk_checkpower (ide_drive_t *drive)
-{
-	return call_idedisk_checkpower(drive, 0);
-}
-#endif
-
 static int do_idedisk_flushcache (ide_drive_t *drive)
 {
 	ide_task_t args;
@@ -1596,13 +1564,8 @@
 			drive->doorlocking = 1;
 		}
 	}
-#if 1
+
 	(void) probe_lba_addressing(drive, 1);
-#else
-	/* if using 48-bit addressing bump the request size up */
-	if (probe_lba_addressing(drive, 1))
-		blk_queue_max_sectors(&drive->queue, 2048);
-#endif
 
 	/* Extract geometry if we did not already have one for the drive */
 	if (!drive->cyl || !drive->head || !drive->sect) {
@@ -1675,13 +1638,9 @@
 
 static int idedisk_cleanup (ide_drive_t *drive)
 {
+	static int ide_cacheflush_p(ide_drive_t *drive);
 	struct gendisk *g = drive->disk;
-
-	do_idedisk_standby(drive);
-	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
-		if (do_idedisk_flushcache(drive))
-			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
-				drive->name);
+	ide_cacheflush_p(drive);
 	if (ide_unregister_subdriver(drive))
 		return 1;
 	del_gendisk(g);
@@ -1725,6 +1684,7 @@
 	drive->usage++;
 	if (drive->removable && drive->usage == 1) {
 		ide_task_t args;
+		u8 cf;
 		memset(&args, 0, sizeof(ide_task_t));
 		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
 		args.command_type = ide_cmd_type_parser(&args);
@@ -1736,6 +1696,32 @@
 		 */
 		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
 			drive->doorlocking = 0;
+		drive->wcache = 0;
+		/* Cache enabled ? */
+		if (drive->id->csfo & 1)
+		drive->wcache = 1;
+		/* Cache command set available ? */
+		if (drive->id->cfs_enable_1 & (1<<5))
+			drive->wcache = 1;
+		/* ATA6 cache extended commands */
+		cf = drive->id->command_set_2 >> 24;
+		if((cf & 0xC0) == 0x40 && (cf & 0x30) != 0)
+			drive->wcache = 1;
+	}
+	return 0;
+}
+
+static int ide_cacheflush_p(ide_drive_t *drive)
+{
+	if(drive->wcache)
+	{
+		if (do_idedisk_flushcache(drive))
+		{
+			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
+				drive->name);
+			return -EIO;
+		}
+		return 1;
 	}
 	return 0;
 }
@@ -1752,10 +1738,7 @@
 		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
 			drive->doorlocking = 0;
 	}
-	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
-		if (do_idedisk_flushcache(drive))
-			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
-				drive->name);
+	ide_cacheflush_p(drive);
 	drive->usage--;
 	return 0;
 }
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	Tue Feb 25 02:43:50 2003
+++ b/drivers/ide/ide-dma.c	Thu Mar  6 09:21:37 2003
@@ -664,11 +664,6 @@
 	if (drive->media != ide_disk)
 		return 0;
 
-	/* paranoia check */
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
-
 	command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
 	
 	if (drive->vdma)
@@ -680,8 +675,7 @@
 	}
 
 	/* issue cmd to drive */
-	hwif->OUTB(command, IDE_COMMAND_REG);
-
+	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
 	return HWIF(drive)->ide_dma_count(drive);
 }
 
@@ -702,11 +696,6 @@
 	if (drive->media != ide_disk)
 		return 0;
 
-	/* paranoia check */
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
-
 	command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
 	if (drive->vdma)
 		command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE;
@@ -717,7 +706,7 @@
 	}
 
 	/* issue cmd to drive */
-	hwif->OUTB(command, IDE_COMMAND_REG);
+	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
 
 	return HWIF(drive)->ide_dma_count(drive);
 }
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	Tue Feb 18 10:06:17 2003
+++ b/drivers/ide/ide-floppy.c	Tue Feb 18 10:06:17 2003
@@ -1077,14 +1077,11 @@
 	}
 	
 	if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
-		ide_set_handler(drive,
+		/* Issue the packet command */
+		ide_execute_command(drive, WIN_PACKETCMD,
 				pkt_xfer_routine,
 				IDEFLOPPY_WAIT_CMD,
 				NULL);
-		/* Issue the packet command */
-		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
 	} else {
 		/* Issue the packet command */
diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c	Mon Feb 24 10:30:38 2003
+++ b/drivers/ide/ide-io.c	Thu Mar  6 09:21:48 2003
@@ -358,18 +358,15 @@
  *	Issue a simple drive command with interrupts.
  *	The drive must be selected beforehand.
  */
- 
+
 void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, handler, WAIT_CMD, NULL);
 	if (IDE_CONTROL_REG)
 		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
 	SELECT_MASK(drive,0);
 	hwif->OUTB(nsect,IDE_NSECTOR_REG);
-	hwif->OUTB(cmd,IDE_COMMAND_REG);
+	ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
 }
 
 EXPORT_SYMBOL(ide_cmd);
@@ -841,14 +838,14 @@
 		 * happens anyway when any interrupt comes in, IDE or otherwise
 		 *  -- the kernel masks the IRQ while it is being handled.
 		 */
-		if (masked_irq && hwif->irq != masked_irq)
+		if (hwif->irq != masked_irq)
 			disable_irq_nosync(hwif->irq);
 		spin_unlock(&ide_lock);
 		local_irq_enable();
 			/* allow other IRQs while we start this request */
 		startstop = start_request(drive, rq);
 		spin_lock_irq(&ide_lock);
-		if (masked_irq && hwif->irq != masked_irq)
+		if (hwif->irq != masked_irq)
 			enable_irq(hwif->irq);
 		if (startstop == ide_released)
 			goto queue_next;
@@ -864,7 +861,7 @@
  */
 void do_ide_request(request_queue_t *q)
 {
-	ide_do_request(q->queuedata, 0);
+	ide_do_request(q->queuedata, IDE_NO_IRQ);
 }
 
 /*
@@ -1012,7 +1009,7 @@
 				hwgroup->busy = 0;
 		}
 	}
-	ide_do_request(hwgroup, 0);
+	ide_do_request(hwgroup, IDE_NO_IRQ);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
@@ -1302,7 +1299,7 @@
 		insert_end = 0;
 	}
 	__elv_add_request(&drive->queue, rq, insert_end, 0);
-	ide_do_request(hwgroup, 0);
+	ide_do_request(hwgroup, IDE_NO_IRQ);
 	spin_unlock_irqrestore(&ide_lock, flags);
 
 	err = 0;
diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
--- a/drivers/ide/ide-iops.c	Tue Feb 18 10:06:17 2003
+++ b/drivers/ide/ide-iops.c	Thu Feb 20 08:50:44 2003
@@ -59,11 +59,11 @@
 {
 }
 
-static void ide_unplugged_outb (u8 addr, unsigned long port)
+static void ide_unplugged_outb (u8 val, unsigned long port)
 {
 }
 
-static void ide_unplugged_outw (u16 addr, unsigned long port)
+static void ide_unplugged_outw (u16 val, unsigned long port)
 {
 }
 
@@ -71,7 +71,7 @@
 {
 }
 
-static void ide_unplugged_outl (u32 addr, unsigned long port)
+static void ide_unplugged_outl (u32 val, unsigned long port)
 {
 }
 
@@ -125,14 +125,14 @@
 	insl(port, addr, count);
 }
 
-static void ide_outb (u8 addr, unsigned long port)
+static void ide_outb (u8 val, unsigned long port)
 {
-	outb(addr, port);
+	outb(val, port);
 }
 
-static void ide_outw (u16 addr, unsigned long port)
+static void ide_outw (u16 val, unsigned long port)
 {
-	outw(addr, port);
+	outw(val, port);
 }
 
 static void ide_outsw (unsigned long port, void *addr, u32 count)
@@ -140,9 +140,9 @@
 	outsw(port, addr, count);
 }
 
-static void ide_outl (u32 addr, unsigned long port)
+static void ide_outl (u32 val, unsigned long port)
 {
-	outl(addr, port);
+	outl(val, port);
 }
 
 static void ide_outsl (unsigned long port, void *addr, u32 count)
diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
--- a/drivers/ide/ide-lib.c	Thu Nov 14 09:12:22 2002
+++ b/drivers/ide/ide-lib.c	Tue Feb 18 10:06:17 2003
@@ -171,7 +171,7 @@
 		BUG();
 	return min(speed, speed_max[mode]);
 #else /* !CONFIG_BLK_DEV_IDEDMA */
-	return min(speed, (u8)XFER_PIO_4);
+	return min(speed, XFER_PIO_4);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Tue Feb 18 10:06:17 2003
+++ b/drivers/ide/ide-probe.c	Sat Mar  8 14:50:22 2003
@@ -1292,11 +1292,8 @@
 	/* we set it back to 1 if all is ok below */	
 	hwif->present = 0;
 
-	if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
-		printk("%s: UNABLE TO GET MAJOR NUMBER %d\n",
-			hwif->name, hwif->major);
+	if (register_blkdev(hwif->major, hwif->name))
 		return 0;
-	}
 
 	if (alloc_disks(hwif) < 0)
 		goto out;
diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	Wed Nov 13 07:06:17 2002
+++ b/drivers/ide/ide-taskfile.c	Tue Feb 18 10:06:17 2003
@@ -177,8 +177,7 @@
 
 	hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
 	if (task->handler != NULL) {
-		ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL);
-		hwif->OUTB(taskfile->command, IDE_COMMAND_REG);
+		ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
 		if (task->prehandler != NULL)
 			return task->prehandler(drive, task->rq);
 		return ide_started;
@@ -1880,9 +1879,8 @@
  			if (task->handler == NULL)
 				return ide_stopped;
 
-			ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL);
 			/* Issue the command */
-			hwif->OUTB(taskfile->command, IDE_COMMAND_REG);
+			ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
 			if (task->prehandler != NULL)
 				return task->prehandler(drive, HWGROUP(drive)->rq);
 	}
diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
--- a/drivers/ide/legacy/hd.c	Wed Nov 20 17:00:00 2002
+++ b/drivers/ide/legacy/hd.c	Sat Mar  8 14:50:22 2003
@@ -708,10 +708,10 @@
 static int __init hd_init(void)
 {
 	int drive;
-	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
-		printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR,"hd"))
 		return -1;
-	}
+
 	blk_init_queue(&hd_queue, do_hd_request, &hd_lock);
 	blk_queue_max_sectors(&hd_queue, 255);
 	init_timer(&device_timer);
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	Wed Feb 19 12:15:57 2003
+++ b/drivers/ide/pci/amd74xx.c	Mon Mar  3 12:09:31 2003
@@ -82,7 +82,7 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
-static long amd_base;
+static unsigned long amd_base;
 static struct pci_dev *bmide_dev;
 extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
 
@@ -102,7 +102,7 @@
 
 	amd_print("----------AMD BusMastering IDE Configuration----------------");
 
-	amd_print("Driver Version:                     2.8");
+	amd_print("Driver Version:                     2.9");
 	amd_print("South Bridge:                       %s", bmide_dev->dev.name);
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
@@ -284,7 +284,7 @@
  * and initialize its drive independent registers.
  */
 
-unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name)
+static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name)
 {
 	unsigned char t;
 	unsigned int u;
@@ -378,12 +378,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
+static unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
 {
 	return ((amd_enabled & amd_80w) >> hwif->channel) & 1;
 }
 
-void __init init_hwif_amd74xx(ide_hwif_t *hwif)
+static void __init init_hwif_amd74xx(ide_hwif_t *hwif)
 {
 	int i;
 
diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
--- a/drivers/ide/pci/via82cxxx.c	Wed Feb 19 12:13:48 2003
+++ b/drivers/ide/pci/via82cxxx.c	Mon Mar  3 12:11:59 2003
@@ -1,16 +1,6 @@
 /*
- * $Id: via82cxxx.c,v 3.35-ac2 2002/09/111 Alan Exp $
  *
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- *
- *  Based on the work of:
- *	Michel Aubry
- *	Jeff Garzik
- *	Andre Hedrick
- */
-
-/*
- * Version 3.35
+ * Version 3.36
  *
  * VIA IDE driver for Linux. Supported southbridges:
  *
@@ -24,6 +14,10 @@
  *	Michel Aubry
  *	Jeff Garzik
  *	Andre Hedrick
+ *
+ * Documentation:
+ *	Obsolete device documentation publically available from via.com.tw
+ *	Current device documentation available under NDA only
  */
 
 /*
@@ -67,6 +61,7 @@
 #define VIA_SET_FIFO		0x040	/* Needs to have FIFO split set */
 #define VIA_NO_UNMASK		0x080	/* Doesn't work with IRQ unmasking on */
 #define VIA_BAD_ID		0x100	/* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST		0x200	/* Don't touch Address Setup Timing */
 
 /*
  * VIA SouthBridge chips.
@@ -82,8 +77,8 @@
 #ifdef FUTURE_BRIDGES
 	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 },
 #endif
-	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 },
-	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 },
+	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, VIA_UDMA_100 },
 	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, VIA_UDMA_100 },
 	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, VIA_UDMA_100 },
@@ -152,7 +147,7 @@
 	via_print("----------VIA BusMastering IDE Configuration"
 		"----------------");
 
-	via_print("Driver Version:                     3.35-ac");
+	via_print("Driver Version:                     3.36");
 	via_print("South Bridge:                       VIA %s",
 		via_config->name);
 
@@ -292,9 +287,11 @@
 {
 	u8 t;
 
-	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
-	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
-	pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
+	if (~via_config->flags & VIA_BAD_AST) {
+		pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
+		t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+		pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
+	}
 
 	pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)),
 		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
diff -Nru a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c
--- a/drivers/isdn/hardware/avm/b1pci.c	Thu Aug 15 15:01:13 2002
+++ b/drivers/isdn/hardware/avm/b1pci.c	Sat Feb 22 09:42:22 2003
@@ -343,12 +343,16 @@
 
 static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
 {
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 	avmcard *card = pci_get_drvdata(pdev);
 
 	if (card->dma)
 		b1pciv4_remove(pdev);
 	else
 		b1pci_remove(pdev);
+#else
+	b1pci_remove(pdev);
+#endif
 }
 
 static struct pci_driver b1pci_pci_driver = {
diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c
--- a/drivers/isdn/hisax/amd7930.c	Sun Jan 12 16:05:35 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,717 +0,0 @@
-/* $Id: amd7930.c,v 1.5.6.4 2001/09/23 22:24:46 kai Exp $
- *
- * HiSax ISDN driver - chip specific routines for AMD 7930
- *
- * Author       Brent Baccala
- * Copyright    by Brent Baccala <baccala@FreeSoft.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- *    - Existing ISDN HiSax driver provides all the smarts
- *    - it compiles, runs, talks to an isolated phone switch, connects
- *      to a Cisco, pings go through
- *    - AMD 7930 support only (no DBRI yet)
- *    - no US NI-1 support (may not work on US phone system - untested)
- *    - periodic packet loss, apparently due to lost interrupts
- *    - ISDN sometimes freezes, requiring reboot before it will work again
- *
- * The code is unreliable enough to be consider alpha
- *
- * This file is (c) under GNU General Public License
- *
- * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
- * SparcStation 1+.  The chip provides microphone and speaker interfaces
- * which provide mono-channel audio at 8K samples per second via either
- * 8-bit A-law or 8-bit mu-law encoding.  Also, the chip features an
- * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
- * which performs basic D channel LAPD processing and provides raw
- * B channel data.  The digital audio channel, the two ISDN B channels,
- * and two 64 Kbps channels to the microprocessor are all interconnected
- * via a multiplexer.
- *
- * This driver interfaces to the Linux HiSax ISDN driver, which performs
- * all high-level Q.921 and Q.931 ISDN functions.  The file is not
- * itself a hardware driver; rather it uses functions exported by
- * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
- * allowing the chip to be simultaneously used for both audio and ISDN data.
- * The hardware driver does _no_ buffering, but provides several callbacks
- * which are called during interrupt service and should therefore run quickly.
- *
- * D channel transmission is performed by passing the hardware driver the
- * address and size of an skb's data area, then waiting for a callback
- * to signal successful transmission of the packet.  A task is then
- * queued to notify the HiSax driver that another packet may be transmitted.
- *
- * D channel reception is quite simple, mainly because of:
- *   1) the slow speed of the D channel - 16 kbps, and
- *   2) the presence of an 8- or 32-byte (depending on chip version) FIFO
- *      to buffer the D channel data on the chip
- * Worst case scenario of back-to-back packets with the 8 byte buffer
- * at 16 kbps yields an service time of 4 ms - long enough to preclude
- * the need for fancy buffering.  We queue a background task that copies
- * data out of the receive buffer into an skb, and the hardware driver
- * simply does nothing until we're done with the receive buffer and
- * reset it for a new packet.
- *
- * B channel processing is more complex, because of:
- *   1) the faster speed - 64 kbps,
- *   2) the lack of any on-chip buffering (it interrupts for every byte), and
- *   3) the lack of any chip support for HDLC encapsulation
- *
- * The HiSax driver can put each B channel into one of three modes -
- * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
- * and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
- * L1_MODE_HDLC is the most common, used for almost all "pure" digital
- * data sessions.  L1_MODE_TRANS is used for ISDN audio.
- *
- * HDLC B channel transmission is performed via a large buffer into
- * which the skb is copied while performing HDLC bit-stuffing.  A CRC
- * is computed and attached to the end of the buffer, which is then
- * passed to the low-level routines for raw transmission.  Once
- * transmission is complete, the hardware driver is set to enter HDLC
- * idle by successive transmission of mark (all 1) bytes, waiting for
- * the ISDN driver to prepare another packet for transmission and
- * deliver it.
- *
- * HDLC B channel reception is performed via an X-byte ring buffer
- * divided into N sections of X/N bytes each.  Defaults: X=256 bytes, N=4.
- * As the hardware driver notifies us that each section is full, we
- * hand it the next section and schedule a background task to peruse
- * the received section, bit-by-bit, with an HDLC decoder.  As
- * packets are detected, they are copied into a large buffer while
- * decoding HDLC bit-stuffing.  The ending CRC is verified, and if
- * it is correct, we alloc a new skb of the correct length (which we
- * now know), copy the packet into it, and hand it to the upper layers.
- * Optimization: for large packets, we hand the buffer (which also
- * happens to be an skb) directly to the upper layer after an skb_trim,
- * and alloc a new large buffer for future packets, thus avoiding a copy.
- * Then we return to HDLC processing; state is saved between calls.
- * 
- */
-
-#include "hisax.h"
-#include "../../sbus/audio/amd7930.h"
-#include "isac.h"
-#include "isdnl1.h"
-#include "rawhdlc.h"
-#include <linux/interrupt.h>
-
-static const char *amd7930_revision = "$Revision: 1.5.6.4 $";
-
-#define RCV_BUFSIZE	1024	/* Size of raw receive buffer in bytes */
-#define RCV_BUFBLKS	4	/* Number of blocks to divide buffer into
-				 * (must divide RCV_BUFSIZE) */
-
-static void Bchan_fill_fifo(struct BCState *, struct sk_buff *);
-
-static void
-Bchan_xmt_bh(void *data)
-{
-	struct BCState *bcs = data;
-	struct sk_buff *skb;
-
-	if (bcs->hw.amd7930.tx_skb != NULL) {
-		dev_kfree_skb(bcs->hw.amd7930.tx_skb);
-		bcs->hw.amd7930.tx_skb = NULL;
-	}
-	xmit_ready_b(bcs);
-}
-
-static void
-Bchan_xmit_callback(struct BCState *bcs)
-{
-	schedule_work(&bcs->hw.amd7930.xmt_work);
-}
-
-/* B channel transmission: two modes (three, if you count L1_MODE_NULL)
- *
- * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
- * the packet (i.e. make_raw_hdlc_data).  Since this can be a
- * time-consuming operation, our completion callback just schedules
- * a bottom half to do encapsulation for the next packet.  In between,
- * the link will just idle
- *
- * L1_MODE_TRANS - Data goes through, well, transparent.  No HDLC encap,
- * and we can't just let the link idle, so the "bottom half" actually
- * gets called during the top half (it's our callback routine in this case),
- * but it's a lot faster now since we don't call make_raw_hdlc_data
- */
-
-static void
-Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	int len;
-
-	if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
-		char tmp[1024];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930_fill_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', skb->len);
-		if (cs->debug & L1_DEB_HSCX_FIFO)
-			QuickHex(t, skb->data, skb->len);
-		debugl1(cs, tmp);
-	}
-
-	if (bcs->mode == L1_MODE_HDLC) {
-		len = make_raw_hdlc_data(skb->data, skb->len,
-					 bcs->hw.amd7930.tx_buff, RAW_BUFMAX);
-		if (len > 0)
-			amd7930_bxmit(0, bcs->channel,
-				      bcs->hw.amd7930.tx_buff, len,
-				      (void *) &Bchan_xmit_callback,
-				      (void *) bcs);
-		dev_kfree_skb(skb);
-	} else if (bcs->mode == L1_MODE_TRANS) {
-		amd7930_bxmit(0, bcs->channel,
-			      bcs->hw.amd7930.tx_buff, skb->len,
-			      (void *) &Bchan_xmt_bh,
-			      (void *) bcs);
-		bcs->hw.amd7930.tx_skb = skb;
-	} else {
-		dev_kfree_skb(skb);
-	}
-}
-
-static void
-Bchan_mode(struct BCState *bcs, int mode, int bc)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "AMD 7930 mode %d bchan %d/%d",
-			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
-	bcs->mode = mode;
-}
-
-/* Bchan_l2l1 is the entry point for upper layer routines that want to
- * transmit on the B channel.  PH_DATA_REQ is a normal packet that
- * we either start transmitting (if idle) or queue (if busy).
- * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
- * once the link is idle.  After a "pull" callback, the upper layer
- * routines can use PH_PULL_IND to send data.
- */
-
-static void
-Bchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct sk_buff *skb = arg;
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-			} else {
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				Bchan_fill_fifo(st->l1.bcs, skb);
-			}
-			break;
-		case (PH_PULL_IND):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				printk(KERN_WARNING "amd7930: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			Bchan_fill_fifo(st->l1.bcs, skb);
-			break;
-		case (PH_PULL_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-/* Receiver callback and bottom half - decodes HDLC at leisure (if
- * L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue.  If
- * a large packet is received, stick rv_skb (the buffer that the
- * packet has been decoded into) on the receive queue and alloc a new
- * (large) skb to act as buffer for future receives.  If a small
- * packet is received, leave rv_skb alone, alloc a new skb of the
- * correct size, and copy the packet into it
- */
-
-static void
-Bchan_recv_callback(struct BCState *bcs)
-{
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-
-	hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS;
-	hw->rv_buff_in %= RCV_BUFSIZE;
-
-	if (hw->rv_buff_in != hw->rv_buff_out) {
-		amd7930_brecv(0, bcs->channel,
-			      hw->rv_buff + hw->rv_buff_in,
-			      RCV_BUFSIZE/RCV_BUFBLKS,
-			      (void *) &Bchan_recv_callback, (void *) bcs);
-	}
-
-	schedule_work(&hw->rcv_work);
-}
-
-static void
-Bchan_rcv_bh(void *data)
-{
-	struct BCState *bcs = data;
-	struct IsdnCardState *cs = bcs->cs;
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-	struct sk_buff *skb;
-	int len;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[1024];
-
-		sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)",
-			hw->rv_buff_in, hw->rv_buff_out);
-		debugl1(cs, tmp);
-		QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
-			 RCV_BUFSIZE/RCV_BUFBLKS);
-		debugl1(cs, tmp);
-	}
-
-	do {
-		if (bcs->mode == L1_MODE_HDLC) {
-			while ((len = read_raw_hdlc_data(hw->hdlc_state,
-							 hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS,
-							 hw->rv_skb->tail, HSCX_BUFMAX))) {
-				if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) {
-					char tmp[1024];
-					char *t = tmp;
-
-					t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len);
-					QuickHex(t, hw->rv_skb->tail, len);
-					debugl1(cs, tmp);
-				}
-
-				if (len > HSCX_BUFMAX/2) {
-					/* Large packet received */
-
-					if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) {
-						printk(KERN_WARNING "amd7930: receive out of memory");
-					} else {
-						skb_put(hw->rv_skb, len);
-						skb_queue_tail(&bcs->rqueue, hw->rv_skb);
-						hw->rv_skb = skb;
-						bcs->event |= 1 << B_RCVBUFREADY;
-						schedule_work(&bcs->work);
-					}
-				} else if (len > 0) {
-					/* Small packet received */
-
-					if (!(skb = dev_alloc_skb(len))) {
-						printk(KERN_WARNING "amd7930: receive out of memory\n");
-					} else {
-						memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
-						skb_queue_tail(&bcs->rqueue, skb);
-						bcs->event |= 1 << B_RCVBUFREADY;
-						schedule_work(&bcs->work);
-					}
-				} else {
-					/* Reception Error */
-					/* printk("amd7930: B channel receive error\n"); */
-				}
-			}
-		} else if (bcs->mode == L1_MODE_TRANS) {
-			if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) {
-				printk(KERN_WARNING "amd7930: receive out of memory\n");
-			} else {
-				memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS),
-				       hw->rv_buff + hw->rv_buff_out,
-				       RCV_BUFSIZE/RCV_BUFBLKS);
-				skb_queue_tail(&bcs->rqueue, skb);
-				bcs->event |= 1 << B_RCVBUFREADY;
-				schedule_work(&bcs->work);
-			}
-		}
-
-		if (hw->rv_buff_in == hw->rv_buff_out) {
-			/* Buffer was filled up - need to restart receiver */
-			amd7930_brecv(0, bcs->channel,
-				      hw->rv_buff + hw->rv_buff_in,
-				      RCV_BUFSIZE/RCV_BUFBLKS,
-				      (void *) &Bchan_recv_callback,
-				      (void *) bcs);
-		}
-
-		hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS;
-		hw->rv_buff_out %= RCV_BUFSIZE;
-
-	} while (hw->rv_buff_in != hw->rv_buff_out);
-}
-
-static void
-Bchan_close(struct BCState *bcs)
-{
-	struct sk_buff *skb;
-
-	Bchan_mode(bcs, 0, 0);
-	amd7930_bclose(0, bcs->channel);
-
-	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		skb_queue_purge(&bcs->rqueue);
-		skb_queue_purge(&bcs->squeue);
-	}
-	test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-}
-
-static int
-Bchan_open(struct BCState *bcs)
-{
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-
-	amd7930_bopen(0, bcs->channel, 0xff);
-	hw->rv_buff_in = 0;
-	hw->rv_buff_out = 0;
-	hw->tx_skb = NULL;
-	init_hdlc_state(hw->hdlc_state, 0);
-	amd7930_brecv(0, bcs->channel,
-		      hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS,
-		      (void *) &Bchan_recv_callback, (void *) bcs);
-
-	bcs->event = 0;
-	bcs->tx_cnt = 0;
-	return (0);
-}
-
-static void
-Bchan_init(struct BCState *bcs)
-{
-	if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.tx_buff\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.rv_buff\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.rv_skb\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state),
-						   GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.hdlc_state\n");
-		return;
-	}
-
-	INIT_WORK(&bcs->hw.amd7930.rcv_work, &Bchan_rcv_bh, bcs);
-	INIT_WORK(&bcs->hw.amd7930.xmt_work, &Bchan_xmt_bh, bcs);
-}
-
-static void
-Bchan_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				Bchan_mode(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
-int
-setstack_amd7930(struct PStack *st, struct BCState *bcs)
-{
-	if (Bchan_open(bcs))
-		return (-1);
-	st->l1.bcs = bcs;
-	st->l2.l2l1 = Bchan_l2l1;
-	st->ma.manl1 = Bchan_manl1;
-	setstack_manager(st);
-	bcs->st = st;
-	return (0);
-}
-
-
-static void
-amd7930_drecv_callback(void *arg, int error, unsigned int count)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct work_struct task;
-	struct sk_buff *skb;
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	if (1) {
-		if (!(skb = alloc_skb(count, GFP_ATOMIC)))
-			printk(KERN_WARNING "HiSax: D receive out of memory\n");
-		else {
-			memcpy(skb_put(skb, count), cs->rcvbuf, count);
-			skb_queue_tail(&cs->rq, skb);
-		}
-
-		INIT_WORK(&task, (void *) DChannel_proc_rcv, (void *) cs);
-		schedule_work(&task);
-	}
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930 Drecv cnt %d", count);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->rcvbuf, count);
-		debugl1(cs, tmp);
-	}
-
-	amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-		      &amd7930_drecv_callback, cs);
-}
-
-static void
-amd7930_dxmit_callback(void *arg, int error)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct work_struct task;
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	/* may wish to do retransmission here, if error indicates collision */
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->tx_skb->data, cs->tx_skb->len);
-		debugl1(cs, tmp);
-	}
-
-	cs->tx_skb = NULL;
-
-	INIT_WORK(&task, (void *) DChannel_proc_xmt, (void *) cs);
-	schedule_work(&task);
-}
-
-static void
-amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
-	struct sk_buff *skb = arg;
-	char str[64];
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
-					/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data+4, skb->len-4,
-						  str);
-				}
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				amd7930_dxmit(0, skb->data, skb->len,
-					      &amd7930_dxmit_callback, cs);
-			}
-			break;
-		case (PH_PULL_IND):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
-				      &amd7930_dxmit_callback, cs);
-			break;
-		case (PH_PULL_REQ):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-int
-setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs)
-{
-	st->l2.l2l1 = amd7930_Dchan_l2l1;
-	if (! cs->rcvbuf) {
-		printk("setDstack_amd7930: No cs->rcvbuf!\n");
-	} else {
-		amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-			      &amd7930_drecv_callback, cs);
-	}
-	return (0);
-}
-
-static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
-
-static void
-amd7930_new_ph(struct IsdnCardState *cs)
-{
-	switch (amd7930_get_liu_state(0)) {
-	        case 3:
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
-                        break;
-
-	        case 7:
-			manl1_msg(cs, PH_I4_P8_IND, NULL);
-			break;
-
-	        case 8:
-			manl1_msg(cs, PH_RSYNC_IND, NULL);
-			break;
-	}
-}
-
-/* amd7930 LIU state change callback */
-
-static void
-amd7930_liu_callback(struct IsdnCardState *cs)
-{
-	static struct work_struct task;
-
-	if (!cs)
-		return;
-
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0));
-		debugl1(cs, tmp);
-	}
-
-	INIT_WORK(&task, (void *) &amd7930_new_ph, (void *) cs);
-	schedule_work(&task);
-}
-
-void
-amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	u8 val;
-	char tmp[32];
-	
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "amd7930_l1cmd msg %x", msg);
-		debugl1(cs, tmp);
-	}
-
-	switch(msg) {
-		case PH_RESET_REQ:
-			if (amd7930_get_liu_state(0) <= 3)
-				amd7930_liu_activate(0,0);
-			else
-				amd7930_liu_deactivate(0);
-			break;
-		case PH_ENABLE_REQ:
-			break;
-		case PH_INFO3_REQ:
-			amd7930_liu_activate(0,0);
-			break;
-		case PH_TESTLOOP_REQ:
-			break;
-		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "amd7930_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
-			}
-			break;
-	}
-}
-
-static void init_amd7930(struct IsdnCardState *cs)
-{
-	Bchan_init(&cs->bcs[0]);
-	Bchan_init(&cs->bcs[1]);
-	cs->bcs[0].BC_SetStack = setstack_amd7930;
-	cs->bcs[1].BC_SetStack = setstack_amd7930;
-	cs->bcs[0].BC_Close = Bchan_close;
-	cs->bcs[1].BC_Close = Bchan_close;
-	Bchan_mode(cs->bcs, 0, 0);
-	Bchan_mode(cs->bcs + 1, 0, 0);
-}
-
-static int
-amd7930_init(struct IsdnCardState *cs)
-{
-	cs->l1cmd = amd7930_l1cmd;
-	amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
-	init_amd7930(cs);
-	return 0;
-}
-
-static struct card_ops amd7930_ops = {
-	.init     = amd7930_init,
-};
-
-int __init
-setup_amd7930(struct IsdnCard *card)
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, amd7930_revision);
-	printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp));
-
-        cs->irq = amd7930_get_irqnum(0);
-        if (cs->irq == 0)
-		return 0;
-
-	cs->card_ops = &amd7930_ops;
-	return 1;
-}
diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
--- a/drivers/isdn/hisax/asuscom.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/asuscom.c	Thu Mar  6 22:52:04 2003
@@ -231,6 +231,51 @@
 	.irq_func = ipac_irq,
 };
 
+static int __init
+asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	u8 val;
+
+	printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
+
+	cs->hw.asus.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn"))
+		goto err;
+
+	rc = -ENODEV;
+	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
+	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
+	if ((val == 1) || (val == 2)) {
+		cs->subtyp = ASUS_IPAC;
+		cs->card_ops = &asuscom_ipac_ops;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+	} else {
+		cs->subtyp = ASUS_ISACHSCX;
+		cs->card_ops = &asuscom_ops;
+		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
+		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
+		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
+	}
+	printk(KERN_INFO "ISDNLink: resetting card\n");
+	cs->card_ops->reset(cs);
+	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id asus_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
@@ -255,9 +300,6 @@
 int __init
 setup_asuscom(struct IsdnCard *card)
 {
-	int bytecnt;
-	struct IsdnCardState *cs = card->cs;
-	u8 val;
 	char tmp[64];
 
 	strcpy(tmp, Asuscom_revision);
@@ -310,36 +352,7 @@
 		}
 	}
 #endif
-	bytecnt = 8;
-	cs->hw.asus.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn"))
-		goto err;
-	printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
-		cs->hw.asus.cfg_reg, cs->irq);
-	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
-	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
-	if ((val == 1) || (val == 2)) {
-		cs->subtyp = ASUS_IPAC;
-		cs->card_ops = &asuscom_ipac_ops;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->subtyp = ASUS_ISACHSCX;
-		cs->card_ops = &asuscom_ops;
-		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
-		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
-		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
-		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	printk(KERN_INFO "ISDNLink: resetting card\n");
-	cs->card_ops->reset(cs);
+	if (asuscom_probe(card->cs, card) < 0)
+		return 0;
 	return 1;
- err:
-	hisax_release_resources(cs);
-	return 0;
 }
diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
--- a/drivers/isdn/hisax/avm_a1.c	Sun Jan 12 16:12:36 2003
+++ b/drivers/isdn/hisax/avm_a1.c	Thu Mar  6 22:52:04 2003
@@ -160,16 +160,16 @@
 	.irq_func = avm_a1_interrupt,
 };
 
-int __init
-setup_avm_a1(struct IsdnCard *card)
+static int __init
+avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
+	int rc;
 	u8 val;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
 
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
 
+	rc = -EBUSY;
 	cs->hw.avm.cfg_reg     = request_io(&cs->rs, card->para[1] + 0x1800,  8, "avm cfg");
 	if (!cs->hw.avm.cfg_reg) goto err;
 	cs->hw.avm.isac        = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac");
@@ -216,23 +216,24 @@
 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
 	       cs->hw.avm.cfg_reg, val);
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.avm.cfg_reg);
-	printk(KERN_INFO
-	       "HiSax: isac:0x%X/0x%X\n",
-	       cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
-	printk(KERN_INFO
-	       "HiSax: hscx A:0x%X/0x%X  hscx B:0x%X/0x%X\n",
-	       cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
-	       cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
-
 	cs->card_ops = &avm_a1_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return rc;
+}
+
+int __init
+setup_avm_a1(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (avm_a1_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
--- a/drivers/isdn/hisax/avm_a1p.c	Sun Jan 12 16:12:36 2003
+++ b/drivers/isdn/hisax/avm_a1p.c	Thu Mar  6 22:52:04 2003
@@ -215,20 +215,13 @@
 	.irq_func = avm_a1p_interrupt,
 };
 
-int __devinit
-setup_avm_a1_pcmcia(struct IsdnCard *card)
+static int __init
+avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
 	u8 model, vers;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
 
-
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-	cs->hw.avm.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
-
+	cs->hw.avm.cfg_reg = card->para[1];
 
 	outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
 
@@ -244,11 +237,26 @@
 	vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
 
 	printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
-				cs->hw.avm.cfg_reg, cs->irq, model, vers);
+	       cs->hw.avm.cfg_reg, cs->irq, model, vers);
 
 	cs->card_ops = &avm_a1p_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		return 0;
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __devinit
+setup_avm_a1_pcmcia(struct IsdnCard *card)
+{
+	char tmp[64];
 
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+	if (avm_a1p_probe(card->cs, card))
+		return 0;
 	return 1;
 }
diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
--- a/drivers/isdn/hisax/avm_pci.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/avm_pci.c	Thu Mar  6 22:52:04 2003
@@ -497,7 +497,7 @@
 	.close     = close_hdlcstate,
 };
 
-void __init
+static void __init
 inithdlc(struct IsdnCardState *cs)
 {
 	u_int val;
@@ -596,6 +596,82 @@
 	.irq_func = avm_pcipnp_interrupt,
 };
 
+static int __init
+avm_pcipnp_hw_init(struct IsdnCardState *cs)
+{
+	cs->bc_hw_ops = &hdlc_hw_ops;
+	cs->bc_l1_ops = &hdlc_l1_ops;
+	cs->card_ops = &avm_pci_ops;
+	avm_pcipnp_reset(cs);
+	return isac_setup(cs, &isac_ops);
+}
+
+static int __init
+avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	int rc;
+	u32 val;
+
+	printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n",
+	       pci_resource_start(pdev, 1), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp = AVM_FRITZ_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI"))
+		goto err;
+
+	val = inl(cs->hw.avm.cfg_reg);
+	printk(KERN_INFO "AVM PCI: stat %#x\n", val);
+	printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
+	       val & 0xff, (val>>8) & 0xff);
+
+	if (avm_pcipnp_hw_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
+static int __init
+avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	u8 val, ver;
+
+	printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
+
+	cs->subtyp = AVM_FRITZ_PNP;
+	cs->irq = card->para[0];
+	cs->hw.avm.cfg_reg = card->para[1];
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP"))
+		goto err;
+	
+	val = inb(cs->hw.avm.cfg_reg);
+	ver = inb(cs->hw.avm.cfg_reg + 1);
+	printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
+
+	if (avm_pcipnp_hw_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 static struct pci_dev *dev_avm __initdata = NULL;
 #ifdef __ISAPNP__
 static struct pnp_card *card_avm __initdata = NULL;
@@ -605,17 +681,15 @@
 int __init
 setup_avm_pcipnp(struct IsdnCard *card)
 {
-	u_int val, ver;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, avm_pci_rev);
 	printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
 	if (card->para[1]) {
 		/* old manual method */
-		cs->hw.avm.cfg_reg = card->para[1];
-		cs->irq = card->para[0];
-		cs->subtyp = AVM_FRITZ_PNP;
+		if (avm_pnp_probe(card->cs, card))
+			return 0;
+		return 1;
 	} else {
 #ifdef __ISAPNP__
 		if (isapnp_present()) {
@@ -647,69 +721,24 @@
 						pnp_device_detach(pnp_avm);
 						return(0);
 					}
-					cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0);
-					cs->irq = pnp_irq(pnp_avm, 0);
-					cs->subtyp = AVM_FRITZ_PNP;
-					goto ready;
+					card->para[1] = pnp_port_start(pnp_avm, 0);
+					card->para[0] = pnp_irq(pnp_avm, 0);
+					if (avm_pnp_probe(card->cs, card))
+						return 0;
+					return 1;
 				}
 			}
-		} else {
-			printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
 		}
 #endif
 #if CONFIG_PCI
 		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
 			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-			cs->irq = dev_avm->irq;
-			if (!cs->irq) {
-				printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			if (pci_enable_device(dev_avm))
-				return(0);
-			cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
-			if (!cs->hw.avm.cfg_reg) {
-				printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = AVM_FRITZ_PCI;
-		} else {
-			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
-			return(0);
+			if (avm_pci_probe(card->cs, dev_avm))
+				return 0;
+			return 1;
 		}
-		cs->irq_flags |= SA_SHIRQ;
 #endif /* CONFIG_PCI */
 	}
-ready:
-	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
-	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32,
-		 cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP"))
-		goto err;
-	
-	switch (cs->subtyp) {
-	  case AVM_FRITZ_PCI:
-		val = inl(cs->hw.avm.cfg_reg);
-		printk(KERN_INFO "AVM PCI: stat %#x\n", val);
-		printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
-			val & 0xff, (val>>8) & 0xff);
-		break;
-	  case AVM_FRITZ_PNP:
-		val = inb(cs->hw.avm.cfg_reg);
-		ver = inb(cs->hw.avm.cfg_reg + 1);
-		printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
-		avm_pcipnp_reset(cs);
-		break;
-	}
-	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
-		(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
-		cs->irq, cs->hw.avm.cfg_reg);
-
-	cs->bc_hw_ops = &hdlc_hw_ops;
-	cs->bc_l1_ops = &hdlc_l1_ops;
-	cs->card_ops = &avm_pci_ops;
-	isac_setup(cs, &isac_ops);
-	return 1;
- err:
-	hisax_release_resources(cs);
+	printk(KERN_WARNING "FritzPCI: No card found\n");
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
--- a/drivers/isdn/hisax/bkm_a4t.c	Sun Jan 12 16:12:36 2003
+++ b/drivers/isdn/hisax/bkm_a4t.c	Thu Mar  6 22:52:04 2003
@@ -21,11 +21,11 @@
 #include "bkm_ax.h"
 
 extern const char *CardType[];
+// FIXME needs per card lock
 static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED;
 
 const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $";
 
-
 static inline u8
 readreg(unsigned int ale, unsigned long adr, u8 off)
 {
@@ -249,15 +249,57 @@
 	.irq_func = bkm_interrupt,
 };
 
+static int __init
+bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	I20_REGISTER_FILE *pI20_Regs;
+	int rc;
+
+	printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n",
+	       pci_resource_start(pdev, 0), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
+
+	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T");
+	if (!cs->hw.ax.base)
+		goto err;
+	
+	/* Check suspicious address */
+	// FIXME needs to use read[bl]
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+		printk(KERN_WARNING "HiSax: address %lx suspicious\n",
+		       cs->hw.ax.base);
+		goto err;
+	}
+	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.isac_ale = GCS_1;
+	cs->hw.ax.jade_ale = GCS_3;
+
+	reset_bkm(cs);
+	cs->card_ops = &bkm_a4t_ops;
+	isac_setup(cs, &isac_ops);
+	jade_setup(cs, &jade_ops);
+	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 static struct pci_dev *dev_a4t __initdata = NULL;
 
 int __init
 setup_bkm_a4t(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u_int pci_memaddr = 0, found = 0;
-	I20_REGISTER_FILE *pI20_Regs;
 
 	strcpy(tmp, bkm_a4t_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
@@ -268,49 +310,13 @@
 
 		sub_vendor = dev_a4t->subsystem_vendor;
 		sub_sys = dev_a4t->subsystem_device;
-		if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
-			if (pci_enable_device(dev_a4t))
-				return(0);
-			found = 1;
-			pci_memaddr = pci_resource_start(dev_a4t, 0);
-			cs->irq = dev_a4t->irq;
-			break;
+		if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && 
+		    sub_vendor == PCI_VENDOR_ID_BERKOM) {
+			if (bkm_a4t_probe(card->cs, dev_a4t))
+				return 0;
+			return 1;
 		}
 	}
-	if (!found) {
-		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
-		return (0);
-	}
-	if (!cs->irq) {		/* IRQ range check ?? */
-		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
-		return (0);
-	}
-	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T");
-	if (!cs->hw.ax.base) {
-		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
-		return (0);
-	}
-	
-	/* Check suspecious address */
-	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
-		printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
-		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
-		hisax_release_resources(cs);
-		return (0);
-	}
-	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.isac_ale = GCS_1;
-	cs->hw.ax.jade_ale = GCS_3;
-
-	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
-	       CardType[card->typ], cs->hw.ax.base, cs->irq);
-
-	reset_bkm(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &bkm_a4t_ops;
-	isac_setup(cs, &isac_ops);
-	jade_setup(cs, &jade_ops);
-	return 1;
+	printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
--- a/drivers/isdn/hisax/config.c	Wed Jan 15 08:20:56 2003
+++ b/drivers/isdn/hisax/config.c	Thu Mar  6 23:20:18 2003
@@ -490,125 +490,36 @@
 __setup("hisax=", HiSax_setup);
 #endif /* MODULES */
 
-#if CARD_TELES0
 extern int setup_teles0(struct IsdnCard *card);
-#endif
-
-#if CARD_TELES3
 extern int setup_teles3(struct IsdnCard *card);
-#endif
-
-#if CARD_S0BOX
 extern int setup_s0box(struct IsdnCard *card);
-#endif
-
-#if CARD_TELESPCI
 extern int setup_telespci(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1
 extern int setup_avm_a1(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1_PCMCIA
 extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
-#endif
-
-#if CARD_FRITZPCI
 extern int setup_avm_pcipnp(struct IsdnCard *card);
-#endif
-
-#if CARD_ELSA
 extern int setup_elsa(struct IsdnCard *card);
-#endif
-
-#if CARD_IX1MICROR2
 extern int setup_ix1micro(struct IsdnCard *card);
-#endif
-
-#if CARD_DIEHLDIVA
 extern int setup_diva(struct IsdnCard *card);
-#endif
-
-#if CARD_ASUSCOM
 extern int setup_asuscom(struct IsdnCard *card);
-#endif
-
-#if CARD_TELEINT
 extern int setup_TeleInt(struct IsdnCard *card);
-#endif
-
-#if CARD_SEDLBAUER
 extern int setup_sedlbauer(struct IsdnCard *card);
-#endif
-
-#if CARD_SPORTSTER
 extern int setup_sportster(struct IsdnCard *card);
-#endif
-
-#if CARD_MIC
 extern int setup_mic(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET_S
 extern int setup_netjet_s(struct IsdnCard *card);
-#endif
-
-#if CARD_HFCS
 extern int setup_hfcs(struct IsdnCard *card);
-#endif
-
-#if CARD_HFC_PCI
 extern int setup_hfcpci(struct IsdnCard *card);
-#endif
-
-#if CARD_HFC_SX
 extern int setup_hfcsx(struct IsdnCard *card);
-#endif
-
-#if CARD_AMD7930
 extern int setup_amd7930(struct IsdnCard *card);
-#endif
-
-#if CARD_NICCY
 extern int setup_niccy(struct IsdnCard *card);
-#endif
-
-#if CARD_ISURF
 extern int setup_isurf(struct IsdnCard *card);
-#endif
-
-#if CARD_HSTSAPHIR
 extern int setup_saphir(struct IsdnCard *card);
-#endif
-
-#if CARD_TESTEMU
 extern int setup_testemu(struct IsdnCard *card);
-#endif
-
-#if CARD_BKM_A4T
 extern int setup_bkm_a4t(struct IsdnCard *card);
-#endif
-
-#if CARD_SCT_QUADRO
 extern int setup_sct_quadro(struct IsdnCard *card);
-#endif
-
-#if CARD_GAZEL
 extern int setup_gazel(struct IsdnCard *card);
-#endif
-
-#if CARD_W6692
 extern int setup_w6692(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET_U
 extern int setup_netjet_u(struct IsdnCard *card);
-#endif
-
-#if CARD_FN_ENTERNOW_PCI
 extern int setup_enternow_pci(struct IsdnCard *card);
-#endif
 
 /*
  * Find card with given driverId
@@ -703,16 +614,16 @@
 	return 8;
 }
 
-static u8 tmpbuf[HISAX_STATUS_BUFSIZE];
+static char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
 		      va_list args)
 {
 	/* if head == NULL the fmt contains the full info */
 
 	unsigned long flags;
 	int count, i;
-	u8 *p;
+	char *p;
 	isdn_ctrl ic;
 	int len;
 
@@ -727,7 +638,7 @@
 		len = p - tmpbuf;
 		p = tmpbuf;
 	} else {
-		p = fmt;
+		p = (char *) fmt;
 		len = strlen(fmt);
 	}
 	if (!cs) {
@@ -814,12 +725,6 @@
 	ic.command = ISDN_STAT_UNLOAD;
 	ic.driver = cs->myid;
 	cs->iif.statcallb(&ic);
-	if (cs->status_buf)
-		kfree(cs->status_buf);
-	cs->status_read = NULL;
-	cs->status_write = NULL;
-	cs->status_end = NULL;
-	kfree(cs->dlog);
 }
 
 static void closecard(int cardnr)
@@ -893,59 +798,97 @@
 	return 3;
 }
 
+static struct IsdnCardState *
+alloc_IsdnCardState(void)
+{
+	struct IsdnCardState *cs;
+
+	cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME
+	if (!cs)
+		goto err;
+
+	memset(cs, 0, sizeof(*cs));
+
+	cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC);
+	if (!cs->dlog)
+		goto err_cs;
+
+	cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC);
+	if (!cs->status_buf)
+		goto err_dlog;
+
+	cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC);
+	if (!cs->rcvbuf)
+		goto err_status_buf;
+
+	cs->chanlimit = 2;	/* maximum B-channel number */
+	cs->debug = L1_DEB_WARN;
+	cs->irq_flags = I4L_IRQ_FLAG;
+	cs->stlist = NULL;
+	cs->status_read = cs->status_buf;
+	cs->status_write = cs->status_buf;
+	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+	cs->rcvidx = 0;
+	cs->tx_skb = NULL;
+	cs->tx_cnt = 0;
+	cs->event = 0;
+
+	skb_queue_head_init(&cs->rq);
+	skb_queue_head_init(&cs->sq);
+
+	spin_lock_init(&cs->lock);
+	resources_init(&cs->rs);
+	return cs;
+
+ err_status_buf:
+	kfree(cs->status_buf);
+ err_dlog:
+	kfree(cs->dlog);
+ err_cs:
+	kfree(cs);
+ err:
+	return NULL;
+}
+
+static void
+free_IsdnCardState(struct IsdnCardState *cs)
+{
+	kfree(cs->rcvbuf);
+	kfree(cs->status_buf);
+	kfree(cs->dlog);
+	kfree(cs);
+}
+
 static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
 {
 	int ret = 0;
 	struct IsdnCard *card = cards + cardnr;
 	struct IsdnCardState *cs;
 
-	cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+	cs = alloc_IsdnCardState();
 	if (!cs) {
 		printk(KERN_WARNING
 		       "HiSax: No memory for IsdnCardState(card %d)\n",
 		       cardnr + 1);
 		goto out;
 	}
-	memset(cs, 0, sizeof(struct IsdnCardState));
 	card->cs = cs;
-	cs->chanlimit = 2;	/* maximum B-channel number */
-	cs->logecho = 0;	/* No echo logging */
-	cs->cardnr = cardnr;
-	cs->debug = L1_DEB_WARN;
-	cs->HW_Flags = 0;
-	cs->busy_flag = busy_flag;
-	cs->irq_flags = I4L_IRQ_FLAG;
 #if TEI_PER_CARD
 	if (card->protocol == ISDN_PTYPE_NI1)
 		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
 #else
 	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
 #endif
+	cs->cardnr = cardnr;
 	cs->protocol = card->protocol;
+	cs->typ = card->typ;
+	cs->busy_flag = busy_flag;
 
 	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
 		printk(KERN_WARNING
 		       "HiSax: Card Type %d out of range\n", card->typ);
 		goto outf_cs;
 	}
-	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
-		goto outf_cs;
-	}
-	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for status_buf(card %d)\n",
-		       cardnr + 1);
-		goto outf_dlog;
-	}
-	cs->stlist = NULL;
-	cs->status_read = cs->status_buf;
-	cs->status_write = cs->status_buf;
-	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
-	cs->typ = card->typ;
-	spin_lock_init(&cs->lock);
-	resources_init(&cs->rs);
 	SET_MODULE_OWNER(&cs->iif);
 	strcpy(cs->iif.id, id);
 	cs->iif.channels = 2;
@@ -982,13 +925,13 @@
 	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
 	       "NONE", cs->iif.id, cs->myid);
 	switch (card->typ) {
-#if CARD_TELES0
+#ifdef CONFIG_HISAX_16_0
 	case ISDN_CTYPE_16_0:
 	case ISDN_CTYPE_8_0:
 		ret = setup_teles0(card);
 		break;
 #endif
-#if CARD_TELES3
+#ifdef CONFIG_HISAX_16_3
 	case ISDN_CTYPE_16_3:
 	case ISDN_CTYPE_PNP:
 	case ISDN_CTYPE_TELESPCMCIA:
@@ -996,32 +939,32 @@
 		ret = setup_teles3(card);
 		break;
 #endif
-#if CARD_S0BOX
+#ifdef CONFIG_HISAX_S0BOX
 	case ISDN_CTYPE_S0BOX:
 		ret = setup_s0box(card);
 		break;
 #endif
-#if CARD_TELESPCI
+#ifdef CONFIG_HISAX_TELESPCI
 	case ISDN_CTYPE_TELESPCI:
 		ret = setup_telespci(card);
 		break;
 #endif
-#if CARD_AVM_A1
+#ifdef CONFIG_HISAX_AVM_A1
 	case ISDN_CTYPE_A1:
 		ret = setup_avm_a1(card);
 		break;
 #endif
-#if CARD_AVM_A1_PCMCIA
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
 	case ISDN_CTYPE_A1_PCMCIA:
 		ret = setup_avm_a1_pcmcia(card);
 		break;
 #endif
-#if CARD_FRITZPCI
+#ifdef CONFIG_HISAX_FRITZPCI
 	case ISDN_CTYPE_FRITZPCI:
 		ret = setup_avm_pcipnp(card);
 		break;
 #endif
-#if CARD_ELSA
+#ifdef CONFIG_HISAX_ELSA
 	case ISDN_CTYPE_ELSA:
 	case ISDN_CTYPE_ELSA_PNP:
 	case ISDN_CTYPE_ELSA_PCMCIA:
@@ -1029,115 +972,115 @@
 		ret = setup_elsa(card);
 		break;
 #endif
-#if CARD_IX1MICROR2
+#ifdef CONFIG_HISAX_IX1MICROR2
 	case ISDN_CTYPE_IX1MICROR2:
 		ret = setup_ix1micro(card);
 		break;
 #endif
-#if CARD_DIEHLDIVA
+#ifdef CONFIG_HISAX_DIEHLDIVA
 	case ISDN_CTYPE_DIEHLDIVA:
 		ret = setup_diva(card);
 		break;
 #endif
-#if CARD_ASUSCOM
+#ifdef CONFIG_HISAX_ASUSCOM
 	case ISDN_CTYPE_ASUSCOM:
 		ret = setup_asuscom(card);
 		break;
 #endif
-#if CARD_TELEINT
+#ifdef CONFIG_HISAX_TELEINT
 	case ISDN_CTYPE_TELEINT:
 		ret = setup_TeleInt(card);
 		break;
 #endif
-#if CARD_SEDLBAUER
+#ifdef CONFIG_HISAX_SEDLBAUER
 	case ISDN_CTYPE_SEDLBAUER:
 	case ISDN_CTYPE_SEDLBAUER_PCMCIA:
 	case ISDN_CTYPE_SEDLBAUER_FAX:
 		ret = setup_sedlbauer(card);
 		break;
 #endif
-#if CARD_SPORTSTER
+#ifdef CONFIG_HISAX_SPORTSTER
 	case ISDN_CTYPE_SPORTSTER:
 		ret = setup_sportster(card);
 		break;
 #endif
-#if CARD_MIC
+#ifdef CONFIG_HISAX_MIC
 	case ISDN_CTYPE_MIC:
 		ret = setup_mic(card);
 		break;
 #endif
-#if CARD_NETJET_S
+#ifdef CONFIG_HISAX_NETJET
 	case ISDN_CTYPE_NETJET_S:
 		ret = setup_netjet_s(card);
 		break;
 #endif
-#if CARD_HFCS
+#ifdef CONFIG_HISAX_HFCS
 	case ISDN_CTYPE_TELES3C:
 	case ISDN_CTYPE_ACERP10:
 		ret = setup_hfcs(card);
 		break;
 #endif
-#if CARD_HFC_PCI
+#ifdef CONFIG_HISAX_HFC_PCI
 	case ISDN_CTYPE_HFC_PCI:
 		ret = setup_hfcpci(card);
 		break;
 #endif
-#if CARD_HFC_SX
+#ifdef CONFIG_HISAX_HFC_SX
 	case ISDN_CTYPE_HFC_SX:
 		ret = setup_hfcsx(card);
 		break;
 #endif
-#if CARD_NICCY
+#ifdef CONFIG_HISAX_NICCY
 	case ISDN_CTYPE_NICCY:
 		ret = setup_niccy(card);
 		break;
 #endif
-#if CARD_AMD7930
+#ifdef CONFIG_HISAX_AMD7930
 	case ISDN_CTYPE_AMD7930:
 		ret = setup_amd7930(card);
 		break;
 #endif
-#if CARD_ISURF
+#ifdef CONFIG_HISAX_ISURF
 	case ISDN_CTYPE_ISURF:
 		ret = setup_isurf(card);
 		break;
 #endif
-#if CARD_HSTSAPHIR
+#ifdef CONFIG_HISAX_HSTSAPHIR
 	case ISDN_CTYPE_HSTSAPHIR:
 		ret = setup_saphir(card);
 		break;
 #endif
-#if CARD_TESTEMU
+#ifdef CONFIG_HISAX_TESTEMU
 	case ISDN_CTYPE_TESTEMU:
 		ret = setup_testemu(card);
 		break;
 #endif
-#if	CARD_BKM_A4T
+#ifdef CONFIG_HISAX_BKM_A4T
 	case ISDN_CTYPE_BKM_A4T:
 		ret = setup_bkm_a4t(card);
 		break;
 #endif
-#if	CARD_SCT_QUADRO
+#ifdef CONFIG_HISAX_SCT_QUADRO
 	case ISDN_CTYPE_SCT_QUADRO:
 		ret = setup_sct_quadro(card);
 		break;
 #endif
-#if CARD_GAZEL
+#ifdef CONFIG_HISAX_GAZEL
 	case ISDN_CTYPE_GAZEL:
 		ret = setup_gazel(card);
 		break;
 #endif
-#if CARD_W6692
+#ifdef CONFIG_HISAX_W6692
 	case ISDN_CTYPE_W6692:
 		ret = setup_w6692(card);
 		break;
 #endif
-#if CARD_NETJET_U
+#ifdef CONFIG_HISAX_NETJET_U
 	case ISDN_CTYPE_NETJET_U:
 		ret = setup_netjet_u(card);
 		break;
 #endif
-#if CARD_FN_ENTERNOW_PCI
+#ifdef CONFIG_HISAX_ENTERNOW_PCI
 	case ISDN_CTYPE_ENTERNOW:
 		ret = setup_enternow_pci(card);
 		break;
@@ -1156,19 +1099,6 @@
 		ll_unload(cs);
 		goto outf_cs;
 	}
-	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
-		printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
-		ll_unload(cs);
-		goto outf_cs;
-	}
-	cs->rcvidx = 0;
-	cs->tx_skb = NULL;
-	cs->tx_cnt = 0;
-	cs->event = 0;
-
-	skb_queue_head_init(&cs->rq);
-	skb_queue_head_init(&cs->sq);
-
 	init_bcstate(cs, 0);
 	init_bcstate(cs, 1);
 
@@ -1201,10 +1131,8 @@
 	ret = 1;
 	goto out;
 
- outf_dlog:
-	kfree(cs->dlog);
  outf_cs:
-	kfree(cs);
+	free_IsdnCardState(cs);
 	card->cs = NULL;
  out:
 	return ret;
@@ -1253,8 +1181,8 @@
 			i++;
 		} else {
 			printk(KERN_WARNING
-			       "HiSax: Card %s not installed !\n",
-			       CardType[cards[i].typ]);
+			       "HiSax: Card type %d not installed !\n",
+			       cards[i].typ);
 			HiSax_shiftcards(i);
 			nrcards--;
 		}
diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
--- a/drivers/isdn/hisax/diva.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/diva.c	Thu Mar  6 22:52:04 2003
@@ -362,7 +362,7 @@
 static void
 diva_release(struct IsdnCardState *cs)
 {
-	del_timer(&cs->hw.diva.tl);
+	del_timer_sync(&cs->hw.diva.tl);
 	if (cs->hw.diva.cfg_reg)
 		byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
 
@@ -515,6 +515,162 @@
 	.irq_func    = diva_ipacx_pci_irq,
 };
 
+static int __init
+diva_ipac_probe(struct IsdnCardState *cs)
+{
+	u8 val;
+
+	// request_io
+	val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
+		      cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
+	printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	return (val == 1 || val == 2);
+}
+
+static int __init
+diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = DIVA_IPAC_ISA;
+	cs->irq = card->para[0];
+	cs->hw.diva.cfg_reg  = card->para[1];
+	cs->hw.diva.isac     = card->para[1] + DIVA_IPAC_DATA;
+	cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		goto err;
+	diva_ipac_isa_reset(cs);
+	cs->card_ops = &diva_ipac_isa_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = DIVA_ISA;
+	cs->irq = card->para[0];
+	cs->hw.diva.cfg_reg  = card->para[1];
+	cs->hw.diva.ctrl     = card->para[1] + DIVA_ISA_CTRL;
+	cs->hw.diva.isac     = card->para[1] + DIVA_ISA_ISAC_DATA;
+	cs->hw.diva.hscx     = card->para[1] + DIVA_HSCX_DATA;
+	cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
+	cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "ISA", cs->hw.diva.cfg_reg, cs->irq);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		goto err;
+	diva_reset(cs);
+	init_timer(&cs->hw.diva.tl);
+	cs->hw.diva.tl.function = (void *) diva_led_handler;
+	cs->hw.diva.tl.data = (long) cs;
+	cs->card_ops = &diva_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int is_ipac;
+	cs->hw.diva.cfg_reg  = card->para[1];
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		return -EBUSY;
+
+	is_ipac = diva_ipac_probe(cs);
+	hisax_release_resources(cs);
+
+	if (is_ipac)
+		return diva_ipac_isa_probe(cs, card);
+	else
+		return diva_isac_isa_probe(cs, card);
+}
+
+static int __init
+diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.diva.cfg_reg  = pci_resource_start(pdev, 2);
+	cs->hw.diva.ctrl     = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+	cs->hw.diva.isac     = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+	cs->hw.diva.hscx     = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+	cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+	cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "PCI", cs->hw.diva.pci_cfg);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn"))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_IPAC_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.diva.pci_cfg = (unsigned long)request_mmio(
+		&cs->rs, pci_resource_start(pdev, 0), 4096, "diva");
+	cs->hw.diva.cfg_reg = (unsigned long)request_mmio(
+		&cs->rs, pci_resource_start(pdev, 1), 4096, "diva");
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "IPAC PCI", cs->hw.diva.pci_cfg);
+	diva_ipac_pci_reset(cs);
+	cs->card_ops = &diva_ipac_pci_ops;
+	if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_IPACX_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "IPACX PCI", cs->hw.diva.pci_cfg);
+	diva_ipacx_pci_reset(cs);
+	cs->card_ops = &diva_ipacx_pci_ops;
+	if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_diva __initdata = NULL;
 static struct pci_dev *dev_diva_u __initdata = NULL;
 static struct pci_dev *dev_diva201 __initdata = NULL;
@@ -545,101 +701,60 @@
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
-
 int __init
 setup_diva(struct IsdnCard *card)
 {
-	int bytecnt = 8;
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Diva_revision);
 	printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
 	if (card->para[1]) {
-		cs->hw.diva.ctrl_reg = 0;
-		cs->hw.diva.cfg_reg = card->para[1];
-		val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
-			cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
-		printk(KERN_INFO "Diva: IPAC version %x\n", val);
-		if ((val == 1) || (val==2)) {
-			cs->subtyp = DIVA_IPAC_ISA;
-			cs->hw.diva.ctrl = 0;
-			cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
-			cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
-			cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
-			cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
-		} else {
-			cs->subtyp = DIVA_ISA;
-			cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
-			cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
-			cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
-			cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
-			cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
-		}
-		cs->irq = card->para[0];
-	} else {
+		if (diva_isa_probe(card->cs, card) < 0)
+			return 0;
+		return 1;
+		
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_card *pb;
-			struct pnp_dev *pd;
-
-			while(pdev->card_vendor) {
-				if ((pb = pnp_find_card(pdev->card_vendor,
-							pdev->card_device,
-							pnp_c))) {
-					pnp_c = pb;
-					pd = NULL;
-					if ((pd = pnp_find_dev(pnp_c,
-							       pdev->vendor,
-							       pdev->function,
-							       pd))) {
-						printk(KERN_INFO "HiSax: %s detected\n",
-							(char *)pdev->driver_data);
-						if (pnp_device_attach(pd) < 0) {
-							printk(KERN_ERR "Diva PnP: attach failed\n");
+	if (isapnp_present()) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+		
+		while(pdev->card_vendor) {
+			if ((pb = pnp_find_card(pdev->card_vendor,
+						pdev->card_device, pnp_c))) {
+				pnp_c = pb;
+				pd = NULL;
+				if ((pd = pnp_find_dev(pnp_c,
+						       pdev->vendor,
+						       pdev->function,
+						       pd))) {
+					printk(KERN_INFO "HiSax: %s detected\n",
+					       (char *)pdev->driver_data);
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "Diva PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd) < 0) {
+						printk(KERN_ERR "Diva PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+						printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
+						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
+						return(0);
+					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
+					if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
+						if (diva_ipac_isa_probe(cs->card, cs))
 							return 0;
-						}
-						if (pnp_activate_dev(pd) < 0) {
-							printk(KERN_ERR "Diva PnP: activate failed\n");
-							pnp_device_detach(pd);
+						return 1;
+					} else {
+						if (diva_isac_isa_probe(cs->card, cs))
 							return 0;
-						}
-						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-							printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
-								pnp_irq(pd, 0), pnp_port_start(pd, 0));
-							pnp_device_detach(pd);
-							return(0);
-						}
-						card->para[1] = pnp_port_start(pd, 0);
-						card->para[0] = pnp_irq(pd, 0);
-						cs->hw.diva.cfg_reg  = card->para[1];
-						cs->irq = card->para[0];
-						if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
-							cs->subtyp = DIVA_IPAC_ISA;
-							cs->hw.diva.ctrl = 0;
-							cs->hw.diva.isac =
-								card->para[1] + DIVA_IPAC_DATA;
-							cs->hw.diva.hscx =
-								card->para[1] + DIVA_IPAC_DATA;
-							cs->hw.diva.isac_adr =
-								card->para[1] + DIVA_IPAC_ADR;
-							cs->hw.diva.hscx_adr =
-								card->para[1] + DIVA_IPAC_ADR;
-						} else {
-							cs->subtyp = DIVA_ISA;
-							cs->hw.diva.ctrl =
-								card->para[1] + DIVA_ISA_CTRL;
-							cs->hw.diva.isac =
-								card->para[1] + DIVA_ISA_ISAC_DATA;
-							cs->hw.diva.hscx =
-								card->para[1] + DIVA_HSCX_DATA;
-							cs->hw.diva.isac_adr =
-								card->para[1] + DIVA_ISA_ISAC_ADR;
-							cs->hw.diva.hscx_adr =
-								card->para[1] + DIVA_HSCX_ADR;
-						}
-						goto ready;
+						return 1;
 					} else {
 						printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
 						return(0);
@@ -652,111 +767,29 @@
 				printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
 			}
 		}
+	}
 #endif
 #if CONFIG_PCI
-		cs->subtyp = 0;
-		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
-			if (pci_enable_device(dev_diva))
-				return(0);
-			cs->subtyp = DIVA_PCI;
-			cs->irq = dev_diva->irq;
-			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
-		} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
-			if (pci_enable_device(dev_diva_u))
-				return(0);
-			cs->subtyp = DIVA_PCI;
-			cs->irq = dev_diva_u->irq;
-			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
-		} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
-			if (pci_enable_device(dev_diva201))
-				return(0);
-			cs->subtyp = DIVA_IPAC_PCI;
-			cs->irq = dev_diva201->irq;
-			cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva");
-			cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva");
-		} else {
-			printk(KERN_WARNING "Diva: No PCI card found\n");
-			return(0);
-		}
-
-		if (!cs->irq) {
-			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
-			goto err;
-		}
-
-		if (!cs->hw.diva.cfg_reg) {
-			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
-			goto err;
-		}
-		cs->irq_flags |= SA_SHIRQ;
-#endif /* CONFIG_PCI */
-		if ((cs->subtyp == DIVA_IPAC_PCI) ||
-		    (cs->subtyp == DIVA_IPACX_PCI)   ) {
-			cs->hw.diva.ctrl = 0;
-			cs->hw.diva.isac = 0;
-			cs->hw.diva.hscx = 0;
-			cs->hw.diva.isac_adr = 0;
-			cs->hw.diva.hscx_adr = 0;
-			bytecnt = 0;
-		} else {
-			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
-			cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
-			cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
-			cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
-			cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
-			bytecnt = 32;
-		}
-	}
-ready:
-	printk(KERN_INFO
-		"Diva: %s card configured at %#lx IRQ %d\n",
-		(cs->subtyp == DIVA_PCI) ? "PCI" :
-		(cs->subtyp == DIVA_ISA) ? "ISA" : 
-		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
-		(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
-		cs->hw.diva.cfg_reg, cs->irq);
-	if ((cs->subtyp == DIVA_IPAC_PCI)  || 
-	    (cs->subtyp == DIVA_IPACX_PCI) || 
-	    (cs->subtyp == DIVA_PCI)         )
-		printk(KERN_INFO "Diva: %s space at %#lx\n",
-			(cs->subtyp == DIVA_PCI) ? "PCI" :
-			(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
-			cs->hw.diva.pci_cfg);
-	if ((cs->subtyp != DIVA_IPAC_PCI) &&
-	    (cs->subtyp != DIVA_IPACX_PCI)   ) {
-		if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn"))
+	if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
+					PCI_DEVICE_ID_EICON_DIVA20,
+					dev_diva))) {
+		if (diva_pci_probe(card->cs, dev_diva))
 			return 0;
+		return 1;
+	} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
+						 PCI_DEVICE_ID_EICON_DIVA20_U,
+						 dev_diva_u))) {
+		if (diva_pci_probe(card->cs, dev_diva_u))
+			return 0;
+		return 1;
+	} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
+						  PCI_DEVICE_ID_EICON_DIVA201,
+						  dev_diva201))) {
+		if (diva_ipac_pci_probe(card->cs, dev_diva201))
+			return 0;
+		return 1;
 	}
-	if (cs->subtyp == DIVA_IPAC_ISA) {
-		diva_ipac_isa_reset(cs);
-		cs->card_ops = &diva_ipac_isa_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else if (cs->subtyp == DIVA_IPAC_PCI) {
-		diva_ipac_pci_reset(cs);
-		cs->card_ops = &diva_ipac_pci_ops;
-		if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
-			goto err;
-	} else if (cs->subtyp == DIVA_IPACX_PCI) {
-		diva_ipacx_pci_reset(cs);
-		cs->card_ops = &diva_ipacx_pci_ops;
-		if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
-			goto err;
-	} else { /* DIVA 2.0 */
-		diva_reset(cs);
-		cs->hw.diva.tl.function = (void *) diva_led_handler;
-		cs->hw.diva.tl.data = (long) cs;
-		init_timer(&cs->hw.diva.tl);
-		cs->card_ops = &diva_ops;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	return 1;
- err:
-	diva_release(cs);
+	printk(KERN_WARNING "Diva: No PCI card found\n");
+#endif /* CONFIG_PCI */
 	return 0;
-
 }
diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
--- a/drivers/isdn/hisax/elsa.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/elsa.c	Thu Mar  6 22:52:04 2003
@@ -690,7 +690,47 @@
 	.irq_func    = elsa_interrupt_ipac,
 };
 
-static unsigned char
+static void __init
+elsa_arcofi_init(struct IsdnCardState *cs)
+{
+#if ARCOFI_USE
+	init_arcofi(cs);
+#endif
+}
+
+static void __init
+elsa_timer_init(struct IsdnCardState *cs)
+{
+	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
+	cs->hw.elsa.tl.data = (long) cs;
+	init_timer(&cs->hw.elsa.tl);
+}
+
+static int __init
+elsa_timer_test(struct IsdnCardState *cs)
+{
+	/* test timer */
+	byteout(cs->hw.elsa.trig, 0xff);
+	byteout(cs->hw.elsa.timer, 0);
+	if (!TimerRun(cs)) {
+		byteout(cs->hw.elsa.timer, 0);	/* second attempt */
+		if (!TimerRun(cs)) {
+			printk(KERN_WARNING "Elsa: timer does not start\n");
+			goto err;
+		}
+	}
+	HZDELAY(10 * HZ / 1000); /* wait >=10 ms */
+	if (TimerRun(cs)) {
+		printk(KERN_WARNING "Elsa: timer does not run\n");
+		goto err;
+	}
+	printk(KERN_INFO "Elsa: timer OK; resetting card\n");
+	return 0;
+ err:
+	return -EBUSY;
+}
+
+static unsigned char __init
 probe_elsa_adr(unsigned int adr, int typ)
 {
 	int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0,
@@ -699,15 +739,13 @@
 	/* In case of the elsa pcmcia card, this region is in use,
 	   reserved for us by the card manager. So we do not check it
 	   here, it would fail. */
-	if (typ != ISDN_CTYPE_ELSA_PCMCIA && check_region(adr, 8)) {
-		printk(KERN_WARNING
-		       "Elsa: Probing Port 0x%x: already in use\n",
-		       adr);
-		return (0);
+	if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) {
+		printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n",  adr);
+		return 0;
 	}
 	for (i = 0; i < 16; i++) {
-		in1 = inb(adr + ELSA_CONFIG);	/* 'toggelt' bei */
-		in2 = inb(adr + ELSA_CONFIG);	/* jedem Zugriff */
+		in1 = inb(adr + ELSA_CONFIG);	/* 'toggels' at */
+		in2 = inb(adr + ELSA_CONFIG);	/* each access  */
 		p16_1 += 0x04 & in1;
 		p16_2 += 0x04 & in2;
 		p8_1 += 0x02 & in1;
@@ -717,6 +755,7 @@
 		pfp_1 += 0x40 & in1;
 		pfp_2 += 0x40 & in2;
 	}
+	release_region(adr, 8);
 	printk(KERN_INFO "Elsa: Probing IO 0x%x", adr);
 	if (65 == ++p16_1 * ++p16_2) {
 		printk(" PCC-16/PCF found\n");
@@ -736,18 +775,227 @@
 	}
 }
 
-static unsigned int
-probe_elsa(struct IsdnCardState *cs)
+static int __init
+elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	int i;
-	unsigned int CARD_portlist[] =
-	{0x160, 0x170, 0x260, 0x360, 0};
-
-	for (i = 0; CARD_portlist[i]; i++) {
-		if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ)))
+	u8 val;
+	int i, bytecnt = 8;
+	unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0};
+
+	cs->hw.elsa.base = card->para[0];
+	printk(KERN_INFO "Elsa: Microlink IO probing\n");
+	if (cs->hw.elsa.base) {
+		cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ);
+		if (!cs->subtyp) {
+			printk(KERN_WARNING "Elsa: no Microlink at %#lx\n",
+			       cs->hw.elsa.base);
+			goto err;
+		}
+	} else {
+		for (i = 0; CARD_portlist[i]; i++) {
+			cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ);
+			if (cs->subtyp)
+				cs->hw.elsa.base = CARD_portlist[i];
 			break;
+		}
+	}
+	if (!cs->hw.elsa.base)
+		goto err;
+		
+	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
+	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
+	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
+	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
+	cs->hw.elsa.itac  = cs->hw.elsa.base + ELSA_ITAC;
+	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
+	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+	val = bytein(cs->hw.elsa.cfg);
+	if (cs->subtyp == ELSA_PC) {
+		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
+	} else if (cs->subtyp == ELSA_PCC8) {
+		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
+	} else {
+		const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
 	}
-	return (CARD_portlist[i]);
+	val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
+	if (val < 3)
+		val |= 8;
+	val += 'A' - 3;
+	if (val == 'B' || val == 'C')
+		val ^= 1;
+	if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
+		val = 'C';
+	printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq);
+	val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
+	if (val) {
+		printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n");
+		cs->hw.elsa.status |= ELSA_BAD_PWR;
+	}
+	switch (cs->subtyp) {
+	case ELSA_PCFPRO: bytecnt = 16;	break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	if (elsa_timer_test(cs))
+		goto err;
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	if (cs->subtyp == ELSA_PC) {
+		val = readitac(cs, ITAC_SYS);
+		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
+		writeitac(cs, ITAC_ISEN, 0);
+		writeitac(cs, ITAC_RFIE, 0);
+		writeitac(cs, ITAC_XFIE, 0);
+		writeitac(cs, ITAC_SCIE, 0);
+		writeitac(cs, ITAC_STIE, 0);
+	}
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int bytecnt = 8;
+
+	cs->irq           = card->para[0];
+	cs->hw.elsa.base  = card->para[1];
+	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
+	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
+	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
+	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
+	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
+	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
+	switch (cs->subtyp) {
+	case ELSA_QS3000: bytecnt = 16;	break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	if (elsa_timer_test(cs))
+		goto err;
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = ELSA_QS1000;
+	return elsa_qs_probe(cs, card);
+}
+
+static int __init
+elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = ELSA_QS3000;
+	return elsa_qs_probe(cs, card);
+}
+
+static int __init
+elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->irq = card->para[0];
+	cs->hw.elsa.base = card->para[1];
+	cs->hw.elsa.ale = cs->hw.elsa.base + 0;
+	val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
+	if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
+		cs->subtyp = ELSA_PCMCIA_IPAC;
+		cs->hw.elsa.isac = cs->hw.elsa.base + 2;
+	} else {
+		cs->subtyp = ELSA_PCMCIA;
+		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
+		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
+		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+	}
+	cs->hw.elsa.timer = 0;
+	cs->hw.elsa.trig = 0;
+	cs->hw.elsa.ctrl = 0;
+	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
+	elsa_arcofi_init(cs);
+	elsa_reset(cs);
+	if (cs->subtyp == ELSA_PCMCIA_IPAC) {
+		cs->card_ops = &elsa_ipac_ops;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+	} else {
+		cs->card_ops = &elsa_ops;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
+	}
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev,
+		  int subtyp)
+{
+	int bytecnt = 2;
+	u8 pci_rev;
+
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = subtyp;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.elsa.cfg = pci_resource_start(pdev, 1);
+	cs->hw.elsa.base = pci_resource_start(pdev, 3);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
+	if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
+		printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
+		__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
+	}
+	cs->hw.elsa.ale  = cs->hw.elsa.base;
+	cs->hw.elsa.isac = cs->hw.elsa.base +1;
+	cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
+	printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg,
+	       cs->irq);
+	switch (cs->subtyp) {
+	case ELSA_QS3000PCI: bytecnt = 16; break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ipac_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
 }
 
 static 	struct pci_dev *dev_qs1000 __devinitdata = NULL;
@@ -771,83 +1019,21 @@
 int __devinit
 setup_elsa(struct IsdnCard *card)
 {
-	int bytecnt;
-	u8 val, pci_rev;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Elsa_revision);
 	printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
-	cs->hw.elsa.ctrl_reg = 0;
-	cs->hw.elsa.status = 0;
-	cs->hw.elsa.MFlag = 0;
-	cs->subtyp = 0;
-	if (cs->typ == ISDN_CTYPE_ELSA) {
-		cs->hw.elsa.base = card->para[0];
-		printk(KERN_INFO "Elsa: Microlink IO probing\n");
-		if (cs->hw.elsa.base) {
-			if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
-							  cs->typ))) {
-				printk(KERN_WARNING
-				       "Elsa: no Elsa Microlink at %#lx\n",
-				       cs->hw.elsa.base);
-				return (0);
-			}
-		} else
-			cs->hw.elsa.base = probe_elsa(cs);
-		if (cs->hw.elsa.base) {
-			cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-			cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-			cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-			cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-			cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-			val = bytein(cs->hw.elsa.cfg);
-			if (cs->subtyp == ELSA_PC) {
-				const u8 CARD_IrqTab[8] =
-				{7, 3, 5, 9, 0, 0, 0, 0};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
-			} else if (cs->subtyp == ELSA_PCC8) {
-				const u8 CARD_IrqTab[8] =
-				{7, 3, 5, 9, 0, 0, 0, 0};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
-			} else {
-				const u8 CARD_IrqTab[8] =
-				{15, 10, 15, 3, 11, 5, 11, 9};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
-			}
-			val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
-			if (val < 3)
-				val |= 8;
-			val += 'A' - 3;
-			if (val == 'B' || val == 'C')
-				val ^= 1;
-			if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
-				val = 'C';
-			printk(KERN_INFO
-			       "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
-			       Elsa_Types[cs->subtyp],
-			       cs->hw.elsa.base,
-			       val, cs->irq);
-			val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
-			if (val) {
-				printk(KERN_WARNING
-				   "Elsa: Microlink S0 bus power bad\n");
-				cs->hw.elsa.status |= ELSA_BAD_PWR;
-			}
-		} else {
-			printk(KERN_WARNING
-			       "No Elsa Microlink found\n");
-			return (0);
-		}
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
+
+	if (card->typ == ISDN_CTYPE_ELSA) {
+		if (elsa_probe(card->cs, card))
+			return 0;
+		return 1;
+	} else if (card->typ == ISDN_CTYPE_ELSA_PNP) {
 #ifdef __ISAPNP__
 		if (!card->para[1] && isapnp_present()) {
 			struct pnp_card *pb;
 			struct pnp_dev *pd;
-
+			
 			while(pdev->card_vendor) {
 				if ((pb = pnp_find_card(pdev->card_vendor,
 							pdev->card_device,
@@ -878,10 +1064,15 @@
 						}
 						card->para[1] = pnp_port_start(pd, 0);
 						card->para[0] = pnp_irq(pd, 0);
-						if (pdev->function == ISAPNP_FUNCTION(0x133))
-							cs->subtyp = ELSA_QS1000;
-						else
-							cs->subtyp = ELSA_QS3000;
+						if (pdev->function == ISAPNP_FUNCTION(0x133)) {
+							if (elsa_qs1000_probe(card->cs, card))
+								return 0;
+							return 1;
+						} else {
+							if (elsa_qs3000_probe(card->cs, card))
+								return 0;
+							return 1;
+						}
 						break;
 					} else {
 						printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
@@ -897,184 +1088,33 @@
 			}
 		}
 #endif
-		if (card->para[1] && card->para[0]) { 
-			cs->hw.elsa.base = card->para[1];
-			cs->irq = card->para[0];
-			if (!cs->subtyp)
-				cs->subtyp = ELSA_QS1000;
-		} else {
-			printk(KERN_ERR "Elsa PnP: no parameter\n");
-		}
-		cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-		cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-		cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-		cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->irq);
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
-		cs->hw.elsa.base = card->para[1];
-		cs->irq = card->para[0];
-		cs->hw.elsa.ale = cs->hw.elsa.base + 0;
-		val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
-		if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
-			cs->subtyp = ELSA_PCMCIA_IPAC;
-			cs->hw.elsa.isac = cs->hw.elsa.base + 2;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
-		} else {
-			cs->subtyp = ELSA_PCMCIA;
-			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
-			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-		}
-		cs->hw.elsa.timer = 0;
-		cs->hw.elsa.trig = 0;
-		cs->hw.elsa.ctrl = 0;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->irq);
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
+		if (elsa_qs1000_probe(card->cs, card))
+			return 0;
+		return 1;
+
+	} else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) {
+		if (elsa_pcmcia_probe(card->cs, card))
+			return 0;
+		return 1;
+	} else if (card->typ == ISDN_CTYPE_ELSA_PCI) {
 #if CONFIG_PCI
-		cs->subtyp = 0;
 		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
-			if (pci_enable_device(dev_qs1000))
-				return(0);
-			cs->subtyp = ELSA_QS1000PCI;
-			cs->irq = dev_qs1000->irq;
-			cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
-			cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
-			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
+			if (elsa_qs_pci_probe(card->cs, dev_qs1000,
+					      ELSA_QS1000PCI))
+				return 0;
+			return 1;
 		} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
-			if (pci_enable_device(dev_qs3000))
-				return(0);
-			cs->subtyp = ELSA_QS3000PCI;
-			cs->irq = dev_qs3000->irq;
-			cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
-			cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
-			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
+			if (elsa_qs_pci_probe(card->cs, dev_qs3000,
+					      ELSA_QS3000PCI))
+				return 0;
+			return 1;
 		} else {
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
-			return(0);
+			return 0;
 		}
-		if (!cs->irq) {
-			printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
-			return(0);
-		}
-
-		if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
-			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
-			return(0);
-		}
-		if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
-			printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
-			set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-		}
-		cs->hw.elsa.ale  = cs->hw.elsa.base;
-		cs->hw.elsa.isac = cs->hw.elsa.base +1;
-		cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
-		cs->hw.elsa.timer = 0;
-		cs->hw.elsa.trig  = 0;
-		cs->irq_flags |= SA_SHIRQ;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx/0x%x IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->hw.elsa.cfg,
-		       cs->irq);
 #endif /* CONFIG_PCI */
-	} else 
-		return (0);
-
-	switch (cs->subtyp) {
-		case ELSA_PC:
-		case ELSA_PCC8:
-		case ELSA_PCC16:
-		case ELSA_QS1000:
-		case ELSA_PCMCIA:
-		case ELSA_PCMCIA_IPAC:
-			bytecnt = 8;
-			break;
-		case ELSA_PCFPRO:
-		case ELSA_PCF:
-		case ELSA_QS3000:
-		case ELSA_QS3000PCI:
-			bytecnt = 16;
-			break;
-		case ELSA_QS1000PCI:
-			bytecnt = 2;
-			break;
-		default:
-			printk(KERN_WARNING
-			       "Unknown ELSA subtype %d\n", cs->subtyp);
-			return (0);
-	}
-	/* In case of the elsa pcmcia card, this region is in use,
-	   reserved for us by the card manager. So we do not check it
-	   here, it would fail. */
-	if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA)
-		if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
-			goto err;
-	
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI))
-		if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
-			goto err;
-
-#if ARCOFI_USE
-	init_arcofi(cs);
-#endif
-
-	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
-	cs->hw.elsa.tl.data = (long) cs;
-	init_timer(&cs->hw.elsa.tl);
-	/* Teste Timer */
-	if (cs->hw.elsa.timer) {
-		byteout(cs->hw.elsa.trig, 0xff);
-		byteout(cs->hw.elsa.timer, 0);
-		if (!TimerRun(cs)) {
-			byteout(cs->hw.elsa.timer, 0);	/* 2. Versuch */
-			if (!TimerRun(cs)) {
-				printk(KERN_WARNING
-				       "Elsa: timer do not start\n");
-				goto err;
-			}
-		}
-		HZDELAY(1);	/* wait >=10 ms */
-		if (TimerRun(cs)) {
-			printk(KERN_WARNING "Elsa: timer do not run down\n");
-			goto err;
-		}
-		printk(KERN_INFO "Elsa: timer OK; resetting card\n");
-	}
-	elsa_reset(cs);
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
-		cs->card_ops = &elsa_ipac_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->card_ops = &elsa_ops;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
 	}
-	if (cs->subtyp == ELSA_PC) {
-		val = readitac(cs, ITAC_SYS);
-		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
-		writeitac(cs, ITAC_ISEN, 0);
-		writeitac(cs, ITAC_RFIE, 0);
-		writeitac(cs, ITAC_XFIE, 0);
-		writeitac(cs, ITAC_SCIE, 0);
-		writeitac(cs, ITAC_STIE, 0);
-	}
-	return 1;
- err:
-	elsa_release(cs);
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
--- a/drivers/isdn/hisax/enternow_pci.c	Mon Feb 24 10:29:08 2003
+++ b/drivers/isdn/hisax/enternow_pci.c	Thu Mar  6 22:52:04 2003
@@ -263,13 +263,65 @@
 	.irq_func    = enpci_interrupt,
 };
 
+static int __init
+enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
+		goto err;
+
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
+
+	/* Reset an */
+	cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
+	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	/* 50 ms Pause */
+	schedule_timeout((50*HZ)/1000);
+	
+	cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
+	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0x00; // war 0xc0
+	cs->hw.njet.dmactrl = 0;
+	
+	OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
+	OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
+	OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
+	
+	printk(KERN_INFO
+	       "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
+	       cs->hw.njet.base, cs->irq);
+	reset_enpci(cs);
+	cs->hw.njet.last_is0 = 0;
+	cs->hw.njet.bc_activate = enpci_bc_activate;
+	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
+	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
+
+	cs->card_ops = &enpci_ops;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 /* called by config.c */
 int __init
 setup_enternow_pci(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
@@ -278,72 +330,22 @@
         strcpy(tmp, enternow_pci_rev);
 	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-                        /* checks Sub-Vendor ID because system crashes with Traverse-Card */
-			if ((dev_netjet->subsystem_vendor != 0x55) ||
-				(dev_netjet->subsystem_device != 0x02)) {
-				printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
-                                printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
-                                return(0);
-                        }
-		} else {
-                        printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
-			return(0);
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		if (dev_netjet->subsystem_vendor != 0x55 ||
+		    dev_netjet->subsystem_device != 0x02) {
+			printk(KERN_WARNING "enter:now: You tried to load "
+			       "this driver with an incompatible "
+			       "TigerJet-card\n");
+			printk(KERN_WARNING "Use type=20 for Traverse "
+			       "NetJet PCI Card.\n");
+			return 0;
 		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
-
-		/* Reset an */
-		cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		/* 50 ms Pause */
-		schedule_timeout((50*HZ)/1000);
-
-		cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0x00; // war 0xc0
-		cs->hw.njet.dmactrl = 0;
-
-		OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-			   break;
-	}
-	printk(KERN_INFO
-		"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
+		if (enpci_probe(card->cs, dev_netjet))
+			return 1;
 		return 0;
-	reset_enpci(cs);
-	cs->hw.njet.last_is0 = 0;
-	cs->hw.njet.bc_activate = enpci_bc_activate;
-	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
-	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
-
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &enpci_ops;
-
-        return 1;
+	}
+	printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
--- a/drivers/isdn/hisax/gazel.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/gazel.c	Thu Mar  6 22:52:04 2003
@@ -294,60 +294,6 @@
 	inithscxisac(cs);
 }
 
-static int
-r647_reserve_regions(struct IsdnCardState *cs)
-{
-	int i, base = cs->hw.gazel.hscx[0];
-
-	for (i = 0; i < 0xc000; i += 0x1000) {
-		if (!request_io(&cs->rs, i + base, 16, "gazel"))
-			goto err;
-	}
-	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r685_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r742_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r753_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
 static struct card_ops r647_ops = {
 	.init     = gazel_init,
 	.reset    = r647_reset,
@@ -377,194 +323,213 @@
 };
 
 static int __init
-setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
+gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
-	// we got an irq parameter, assume it is an ISA card
-	// R742 decodes address even in not started...
-	// R647 returns FF if not present or not started
-	// eventually needs improvment
-	cs->hw.gazel.ipac = card->para[1];
-	if (ipac_read(cs, IPAC_ID) == 1)
-		cs->subtyp = R742;
-	else
-		cs->subtyp = R647;
+	int i, base;
 
+	cs->subtyp = R647;
+	cs->irq = card->para[0];
 	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
+
+	printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
+	cs->dc.isac.adf2 = 0x87;
+	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+	printk(KERN_INFO
+	       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
 	cs->hw.gazel.isac = card->para[1] + 0x8000;
 	cs->hw.gazel.hscx[0] = card->para[1];
 	cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
-	cs->irq = card->para[0];
 	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
 
-	switch (cs->subtyp) {
-	case R647:
-		printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
-		cs->dc.isac.adf2 = 0x87;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-		printk(KERN_INFO
-		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-		
-		return r647_reserve_regions(cs);
-	case R742:
-		printk(KERN_INFO "Gazel: Card ISA R742 found\n");
-		printk(KERN_INFO
-		       "Gazel: config irq:%d ipac:0x%X\n",
-		       cs->irq, cs->hw.gazel.ipac);
-		return r742_reserve_regions(cs);
+	base = cs->hw.gazel.hscx[0];
+	for (i = 0; i < 0xc000; i += 0x1000) {
+		if (!request_io(&cs->rs, base + i, 16, "gazel"))
+			goto err;
 	}
+	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
+		goto err;
+
+	cs->card_ops = &r647_ops;
+	if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
 }
 
-static struct pci_dev *dev_tel __initdata = NULL;
-
 static int __init
-setup_gazelpci(struct IsdnCardState *cs)
+gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
-	u8 pci_irq = 0, found;
-	u_int nbseek, seekcard;
-	u8 pci_rev;
+	cs->subtyp = R742;
+	cs->irq = card->para[0];
+	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
 
-	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
+	printk(KERN_INFO "Gazel: Card ISA R742 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n",
+	       cs->irq, cs->hw.gazel.ipac);
 
-	found = 0;
-	if (!pci_present()) {
-		printk(KERN_WARNING "Gazel: No PCI bus present\n");
-		return 1;
-	}
-	seekcard = PCI_DEVICE_ID_PLX_R685;
-	for (nbseek = 0; nbseek < 3; nbseek++) {
-		if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) {
-			if (pci_enable_device(dev_tel))
-				return 1;
-			pci_irq = dev_tel->irq;
-			pci_ioaddr0 = pci_resource_start(dev_tel, 1);
-			pci_ioaddr1 = pci_resource_start(dev_tel, 2);
-			found = 1;
-		}
-		if (found)
-			break;
-		else {
-			switch (seekcard) {
-			case PCI_DEVICE_ID_PLX_R685:
-				seekcard = PCI_DEVICE_ID_PLX_R753;
-				break;
-			case PCI_DEVICE_ID_PLX_R753:
-				seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
-				break;
-			}
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "Gazel: No PCI card found\n");
-		return -ENODEV;
-	}
-	if (!pci_irq) {
-		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
-		return -ENODEV;
-	}
-	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
-	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
 
-	pci_ioaddr1 &= 0xfffe;
-	cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
-	cs->hw.gazel.ipac = pci_ioaddr1;
-	cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
-	cs->hw.gazel.hscx[0] = pci_ioaddr1;
-	cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
-	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
+	cs->card_ops = &r742_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp               = R685;
+	cs->irq                  = pdev->irq;
+	cs->irq_flags           |= SA_SHIRQ;
+	cs->hw.gazel.cfg_reg     = pci_resource_start(pdev, 1);
+	cs->hw.gazel.isac        = pci_resource_start(pdev, 2) + 0x80;
+	cs->hw.gazel.hscx[0]     = pci_resource_start(pdev, 2);
+	cs->hw.gazel.hscx[1]     = pci_resource_start(pdev, 2) + 0x40;
+	cs->hw.gazel.isacfifo    = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
-	cs->irq = pci_irq;
-	cs->irq_flags |= SA_SHIRQ;
+	cs->dc.isac.adf2 = 0x87;
 
-	switch (seekcard) {
-	case PCI_DEVICE_ID_PLX_R685:
-		printk(KERN_INFO "Gazel: Card PCI R685 found\n");
-		cs->subtyp = R685;
-		cs->dc.isac.adf2 = 0x87;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-		printk(KERN_INFO
-		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-		return r685_reserve_regions(cs);
-	case PCI_DEVICE_ID_PLX_R753:
-	case PCI_DEVICE_ID_PLX_DJINN_ITOO:
-		printk(KERN_INFO "Gazel: Card PCI R753 found\n");
-		cs->subtyp = R753;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
-		/* 
-		 * Erratum for PLX9050, revision 1:
-		 * If bit 7 of BAR 0/1 is set, local config registers
-		 * can not be read (write is okay)
-		 */
-		if (cs->hw.gazel.cfg_reg & 0x80) {
-			pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
-			if (pci_rev == 1) {
-				printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n");
-				set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-			}
+	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
+
+	printk(KERN_INFO "Gazel: Card PCI R685 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+	printk(KERN_INFO "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
+	cs->card_ops  = &r685_ops;
+	if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	u8 pci_rev;
+
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp           = R753;
+	cs->irq              = pdev->irq;
+	cs->irq_flags       |= SA_SHIRQ;
+	cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
+	cs->hw.gazel.ipac    = pci_resource_start(pdev, 2);
+
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
+
+	printk(KERN_INFO "Gazel: Card PCI R753 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+	/* 
+	 * Erratum for PLX9050, revision 1:
+	 * If bit 7 of BAR 0/1 is set, local config registers
+	 * can not be read (write is okay)
+	 */
+	if (cs->hw.gazel.cfg_reg & 0x80) {
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
+		if (pci_rev == 1) {
+			printk(KERN_INFO "Gazel: PLX9050 rev1 workaround "
+			       "activated\n");
+			__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
 		}
-		return r753_reserve_regions(cs);
 	}
+	cs->card_ops = &r753_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
 }
 
+static struct pci_dev *dev_tel __initdata = NULL;
+static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685;
+
 int __init
 setup_gazel(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, gazel_revision);
 	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
 
 	if (card->para[0]) {
-		if (setup_gazelisa(card, cs))
-			return (0);
-	} else {
-		if (setup_gazelpci(cs))
-			return (0);
+		printk(KERN_INFO "Gazel: ISA card automatic recognition\n");
+		// we got an irq parameter, assume it is an ISA card
+		// R742 decodes address even in not started...
+		// R647 returns FF if not present or not started
+		// eventually needs improvment
+		card->cs->hw.gazel.ipac = card->para[1];
+		if (ipac_read(card->cs, IPAC_ID) == 1) {
+			if (gazel742_probe(card->cs, card))
+				return 0;
+		} else {
+			if (gazel647_probe(card->cs, card))
+				return 0;
+		}
+		return 1;
 	}
 
-	switch (cs->subtyp) {
-	case R647:
-	case R685:
-		if (cs->subtyp == R647) {
-			cs->card_ops  = &r647_ops;
-			if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
-				goto err;
-		} else {
-			cs->card_ops  = &r685_ops;
-			if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
-				goto err;
+	for (;;) {
+		dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel);
+		if (dev_tel) {
+			switch (dev_id) {
+			case PCI_DEVICE_ID_PLX_R685:
+				if (gazel685_probe(card->cs, dev_tel))
+					return 0;
+				return 1;
+			case PCI_DEVICE_ID_PLX_R753:
+			case PCI_DEVICE_ID_PLX_DJINN_ITOO:
+				if (gazel753_probe(card->cs, dev_tel))
+					return 0;
+				return 1;
+			}
 		}
-		cs->card_ops->reset(cs);
-		break;
-	case R742:
-	case R753:
-		if (cs->subtyp == R742) {
-			cs->card_ops = &r742_ops;
-		} else {
-			cs->card_ops = &r753_ops;
+		switch (dev_id) {
+		case PCI_DEVICE_ID_PLX_R685:
+			dev_id = PCI_DEVICE_ID_PLX_R753;
+		case PCI_DEVICE_ID_PLX_R753:
+			dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO;
+		default:
+			break;
 		}
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-		cs->card_ops->reset(cs);
-		break;
 	}
-	return 1;
- err:
-	hisax_release_resources(cs);
+	printk(KERN_WARNING "Gazel: No PCI card found\n");
 	return 0;
 }
+
+
diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
--- a/drivers/isdn/hisax/hfc_pci.c	Sun Jan 12 16:05:35 2003
+++ b/drivers/isdn/hisax/hfc_pci.c	Thu Mar  6 22:52:04 2003
@@ -1382,72 +1382,41 @@
 };
 
 
-/* this variable is used as card index when more than one cards are present */
-static struct pci_dev *dev_hfcpci __initdata = NULL;
-
-int __init
-setup_hfcpci(struct IsdnCard *card)
+static int __init
+niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-	int i;
-	struct pci_dev *tmp_hfcpci = NULL;
+	int rc;
 
-	strcpy(tmp, hfcpci_revision);
-	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	cs->hw.hfcpci.int_s1 = 0;
-	cs->dc.hfcpci.ph_state = 0;
-	cs->hw.hfcpci.fifo = 255;
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
 
-	i = 0;
-	while (id_list[i].vendor_id) {
-		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
-					     id_list[i].device_id,
-					     dev_hfcpci);
-		i++;
-		if (tmp_hfcpci) {
-			if (pci_enable_device(tmp_hfcpci))
-				continue;
-			pci_set_master(tmp_hfcpci);
-			if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
-				continue;
-			else
-				break;
-		}
-	}
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.hfcpci.pdev = pdev;
+
+	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, 
+					    pci_resource_start(pdev, 1), 128,
+					    "hfc_pci");
+	if (!cs->hw.hfcpci.pci_io)
+		goto err;
 	
-	if (tmp_hfcpci) {
-		i--;
-		dev_hfcpci = tmp_hfcpci;	/* old device */
-		cs->irq = dev_hfcpci->irq;
-		cs->hw.hfcpci.pdev = tmp_hfcpci;
-		if (!cs->irq) {
-			printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
-			return (0);
-		}
-		printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
-	} else {
-		printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
-		return (0);
-	}
 	/* Allocate memory for FIFOS */
-	cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma);
-	if (!cs->hw.hfcpci.fifos) {
-		printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
-		return 0;
-	}
+	rc = -ENOMEM;
+	cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, 
+						   &cs->hw.hfcpci.fifos_dma);
+	if (!cs->hw.hfcpci.fifos)
+		goto err;
+
 	pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
 			       (u_int)cs->hw.hfcpci.fifos_dma);
-	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci");
-	if (!cs->hw.hfcpci.pci_io)
-		goto err;
-	
-	printk(KERN_INFO
-	       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
-	       (u_int) cs->hw.hfcpci.pci_io,
-	       (u_int) cs->hw.hfcpci.fifos,
-	       (u_int) cs->hw.hfcpci.fifos_dma,
-	       cs->irq, HZ);
+	printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n",
+	       id_list[i].vendor_name, id_list[i].card_name);
+	printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n",
+	       (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos,
+	       (u_int) cs->hw.hfcpci.fifos_dma, cs->irq);
 	printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
 	cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
 	cs->hw.hfcpci.int_m1 = 0;
@@ -1456,17 +1425,46 @@
 	/* At this point the needed PCI config is done */
 	/* fifos are still not enabled */
 
-	cs->irq_flags |= SA_SHIRQ;
-
+	init_timer(&cs->hw.hfcpci.timer);
 	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
 	cs->hw.hfcpci.timer.data = (long) cs;
-	init_timer(&cs->hw.hfcpci.timer);
 
 	hfcpci_reset(cs);
 	cs->auxcmd = &hfcpci_auxcmd;
 	cs->card_ops = &hfcpci_ops;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+/* this variable is used as card index when more than one cards are present */
+static struct pci_dev *dev_hfcpci __initdata = NULL;
+
+int __init
+setup_hfcpci(struct IsdnCard *card)
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	int i;
+	struct pci_dev *tmp_hfcpci = NULL;
+
+	strcpy(tmp, hfcpci_revision);
+	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	cs->hw.hfcpci.int_s1 = 0;
+	cs->dc.hfcpci.ph_state = 0;
+	cs->hw.hfcpci.fifo = 255;
+
+	for (i = 0; id_list[i].vendor_id; i++) {
+		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+					     id_list[i].device_id,
+					     dev_hfcpci);
+		if (!tmp_hfcpci)
+			continue;
+
+		if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0)
+			return 0;
+		return 1;
+	}
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
--- a/drivers/isdn/hisax/hfc_sx.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/isdn/hisax/hfc_sx.c	Thu Mar  6 22:52:04 2003
@@ -1159,6 +1159,74 @@
 	.irq_func = hfcsx_interrupt,
 };
 
+static int __init
+hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	char c;
+
+	cs->irq = card->para[0];
+	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+
+	cs->hw.hfcsx.fifo = 255;
+	cs->hw.hfcsx.int_s1 = 0;
+	cs->dc.hfcsx.ph_state = 0;
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
+		goto err;
+
+	rc = -ENODEV;
+	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
+	byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
+	udelay(10);
+	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
+	switch (cs->hw.hfcsx.chip >> 4) {
+	case 1: 
+		c ='+';
+		break;
+	case 9: 
+		c ='P';
+		break;
+	default:
+		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
+		       cs->hw.hfcsx.chip >> 4);
+		goto err;
+	}  
+	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
+		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
+		       cs->irq & 0xF);
+		goto err;
+	}
+	rc = -ENOMEM;
+	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC);
+	if (!cs->hw.hfcsx.extra) {
+		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
+		goto err;
+	}
+	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n",
+	       c, (u_int) cs->hw.hfcsx.base, cs->irq);
+
+	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
+	cs->hw.hfcsx.int_m1 = 0;
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+
+	init_timer(&cs->hw.hfcsx.timer);
+	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
+	cs->hw.hfcsx.timer.data = (long) cs;
+	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
+	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */
+
+	hfcsx_reset(cs);
+	cs->auxcmd = &hfcsx_auxcmd;
+	cs->card_ops = &hfcsx_ops;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
@@ -1174,7 +1242,6 @@
 int __devinit
 setup_hfcsx(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcsx_revision);
@@ -1227,62 +1294,7 @@
 		}
 	}
 #endif
-	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
-	cs->irq = card->para[0];
-	cs->hw.hfcsx.int_s1 = 0;
-	cs->dc.hfcsx.ph_state = 0;
-	cs->hw.hfcsx.fifo = 255;
-
-	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
-		return 0;
-	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
-	byteout(cs->hw.hfcsx.base + 1,
-		((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
-	udelay(10);
-	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
-	switch (cs->hw.hfcsx.chip >> 4) {
-	case 1: 
-		tmp[0] ='+';
-		break;
-	case 9: 
-		tmp[0] ='P';
-		break;
-	default:
-		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
-		       cs->hw.hfcsx.chip >> 4);
-		hisax_release_resources(cs);
+	if (hfcsx_probe(card->cs, card) < 0)
 		return 0;
-	}  
-	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
-		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
-		       cs->irq & 0xF);
-		hisax_release_resources(cs);
-		return 0;
-	}  
-	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), 
-				     GFP_ATOMIC);
-	if (!cs->hw.hfcsx.extra) {
-		hisax_release_resources(cs);
-		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
-		return 0;
-	}
-	
-	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
-	       tmp[0], (u_int) cs->hw.hfcsx.base,
-	       cs->irq, HZ);
-	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
-	cs->hw.hfcsx.int_m1 = 0;
-	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
-
-	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
-	cs->hw.hfcsx.timer.data = (long) cs;
-	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
-	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
-	init_timer(&cs->hw.hfcsx.timer);
-
-	hfcsx_reset(cs);
-	cs->auxcmd = &hfcsx_auxcmd;
-	cs->card_ops = &hfcsx_ops;
 	return 1;
 }
diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
--- a/drivers/isdn/hisax/hfcscard.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/hfcscard.c	Thu Mar  6 22:52:04 2003
@@ -133,6 +133,50 @@
 	.irq_func = hfcs_interrupt,
 };
 
+static int __init
+hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.hfcD.addr = card->para[1];
+
+	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
+		goto err;
+
+	printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n",
+	       cs->hw.hfcD.addr, cs->irq);
+
+	cs->hw.hfcD.cip = 0;
+	cs->hw.hfcD.int_s1 = 0;
+	cs->hw.hfcD.send = NULL;
+	cs->bcs[0].hw.hfc.send = NULL;
+	cs->bcs[1].hw.hfc.send = NULL;
+	cs->hw.hfcD.dfifosize = 512;
+	cs->dc.hfcd.ph_state = 0;
+	cs->hw.hfcD.fifo = 255;
+
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		cs->hw.hfcD.bfifosize = 1024 + 512;
+		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x56, cs->hw.hfcD.addr | 1);
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		cs->hw.hfcD.bfifosize = 7*1024 + 512;
+		/* Acer P10 IO ADR is 0x300 */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x57, cs->hw.hfcD.addr | 1);
+	}
+	set_cs_func(cs);
+	init_timer(&cs->hw.hfcD.timer);
+	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
+	cs->hw.hfcD.timer.data = (long) cs;
+	hfcs_reset(cs);
+	cs->card_ops = &hfcs_ops;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
@@ -166,7 +210,6 @@
 int __init
 setup_hfcs(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcs_revision);
@@ -220,42 +263,8 @@
 		}
 	}
 #endif
-	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
-	cs->irq = card->para[0];
-	cs->hw.hfcD.cip = 0;
-	cs->hw.hfcD.int_s1 = 0;
-	cs->hw.hfcD.send = NULL;
-	cs->bcs[0].hw.hfc.send = NULL;
-	cs->bcs[1].hw.hfc.send = NULL;
-	cs->hw.hfcD.dfifosize = 512;
-	cs->dc.hfcd.ph_state = 0;
-	cs->hw.hfcD.fifo = 255;
-	if (cs->typ == ISDN_CTYPE_TELES3C) {
-		cs->hw.hfcD.bfifosize = 1024 + 512;
-	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
-		cs->hw.hfcD.bfifosize = 7*1024 + 512;
-	} else
-		return (0);
-	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
+	if (hfcs_probe(card->cs, card) < 0)
 		return 0;
-	printk(KERN_INFO
-	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
-	       cs->hw.hfcD.addr,
-	       cs->irq, HZ);
-	if (cs->typ == ISDN_CTYPE_TELES3C) {
-		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x56, cs->hw.hfcD.addr | 1);
-	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
-		/* Acer P10 IO ADR is 0x300 */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x57, cs->hw.hfcD.addr | 1);
-	}
-	set_cs_func(cs);
-	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
-	cs->hw.hfcD.timer.data = (long) cs;
-	init_timer(&cs->hw.hfcD.timer);
-	hfcs_reset(cs);
-	cs->card_ops = &hfcs_ops;
-	return (1);
+	return 1;
+	
 }
diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
--- a/drivers/isdn/hisax/hisax.h	Sun Jan 12 16:03:30 2003
+++ b/drivers/isdn/hisax/hisax.h	Thu Mar  6 23:20:18 2003
@@ -782,7 +782,6 @@
 
 struct gazel_hw {
 	unsigned int cfg_reg;
-	unsigned int pciaddr[2];
         signed   int ipac;
 	signed   int isac;
 	signed   int hscx[2];
@@ -1073,264 +1072,17 @@
 #define  ISDN_CTYPE_COUNT	41
 
 
-#ifdef ISDN_CHIP_ISAC
-#undef ISDN_CHIP_ISAC
-#endif
-
-#ifdef	CONFIG_HISAX_16_0
-#define  CARD_TELES0 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELES0  0
-#endif
-
-#ifdef	CONFIG_HISAX_16_3
-#define  CARD_TELES3 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELES3  0
-#endif
-
-#ifdef	CONFIG_HISAX_TELESPCI
-#define  CARD_TELESPCI 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELESPCI  0
-#endif
-
-#ifdef	CONFIG_HISAX_AVM_A1
-#define  CARD_AVM_A1 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_AVM_A1  0
-#endif
-
-#ifdef	CONFIG_HISAX_AVM_A1_PCMCIA
-#define  CARD_AVM_A1_PCMCIA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_AVM_A1_PCMCIA  0
-#endif
-
-#ifdef	CONFIG_HISAX_FRITZPCI
-#define  CARD_FRITZPCI 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_FRITZPCI  0
-#endif
-
-#ifdef	CONFIG_HISAX_ELSA
-#define  CARD_ELSA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_ELSA  0
-#endif
-
-#ifdef	CONFIG_HISAX_IX1MICROR2
-#define	CARD_IX1MICROR2 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_IX1MICROR2 0
-#endif
-
-#ifdef  CONFIG_HISAX_DIEHLDIVA
-#define CARD_DIEHLDIVA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_DIEHLDIVA 0
-#endif
-
-#ifdef  CONFIG_HISAX_ASUSCOM
-#define CARD_ASUSCOM 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_ASUSCOM 0
-#endif
-
-#ifdef  CONFIG_HISAX_TELEINT
-#define CARD_TELEINT 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_TELEINT 0
-#endif
-
-#ifdef  CONFIG_HISAX_SEDLBAUER
-#define CARD_SEDLBAUER 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SEDLBAUER 0
-#endif
-
-#ifdef  CONFIG_HISAX_SPORTSTER
-#define CARD_SPORTSTER 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SPORTSTER 0
-#endif
-
-#ifdef  CONFIG_HISAX_MIC
-#define CARD_MIC 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_MIC 0
-#endif
-
-#ifdef  CONFIG_HISAX_NETJET
-#define CARD_NETJET_S 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_NETJET_S 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFCS
-#define  CARD_HFCS 1
-#else
-#define  CARD_HFCS 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFC_PCI
-#define  CARD_HFC_PCI 1
-#else
-#define  CARD_HFC_PCI 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFC_SX
-#define  CARD_HFC_SX 1
-#else
-#define  CARD_HFC_SX 0
-#endif
-
-#ifdef  CONFIG_HISAX_AMD7930
-#define CARD_AMD7930 1
-#else
-#define CARD_AMD7930 0
-#endif
-
-#ifdef	CONFIG_HISAX_NICCY
-#define	CARD_NICCY 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_NICCY 0
-#endif
-
-#ifdef	CONFIG_HISAX_ISURF
-#define	CARD_ISURF 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_ISURF 0
-#endif
-
-#ifdef	CONFIG_HISAX_S0BOX
-#define	CARD_S0BOX 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_S0BOX 0
-#endif
-
-#ifdef	CONFIG_HISAX_HSTSAPHIR
-#define	CARD_HSTSAPHIR 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_HSTSAPHIR 0
-#endif
-
 #ifdef	CONFIG_HISAX_TESTEMU
-#define	CARD_TESTEMU 1
 #define ISDN_CTYPE_TESTEMU 99
 #undef ISDN_CTYPE_COUNT
 #define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
-#else
-#define CARD_TESTEMU 0
-#endif
-
-#ifdef	CONFIG_HISAX_BKM_A4T
-#define	CARD_BKM_A4T 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_BKM_A4T 0
-#endif
-
-#ifdef	CONFIG_HISAX_SCT_QUADRO
-#define	CARD_SCT_QUADRO 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SCT_QUADRO 0
-#endif
-
-#ifdef	CONFIG_HISAX_GAZEL
-#define  CARD_GAZEL 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_GAZEL  0
-#endif
-
-#ifdef	CONFIG_HISAX_W6692
-#define	CARD_W6692	1
-#ifndef	ISDN_CHIP_W6692
-#define	ISDN_CHIP_W6692	1
-#endif
-#else
-#define	CARD_W6692	0
 #endif
 
 #ifdef  CONFIG_HISAX_NETJET_U
-#define CARD_NETJET_U 1
-#ifndef ISDN_CHIP_ICC
-#define ISDN_CHIP_ICC 1
-#endif
 #ifndef HISAX_UINTERFACE
 #define HISAX_UINTERFACE 1
 #endif
 #else
-#define CARD_NETJET_U 0
-#endif
-
-#ifdef CONFIG_HISAX_ENTERNOW_PCI
-#define CARD_FN_ENTERNOW_PCI 1
 #endif
 
 #define TEI_PER_CARD 1
@@ -1402,7 +1154,7 @@
 int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u8 * p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u8 * p, int size);
diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.c b/drivers/isdn/hisax/hisax_fcclassic.c
--- a/drivers/isdn/hisax/hisax_fcclassic.c	Sat Jan  4 07:35:38 2003
+++ b/drivers/isdn/hisax/hisax_fcclassic.c	Sat Feb 22 08:50:25 2003
@@ -231,7 +231,7 @@
 	adapter->isac.write_isac      = &fcclassic_write_isac;
 	adapter->isac.read_isac_fifo  = &fcclassic_read_isac_fifo;
 	adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo;
-	isac_setup(&adapter->isac);
+	hisax_isac_setup(&adapter->isac);
 	for (i = 0; i < 2; i++) {
 		hscx_init(&adapter->hscx[i]);
 		adapter->hscx[i].priv            = adapter;
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	Wed Jan 15 08:22:25 2003
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	Sat Feb 22 10:05:19 2003
@@ -46,24 +46,22 @@
 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
 MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
 
-// FIXME temporary hack until I sort out the new PnP stuff
-#define __ISAPNP__
-
 static struct pci_device_id fcpci_ids[] __devinitdata = {
-	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1   , PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, (unsigned long) "Fritz!Card PCI" },
-	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, (unsigned long) "Fritz!Card PCI v2" },
-	{ }
+	{ .vendor      = PCI_VENDOR_ID_AVM,
+	  .device      = PCI_DEVICE_ID_AVM_A1,
+	  .subvendor   = PCI_ANY_ID,
+	  .subdevice   = PCI_ANY_ID,
+	  .driver_data = (unsigned long) "Fritz!Card PCI",
+	},
+	{ .vendor      = PCI_VENDOR_ID_AVM,
+	  .device      = PCI_DEVICE_ID_AVM_A1_V2,
+	  .subvendor   = PCI_ANY_ID,
+	  .subdevice   = PCI_ANY_ID,
+	  .driver_data = (unsigned long) "Fritz!Card PCI v2" },
+	{}
 };
-MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
-static struct pnp_card_device_id fcpnp_ids[] __devinitdata = {
-	{ .id = "AVM0900", 
-	  .driver_data = (unsigned long) "Fritz!Card PnP",
-	  .devs = { { "AVM0900" } } }
-};
-MODULE_DEVICE_TABLE(pnp_card, fcpnp_ids);
+MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
 static int protocol = 2;       /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
@@ -782,7 +780,7 @@
 	case AVM_FRITZ_PCI:
 	case AVM_FRITZ_PNP:
 		fcpci_init(adapter);
-		isac_setup(&adapter->isac);
+		hisax_isac_setup(&adapter->isac);
 		break;
 	}
 	val = adapter->read_hdlc_status(adapter, 0);
@@ -908,10 +906,10 @@
 	.id_table = fcpci_ids,
 };
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 
 static int __devinit fcpnp_probe(struct pnp_card *card,
-				 const struct pnp_card_device_id *card_id)
+				 const struct pnp_card_id *card_id)
 {
 	struct fritz_adapter *adapter;
 	struct pnp_dev *pnp_dev;
@@ -957,6 +955,14 @@
 	delete_adapter(adapter);
 }
 
+static struct pnp_card_id fcpnp_ids[] __devinitdata = {
+	{ .id          = "AVM0900", 
+	  .driver_data = (unsigned long) "Fritz!Card PnP",
+	  .devs        = { { "AVM0900" } },
+	},
+	{}
+};
+
 static struct pnpc_driver fcpnp_driver = {
 	.name     = "fcpnp",
 	.probe    = fcpnp_probe,
@@ -968,7 +974,7 @@
 
 static int __init hisax_fcpcipnp_init(void)
 {
-	int retval, pci_nr_found;
+	int retval = 0, pci_nr_found;
 
 	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
 
@@ -977,10 +983,8 @@
 		goto out;
 	pci_nr_found = retval;
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 	retval = pnpc_register_driver(&fcpnp_driver);
-#else
-	retval = 0;
 #endif
 	if (retval < 0)
 		goto out_unregister_pci;
@@ -988,14 +992,14 @@
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
 	if (pci_nr_found + retval == 0) {
 		retval = -ENODEV;
-		goto out_unregister_isapnp;
+		goto out_unregister_pnp;
 	}
 #endif
 	return 0;
 
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
- out_unregister_isapnp:
-#ifdef __ISAPNP__
+ out_unregister_pnp:
+#ifdef CONFIG_PNP_CARD
 	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 #endif
@@ -1007,7 +1011,7 @@
 
 static void __exit hisax_fcpcipnp_exit(void)
 {
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 	pci_unregister_driver(&fcpci_driver);
diff -Nru a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c
--- a/drivers/isdn/hisax/hisax_isac.c	Sat Jan  4 07:35:38 2003
+++ b/drivers/isdn/hisax/hisax_isac.c	Sat Feb 22 08:50:25 2003
@@ -770,7 +770,7 @@
 	FsmInitTimer(&isac->l1m, &isac->timer);
 }
 
-void isac_setup(struct isac *isac)
+void hisax_isac_setup(struct isac *isac)
 {
 	int val, eval;
 
@@ -890,7 +890,7 @@
 EXPORT_SYMBOL(isacsx_setup);
 EXPORT_SYMBOL(isacsx_irq);
 
-EXPORT_SYMBOL(isac_setup);
+EXPORT_SYMBOL(hisax_isac_setup);
 EXPORT_SYMBOL(isac_irq);
 
 module_init(hisax_isac_init);
diff -Nru a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h
--- a/drivers/isdn/hisax/hisax_isac.h	Sat Jan  4 07:35:38 2003
+++ b/drivers/isdn/hisax/hisax_isac.h	Sat Feb 22 08:50:25 2003
@@ -36,7 +36,7 @@
 void isac_init(struct isac *isac);
 void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
 
-void isac_setup(struct isac *isac);
+void hisax_isac_setup(struct isac *isac);
 void isac_irq(struct isac *isac);
 
 void isacsx_setup(struct isac *isac);
diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
--- a/drivers/isdn/hisax/isdnl1.c	Sat Jan 11 11:24:09 2003
+++ b/drivers/isdn/hisax/isdnl1.c	Sat Feb 22 09:10:42 2003
@@ -126,7 +126,7 @@
 };
 
 void
-debugl1(struct IsdnCardState *cs, char *fmt, ...)
+debugl1(struct IsdnCardState *cs, const char *fmt, ...)
 {
 	va_list args;
 	char tmp[8];
diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
--- a/drivers/isdn/hisax/isdnl1.h	Sat Jan 11 11:24:09 2003
+++ b/drivers/isdn/hisax/isdnl1.h	Sat Feb 22 09:10:42 2003
@@ -28,7 +28,7 @@
 #define B_LL_CONNECT	9
 #define B_LL_OK		10
 
-extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
+extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...);
 extern void DChannel_proc_xmt(struct IsdnCardState *cs);
 extern void DChannel_proc_rcv(struct IsdnCardState *cs);
 extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
--- a/drivers/isdn/hisax/isurf.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/isurf.c	Thu Mar  6 22:52:04 2003
@@ -187,95 +187,92 @@
 static struct pnp_card *pnp_surf __devinitdata = NULL;
 #endif
 
-int __init
-setup_isurf(struct IsdnCard *card)
+static int __init
+isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	unsigned long phymem;
-	char tmp[64];
 
-	strcpy(tmp, ISurf_revision);
-	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
-	
-	if (card->para[1] && card->para[2]) {
-		cs->hw.isurf.reset = card->para[1];
-		phymem = card->para[2];
-		cs->irq = card->para[0];
-	} else {
-#ifdef __ISAPNP__
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
+	phymem = card->para[2];
+	cs->hw.isurf.reset = card->para[1];
+	cs->irq = card->para[0];
 
-		if (isapnp_present()) {
-			cs->subtyp = 0;
-			if ((pb = pnp_find_card(
-				ISAPNP_VENDOR('S', 'I', 'E'),
-				ISAPNP_FUNCTION(0x0010), pnp_surf))) {
-				pnp_surf = pb;
-				pd = NULL;
-				if (!(pd = pnp_find_dev(pnp_surf,
-					ISAPNP_VENDOR('S', 'I', 'E'),
-					ISAPNP_FUNCTION(0x0010), pd))) {
-					printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
-					return (0);
-				}
-				if (pnp_device_attach(pd) < 0) {
-					printk(KERN_ERR "ISurfPnP: attach failed\n");
-					return 0;
-				}
-				if (pnp_activate_dev(pd) < 0) {
-					printk(KERN_ERR "ISurfPnP: activate failed\n");
-					pnp_device_detach(pd);
-					return 0;
-				}
-				if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
-					printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
-						pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
-					pnp_device_detach(pd);
-					return(0);
-				}
-				cs->hw.isurf.reset = pnp_port_start(pd, 0);
-				phymem = pnp_port_start(pd, 1);
-				cs->irq = pnp_irq(pd, 0);
-			} else {
-				printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
-				return(0);
-			}
-		} else {
-			printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
-			return(0);
-		}
-#else
-		printk(KERN_WARNING "HiSax: %s port/mem not set\n",
-			CardType[card->typ]);
-		return (0);
-#endif
-	}
 	if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn"))
 		goto err;
-	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem");
+
+	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE,
+					 "isurf iomem");
 	if (!cs->hw.isurf.isar)
 		goto err;
 
 	cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
-	printk(KERN_INFO
-	       "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
-	       cs->hw.isurf.reset,
-	       card->para[2],
-	       cs->irq);
+	printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
+	       cs->hw.isurf.reset, phymem, cs->irq);
 
 	cs->auxcmd = &isurf_auxcmd;
 	cs->card_ops = &isurf_ops;
 	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
 	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
 	reset_isurf(cs, ISURF_RESET);
-	test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+	__set_bit(HW_ISAR, &cs->HW_Flags);
 	isac_setup(cs, &isac_ops);
 	if (isar_setup(cs, &isar_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
 
+int __init
+setup_isurf(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, ISurf_revision);
+	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
+	
+#ifdef __ISAPNP__
+	if (!card->para[1] || !card->para[2]) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+	
+		cs->subtyp = 0;
+		if ((pb = pnp_find_card(
+			     ISAPNP_VENDOR('S', 'I', 'E'),
+			     ISAPNP_FUNCTION(0x0010), pnp_surf))) {
+			pnp_surf = pb;
+			pd = NULL;
+			if (!(pd = pnp_find_dev(pnp_surf,
+						ISAPNP_VENDOR('S', 'I', 'E'),
+						ISAPNP_FUNCTION(0x0010), pd))) {
+				printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
+				return (0);
+			}
+			if (pnp_device_attach(pd) < 0) {
+				printk(KERN_ERR "ISurfPnP: attach failed\n");
+				return 0;
+			}
+			if (pnp_activate_dev(pd) < 0) {
+				printk(KERN_ERR "ISurfPnP: activate failed\n");
+				pnp_device_detach(pd);
+				return 0;
+			}
+			if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
+				printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
+				       pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
+				pnp_device_detach(pd);
+				return(0);
+			}
+			card->para[1] = pnp_port_start(pd, 0);
+			card->para[2] = pnp_port_start(pd, 1);
+			card->para[0] = pnp_irq(pd, 0);
+		} else {
+			printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
+			return 0;
+		}
+	}
+#endif
+	if (isurf_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
--- a/drivers/isdn/hisax/ix1_micro.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/ix1_micro.c	Thu Mar  6 22:52:04 2003
@@ -162,6 +162,29 @@
 	.irq_func = hscxisac_irq,
 };
 
+static int __init
+ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq             = card->para[0];
+	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
+	cs->hw.ix1.isac     = card->para[1] + ISAC_DATA_OFFSET;
+	cs->hw.ix1.hscx     = card->para[1] + HSCX_DATA_OFFSET;
+	cs->hw.ix1.cfg_reg  = card->para[1];
+	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
+		goto err;
+	
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
+	ix1_reset(cs);
+	cs->card_ops = &ix1_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id itk_ids[] __initdata = {
 	{ ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
@@ -181,14 +204,18 @@
 int __init
 setup_ix1micro(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, ix1_revision);
 	printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
 
+	if (card->para[1]) {
+		if (ix1_probe(card->cs, card))
+			return 0;
+		return 1;
+	}
 #ifdef __ISAPNP__
-	if (!card->para[1] && isapnp_present()) {
+	if (isapnp_present()) {
 		struct pnp_card *pb;
 		struct pnp_dev *pd;
 
@@ -221,7 +248,9 @@
 					}
 					card->para[1] = pnp_port_start(pd, 0);
 					card->para[0] = pnp_irq(pd, 0);
-					break;
+					if (ix1_probe(card->cs, card))
+						return 0;
+					return 1;
 				} else {
 					printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
 				}
@@ -231,27 +260,8 @@
 		} 
 		if (!idev->card_vendor) {
 			printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
-			return(0);
 		}
 	}
 #endif
-	/* IO-Ports */
-	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
-	cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET;
-	cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
-	cs->hw.ix1.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
-		goto err;
-	
-	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
-	ix1_reset(cs);
-	cs->card_ops = &ix1_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 1;
- err:
-	hisax_release_resources(cs);
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
--- a/drivers/isdn/hisax/mic.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/mic.c	Thu Mar  6 22:52:04 2003
@@ -138,17 +138,11 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_mic(struct IsdnCard *card)
+static int __init
+mic_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, mic_revision);
-	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
-
-	cs->hw.mic.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
+	cs->hw.mic.cfg_reg = card->para[1];
 	cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
 	cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
 	cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
@@ -158,11 +152,25 @@
   
 	printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
 	       cs->hw.mic.cfg_reg, cs->irq);
+
 	cs->card_ops = &mic_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
+
+int __init
+setup_mic(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, mic_revision);
+	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (mic_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
--- a/drivers/isdn/hisax/niccy.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/niccy.c	Thu Mar  6 22:52:04 2003
@@ -199,6 +199,70 @@
 	.irq_func = niccy_interrupt,
 };
 
+static int __init
+niccy_probe(struct IsdnCardState *cs)
+{
+	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
+	       CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
+	       cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
+	cs->card_ops = &niccy_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -EBUSY;
+	return 0;
+}
+
+static int __init
+niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = NICCY_PNP;
+	cs->irq = card->para[0];
+	cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
+	cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
+	cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
+	cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
+	cs->hw.niccy.cfg_reg = 0;
+
+	if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
+		goto err;
+	if (niccy_probe(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	u32 pci_ioaddr;
+
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = NICCY_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0);
+	pci_ioaddr = pci_resource_start(pdev, 1);
+	cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
+	cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
+	cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
+	cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
+	if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
+		goto err;
+	if (niccy_probe(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *niccy_dev __initdata = NULL;
 #ifdef __ISAPNP__
 static struct pnp_card *pnp_c __devinitdata = NULL;
@@ -207,7 +271,6 @@
 int __init
 setup_niccy(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, niccy_revision);
@@ -252,66 +315,18 @@
 	}
 #endif
 	if (card->para[1]) {
-		cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
-		cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
-		cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
-		cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
-		cs->hw.niccy.cfg_reg = 0;
-		cs->subtyp = NICCY_PNP;
-		cs->irq = card->para[0];
-		if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
-			goto err;
+		if (niccy_pnp_probe(card->cs, card) < 0)
+			return 0;
+		return 1;
 	} else {
 #if CONFIG_PCI
-		u_int pci_ioaddr;
-		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
 			PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
-			if (pci_enable_device(niccy_dev))
-				return(0);
-			/* get IRQ */
-			if (!niccy_dev->irq) {
-				printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->irq = niccy_dev->irq;
-			cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
-			if (!cs->hw.niccy.cfg_reg) {
-				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
-				return(0);
-			}
-			pci_ioaddr = pci_resource_start(niccy_dev, 1);
-			if (!pci_ioaddr) {
-				printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = NICCY_PCI;
-		} else {
-			printk(KERN_WARNING "Niccy: No PCI card found\n");
-			return(0);
+			if (niccy_pci_probe(card->cs, niccy_dev) < 0)
+				return 0;
+			return 1;
 		}
-		cs->irq_flags |= SA_SHIRQ;
-		cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
-		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
-		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
-		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-
-		if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
-			goto err;
 #endif /* CONFIG_PCI */
 	}
-	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
-		CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
-		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
-	cs->card_ops = &niccy_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 1;
- err:
-	niccy_release(cs);
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
--- a/drivers/isdn/hisax/nj_s.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/nj_s.c	Thu Mar  6 22:52:04 2003
@@ -106,96 +106,99 @@
 	.irq_func = nj_s_interrupt,
 };
 
+static int __init
+nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.pdev = pdev;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		return 0;
+	
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+	
+	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+	
+	byteout(cs->hw.njet.auxa, 0);
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) {
+	case 0 :
+		break;
+	case 3 :
+		printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
+		goto err;
+	default :
+		printk(KERN_WARNING "NETjet-S: No PCI card found\n" );
+		goto err;
+	}
+	printk(KERN_INFO
+		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
+		cs->hw.njet.base, cs->irq);
+	
+	nj_s_reset(cs);
+	cs->irq_flags |= SA_SHIRQ;
+	cs->card_ops = &nj_s_ops;
+	isac_setup(cs, &netjet_dc_ops);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_s(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_S_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
-				return(0);
-			}
- 			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
- 			if ((dev_netjet->subsystem_vendor == 0x55) &&
- 				(dev_netjet->subsystem_device == 0x02)) {
- 				printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
- 				printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
- 				return(0);
- 			}
- 			/* end new code */
-			cs->hw.njet.pdev = dev_netjet;
-		} else {
-			printk(KERN_WARNING "NETjet-S: No PCI card found\n");
-			return(0);
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+		if (dev_netjet->subsystem_vendor == 0x55 &&
+		    dev_netjet->subsystem_device == 0x02) {
+			printk(KERN_WARNING "Netjet: You tried to load this "
+			       "driver with an incompatible TigerJet-card\n");
+			printk(KERN_WARNING "Use type=41 for Formula-n "
+			       "enter:now ISDN PCI and compatible\n");
+			return 0;
 		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 0 :
-				break;
-
-			case 3 :
-				printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
-				return 0;
-                }
-                break;
-	}
-	printk(KERN_INFO
-		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		if (nj_s_probe(card->cs, dev_netjet))
+			return 1;
 		return 0;
-	
-	nj_s_reset(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &nj_s_ops;
-	isac_setup(cs, &netjet_dc_ops);
-	return 1;
+	}
+	printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+	return 0;
 }
+
diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
--- a/drivers/isdn/hisax/nj_u.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/nj_u.c	Thu Mar  6 22:52:05 2003
@@ -110,88 +110,85 @@
 	.irq_func = nj_u_interrupt,
 };
 
+static int __init
+nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.pdev = pdev;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn"))
+		goto err;
+	
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+
+	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+	
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3)	{
+	case 3:
+		break;
+	case 0:
+		printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
+		goto err;
+	default:
+		printk(KERN_WARNING "NETspider-U: No PCI card found\n" );
+		goto err;
+	}
+	printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n",
+	       cs->hw.njet.base, cs->irq);
+
+	nj_u_reset(cs);
+	cs->card_ops = &nj_u_ops;
+	icc_setup(cs, &netjet_dc_ops);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_u(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_U_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
-
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.pdev = dev_netjet;
-		} else {
-			printk(KERN_WARNING "NETspider-U: No PCI card found\n");
-			return(0);
-		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.auxa, 0);
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 3 :
-				break;
-
-			case 0 :
-				printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
-				return 0;
-                }
-                break;
-	}
-	printk(KERN_INFO
-		"NETspider-U: PCI card configured at %#lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
-		return 0;
+	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 	
-	nj_u_reset(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &nj_u_ops;
-	icc_setup(cs, &netjet_dc_ops);
-	return 1;
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		if (nj_u_probe(card->cs, dev_netjet))
+			return 1;
+		return 0;
+	}
+	printk(KERN_WARNING "NETspider-U: No PCI card found\n");
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
--- a/drivers/isdn/hisax/s0box.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/s0box.c	Thu Mar  6 22:52:05 2003
@@ -172,14 +172,9 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_s0box(struct IsdnCard *card)
+static int __init
+s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, s0box_revision);
-	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
 	cs->hw.teles3.cfg_reg = card->para[1];
 	cs->hw.teles3.hscx[0] = -0x20;
 	cs->hw.teles3.hscx[1] = 0x0;
@@ -200,8 +195,20 @@
 	cs->card_ops = &s0box_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
+
+int __init
+setup_s0box(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, s0box_revision);
+	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
+	if (s0box_probe(card->cs, card))
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
--- a/drivers/isdn/hisax/saphir.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/saphir.c	Thu Mar  6 22:52:05 2003
@@ -201,36 +201,21 @@
 	.irq_func = saphir_interrupt,
 };
 
-int __init
-setup_saphir(struct IsdnCard *card)
+static int __init
+saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, saphir_rev);
-	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
-		return (0);
-
-	init_timer(&cs->hw.saphir.timer);
-	/* IO-Ports */
 	cs->hw.saphir.cfg_reg = card->para[1];
 	cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
 	cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
 	cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
 	cs->irq = card->para[0];
+
 	if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir"))
 		goto err;
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.saphir.cfg_reg);
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
 
-	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
-	cs->hw.saphir.timer.data = (long) cs;
-	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
-	add_timer(&cs->hw.saphir.timer);
 	if (saphir_reset(cs))
 		goto err;
 
@@ -238,8 +223,27 @@
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
 
-	return 1;
- err:
-	saphir_release(cs);
+	init_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+	cs->hw.saphir.timer.data = (long) cs;
+	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
+	add_timer(&cs->hw.saphir.timer);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_saphir(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, saphir_rev);
+	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (saphir_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
--- a/drivers/isdn/hisax/sedlbauer.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/sedlbauer.c	Thu Mar  6 22:52:05 2003
@@ -73,7 +73,6 @@
 #define SEDL_SPEEDFAX_PYRAMID	7
 #define SEDL_SPEEDFAX_PCI	8
 
-#define SEDL_CHIP_TEST		0
 #define SEDL_CHIP_ISAC_HSCX	1
 #define SEDL_CHIP_ISAC_ISAR	2
 #define SEDL_CHIP_IPAC		3
@@ -452,6 +451,241 @@
 	.irq_func    = sedlbauer_isar_interrupt,
 };
 
+static int __init
+sedl_ipac_probe(struct IsdnCardState *cs)
+{
+	u8 val;
+
+	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+	val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+	printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
+	return (val == 1 || val == 2);
+}
+
+static int __init
+sedl_ipac_init(struct IsdnCardState *cs)
+{
+	cs->card_ops = &sedlbauer_ipac_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		return -ENODEV;
+	sedlbauer_reset(cs);
+	return 0;
+}
+
+static int __init
+sedl_isac_isar_init(struct IsdnCardState *cs)
+{
+	cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+	cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+	__set_bit(HW_ISAR, &cs->HW_Flags);
+	cs->card_ops = &sedlbauer_isar_ops;
+	cs->auxcmd = &isar_auxcmd;
+	isac_setup(cs, &isac_ops);
+	return isar_setup(cs, &isar_ops);
+}
+
+static int __init
+sedl_isac_hscx_init(struct IsdnCardState *cs)
+{
+	cs->card_ops = &sedlbauer_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -ENODEV;
+	sedlbauer_reset(cs);
+	return 0;
+}
+
+static int __init
+sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.sedl.cfg_reg = card->para[1];
+	cs->hw.sedl.bus = SEDL_BUS_ISA;
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn"))
+		goto err;
+
+	if (sedl_ipac_probe(cs)) {
+		cs->subtyp = SEDL_SPEED_WIN2_PC104;
+		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		if (sedl_ipac_init(cs))
+			goto err;
+	} else {
+		cs->subtyp = SEDL_SPEED_CARD_WIN;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+		if (sedl_isac_hscx_init(cs))
+			goto err;
+	}
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+	if (sedl_ipac_probe(cs)) {
+		cs->subtyp = SEDL_SPEED_STAR2;
+		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		if (sedl_ipac_init(cs))
+			goto err;
+	} else {
+		cs->subtyp = SEDL_SPEED_STAR;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+		if (sedl_isac_hscx_init(cs))
+			goto err;
+	}
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = SEDL_SPEED_FAX;
+	cs->hw.sedl.bus = SEDL_BUS_ISA;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn"))
+		goto err;
+
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq);
+
+	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg  + SEDL_ISAR_ISA_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
+	cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
+	cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0);
+	cs->hw.sedl.bus = SEDL_BUS_PCI;
+
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn"))
+		return -EBUSY;
+
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq);
+
+	cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
+	cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
+	byteout(cs->hw.sedl.cfg_reg, 0xff);
+	byteout(cs->hw.sedl.cfg_reg, 0x00);
+	byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+	byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+	return 0;
+}
+
+static int __init
+sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEEDFAX_PCI;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEED_PCI;
+	cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+	if (sedl_ipac_init(cs))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_sedl __devinitdata = NULL;
 
 #ifdef __ISAPNP__
@@ -472,265 +706,117 @@
 int __devinit
 setup_sedlbauer(struct IsdnCard *card)
 {
-	int bytecnt, val;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u16 sub_vendor_id, sub_id;
 
 	strcpy(tmp, Sedlbauer_revision);
-	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 	
- 	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
- 		cs->subtyp = SEDL_SPEED_CARD_WIN;
-		cs->hw.sedl.bus = SEDL_BUS_ISA;
-		cs->hw.sedl.chip = SEDL_CHIP_TEST;
- 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
- 		cs->subtyp = SEDL_SPEED_STAR;
-		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
-		cs->hw.sedl.chip = SEDL_CHIP_TEST;
- 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
- 		cs->subtyp = SEDL_SPEED_FAX;
-		cs->hw.sedl.bus = SEDL_BUS_ISA;
-		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
- 	} else
-		return (0);
-
-	bytecnt = 8;
 	if (card->para[1]) {
-		cs->hw.sedl.cfg_reg = card->para[1];
-		cs->irq = card->para[0];
-		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-			bytecnt = 16;
+		if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
+			if (sedl_card_win_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
+		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
+			if (sedl_star_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
+		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
+			if (sedl_fax_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
 		}
-	} else {
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_card *pb;
-			struct pnp_dev *pd;
-
-			while(pdev->card_vendor) {
-				if ((pb = pnp_find_card(pdev->card_vendor,
-						        pdev->card_device,
-						        pnp_c))) {
-					pnp_c = pb;
-					pd = NULL;
-					if ((pd = pnp_find_dev(pnp_c,
-							       pdev->vendor,
-							       pdev->function,
-							       pd))) {
-						printk(KERN_INFO "HiSax: %s detected\n",
-							(char *)pdev->driver_data);
-						if (pnp_device_attach(pd) < 0) {
-							printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
-							return 0;
-						}
-						if (pnp_activate_dev(pd) < 0) {
-							printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
-							pnp_device_detach(pd);
+	if (isapnp_present()) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+		
+		while(pdev->card_vendor) {
+			if ((pb = pnp_find_card(pdev->card_vendor,
+						pdev->card_device,
+						pnp_c))) {
+				pnp_c = pb;
+				pd = NULL;
+				if ((pd = pnp_find_dev(pnp_c,
+						       pdev->vendor,
+						       pdev->function,
+						       pd))) {
+					printk(KERN_INFO "HiSax: %s detected\n",
+					       (char *)pdev->driver_data);
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd) < 0) {
+						printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+						printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
+						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
+						goto err;
+					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
+					cs->hw.sedl.cfg_reg = card->para[1];
+					cs->irq = card->para[0];
+					if (pdev->function == ISAPNP_FUNCTION(0x2)) {
+						if (sedl_fax_probe(card->cs, card))
 							return 0;
-						}
-						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-							printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
-								pnp_irq(pd, 0), pnp_port_start(pd, 0));
-							pnp_device_detach(pd);
-							goto err;
-						}
-						card->para[1] = pnp_port_start(pd, 0);
-						card->para[0] = pnp_irq(pd, 0);
-						cs->hw.sedl.cfg_reg = card->para[1];
-						cs->irq = card->para[0];
-						if (pdev->function == ISAPNP_FUNCTION(0x2)) {
-							cs->subtyp = SEDL_SPEED_FAX;
-							cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-							bytecnt = 16;
-						} else {
-							cs->subtyp = SEDL_SPEED_CARD_WIN;
-							cs->hw.sedl.chip = SEDL_CHIP_TEST;
-						}
-						goto ready;
+						return 1;
 					} else {
-						printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
-						goto err;
+						if (sedl_card_win_probe(card->cs, card))
+							return 0;
+						return 1;
 					}
+				} else {
+					printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
+					goto err;
 				}
-				pdev++;
-				pnp_c=NULL;
-			} 
-			if (!pdev->card_vendor) {
-				printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 			}
+			pdev++;
+			pnp_c=NULL;
+		} 
+		if (!pdev->card_vendor) {
+			printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 		}
+	}
 #endif
 /* Probe for Sedlbauer speed pci */
 #if CONFIG_PCI
-		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
-			if (pci_enable_device(dev_sedl))
-				goto err;
-			cs->irq = dev_sedl->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
-				goto err;
-			}
-			cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
-		} else {
-			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
-			goto err;
-		}
-		cs->irq_flags |= SA_SHIRQ;
-		cs->hw.sedl.bus = SEDL_BUS_PCI;
+	dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				   PCI_DEVICE_ID_TIGERJET_100, dev_sedl);
+	if (dev_sedl) {
 		sub_vendor_id = dev_sedl->subsystem_vendor;
 		sub_id = dev_sedl->subsystem_device;
 		printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
-			sub_vendor_id, sub_id);
-		printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
-			cs->hw.sedl.cfg_reg);
+		       sub_vendor_id, sub_id);
 		if (sub_id != PCI_SUB_ID_SEDLBAUER) {
 			printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
-			goto err;
+			return 0;
 		}
 		if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
-			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-			cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
+			if (sedl_fax_pyramid_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
-			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-			cs->subtyp = SEDL_SPEEDFAX_PCI;
+			if (sedl_fax_pci_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
-			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-			cs->subtyp = SEDL_SPEED_PCI;
-		} else {
-			printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
-				sub_vendor_id);
-			goto err;
-		}
-		bytecnt = 256;
-		cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
-		cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
-		byteout(cs->hw.sedl.cfg_reg, 0xff);
-		byteout(cs->hw.sedl.cfg_reg, 0x00);
-		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
-		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);
-		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-#endif /* CONFIG_PCI */
-	}	
-ready:	
-	/* In case of the sedlbauer pcmcia card, this region is in use,
-	 * reserved for us by the card manager. So we do not check it
-	 * here, it would fail.
-	 */
-	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) {
-		if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn"))
-			goto err;
-	}
-
-	printk(KERN_INFO
-	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
-	       cs->hw.sedl.cfg_reg,
-	       cs->hw.sedl.cfg_reg + bytecnt,
-	       cs->irq);
-
-/*
- * testing ISA and PCMCIA Cards for IPAC, default is ISAC
- * do not test for PCI card, because ports are different
- * and PCI card uses only IPAC (for the moment)
- */	
-	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-		val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC,
-			      IPAC_ID);
-		printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
-	        if ((val == 1) || (val == 2)) {
-			/* IPAC */
-			cs->subtyp = SEDL_SPEED_WIN2_PC104;
-			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
-				cs->subtyp = SEDL_SPEED_STAR2;
-			}
-			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-		} else {
-			/* ISAC_HSCX oder ISAC_ISAR */
-			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
-				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
-			}
-		}
-	}
-
-/*
- * hw.sedl.chip is now properly set
- */
-	printk(KERN_INFO "Sedlbauer: %s detected\n",
-		Sedlbauer_Types[cs->subtyp]);
-
-
-	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
-		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
-	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
-			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
-			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
-		} else {
-	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-		}
-		cs->card_ops = &sedlbauer_ipac_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-		sedlbauer_reset(cs);
-	} else {
-		/* ISAC_HSCX oder ISAC_ISAR */
-		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-			if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ISAR;
-			} else {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR_RESET_ON;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR_RESET_OFF;
-			}
-			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
-			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
-			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
-			cs->card_ops = &sedlbauer_isar_ops;
-			cs->auxcmd = &isar_auxcmd;
-			isac_setup(cs, &isac_ops);
-			if (isar_setup(cs, &isar_ops))
-				goto err;
-		} else {
-			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-			} else {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
-			}
-			cs->card_ops = &sedlbauer_ops;
-			if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-				goto err;
-
-			sedlbauer_reset(cs);
+			if (sedl_pci_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		}
+		printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
+		       sub_vendor_id);
+		return 0;
 	}
-	return 1;
- err:
-	hisax_release_resources(cs);
+#endif /* CONFIG_PCI */
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
--- a/drivers/isdn/hisax/sportster.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/sportster.c	Thu Mar  6 22:52:05 2003
@@ -189,42 +189,29 @@
 	}
 	return 0;
 }
-  
-int __init
-setup_sportster(struct IsdnCard *card)
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, sportster_revision);
-	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
 
-	cs->hw.spt.cfg_reg = card->para[1];
+static int __init
+sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
 	cs->irq = card->para[0];
+	cs->hw.spt.cfg_reg = card->para[1];
 	if (!get_io_range(cs))
-		return (0);
+		return -EBUSY;
 	cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC;
 	cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA;
 	cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB;
 	
 	switch(cs->irq) {
-		case 5:	cs->hw.spt.res_irq = 1;
-			break;
-		case 7:	cs->hw.spt.res_irq = 2;
-			break;
-		case 10:cs->hw.spt.res_irq = 3;
-			break;
-		case 11:cs->hw.spt.res_irq = 4;
-			break;
-		case 12:cs->hw.spt.res_irq = 5;
-			break;
-		case 14:cs->hw.spt.res_irq = 6;
-			break;
-		case 15:cs->hw.spt.res_irq = 7;
-			break;
-		default:sportster_release(cs);
-			printk(KERN_WARNING "Sportster: wrong IRQ\n");
-			return(0);
+	case 5:	cs->hw.spt.res_irq = 1;	break;
+	case 7:	cs->hw.spt.res_irq = 2;	break;
+	case 10:cs->hw.spt.res_irq = 3;	break;
+	case 11:cs->hw.spt.res_irq = 4;	break;
+	case 12:cs->hw.spt.res_irq = 5;	break;
+	case 14:cs->hw.spt.res_irq = 6;	break;
+	case 15:cs->hw.spt.res_irq = 7;	break;
+	default:
+		printk(KERN_WARNING "Sportster: wrong IRQ\n");
+		goto err;
 	}
 	sportster_reset(cs);
 	printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
@@ -234,8 +221,22 @@
 	cs->card_ops = &sportster_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
- err:
-	hisax_release_resources(cs);
 	return 0;
+ err:
+	sportster_release(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_sportster(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, sportster_revision);
+	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (sportster_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
--- a/drivers/isdn/hisax/teleint.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/teleint.c	Thu Mar  6 22:52:05 2003
@@ -256,15 +256,9 @@
 	.irq_func = teleint_interrupt,
 };
 
-int __init
-setup_TeleInt(struct IsdnCard *card)
+static int __init
+teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, TeleInt_revision);
-	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
-
 	cs->hw.hfc.addr = card->para[1] & 0x3fe;
 	cs->irq = card->para[0];
 	cs->hw.hfc.cirm = HFC_CIRM;
@@ -284,42 +278,54 @@
 	byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
 	byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
 	switch (cs->irq) {
-		case 3:
-			cs->hw.hfc.cirm |= HFC_INTA;
-			break;
-		case 4:
-			cs->hw.hfc.cirm |= HFC_INTB;
-			break;
-		case 5:
-			cs->hw.hfc.cirm |= HFC_INTC;
-			break;
-		case 7:
-			cs->hw.hfc.cirm |= HFC_INTD;
-			break;
-		case 10:
-			cs->hw.hfc.cirm |= HFC_INTE;
-			break;
-		case 11:
-			cs->hw.hfc.cirm |= HFC_INTF;
-			break;
-		default:
-			printk(KERN_WARNING "TeleInt: wrong IRQ\n");
-			goto err;
+	case 3:
+		cs->hw.hfc.cirm |= HFC_INTA;
+		break;
+	case 4:
+		cs->hw.hfc.cirm |= HFC_INTB;
+		break;
+	case 5:
+		cs->hw.hfc.cirm |= HFC_INTC;
+		break;
+	case 7:
+		cs->hw.hfc.cirm |= HFC_INTD;
+		break;
+	case 10:
+		cs->hw.hfc.cirm |= HFC_INTE;
+		break;
+	case 11:
+		cs->hw.hfc.cirm |= HFC_INTF;
+		break;
+	default:
+		printk(KERN_WARNING "TeleInt: wrong IRQ\n");
+		goto err;
 	}
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
 
-	printk(KERN_INFO
-	       "TeleInt: defined at 0x%x IRQ %d\n",
-	       cs->hw.hfc.addr,
-	       cs->irq);
+	printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
+	       cs->hw.hfc.addr, cs->irq);
 
 	cs->card_ops = &teleint_ops;
 	teleint_reset(cs);
 	isac_setup(cs, &isac_ops);
 	hfc_setup(cs, &hfc_ops);
-	return 1;
- err:
-	teleint_release(cs);
 	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_TeleInt(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, TeleInt_revision);
+	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (teleint_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
--- a/drivers/isdn/hisax/teles0.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/teles0.c	Thu Mar  6 22:52:05 2003
@@ -165,72 +165,95 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_teles0(struct IsdnCard *card)
+static int __init
+teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, teles0_revision);
-	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ == ISDN_CTYPE_16_0)
-		cs->hw.teles0.cfg_reg = card->para[2];
-	else			/* 8.0 */
-		cs->hw.teles0.cfg_reg = 0;
-
-	if (card->para[1] < 0x10000) {
-		card->para[1] <<= 4;
-		printk(KERN_INFO
-		   "Teles0: membase configured DOSish, assuming 0x%lx\n",
-		       (unsigned long) card->para[1]);
-	}
 	cs->irq = card->para[0];
-	if (cs->hw.teles0.cfg_reg) {
-		if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
-			goto err;
-
-		if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 0, val);
-			goto err;
-		}
-		if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 1, val);
-			goto err;
-		}
-		val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
-							 * 0x1f=with AB
-							 * 0x1c 16.3 ???
-							 */
-		if (val != 0x1e && val != 0x1f) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 2, val);
-			goto err;
-		}
-	}
 	/* 16.0 and 8.0 designed for IOM1 */
 	test_and_set_bit(HW_IOM1, &cs->HW_Flags);
 	cs->hw.teles0.phymem = card->para[1];
-	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem");
+	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem,
+					     TELES_IOMEM_SIZE, "teles iomem");
 	if (!cs->hw.teles0.membase)
-		goto err;
+		return -EBUSY;
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
 	if (teles0_reset(cs)) {
 		printk(KERN_WARNING "Teles0: wrong IRQ\n");
-		goto err;
+		return -EBUSY;
 	}
 	cs->card_ops = &teles0_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-  		goto err;
-	return 1;
+		return -EBUSY;
 
+	return 0;
+}
+
+static int __init
+teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->hw.teles0.cfg_reg = card->para[2];
+	if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
+		goto err;
+		
+	if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 0, val);
+		goto err;
+	}
+	if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 1, val);
+		goto err;
+	}
+	val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
+						 * 0x1f=with AB
+						 * 0x1c 16.3 ???
+						 */
+	if (val != 0x1e && val != 0x1f) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 2, val);
+		goto err;
+	}
+	if (teles0_probe(cs, card) < 0)
+		goto err;
+
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles0.cfg_reg = 0;
+
+	if (teles0_probe(cs, card) < 0)
+		goto err;
+
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_teles0(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, teles0_revision);
+	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (card->cs->typ == ISDN_CTYPE_16_0) {
+		if (teles16_0_probe(card->cs, card) < 0)
+			return 0;
+	} else {
+		if (teles8_0_probe(card->cs, card) < 0)
+			return 0;
+	}
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
--- a/drivers/isdn/hisax/teles3.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/teles3.c	Thu Mar  6 22:52:05 2003
@@ -176,6 +176,152 @@
 	.irq_func = hscxisac_irq,
 };
 
+static int
+teles_hw_init(struct IsdnCardState *cs)
+{
+	
+	printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
+	printk(KERN_INFO "HiSax: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
+
+	if (teles3_reset(cs)) {
+		printk(KERN_WARNING "Teles3: wrong IRQ\n");
+		return -EBUSY;
+	}
+	cs->card_ops = &teles3_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -EBUSY;
+	return 0;
+}
+
+static void __init
+teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
+	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
+	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+}
+
+static int __init
+telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = 0;
+	cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
+	cs->hw.teles3.hscx[1] = card->para[1];
+	cs->hw.teles3.isac = card->para[1] + 0x20;
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, 
+			"HiSax Teles PCMCIA"))
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+teles_request_io(struct IsdnCardState *cs)
+{
+	if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
+		return -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A"))
+		return -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B"))
+		return -EBUSY;
+	return 0;
+}
+
+static int __init
+teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->hw.teles3.cfg_reg = card->para[1];
+	switch (cs->hw.teles3.cfg_reg) {
+	case 0x180:
+	case 0x280:
+	case 0x380:
+		cs->hw.teles3.cfg_reg |= 0xc00;
+		break;
+	}
+	cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
+	cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
+	cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
+		goto err;
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 0, val);
+		goto err;
+	}
+	if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 1, val);
+		goto err;
+	}
+	/* 0x1e without AB, 0x1f with AB,  0x1c 16.3 ???, 
+	 * 0x39 16.3 1.1,   0x38 16.3 1.3, 0x46 16.3 with AB + Video */
+	val = bytein(cs->hw.teles3.cfg_reg + 2);
+	if (val != 0x46 && val != 0x39 && val != 0x38 && 
+	    val != 0x1c && val != 0x1e && val != 0x1f) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 2, val);
+		goto err;
+	}
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = card->para[3];
+	cs->hw.teles3.isac = card->para[2] - 32;
+	cs->hw.teles3.hscx[0] = card->para[1] - 32;
+	cs->hw.teles3.hscx[1] = card->para[1];
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
+		goto err;
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = 0;
+	cs->hw.teles3.isac = card->para[1] - 32;
+	cs->hw.teles3.hscx[0] = card->para[2] - 32;
+	cs->hw.teles3.hscx[1] = card->para[2];
+	teles_setup_io(cs, card);
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id teles_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
@@ -197,16 +343,10 @@
 int __devinit
 setup_teles3(struct IsdnCard *card)
 {
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, teles3_revision);
 	printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
-	if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP)
-	    && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
-		return (0);
-
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
 		struct pnp_card *pnp_card;
@@ -258,100 +398,18 @@
 		}
 	}
 #endif
-	if (cs->typ == ISDN_CTYPE_16_3) {
-		cs->hw.teles3.cfg_reg = card->para[1];
-		switch (cs->hw.teles3.cfg_reg) {
-			case 0x180:
-			case 0x280:
-			case 0x380:
-				cs->hw.teles3.cfg_reg |= 0xc00;
-				break;
-		}
-		cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
-		cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
-		cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
-	} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		cs->hw.teles3.cfg_reg = 0;
-		cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
-		cs->hw.teles3.hscx[1] = card->para[1];
-		cs->hw.teles3.isac = card->para[1] + 0x20;
-	} else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-		cs->hw.teles3.cfg_reg = card->para[3];
-		cs->hw.teles3.isac = card->para[2] - 32;
-		cs->hw.teles3.hscx[0] = card->para[1] - 32;
-		cs->hw.teles3.hscx[1] = card->para[1];
+	if (card->cs->typ == ISDN_CTYPE_16_3) {
+		if (teles16_3_probe(card->cs, card) < 0)
+			return 0;
+	} else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) {
+		if (telespcmcia_probe(card->cs, card) < 0)
+			return 0;
+	} else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+		if (compaq_probe(card->cs, card) < 0)
+			return 0;
 	} else {	/* PNP */
-		cs->hw.teles3.cfg_reg = 0;
-		cs->hw.teles3.isac = card->para[1] - 32;
-		cs->hw.teles3.hscx[0] = card->para[2] - 32;
-		cs->hw.teles3.hscx[1] = card->para[2];
-	}
-	cs->irq = card->para[0];
-	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
-	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
-	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
-	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA"))
-			goto err;
-	} else {
-		if (cs->hw.teles3.cfg_reg) {
-			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
-					goto err;
-			} else {
-				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
-					goto err;
-			}
-		}
-		if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B"))
-			goto err;
-	}
-	if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
-		if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 0, val);
-			goto err;
-		}
-		if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 1, val);
-			goto err;
-		}
-		val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
-							 * 0x1f=with AB
-							 * 0x1c 16.3 ???
-							 * 0x39 16.3 1.1
-							 * 0x38 16.3 1.3
-							 * 0x46 16.3 with AB + Video (Teles-Vision)
-							 */
-		if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 2, val);
-			goto err;
-		}
-	}
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
-	printk(KERN_INFO
-	       "HiSax: hscx A:0x%X  hscx B:0x%X\n",
-	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
-
-	if (teles3_reset(cs)) {
-		printk(KERN_WARNING "Teles3: wrong IRQ\n");
-		goto err;
+		if (telespnp_probe(card->cs, card) < 0)
+			return 0;
 	}
-	cs->card_ops = &teles3_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
 	return 1;
- err:
-	hisax_release_resources(cs);
-	return 0;
-
 }
diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
--- a/drivers/isdn/hisax/telespci.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/telespci.c	Thu Mar  6 22:52:05 2003
@@ -231,36 +231,23 @@
 	.irq_func = telespci_interrupt,
 };
 
-static struct pci_dev *dev_tel __initdata = NULL;
-
-int __init
-setup_telespci(struct IsdnCard *card)
+static int __init
+telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
+	int rc;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-	strcpy(tmp, telespci_revision);
-	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
-		if (pci_enable_device(dev_tel))
-			return(0);
-		cs->irq = dev_tel->irq;
-		if (!cs->irq) {
-			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
-			return(0);
-		}
-		cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci");
-		if (!cs->hw.teles0.membase)
-			goto err;
-		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
-			pci_resource_start(dev_tel, 0), dev_tel->irq);
-	} else {
-		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
-		return(0);
-	}
+	printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n",
+	       pci_resource_start(pdev, 0), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci");
+	if (!cs->hw.teles0.membase)
+		goto err;
 
 	/* Initialize Zoran PCI controller */
 	writel(0x00000000, cs->hw.teles0.membase + 0x28);
@@ -270,17 +257,36 @@
 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
 	writel(0x61000000, cs->hw.teles0.membase + 0x40);
 	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:%p\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles0.membase);
 
-	cs->irq_flags |= SA_SHIRQ;
 	cs->card_ops = &telespci_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return rc;
+}
+
+static struct pci_dev *dev_tel __initdata = NULL;
+
+int __init
+setup_telespci(struct IsdnCard *card)
+{
+	char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+	strcpy(tmp, telespci_revision);
+	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+	dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, 
+				  PCI_DEVICE_ID_ZORAN_36120, dev_tel);
+	if (dev_tel) {
+		if (telespci_probe(card->cs, dev_tel) < 0)
+			return 0;
+		return 1;
+	}
+	printk(KERN_WARNING "TelesPCI: No PCI card found\n");
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
--- a/drivers/isdn/hisax/w6692.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/w6692.c	Thu Mar  6 22:52:05 2003
@@ -669,11 +669,11 @@
 static struct pci_dev *dev_w6692 __initdata = NULL;
 
 static int
-w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops,
-	    struct bc_hw_ops *bc_ops)
+w6692_hw_init(struct IsdnCardState *cs)
 {
-	cs->dc_hw_ops = dc_ops;
-	cs->bc_hw_ops = bc_ops;
+	cs->card_ops = &w6692_ops;
+	cs->dc_hw_ops = &w6692_dc_hw_ops, 
+	cs->bc_hw_ops = &w6692_bc_hw_ops;
 	dc_l1_init(cs, &w6692_dc_l1_ops);
 	cs->bc_l1_ops = &w6692_bc_l1_ops;
 	W6692Version(cs, "W6692:");
@@ -685,14 +685,45 @@
 	return 0;
 }
 
+static int __init
+w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	int rc;
+
+	printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n",
+	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
+	       pci_resource_start(pdev, 1), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	/* USR ISDN PCI card TA need some special handling */
+	if (cs->subtyp == W6692_WINBOND) {
+		if (pdev->subsystem_vendor == W6692_SV_USR  &&
+		    pdev->subsystem_device == W6692_SD_USR) {
+			cs->subtyp = W6692_USR;
+		}
+	}
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.w6692.iobase = pci_resource_start(pdev, 1);
+	
+	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100,
+			id_list[cs->subtyp].card_name))
+		goto err;
+
+	w6692_hw_init(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 int __init 
 setup_w6692(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u8 found = 0;
-	u8 pci_irq = 0;
-	u_int pci_ioaddr = 0;
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
@@ -704,54 +735,13 @@
 					    id_list[id_idx].device_id,
 					    dev_w6692);
 		if (dev_w6692) {
-			if (pci_enable_device(dev_w6692))
-				continue;
-			cs->subtyp = id_idx;
-			break;
+			card->cs->subtyp = id_idx;
+			if (w6692_probe(card->cs, dev_w6692) < 0)
+				return 0;
+			return 1;
 		}
 		id_idx++;
 	}
-	if (dev_w6692) {
-		found = 1;
-		pci_irq = dev_w6692->irq;
-		/* I think address 0 is allways the configuration area */
-		/* and address 1 is the real IO space KKe 03.09.99 */
-		pci_ioaddr = pci_resource_start(dev_w6692, 1);
-		/* USR ISDN PCI card TA need some special handling */
-		if (cs->subtyp == W6692_WINBOND) {
-			if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
-			    (W6692_SD_USR == dev_w6692->subsystem_device)) {
-				cs->subtyp = W6692_USR;
-			}
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "W6692: No PCI card found\n");
-		return (0);
-	}
-	cs->irq = pci_irq;
-	if (!cs->irq) {
-		printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
-		return (0);
-	}
-	if (!pci_ioaddr) {
-		printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
-		return (0);
-	}
-	cs->hw.w6692.iobase = pci_ioaddr;
-	printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
-	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
-	       pci_ioaddr, pci_irq);
-	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name))
-		return 0;
-	
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d I/O:%x\n",
-	       id_list[cs->subtyp].card_name, cs->irq,
-	       cs->hw.w6692.iobase);
-
-	cs->card_ops = &w6692_ops;
-	w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops);
-	cs->irq_flags |= SA_SHIRQ;
-	return (1);
+	printk(KERN_WARNING "W6692: No PCI card found\n");
+	return 0;
 }
diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
--- a/drivers/isdn/i4l/Kconfig	Tue Nov 12 12:48:13 2002
+++ b/drivers/isdn/i4l/Kconfig	Sat Feb 22 09:17:33 2003
@@ -85,7 +85,7 @@
 
 config ISDN_X25
 	bool "X.25 PLP on top of ISDN"
-	depends on X25
+	depends on X25 && BROKEN
 	help
 	  This feature provides the X.25 protocol over ISDN connections.
 	  See <file:Documentation/isdn/README.x25> for more information
diff -Nru a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c
--- a/drivers/isdn/i4l/isdn_net_lib.c	Tue Nov 12 13:33:35 2002
+++ b/drivers/isdn/i4l/isdn_net_lib.c	Sat Feb 22 09:17:33 2003
@@ -58,6 +58,7 @@
 #include "isdn_net.h"
 #include "isdn_ppp.h"
 #include "isdn_ciscohdlck.h"
+#include "isdn_concap.h"
 
 #define ISDN_NET_TX_TIMEOUT (20*HZ) 
 
diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
--- a/drivers/isdn/i4l/isdn_ppp.c	Tue Nov 12 13:34:48 2002
+++ b/drivers/isdn/i4l/isdn_ppp.c	Sat Mar  1 13:01:59 2003
@@ -867,7 +867,7 @@
 		skb_pull(skb, 1);
 	} else {
 		if (skb->len < 2)
-			return -1;
+			return -EINVAL;
 		get_u16(skb->data, proto);
 		skb_pull(skb, 2);
 	}
@@ -1037,7 +1037,7 @@
                 isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1);
 
 	ippp_push_proto(ind_ppp, skb, proto);
-	ippp_mp_xmit(idev, skb, proto);
+	ippp_mp_xmit(idev, skb);
 	return 0;
 
  drop:
diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.c b/drivers/isdn/i4l/isdn_ppp_mp.c
--- a/drivers/isdn/i4l/isdn_ppp_mp.c	Tue Oct 29 18:41:43 2002
+++ b/drivers/isdn/i4l/isdn_ppp_mp.c	Sat Feb 22 10:03:46 2003
@@ -91,12 +91,13 @@
 }
 
 void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
 {
 	struct ind_ppp *ind_ppp = idev->ind_priv;
 	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
 	unsigned char *p;
-	long txseq;
+	u32 txseq;
+	u16 proto;
 
 	if (!(inl_ppp->mp_cfg & SC_MP_PROT)) {
 		return ippp_xmit(idev, skb);
diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.h b/drivers/isdn/i4l/isdn_ppp_mp.h
--- a/drivers/isdn/i4l/isdn_ppp_mp.h	Tue Oct 29 18:28:25 2002
+++ b/drivers/isdn/i4l/isdn_ppp_mp.h	Sat Feb 22 10:03:46 2003
@@ -19,7 +19,7 @@
 int  ippp_mp_bind(isdn_net_dev *idev);
 void ippp_mp_disconnected(isdn_net_dev *idev);
 int  ippp_mp_bundle(isdn_net_dev *idev, int val);
-void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
+void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb);
 void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
 
 #else
@@ -42,9 +42,9 @@
 }
 
 static inline void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
 {
-	ippp_xmit(idev, skb, proto);
+	ippp_xmit(idev, skb);
 }
 
 static inline void 
diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
--- a/drivers/macintosh/macserial.c	Mon Nov 11 05:18:24 2002
+++ b/drivers/macintosh/macserial.c	Fri Feb 14 15:20:31 2003
@@ -3043,10 +3043,12 @@
 /*
  *	Register console.
  */
-void __init mac_scc_console_init(void)
+static void __init mac_scc_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(mac_scc_console_init);
+
 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
 
 #ifdef CONFIG_KGDB
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	Thu Jan  2 03:27:23 2003
+++ b/drivers/md/dm.c	Sat Mar  8 14:50:22 2003
@@ -79,9 +79,8 @@
 		return -ENOMEM;
 
 	_major = major;
-	r = register_blkdev(_major, _name, &dm_blk_dops);
+	r = register_blkdev(_major, _name);
 	if (r < 0) {
-		DMERR("register_blkdev failed");
 		kmem_cache_destroy(_io_cache);
 		return r;
 	}
diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c
--- a/drivers/md/linear.c	Mon Feb 17 13:54:05 2003
+++ b/drivers/md/linear.c	Tue Mar 11 18:46:36 2003
@@ -203,36 +203,34 @@
 		return 0;
 	}
 	bio->bi_bdev = tmp_dev->rdev->bdev;
-	bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1);
+	bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset;
 
 	return 1;
 }
 
-static int linear_status (char *page, mddev_t *mddev)
+static void linear_status (struct seq_file *seq, mddev_t *mddev)
 {
-	int sz = 0;
 
 #undef MD_DEBUG
 #ifdef MD_DEBUG
 	int j;
 	linear_conf_t *conf = mddev_to_conf(mddev);
   
-	sz += sprintf(page+sz, "      ");
+	seq_printf(seq, "      ");
 	for (j = 0; j < conf->nr_zones; j++)
 	{
-		sz += sprintf(page+sz, "[%s",
+		seq_printf(seq, "[%s",
 			bdev_partition_name(conf->hash_table[j].dev0->rdev->bdev));
 
 		if (conf->hash_table[j].dev1)
-			sz += sprintf(page+sz, "/%s] ",
+			seq_printf(seq, "/%s] ",
 			  bdev_partition_name(conf->hash_table[j].dev1->rdev->bdev));
 		else
-			sz += sprintf(page+sz, "] ");
+			seq_printf(seq, "] ");
 	}
-	sz += sprintf(page+sz, "\n");
+	seq_printf(seq, "\n");
 #endif
-	sz += sprintf(page+sz, " %dk rounding", mddev->chunk_size/1024);
-	return sz;
+	seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
 }
 
 
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Tue Feb 25 02:44:05 2003
+++ b/drivers/md/md.c	Sun Mar 16 22:35:11 2003
@@ -124,9 +124,6 @@
 	{ .ctl_name = 0 }
 };
 
-static void md_recover_arrays(void);
-static mdk_thread_t *md_recovery_thread;
-
 sector_t md_size[MAX_MD_DEVS];
 
 static struct block_device_operations md_fops;
@@ -222,6 +219,7 @@
 	init_MUTEX(&new->reconfig_sem);
 	INIT_LIST_HEAD(&new->disks);
 	INIT_LIST_HEAD(&new->all_mddevs);
+	init_timer(&new->safemode_timer);
 	atomic_set(&new->active, 1);
 	blk_queue_make_request(&new->queue, md_fail_request);
 
@@ -272,40 +270,35 @@
 	return NULL;
 }
 
-static sector_t calc_dev_sboffset(struct block_device *bdev)
+inline static sector_t calc_dev_sboffset(struct block_device *bdev)
 {
 	sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
 	return MD_NEW_SIZE_BLOCKS(size);
 }
 
-static sector_t calc_dev_size(struct block_device *bdev, mddev_t *mddev)
+static sector_t calc_dev_size(mdk_rdev_t *rdev, unsigned chunk_size)
 {
 	sector_t size;
 
-	if (mddev->persistent)
-		size = calc_dev_sboffset(bdev);
-	else
-		size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
-	if (mddev->chunk_size)
-		size &= ~((sector_t)mddev->chunk_size/1024 - 1);
+	size = rdev->sb_offset;
+
+	if (chunk_size)
+		size &= ~((sector_t)chunk_size/1024 - 1);
 	return size;
 }
 
 static sector_t zoned_raid_size(mddev_t *mddev)
 {
-	sector_t mask;
 	mdk_rdev_t * rdev;
 	struct list_head *tmp;
 
 	/*
 	 * do size and offset calculations.
 	 */
-	mask = ~((sector_t)mddev->chunk_size/1024 - 1);
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
-		rdev->size &= mask;
+	ITERATE_RDEV(mddev,rdev,tmp)
 		md_size[mdidx(mddev)] += rdev->size;
-	}
+
 	return 0;
 }
 
@@ -389,7 +382,6 @@
 
 static int read_disk_sb(mdk_rdev_t * rdev)
 {
-	sector_t sb_offset;
 
 	if (!rdev->sb_page) {
 		MD_BUG();
@@ -398,16 +390,8 @@
 	if (rdev->sb_loaded)
 		return 0;
 
-	/*
-	 * Calculate the position of the superblock,
-	 * it's at the end of the disk.
-	 *
-	 * It also happens to be a multiple of 4Kb.
-	 */
-	sb_offset = calc_dev_sboffset(rdev->bdev);
-	rdev->sb_offset = sb_offset;
 
-	if (!sync_page_io(rdev->bdev, sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ))
+	if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ))
 		goto fail;
 	rdev->sb_loaded = 1;
 	return 0;
@@ -486,7 +470,7 @@
  * We rely on user-space to write the initial superblock, and support
  * reading and updating of superblocks.
  * Interface methods are:
- *   int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev)
+ *   int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev, int minor_version)
  *      loads and validates a superblock on dev.
  *      if refdev != NULL, compare superblocks on both devices
  *    Return:
@@ -511,7 +495,7 @@
 struct super_type  {
 	char 		*name;
 	struct module	*owner;
-	int		(*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev);
+	int		(*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version);
 	int		(*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
 	void		(*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
 };
@@ -519,10 +503,20 @@
 /*
  * load_super for 0.90.0 
  */
-static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev)
+static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 {
 	mdp_super_t *sb;
 	int ret;
+	sector_t sb_offset;
+
+	/*
+	 * Calculate the position of the superblock,
+	 * it's at the end of the disk.
+	 *
+	 * It also happens to be a multiple of 4Kb.
+	 */
+	sb_offset = calc_dev_sboffset(rdev->bdev);
+	rdev->sb_offset = sb_offset;
 
 	ret = read_disk_sb(rdev);
 	if (ret) return ret;
@@ -557,6 +551,12 @@
 	}
 
 	rdev->preferred_minor = sb->md_minor;
+	rdev->data_offset = 0;
+
+	if (sb->level == MULTIPATH)
+		rdev->desc_nr = -1;
+	else
+		rdev->desc_nr = sb->this_disk.number;
 
 	if (refdev == 0)
 		ret = 1;
@@ -582,7 +582,7 @@
 		else 
 			ret = 0;
 	}
-
+	rdev->size = calc_dev_size(rdev, sb->chunk_size);
 
  abort:
 	return ret;
@@ -597,7 +597,7 @@
 	mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
 
 	if (mddev->raid_disks == 0) {
-		mddev->major_version = sb->major_version;
+		mddev->major_version = 0;
 		mddev->minor_version = sb->minor_version;
 		mddev->patch_version = sb->patch_version;
 		mddev->persistent = ! sb->not_persistent;
@@ -634,7 +634,6 @@
 			return -EINVAL;
 	}
 	if (mddev->level != LEVEL_MULTIPATH) {
-		rdev->desc_nr = sb->this_disk.number;
 		rdev->raid_disk = -1;
 		rdev->in_sync = rdev->faulty = 0;
 		desc = sb->disks + rdev->desc_nr;
@@ -704,10 +703,8 @@
 		sb->recovery_cp = mddev->recovery_cp;
 		sb->cp_events_hi = (mddev->events>>32);
 		sb->cp_events_lo = (u32)mddev->events;
-		if (mddev->recovery_cp == MaxSector) {
-			printk(KERN_INFO "md: marking sb clean...\n");
+		if (mddev->recovery_cp == MaxSector)
 			sb->state = (1<< MD_SB_CLEAN);
-		}
 	} else
 		sb->recovery_cp = 0;
 
@@ -717,7 +714,7 @@
 	sb->disks[0].state = (1<<MD_DISK_REMOVED);
 	ITERATE_RDEV(mddev,rdev2,tmp) {
 		mdp_disk_t *d;
-		if (rdev2->raid_disk >= 0)
+		if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty)
 			rdev2->desc_nr = rdev2->raid_disk;
 		else
 			rdev2->desc_nr = next_spare++;
@@ -726,7 +723,7 @@
 		d->number = rdev2->desc_nr;
 		d->major = MAJOR(rdev2->bdev->bd_dev);
 		d->minor = MINOR(rdev2->bdev->bd_dev);
-		if (rdev2->raid_disk >= 0)
+		if (rdev2->raid_disk >= 0 && rdev->in_sync && !rdev2->faulty)
 			d->raid_disk = rdev2->raid_disk;
 		else
 			d->raid_disk = rdev2->desc_nr; /* compatibility */
@@ -766,6 +763,210 @@
 	sb->sb_csum = calc_sb_csum(sb);
 }
 
+/*
+ * version 1 superblock
+ */
+
+static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
+{
+	unsigned int disk_csum, csum;
+	int size = 256 + sb->max_dev*2;
+
+	disk_csum = sb->sb_csum;
+	sb->sb_csum = 0;
+	csum = csum_partial((void *)sb, size, 0);
+	sb->sb_csum = disk_csum;
+	return csum;
+}
+
+static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+{
+	struct mdp_superblock_1 *sb;
+	int ret;
+	sector_t sb_offset;
+
+	/*
+	 * Calculate the position of the superblock.
+	 * It is always aligned to a 4K boundary and
+	 * depeding on minor_version, it can be:
+	 * 0: At least 8K, but less than 12K, from end of device
+	 * 1: At start of device
+	 * 2: 4K from start of device.
+	 */
+	switch(minor_version) {
+	case 0:
+		sb_offset = rdev->bdev->bd_inode->i_size >> 9;
+		sb_offset -= 8*2;
+		sb_offset &= ~(4*2);
+		/* convert from sectors to K */
+		sb_offset /= 2;
+		break;
+	case 1:
+		sb_offset = 0;
+		break;
+	case 2:
+		sb_offset = 4;
+		break;
+	default:
+		return -EINVAL;
+	}
+	rdev->sb_offset = sb_offset;
+
+	ret = read_disk_sb(rdev);
+	if (ret) return ret;
+
+
+	sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+
+	if (sb->magic != cpu_to_le32(MD_SB_MAGIC) ||
+	    sb->major_version != cpu_to_le32(1) ||
+	    le32_to_cpu(sb->max_dev) > (4096-256)/2 ||
+	    le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) ||
+	    sb->feature_map != 0)
+		return -EINVAL;
+
+	if (calc_sb_1_csum(sb) != sb->sb_csum) {
+		printk(BAD_CSUM, bdev_partition_name(rdev->bdev));
+		return -EINVAL;
+	}
+	rdev->preferred_minor = 0xffff;
+	rdev->data_offset = le64_to_cpu(sb->data_offset);
+
+	if (refdev == 0)
+		return 1;
+	else {
+		__u64 ev1, ev2;
+		struct mdp_superblock_1 *refsb = 
+			(struct mdp_superblock_1*)page_address(refdev->sb_page);
+
+		if (memcmp(sb->set_uuid, refsb->set_uuid, 16) != 0 ||
+		    sb->level != refsb->level ||
+		    sb->layout != refsb->layout ||
+		    sb->chunksize != refsb->chunksize) {
+			printk(KERN_WARNING "md: %s has strangely different superblock to %s\n",
+			       bdev_partition_name(rdev->bdev),
+			       bdev_partition_name(refdev->bdev));
+			return -EINVAL;
+		}
+		ev1 = le64_to_cpu(sb->events);
+		ev2 = le64_to_cpu(refsb->events);
+
+		if (ev1 > ev2)
+			return 1;
+	}
+	if (minor_version) 
+		rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2;
+	else
+		rdev->size = rdev->sb_offset;
+	if (rdev->size < le64_to_cpu(sb->data_size)/2)
+		return -EINVAL;
+	rdev->size = le64_to_cpu(sb->data_size)/2;
+	if (le32_to_cpu(sb->chunksize))
+		rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1);
+	return 0;
+}
+
+static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+
+	if (mddev->raid_disks == 0) {
+		mddev->major_version = 1;
+		mddev->minor_version = 0;
+		mddev->patch_version = 0;
+		mddev->persistent = 1;
+		mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
+		mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
+		mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
+		mddev->level = le32_to_cpu(sb->level);
+		mddev->layout = le32_to_cpu(sb->layout);
+		mddev->raid_disks = le32_to_cpu(sb->raid_disks);
+		mddev->size = (u32)le64_to_cpu(sb->size);
+		mddev->events = le64_to_cpu(sb->events);
+		
+		mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
+		memcpy(mddev->uuid, sb->set_uuid, 16);
+
+		mddev->max_disks =  (4096-256)/2;
+	} else {
+		__u64 ev1;
+		ev1 = le64_to_cpu(sb->events);
+		++ev1;
+		if (ev1 < mddev->events)
+			return -EINVAL;
+	}
+
+	if (mddev->level != LEVEL_MULTIPATH) {
+		int role;
+		rdev->desc_nr = le32_to_cpu(sb->dev_number);
+		role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
+		switch(role) {
+		case 0xffff: /* spare */
+			rdev->in_sync = 0;
+			rdev->faulty = 0;
+			rdev->raid_disk = -1;
+			break;
+		case 0xfffe: /* faulty */
+			rdev->in_sync = 0;
+			rdev->faulty = 1;
+			rdev->raid_disk = -1;
+			break;
+		default:
+			rdev->in_sync = 1;
+			rdev->faulty = 0;
+			rdev->raid_disk = role;
+			break;
+		}
+	}
+	return 0;
+}
+
+static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	struct mdp_superblock_1 *sb;
+	struct list_head *tmp;
+	mdk_rdev_t *rdev2;
+	int max_dev, i;
+	/* make rdev->sb match mddev and rdev data. */
+
+	sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+
+	sb->feature_map = 0;
+	sb->pad0 = 0;
+	memset(sb->pad1, 0, sizeof(sb->pad1));
+	memset(sb->pad2, 0, sizeof(sb->pad2));
+	memset(sb->pad3, 0, sizeof(sb->pad3));
+
+	sb->utime = cpu_to_le64((__u64)mddev->utime);
+	sb->events = cpu_to_le64(mddev->events);
+	if (mddev->in_sync)
+		sb->resync_offset = cpu_to_le64(mddev->recovery_cp);
+	else
+		sb->resync_offset = cpu_to_le64(0);
+
+	max_dev = 0;
+	ITERATE_RDEV(mddev,rdev2,tmp)
+		if (rdev2->desc_nr > max_dev)
+			max_dev = rdev2->desc_nr;
+	
+	sb->max_dev = max_dev;
+	for (i=0; i<max_dev;i++)
+		sb->dev_roles[max_dev] = cpu_to_le16(0xfffe);
+	
+	ITERATE_RDEV(mddev,rdev2,tmp) {
+		i = rdev2->desc_nr;
+		if (rdev2->faulty)
+			sb->dev_roles[i] = cpu_to_le16(0xfffe);
+		else if (rdev2->in_sync)
+			sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk);
+		else
+			sb->dev_roles[i] = cpu_to_le16(0xffff);
+	}
+
+	sb->recovery_offset = cpu_to_le64(0); /* not supported yet */
+}
+
+
 struct super_type super_types[] = {
 	[0] = {
 		.name	= "0.90.0",
@@ -774,9 +975,14 @@
 		.validate_super	= super_90_validate,
 		.sync_super	= super_90_sync,
 	},
+	[1] = {
+		.name	= "md-1",
+		.owner	= THIS_MODULE,
+		.load_super	= super_1_load,
+		.validate_super	= super_1_validate,
+		.sync_super	= super_1_sync,
+	},
 };
-
-
 	
 static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev)
 {
@@ -804,13 +1010,13 @@
 
 static LIST_HEAD(pending_raid_disks);
 
-static void bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
+static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 {
 	mdk_rdev_t *same_pdev;
 
 	if (rdev->mddev) {
 		MD_BUG();
-		return;
+		return -EINVAL;
 	}
 	same_pdev = match_dev_unit(mddev, rdev);
 	if (same_pdev)
@@ -820,9 +1026,25 @@
 			mdidx(mddev), bdev_partition_name(rdev->bdev),
 				bdev_partition_name(same_pdev->bdev));
 
+	/* Verify rdev->desc_nr is unique.
+	 * If it is -1, assign a free number, else
+	 * check number is not in use
+	 */
+	if (rdev->desc_nr < 0) {
+		int choice = 0;
+		if (mddev->pers) choice = mddev->raid_disks;
+		while (find_rdev_nr(mddev, choice))
+			choice++;
+		rdev->desc_nr = choice;
+	} else {
+		if (find_rdev_nr(mddev, rdev->desc_nr))
+			return -EBUSY;
+	}
+			
 	list_add(&rdev->same_set, &mddev->disks);
 	rdev->mddev = mddev;
 	printk(KERN_INFO "md: bind<%s>\n", bdev_partition_name(rdev->bdev));
+	return 0;
 }
 
 static void unbind_rdev_from_array(mdk_rdev_t * rdev)
@@ -910,6 +1132,7 @@
 	if (!list_empty(&mddev->disks))
 		MD_BUG();
 	mddev->raid_disks = 0;
+	mddev->major_version = 0;
 }
 
 #undef BAD_CSUM
@@ -994,8 +1217,6 @@
 
 static int write_disk_sb(mdk_rdev_t * rdev)
 {
-	sector_t sb_offset;
-	sector_t size;
 
 	if (!rdev->sb_loaded) {
 		MD_BUG();
@@ -1006,35 +1227,12 @@
 		return 1;
 	}
 
-	sb_offset = calc_dev_sboffset(rdev->bdev);
-	if (rdev->sb_offset != sb_offset) {
-		printk(KERN_INFO "%s's sb offset has changed from %llu to %llu, skipping\n",
-		       bdev_partition_name(rdev->bdev), 
-		    (unsigned long long)rdev->sb_offset, 
-		    (unsigned long long)sb_offset);
-		goto skip;
-	}
-	/*
-	 * If the disk went offline meanwhile and it's just a spare, then
-	 * its size has changed to zero silently, and the MD code does
-	 * not yet know that it's faulty.
-	 */
-	size = calc_dev_size(rdev->bdev, rdev->mddev);
-	if (size != rdev->size) {
-		printk(KERN_INFO "%s's size has changed from %llu to %llu since import, skipping\n",
-		       bdev_partition_name(rdev->bdev),
-		       (unsigned long long)rdev->size, 
-		       (unsigned long long)size);
-		goto skip;
-	}
-
-	printk(KERN_INFO "(write) %s's sb offset: %llu\n", bdev_partition_name(rdev->bdev), (unsigned long long)sb_offset);
+	dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", bdev_partition_name(rdev->bdev),
+	       (unsigned long long)rdev->sb_offset);
+  
+	if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE))
+		return 0;
 
-	if (!sync_page_io(rdev->bdev, sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE))
-		goto fail;
-skip:
-	return 0;
-fail:
 	printk("md: write_disk_sb failed for device %s\n", bdev_partition_name(rdev->bdev));
 	return 1;
 }
@@ -1045,7 +1243,8 @@
 	struct list_head *tmp;
 
 	ITERATE_RDEV(mddev,rdev,tmp) {
-		super_90_sync(mddev, rdev);
+		super_types[mddev->major_version].
+			sync_super(mddev, rdev);
 		rdev->sb_loaded = 1;
 	}
 }
@@ -1079,20 +1278,20 @@
 	if (!mddev->persistent)
 		return;
 
-	printk(KERN_INFO "md: updating md%d RAID superblock on device (in sync %d)\n",
+	dprintk(KERN_INFO "md: updating md%d RAID superblock on device (in sync %d)\n",
 					mdidx(mddev),mddev->in_sync);
 
 	err = 0;
 	ITERATE_RDEV(mddev,rdev,tmp) {
-		printk(KERN_INFO "md: ");
+		dprintk(KERN_INFO "md: ");
 		if (rdev->faulty)
-			printk("(skipping faulty ");
+			dprintk("(skipping faulty ");
 
-		printk("%s ", bdev_partition_name(rdev->bdev));
+		dprintk("%s ", bdev_partition_name(rdev->bdev));
 		if (!rdev->faulty) {
 			err += write_disk_sb(rdev);
 		} else
-			printk(")\n");
+			dprintk(")\n");
 		if (!err && mddev->level == LEVEL_MULTIPATH)
 			/* only need to write one superblock... */
 			break;
@@ -1107,7 +1306,7 @@
 }
 
 /*
- * Import a device. If 'on_disk', then sanity check the superblock
+ * Import a device. If 'super_format' >= 0, then sanity check the superblock
  *
  * mark the device faulty if:
  *
@@ -1116,7 +1315,7 @@
  *
  * a faulty rdev _never_ has rdev->sb set.
  */
-static mdk_rdev_t *md_import_device(dev_t newdev, int on_disk)
+static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
 	int err;
 	mdk_rdev_t *rdev;
@@ -1141,6 +1340,7 @@
 	rdev->desc_nr = -1;
 	rdev->faulty = 0;
 	rdev->in_sync = 0;
+	rdev->data_offset = 0;
 	atomic_set(&rdev->nr_pending, 0);
 
 	size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -1152,8 +1352,9 @@
 		goto abort_free;
 	}
 
-	if (on_disk) {
-		err = super_90_load(rdev, NULL);
+	if (super_format >= 0) {
+		err = super_types[super_format].
+			load_super(rdev, NULL, super_minor);
 		if (err == -EINVAL) {
 			printk(KERN_WARNING "md: %s has invalid sb, not importing!\n",
 			       bdev_partition_name(rdev->bdev));
@@ -1206,7 +1407,8 @@
 
 	freshest = NULL;
 	ITERATE_RDEV(mddev,rdev,tmp)
-		switch (super_90_load(rdev, freshest)) {
+		switch (super_types[mddev->major_version].
+			load_super(rdev, freshest, mddev->minor_version)) {
 		case 1:
 			freshest = rdev;
 			break;
@@ -1218,12 +1420,14 @@
 		}
 
 
-	super_90_validate(mddev, freshest);
+	super_types[mddev->major_version].
+		validate_super(mddev, freshest);
 
 	i = 0;
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		if (rdev != freshest)
-			if (super_90_validate(mddev, rdev)) {
+			if (super_types[mddev->major_version].
+			    validate_super(mddev, rdev)) {
 				printk(KERN_WARNING "md: kicking non-fresh %s from array!\n",
 				       bdev_partition_name(rdev->bdev));
 				kick_rdev_from_array(rdev);
@@ -1278,11 +1482,6 @@
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		if (rdev->faulty)
 			continue;
-		if (rdev->size) {
-			MD_BUG();
-			continue;
-		}
-		rdev->size = calc_dev_size(rdev->bdev, mddev);
 		if (rdev->size < mddev->chunk_size / 1024) {
 			printk(KERN_WARNING
 				"md: Dev %s smaller than chunk_size: %lluk < %dk\n",
@@ -1380,6 +1579,16 @@
 	return NULL;
 }
 
+void md_wakeup_thread(mdk_thread_t *thread);
+
+static void md_safemode_timeout(unsigned long data)
+{
+	mddev_t *mddev = (mddev_t *) data;
+
+	mddev->safemode = 1;
+	md_wakeup_thread(mddev->thread);
+}
+
 #define TOO_BIG_CHUNKSIZE KERN_ERR \
 "too big chunk_size: %d > %d\n"
 
@@ -1521,13 +1730,14 @@
 	}
  	atomic_set(&mddev->writes_pending,0);
 	mddev->safemode = 0;
-	if (mddev->pers->sync_request)
-		mddev->in_sync = 0;
-	else
-		mddev->in_sync = 1;
+	mddev->safemode_timer.function = md_safemode_timeout;
+	mddev->safemode_timer.data = (unsigned long) mddev;
+	mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */
+	mddev->in_sync = 1;
 	
 	md_update_sb(mddev);
-	md_recover_arrays();
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	md_wakeup_thread(mddev->thread);
 	set_capacity(disk, md_size[mdidx(mddev)]<<1);
 	return (0);
 }
@@ -1553,7 +1763,6 @@
 			goto out;
 
 		mddev->safemode = 0;
-		mddev->in_sync = 0;
 		md_update_sb(mddev);
 		mddev->ro = 0;
 		set_disk_ro(disk, 0);
@@ -1563,7 +1772,8 @@
 		/*
 		 * Kick recovery or resync if necessary
 		 */
-		md_recover_arrays();
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+		md_wakeup_thread(mddev->thread);
 		err = 0;
 	} else {
 		printk(KERN_ERR "md: md%d has no personality assigned.\n",
@@ -1593,12 +1803,13 @@
 
 	if (mddev->pers) {
 		if (mddev->sync_thread) {
-			if (mddev->recovery_running > 0)
-				mddev->recovery_running = -1;
+			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 			md_unregister_thread(mddev->sync_thread);
 			mddev->sync_thread = NULL;
 		}
 
+		del_timer_sync(&mddev->safemode_timer);
+
 		invalidate_device(mk_kdev(disk->major, disk->first_minor), 1);
 
 		if (ro) {
@@ -1699,7 +1910,7 @@
 		printk(KERN_INFO "md: considering %s ...\n", bdev_partition_name(rdev0->bdev));
 		INIT_LIST_HEAD(&candidates);
 		ITERATE_RDEV_PENDING(rdev,tmp)
-			if (super_90_load(rdev, rdev0) >= 0) {
+			if (super_90_load(rdev, rdev0, 0) >= 0) {
 				printk(KERN_INFO "md:  adding %s ...\n", bdev_partition_name(rdev->bdev));
 				list_move(&rdev->same_set, &candidates);
 			}
@@ -1717,7 +1928,8 @@
 		if (mddev_lock(mddev)) 
 			printk(KERN_WARNING "md: md%d locked, cannot run\n",
 			       mdidx(mddev));
-		else if (mddev->raid_disks || !list_empty(&mddev->disks)) {
+		else if (mddev->raid_disks || mddev->major_version
+			 || !list_empty(&mddev->disks)) {
 			printk(KERN_WARNING "md: md%d already running, cannot run %s\n",
 			       mdidx(mddev), bdev_partition_name(rdev0->bdev));
 			mddev_unlock(mddev);
@@ -1725,7 +1937,8 @@
 			printk(KERN_INFO "md: created md%d\n", mdidx(mddev));
 			ITERATE_RDEV_GENERIC(candidates,rdev,tmp) {
 				list_del_init(&rdev->same_set);
-				bind_rdev_to_array(rdev, mddev);
+				if (bind_rdev_to_array(rdev, mddev))
+					export_rdev(rdev);
 			}
 			autorun_array(mddev);
 			mddev_unlock(mddev);
@@ -1778,7 +1991,7 @@
 	mdp_super_t *sb = NULL;
 	mdk_rdev_t *start_rdev = NULL, *rdev;
 
-	start_rdev = md_import_device(startdev, 1);
+	start_rdev = md_import_device(startdev, 0, 0);
 	if (IS_ERR(start_rdev)) {
 		printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev));
 		return err;
@@ -1812,7 +2025,7 @@
 			continue;
 		if (dev == startdev)
 			continue;
-		rdev = md_import_device(dev, 1);
+		rdev = md_import_device(dev, 0, 0);
 		if (IS_ERR(rdev)) {
 			printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n",
 			       partition_name(dev));
@@ -1875,9 +2088,8 @@
 	}
 
 	info.major_version = mddev->major_version;
-	info.major_version = mddev->major_version;
 	info.minor_version = mddev->minor_version;
-	info.patch_version = mddev->patch_version;
+	info.patch_version = 1;
 	info.ctime         = mddev->ctime;
 	info.level         = mddev->level;
 	info.size          = mddev->size;
@@ -1888,7 +2100,7 @@
 
 	info.utime         = mddev->utime;
 	info.state         = 0;
-	if (mddev->recovery_cp == MaxSector)
+	if (mddev->in_sync)
 		info.state = (1<<MD_SB_CLEAN);
 	info.active_disks  = active;
 	info.working_disks = working;
@@ -1943,13 +2155,13 @@
 
 static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
 {
-	sector_t size;
 	mdk_rdev_t *rdev;
 	dev_t dev;
 	dev = MKDEV(info->major,info->minor);
 	if (!mddev->raid_disks) {
+		int err;
 		/* expecting a device which has a superblock */
-		rdev = md_import_device(dev, 1);
+		rdev = md_import_device(dev, mddev->major_version, mddev->minor_version);
 		if (IS_ERR(rdev)) {
 			printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev));
 			return PTR_ERR(rdev);
@@ -1957,7 +2169,8 @@
 		if (!list_empty(&mddev->disks)) {
 			mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
 							mdk_rdev_t, same_set);
-			int err = super_90_load(rdev, rdev0);
+			int err = super_types[mddev->major_version]
+				.load_super(rdev, rdev0, mddev->minor_version);
 			if (err < 0) {
 				printk(KERN_WARNING "md: %s has different UUID to %s\n",
 				       bdev_partition_name(rdev->bdev), bdev_partition_name(rdev0->bdev));
@@ -1965,12 +2178,52 @@
 				return -EINVAL;
 			}
 		}
-		bind_rdev_to_array(rdev, mddev);
-		return 0;
+		err = bind_rdev_to_array(rdev, mddev);
+		if (err)
+			export_rdev(rdev);
+		return err;
+	}
+
+	/*
+	 * add_new_disk can be used once the array is assembled
+	 * to add "hot spares".  They must already have a superblock
+	 * written
+	 */
+	if (mddev->pers) {
+		int err;
+		if (!mddev->pers->hot_add_disk) {
+			printk(KERN_WARNING "md%d: personality does not support diskops!\n",
+			       mdidx(mddev));
+			return -EINVAL;
+		}
+		rdev = md_import_device(dev, mddev->major_version,
+					mddev->minor_version);
+		if (IS_ERR(rdev)) {
+			printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev));
+			return PTR_ERR(rdev);
+		}
+		rdev->in_sync = 0; /* just to be sure */
+		rdev->raid_disk = -1;
+		err = bind_rdev_to_array(rdev, mddev);
+		if (err)
+			export_rdev(rdev);
+		if (mddev->thread)
+			md_wakeup_thread(mddev->thread);
+		return err;
+	}
+
+	/* otherwise, add_new_disk is only allowed
+	 * for major_version==0 superblocks
+	 */
+	if (mddev->major_version != 0) {
+		printk(KERN_WARNING "md%d: ADD_NEW_DISK not supported\n",
+		       mdidx(mddev));
+		return -EINVAL;
 	}
 
 	if (!(info->state & (1<<MD_DISK_FAULTY))) {
-		rdev = md_import_device (dev, 0);
+		int err;
+		rdev = md_import_device (dev, -1, 0);
 		if (IS_ERR(rdev)) {
 			printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev));
 			return PTR_ERR(rdev);
@@ -1987,16 +2240,21 @@
 		else
 			rdev->in_sync = 0;
 
-		bind_rdev_to_array(rdev, mddev);
+		err = bind_rdev_to_array(rdev, mddev);
+		if (err) {
+			export_rdev(rdev);
+			return err;
+		}
 
-		if (!mddev->persistent)
+		if (!mddev->persistent) {
 			printk(KERN_INFO "md: nonpersistent superblock ...\n");
+			rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
+		} else 
+			rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+		rdev->size = calc_dev_size(rdev, mddev->chunk_size);
 
-		size = calc_dev_size(rdev->bdev, mddev);
-		rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
-
-		if (!mddev->size || (mddev->size > size))
-			mddev->size = size;
+		if (!mddev->size || (mddev->size > rdev->size))
+			mddev->size = rdev->size;
 	}
 
 	return 0;
@@ -2066,7 +2324,7 @@
 
 static int hot_add_disk(mddev_t * mddev, dev_t dev)
 {
-	int i, err;
+	int err;
 	unsigned int size;
 	mdk_rdev_t *rdev;
 
@@ -2076,19 +2334,26 @@
 	printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n",
 		partition_name(dev), mdidx(mddev));
 
+	if (mddev->major_version != 0) {
+		printk(KERN_WARNING "md%d: HOT_ADD may only be used with version-0 superblocks.\n",
+		       mdidx(mddev));
+		return -EINVAL;
+	}
 	if (!mddev->pers->hot_add_disk) {
 		printk(KERN_WARNING "md%d: personality does not support diskops!\n",
 		       mdidx(mddev));
 		return -EINVAL;
 	}
 
-	rdev = md_import_device (dev, 0);
+	rdev = md_import_device (dev, -1, 0);
 	if (IS_ERR(rdev)) {
 		printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev));
 		return -EINVAL;
 	}
 
-	size = calc_dev_size(rdev->bdev, mddev);
+	rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+	size = calc_dev_size(rdev, mddev->chunk_size);
+	rdev->size = size;
 
 	if (size < mddev->size) {
 		printk(KERN_WARNING "md%d: disk size %llu blocks < array size %llu\n",
@@ -2105,27 +2370,21 @@
 		goto abort_export;
 	}
 	rdev->in_sync = 0;
+	rdev->desc_nr = -1;
 	bind_rdev_to_array(rdev, mddev);
 
 	/*
 	 * The rest should better be atomic, we can have disk failures
 	 * noticed in interrupt contexts ...
 	 */
-	rdev->size = size;
-	rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
 
-	for (i = mddev->raid_disks; i < mddev->max_disks; i++)
-		if (find_rdev_nr(mddev,i)==NULL)
-			break;
-
-	if (i == mddev->max_disks) {
+	if (rdev->desc_nr == mddev->max_disks) {
 		printk(KERN_WARNING "md%d: can not hot-add to full array!\n",
 		       mdidx(mddev));
 		err = -EBUSY;
 		goto abort_unbind_export;
 	}
 
-	rdev->desc_nr = i;
 	rdev->raid_disk = -1;
 
 	md_update_sb(mddev);
@@ -2134,7 +2393,8 @@
 	 * Kick recovery, maybe this spare has to be added to the
 	 * array immediately.
 	 */
-	md_recover_arrays();
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	md_wakeup_thread(mddev->thread);
 
 	return 0;
 
@@ -2146,9 +2406,37 @@
 	return err;
 }
 
+/*
+ * set_array_info is used two different ways
+ * The original usage is when creating a new array.
+ * In this usage, raid_disks is > = and it together with
+ *  level, size, not_persistent,layout,chunksize determine the
+ *  shape of the array.
+ *  This will always create an array with a type-0.90.0 superblock.
+ * The newer usage is when assembling an array.
+ *  In this case raid_disks will be 0, and the major_version field is
+ *  use to determine which style super-blocks are to be found on the devices.
+ *  The minor and patch _version numbers are also kept incase the
+ *  super_block handler wishes to interpret them.
+ */
 static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
 {
 
+	if (info->raid_disks == 0) {
+		/* just setting version number for superblock loading */
+		if (info->major_version < 0 ||
+		    info->major_version >= sizeof(super_types)/sizeof(super_types[0]) ||
+		    super_types[info->major_version].name == NULL) {
+			/* maybe try to auto-load a module? */
+			printk(KERN_INFO "md: superblock version %d not known\n",
+			       info->major_version);
+			return -EINVAL;
+		}
+		mddev->major_version = info->major_version;
+		mddev->minor_version = info->minor_version;
+		mddev->patch_version = info->patch_version;
+		return 0;
+	}
 	mddev->major_version = MD_MAJOR_VERSION;
 	mddev->minor_version = MD_MINOR_VERSION;
 	mddev->patch_version = MD_PATCHLEVEL_VERSION;
@@ -2169,6 +2457,7 @@
 	mddev->layout        = info->layout;
 	mddev->chunk_size    = info->chunk_size;
 
+	mddev->max_disks     = MD_SB_DISKS;
 
 
 	/*
@@ -2282,9 +2571,11 @@
 				err = -EBUSY;
 				goto abort_unlock;
 			}
-			if (arg) {
+			{
 				mdu_array_info_t info;
-				if (copy_from_user(&info, (void*)arg, sizeof(info))) {
+				if (!arg)
+					memset(&info, 0, sizeof(info));
+				else if (copy_from_user(&info, (void*)arg, sizeof(info))) {
 					err = -EFAULT;
 					goto abort_unlock;
 				}
@@ -2473,12 +2764,6 @@
 	.ioctl		= md_ioctl,
 };
 
-
-static inline void flush_curr_signals(void)
-{
-	flush_signals(current);
-}
-
 int md_thread(void * arg)
 {
 	mdk_thread_t *thread = arg;
@@ -2489,7 +2774,7 @@
 	 * Detach thread
 	 */
 
-	daemonize(thread->name);
+	daemonize(thread->name, mdidx(thread->mddev));
 
 	current->exit_signal = SIGCHLD;
 	allow_signal(SIGKILL);
@@ -2510,7 +2795,7 @@
 
 	complete(thread->event);
 	while (thread->run) {
-		void (*run)(void *data);
+		void (*run)(mddev_t *);
 
 		wait_event_interruptible(thread->wqueue,
 					 test_bit(THREAD_WAKEUP, &thread->flags));
@@ -2521,11 +2806,11 @@
 
 		run = thread->run;
 		if (run) {
-			run(thread->data);
+			run(thread->mddev);
 			blk_run_queues();
 		}
 		if (signal_pending(current))
-			flush_curr_signals();
+			flush_signals(current);
 	}
 	complete(thread->event);
 	return 0;
@@ -2533,13 +2818,15 @@
 
 void md_wakeup_thread(mdk_thread_t *thread)
 {
-	dprintk("md: waking up MD thread %p.\n", thread);
-	set_bit(THREAD_WAKEUP, &thread->flags);
-	wake_up(&thread->wqueue);
+	if (thread) {
+		dprintk("md: waking up MD thread %p.\n", thread);
+		set_bit(THREAD_WAKEUP, &thread->flags);
+		wake_up(&thread->wqueue);
+	}
 }
 
-mdk_thread_t *md_register_thread(void (*run) (void *),
-						void *data, const char *name)
+mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+				 const char *name)
 {
 	mdk_thread_t *thread;
 	int ret;
@@ -2556,7 +2843,7 @@
 	init_completion(&event);
 	thread->event = &event;
 	thread->run = run;
-	thread->data = data;
+	thread->mddev = mddev;
 	thread->name = name;
 	ret = kernel_thread(md_thread, thread, 0);
 	if (ret < 0) {
@@ -2591,16 +2878,6 @@
 	kfree(thread);
 }
 
-static void md_recover_arrays(void)
-{
-	if (!md_recovery_thread) {
-		MD_BUG();
-		return;
-	}
-	md_wakeup_thread(md_recovery_thread);
-}
-
-
 void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
@@ -2618,33 +2895,34 @@
 	if (!mddev->pers->error_handler)
 		return;
 	mddev->pers->error_handler(mddev,rdev);
-	md_recover_arrays();
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	md_wakeup_thread(mddev->thread);
 }
 
-static int status_unused(char * page)
+/* seq_file implementation /proc/mdstat */
+
+static void status_unused(struct seq_file *seq)
 {
-	int sz = 0, i = 0;
+	int i = 0;
 	mdk_rdev_t *rdev;
 	struct list_head *tmp;
 
-	sz += sprintf(page + sz, "unused devices: ");
+	seq_printf(seq, "unused devices: ");
 
 	ITERATE_RDEV_PENDING(rdev,tmp) {
 		i++;
-		sz += sprintf(page + sz, "%s ",
+		seq_printf(seq, "%s ",
 			      bdev_partition_name(rdev->bdev));
 	}
 	if (!i)
-		sz += sprintf(page + sz, "<none>");
+		seq_printf(seq, "<none>");
 
-	sz += sprintf(page + sz, "\n");
-	return sz;
+	seq_printf(seq, "\n");
 }
 
 
-static int status_resync(char * page, mddev_t * mddev)
+static void status_resync(struct seq_file *seq, mddev_t * mddev)
 {
-	int sz = 0;
 	unsigned long max_blocks, resync, res, dt, db, rt;
 
 	resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
@@ -2655,21 +2933,22 @@
 	 */
 	if (!max_blocks) {
 		MD_BUG();
-		return 0;
+		return;
 	}
 	res = (resync/1024)*1000/(max_blocks/1024 + 1);
 	{
 		int i, x = res/50, y = 20-x;
-		sz += sprintf(page + sz, "[");
+		seq_printf(seq, "[");
 		for (i = 0; i < x; i++)
-			sz += sprintf(page + sz, "=");
-		sz += sprintf(page + sz, ">");
+			seq_printf(seq, "=");
+		seq_printf(seq, ">");
 		for (i = 0; i < y; i++)
-			sz += sprintf(page + sz, ".");
-		sz += sprintf(page + sz, "] ");
+			seq_printf(seq, ".");
+		seq_printf(seq, "] ");
 	}
-	sz += sprintf(page + sz, " %s =%3lu.%lu%% (%lu/%lu)",
-		      (mddev->spares ? "recovery" : "resync"),
+	seq_printf(seq, " %s =%3lu.%lu%% (%lu/%lu)",
+		      (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ?
+		       "resync" : "recovery"),
 		      res/10, res % 10, resync, max_blocks);
 
 	/*
@@ -2686,44 +2965,110 @@
 	db = resync - (mddev->resync_mark_cnt/2);
 	rt = (dt * ((max_blocks-resync) / (db/100+1)))/100;
 
-	sz += sprintf(page + sz, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
+	seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
 
-	sz += sprintf(page + sz, " speed=%ldK/sec", db/dt);
+	seq_printf(seq, " speed=%ldK/sec", db/dt);
+}
 
-	return sz;
+static void *md_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	struct list_head *tmp;
+	loff_t l = *pos;
+	mddev_t *mddev;
+
+	if (l > 0x10000)
+		return NULL;
+	if (!l--)
+		/* header */
+		return (void*)1;
+
+	spin_lock(&all_mddevs_lock);
+	list_for_each(tmp,&all_mddevs)
+		if (!l--) {
+			mddev = list_entry(tmp, mddev_t, all_mddevs);
+			mddev_get(mddev);
+			spin_unlock(&all_mddevs_lock);
+			return mddev;
+		}
+	spin_unlock(&all_mddevs_lock);
+	return (void*)2;/* tail */
 }
 
-static int md_status_read_proc(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
+static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	int sz = 0, j;
+	struct list_head *tmp;
+	mddev_t *next_mddev, *mddev = v;
+	
+	++*pos;
+	if (v == (void*)2)
+		return NULL;
+
+	spin_lock(&all_mddevs_lock);
+	if (v == (void*)1)
+		tmp = all_mddevs.next;
+	else
+		tmp = mddev->all_mddevs.next;
+	if (tmp != &all_mddevs)
+		next_mddev = mddev_get(list_entry(tmp,mddev_t,all_mddevs));
+	else {
+		next_mddev = (void*)2;
+		*pos = 0x10000;
+	}		
+	spin_unlock(&all_mddevs_lock);
+
+	if (v != (void*)1)
+		mddev_put(mddev);
+	return next_mddev;
+
+}
+
+static void md_seq_stop(struct seq_file *seq, void *v)
+{
+	mddev_t *mddev = v;
+
+	if (mddev && v != (void*)1 && v != (void*)2)
+		mddev_put(mddev);
+}
+
+static int md_seq_show(struct seq_file *seq, void *v)
+{
+	mddev_t *mddev = v;
 	sector_t size;
-	struct list_head *tmp, *tmp2;
+	struct list_head *tmp2;
 	mdk_rdev_t *rdev;
-	mddev_t *mddev;
+	int i;
 
-	sz += sprintf(page + sz, "Personalities : ");
-	for (j = 0; j < MAX_PERSONALITY; j++)
-	if (pers[j])
-		sz += sprintf(page+sz, "[%s] ", pers[j]->name);
+	if (v == (void*)1) {
+		seq_printf(seq, "Personalities : ");
+		for (i = 0; i < MAX_PERSONALITY; i++)
+			if (pers[i])
+				seq_printf(seq, "[%s] ", pers[i]->name);
 
-	sz += sprintf(page+sz, "\n");
+		seq_printf(seq, "\n");
+		return 0;
+	}
+	if (v == (void*)2) {
+		status_unused(seq);
+		return 0;
+	}
 
-	ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) {
-		sz += sprintf(page + sz, "md%d : %sactive", mdidx(mddev),
+	if (mddev_lock(mddev)!=0) 
+		return -EINTR;
+	if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
+		seq_printf(seq, "md%d : %sactive", mdidx(mddev),
 						mddev->pers ? "" : "in");
 		if (mddev->pers) {
 			if (mddev->ro)
-				sz += sprintf(page + sz, " (read-only)");
-			sz += sprintf(page + sz, " %s", mddev->pers->name);
+				seq_printf(seq, " (read-only)");
+			seq_printf(seq, " %s", mddev->pers->name);
 		}
 
 		size = 0;
 		ITERATE_RDEV(mddev,rdev,tmp2) {
-			sz += sprintf(page + sz, " %s[%d]",
+			seq_printf(seq, " %s[%d]",
 				bdev_partition_name(rdev->bdev), rdev->desc_nr);
 			if (rdev->faulty) {
-				sz += sprintf(page + sz, "(F)");
+				seq_printf(seq, "(F)");
 				continue;
 			}
 			size += rdev->size;
@@ -2731,34 +3076,50 @@
 
 		if (!list_empty(&mddev->disks)) {
 			if (mddev->pers)
-				sz += sprintf(page + sz, "\n      %llu blocks",
+				seq_printf(seq, "\n      %llu blocks",
 						 (unsigned long long)md_size[mdidx(mddev)]);
 			else
-				sz += sprintf(page + sz, "\n      %llu blocks", (unsigned long long)size);
+				seq_printf(seq, "\n      %llu blocks", (unsigned long long)size);
 		}
 
-		if (!mddev->pers) {
-			sz += sprintf(page+sz, "\n");
-			mddev_unlock(mddev);
-			continue;
+		if (mddev->pers) {
+			mddev->pers->status (seq, mddev);
+	 		seq_printf(seq, "\n      ");
+			if (mddev->curr_resync > 2)
+				status_resync (seq, mddev);
+			else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
+				seq_printf(seq, "	resync=DELAYED");
 		}
 
-		sz += mddev->pers->status (page+sz, mddev);
+		seq_printf(seq, "\n");
+	}
+	mddev_unlock(mddev);
+	
+	return 0;
+}
 
-		sz += sprintf(page+sz, "\n      ");
-		if (mddev->curr_resync > 2)
-			sz += status_resync (page+sz, mddev);
-		else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
-				sz += sprintf(page + sz, "	resync=DELAYED");
+static struct seq_operations md_seq_ops = {
+	.start  = md_seq_start,
+	.next   = md_seq_next,
+	.stop   = md_seq_stop,
+	.show   = md_seq_show,
+};
 
-		sz += sprintf(page + sz, "\n");
-		mddev_unlock(mddev);
-	}
-	sz += status_unused(page + sz);
+static int md_seq_open(struct inode *inode, struct file *file)
+{
+	int error;
 
-	return sz;
+	error = seq_open(file, &md_seq_ops);
+	return error;
 }
 
+static struct file_operations md_seq_fops = {
+	.open           = md_seq_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release	= seq_release,
+};
+
 int register_md_personality(int pnum, mdk_personality_t *p)
 {
 	if (pnum >= MAX_PERSONALITY) {
@@ -2803,7 +3164,9 @@
 	idle = 1;
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
-		curr_events = disk->read_sectors + disk->write_sectors - disk->sync_io;
+		curr_events = disk_stat_read(disk, read_sectors) + 
+				disk_stat_read(disk, write_sectors) - 
+				disk->sync_io;
 		if ((curr_events - rdev->last_events) > 32) {
 			rdev->last_events = curr_events;
 			idle = 0;
@@ -2818,9 +3181,8 @@
 	atomic_sub(blocks, &mddev->recovery_active);
 	wake_up(&mddev->recovery_wait);
 	if (!ok) {
-		mddev->recovery_error = -EIO;
-		mddev->recovery_running = -1;
-		md_recover_arrays();
+		set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+		md_wakeup_thread(mddev->thread);
 		// stop recovery, signal do_sync ....
 	}
 }
@@ -2828,40 +3190,49 @@
 
 void md_write_start(mddev_t *mddev)
 {
-	if (mddev->safemode && !atomic_read(&mddev->writes_pending)) {
+	if (!atomic_read(&mddev->writes_pending)) {
 		mddev_lock_uninterruptible(mddev);
-		atomic_inc(&mddev->writes_pending);
 		if (mddev->in_sync) {
 			mddev->in_sync = 0;
+ 			del_timer(&mddev->safemode_timer);
 			md_update_sb(mddev);
 		}
+		atomic_inc(&mddev->writes_pending);
 		mddev_unlock(mddev);
 	} else
 		atomic_inc(&mddev->writes_pending);
 }
 
-void md_write_end(mddev_t *mddev, mdk_thread_t *thread)
+void md_write_end(mddev_t *mddev)
 {
-	if (atomic_dec_and_test(&mddev->writes_pending) && mddev->safemode)
-		md_wakeup_thread(thread);
+	if (atomic_dec_and_test(&mddev->writes_pending)) {
+		if (mddev->safemode == 2)
+			md_wakeup_thread(mddev->thread);
+		else
+			mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay);
+	}
 }
+
 static inline void md_enter_safemode(mddev_t *mddev)
 {
-
 	mddev_lock_uninterruptible(mddev);
-	if (mddev->safemode && !atomic_read(&mddev->writes_pending) && !mddev->in_sync && !mddev->recovery_running) {
+	if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+	    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
 		mddev->in_sync = 1;
 		md_update_sb(mddev);
 	}
 	mddev_unlock(mddev);
+
+	if (mddev->safemode == 1)
+		mddev->safemode = 0;
 }
 
 void md_handle_safemode(mddev_t *mddev)
 {
 	if (signal_pending(current)) {
-		printk(KERN_INFO "md: md%d in safe mode\n",mdidx(mddev));
-		mddev->safemode= 1;
-		flush_curr_signals();
+		printk(KERN_INFO "md: md%d in immediate safe mode\n",mdidx(mddev));
+		mddev->safemode = 2;
+		flush_signals(current);
 	}
 	if (mddev->safemode)
 		md_enter_safemode(mddev);
@@ -2872,9 +3243,8 @@
 
 #define SYNC_MARKS	10
 #define	SYNC_MARK_STEP	(3*HZ)
-static void md_do_sync(void *data)
+static void md_do_sync(mddev_t *mddev)
 {
-	mddev_t *mddev = data;
 	mddev_t *mddev2;
 	unsigned int max_sectors, currspeed = 0,
 		j, window, err;
@@ -2885,7 +3255,7 @@
 	unsigned long last_check;
 
 	/* just incase thread restarts... */
-	if (mddev->recovery_running <= 0)
+	if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
 		return;
 
 	/* we overload curr_resync somewhat here.
@@ -2912,14 +3282,16 @@
 				}
 				if (wait_event_interruptible(resync_wait,
 							     mddev2->curr_resync < mddev->curr_resync)) {
-					flush_curr_signals();
+					flush_signals(current);
 					err = -EINTR;
 					mddev_put(mddev2);
 					goto skip;
 				}
 			}
-			if (mddev->curr_resync == 1)
+			if (mddev->curr_resync == 1) {
+				mddev_put(mddev2);
 				break;
+			}
 		}
 	} while (mddev->curr_resync < 2);
 
@@ -2932,9 +3304,13 @@
 	       sysctl_speed_limit_max);
 
 	is_mddev_idle(mddev); /* this also initializes IO event counters */
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+		j = mddev->recovery_cp;
+	else
+		j = 0;
 	for (m = 0; m < SYNC_MARKS; m++) {
 		mark[m] = jiffies;
-		mark_cnt[m] = mddev->recovery_cp;
+		mark_cnt[m] = j;
 	}
 	last_mark = 0;
 	mddev->resync_mark = mark[last_mark];
@@ -2951,12 +3327,10 @@
 	init_waitqueue_head(&mddev->recovery_wait);
 	last_check = 0;
 
-	mddev->recovery_error = 0;
-
-	if (mddev->recovery_cp)
+	if (j)
 		printk(KERN_INFO "md: resuming recovery of md%d from checkpoint.\n", mdidx(mddev));
 
-	for (j = mddev->recovery_cp; j < max_sectors;) {
+	while (j < max_sectors) {
 		int sectors;
 
 		sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);
@@ -2973,6 +3347,10 @@
 
 		last_check = j;
 
+		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
+		    test_bit(MD_RECOVERY_ERR, &mddev->recovery))
+			break;
+
 		blk_run_queues();
 
 	repeat:
@@ -2993,7 +3371,7 @@
 			 * got a signal, exit.
 			 */
 			printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n");
-			flush_curr_signals();
+			flush_signals(current);
 			err = -EINTR;
 			goto out;
 		}
@@ -3027,39 +3405,42 @@
  out:
 	wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
 
-	if (mddev->recovery_running < 0 && 
-		!mddev->recovery_error && mddev->curr_resync > 2)
-	{
-		/* interrupted but no write errors */
-		printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev));
-		mddev->recovery_cp = mddev->curr_resync;
-	}
-
 	/* tell personality that we are finished */
 	mddev->pers->sync_request(mddev, max_sectors, 1);
- skip:
-	mddev->curr_resync = 0;
+
 	if (err)
-		mddev->recovery_running = -1;
-	if (mddev->recovery_running > 0)
-		mddev->recovery_running = 0;
-	if (mddev->recovery_running == 0)
-		mddev->recovery_cp = MaxSector;
+		set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+	if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
+	    mddev->curr_resync > 2 &&
+	    mddev->curr_resync > mddev->recovery_cp) {
+		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
+			printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev));
+			mddev->recovery_cp = mddev->curr_resync;
+		} else
+			mddev->recovery_cp = MaxSector;
+	}
+
 	if (mddev->safemode)
 		md_enter_safemode(mddev);
-	md_recover_arrays();
+ skip:
+	mddev->curr_resync = 0;
+	set_bit(MD_RECOVERY_DONE, &mddev->recovery);
+	md_wakeup_thread(mddev->thread);
 }
 
 
 /*
- * This is the kernel thread that watches all md arrays for re-sync and other
- * action that might be needed.
+ * This routine is regularly called by all per-raid-array threads to
+ * deal with generic issues like resync and super-block update.
+ * Raid personalities that don't have a thread (linear/raid0) do not
+ * need this as they never do any recovery or update the superblock.
+ *
  * It does not do any resync itself, but rather "forks" off other threads
  * to do that as needed.
- * When it is determined that resync is needed, we set "->recovery_running" and
- * create a thread at ->sync_thread.
- * When the thread finishes it clears recovery_running (or sets an error)
- * and wakeup up this thread which will reap the thread and finish up.
+ * When it is determined that resync is needed, we set MD_RECOVERY_RUNNING in
+ * "->recovery" and create a thread at ->sync_thread.
+ * When the thread finishes it sets MD_RECOVERY_DONE (and might set MD_RECOVERY_ERR)
+ * and wakeups up this thread which will reap the thread and finish up.
  * This thread also removes any faulty devices (with nr_pending == 0).
  *
  * The overall approach is:
@@ -3070,41 +3451,47 @@
  *  5/ If array is degraded, try to add spares devices
  *  6/ If array has spares or is not in-sync, start a resync thread.
  */
-void md_do_recovery(void *data)
+void md_check_recovery(mddev_t *mddev)
 {
-	mddev_t *mddev;
 	mdk_rdev_t *rdev;
-	struct list_head *tmp, *rtmp;
+	struct list_head *rtmp;
 
 
 	dprintk(KERN_INFO "md: recovery thread got woken up ...\n");
 
-	ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) {
-		if (!mddev->raid_disks || !mddev->pers || mddev->ro)
-			goto unlock;
+	if (mddev->ro)
+		return;
+	if ( ! (
+		mddev->sb_dirty ||
+		test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+		test_bit(MD_RECOVERY_DONE, &mddev->recovery)
+		))
+		return;
+	if (mddev_trylock(mddev)==0) {
+		int spares =0;
 		if (mddev->sb_dirty)
 			md_update_sb(mddev);
-		if (mddev->recovery_running > 0)
+		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
+		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery))
 			/* resync/recovery still happening */
 			goto unlock;
 		if (mddev->sync_thread) {
 			/* resync has finished, collect result */
 			md_unregister_thread(mddev->sync_thread);
 			mddev->sync_thread = NULL;
-			if (mddev->recovery_running == 0) {
+			if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery)) {
 				/* success...*/
 				/* activate any spares */
 				mddev->pers->spare_active(mddev);
-				mddev->spares = 0;
 			}
 			md_update_sb(mddev);
-			mddev->recovery_running = 0;
+			mddev->recovery = 0;
 			wake_up(&resync_wait);
 			goto unlock;
 		}
-		if (mddev->recovery_running) {
+		if (mddev->recovery) {
 			/* that's odd.. */
-			mddev->recovery_running = 0;
+			mddev->recovery = 0;
 			wake_up(&resync_wait);
 		}
 
@@ -3112,7 +3499,6 @@
 		 * remove any failed drives, then
 		 * add spares if possible
 		 */
-		mddev->spares = 0;
 		ITERATE_RDEV(mddev,rdev,rtmp) {
 			if (rdev->raid_disk >= 0 &&
 			    rdev->faulty &&
@@ -3121,43 +3507,41 @@
 				rdev->raid_disk = -1;
 			}
 			if (!rdev->faulty && rdev->raid_disk >= 0 && !rdev->in_sync)
-				mddev->spares++;
+				spares++;
 		}
 		if (mddev->degraded) {
 			ITERATE_RDEV(mddev,rdev,rtmp)
 				if (rdev->raid_disk < 0
 				    && !rdev->faulty) {
-					if (mddev->pers->hot_add_disk(mddev,rdev)) {
-						mddev->spares++;
-						mddev->recovery_cp = 0;
-					}
+					if (mddev->pers->hot_add_disk(mddev,rdev))
+						spares++;
 					else
 						break;
 				}
 		}
 
-		if (!mddev->spares && (mddev->recovery_cp == MaxSector )) {
+		if (!spares && (mddev->recovery_cp == MaxSector )) {
 			/* nothing we can do ... */
 			goto unlock;
 		}
 		if (mddev->pers->sync_request) {
+			set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+			if (!spares)
+				set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 			mddev->sync_thread = md_register_thread(md_do_sync,
 								mddev,
-								"md_resync");
+								"md%d_resync");
 			if (!mddev->sync_thread) {
 				printk(KERN_ERR "md%d: could not start resync thread...\n", mdidx(mddev));
 				/* leave the spares where they are, it shouldn't hurt */
-				mddev->recovery_running = 0;
+				mddev->recovery = 0;
 			} else {
-				mddev->recovery_running = 1;
 				md_wakeup_thread(mddev->sync_thread);
 			}
 		}
 	unlock:
 		mddev_unlock(mddev);
 	}
-	dprintk(KERN_INFO "md: recovery thread finished ...\n");
-
 }
 
 int md_notify_reboot(struct notifier_block *this,
@@ -3192,6 +3576,7 @@
 
 static void md_geninit(void)
 {
+	struct proc_dir_entry *p;
 	int i;
 
 	for(i = 0; i < MAX_MD_DEVS; i++) {
@@ -3201,24 +3586,24 @@
 	dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
 #ifdef CONFIG_PROC_FS
-	create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
+	p = create_proc_entry("mdstat", S_IRUGO, NULL);
+	if (p)
+		p->proc_fops = &md_seq_fops;
 #endif
 }
 
 int __init md_init(void)
 {
-	static char * name = "mdrecoveryd";
 	int minor;
 
 	printk(KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
 			MD_MAJOR_VERSION, MD_MINOR_VERSION,
 			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
 
-	if (register_blkdev (MAJOR_NR, "md", &md_fops)) {
-		printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
-		return (-1);
-	}
-	devfs_mk_dir (NULL, "md", NULL);
+	if (register_blkdev(MAJOR_NR, "md"))
+		return -1;
+
+	devfs_mk_dir(NULL, "md", NULL);
 	blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE,
 				md_probe, NULL, NULL);
 	for (minor=0; minor < MAX_MD_DEVS; ++minor) {
@@ -3228,11 +3613,6 @@
 			       S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL);
 	}
 
-	md_recovery_thread = md_register_thread(md_do_recovery, NULL, name);
-	if (!md_recovery_thread)
-		printk(KERN_ALERT
-		       "md: bug: couldn't allocate md_recovery_thread\n");
-
 	register_reboot_notifier(&md_notifier);
 	raid_table_header = register_sysctl_table(raid_root_table, 1);
 
@@ -3267,7 +3647,7 @@
 	for (i = 0; i < dev_cnt; i++) {
 		dev_t dev = detected_devices[i];
 
-		rdev = md_import_device(dev,1);
+		rdev = md_import_device(dev,0, 0);
 		if (IS_ERR(rdev)) {
 			printk(KERN_ALERT "md: could not import %s!\n",
 				partition_name(dev));
@@ -3290,7 +3670,6 @@
 {
 	int i;
 	blk_unregister_region(MKDEV(MAJOR_NR,0), MAX_MD_DEVS);
-	md_unregister_thread(md_recovery_thread);
 	for (i=0; i < MAX_MD_DEVS; i++)
 		devfs_remove("md/%d", i);
 	devfs_remove("md");
@@ -3330,4 +3709,5 @@
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_print_devices);
 EXPORT_SYMBOL(md_interrupt_thread);
+EXPORT_SYMBOL(md_check_recovery);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/multipath.c b/drivers/md/multipath.c
--- a/drivers/md/multipath.c	Mon Feb 17 13:55:16 2003
+++ b/drivers/md/multipath.c	Tue Mar 11 18:15:04 2003
@@ -86,7 +86,6 @@
 {
 	unsigned long flags;
 	mddev_t *mddev = mp_bh->mddev;
-	multipath_conf_t *conf = mddev_to_conf(mddev);
 
 	spin_lock_irqsave(&retry_list_lock, flags);
 	if (multipath_retry_list == NULL)
@@ -95,7 +94,7 @@
 	multipath_retry_tail = &mp_bh->next_mp;
 	mp_bh->next_mp = NULL;
 	spin_unlock_irqrestore(&retry_list_lock, flags);
-	md_wakeup_thread(conf->thread);
+	md_wakeup_thread(mddev->thread);
 }
 
 
@@ -185,19 +184,18 @@
 	return 0;
 }
 
-static int multipath_status (char *page, mddev_t *mddev)
+static void multipath_status (struct seq_file *seq, mddev_t *mddev)
 {
 	multipath_conf_t *conf = mddev_to_conf(mddev);
-	int sz = 0, i;
+	int i;
 	
-	sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks,
+	seq_printf (seq, " [%d/%d] [", conf->raid_disks,
 						 conf->working_disks);
 	for (i = 0; i < conf->raid_disks; i++)
-		sz += sprintf (page+sz, "%s",
+		seq_printf (seq, "%s",
 			       conf->multipaths[i].rdev && 
 			       conf->multipaths[i].rdev->in_sync ? "U" : "_");
-	sz += sprintf (page+sz, "]");
-	return sz;
+	seq_printf (seq, "]");
 }
 
 #define LAST_DISK KERN_ALERT \
@@ -334,14 +332,14 @@
  *	3.	Performs writes following reads for array syncronising.
  */
 
-static void multipathd (void *data)
+static void multipathd (mddev_t *mddev)
 {
 	struct multipath_bh *mp_bh;
 	struct bio *bio;
 	unsigned long flags;
-	mddev_t *mddev;
 	mdk_rdev_t *rdev;
 
+	md_check_recovery(mddev);
 	for (;;) {
 		spin_lock_irqsave(&retry_list_lock, flags);
 		mp_bh = multipath_retry_list;
@@ -471,10 +469,10 @@
 	}
 
 	{
-		const char * name = "multipathd";
+		const char * name = "md%d_multipath";
 
-		conf->thread = md_register_thread(multipathd, conf, name);
-		if (!conf->thread) {
+		mddev->thread = md_register_thread(multipathd, mddev, name);
+		if (!mddev->thread) {
 			printk(THREAD_ERROR, mdidx(mddev));
 			goto out_free_conf;
 		}
@@ -513,7 +511,7 @@
 {
 	multipath_conf_t *conf = mddev_to_conf(mddev);
 
-	md_unregister_thread(conf->thread);
+	md_unregister_thread(mddev->thread);
 	mempool_destroy(conf->pool);
 	kfree(conf);
 	mddev->private = NULL;
diff -Nru a/drivers/md/raid0.c b/drivers/md/raid0.c
--- a/drivers/md/raid0.c	Wed Dec  4 10:09:27 2002
+++ b/drivers/md/raid0.c	Tue Mar 11 18:46:36 2003
@@ -349,7 +349,7 @@
 	 * is the only IO operation happening on this bh.
 	 */
 	bio->bi_bdev = tmp_dev->bdev;
-	bio->bi_sector = rsect;
+	bio->bi_sector = rsect + tmp_dev->data_offset;
 
 	/*
 	 * Let the main block layer submit the IO and resolve recursion:
@@ -372,41 +372,40 @@
 	return 0;
 }
 			   
-static int raid0_status (char *page, mddev_t *mddev)
+static void raid0_status (struct seq_file *seq, mddev_t *mddev)
 {
-	int sz = 0;
 #undef MD_DEBUG
 #ifdef MD_DEBUG
 	int j, k;
 	raid0_conf_t *conf = mddev_to_conf(mddev);
   
-	sz += sprintf(page + sz, "      ");
+	seq_printf(seq, "      ");
 	for (j = 0; j < conf->nr_zones; j++) {
-		sz += sprintf(page + sz, "[z%d",
+		seq_printf(seq, "[z%d",
 				conf->hash_table[j].zone0 - conf->strip_zone);
 		if (conf->hash_table[j].zone1)
-			sz += sprintf(page+sz, "/z%d] ",
+			seq_printf(seq, "/z%d] ",
 				conf->hash_table[j].zone1 - conf->strip_zone);
 		else
-			sz += sprintf(page+sz, "] ");
+			seq_printf(seq, "] ");
 	}
   
-	sz += sprintf(page + sz, "\n");
+	seq_printf(seq, "\n");
   
 	for (j = 0; j < conf->nr_strip_zones; j++) {
-		sz += sprintf(page + sz, "      z%d=[", j);
+		seq_printf(seq, "      z%d=[", j);
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
-			sz += sprintf (page+sz, "%s/", bdev_partition_name(
+			seq_printf (seq, "%s/", bdev_partition_name(
 				conf->strip_zone[j].dev[k]->bdev));
-		sz--;
-		sz += sprintf (page+sz, "] zo=%d do=%d s=%d\n",
+
+		seq_printf (seq, "] zo=%d do=%d s=%d\n",
 				conf->strip_zone[j].zone_offset,
 				conf->strip_zone[j].dev_offset,
 				conf->strip_zone[j].size);
 	}
 #endif
-	sz += sprintf(page + sz, " %dk chunks", mddev->chunk_size/1024);
-	return sz;
+	seq_printf(seq, " %dk chunks", mddev->chunk_size/1024);
+	return;
 }
 
 static mdk_personality_t raid0_personality=
diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c
--- a/drivers/md/raid1.c	Mon Feb 17 14:07:44 2003
+++ b/drivers/md/raid1.c	Tue Mar 11 18:46:36 2003
@@ -225,13 +225,12 @@
 {
 	unsigned long flags;
 	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev_to_conf(mddev);
 
 	spin_lock_irqsave(&retry_list_lock, flags);
 	list_add(&r1_bio->retry_list, &retry_list_head);
 	spin_unlock_irqrestore(&retry_list_lock, flags);
 
-	md_wakeup_thread(conf->thread);
+	md_wakeup_thread(mddev->thread);
 }
 
 /*
@@ -320,7 +319,7 @@
 		 * already.
 		 */
 		if (atomic_dec_and_test(&r1_bio->remaining)) {
-			md_write_end(r1_bio->mddev,conf->thread);
+			md_write_end(r1_bio->mddev);
 			raid_end_bio_io(r1_bio, uptodate);
 		}	
 	}
@@ -494,7 +493,7 @@
 			BUG();
 		r1_bio->read_bio = read_bio;
 
-		read_bio->bi_sector = r1_bio->sector;
+		read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
 		read_bio->bi_bdev = mirror->rdev->bdev;
 		read_bio->bi_end_io = end_request;
 		read_bio->bi_rw = r1_bio->cmd;
@@ -529,7 +528,7 @@
 		mbio = bio_clone(bio, GFP_NOIO);
 		r1_bio->write_bios[i] = mbio;
 
-		mbio->bi_sector	= r1_bio->sector;
+		mbio->bi_sector	= r1_bio->sector + conf->mirrors[i].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		mbio->bi_end_io	= end_request;
 		mbio->bi_rw = r1_bio->cmd;
@@ -542,7 +541,7 @@
 		 * If all mirrors are non-operational
 		 * then return an IO error:
 		 */
-		md_write_end(mddev,conf->thread);
+		md_write_end(mddev);
 		raid_end_bio_io(r1_bio, 0);
 		return 0;
 	}
@@ -571,19 +570,18 @@
 	return 0;
 }
 
-static int status(char *page, mddev_t *mddev)
+static void status(struct seq_file *seq, mddev_t *mddev)
 {
 	conf_t *conf = mddev_to_conf(mddev);
-	int sz = 0, i;
+	int i;
 
-	sz += sprintf(page+sz, " [%d/%d] [", conf->raid_disks,
+	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
 						conf->working_disks);
 	for (i = 0; i < conf->raid_disks; i++)
-		sz += sprintf(page+sz, "%s",
+		seq_printf(seq, "%s",
 			      conf->mirrors[i].rdev &&
 			      conf->mirrors[i].rdev->in_sync ? "U" : "_");
-	sz += sprintf (page+sz, "]");
-	return sz;
+	seq_printf(seq, "]");
 }
 
 #define LAST_DISK KERN_ALERT \
@@ -624,10 +622,9 @@
 		mddev->degraded++;
 		conf->working_disks--;
 		/*
-		 * if recovery was running, stop it now.
+		 * if recovery is running, make sure it aborts.
 		 */
-		if (mddev->recovery_running) 
-			mddev->recovery_running = -EIO;
+		set_bit(MD_RECOVERY_ERR, &mddev->recovery);
 	}
 	rdev->in_sync = 0;
 	rdev->faulty = 1;
@@ -859,7 +856,7 @@
 		mbio = bio_clone(bio, GFP_NOIO);
 		r1_bio->write_bios[i] = mbio;
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
-		mbio->bi_sector = r1_bio->sector;
+		mbio->bi_sector = r1_bio->sector | conf->mirrors[i].rdev->data_offset;
 		mbio->bi_end_io	= end_sync_write;
 		mbio->bi_rw = WRITE;
 		mbio->bi_private = r1_bio;
@@ -900,17 +897,17 @@
  *	3.	Performs writes following reads for array syncronising.
  */
 
-static void raid1d(void *data)
+static void raid1d(mddev_t *mddev)
 {
 	struct list_head *head = &retry_list_head;
 	r1bio_t *r1_bio;
 	struct bio *bio;
 	unsigned long flags;
-	mddev_t *mddev;
-	conf_t *conf = data;
+	conf_t *conf = mddev_to_conf(mddev);
 	mdk_rdev_t *rdev;
 
-	md_handle_safemode(conf->mddev);
+	md_check_recovery(mddev);
+	md_handle_safemode(mddev);
 	
 	for (;;) {
 		spin_lock_irqsave(&retry_list_lock, flags);
@@ -937,7 +934,7 @@
 			printk(REDIRECT_SECTOR,
 				bdev_partition_name(rdev->bdev), (unsigned long long)r1_bio->sector);
 			bio->bi_bdev = rdev->bdev;
-			bio->bi_sector = r1_bio->sector;
+			bio->bi_sector = r1_bio->sector + rdev->data_offset;
 			bio->bi_rw = r1_bio->cmd;
 
 			generic_make_request(bio);
@@ -1048,7 +1045,7 @@
 
 	read_bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
 
-	read_bio->bi_sector = sector_nr;
+	read_bio->bi_sector = sector_nr + mirror->rdev->data_offset;
 	read_bio->bi_bdev = mirror->rdev->bdev;
 	read_bio->bi_end_io = end_sync_read;
 	read_bio->bi_rw = READ;
@@ -1190,10 +1187,8 @@
 
 
 	{
-		snprintf(conf->thread_name,MD_THREAD_NAME_MAX,"raid1d_md%d",mdidx(mddev));
-
-		conf->thread = md_register_thread(raid1d, conf, conf->thread_name);
-		if (!conf->thread) {
+		mddev->thread = md_register_thread(raid1d, mddev, "md%d_raid1");
+		if (!mddev->thread) {
 			printk(THREAD_ERROR, mdidx(mddev));
 			goto out_free_conf;
 		}
@@ -1219,7 +1214,8 @@
 {
 	conf_t *conf = mddev_to_conf(mddev);
 
-	md_unregister_thread(conf->thread);
+	md_unregister_thread(mddev->thread);
+	mddev->thread = NULL;
 	if (conf->r1bio_pool)
 		mempool_destroy(conf->r1bio_pool);
 	kfree(conf);
diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c
--- a/drivers/md/raid5.c	Mon Feb 17 14:07:44 2003
+++ b/drivers/md/raid5.c	Tue Mar 11 18:46:36 2003
@@ -71,12 +71,12 @@
 				list_add_tail(&sh->lru, &conf->delayed_list);
 			else
 				list_add_tail(&sh->lru, &conf->handle_list);
-			md_wakeup_thread(conf->thread);
+			md_wakeup_thread(conf->mddev->thread);
 		} else {
 			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 				atomic_dec(&conf->preread_active_stripes);
 				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-					md_wakeup_thread(conf->thread);
+					md_wakeup_thread(conf->mddev->thread);
 			}
 			list_add_tail(&sh->lru, &conf->inactive_list);
 			atomic_dec(&conf->active_stripes);
@@ -463,10 +463,9 @@
 			conf->failed_disks++;
 			rdev->in_sync = 0;
 			/*
-			 * if recovery was running, stop it now.
+			 * if recovery was running, make sure it aborts.
 			 */
-			if (mddev->recovery_running) 
-				mddev->recovery_running = -EIO;
+			set_bit(MD_RECOVERY_ERR, &mddev->recovery);
 		}
 		rdev->faulty = 1;
 		printk (KERN_ALERT
@@ -913,7 +912,7 @@
 				struct bio *nextbi = bi->bi_next;
 				clear_bit(BIO_UPTODATE, &bi->bi_flags);
 				if (--bi->bi_phys_segments == 0) {
-					md_write_end(conf->mddev, conf->thread);
+					md_write_end(conf->mddev);
 					bi->bi_next = return_bi;
 					return_bi = bi;
 				}
@@ -970,7 +969,7 @@
 			    while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
 				    wbi2 = wbi->bi_next;
 				    if (--wbi->bi_phys_segments == 0) {
-					    md_write_end(conf->mddev, conf->thread);
+					    md_write_end(conf->mddev);
 					    wbi->bi_next = return_bi;
 					    return_bi = wbi;
 				    }
@@ -1113,7 +1112,7 @@
 			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 				atomic_dec(&conf->preread_active_stripes);
 				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-					md_wakeup_thread(conf->thread);
+					md_wakeup_thread(conf->mddev->thread);
 			}
 		}
 	}
@@ -1207,7 +1206,7 @@
 			bi->bi_bdev = rdev->bdev;
 			PRINTK("for %llu schedule op %ld on disc %d\n", (unsigned long long)sh->sector, bi->bi_rw, i);
 			atomic_inc(&sh->count);
-			bi->bi_sector = sh->sector;
+			bi->bi_sector = sh->sector + rdev->data_offset;
 			bi->bi_flags = 1 << BIO_UPTODATE;
 			bi->bi_vcnt = 1;	
 			bi->bi_idx = 0;
@@ -1251,7 +1250,7 @@
 
 	if (blk_remove_plug(q))
 		raid5_activate_delayed(conf);
-	md_wakeup_thread(conf->thread);
+	md_wakeup_thread(mddev->thread);
 
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 }
@@ -1304,7 +1303,7 @@
 		int bytes = bi->bi_size;
 
 		if ( bio_data_dir(bi) == WRITE )
-			md_write_end(mddev,conf->thread);
+			md_write_end(mddev);
 		bi->bi_size = 0;
 		bi->bi_end_io(bi, bytes, 0);
 	}
@@ -1356,16 +1355,17 @@
  * During the scan, completed stripes are saved for us by the interrupt
  * handler, so that they will not have to wait for our next wakeup.
  */
-static void raid5d (void *data)
+static void raid5d (mddev_t *mddev)
 {
 	struct stripe_head *sh;
-	raid5_conf_t *conf = data;
-	mddev_t *mddev = conf->mddev;
+	raid5_conf_t *conf = mddev_to_conf(mddev);
 	int handled;
 
 	PRINTK("+++ raid5d active\n");
 
+	md_check_recovery(mddev);
 	md_handle_safemode(mddev);
+
 	handled = 0;
 	spin_lock_irq(&conf->device_lock);
 	while (1) {
@@ -1486,10 +1486,8 @@
 	}
 
 	{
-		snprintf(conf->thread_name,MD_THREAD_NAME_MAX,"raid5d_md%d",mdidx(mddev));
-
-		conf->thread = md_register_thread(raid5d, conf, conf->thread_name);
-		if (!conf->thread) {
+		mddev->thread = md_register_thread(raid5d, mddev, "md%d_raid5");
+		if (!mddev->thread) {
 			printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev));
 			goto abort;
 		}
@@ -1500,7 +1498,7 @@
 	if (grow_stripes(conf, conf->max_nr_stripes)) {
 		printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory);
 		shrink_stripes(conf);
-		md_unregister_thread(conf->thread);
+		md_unregister_thread(mddev->thread);
 		goto abort;
 	} else
 		printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev));
@@ -1536,7 +1534,8 @@
 {
 	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
 
-	md_unregister_thread(conf->thread);
+	md_unregister_thread(mddev->thread);
+	mddev->thread = NULL;
 	shrink_stripes(conf);
 	free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
 	kfree(conf);
@@ -1574,29 +1573,26 @@
 		}
 	}
 	spin_unlock_irq(&conf->device_lock);
-
-	PRINTK("--- raid5d inactive\n");
 }
 #endif
 
-static int status (char *page, mddev_t *mddev)
+static void status (struct seq_file *seq, mddev_t *mddev)
 {
 	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
-	int sz = 0, i;
+	int i;
 
-	sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout);
-	sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, conf->working_disks);
+	seq_printf (seq, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout);
+	seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks);
 	for (i = 0; i < conf->raid_disks; i++)
-		sz += sprintf (page+sz, "%s",
+		seq_printf (seq, "%s",
 			       conf->disks[i].rdev &&
 			       conf->disks[i].rdev->in_sync ? "U" : "_");
-	sz += sprintf (page+sz, "]");
+	seq_printf (seq, "]");
 #if RAID5_DEBUG
 #define D(x) \
-	sz += sprintf (page+sz, "<"#x":%d>", atomic_read(&conf->x))
+	seq_printf (seq, "<"#x":%d>", atomic_read(&conf->x))
 	printall(conf);
 #endif
-	return sz;
 }
 
 static void print_raid5_conf (raid5_conf_t *conf)
diff -Nru a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
--- a/drivers/media/radio/miropcm20-rds.c	Wed Jan  1 11:31:32 2003
+++ b/drivers/media/radio/miropcm20-rds.c	Sun Mar 16 22:33:22 2003
@@ -12,8 +12,9 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
 #include <linux/devfs_fs_kernel.h>
+#include <asm/uaccess.h>
 #include "miropcm20-rds-core.h"
 
 static char * text_buffer;
@@ -103,28 +104,39 @@
 	}
 }
 
-static struct file_operations rds_f_ops = {
+static struct file_operations rds_fops = {
 	.owner		= THIS_MODULE,
 	.read		= rds_f_read,
 	.open		= rds_f_open,
 	.release	= rds_f_release
 };
 
+static struct miscdevice rds_miscdev = {
+	.minor		= MISC_DYNAMIC_MINOR,
+	.name		= "radiotext",
+	.fops		= &rds_fops,
+};
 
 static int __init miropcm20_rds_init(void)
 {
-	if (!devfs_register(NULL, "v4l/rds/radiotext", 
-				   DEVFS_FL_DEFAULT | DEVFS_FL_AUTO_DEVNUM,
-				   0, 0, S_IRUGO | S_IFCHR, &rds_f_ops, NULL))
-		return -EINVAL;
+	int error;
 
-	printk("miropcm20-rds: userinterface driver loaded.\n");
-	return 0;
+	error = misc_register(&rds_miscdev);
+	if (error)
+		return error;
+
+	error = devfs_mk_symlink(NULL, "v4l/rds/radiotext", 0,
+				 "../misc/radiotext", NULL, NULL);
+	if (error)
+		misc_deregister(&rds_miscdev);
+
+	return error;
 }
 
 static void __exit miropcm20_rds_cleanup(void)
 {
 	devfs_remove("v4l/rds/radiotext");
+	misc_deregister(&rds_miscdev);
 }
 
 module_init(miropcm20_rds_init);
diff -Nru a/drivers/media/video/audiochip.h b/drivers/media/video/audiochip.h
--- a/drivers/media/video/audiochip.h	Wed Jan  8 01:59:59 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-#ifndef AUDIOCHIP_H
-#define AUDIOCHIP_H
-
-/* ---------------------------------------------------------------------- */
-
-#define MIN(a,b) (((a)>(b))?(b):(a))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-/* v4l device was opened in Radio mode */
-#define AUDC_SET_RADIO        _IO('m',2)
-/* select from TV,radio,extern,MUTE */
-#define AUDC_SET_INPUT        _IOW('m',17,int)
-
-/* audio inputs */
-#define AUDIO_TUNER        0x00
-#define AUDIO_RADIO        0x01
-#define AUDIO_EXTERN       0x02
-#define AUDIO_INTERN       0x03
-#define AUDIO_OFF          0x04 
-#define AUDIO_ON           0x05
-#define AUDIO_MUTE         0x80
-#define AUDIO_UNMUTE       0x81
-
-/* all the stuff below is obsolete and just here for reference.  I'll
- * remove it once the driver is tested and works fine.
- *
- * Instead creating alot of tiny API's for all kinds of different
- * chips, we'll just pass throuth the v4l ioctl structs (v4l2 not
- * yet...).  It is a bit less flexible, but most/all used i2c chips
- * make sense in v4l context only.  So I think that's acceptable...
- */
-
-/* misc stuff to pass around config info to i2c chips */
-#define AUDC_CONFIG_PINNACLE  _IOW('m',32,int)
-
-#endif /* AUDIOCHIP_H */
diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
--- a/drivers/media/video/bttv-cards.c	Mon Jan 27 13:30:24 2003
+++ b/drivers/media/video/bttv-cards.c	Wed Mar 12 06:07:06 2003
@@ -36,7 +36,6 @@
 #include <asm/io.h>
 
 #include "bttvp.h"
-#include "tuner.h"
 #include "bt832.h"
 
 /* fwd decl */
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	Thu Jan 16 16:48:05 2003
+++ b/drivers/media/video/bttv-driver.c	Wed Mar 12 06:07:06 2003
@@ -37,7 +37,6 @@
 #include <asm/io.h>
 
 #include "bttvp.h"
-#include "tuner.h"
 
 int bttv_num;			/* number of Bt848s in use */
 struct bttv bttvs[BTTV_MAX];
diff -Nru a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c
--- a/drivers/media/video/bttv-if.c	Wed Jan  8 01:59:58 2003
+++ b/drivers/media/video/bttv-if.c	Wed Mar 12 06:07:06 2003
@@ -34,7 +34,6 @@
 #include <asm/io.h>
 
 #include "bttvp.h"
-#include "tuner.h"
 
 static struct i2c_algo_bit_data bttv_i2c_algo_template;
 static struct i2c_adapter bttv_i2c_adap_template;
diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
--- a/drivers/media/video/bttvp.h	Wed Jan  8 01:59:58 2003
+++ b/drivers/media/video/bttvp.h	Wed Mar 12 06:07:06 2003
@@ -34,10 +34,12 @@
 #include <linux/pci.h>
 #include <asm/scatterlist.h>
 
+#include <media/video-buf.h>
+#include <media/audiochip.h>
+#include <media/tuner.h>
+
 #include "bt848.h"
 #include "bttv.h"
-#include "video-buf.h"
-#include "audiochip.h"
 
 #ifdef __KERNEL__
 
diff -Nru a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
--- a/drivers/media/video/bw-qcam.c	Fri Nov 29 08:30:40 2002
+++ b/drivers/media/video/bw-qcam.c	Sun Feb 16 16:16:53 2003
@@ -83,11 +83,9 @@
 static unsigned int yieldlines=4;  /* Yield after this many during capture */
 static int video_nr = -1;
 
-#if LINUX_VERSION_CODE >= 0x020117
 MODULE_PARM(maxpoll,"i");
 MODULE_PARM(yieldlines,"i");   
 MODULE_PARM(video_nr,"i");
-#endif
 
 static inline int read_lpstatus(struct qcam_device *q)
 {
diff -Nru a/drivers/media/video/id.h b/drivers/media/video/id.h
--- a/drivers/media/video/id.h	Fri Mar  8 04:42:43 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,35 +0,0 @@
-/* FIXME: this temporarely, until these are included in linux/i2c-id.h */
-
-/* drivers */
-#ifndef  I2C_DRIVERID_TVMIXER
-# define I2C_DRIVERID_TVMIXER I2C_DRIVERID_EXP0
-#endif
-#ifndef  I2C_DRIVERID_TVAUDIO
-# define I2C_DRIVERID_TVAUDIO I2C_DRIVERID_EXP1
-#endif
-
-/* chips */
-#ifndef  I2C_DRIVERID_DPL3518
-# define I2C_DRIVERID_DPL3518 I2C_DRIVERID_EXP2
-#endif
-#ifndef  I2C_DRIVERID_TDA9873
-# define I2C_DRIVERID_TDA9873 I2C_DRIVERID_EXP3
-#endif
-#ifndef  I2C_DRIVERID_TDA9875
-# define I2C_DRIVERID_TDA9875 I2C_DRIVERID_EXP0+4
-#endif
-#ifndef  I2C_DRIVERID_PIC16C54_PV951
-# define I2C_DRIVERID_PIC16C54_PV951 I2C_DRIVERID_EXP0+5
-#endif
-#ifndef  I2C_DRIVERID_TDA7432
-# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6
-#endif
-#ifndef  I2C_DRIVERID_TDA9874
-# define I2C_DRIVERID_TDA9874 I2C_DRIVERID_EXP0+7
-#endif
-
-/* algorithms */
-#ifndef I2C_ALGO_SAA7134
-# define I2C_ALGO_SAA7134 0x090000
-#endif
-
diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
--- a/drivers/media/video/msp3400.c	Tue Feb 11 14:57:51 2003
+++ b/drivers/media/video/msp3400.c	Wed Mar 12 06:07:06 2003
@@ -56,7 +56,7 @@
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
 
-#include "audiochip.h"
+#include <media/audiochip.h>
 #include "msp3400.h"
 
 /* Addresses to scan */
@@ -1495,8 +1495,8 @@
 			VIDEO_AUDIO_MUTABLE;
 		if (msp->muted)
 			va->flags |= VIDEO_AUDIO_MUTE;
-		va->volume=MAX(msp->left,msp->right);
-		va->balance=(32768*MIN(msp->left,msp->right))/
+		va->volume=max(msp->left,msp->right);
+		va->balance=(32768*min(msp->left,msp->right))/
 			(va->volume ? va->volume : 1);
 		va->balance=(msp->left<msp->right)?
 			(65535-va->balance) : va->balance;
@@ -1517,9 +1517,9 @@
 
 		dprintk(KERN_DEBUG "msp34xx: VIDIOCSAUDIO\n");
 		msp->muted = (va->flags & VIDEO_AUDIO_MUTE);
-		msp->left = (MIN(65536 - va->balance,32768) *
+		msp->left = (min(65536 - va->balance,32768) *
 			     va->volume) / 32768;
-		msp->right = (MIN(va->balance,32768) *
+		msp->right = (min(va->balance,(__u16)32768) *
 			      va->volume) / 32768;
 		msp->bass = va->bass;
 		msp->treble = va->treble;
diff -Nru a/drivers/media/video/planb.c b/drivers/media/video/planb.c
--- a/drivers/media/video/planb.c	Fri Nov 29 08:30:40 2002
+++ b/drivers/media/video/planb.c	Sun Feb 16 16:16:53 2003
@@ -181,12 +181,7 @@
 
 	/* Let's wait 30msec for this one */
 	current->state = TASK_INTERRUPTIBLE;
-#if LINUX_VERSION_CODE >= 0x02017F
 	schedule_timeout(30 * HZ / 1000);
-#else
-	current->timeout = jiffies + 30 * HZ / 1000;	/* 30 ms */;
-	schedule();
-#endif
 
 	return (unsigned char)in_8 (&planb_regs->saa_status);
 }
diff -Nru a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
--- a/drivers/media/video/saa7134/saa7134-cards.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/saa7134/saa7134-cards.c	Wed Mar 12 06:07:06 2003
@@ -24,7 +24,6 @@
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
-#include "tuner.h"
 
 /* commly used strings */
 static char name_mute[]    = "mute";
diff -Nru a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
--- a/drivers/media/video/saa7134/saa7134-core.c	Thu Dec  5 18:56:40 2002
+++ b/drivers/media/video/saa7134/saa7134-core.c	Wed Mar 12 06:07:06 2003
@@ -30,7 +30,6 @@
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
-#include "tuner.h"
 
 MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
--- a/drivers/media/video/saa7134/saa7134-i2c.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/saa7134/saa7134-i2c.c	Wed Mar 12 06:07:06 2003
@@ -30,8 +30,6 @@
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
-#include "tuner.h"
-#include "id.h"
 
 /* ----------------------------------------------------------- */
 
diff -Nru a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
--- a/drivers/media/video/saa7134/saa7134-video.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/saa7134/saa7134-video.c	Wed Mar 12 06:07:06 2003
@@ -29,8 +29,6 @@
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
-#include "tuner.h"
-#include "audiochip.h"
 
 /* ------------------------------------------------------------------ */
 
diff -Nru a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
--- a/drivers/media/video/saa7134/saa7134.h	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/saa7134/saa7134.h	Wed Mar 12 06:07:06 2003
@@ -22,7 +22,11 @@
 #include <linux/i2c.h>
 #include <linux/videodev.h>
 #include <linux/kdev_t.h>
-#include "video-buf.h"
+
+#include <media/video-buf.h>
+#include <media/tuner.h>
+#include <media/audiochip.h>
+#include <media/id.h>
 
 #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,2)
 
diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
--- a/drivers/media/video/tda7432.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/tda7432.c	Wed Mar 12 06:07:06 2003
@@ -49,8 +49,8 @@
 #include <linux/i2c-algo-bit.h>
 
 #include "bttv.h"
-#include "audiochip.h"
-#include "id.h"
+#include <media/audiochip.h>
+#include <media/id.h>
 
 #ifndef VIDEO_AUDIO_BALANCE
 # define VIDEO_AUDIO_BALANCE 32
diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
--- a/drivers/media/video/tda9875.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/tda9875.c	Wed Mar 12 06:07:06 2003
@@ -31,8 +31,8 @@
 #include <linux/init.h>
 
 #include "bttv.h"
-#include "audiochip.h"
-#include "id.h"
+#include <media/audiochip.h>
+#include <media/id.h>
 
 MODULE_PARM(debug,"i");
 MODULE_LICENSE("GPL");
@@ -316,17 +316,15 @@
 		/* min is -84 max is 24 */
 		left = (t->lvol+84)*606;
 		right = (t->rvol+84)*606;
-		va->volume=MAX(left,right);
-		va->balance=(32768*MIN(left,right))/
+		va->volume=max(left,right);
+		va->balance=(32768*min(left,right))/
 			(va->volume ? va->volume : 1);
 		va->balance=(left<right)?
 			(65535-va->balance) : va->balance;
 		va->bass = (t->bass+12)*2427;    /* min -12 max +15 */
 		va->treble = (t->treble+12)*2730;/* min -12 max +12 */
-
 		va->mode |= VIDEO_SOUND_MONO;
 
-
 		break; /* VIDIOCGAUDIO case */
 	}
 
@@ -336,9 +334,9 @@
 		int left,right;
 
 		dprintk("VIDEOCSAUDIO...\n"); 
-		left = (MIN(65536 - va->balance,32768) *
+		left = (min(65536 - va->balance,32768) *
 			va->volume) / 32768;
-		right = (MIN(va->balance,32768) *
+		right = (min(va->balance,(__u16)32768) *
 			 va->volume) / 32768;
 		t->lvol = ((left/606)-84) & 0xff;
 		if (t->lvol > 24)
diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
--- a/drivers/media/video/tda9887.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/tda9887.c	Wed Mar 12 06:07:06 2003
@@ -7,8 +7,8 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-#include "id.h"
-#include "audiochip.h"
+#include <media/audiochip.h>
+#include <media/id.h>
 
 /* Chips:
    TDA9885 (PAL, NTSC)
diff -Nru a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
--- a/drivers/media/video/tuner-3036.c	Fri Feb 14 11:10:34 2003
+++ b/drivers/media/video/tuner-3036.c	Wed Mar 12 06:07:06 2003
@@ -27,7 +27,7 @@
 #include <linux/i2c.h>
 #include <linux/videodev.h>
 
-#include "tuner.h"
+#include <media/tuner.h>
 
 static int debug;	/* insmod parameter */
 static int this_adap;
diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
--- a/drivers/media/video/tuner.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/tuner.c	Wed Mar 12 06:07:06 2003
@@ -12,8 +12,8 @@
 #include <linux/videodev.h>
 #include <linux/init.h>
 
-#include "tuner.h"
-#include "audiochip.h"
+#include <media/tuner.h>
+#include <media/audiochip.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {I2C_CLIENT_END};
diff -Nru a/drivers/media/video/tuner.h b/drivers/media/video/tuner.h
--- a/drivers/media/video/tuner.h	Thu Oct 31 05:20:28 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,94 +0,0 @@
-/* 
-    tuner.h - definition for different tuners
-
-    Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
-    minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de)
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _TUNER_H
-#define _TUNER_H
-
-#include "id.h"
-
-#define TUNER_TEMIC_PAL     0        /* 4002 FH5 (3X 7756, 9483) */
-#define TUNER_PHILIPS_PAL_I 1
-#define TUNER_PHILIPS_NTSC  2
-#define TUNER_PHILIPS_SECAM 3		/* you must actively select B/G, L, L` */
-#define TUNER_ABSENT        4
-#define TUNER_PHILIPS_PAL   5
-#define TUNER_TEMIC_NTSC    6        /* 4032 FY5 (3X 7004, 9498, 9789)  */
-#define TUNER_TEMIC_PAL_I   7        /* 4062 FY5 (3X 8501, 9957)        */
-#define TUNER_TEMIC_4036FY5_NTSC 8   /* 4036 FY5 (3X 1223, 1981, 7686)  */
-#define TUNER_ALPS_TSBH1_NTSC 	 9
-#define TUNER_ALPS_TSBE1_PAL 	10
-#define TUNER_ALPS_TSBB5_PAL_I 	11
-#define TUNER_ALPS_TSBE5_PAL 	12
-#define TUNER_ALPS_TSBC5_PAL 	13
-#define TUNER_TEMIC_4006FH5_PAL	14   /* 4006 FH5 (3X 9500, 9501, 7291)     */
-#define TUNER_ALPS_TSHC6_NTSC 	15
-#define TUNER_TEMIC_PAL_DK	16   /* 4016 FY5 (3X 1392, 1393)     */
-#define TUNER_PHILIPS_NTSC_M	17
-#define TUNER_TEMIC_4066FY5_PAL_I       18  /* 4066 FY5 (3X 7032, 7035) */
-#define TUNER_TEMIC_4006FN5_MULTI_PAL   19  /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
-#define TUNER_TEMIC_4009FR5_PAL         20  /* incl. FM radio (3X 7607, 7488, 7711)*/
-#define TUNER_TEMIC_4039FR5_NTSC        21  /* incl. FM radio (3X 7246, 7578, 7732)*/
-#define TUNER_TEMIC_4046FM5             22  /* you must actively select B/G, D/K, I, L, L` !  (3X 7804, 7806, 8103, 8104)*/
-#define TUNER_PHILIPS_PAL_DK		23
-#define TUNER_PHILIPS_FQ1216ME		24  /* you must actively select B/G/D/K, I, L, L` */
-#define TUNER_LG_PAL_I_FM	25
-#define TUNER_LG_PAL_I		26
-#define TUNER_LG_NTSC_FM	27
-#define TUNER_LG_PAL_FM		28
-#define TUNER_LG_PAL		29
-#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM	30  /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
-#define TUNER_SHARP_2U5JF5540_NTSC  31
-#define TUNER_Samsung_PAL_TCPM9091PD27 32
-#define TUNER_MT2032 33
-#define TUNER_TEMIC_4106FH5 	34	/* 4106 FH5 (3X 7808, 7865)*/
-#define TUNER_TEMIC_4012FY5	35	/* 4012 FY5 (3X 0971, 1099)*/
-#define TUNER_TEMIC_4136FY5	36	/* 4136 FY5 (3X 7708, 7746)*/
-#define TUNER_LG_PAL_NEW_TAPC   37
-#define TUNER_PHILIPS_FM1216ME_MK3  38
-#define TUNER_LG_NTSC_NEW_TAPC   39
-
-
-
-
-#define NOTUNER 0
-#define PAL     1	/* PAL_BG */
-#define PAL_I   2
-#define NTSC    3
-#define SECAM   4
-
-#define NoTuner 0
-#define Philips 1
-#define TEMIC   2
-#define Sony    3
-#define Alps    4
-#define LGINNOTEK 5
-#define SHARP   6
-#define Samsung 7
-#define Microtune 8
-
-#define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
-#define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
-#if 0 /* obsolete */
-# define TUNER_SET_RADIOFREQ         _IOW('t',3,int)    /* set radio freq */
-# define TUNER_SET_MODE              _IOW('t',4,int)    /* set tuner mode */
-#endif
-
-#endif
diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
--- a/drivers/media/video/tvaudio.c	Tue Feb 11 14:57:51 2003
+++ b/drivers/media/video/tvaudio.c	Wed Mar 12 06:07:06 2003
@@ -29,9 +29,10 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 
-#include "audiochip.h"
+#include <media/audiochip.h>
+#include <media/id.h>
+
 #include "tvaudio.h"
-#include "id.h"
 
 
 /* ---------------------------------------------------------------------- */
@@ -1477,8 +1478,8 @@
 
 		if (desc->flags & CHIP_HAS_VOLUME) {
 			va->flags  |= VIDEO_AUDIO_VOLUME;
-			va->volume  = MAX(chip->left,chip->right);
-			va->balance = (32768*MIN(chip->left,chip->right))/
+			va->volume  = max(chip->left,chip->right);
+			va->balance = (32768*min(chip->left,chip->right))/
 				(va->volume ? va->volume : 1);
 		}
 		if (desc->flags & CHIP_HAS_BASSTREBLE) {
@@ -1500,9 +1501,9 @@
 		struct video_audio *va = arg;
 		
 		if (desc->flags & CHIP_HAS_VOLUME) {
-			chip->left = (MIN(65536 - va->balance,32768) *
+			chip->left = (min(65536 - va->balance,32768) *
 				      va->volume) / 32768;
-			chip->right = (MIN(va->balance,32768) *
+			chip->right = (min(va->balance,(__u16)32768) *
 				       va->volume) / 32768;
 			chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
 			chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
--- a/drivers/media/video/tvmixer.c	Wed Jan  8 01:59:59 2003
+++ b/drivers/media/video/tvmixer.c	Wed Mar 12 06:03:51 2003
@@ -16,8 +16,6 @@
 #include <linux/soundcard.h>
 #include <asm/uaccess.h>
 
-#include "audiochip.h"
-#include "id.h"
 
 #define DEV_MAX  4
 
@@ -136,16 +134,16 @@
 	case MIXER_WRITE(SOUND_MIXER_VOLUME):
 		left  = mix_to_v4l(val);
 		right = mix_to_v4l(val >> 8);
-		va.volume  = MAX(left,right);
-		va.balance = (32768*MIN(left,right)) / (va.volume ? va.volume : 1);
+		va.volume  = max(left,right);
+		va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1);
 		va.balance = (left<right) ? (65535-va.balance) : va.balance;
 		client->driver->command(client,VIDIOCSAUDIO,&va);
 		client->driver->command(client,VIDIOCGAUDIO,&va);
 		/* fall throuth */
 	case MIXER_READ(SOUND_MIXER_VOLUME):
-		left  = (MIN(65536 - va.balance,32768) *
+		left  = (min(65536 - va.balance,32768) *
 			 va.volume) / 32768;
-		right = (MIN(va.balance,32768) *
+		right = (min(va.balance,32768) *
 			 va.volume) / 32768;
 		ret = v4l_to_mix2(left,right);
 		break;
diff -Nru a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
--- a/drivers/media/video/video-buf.c	Wed Jan  8 01:59:58 2003
+++ b/drivers/media/video/video-buf.c	Wed Mar 12 06:07:06 2003
@@ -31,7 +31,7 @@
 # define TryLockPage TestSetPageLocked
 #endif
 
-#include "video-buf.h"
+#include <media/video-buf.h>
 
 static int debug = 0;
 
@@ -83,6 +83,8 @@
 		return NULL;
 	memset(sglist, 0, sizeof(*sglist) * nr_pages);
 
+	if (NULL == pages[0])
+		goto nopage;
 	if (PageHighMem(pages[0]))
 		/* DMA to highmem pages might not work */
 		goto highmem;
@@ -118,7 +120,7 @@
 	for (i = 0; i < nr_pages; i++)
 		if (TryLockPage(pages[i]))
 			goto err;
-	dprintk(2,"lock ok\n");
+	dprintk(2,"lock ok [%d pages]\n",nr_pages);
 	return 0;
 
  err:
@@ -136,7 +138,7 @@
 	dprintk(2,"unlock start ...\n");
 	for (i = 0; i < nr_pages; i++)
 		unlock_page(pages[i]);
-	dprintk(2,"unlock ok\n");
+	dprintk(2,"unlock ok [%d pages]\n",nr_pages);
 	return 0;
 }
 
@@ -270,7 +272,7 @@
 
 /* --------------------------------------------------------------------- */
 
-void* videobuf_alloc(int size)
+void* videobuf_alloc(unsigned int size)
 {
 	struct videobuf_buffer *vb;
 
@@ -340,7 +342,7 @@
 		    spinlock_t *irqlock,
 		    enum v4l2_buf_type type,
 		    enum v4l2_field field,
-		    int msize)
+		    unsigned int msize)
 {
 	memset(q,0,sizeof(*q));
 
@@ -417,11 +419,11 @@
 
 	if (V4L2_FIELD_ALTERNATE == field) {
 		if (V4L2_FIELD_TOP == q->last) {
-			field   = V4L2_FIELD_TOP;
-			q->last = V4L2_FIELD_TOP;
-		} else {
 			field   = V4L2_FIELD_BOTTOM;
 			q->last = V4L2_FIELD_BOTTOM;
+		} else {
+			field   = V4L2_FIELD_TOP;
+			q->last = V4L2_FIELD_TOP;
 		}
 	}
 	return field;
@@ -463,7 +465,8 @@
 videobuf_reqbufs(struct file *file, struct videobuf_queue *q,
 		 struct v4l2_requestbuffers *req)
 {
-	int size,count,retval;
+	unsigned int size,count;
+	int retval;
 
 	if (req->type != q->type)
 		return -EINVAL;
@@ -477,6 +480,8 @@
 	size = 0;
 	q->ops->buf_setup(file,&count,&size);
 	size = PAGE_ALIGN(size);
+	dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n",
+		count, size, (count*size)>>PAGE_SHIFT);
 
 	retval = videobuf_mmap_setup(file,q,count,size);
 	if (retval < 0)
@@ -660,7 +665,10 @@
         retval = videobuf_waiton(q->read_buf,0,0);
         if (0 == retval) {
 		videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
-                retval = q->read_buf->size;
+		if (STATE_ERROR == q->read_buf->state)
+			retval = -EIO;
+		else
+			retval = q->read_buf->size;
 	}
 
  done:
@@ -676,7 +684,8 @@
 {
 	enum v4l2_field field;
 	unsigned long flags;
-	int retval, bytes, size, nbufs;
+	unsigned size, nbufs, bytes;
+	int retval;
 
 	down(&q->lock);
 
@@ -686,7 +695,7 @@
 	    count >= size        &&
 	    !(file->f_flags & O_NONBLOCK)) {
 		retval = videobuf_read_zerocopy(file,q,data,count,ppos);
-		if (retval >= 0)
+		if (retval >= 0  ||  retval == -EIO)
 			/* ok, all done */
 			goto done;
 		/* fallback to kernel bounce buffer on failures */
@@ -714,6 +723,15 @@
 		goto done;
 	videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
 
+	if (STATE_ERROR == q->read_buf->state) {
+		/* catch I/O errors */
+		q->ops->buf_release(file,q->read_buf);
+		kfree(q->read_buf);
+		q->read_buf = NULL;
+		retval = -EIO;
+		goto done;
+	}
+
 	/* copy to userspace */
 	bytes = count;
 	if (bytes > q->read_buf->size - q->read_off)
@@ -788,8 +806,8 @@
 			     char *data, size_t count, loff_t *ppos,
 			     int vbihack)
 {
-	unsigned int *fc;
-	int err, bytes, retval;
+	unsigned int *fc, bytes;
+	int err, retval;
 	unsigned long flags;
 	
 	down(&q->lock);
@@ -968,9 +986,10 @@
 };
 
 int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q,
-			int bcount, int bsize)
+			unsigned int bcount, unsigned int bsize)
 {
-	int i,err;
+	unsigned int i;
+	int err;
 
 	err = videobuf_mmap_free(file,q);
 	if (0 != err)
@@ -1008,7 +1027,8 @@
 			 struct videobuf_queue *q)
 {
 	struct videobuf_mapping *map;
-	int first,last,size,i,retval;
+	unsigned int first,last,size,i;
+	int retval;
 
 	down(&q->lock);
 	retval = -EINVAL;
@@ -1025,7 +1045,7 @@
 	for (first = 0; first < VIDEO_MAX_FRAME; first++) {
 		if (NULL == q->bufs[first])
 			continue;
-		if (q->bufs[first]->boff  == (vma->vm_pgoff << PAGE_SHIFT))
+		if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
 			break;
 	}
 	if (VIDEO_MAX_FRAME == first) {
diff -Nru a/drivers/media/video/video-buf.h b/drivers/media/video/video-buf.h
--- a/drivers/media/video/video-buf.h	Wed Jan  8 01:59:58 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,232 +0,0 @@
-/*
- * generic helper functions for video4linux capture buffers, to handle
- * memory management and PCI DMA.  Right now bttv + saa7134 use it.
- *
- * The functions expect the hardware being able to scatter gatter
- * (i.e. the buffers are not linear in physical memory, but fragmented
- * into PAGE_SIZE chunks).  They also assume the driver does not need
- * to touch the video data (thus it is probably not useful for USB as
- * data often must be uncompressed by the drivers).
- * 
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/videodev.h>
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Return a scatterlist for some page-aligned vmalloc()'ed memory
- * block (NULL on errors).  Memory for the scatterlist is allocated
- * using kmalloc.  The caller must free the memory.
- */
-struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages);
-
-/*
- * Return a scatterlist for a an array of userpages (NULL on errors).
- * Memory for the scatterlist is allocated using kmalloc.  The caller
- * must free the memory.
- */
-struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages,
-					 int offset);
-int videobuf_lock(struct page **pages, int nr_pages);
-int videobuf_unlock(struct page **pages, int nr_pages);
-
-/* --------------------------------------------------------------------- */
-
-/*
- * A small set of helper functions to manage buffers (both userland
- * and kernel) for DMA.
- *
- * videobuf_init_*_dmabuf()
- *	creates a buffer.  The userland version takes a userspace
- *	pointer + length.  The kernel version just wants the size and
- *	does memory allocation too using vmalloc_32().
- *
- * videobuf_pci_*_dmabuf()
- *	see Documentation/DMA-mapping.txt, these functions to
- *	basically the same.  The map function does also build a
- *	scatterlist for the buffer (and unmap frees it ...)
- *
- * videobuf_free_dmabuf()
- *	no comment ...
- *
- */
-
-struct videobuf_dmabuf {
-	/* for userland buffer */
-	int                 offset;
-	struct page         **pages;
-
-	/* for kernel buffers */
-	void                *vmalloc;
-
-	/* common */
-	struct scatterlist  *sglist;
-	int                 sglen;
-	int                 nr_pages;
-	int                 direction;
-};
-
-int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
-			   unsigned long data, unsigned long size);
-int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
-			     int nr_pages);
-int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma);
-int videobuf_dma_pci_sync(struct pci_dev *dev,
-			  struct videobuf_dmabuf *dma);
-int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma);
-int videobuf_dma_free(struct videobuf_dmabuf *dma);
-
-/* --------------------------------------------------------------------- */
-
-/*
- * A small set of helper functions to manage video4linux buffers.
- *
- * struct videobuf_buffer holds the data structures used by the helper
- * functions, additionally some commonly used fields for v4l buffers
- * (width, height, lists, waitqueue) are in there.  That struct should
- * be used as first element in the drivers buffer struct.
- * 
- * about the mmap helpers (videobuf_mmap_*):
- *
- * The mmaper function allows to map any subset of contingous buffers.
- * This includes one mmap() call for all buffers (which the original
- * video4linux API uses) as well as one mmap() for every single buffer
- * (which v4l2 uses).
- *
- * If there is a valid mapping for a buffer, buffer->baddr/bsize holds
- * userspace address + size which can be feeded into the
- * videobuf_dma_init_user function listed above.
- *
- */
-
-struct videobuf_buffer;
-struct videobuf_queue;
-
-struct videobuf_mapping {
-	int count;
-	int highmem_ok;
-	unsigned long start;
-	unsigned long end;
-	struct videobuf_queue *q;
-};
-
-enum videobuf_state {
-	STATE_NEEDS_INIT = 0,
-	STATE_PREPARED   = 1,
-	STATE_QUEUED     = 2,
-	STATE_ACTIVE     = 3,
-	STATE_DONE       = 4,
-	STATE_ERROR      = 5,
-	STATE_IDLE       = 6,
-};
-
-struct videobuf_buffer {
-	int                     i;
-
-	/* info about the buffer */
-	int                     width;
-	int                     height;
-	long                    size;
-	enum v4l2_field         field;
-	enum videobuf_state     state;
-	struct videobuf_dmabuf  dma;
-	struct list_head        stream;  /* QBUF/DQBUF list */
-
-	/* for mmap'ed buffers */
-	off_t                   boff;    /* buffer offset (mmap) */
-	size_t                  bsize;   /* buffer size */
-	unsigned long           baddr;   /* buffer addr (userland ptr!) */
-	struct videobuf_mapping *map;
-
-	/* touched by irq handler */
-	struct list_head        queue;
-	wait_queue_head_t       done;
-	int                     field_count;
-	struct timeval          ts;
-};
-
-struct videobuf_queue_ops {
-	int (*buf_setup)(struct file *file, int *count, int *size);
-	int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb,
-			   enum v4l2_field field);
-	void (*buf_queue)(struct file *file,struct videobuf_buffer *vb);
-	void (*buf_release)(struct file *file,struct videobuf_buffer *vb);
-};
-
-struct videobuf_queue {
-        struct semaphore           lock;
-	spinlock_t                 *irqlock;
-	struct pci_dev             *pci;
-
-	enum v4l2_buf_type         type;
-	int                        msize;
-	enum v4l2_field            field;
-	enum v4l2_field            last; /* for field=V4L2_FIELD_ALTERNATE */
-	struct videobuf_buffer     *bufs[VIDEO_MAX_FRAME];
-	struct videobuf_queue_ops  *ops;
-
-	/* capture via mmap() + ioctl(QBUF/DQBUF) */
-	int                        streaming;
-	struct list_head           stream;
-
-	/* capture via read() */
-	int                        reading;
-	int                        read_off;
-	struct videobuf_buffer     *read_buf;
-};
-
-void* videobuf_alloc(int size);
-int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
-int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb);
-
-void videobuf_queue_init(struct videobuf_queue *q,
-			 struct videobuf_queue_ops *ops,
-			 struct pci_dev *pci, spinlock_t *irqlock,
-			 enum v4l2_buf_type type,
-			 enum v4l2_field field, int msize);
-int  videobuf_queue_is_busy(struct videobuf_queue *q);
-void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q);
-
-void videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,
-		     enum v4l2_buf_type type);
-int videobuf_reqbufs(struct file *file, struct videobuf_queue *q,
-		     struct v4l2_requestbuffers *req);
-int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b);
-int videobuf_qbuf(struct file *file, struct videobuf_queue *q,
-		  struct v4l2_buffer *b);
-int videobuf_dqbuf(struct file *file, struct videobuf_queue *q,
-		   struct v4l2_buffer *b);
-int videobuf_streamon(struct file *file, struct videobuf_queue *q);
-int videobuf_streamoff(struct file *file, struct videobuf_queue *q);
-
-int videobuf_read_start(struct file *file, struct videobuf_queue *q);
-void videobuf_read_stop(struct file *file, struct videobuf_queue *q);
-ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q,
-			     char *data, size_t count, loff_t *ppos,
-			     int vbihack);
-ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q,
-			  char *data, size_t count, loff_t *ppos);
-unsigned int videobuf_poll_stream(struct file *file,
-				  struct videobuf_queue *q,
-				  poll_table *wait);
-
-int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q,
-			int bcount, int bsize);
-int videobuf_mmap_free(struct file *file, struct videobuf_queue *q);
-int videobuf_mmap_mapper(struct vm_area_struct *vma,
-			 struct videobuf_queue *q);
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff -Nru a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
--- a/drivers/media/video/zoran.h	Tue Feb  5 11:10:31 2002
+++ b/drivers/media/video/zoran.h	Sun Feb 16 16:16:53 2003
@@ -32,10 +32,6 @@
 
 #include <linux/config.h>
 
-#if LINUX_VERSION_CODE < 0x20212
-typedef struct wait_queue *wait_queue_head_t;
-#endif
-
 /* The Buz only supports a maximum width of 720, but some V4L
    applications (e.g. xawtv are more happy with 768).
    If XAWTV_HACK is defined, we try to fake a device with bigger width */
diff -Nru a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
--- a/drivers/media/video/zr36120.c	Thu Feb  6 07:33:47 2003
+++ b/drivers/media/video/zr36120.c	Sun Feb 16 16:16:53 2003
@@ -943,7 +943,6 @@
 	return -EINVAL;
 }
 
-#if LINUX_VERSION_CODE >= 0x020100
 static
 unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait)
 {
@@ -964,7 +963,6 @@
 
 	return mask;
 }
-#endif
 
 /* append a new clipregion to the vector of video_clips */
 static
@@ -1745,7 +1743,6 @@
 	return count;
 }
 
-#if LINUX_VERSION_CODE >= 0x020100
 static
 unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait)
 {
@@ -1766,7 +1763,6 @@
 
 	return mask;
 }
-#endif
 
 static
 int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
diff -Nru a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h
--- a/drivers/message/fusion/lsi/mpi_raid.h	Fri Feb 21 06:26:38 2003
+++ b/drivers/message/fusion/lsi/mpi_raid.h	Thu Feb 20 08:33:15 2003
@@ -184,7 +184,7 @@
 
 
 /****************************************************************************/
-/* Mailbox reqeust structure */
+/* Mailbox request structure */
 /****************************************************************************/
 
 typedef struct _MSG_MAILBOX_REQUEST
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Tue Feb 25 11:05:27 2003
+++ b/drivers/message/i2o/i2o_block.c	Sat Mar  8 14:50:22 2003
@@ -1608,12 +1608,8 @@
 	/*
 	 *	Register the block device interfaces
 	 */
-
-	if (register_blkdev(MAJOR_NR, "i2o_block", &i2ob_fops)) {
-		printk(KERN_ERR "Unable to get major number %d for i2o_block\n",
-		       MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "i2o_block"))
 		return -EIO;
-	}
 
 	for (i = 0; i < MAX_I2OB; i++) {
 		struct gendisk *disk = alloc_disk(16);
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Wed Feb 26 05:35:35 2003
+++ b/drivers/mtd/ftl.c	Sat Mar  8 14:50:22 2003
@@ -1281,11 +1281,9 @@
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
 	DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n");
 
-	if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
-		printk(KERN_NOTICE "ftl_cs: unable to grab major "
-		       "device number!\n");
+	if (register_blkdev(FTL_MAJOR, "ftl"))
 		return -EAGAIN;
-	}
+
 	blk_init_queue(&ftl_queue, &do_ftl_request, &lock);
 	register_mtd_user(&ftl_notifier);
 	return 0;
diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
--- a/drivers/mtd/mtdblock.c	Tue Feb 11 14:57:51 2003
+++ b/drivers/mtd/mtdblock.c	Sat Mar  8 14:50:22 2003
@@ -570,11 +570,10 @@
 int __init init_mtdblock(void)
 {
 	spin_lock_init(&mtdblks_lock);
-	if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-		       MTD_BLOCK_MAJOR);
+
+	if (register_blkdev(MAJOR_NR, DEVICE_NAME))
 		return -EAGAIN;
-	}
+
 #ifdef CONFIG_DEVFS_FS
 	devfs_mk_dir(NULL, DEVICE_NAME, NULL);
 #endif
diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
--- a/drivers/mtd/mtdblock_ro.c	Mon Oct 28 11:57:56 2002
+++ b/drivers/mtd/mtdblock_ro.c	Sat Mar  8 14:50:22 2003
@@ -240,20 +240,13 @@
 
 int __init init_mtdblock(void)
 {
-	int err;
-
-	if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-		       MTD_BLOCK_MAJOR);
-		err = -EAGAIN;
-		goto out;
-	}
+	if (register_blkdev(MAJOR_NR, DEVICE_NAME))
+		return -EAGAIN;
 
 	blk_init_queue(&mtdro_queue, &mtdblock_request, &mtdro_lock);
 	register_mtd_user(&notifier);
-	err = 0;
- out:
-	return err;
+
+	return 0;
 }
 
 static void __exit cleanup_mtdblock(void)
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Wed Feb 26 05:35:01 2003
+++ b/drivers/mtd/nftlcore.c	Sat Mar  8 14:50:22 2003
@@ -928,10 +928,8 @@
 	printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.82 $, nftlmount.c %s\n", nftlmountrev);
 #endif
 
-	if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)) {
-		printk("unable to register NFTL block device on major %d\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "nftl"))
 		return -EBUSY;
-	}
 
 	blk_register_region(MKDEV(MAJOR_NR, 0), 256,
 			THIS_MODULE, nftl_probe, NULL, NULL);
diff -Nru a/drivers/net/bonding.c b/drivers/net/bonding.c
--- a/drivers/net/bonding.c	Tue Feb 18 10:50:38 2003
+++ b/drivers/net/bonding.c	Sat Mar  8 14:50:38 2003
@@ -2574,6 +2574,13 @@
 		return 0;
 	}
 
+	if (bond->slave_cnt == 0) {
+		/* no slaves in the bond, frame not sent */
+		dev_kfree_skb(skb);
+		read_unlock_irqrestore(&bond->lock, flags);
+		return 0;
+	}
+	
 	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
 
 	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c
--- a/drivers/net/dgrs.c	Tue Feb 25 11:05:27 2003
+++ b/drivers/net/dgrs.c	Tue Mar  4 22:44:07 2003
@@ -981,7 +981,7 @@
 {
 	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
 	int		is;
-	int		i;
+	unsigned long	i;
 
 	static int	iv2is[16] = {
 				0, 0, 0, ES4H_IS_INT3,
@@ -1140,7 +1140,7 @@
 dgrs_probe1(struct net_device *dev)
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
-	int		i;
+	unsigned long	i;
 	int		rc;
 
 	printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n",
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c	Sun Mar  2 18:12:52 2003
+++ b/drivers/net/e100/e100_main.c	Sun Mar 16 22:33:15 2003
@@ -3784,11 +3784,15 @@
 		return -EOPNOTSUPP;
 	}
 
-	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
+	if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) {
+		kfree(strings);
 		return -EFAULT;
+	}
 
-	if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN))
+	if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) {
+		kfree(strings);
 		return -EFAULT;
+	}
 
 	kfree(strings);
 	return 0;
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Mon Feb 24 10:34:28 2003
+++ b/drivers/net/eepro100.c	Sat Mar  8 18:51:49 2003
@@ -529,8 +529,6 @@
 static int eepro100_init_one(struct pci_dev *pdev,
 		const struct pci_device_id *ent);
 
-static void eepro100_remove_one (struct pci_dev *pdev);
-
 static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
@@ -843,6 +841,7 @@
 	sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
 	sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
 	init_timer(&sp->timer); /* used in ioctl() */
+	spin_lock_init(&sp->lock);
 
 	sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
 	if (card_idx >= 0) {
@@ -994,7 +993,6 @@
 	sp->dirty_tx = 0;
 	sp->last_cmd = 0;
 	sp->tx_full = 0;
-	spin_lock_init(&sp->lock);
 	sp->in_interrupt = 0;
 
 	/* .. we can safely take handler calls during init. */
diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c
--- a/drivers/net/eth16i.c	Tue Feb 25 02:08:43 2003
+++ b/drivers/net/eth16i.c	Thu Mar  6 09:23:56 2003
@@ -1404,7 +1404,6 @@
 static char* mediatype[MAX_ETH16I_CARDS];
 static int debug = -1;
 
-#if (LINUX_VERSION_CODE >= 0x20115) 
 MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
 MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
 MODULE_LICENSE("GPL");
@@ -1423,7 +1422,6 @@
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
-#endif
 
 int init_module(void)
 {
diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c
--- a/drivers/net/mac8390.c	Sun Feb  9 17:29:54 2003
+++ b/drivers/net/mac8390.c	Sun Feb 16 16:17:32 2003
@@ -376,11 +376,9 @@
 }
 
 #ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
 MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
 MODUEL_LICENSE("GPL");
-#endif
 
 int init_module(void)
 {
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c	Tue Feb 25 09:17:47 2003
+++ b/drivers/net/pppoe.c	Thu Mar  6 11:06:44 2003
@@ -538,7 +538,7 @@
 	if (!sk)
 		return 0;
 
-	if (sk->dead != 0)
+	if (test_bit(SOCK_DEAD, &sk->flags))
 		return -EBADF;
 
 	pppox_unbind_sock(sk);
@@ -777,7 +777,7 @@
 
 
 int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		  int total_len, struct scm_cookie *scm)
+		  int total_len)
 {
 	struct sk_buff *skb = NULL;
 	struct sock *sk = sock->sk;
@@ -788,7 +788,7 @@
 	struct net_device *dev;
 	char *start;
 
-	if (sk->dead || !(sk->state & PPPOX_CONNECTED)) {
+	if (test_bit(SOCK_DEAD, &sk->flags) || !(sk->state & PPPOX_CONNECTED)) {
 		error = -ENOTCONN;
 		goto end;
 	}
@@ -864,7 +864,7 @@
 	int data_len = skb->len;
 	struct sk_buff *skb2;
 
-	if (sk->dead  || !(sk->state & PPPOX_CONNECTED))
+	if (test_bit(SOCK_DEAD, &sk->flags)  || !(sk->state & PPPOX_CONNECTED))
 		goto abort;
 
 	hdr.ver	= 1;
@@ -937,7 +937,8 @@
 
 struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL };
 
-int pppoe_rcvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm)
+int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
+		  struct msghdr *m, int total_len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb = NULL;
@@ -1089,7 +1090,7 @@
     .setsockopt		= sock_no_setsockopt,
     .getsockopt		= sock_no_getsockopt,
     .sendmsg		= pppoe_sendmsg,
-    .recvmsg		= pppoe_rcvmsg,
+    .recvmsg		= pppoe_recvmsg,
     .mmap		= sock_no_mmap
 };
 
diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c
--- a/drivers/net/shaper.c	Sat Feb 15 11:32:47 2003
+++ b/drivers/net/shaper.c	Tue Mar  4 22:44:07 2003
@@ -88,10 +88,10 @@
 #include <net/arp.h>
 
 struct shaper_cb { 
+	unsigned long	shapeclock;		/* Time it should go out */
+	unsigned long	shapestamp;		/* Stamp for shaper    */
 	__u32		shapelatency;		/* Latency on frame */
-	__u32		shapeclock;		/* Time it should go out */
 	__u32		shapelen;		/* Frame length in clocks */
-	__u32		shapestamp;		/* Stamp for shaper    */
 	__u16		shapepend;		/* Pending */
 }; 
 #define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb))
@@ -335,7 +335,7 @@
 		 */
 		 
 		if(sh_debug)
-			printk("Clock = %d, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies);
+			printk("Clock = %ld, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies);
 		if(time_before_eq(SHAPERCB(skb)->shapeclock - jiffies, SHAPER_BURST))
 		{
 			/*
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	Tue Feb 25 02:45:05 2003
+++ b/drivers/net/sis900.c	Tue Mar  4 22:44:07 2003
@@ -509,7 +509,7 @@
 {
 	struct sis900_private * sis_priv = net_dev->priv;
 	u16 poll_bit = MII_STAT_LINK, status = 0;
-	unsigned int timeout = jiffies + 5 * HZ;
+	unsigned long timeout = jiffies + 5 * HZ;
 	int phy_addr;
 	u8 revision;
 
diff -Nru a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
--- a/drivers/net/sk98lin/h/skgepnm2.h	Mon Feb  4 23:42:03 2002
+++ b/drivers/net/sk98lin/h/skgepnm2.h	Thu Mar  6 08:18:07 2003
@@ -341,7 +341,7 @@
 #if SK_TICKS_PER_SEC == 100
 #define SK_PNMI_HUNDREDS_SEC(t)	(t)
 #else
-#define SK_PNMI_HUNDREDS_SEC(t)	(((t) * 100) / (SK_TICKS_PER_SEC))
+#define SK_PNMI_HUNDREDS_SEC(t)	((((long)t) * 100) / (SK_TICKS_PER_SEC))
 #endif
 
 /*
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c	Mon Feb 24 12:16:14 2003
+++ b/drivers/net/sk_mca.c	Thu Mar  6 09:24:43 2003
@@ -649,9 +649,7 @@
 				skb->protocol = eth_type_trans(skb, dev);
 				skb->ip_summed = CHECKSUM_NONE;
 				priv->stat.rx_packets++;
-#if LINUX_VERSION_CODE >= 0x020119	/* byte counters for >= 2.1.25 */
 				priv->stat.rx_bytes += descr.Len;
-#endif
 				netif_rx(skb);
 				dev->last_rx = jiffies;
 			}
@@ -709,9 +707,7 @@
 		/* update statistics */
 		if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) {
 			priv->stat.tx_packets++;
-#if LINUX_VERSION_CODE >= 0x020119	/* byte counters for >= 2.1.25 */
 			priv->stat.tx_bytes++;
-#endif
 		} else {
 			priv->stat.tx_errors++;
 			if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) {
@@ -1001,13 +997,8 @@
 
       tx_done:
 
-	/* When did that change exactly ? */
-
-#if LINUX_VERSION_CODE >= 0x020200
 	dev_kfree_skb(skb);
-#else
-	dev_kfree_skb(skb, FREE_WRITE);
-#endif
+
 	return retval;
 }
 
@@ -1146,9 +1137,7 @@
 		mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter");
 	mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev);
 
-#if LINUX_VERSION_CODE >= 0x020200
 	mca_mark_as_used(slot);
-#endif
 
 	/* announce success */
 	printk("%s: SKNet %s adapter found in slot %d\n", dev->name,
@@ -1283,9 +1272,7 @@
 				free_irq(dev->irq, dev);
 			dev->irq = 0;
 			unregister_netdev(dev);
-#if LINUX_VERSION_CODE >= 0x020200
 			mca_mark_as_unused(priv->slot);
-#endif
 			mca_set_adapter_procfn(priv->slot, NULL, NULL);
 			kfree(dev->priv);
 			dev->priv = NULL;
diff -Nru a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c
--- a/drivers/net/wan/comx-hw-munich.c	Tue Feb 25 02:45:14 2003
+++ b/drivers/net/wan/comx-hw-munich.c	Thu Mar  6 09:25:13 2003
@@ -812,13 +812,8 @@
 
 	printk("munich_probe: munich chip found, IRQ %d\n", pci->irq);
 
-#if (LINUX_VERSION_CODE < 0x02030d)
-	bar1 = ioremap_nocache(pci->base_address[0], 0x100);
-	lbi = ioremap_nocache(pci->base_address[1], 0x100);
-#else
 	bar1 = ioremap_nocache(pci->resource[0].start, 0x100);
 	lbi = ioremap_nocache(pci->resource[1].start, 0x100);
-#endif
 
 	if (bar1 && lbi)
 	{
diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
--- a/drivers/net/wan/pc300_tty.c	Thu Nov 21 14:06:12 2002
+++ b/drivers/net/wan/pc300_tty.c	Sun Feb 16 16:22:42 2003
@@ -198,12 +198,6 @@
 	int port, aux;
 	st_cpc_tty_area * cpc_tty;
 
-	if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) {
-		printk("%s-tty: Error: TTY driver is supported on 2.4.X kernel!\n",
-			((struct net_device*)(pc300dev->hdlc))->name);
-		return;
-	}
-	
 	/* hdlcX - X=interface number */
 	port = ((struct net_device*)(pc300dev->hdlc))->name[4] - '0';
 	if (port >= CPC_TTY_NPORTS) {
diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
--- a/drivers/net/wan/sdla_chdlc.c	Tue Feb 25 02:45:24 2003
+++ b/drivers/net/wan/sdla_chdlc.c	Thu Mar  6 09:25:13 2003
@@ -60,14 +60,9 @@
 #include <linux/if_arp.h>	/* ARPHRD_* defines */
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
- #include <asm/uaccess.h>
- #include <linux/inetdevice.h>
- #include <linux/netdevice.h>
-#else 				
- #include <asm/segment.h>
- #include <net/route.h>          /* Adding new route entries : 2.0.X kernels */
-#endif
+#include <asm/uaccess.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
 
 #include <linux/in.h>		/* sockaddr_in */
 #include <linux/inet.h>	
@@ -153,13 +148,11 @@
 	unsigned short timer_int_enabled;
 	char update_comms_stats;		/* updating comms stats */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	bh_data_t *bh_head;	  	  /* Circular buffer for chdlc_bh */
 	unsigned long  tq_working;
 	volatile int  bh_write;
 	volatile int  bh_read;
 	atomic_t  bh_buff_used;
-#endif
 	
 	unsigned char interface_down;
 
@@ -204,15 +197,8 @@
 static int if_header (struct sk_buff* skb, netdevice_t* dev,
 	unsigned short type, void* daddr, void* saddr, unsigned len);
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-  static int if_rebuild_hdr (struct sk_buff *skb);
-  static struct net_device_stats* if_stats (netdevice_t* dev);
-
-#else
-  static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-        struct sk_buff* skb);
-  static struct enet_statistics* if_stats (netdevice_t* dev);
-#endif
+static int if_rebuild_hdr (struct sk_buff *skb);
+static struct net_device_stats* if_stats (netdevice_t* dev);
   
 static int if_send (struct sk_buff* skb, netdevice_t* dev);
 
@@ -228,9 +214,7 @@
 
 
 static int chdlc_disable_comm_shutdown (sdla_t *card);
-#ifdef LINUX_2_4
-  static void if_tx_timeout (netdevice_t *dev);
-#endif
+static void if_tx_timeout (netdevice_t *dev);
 
 /* Miscellaneous CHDLC Functions */
 static int set_chdlc_config (sdla_t* card);
@@ -260,12 +244,10 @@
 static void rx_intr (sdla_t* card);
 static void timer_intr(sdla_t *);
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-  /* Bottom half handlers */
-  static void chdlc_work (netdevice_t *);
-  static int chdlc_work_cleanup (netdevice_t *);
-  static int bh_enqueue (netdevice_t *, struct sk_buff *);
-#endif
+/* Bottom half handlers */
+static void chdlc_work (netdevice_t *);
+static int chdlc_work_cleanup (netdevice_t *);
+static int bh_enqueue (netdevice_t *, struct sk_buff *);
 
 /* Miscellaneous functions */
 static int chk_bcast_mcast_addr(sdla_t* card, netdevice_t* dev,
@@ -287,8 +269,6 @@
 
 /* TTY Global Definitions */
 
-#if defined(LINUX_2_4) || defined(LINUX_2_1)
-
 #define NR_PORTS 4
 #define WAN_TTY_MAJOR 226
 #define WAN_TTY_MINOR 0
@@ -321,8 +301,6 @@
 
 static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL};
 
-#endif
-
 
 /****** Public Functions ****************************************************/
 
@@ -569,7 +547,6 @@
 	}
 
 	if ((card->tty_opt=conf->tty) == WANOPT_YES){
-#if defined(LINUX_2_4) || defined(LINUX_2_1)	
 		int err;
 		card->tty_minor = conf->tty_minor;
 
@@ -582,11 +559,6 @@
 		if (err){
 			return err;
 		}
-#else
-		printk(KERN_INFO "%s: Error: TTY driver is not supported on 2.0.X kernels!\n",
-				card->devname);	
-		return -EINVAL;  
-#endif
 	}else{
 	
 
@@ -851,18 +823,6 @@
 			min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) :
 			DEFAULT_SLARP_REQ_TIMER;
 
-#ifdef LINUX_2_0
-		if (card->u.c.slarp_timer){
-			printk(KERN_INFO 
-				"%s: Error: Dynamic IP support not available for 2.0.X kernels\n",
-					card->devname);
-			printk(KERN_INFO "%s:        Defaulting to Static IP addressing\n",
-						card->devname);
-		}
-		card->u.c.slarp_timer=0;
-#endif	
-
-
 		if (conf->hdlc_streaming == WANOPT_YES) {
 			printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n",
 				wandev->name);
@@ -892,40 +852,24 @@
 			} 
 
 		} else if( strcmp(conf->usedby, "API") == 0) {
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 			card->u.c.usedby = API;
 			printk(KERN_INFO "%s: Running in API mode !\n",
 				wandev->name);
-#else
-			printk(KERN_INFO "%s: API Mode is not supported for kernels lower than 2.2.X!\n",
-				wandev->name);
-			printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel fro the API support\n",
-				wandev->name);
-	                kfree(chdlc_priv_area);
-			return -EINVAL;
-#endif
 		}
 	}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	/* Tells us that if this interface is a
          * gateway or not */
 	if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){
 		printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
 			card->devname,card->u.c.if_name);
 	}
-#endif
 
 	/* Get Multicast Information */
 	chdlc_priv_area->mc = conf->mc;
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
 	strcpy(dev->name,card->u.c.if_name);
-#else
-	dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); 
-	sprintf(dev->name, "%s", card->u.c.if_name);
-#endif
 
 	dev->init = &if_init;
 	dev->priv = chdlc_priv_area;
@@ -958,9 +902,6 @@
 	chdlc_private_area_t* chdlc_priv_area = dev->priv;
 	sdla_t* card = chdlc_priv_area->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -969,10 +910,8 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 	
 	/* Initialize media-specific parameters */
@@ -984,16 +923,8 @@
 		dev->flags 	|= IFF_MULTICAST;
 	}
 	
-#ifdef LINUX_2_0
-	dev->family		= AF_INET;
-#endif	
-
 	if (chdlc_priv_area->true_if_encoding){
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		dev->type	= ARPHRD_HDLC; /* This breaks the tcpdump */
-#else
-		dev->type	= ARPHRD_PPP;
-#endif
 	}else{
 		dev->type	= ARPHRD_PPP;
 	}
@@ -1019,11 +950,6 @@
 	 */
         dev->tx_queue_len = 100;
    
-	/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-#endif
 	return 0;
 }
 
@@ -1043,10 +969,9 @@
 
 	/* Only one open per interface is allowed */
 
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	/* Initialize the work queue entry */
 	chdlc_priv_area->tq_working=0;
 
@@ -1058,18 +983,11 @@
 	chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
 	memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
 	atomic_set(&chdlc_priv_area->bh_buff_used, 0);
-#endif
  
 	do_gettimeofday(&tv);
 	chdlc_priv_area->router_start_time = tv.tv_sec;
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 
 	wanpipe_open(card);
 
@@ -1100,8 +1018,6 @@
 	chdlc_private_area_t* chdlc_priv_area = dev->priv;
 	sdla_t* card = chdlc_priv_area->card;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	if (chdlc_priv_area->bh_head){
 		int i;
 		struct sk_buff *skb;
@@ -1109,18 +1025,14 @@
 		for (i=0; i<(MAX_BH_BUFF+1); i++){
 			skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb;
 			if (skb != NULL){
-                		wan_dev_kfree_skb(skb, FREE_READ);
+                		dev_kfree_skb_any(skb);
 			}
 		}
 		kfree(chdlc_priv_area->bh_head);
 		chdlc_priv_area->bh_head=NULL;
 	}
-#endif
 
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 	wanpipe_close(card);
 	del_timer(&chdlc_priv_area->poll_delay_timer);
 	return 0;
@@ -1136,7 +1048,6 @@
 		flags->interrupt_info_struct.interrupt_permission = 0;	
 	}
 
-#if defined(LINUX_2_4) || defined(LINUX_2_1)	
 	if (!tty_init_cnt)
 		return;
 
@@ -1160,7 +1071,6 @@
 		state = &rs_table[card->tty_minor];
 		memset(state,0,sizeof(state));
 	}
-#endif
 	return;
 }
 
@@ -1183,7 +1093,6 @@
 }
 
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -1203,7 +1112,6 @@
 	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
 	netif_wake_queue (dev);
 }
-#endif
 
 
 
@@ -1213,18 +1121,11 @@
  * Return:	1	physical address resolved.
  *		0	physical address not resolved
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff *skb)
 {
 	return 1;
 }
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-                           struct sk_buff* skb)
-{
-        return 1;
-}
-#endif
+
 
 /*============================================================================
  * Send a packet on a network interface.
@@ -1253,9 +1154,7 @@
 	unsigned long smp_flags;
 	int err=0;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 	
 	if (skb == NULL){
 		/* If we get here, some higher layer thinks we've missed an
@@ -1264,31 +1163,10 @@
 		printk(KERN_INFO "%s: interface %s got kicked!\n",
 			card->devname, dev->name);
 
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
-#ifndef LINUX_2_4
-	if (dev->tbusy){
-
-		/* If our device stays busy for at least 5 seconds then we will
-		 * kick start the device by making dev->tbusy = 0.  We expect 
-		 * that our device never stays busy more than 5 seconds. So this
-		 * is only used as a last resort. 
-		 */
-                ++card->wandev.stats.collisions;
-		if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) {
-			return 1;
-		}
-
-		printk (KERN_INFO "%s: Transmit timeout !\n",
-			card->devname);
-
-		/* unbusy the interface */
-		clear_bit(0,&dev->tbusy);
-	}
-#endif
-
    	if (ntohs(skb->protocol) != htons(PVC_PROT)){
 
 		/* check the udp packet type */
@@ -1301,7 +1179,7 @@
 	                	chdlc_int->interrupt_permission |=
 					APP_INT_ON_TIMER;
 			}
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			return 0;
 		}
 
@@ -1309,8 +1187,8 @@
 		/* multicast IP address */
                 if(chk_bcast_mcast_addr(card, dev, skb)){
 			++card->wandev.stats.tx_dropped;
-			wan_dev_kfree_skb(skb,FREE_WRITE);
-			start_net_queue(dev);
+			dev_kfree_skb_any(skb);
+			netif_start_queue(dev);
 			return 0;
 		}
         }
@@ -1325,17 +1203,17 @@
 		printk(KERN_INFO "%s: Critical in if_send: %lx\n",
 					card->wandev.name,card->wandev.critical);
                 ++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_exit_crit;
 	}
 
 	if(card->u.c.state != WAN_CONNECTED){
        		++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
 	}else if(!skb->protocol){
         	++card->wandev.stats.tx_errors;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
 	}else {
 		void* data = skb->data;
@@ -1355,7 +1233,7 @@
 				(len <= sizeof(api_tx_hdr_t))) {
 				
 				++card->wandev.stats.tx_dropped;
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				goto if_send_exit_crit;
 			}
 				
@@ -1366,25 +1244,21 @@
 		}
 
 		if(chdlc_send(card, data, len)) {
-			stop_net_queue(dev);
+			netif_stop_queue(dev);
 		}else{
 			++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                         card->wandev.stats.tx_bytes += len;
-#endif
 			
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			
-#ifdef LINUX_2_4
 		 	dev->trans_start = jiffies;
-#endif
 		}	
 	}
 
 if_send_exit_crit:
 	
-	if (!(err=is_queue_stopped(dev))) {
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+	if (!(err=netif_queue_stopped(dev))) {
+		dev_kfree_skb_any(skb);
 	}else{
 		chdlc_priv_area->tick_counter = jiffies;
 		chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
@@ -1409,14 +1283,12 @@
 {
 	u32 src_ip_addr;
         u32 broadcast_ip_addr = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct in_device *in_dev;
-#endif
+
         /* read the IP source address from the outgoing packet */
         src_ip_addr = *(u32 *)(skb->data + 12);
 
 	/* read the IP broadcast address for the device */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         in_dev = dev->ip_ptr;
         if(in_dev != NULL) {
                 struct in_ifaddr *ifa= in_dev->ifa_list;
@@ -1425,9 +1297,6 @@
                 else
                         return 0;
         }
-#else
-        broadcast_ip_addr = dev->pa_brdaddr;
-#endif
  
         /* check if the IP Source Address is a Broadcast address */
         if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
@@ -1552,7 +1421,6 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct enet_statistics.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats* if_stats (netdevice_t* dev)
 {
 	sdla_t *my_card;
@@ -1564,19 +1432,7 @@
 	my_card = chdlc_priv_area->card;
 	return &my_card->wandev.stats; 
 }
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev)
-{
-        sdla_t *my_card;
-        chdlc_private_area_t* chdlc_priv_area = dev->priv;
 
-	if ((chdlc_priv_area=dev->priv) == NULL)
-		return NULL;
-
-        my_card = chdlc_priv_area->card;
-        return &my_card->wandev.stats;
-}
-#endif
 
 /****** Cisco HDLC Firmware Interface Functions *******************************/
 
@@ -1846,7 +1702,7 @@
 	return 0;
 }
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
+
 /********** Bottom Half Handlers ********************************************/
 
 /* NOTE: There is no API, BH support for Kernels lower than 2.2.X.
@@ -1873,7 +1729,7 @@
 
 			if (chan->common.sk == NULL || chan->common.func == NULL){
 				++card->wandev.stats.rx_dropped;
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 				chdlc_work_cleanup(dev);
 				continue;
 			}
@@ -1921,7 +1777,7 @@
 
 	if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
 		++card->wandev.stats.rx_dropped;
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 		return 1; 
 	}
 
@@ -1940,7 +1796,6 @@
 
 /* END OF API BH Support */
 
-#endif
 
 /****** Interrupt Handlers **************************************************/
 
@@ -2017,24 +1872,19 @@
 		flags->interrupt_info_struct.interrupt_permission &=
 			 ~APP_INT_ON_TX_FRAME;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 		if (card->tty_opt){
 			wanpipe_tty_trigger_poll(card);
 			break;
 		}
 
-		if (dev && is_queue_stopped(dev)){
+		if (dev && netif_queue_stopped(dev)){
 			if (card->u.c.usedby == API){
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				wakeup_sk_bh(dev);
 			}else{
-				wake_net_dev(dev);
+				netif_wake_queue(dev);
 			}
 		}
-#else
-		wake_net_dev(dev);
-#endif
 		break;
 
 	case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
@@ -2120,7 +1970,6 @@
 
 	len  = rxbuf->frame_length;
 
-#if defined(LINUX_2_4) || defined(LINUX_2_1)	
 	if (card->tty_opt){
 
 		if (rxbuf->error_flag){	
@@ -2138,7 +1987,6 @@
 		wanpipe_tty_receive(card,addr,len);
 		goto rx_exit;
 	}
-#endif
 
 	dev = card->wandev.dev;
 
@@ -2146,7 +1994,7 @@
 		goto rx_exit;
 	}
 
-	if (!is_dev_running(dev))
+	if (!netif_running(dev))
 		goto rx_exit;
 
 	chdlc_priv_area = dev->priv;
@@ -2177,9 +2025,7 @@
 	skb->protocol = htons(ETH_P_IP);
 
 	card->wandev.stats.rx_packets ++;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	card->wandev.stats.rx_bytes += skb->len;
-#endif
 	udp_type = udp_pkt_type( skb, card );
 
 	if(udp_type == UDP_CPIPE_TYPE) {
@@ -2189,7 +2035,6 @@
 						interrupt_permission |= 
 							APP_INT_ON_TIMER; 
 		}
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	} else if(card->u.c.usedby == API) {
 
 		api_rx_hdr_t* api_rx_hdr;
@@ -2207,7 +2052,6 @@
 
 		if (!test_and_set_bit(0,&chdlc_priv_area->tq_working))
 			wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work);
-#endif
 	}else{
 		/* FIXME: we should check to see if the received packet is a 
                           multicast packet so that we can increment the multicast 
@@ -2331,7 +2175,6 @@
 		netdevice_t * dev = card->wandev.dev;
 		chdlc_private_area_t *chdlc_priv_area = dev->priv;
 		
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                 struct in_device *in_dev = dev->ip_ptr;
 
 		if(in_dev != NULL) {
@@ -2344,12 +2187,6 @@
 				chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); 
 			}
 		}
-#else
-                cfg.IP_address          = ntohl(dev->pa_addr);
-                cfg.IP_netmask          = ntohl(dev->pa_mask);
-		chdlc_priv_area->IP_address = ntohl(dev->pa_addr);
-		chdlc_priv_area->IP_netmask = ntohl(dev->pa_mask);
-#endif
 
 		/* FIXME: We must re-think this message in next release
 		if((cfg.IP_address & 0x000000FF) > 2) {
@@ -2647,15 +2484,10 @@
 	u32 remote_IP_addr = 0;
 	u32 IP_netmask, IP_addr;
         int err = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct in_device *in_dev;
 	mm_segment_t fs;
 	struct ifreq if_info;
         struct sockaddr_in *if_data1, *if_data2;
-#else
-	unsigned long fs = 0;
-        struct rtentry route;
-#endif
 	
         chdlc_priv_area = dev->priv;
         port_num = card->u.c.comm_port;
@@ -2705,7 +2537,6 @@
 	                return;
         	}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                 in_dev = dev->ip_ptr;
 
                 if(in_dev != NULL) {
@@ -2715,11 +2546,6 @@
                                 IP_netmask  = ifa->ifa_mask;
                         }
                 }
-#else
-                local_IP_addr = dev->pa_addr;
-                remote_IP_addr = dev->pa_dstaddr;
-                IP_netmask = dev->pa_mask;
-#endif
 	}else{ 
        		/* According to Cisco HDLC, if the point-to-point address is
 		   A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa.
@@ -2749,44 +2575,20 @@
         fs = get_fs();                  /* Save file system  */
         set_fs(get_ds());               /* Get user space block */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         /* Setup a structure for adding/removing routes */
         memset(&if_info, 0, sizeof(if_info));
         strcpy(if_info.ifr_name, dev->name);
 
-#else
-	/* Setup a structure for adding/removing routes */
-	dev->pa_mask = IP_netmask;
-	dev->pa_dstaddr = remote_IP_addr;
-	dev->pa_addr = local_IP_addr;
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev = dev->name;
-	route.rt_flags = 0;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =
-			dev->pa_dstaddr;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =
-			0xFFFFFFFF;
-        ((struct sockaddr_in *)&(route.rt_genmask))->sin_family =
-			AF_INET;
-#endif
-
 	switch (chdlc_priv_area->route_status) {
 
 	case ADD_ROUTE:
 
 		if(!card->u.c.slarp_timer) {
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
 			if_data2->sin_addr.s_addr = remote_IP_addr;
 			if_data2->sin_family = AF_INET;
 			err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
-#else
-                        err = ip_rt_new(&route);
-#endif
 		} else { 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
 			if_data1->sin_addr.s_addr = local_IP_addr;
 			if_data1->sin_family = AF_INET;
@@ -2796,9 +2598,6 @@
 				if_data2->sin_family = AF_INET;
 				err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
 			}
-#else
-               		err = ip_rt_new(&route);
-#endif
 		}
 
                if(err) {
@@ -2819,7 +2618,6 @@
 
 	case REMOVE_ROUTE:
 	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		/* Change the local ip address of the interface to 0.
 		 * This will also delete the destination route.
 		 */
@@ -2835,11 +2633,6 @@
 			err = devinet_ioctl(SIOCSIFADDR,&if_info);
 		
 		}
-#else
-		/* set the point-to-point IP address to 0.0.0.0 */
-		dev->pa_dstaddr = 0; 
-		err = ip_rt_kill(&route);
-#endif
 		if(err) {
 			printk(KERN_INFO
 				"%s: Remove route %u.%u.%u.%u failed, (err %d)\n",
@@ -2880,9 +2673,9 @@
 	}
 
 	if(udp_pkt_src == UDP_PKT_FRM_STACK){
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+		dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 		
 	return(udp_pkt_stored);
@@ -3256,9 +3049,7 @@
 		
 			if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
 				++ card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 				card->wandev.stats.tx_bytes += len;
-#endif
 			}
 		}
 	} else {	
@@ -3808,30 +3599,21 @@
 
 void s508_lock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
         if (card->next){
         	spin_lock(&card->next->wandev.lock);
 	}
-#else
-        disable_irq(card->hw.irq);
-#endif                                                                     
 }
 
 void s508_unlock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
         if (card->next){
         	spin_unlock(&card->next->wandev.lock);
         }
         spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-#else
-        enable_irq(card->hw.irq);
-#endif           
 }
 
 //*********** TTY SECTION ****************
-#if defined(LINUX_2_4) || defined(LINUX_2_1)
 
 static void wanpipe_tty_trigger_tx_irq(sdla_t *card)
 {
@@ -3858,8 +3640,7 @@
 		(tty->ldisc.write_wakeup)(tty);
 	}
 	wake_up_interruptible(&tty->write_wait);
-#if defined(SERIAL_HAVE_POLL_WAIT) || \
-         (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15))
+#if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif	
 	return;
@@ -4479,8 +4260,7 @@
 		return;
 	
 	wake_up_interruptible(&tty->write_wait);
-#if defined(SERIAL_HAVE_POLL_WAIT) || \
-         (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15))
+#if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
@@ -4721,8 +4501,6 @@
 	INIT_WORK(&card->tty_work, tty_poll_work, (void*)card);
 	return 0;
 }
-
-#endif
 
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
--- a/drivers/net/wan/sdla_fr.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdla_fr.c	Thu Mar  6 09:25:30 2003
@@ -229,11 +229,7 @@
 	int inarp_interval;		/* Time between InArp Requests */
 	unsigned long inarp_tick;	/* InArp jiffies tick counter */
 	long interface_down;		/* Bring interface down on disconnect */
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct net_device_stats ifstats;	/* interface statistics */
-      #else
-	struct enet_statistics ifstats;
-      #endif	
 	if_send_stat_t drvstats_if_send;
         rx_intr_stat_t drvstats_rx_intr;
         pipe_mgmt_stat_t drvstats_gen;
@@ -242,14 +238,11 @@
 	unsigned short transmit_length;
 	struct sk_buff *delay_skb;
 
-
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	bh_data_t *bh_head;	  	  /* Circular buffer for chdlc_bh */
 	unsigned long  tq_working;
 	volatile int  bh_write;
 	volatile int  bh_read;
 	atomic_t  bh_buff_used;
-      #endif
 
 	/* Polling task queue. Each interface
          * has its own task queue, which is used
@@ -343,26 +336,14 @@
 static int if_open(netdevice_t *dev);
 static int if_close(netdevice_t *dev);
 
-
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff *skb);
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-        struct sk_buff* skb);
-#endif
 
 static int if_send(struct sk_buff *skb, netdevice_t *dev);
 static int chk_bcast_mcast_addr(sdla_t *card, netdevice_t* dev,
                                 struct sk_buff *skb);
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats *if_stats(netdevice_t *dev);
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev);
-#endif
 
 /* Interrupt handlers */
 static void fr_isr(sdla_t *card);
@@ -417,13 +398,11 @@
 netdevice_t * move_dev_to_next (sdla_t *, netdevice_t *);
 static int check_tx_status(sdla_t *, netdevice_t *);
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 /* Frame Relay Socket API */
 static void trigger_fr_bh (fr_channel_t *);
 static void fr_bh (netdevice_t *);
 static int fr_bh_cleanup (netdevice_t *);
 static int bh_enqueue (netdevice_t *, struct sk_buff *);
-#endif
 
 static void trigger_fr_poll (netdevice_t *);
 static void fr_poll (netdevice_t *);
@@ -886,26 +865,14 @@
 			
 			chan->common.usedby = BRIDGE;
 			
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 			printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", 
 					card->devname);
-#else
-			printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n",
-					card->devname);
-			err = -EPROTONOSUPPORT;
-#endif
 		}else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){
 			
 			chan->common.usedby = BRIDGE_NODE;
 		
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", 
 					card->devname);
-#else
-			printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n",
-					card->devname);
-			err = -EPROTONOSUPPORT;
-#endif
 		}
 
 		if (!err){
@@ -922,18 +889,9 @@
 
         } else if(strcmp(conf->usedby, "API") == 0){
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
                 chan->common.usedby = API;
                 printk(KERN_INFO "%s: Running in API mode.\n",
 			wandev->name);
-#else
-                printk(KERN_INFO "%s: The API Mode is not supported for"
-				 "kernels lower than 2.2.X !\n",
-					wandev->name);
-		printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel for the API support\n",
-					wandev->name);
-                err = -EINVAL;
-#endif
         }
 
 	if (err) {
@@ -980,16 +938,9 @@
 	chan->mc = conf->mc;
 
 	if (conf->inarp == WANOPT_YES){
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname);
 		chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE;
 		chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10;
-#else
-		printk(KERN_INFO "%s: Warning, Inverse ARP Support not available for 2.0.X kernels!\n",
-				card->devname);
-		chan->inarp = INARP_NONE;
-		chan->inarp_interval = 10;
-#endif
 	}else{
 		printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname);
 		chan->inarp = INARP_NONE;
@@ -1023,17 +974,7 @@
 	chan->transmit_length = 0;
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
 	strcpy(dev->name,chan->name);
-#else
-	dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(chan);
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", chan->name);
-#endif
 	
 	dev->init = &if_init;
 	dev->priv = chan;
@@ -1042,9 +983,6 @@
          * We need a poll routine for each network
          * interface. 
          */
-#ifndef LINUX_2_4
-	chan->fr_poll_task.next = NULL;
-#endif
 	chan->fr_poll_task.sync = 0;
 	chan->fr_poll_task.routine = (void *)(void *)fr_poll;
 	chan->fr_poll_task.data = dev;
@@ -1138,8 +1076,6 @@
 	int err, len;
 	fr_cmd_t cmd;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd)))
 		return -EFAULT;
 	
@@ -1169,44 +1105,6 @@
 	if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len))
 		return -EFAULT;
 	return 0;
-
-#else
-        if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(fr_cmd_t)))
-                return -EFAULT;
-
-        memcpy_fromfs((void*)&cmd, u_cmd, sizeof(cmd));
-
-        if (cmd.length) {
-
-                if (!u_data || verify_area(VERIFY_READ, u_data, cmd.length))
-                        return -EFAULT;
-        }
-
-        /* execute command */
-        do
-        {
-                memcpy(&mbox->cmd, &cmd, sizeof(cmd));
-
-                if (cmd.length)
-                        memcpy_fromfs((void*)&mbox->data, u_data, cmd.length);
-
-                if (sdla_exec(mbox))
-                        err = mbox->cmd.result;
-
-                else return -EIO;
-        } while (err && retry-- && fr_event(card, err, mbox));
-
-        /* return result */
-        memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t));
-        len = mbox->cmd.length;
-
-        if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len))
-                memcpy_tofs(u_data, (void*)&mbox->data, len);
-
-        return 0;
-
-#endif
-
 }
 
 /****** Network Device Interface ********************************************/
@@ -1223,9 +1121,6 @@
 	fr_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -1234,15 +1129,11 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 	
 	if (chan->common.usedby == WANPIPE || chan->common.usedby == API){
-#ifdef LINUX_2_0
-		dev->family = AF_INET;
-#endif
+
 		/* Initialize media-specific parameters */
 		if (chan->true_if_encoding){
 			dev->type 		= ARPHRD_DLCI;  /* This breaks tcpdump */
@@ -1274,11 +1165,6 @@
 		/* Set transmit buffer queue length */
         	dev->tx_queue_len = 100;
 
-			/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-	        for (i = 0; i < DEV_NUMBUFFS; ++i)
-			skb_queue_head_init(&dev->buffs[i]);
-#endif
 	}else{
 
 		/* Setup the interface for Bridging */
@@ -1315,16 +1201,12 @@
 	int err = 0;
 	struct timeval tv;
 
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	/* Initialize the task queue */
 	chan->tq_working=0;
 
-#ifndef LINUX_2_4
-	chan->common.wanpipe_task.next = NULL;
-#endif
 	chan->common.wanpipe_task.sync = 0;
 	chan->common.wanpipe_task.routine = (void *)(void *)fr_bh;
 	chan->common.wanpipe_task.data = dev;
@@ -1333,15 +1215,8 @@
 	chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC);
 	memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF));
 	atomic_set(&chan->bh_buff_used, 0);
-#endif
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else	
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 
 	wanpipe_open(card);
 	do_gettimeofday( &tv );
@@ -1370,10 +1245,7 @@
 		chan->inarp = INARP_REQUEST;
 	}
 
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 	wanpipe_close(card);
 
 	return 0;
@@ -1385,18 +1257,10 @@
  * Return:	1	physical address resolved.
  *		0	physical address not resolved
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff* skb)
 {
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-                           struct sk_buff* skb)
-{
-#endif
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 	netdevice_t *dev = skb->dev;
-#endif
 	fr_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
 
@@ -1405,7 +1269,6 @@
 	return 1;
 }
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -1429,7 +1292,7 @@
 	netif_wake_queue (dev);
 
 }
-#endif
+
 
 /*============================================================================
  * Send a packet on a network interface.
@@ -1448,7 +1311,7 @@
  * 1. This routine is called either by the protocol stack or by the "net
  *    bottom half" (with interrupts enabled).
  * 
- * 2. Using the start_net_queue() and stop_net_queue() MACROS
+ * 2. Using netif_start_queue() and netif_stop_queue()
  *    will inhibit further transmit requests from the protocol stack 
  *    and can be used for flow control with protocol layer.
  */
@@ -1466,9 +1329,7 @@
 
 	chan->drvstats_if_send.if_send_entry++;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 	
         if (skb == NULL) {             
 		/* if we get here, some higher layer thinks we've missed an
@@ -1478,7 +1339,7 @@
 			card->devname, dev->name);
 		chan->drvstats_if_send.if_send_skb_null ++;
 
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
@@ -1488,8 +1349,8 @@
 		printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n",
 				card->devname);
 		
-		wan_dev_kfree_skb(skb,FREE_WRITE);
-		start_net_queue(dev);
+		dev_kfree_skb_any(skb);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1500,37 +1361,13 @@
 	*/
 	set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
         if(chan->transmit_length) {
-		stop_net_queue(dev);
+		netif_stop_queue(dev);
 		chan->tick_counter = jiffies;
  		clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
 		return 1;
 	}
        	clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
  
-#ifndef LINUX_2_4
-    	if (dev->tbusy) {
-
-		/* If our device stays busy for at least 5 seconds then we will
-                 * kick start the device by making dev->tbusy = 0.  We expect
-                 * that our device never stays busy more than 5 seconds. So this                 
-		 * is only used as a last resort.
-                 */
-		
-		chan->drvstats_if_send.if_send_tbusy++;
-		++chan->ifstats.collisions;
-
-		if ((jiffies - chan->tick_counter) < (5 * HZ)) {
-			return 1;
-		}
-
-		printk(KERN_INFO "%s: Transmit timed out on %s\n", 
-				card->devname, chan->name);
-		chan->drvstats_if_send.if_send_tbusy_timeout ++;
-		dev->tbusy = 0;
-    	}
-#endif
-
-	
 	/* Move the if_header() code to here. By inserting frame
 	 * relay header in if_header() we would break the
 	 * tcpdump and other packet sniffers */
@@ -1539,8 +1376,8 @@
 		++chan->ifstats.tx_dropped;
 		++card->wandev.stats.tx_dropped;
 		
-		wan_dev_kfree_skb(skb,FREE_WRITE);
-		start_net_queue(dev);	
+		dev_kfree_skb_any(skb);
+		netif_start_queue(dev);	
 		return 0;
 	}
 
@@ -1557,7 +1394,7 @@
 					if_send_PIPE_request ++;
 			}
                 }
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1569,8 +1406,8 @@
                 if(chk_bcast_mcast_addr(card, dev, skb)){
             		++chan->ifstats.tx_dropped;
 			++card->wandev.stats.tx_dropped;
-                	wan_dev_kfree_skb(skb, FREE_WRITE);
-			start_net_queue(dev);
+                	dev_kfree_skb_any(skb);
+			netif_start_queue(dev);
 			return 0;
 		}
 	}
@@ -1691,26 +1528,22 @@
 				++chan->ifstats.tx_packets;
 				++card->wandev.stats.tx_packets;
 				
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                                 chan->ifstats.tx_bytes += skb->len;
                                 card->wandev.stats.tx_bytes += skb->len;
-#endif
-#ifdef LINUX_2_4
 				dev->trans_start = jiffies;
-#endif
 			}
 		}
 	}
 
 if_send_start_and_exit:
 
-	start_net_queue(dev);
+	netif_start_queue(dev);
 	
 	/* If we queued the packet for transmission, we must not
 	 * deallocate it. The packet is unlinked from the IP stack
 	 * not copied. Therefore, we must keep the original packet */
 	if (!test_bit(1,&delay_tx_queued)) {
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+                dev_kfree_skb_any(skb);
 	}else{
 		adptr_flags->imask |= FR_INTR_TXRDY;
 		card->u.f.tx_interrupts_pending ++;
@@ -1786,16 +1619,13 @@
 {
         u32 src_ip_addr;
         u32 broadcast_ip_addr = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct in_device *in_dev;
-#endif
         fr_channel_t* chan = dev->priv;
  
         /* read the IP source address from the outgoing packet */
         src_ip_addr = *(u32 *)(skb->data + 14);
 
         /* read the IP broadcast address for the device */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         in_dev = dev->ip_ptr;
         if(in_dev != NULL) {
                 struct in_ifaddr *ifa= in_dev->ifa_list;
@@ -1804,9 +1634,6 @@
                 else
                         return 0;
         }
-#else
-        broadcast_ip_addr = dev->pa_brdaddr;
-#endif
 
         /* check if the IP Source Address is a Broadcast address */
         if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
@@ -1999,11 +1826,7 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct enet_statistics.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats *if_stats(netdevice_t *dev)
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev)
-#endif
 {
 	fr_channel_t* chan = dev->priv;
 	
@@ -2193,7 +2016,7 @@
 
 	skb = dev_alloc_skb(len); 
 
-	if (!is_dev_running(dev) || (skb == NULL)){
+	if (!netif_running(dev) || (skb == NULL)){
 
 		++chan->ifstats.rx_dropped;
 	
@@ -2206,11 +2029,11 @@
 			chan->drvstats_rx_intr.rx_intr_no_socket ++;
 		} 
 
-		if (!is_dev_running(dev)){
+		if (!netif_running(dev)){
 			chan->drvstats_rx_intr.
 				rx_intr_dev_not_started ++;
 			if (skb){
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 			}
 		}
 		goto rx_done;
@@ -2252,7 +2075,6 @@
 			}
 		}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	}else if (chan->common.usedby == API) {
 
 		/* We are in API mode. 
@@ -2281,7 +2103,6 @@
 		bh_enqueue(dev, skb);
 
 		trigger_fr_bh(chan);
-	#endif
 
 	}else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){
 
@@ -2289,7 +2110,7 @@
 		//if (chan->enable_IPX) {
 		//	fr_send(card, dlci, 0, skb->len,skb->data);
 		//}
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 
 	} else if (is_arp(skb->data)) {
 
@@ -2304,7 +2125,7 @@
 					card->devname);
 			}
 		}
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 
 	} else if (skb->data[0] != 0x03) {
 
@@ -2312,7 +2133,7 @@
 			printk(KERN_INFO "%s: Non IETF packet discarded.\n", 
 				card->devname);
 		}
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 
 	} else {
 
@@ -2341,7 +2162,7 @@
 			if (!wanrouter_type_trans(skb, dev)) {
 				
 				/* can't decapsulate packet */
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 
 				++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
 				++chan->ifstats.rx_errors;
@@ -2359,10 +2180,8 @@
 		++chan->ifstats.rx_packets;
 		++card->wandev.stats.rx_packets;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		chan->ifstats.rx_bytes += len_incl_hdr;
 		card->wandev.stats.rx_bytes += len_incl_hdr;
-#endif
 	}
 
 rx_done:
@@ -2454,36 +2273,28 @@
 
 		++chan->ifstats.tx_packets;
 		++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		chan->ifstats.tx_bytes += chan->transmit_length;
 		card->wandev.stats.tx_bytes += chan->transmit_length;
-#endif
 
 		/* We must free an sk buffer, which we used
 		 * for delayed transmission; Otherwise, the sock
 		 * will run out of memory */
-                wan_dev_kfree_skb(chan->delay_skb, FREE_WRITE);
+                dev_kfree_skb_any(chan->delay_skb);
 
 		chan->delay_skb = NULL;				
         	chan->transmit_length = 0;
 
-#ifdef LINUX_2_4
 		dev->trans_start = jiffies;
-#endif
 
-#ifdef LINUX_2_0
-		wake_net_dev(dev);
-#else
-		if (is_queue_stopped(dev)){
+		if (netif_queue_stopped(dev)){
 			/* If using API, than wakeup socket BH handler */
 			if (chan->common.usedby == API){
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				wakeup_sk_bh(dev);
 			}else{
-				wake_net_dev(dev);
+				netif_wake_queue(dev);
 			}
 		}
-#endif
 	}
 
 end_of_tx_intr:
@@ -2778,8 +2589,6 @@
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	struct ifreq if_info;
 	struct sockaddr_in *if_data;
 	mm_segment_t fs = get_fs();
@@ -2851,66 +2660,6 @@
 
 	} /* Case Statement */
 
-#else
-        /* Dynamic Route adding/removing */
-	struct rtentry route;
-        int err = 0;
-        unsigned long fs = get_fs();
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev   = dev->name;
-	route.rt_flags = 0;
-
-	((struct sockaddr_in *) &(route.rt_dst)) ->
-					sin_addr.s_addr=dev->pa_dstaddr;
-	((struct sockaddr_in *) &(route.rt_dst)) ->
-						sin_family = AF_INET;
-	((struct sockaddr_in *) &(route.rt_genmask)) ->
-				sin_addr.s_addr = 0xFFFFFFFF;
-	((struct sockaddr_in *) &(route.rt_genmask)) ->
-						sin_family = AF_INET;
-	switch(chan->route_flag) {
-
-	case ADD_ROUTE:
-
-		set_fs(get_ds());     /* get user space block */
-		err = ip_rt_new(&route);
-		set_fs(fs);           /* restore old block */
-
-		if (err) {
-			printk(KERN_INFO "%s: Adding of route failed.  Error: %d\n", 
-						card->devname,err);
-			printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
-				chan->name, NIPQUAD(dev->pa_dstaddr) );
-			}
-		else {
-			chan->route_flag = ROUTE_ADDED;
-		}
-		break;
-
-	case REMOVE_ROUTE:
-
-		set_fs(get_ds());     /* get user space block */
-		err = ip_rt_kill(&route);
-		set_fs(fs);           /* restore old block */
-
-		if (err) {
-		     printk(KERN_INFO "%s: Deleting of route failed.  Error: %d\n", 
-				card->devname,err);
-		     printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
-				dev->name,NIPQUAD(dev->pa_dstaddr) );
-		} else {
-
-		     printk(KERN_INFO "%s: Removed route.\n",
-			((fr_channel_t*)dev->priv)->name);
-		     chan->route_flag = NO_ROUTE;
-
-		}
-		break;
-	}
-
-#endif	
-
 }
 
 
@@ -3468,7 +3217,7 @@
 					"%s: DLCI %u is inactive!\n",
 					card->devname, dlci);
 
-				if (dev && is_dev_running(dev))
+				if (dev && netif_running(dev))
 					set_chan_state(dev, WAN_DISCONNECTED);
 			}
 	
@@ -3478,7 +3227,7 @@
 					"%s: DLCI %u has been deleted!\n",
 					card->devname, dlci);
 
-				if (dev && is_dev_running(dev)){
+				if (dev && netif_running(dev)){
 
 					fr_channel_t *chan = dev->priv;
 
@@ -3743,9 +3492,9 @@
 	}
 
         if(udp_pkt_src == UDP_PKT_FRM_STACK){
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+                dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 		
         return(udp_pkt_stored);
@@ -4173,8 +3922,6 @@
 {
 	int err=0;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	arphdr_1490_t *ArpPacket;
 	arphdr_fr_t *arphdr;
 	fr_channel_t *chan = dev->priv;
@@ -4225,47 +3972,6 @@
 		return 1;
 	}
 
-#else
-        arphdr_1490_t *ArpPacket;
-        arphdr_fr_t *arphdr;
-        fr_channel_t *chan = dev->priv;
-
-        ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC);
-        /* SNAP Header indicating ARP */
-        ArpPacket->control      = 0x03;
-        ArpPacket->pad          = 0x00;
-        ArpPacket->NLPID        = 0x80;
-        ArpPacket->OUI[0]       = 0;
-        ArpPacket->OUI[1]       = 0;
-        ArpPacket->OUI[2]       = 0;
-        ArpPacket->PID          = 0x0608;
-
-        arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet
-       /* InARP request */
-        arphdr->ar_hrd = 0x0F00;        /* Frame Relay HW type */
-        arphdr->ar_pro = 0x0008;        /* IP Protocol         */
-        arphdr->ar_hln = 2;             /* HW addr length      */
-        arphdr->ar_pln = 4;             /* IP addr length      */
-        arphdr->ar_op = htons(0x08);    /* InARP Request       */
-        arphdr->ar_sha = 0;             /* src HW DLCI - Doesn't matter */
-        arphdr->ar_sip = dev->pa_addr;  /* Local Address       */
-        arphdr->ar_tha = 0;             /* dst HW DLCI - Doesn't matter */
-        arphdr->ar_tip = 0;             /* Remote Address -- what we want */
-
-        printk(KERN_INFO "%s: Sending InARP request on DLCI %d.\n", card->devname, chan->dlci);
-        err = fr_send(card, chan->dlci, 0,
-                   sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t),
-                   (void *)ArpPacket);
-	
-	if (!err){
-         	printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n",
-                        card->devname, chan->dlci);
-                clear_bit(ARP_CRIT,&card->wandev.critical);
-        }
-
-        kfree(ArpPacket);
-#endif
-
 	return 0;
 }
 	
@@ -4293,15 +3999,10 @@
 {
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */
 	fr_rx_buf_ctl_t* frbuf = card->rxmb;
 	struct in_device *in_dev;
 	fr_channel_t *chan = dev->priv;		
-#else
-  	arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */
-        fr_rx_buf_ctl_t* frbuf = card->rxmb;
-#endif
 	
 	/* Before we transmit ARP packet, we must check 
 	 * to see that we are not currently transmitting a 
@@ -4316,8 +4017,6 @@
 		return 0;
 	}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	in_dev = dev->ip_ptr;
 
 	/* Check that IP addresses exist for our network address */
@@ -4434,87 +4133,6 @@
 	}
 
 	return 0;	
-#else
-
-        switch (ntohs(arphdr->ar_op)) {
-
-                case 0x08:  // Inverse ARP request  -- Send Reply, add route.
-
-                        /* Check for valid Address */
-                        printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Req\n", 
-				((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip));
-
-
-			if (dev->pa_mask != 0xFFFFFFFF){
-
-	                        if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) {
-        	                        printk(KERN_INFO "%s: Invalid PtP address.  InARP ignored.\n", 
-							card->devname);
-                        	        return -1;
-                        	}
-			}
-
-                        if (dev->pa_addr == arphdr->ar_sip) {
-                                printk(KERN_INFO "%s: Local addr = PtP addr.  InARP ignored.\n", 
-						card->devname);
-                                return -1;
-                        }
-
-                        arphdr->ar_op = htons(0x09);    /* InARP Reply */
-
-                        /* Set addresses */
-                        arphdr->ar_tip = arphdr->ar_sip;
-                        arphdr->ar_sip = dev->pa_addr;
-
-                        fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket);
-
-			clear_bit(ARP_CRIT,&card->wandev.critical);
-
-                        /* Modify Point-to-Point Address */
-                        dev->pa_dstaddr = arphdr->ar_tip;
-
-                        /* Add Route Flag */
-                        /* The route will be added in the polling routine so
-                           that it is not interrupt context. */
-                        ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE;
-			trigger_fr_poll(dev);
-
-                        break;
-                case 0x09:  // Inverse ARP reply
-
-                        /* Check for valid Address */
-                        printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n", 
-				((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip));
-
-                        if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) {
-                                printk(KERN_INFO "%s: Invalid PtP address.  InARP ignored.\n", 
-					card->devname);
-                                return -1;
-                        }
-
-                        if (dev->pa_addr == arphdr->ar_sip) {
-                                printk(KERN_INFO "%s: Local addr = PtP addr.  InARP ignored.\n", 
-					card->devname);
-                                return -1;
-                        }
-
-                        /* Modify Point-to-Point Address */
-                        dev->pa_dstaddr = arphdr->ar_sip;
-                        /* Add Route Flag */
-                        /* The route will be added in the polling routine so
-                           that it is not interrupt context. */
-
-                        ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE;
-                        ((fr_channel_t *) dev->priv)->inarp = INARP_CONFIGURED;
-			trigger_fr_poll(dev);
-
-                        break;
-                default:  // ARP's and RARP's -- Shouldn't happen.
-        }
-
-        return 0;
-
-#endif
 }
 
 
@@ -4706,15 +4324,9 @@
 {
 	if (card->hw.type != SDLA_S514){
 
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-#else
-          	disable_irq(card->hw.irq);
-#endif
 	}else{
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_lock(&card->u.f.if_send_lock);
-#endif
 	}
 	return;
 }
@@ -4724,23 +4336,15 @@
 {
 	if (card->hw.type != SDLA_S514){
 
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_unlock_irqrestore (&card->wandev.lock, *smp_flags);
-#else
-          	enable_irq(card->hw.irq);
-#endif
 	}else{
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_unlock(&card->u.f.if_send_lock);
-#endif
 	}
 	return;
 }
 
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 /*----------------------------------------------------------------------
                   RECEIVE INTERRUPT: BOTTOM HALF HANDLERS 
  ----------------------------------------------------------------------*/
@@ -4770,7 +4374,7 @@
 
 	if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){
 		++card->wandev.stats.rx_dropped;
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 		return 1; 
 	}
 
@@ -4859,7 +4463,7 @@
 			if (chan->common.sk == NULL || chan->common.func == NULL){
 				++card->wandev.stats.rx_dropped;
 				++chan->ifstats.rx_dropped;
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 				fr_bh_cleanup(dev);
 				continue;
 			}
@@ -4896,7 +4500,6 @@
 	atomic_dec(&chan->bh_buff_used);
 	return 0;
 }
-#endif
 
 
 /*----------------------------------------------------------------------
@@ -4919,11 +4522,7 @@
 static void trigger_fr_poll (netdevice_t *dev)
 {
 	fr_channel_t* chan = dev->priv;
-#ifdef LINUX_2_4
 	schedule_task(&chan->fr_poll_task);
-#else
-	queue_task(&chan->fr_poll_task, &tq_scheduler);
-#endif
 	return;
 }
 
@@ -5047,7 +4646,7 @@
 		}
 	}
 
-	if (is_queue_stopped(dev) || (card->u.f.tx_interrupts_pending))
+	if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending))
      		return 1; 
 
 	return 0;
@@ -5295,7 +4894,6 @@
 	 * an Ethernet header */
 	if (op_mode == BRIDGE || op_mode == BRIDGE_NODE){
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 
 		/* Encapsulate the packet as a bridged Ethernet frame. */
 #ifdef DEBUG
@@ -5316,12 +4914,6 @@
 		skb->protocol = ETH_P_802_3;
 		return 8;
 
-#else
-
-		/* BRIDGING is not supported in 2.0.X */
-		return -EINVAL;
-
-#endif
 	}
 		
 	return 0;
diff -Nru a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c
--- a/drivers/net/wan/sdla_ft1.c	Mon Aug 26 11:35:50 2002
+++ b/drivers/net/wan/sdla_ft1.c	Sun Feb 16 16:22:42 2003
@@ -252,8 +252,6 @@
 	CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
 	int len;
 
-	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
 		return -EFAULT;
 	}
@@ -281,36 +279,6 @@
 	if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
 		return -EFAULT;
 	}
-
-#else
-
-        if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ft1_exec_cmd_t))){
-                return -EFAULT;
-	}
-
-        memcpy_fromfs((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t));
-
-	len = mbox->buffer_length;
-
-        if (len) {
-                if (!u_data || verify_area(VERIFY_READ, u_data, len))
-                        return -EFAULT;
-		memcpy_fromfs((void*)&mbox->data, u_data, len);
-        }
-
-        /* execute command */
-        if (!sdla_exec(mbox))
-               	return -EIO;
-
-        /* return result */
-        memcpy_tofs(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t));
-        len = mbox->buffer_length;
-
-        if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)){
-                memcpy_tofs(u_data, (void*)&mbox->data, len);
-	}
-
-#endif
 
 	return 0;
 
diff -Nru a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
--- a/drivers/net/wan/sdla_ppp.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdla_ppp.c	Thu Mar  6 09:25:30 2003
@@ -104,15 +104,9 @@
 #include <linux/in.h>		/* sockaddr_in */
 
 
-/* ---- 2.4.X KERNEL SUPPORT -----------------------*/
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
- #include <asm/uaccess.h>
- #include <linux/inetdevice.h>
- #include <linux/netdevice.h>
-#else
- #include <asm/segment.h>
- #include <net/route.h>          /* Adding new route entries : 2.0.X kernels */
-#endif
+#include <asm/uaccess.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
 
 #include <linux/if.h>
 #include <linux/sdla_ppp.h>		/* PPP firmware API definitions */
@@ -163,10 +157,6 @@
 #define NUM_AUTH_REQ_WITHOUT_REPLY      10
 
 #define END_OFFSET 0x1F0
-#if LINUX_VERSION_CODE < 0x020125
-#define test_and_set_bit set_bit
-#define net_ratelimit() 1
-#endif
 
 
 /******Data Structures*****************************************************/
@@ -255,18 +245,10 @@
 static int if_header(struct sk_buff *skb, netdevice_t *dev, unsigned short type, 
 		     void *daddr, void *saddr, unsigned len);
 
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr(struct sk_buff *skb);
 static struct net_device_stats *if_stats(netdevice_t *dev);
-#else
-static struct enet_statistics *if_stats(netdevice_t *dev);
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-        struct sk_buff* skb);
-#endif
 static int if_send(struct sk_buff *skb, netdevice_t *dev);
 
 
@@ -615,17 +597,7 @@
 	}
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
  	strcpy(dev->name,card->u.p.if_name);
-#else
-	dev->name = (char *)kmalloc(strlen(card->u.p.if_name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(ppp_priv_area);
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", card->u.p.if_name);
-#endif
 	
 	dev->init = &if_init;
 	dev->priv = ppp_priv_area;
@@ -673,7 +645,6 @@
 	ppp_mbox_t *mbox = card->mbox;
 	int len;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t)))
 		return -EFAULT;
 
@@ -698,35 +669,6 @@
 	if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len))
 		return -EFAULT;
 
-#else
-
-        if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ppp_cmd_t)))
-                return -EFAULT;
-
-        memcpy_fromfs((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t));
-
-	len = mbox->cmd.length;
-
-        if (len) {
-
-                if (!u_data || verify_area(VERIFY_READ, u_data, len))
-                        return -EFAULT;
-        }
-
-        /* execute command */
-        if (!sdla_exec(mbox))
-               	return -EIO;
-
-        /* return result */
-        memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t));
-        len = mbox->cmd.length;
-
-        if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len))
-                memcpy_tofs(u_data, (void*)&mbox->data, len);
-
-
-#endif
-
 	return 0;
 }
 
@@ -744,9 +686,6 @@
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
 	wan_device_t *wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -755,10 +694,8 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 	/* Initialize media-specific parameters */
 	dev->type		= ARPHRD_PPP;	/* ARP h/w type */
@@ -770,9 +707,6 @@
 		dev->flags	|= IFF_MULTICAST;
 	}
 
-#ifdef LINUX_2_0
-	dev->family		= AF_INET;
-#endif	
 	dev->mtu		= wandev->mtu;
 	dev->hard_header_len	= PPP_HDR_LEN;	/* media header length */
 
@@ -786,12 +720,6 @@
         /* Set transmit buffer queue length */
         dev->tx_queue_len = 100;
    
-	/* Initialize socket buffers */
-      #if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-      #endif
-
 	return 0;
 }
 
@@ -809,18 +737,12 @@
 	struct timeval tv;
 	//unsigned long smp_flags;
 
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 
 	wanpipe_open(card);
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 	
 	do_gettimeofday( &tv );
 	ppp_priv_area->router_start_time = tv.tv_sec;
@@ -852,10 +774,7 @@
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
 
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 	wanpipe_close(card);
 
 	del_timer (&ppp_priv_area->poll_delay_timer);
@@ -894,7 +813,6 @@
  * Return:	1	physical address resolved.
  *		0	physical address not resolved
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff *skb)
 {
 	netdevice_t *dev = skb->dev;
@@ -906,16 +824,6 @@
 	return 1;
 }
 
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-                           struct sk_buff* skb)
-{
-	return 1;
-
-}
-#endif
-
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -937,7 +845,6 @@
 	++chan->if_send_stat.if_send_tbusy_timeout;
 	netif_wake_queue (dev);
 }
-#endif
 
 
 
@@ -970,9 +877,7 @@
 	
 	++ppp_priv_area->if_send_stat.if_send_entry;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 	
 	if (skb == NULL) {
 
@@ -984,36 +889,10 @@
 		
 		++ppp_priv_area->if_send_stat.if_send_skb_null;
 	
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
-#ifndef LINUX_2_4
-	if (dev->tbusy) {
-
-		/* If our device stays busy for at least 5 seconds then we will
-		 * kick start the device by making dev->tbusy = 0.  We expect 
-		 * that our device never stays busy more than 5 seconds. So this
-		 * is only used as a last resort. 
-		 */
-              
-		++ppp_priv_area->if_send_stat.if_send_tbusy;
-        	++card->wandev.stats.collisions;
-
-		if ((jiffies - ppp_priv_area->tick_counter) < (5*HZ)) {
-			return 1;
-		}
-
-		printk (KERN_INFO "%s: Transmit times out on %s\n",card->devname,dev->name);
-	
-		++ppp_priv_area->if_send_stat.if_send_tbusy_timeout;
-		++card->wandev.stats.collisions;
-
-		/* unbusy the card (because only one interface per card)*/
-		dev->tbusy = 0;
-	}	
-#endif
-	
 	sendpacket = skb->data;
 
 	udp_type = udp_pkt_type( skb, card );
@@ -1025,7 +904,7 @@
 	               	flags->imask |= PPP_INTR_TIMER;
 		}
 		++ppp_priv_area->if_send_stat.if_send_PIPE_request;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1034,8 +913,8 @@
 	 */
 	if(chk_bcast_mcast_addr(card, dev, skb)){
 		++card->wandev.stats.tx_dropped;
-		wan_dev_kfree_skb(skb,FREE_WRITE);
-		start_net_queue(dev);
+		dev_kfree_skb_any(skb);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1051,7 +930,7 @@
 		
 		++card->wandev.stats.tx_dropped;
 		++ppp_priv_area->if_send_stat.if_send_critical_non_ISR;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_exit_crit;
 	}
 
@@ -1059,12 +938,12 @@
 
 		++ppp_priv_area->if_send_stat.if_send_wan_disconnected;
         	++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
      	} else if (!skb->protocol) {
 		++ppp_priv_area->if_send_stat.if_send_protocol_error;
         	++card->wandev.stats.tx_errors;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
 	} else {
 
@@ -1075,32 +954,28 @@
 					ppp_priv_area->network_number, 0);
 			} else {
 				++card->wandev.stats.tx_dropped;
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				goto if_send_exit_crit;
 			}
 		}
 
 		if (ppp_send(card, skb->data, skb->len, skb->protocol)) {
-			stop_net_queue(dev);
+			netif_stop_queue(dev);
 			++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full;
 			++ppp_priv_area->if_send_stat.if_send_tx_int_enabled;
 		} else {
 			++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr;
 			++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			card->wandev.stats.tx_bytes += skb->len;
-#endif
-			start_net_queue(dev);
-#ifdef LINUX_2_4
+			netif_start_queue(dev);
 			dev->trans_start = jiffies;
-#endif
 		}
     	}
 	
 if_send_exit_crit:
 	
-	if (!(err=is_queue_stopped(dev))){
-      		wan_dev_kfree_skb(skb, FREE_WRITE);
+	if (!(err=netif_queue_stopped(dev))){
+      		dev_kfree_skb_any(skb);
 	}else{
 		ppp_priv_area->tick_counter = jiffies;
 		flags->imask |= PPP_INTR_TXRDY;	/* unmask Tx interrupts */
@@ -1134,13 +1009,8 @@
 		udp_pkt_stored = 1;
 	}else{
 		if (skb->len > MAX_LGTH_UDP_MGNT_PKT){
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n",
 				card->devname, skb->len);
-#else
-			printk(KERN_INFO "%s: PIPEMON UDP request too long : %li\n",
-				card->devname, skb->len);
-#endif
 		}else{
 			printk(KERN_INFO "%s: PIPEMON UPD request already pending\n",
 				card->devname);
@@ -1149,9 +1019,9 @@
 	}
 
 	if(udp_pkt_src == UDP_PKT_FRM_STACK){
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+		dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 
 	return(udp_pkt_stored);
@@ -1319,11 +1189,7 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct net_device_stats.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats *if_stats(netdevice_t *dev)
-#else
-static struct enet_statistics *if_stats(netdevice_t *dev)
-#endif
 {
 
 	ppp_private_area_t *ppp_priv_area = dev->priv;
@@ -1743,7 +1609,7 @@
 		case PPP_INTR_TXRDY:	/* transmit interrupt  0x02 (bit 1)*/
 			++card->statistics.isr_tx;
 			flags->imask &= ~PPP_INTR_TXRDY;
-			wake_net_dev(dev);
+			netif_wake_queue(dev);
 			break;
 
 		case PPP_INTR_CMD:      /* interface command completed */
@@ -1821,7 +1687,7 @@
 		return;
 	}
       
-	if (dev && is_dev_running(dev) && dev->priv){
+	if (dev && netif_running(dev) && dev->priv){
 	
 		len  = rxbuf->length;
 		ppp_priv_area = dev->priv;
@@ -1881,7 +1747,7 @@
 					if (!test_bit(SEND_CRIT, &card->wandev.critical)){
 					 	ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX));
 					}
-					wan_dev_kfree_skb(skb,FREE_READ);
+					dev_kfree_skb_any(skb);
 
 				} else {
 					++card->wandev.stats.rx_dropped;
@@ -1892,9 +1758,7 @@
 				skb->mac.raw  = skb->data;
 
 			    	++card->wandev.stats.rx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 				card->wandev.stats.rx_bytes += skb->len;
-#endif
 		    		++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack;	
 				netif_rx(skb);
 				dev->last_rx = jiffies;
@@ -2244,8 +2108,6 @@
 	netdevice_t *dev = card->wandev.dev;
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
 	    (flags->ip_state == 0x09)){ 
 
@@ -2276,29 +2138,6 @@
 			}
 		}
 	}
-#else
-
-	if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
-	    (flags->ip_state == 0x09)){ 
-	
-		if (ppp_priv_area->ip_local == 0)
-			return;
-	
-		printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname);
-		if (read_info( card )) {
-			printk(KERN_INFO 
-				"%s: An error occurred in IP assignment.\n", 
-				card->devname);
-		} else {
-			printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", 
-					card->devname, NIPQUAD(dev->pa_addr));
-			printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%U\n", 
-					card->devname, NIPQUAD(dev->pa_dstaddr));
-		}
-	}
-
-#endif
-
 }
 
 /*============================================================================
@@ -2328,9 +2167,7 @@
 static int config508(netdevice_t *dev, sdla_t *card)
 {
 	ppp508_conf_t cfg;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct in_device *in_dev = dev->ip_ptr;
-#endif
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 
 	/* Prepare PPP configuration structure */
@@ -2393,14 +2230,8 @@
 			printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname);
 			cfg.ip_options		= L_AND_R_IP_NO_ASSIG | 
 							    ENABLE_IP;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			cfg.ip_local		= in_dev->ifa_list->ifa_local;
 			cfg.ip_remote		= in_dev->ifa_list->ifa_address;
-#else
-			cfg.ip_local		= dev->pa_addr;
-			cfg.ip_remote		= dev->pa_dstaddr;
-#endif
-
 			/* Debugging code used to check that IP addresses
                          * obtained from the kernel are correct */
 
@@ -2414,14 +2245,8 @@
 			cfg.ip_options		= L_IP_LOCAL_ASSIG |
 						  R_IP_LOCAL_ASSIG | 
 						  ENABLE_IP;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			cfg.ip_local		= in_dev->ifa_list->ifa_local;
 			cfg.ip_remote		= in_dev->ifa_list->ifa_address;
-#else
-			cfg.ip_local		= dev->pa_addr;
-			cfg.ip_remote		= dev->pa_dstaddr;
-#endif
-
 			/* Debugging code used to check that IP addresses
                          * obtained from the kernel are correct */
                         NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
@@ -2431,8 +2256,6 @@
 	
 		case WANOPT_PPP_PEER:
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 			printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname);
 			cfg.ip_options		= L_IP_REMOTE_ASSIG | 
 						  R_IP_REMOTE_ASSIG | 
@@ -2441,16 +2264,6 @@
 			cfg.ip_remote		= 0x00;
 			break;
 
-#else
-
-			/* No PEER support for 2.0.X kernels, drop down to default
-   			 * condition */
-
-			printk(KERN_INFO "%s: ERROR, PEER mode is not supported in 2.0.X kernels\n",
-						card->devname);
-			
-#endif
-
 		default:
 			printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n",
 					card->devname);
@@ -3038,19 +2851,9 @@
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	int err;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct ifreq if_info;
 	struct sockaddr_in *if_data1, *if_data2;
 	mm_segment_t fs;
-#else
-#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_
-        struct rtentry route;
-#endif
-#endif
-
-
-	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 
 	/* Set Local and remote addresses */
 	memset(&if_info, 0, sizeof(if_info));
@@ -3074,39 +2877,6 @@
 
 	set_fs(fs);           /* restore old block */
 	
-#else
-	/* FIXME: Dynamic Routing in 2.0.X kernels is not
-         * supported. Sorry ! I'll come back to it when I get
-         * a chance. */
-	
-	printk(KERN_INFO "%s: ERROR, Dynamic routing is not supported in 2.0.X kernels\n",
-				card->devname);
-	printk(KERN_INFO "%s:        Please use the STATIC IP mode!\n",
-				card->devname);
-
-	err = 0;
-
-#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_
-	dev->pa_dstaddr = ppp_priv_area->ip_remote;
-	dev->pa_addr = ppp_priv_area->ip_local;
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev = dev->name;
-	route.rt_flags = 0;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =
-		dev->pa_dstaddr;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =
-			0xFFFFFFFF;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_family =
-			AF_INET;
-	
-	err = ip_rt_new(&route);
-
-#endif
-
-#endif
-
 	if (err) {
 		printk (KERN_INFO "%s: Adding of route failed: %i\n",
 			card->devname,err);
@@ -3130,32 +2900,21 @@
 	long ip_addr;
 	int err;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         mm_segment_t fs;
 	struct ifreq if_info;
 	struct sockaddr_in *if_data1;
         struct in_device *in_dev = dev->ip_ptr;
         struct in_ifaddr *ifa = in_dev->ifa_list;	
-#else
-	unsigned long fs = 0;
-        struct rtentry route;
-#endif
-
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	ip_addr = ifa->ifa_local;
 
 	/* Set Local and remote addresses */
 	memset(&if_info, 0, sizeof(if_info));
 	strcpy(if_info.ifr_name, dev->name);
-#endif
-
 
 	fs = get_fs();
        	set_fs(get_ds());     /* get user space block */ 
 
-
-#if defined(LINUX_2_1) || defined(LINUX_2_4)	
 	/* Change the local ip address of the interface to 0.
 	 * This will also delete the destination route.
 	 */	
@@ -3163,26 +2922,6 @@
 	if_data1->sin_addr.s_addr = 0;
 	if_data1->sin_family = AF_INET;
 	err = devinet_ioctl( SIOCSIFADDR, &if_info );
-#else
-
-	ip_addr = dev->pa_addr;
-	dev->pa_dstaddr = 0;
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev = dev->name;
-	route.rt_flags = 0;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =
-			dev->pa_dstaddr;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =
-			0xFFFFFFFF;
-        ((struct sockaddr_in *)&(route.rt_genmask))->sin_family =
-			AF_INET;
-
-
-	err = ip_rt_kill(&route);
-
-#endif
 
         set_fs(fs);           /* restore old block */
 
@@ -3288,14 +3027,12 @@
 {
 	u32 src_ip_addr;
         u32 broadcast_ip_addr = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct in_device *in_dev;
-#endif
+
         /* read the IP source address from the outgoing packet */
         src_ip_addr = *(u32 *)(skb->data + 12);
 
 	/* read the IP broadcast address for the device */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         in_dev = dev->ip_ptr;
         if(in_dev != NULL) {
                 struct in_ifaddr *ifa= in_dev->ifa_list;
@@ -3304,9 +3041,6 @@
                 else
                         return 0;
         }
-#else
-        broadcast_ip_addr = dev->pa_brdaddr;
-#endif
  
         /* check if the IP Source Address is a Broadcast address */
         if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
@@ -3328,20 +3062,12 @@
 
 void s508_lock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-#else
-	disable_irq(card->hw.irq);
-#endif                                                                     
 }
 
 void s508_unlock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
         spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-#else
-	enable_irq(card->hw.irq);
-#endif           
 }
 
 static int read_connection_info (sdla_t *card)
diff -Nru a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
--- a/drivers/net/wan/sdla_x25.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdla_x25.c	Thu Mar  6 09:25:30 2003
@@ -95,12 +95,7 @@
 #include <asm/atomic.h>
 #include <linux/delay.h>	/* Experimental delay */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
- #include <asm/uaccess.h>
-#else
- #include <asm/segment.h>
- #include <net/route.h>
-#endif
+#include <asm/uaccess.h>
 
 #include <linux/if.h>
 #include <linux/if_arp.h>
@@ -281,11 +276,7 @@
 	int ch_idx;
 	unsigned char enable_IPX;
 	unsigned long network_number;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct net_device_stats ifstats;	/* interface statistics */
-#else
-	struct enet_statistics ifstats;
-#endif	
 	unsigned short transmit_length;
 	unsigned short tx_offset;
 	char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)];
@@ -369,9 +360,7 @@
 static int if_send (struct sk_buff* skb, netdevice_t* dev);
 static struct net_device_stats *if_stats (netdevice_t* dev);
 
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
 /*=================================================  
  * 	Interrupt handlers 
@@ -792,9 +781,6 @@
 	
 	init_global_statistics(card);	
 
-#ifndef LINUX_2_4
-	card->u.x.x25_poll_task.next = NULL;
-#endif
 	card->u.x.x25_poll_task.sync=0;
 	card->u.x.x25_poll_task.routine = (void*)(void*)wpx_poll;
 	card->u.x.x25_poll_task.data = card;
@@ -1011,18 +997,8 @@
 		chan->network_number = 0xDEADBEEF;
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
 	strcpy(dev->name,chan->name);
-#else
-	dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(chan);
-		dev->priv = NULL;
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", chan->name);
-#endif
+
 	dev->init = &if_init;
 
 	init_x25_channel_struct(chan);
@@ -1124,9 +1100,6 @@
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -1135,19 +1108,11 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 	/* Initialize media-specific parameters */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	dev->type		= ARPHRD_PPP;		/* ARP h/w type */
-#else
-        dev->family             = AF_INET;      /* address family */
-        dev->type               = ARPHRD_PPP;   /* no x25 type */
-#endif
 	dev->flags		|= IFF_POINTOPOINT;
 	dev->flags		|= IFF_NOARP;
 
@@ -1174,11 +1139,6 @@
         /* Set transmit buffer queue length */
         dev->tx_queue_len = 100;
 
-	/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-#endif
 	/* FIXME Why are we doing this */
 	set_chan_state(dev, WAN_DISCONNECTED);
 	return 0;
@@ -1214,15 +1174,12 @@
 	struct timeval tv;
 	unsigned long smp_flags;
 	
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 
 	chan->tq_working = 0;
 
 	/* Initialize the task queue */
-#ifndef LINUX_2_4
-	chan->common.wanpipe_task.next = NULL;
-#endif
 	chan->common.wanpipe_task.sync = 0;
 	chan->common.wanpipe_task.routine = (void *)(void *)x25api_bh;
 	chan->common.wanpipe_task.data = dev;
@@ -1276,13 +1233,8 @@
 	do_gettimeofday( &tv );
 	chan->router_start_time = tv.tv_sec;
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else	
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
+
 	return 0;
 }
 
@@ -1314,10 +1266,7 @@
 	sdla_t* card = chan->card;
 	unsigned long smp_flags;
 	
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 
 	if ((chan->common.state == WAN_CONNECTED) || 
 	    (chan->common.state == WAN_CONNECTING)){
@@ -1336,7 +1285,7 @@
 		for (i=0; i<(MAX_BH_BUFF+1); i++){
 			skb = ((bh_data_t *)&chan->bh_head[i])->skb;
 			if (skb != NULL){
-                		wan_dev_kfree_skb(skb, FREE_READ);
+                		dev_kfree_skb_any(skb);
 			}
 		}
 		kfree(chan->bh_head);
@@ -1405,7 +1354,6 @@
 }
 
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -1425,7 +1373,6 @@
 			card->devname, dev->name);
 	netif_wake_queue (dev);
 }
-#endif
 
 
 /*=========================================================================
@@ -1457,33 +1404,11 @@
 
 	++chan->if_send_stat.if_send_entry;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 
 	/* No need to check frame length, since socket code
          * will perform the check for us */
 
-#ifndef LINUX_2_4
-	if (dev->tbusy){
-		netdevice_t *dev2;
-		
-		++chan->if_send_stat.if_send_tbusy;
-		if ((jiffies - chan->tick_counter) < (5*HZ)){
-			return 1;
-		}
-		printk(KERN_INFO "%s: Transmit time out %s!\n",
-			card->devname, dev->name);
-		
-		for( dev2 = card->wandev.dev; dev2; 
-		     dev2 = *((netdevice_t**)dev2->priv)){
-
-	        	dev2->tbusy = 0;
-		}
-		++chan->if_send_stat.if_send_tbusy_timeout;
-	}
-#endif
-
 	chan->tick_counter = jiffies;
 	
 	/* Critical region starts here */
@@ -1506,7 +1431,7 @@
                                 chan->if_send_stat.if_send_PIPE_request++;
 			}
                	}
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
 		S508_S514_unlock(card, &smp_flags);
 		return 0;
@@ -1518,7 +1443,7 @@
 			chan->transmit_length=0;
 			atomic_set(&chan->common.driver_busy,0);
 		}else{
-			stop_net_queue(dev);
+			netif_stop_queue(dev);
 			++card->u.x.tx_interrupts_pending;
 		        status->imask |= INTR_ON_TX_FRAME;
 			clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
@@ -1589,9 +1514,9 @@
 
 if_send_crit_exit:
 	
-       	wan_dev_kfree_skb(skb, FREE_WRITE);
+       	dev_kfree_skb_any(skb);
 
-	start_net_queue(dev);
+	netif_start_queue(dev);
 	clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
 	S508_S514_unlock(card, &smp_flags);
 	return 0;
@@ -1787,14 +1712,12 @@
 			++chan->ifstats.rx_dropped;
 			++card->wandev.stats.rx_dropped;
 			++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-			wan_dev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb_any(skb);
 			return;
 		}		
 
 		++chan->ifstats.rx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		chan->ifstats.rx_bytes += skb->len;
-#endif
 		
 
 		chan->rx_skb = NULL;
@@ -1814,7 +1737,7 @@
 	/* Decapsulate packet, if necessary */
 	if (!skb->protocol && !wanrouter_type_trans(skb, dev)){
 		/* can't decapsulate packet */
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 		++chan->ifstats.rx_errors;
 		++chan->ifstats.rx_dropped;
 		++card->wandev.stats.rx_dropped;
@@ -1829,7 +1752,7 @@
 				if(chan_send(dev, skb->data, skb->len,0)){
 					chan->tx_skb = skb;
 				}else{
-                                        wan_dev_kfree_skb(skb, FREE_WRITE);
+                                        dev_kfree_skb_any(skb);
 					++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
 				}
 			}else{
@@ -1839,9 +1762,7 @@
 			}
 		}else{
 			skb->mac.raw = skb->data;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			chan->ifstats.rx_bytes += skb->len;
-#endif
 			++chan->ifstats.rx_packets;
 			++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
 			netif_rx(skb);
@@ -1898,7 +1819,7 @@
 
 	if (skb_tailroom(new_skb) < len){
 		/* No room for the packet. Call off the whole thing! */
-                wan_dev_kfree_skb(new_skb, FREE_READ);
+                dev_kfree_skb_any(new_skb);
 		if (chan->common.usedby == WANPIPE){
 			chan->rx_skb = NULL;
 			if (qdm & 0x01){ 
@@ -1985,12 +1906,12 @@
 				chan->transmit_length = 0;
 				atomic_set(&chan->common.driver_busy,0);
 				chan->tx_offset=0;
-				if (is_queue_stopped(dev)){
+				if (netif_queue_stopped(dev)){
 					if (chan->common.usedby == API){
-						start_net_queue(dev);
+						netif_start_queue(dev);
 						wakeup_sk_bh(dev);
 					}else{
-						wake_net_dev(dev);
+						netif_wake_queue(dev);
 					}
 				}
 				dev = move_dev_to_next(card,dev);
@@ -2092,12 +2013,12 @@
 
 	/* If we are in API mode, wakeup the 
          * sock BH handler, not the NET_BH */
-	if (is_queue_stopped(dev)){
+	if (netif_queue_stopped(dev)){
 		if (chan->common.usedby == API){
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			wakeup_sk_bh(dev);
 		}else{
-			wake_net_dev(dev);
+			netif_wake_queue(dev);
 		}
 	}
 	return 0;
@@ -2342,11 +2263,7 @@
 
 static void trigger_x25_poll(sdla_t *card)
 {
-#ifdef LINUX_2_4
 	schedule_task(&card->u.x.x25_poll_task);
-#else
-	queue_task(&card->u.x.x25_poll_task, &tq_scheduler);
-#endif
 }
 
 /*====================================================================
@@ -3658,8 +3575,8 @@
 					chan->transmit_length=0;
 					atomic_set(&chan->common.driver_busy,0);
 					chan->tx_offset=0;
-					if (is_queue_stopped(dev)){
-						wake_net_dev(dev);
+					if (netif_queue_stopped(dev)){
+						netif_wake_queue(dev);
 					}
 				}
 				atomic_set(&chan->common.command,0);
@@ -3766,9 +3683,7 @@
 		case 0x00:	/* success */
 			chan->i_timeout_sofar = jiffies;
 
-#ifdef LINUX_2_4
 			dev->trans_start=jiffies;
-#endif
 			
 			if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){
 				if (!tx_intr){
@@ -3780,9 +3695,7 @@
 					chan->tx_offset += len;
 
 					++chan->ifstats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 					chan->ifstats.tx_bytes += len;
-#endif
 					
 					if (chan->tx_offset < orig_len){
 						setup_for_delayed_transmit (dev, buff, data_len);
@@ -3795,9 +3708,7 @@
                                          * be X number of times larger than max data size.
 					 */
 					++chan->ifstats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 					chan->ifstats.tx_bytes += len;
-#endif
 					
 					++chan->if_send_stat.if_send_bfr_passed_to_adptr;
 					chan->tx_offset += len;
@@ -3817,9 +3728,7 @@
 				}
 			}else{
 				++chan->ifstats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 				chan->ifstats.tx_bytes += len;
-#endif
 				++chan->if_send_stat.if_send_bfr_passed_to_adptr;
 				res=0;
 			}
@@ -4288,7 +4197,7 @@
 			if (chan->common.sk == NULL || chan->common.func == NULL){
 				printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n",
 						card->devname);
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 				x25api_bh_cleanup(dev);
 				++chan->ifstats.rx_dropped;
 				++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
@@ -4745,7 +4654,7 @@
 
 	if (card->func(skb,card->sk) < 0){
 		printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname);
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 		return 1;
 	}
 
@@ -4912,7 +4821,7 @@
 	if (chan->common.func(skb,dev,chan->common.sk) < 0){
 		if (bh_enqueue(dev,skb)){
 			printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname);
-                	wan_dev_kfree_skb(skb, FREE_READ);
+                	dev_kfree_skb_any(skb);
 		}
 	}
 
@@ -4940,7 +4849,7 @@
 
 	if (skb_tailroom(new_skb) < len){
 		/* No room for the packet. Call off the whole thing! */
-                wan_dev_kfree_skb(new_skb, FREE_READ);
+                dev_kfree_skb_any(new_skb);
 		printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n"
 			,card->devname);
 		*skb = NULL;
@@ -5448,9 +5357,9 @@
 	}
 
         if(udp_pkt_src == UDP_PKT_FRM_STACK){
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+                dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 
         return(udp_pkt_stored);
diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
--- a/drivers/net/wan/sdladrv.c	Wed May 22 11:16:37 2002
+++ b/drivers/net/wan/sdladrv.c	Sun Feb 16 16:22:42 2003
@@ -108,16 +108,8 @@
 #define _OUTB(port, byte)	(outb((byte),(port)))
 #define	SYSTEM_TICK		jiffies
 
+#include <linux/init.h>
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
- #include <linux/init.h>
-#else
- #include <linux/bios32.h>/* BIOS32, PCI BIOS functions and definitions */
- #define ioremap vremap
- #define iounmap vfree
- extern void * vremap (unsigned long offset, unsigned long size);
- extern void vfree (void *addr);
-#endif
 
 #elif	defined(_SCO_UNIX_)	/****** SCO Unix ****************************/
 
@@ -381,9 +373,7 @@
  *		< 0	error
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 EXPORT_SYMBOL(sdla_setup);
-#endif
 
 int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
 {
@@ -528,9 +518,7 @@
  * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_down);
-#endif
 
 int sdla_down (sdlahw_t* hw)
 {
@@ -572,7 +560,6 @@
                 *(char *)hw->vector = S514_CPU_HALT;
         	CPU_no = hw->S514_cpu_no[0];
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		/* disable the PCI IRQ and disable memory access */
                 pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);
 	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;
@@ -585,22 +572,6 @@
 		else
                         pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,
 				PCI_CPU_B_MEM_DISABLE);
-#else
-                /* disable the PCI IRQ and disable memory access */
-             	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
-			PCI_INT_CONFIG, &int_config);
-	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;
-        	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
-			PCI_INT_CONFIG, int_config);
-                read_S514_int_stat(hw, &int_status);
-                S514_intack(hw, int_status);
-     		// disable PCI memory access
-		if(CPU_no == S514_CPU_A)
-	     		pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,
-				PCI_MAP0_DWORD, PCI_CPU_A_MEM_DISABLE);
-		else
-                        pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,							PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE);
-#endif
 
 		/* free up the allocated virtual memory */
  		iounmap((void *)hw->dpmbase);
@@ -618,9 +589,7 @@
  * Map shared memory window into SDLA address space.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_mapmem);
-#endif
 
 int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
 {
@@ -681,9 +650,7 @@
  * Enable interrupt generation.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_inten);
-#endif
 
 int sdla_inten (sdlahw_t* hw)
 {
@@ -739,9 +706,7 @@
  * Disable interrupt generation.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_intde);
-#endif
 
 int sdla_intde (sdlahw_t* hw)
 {
@@ -796,9 +761,7 @@
  * Acknowledge SDLA hardware interrupt.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_intack);
-#endif
 
 int sdla_intack (sdlahw_t* hw)
 {
@@ -848,18 +811,11 @@
  * Acknowledge S514 hardware interrupt.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(S514_intack);
-#endif
 
 void S514_intack (sdlahw_t* hw, u32 int_status)
 {
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-#else
-	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
-                PCI_INT_STATUS, int_status);
-#endif
 }
 
 
@@ -867,18 +823,11 @@
  * Read the S514 hardware interrupt status.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(read_S514_int_stat);
-#endif
 
 void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
 {
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-#else
-        pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_STATUS,
-		int_status);
-#endif
 }
 
 
@@ -886,9 +835,7 @@
  * Generate an interrupt to adapter's CPU.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_intr);
-#endif
 
 int sdla_intr (sdlahw_t* hw)
 {
@@ -932,9 +879,7 @@
  * o Return number of loops made, or 0 if command timed out.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_exec);
-#endif
 
 int sdla_exec (void* opflag)
 {
@@ -970,9 +915,7 @@
  * interrupt routines are accessing adapter shared memory.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_peek);
-#endif
 
 int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
 {
@@ -1054,9 +997,7 @@
  * interrupt routines are accessing adapter shared memory.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_poke);
-#endif
  
 int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
 {
@@ -1961,20 +1902,11 @@
 	int number_S514_cards = 0;
 	u32 S514_mem_base_addr = 0;
 	u32 ut_u32;
-
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct pci_dev *pci_dev;
-#else
-	u8 ut_u8;
-#endif
 
 
 #ifdef CONFIG_PCI
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         if(!pci_present())
-#else
-	if(!pcibios_present())
-#endif
         {
                 printk(KERN_INFO "%s: PCI BIOS not present!\n", modname);
                 return 0;
@@ -2029,26 +1961,12 @@
 		}
 	}
 
-      #if defined(LINUX_2_4)
 	pci_dev = hw->pci_dev;
 	/* read the physical memory base address */
 	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 
 		(pci_dev->resource[1].start) :
 		(pci_dev->resource[2].start);
 	
-      #elif defined (LINUX_2_1)
-	pci_dev = hw->pci_dev;
-	/* read the physical memory base address */
-	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 
-		(pci_dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK) :
-		(pci_dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK);
-	
-      #else
-	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
-		(CPU_no == S514_CPU_A) ? PCI_MEM_BASE0_DWORD :
-		PCI_MEM_BASE1_DWORD, &S514_mem_base_addr);
-      #endif
-
 	printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",
 		modname, S514_mem_base_addr);
 	if(!S514_mem_base_addr) {
@@ -2060,24 +1978,14 @@
 	}
 
 	/* enable the PCI memory */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	pci_read_config_dword(pci_dev, 
 		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
 		&ut_u32);
 	pci_write_config_dword(pci_dev,
 		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
 		(ut_u32 | PCI_MEMORY_ENABLE));
-#else
-        pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
-		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
-		&ut_u32); 
-        pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
-		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
-		(ut_u32 | PCI_MEMORY_ENABLE));
-#endif
 
 	/* check the IRQ allocated and enable IRQ usage */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if(!(hw->irq = pci_dev->irq)) {
 		printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
 			modname);
@@ -2099,29 +2007,6 @@
         ut_u32 |= (CPU_no == S514_CPU_A) ?
                 PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
         pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);
-#else
-	/* the INTPIN must not be 0 - if it is, then the S514 adapter is not */
-	/* configured for IRQ usage */
-	pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
-		PCI_INT_PIN_BYTE, &ut_u8);
-        if(!ut_u8) {
-                printk(KERN_INFO "%s: invalid setting for INTPIN on S514 card\n", modname);
-                printk(KERN_INFO "Please contact your Sangoma representative\n");
-                return 0;
-        }
-        pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
-		PCI_INT_LINE_BYTE, (unsigned char *)&hw->irq);
-        if(hw->irq == PCI_IRQ_NOT_ALLOCATED) {
-                printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
-			modname);
-                return 0;
-        }
-	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_CONFIG, &ut_u32);
-	ut_u32 |= (CPU_no == S514_CPU_A) ?
-		PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
-        pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, 
-		PCI_INT_CONFIG, ut_u32);
-#endif
 
 	printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",
 		modname, hw->irq);
@@ -2157,15 +2042,10 @@
 	char S514_found_in_slot = 0;
         u16 PCI_subsys_vendor;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct pci_dev *pci_dev = NULL;
-#else
-        int pci_index;
-#endif
  
        slot_no = hw->S514_slot_no;
   
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
         	!= NULL) {
                 
@@ -2197,40 +2077,6 @@
                 }
         }
 
-#else
-	//LINUX VERSION 2.0.X 
-        for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) {
-                if (pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index,
-                        &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) {
-                                break;
-                }
-                
-		pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func,
-                        PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor);
-                
-		if (PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
-                        continue;
-                
-		if (find_first_S514_card)
-                        return(1);
-           	
-		number_S514_cards ++;
-		
-                printk(KERN_INFO "%s: S514 card found, bus #%d, slot #%d\n",
-                        modname, hw->pci_bus,
-                        ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK));
-
-		if (hw->auto_pci_cfg){
-			hw->S514_slot_no = ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK)
-			slot_no = hw->S514_slot_no;
-				
-		}else if (((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK) == slot_no) {
-                        S514_found_in_slot = 1;
-                        break;
-                }
-        }
-#endif
-
 	/* if no S514 adapter has been found, then exit */
         if (!number_S514_cards) {
                 printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);
@@ -2408,17 +2254,11 @@
         u16 PCI_subsys_vendor;
 	u16 PCI_card_type;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct pci_dev *pci_dev = NULL;
 	struct pci_bus *bus = NULL;
-#else
-        int pci_index;
-	u8 irq;
-#endif
  
        slot_no = 0;
   
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
         	!= NULL) {
 		
@@ -2453,52 +2293,13 @@
 		}
         }
 
-#else
-        for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) {
-		
-                if(pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index,
-                        &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) {
-                                break;
-                }
-                pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func,
-                        PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor);
-                if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
-                        continue;
-		
-		pcibios_read_config_word(hw->pci_bus,hw->pci_dev_func,PCI_CARD_TYPE,
-                        &PCI_card_type);
-
-		pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
-				PCI_INT_LINE_BYTE, &irq);
-
-		/* A dual cpu card can support up to 4 physical connections,
-		 * where a single cpu card can support up to 2 physical
-		 * connections.  The FT1 card can only support a single 
-		 * connection, however we cannot distinguish between a Single
-		 * CPU card and an FT1 card. */
-		if (PCI_card_type == S514_DUAL_CPU){
-                	number_S514_cards += 4;
-			 printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
-                        	modname, hw->pci_bus,
-                        	((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq);
-		}else{
-			printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
-                        	modname, hw->pci_bus,
-                        	((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq);
-			number_S514_cards += 2;
-		}
-        }
-#endif
-
 	return number_S514_cards;
 
 }
 
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(wanpipe_hw_probe);
-#endif
 
 unsigned wanpipe_hw_probe(void)
 {
diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
--- a/drivers/net/wan/sdlamain.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdlamain.c	Thu Mar  6 09:25:30 2003
@@ -64,26 +64,10 @@
 #include <linux/sdlapci.h>
 #include <linux/if_wanpipe_common.h>
 
-#if defined(LINUX_2_4)
+#define netdevice_t struct net_device
 
- #include <asm/uaccess.h>	/* kernel <-> user copy */
- #include <linux/inetdevice.h>
- #define netdevice_t struct net_device 
-
-#elif defined(LINUX_2_1)
-
- #include <asm/uaccess.h>	/* kernel <-> user copy */
- #include <linux/inetdevice.h>
- #define netdevice_t struct device 
-
-#else
-
- #include <asm/segment.h>
- #define devinet_ioctl(x,y) dev_ioctl(x,y)
- #define netdevice_t struct device 
- #define test_and_set_bit set_bit
- typedef unsigned long mm_segment_t; 
-#endif
+#include <asm/uaccess.h>	/* kernel <-> user copy */
+#include <linux/inetdevice.h>
 
 #include <linux/ip.h>
 #include <net/route.h>
@@ -240,23 +224,12 @@
  * function, which will execute all pending,
  * tasks in wanpipe_tq_custom queue */
 
-#ifdef LINUX_2_4
 DECLARE_TASK_QUEUE(wanpipe_tq_custom);
 static struct tq_struct wanpipe_tq_task = 
 {
 	.routine = (void (*)(void *)) run_wanpipe_tq,
 	.data = &wanpipe_tq_custom
 };
-#else
-static struct tq_struct *wanpipe_tq_custom = NULL;
-static struct tq_struct wanpipe_tq_task = 
-{
-	NULL,
-	0,
-	(void *)(void *) run_wanpipe_tq,
-	&wanpipe_tq_custom
-};
-#endif
 
 static int wanpipe_bh_critical=0;
 
@@ -511,9 +484,7 @@
 	if (!card->configured){
 
 		/* Initialize the Spin lock */
-#if defined(__SMP__) || defined(LINUX_2_4) 
 		printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name);
-#endif
 
 		/* Piggyback spin lock has already been initialized,
 		 * in check_s514/s508_conflicts() */
@@ -974,26 +945,13 @@
 	unsigned long smp_flags;
 	int err = 0;
 
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)))
 		return -EFAULT;
-      #else
-        if ((u_dump == NULL) ||
-            verify_area(VERIFY_READ, u_dump, sizeof(sdla_dump_t)))
-                return -EFAULT;
-        memcpy_fromfs((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t));
-      #endif
 		
 	if ((dump.magic != WANPIPE_MAGIC) ||
 	    (dump.offset + dump.length > card->hw.memory))
 		return -EINVAL;
 	
-      #ifdef LINUX_2_0
-        if ((dump.ptr == NULL) ||
-            verify_area(VERIFY_WRITE, dump.ptr, dump.length))
-                return -EFAULT;
-      #endif	
-
 	winsize = card->hw.dpmsize;
 
 	if(card->hw.type != SDLA_S514) {
@@ -1014,17 +972,13 @@
                                 break;
                         }
 			
-                      #if defined(LINUX_2_1) || defined(LINUX_2_4)
                         if(copy_to_user((void *)dump.ptr,
                                 (u8 *)card->hw.dpmbase + pos, len)){ 
 				
 				unlock_adapter_irq(&card->wandev.lock, &smp_flags);
 				return -EFAULT;
 			}
-                      #else
-			memcpy_tofs((void*)(dump.ptr),
-                        	(void*)(card->hw.dpmbase + pos), len);
-                      #endif
+
                         dump.length     -= len;
                         dump.offset     += len;
                         (char*)dump.ptr += len;
@@ -1035,15 +989,10 @@
         
 	}else {
 
-	     #if defined(LINUX_2_1) || defined(LINUX_2_4) 
                if(copy_to_user((void *)dump.ptr,
 			       (u8 *)card->hw.dpmbase + dump.offset, dump.length)){
 			return -EFAULT;
 		}
-             #else
-                memcpy_tofs((void*)(dump.ptr),
-                (void*)(card->hw.dpmbase + dump.offset), dump.length);
-             #endif
 	}
 
 	return err;
@@ -1064,15 +1013,8 @@
 		return -ENODEV;
 	}
 
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)	
 	if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)))
 		return -EFAULT;
-      #else
-        if ((u_exec == NULL) ||
-            verify_area(VERIFY_READ, u_exec, sizeof(sdla_exec_t)))
-                return -EFAULT;
-        memcpy_fromfs((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t));
-      #endif
 
 	if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL))
 		return -EINVAL;
@@ -1345,60 +1287,33 @@
 unsigned long get_ip_address (netdevice_t *dev, int option)
 {
 	
-      #ifdef LINUX_2_4
 	struct in_ifaddr *ifaddr;
 	struct in_device *in_dev;
 
 	if ((in_dev = __in_dev_get(dev)) == NULL){
 		return 0;
 	}
-      #elif defined(LINUX_2_1)
-	struct in_ifaddr *ifaddr;
-	struct in_device *in_dev;
-	
-	if ((in_dev = dev->ip_ptr) == NULL){
-		return 0;
-	}
-      #endif
 
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if ((ifaddr = in_dev->ifa_list)== NULL ){
 		return 0;
 	}
-      #endif
 	
 	switch (option){
 
 	case WAN_LOCAL_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_addr;
-	      #else	
 		return ifaddr->ifa_local;
-	      #endif	
 		break;
 	
 	case WAN_POINTOPOINT_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_dstaddr;
-	      #else	
 		return ifaddr->ifa_address;
-	      #endif	
 		break;	
 
 	case WAN_NETMASK_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_mask;
-	      #else	
 		return ifaddr->ifa_mask;
-	      #endif	
 		break;
 
 	case WAN_BROADCAST_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_brdaddr;
-	      #else	
 		return ifaddr->ifa_broadcast;
-	      #endif	
 		break;
 	default:
 		return 0;
@@ -1431,11 +1346,7 @@
 
 	oldfs = get_fs();
 	set_fs(get_ds());
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	res = ip_rt_ioctl(SIOCADDRT,&route);
-      #else
-	res = ip_rt_new(&route);
-      #endif
 	set_fs(oldfs);
 
 	if (res == 0){
diff -Nru a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c
--- a/drivers/net/wan/wanpipe_multppp.c	Mon Feb 24 09:56:18 2003
+++ b/drivers/net/wan/wanpipe_multppp.c	Thu Mar  6 09:25:30 2003
@@ -42,19 +42,11 @@
 #include <linux/if_wanpipe.h>		
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-  #include <linux/inetdevice.h>
-  #include <asm/uaccess.h>
+#include <linux/inetdevice.h>
+#include <asm/uaccess.h>
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
- #include <net/syncppp.h>
-#else
- #include "syncppp.h"
-#endif
+#include <net/syncppp.h>
 
-#else
-  #include <net/route.h>          /* Adding new route entries */
-#endif
 
 /****** Defines & Macros ****************************************************/
 
@@ -148,15 +140,9 @@
 static int if_open   (netdevice_t* dev);
 static int if_close  (netdevice_t* dev);
 static int if_send (struct sk_buff* skb, netdevice_t* dev);
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats* if_stats (netdevice_t* dev);
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev);
-#endif
 
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
 /* CHDLC Firmware interface functions */
 static int chdlc_configure 	(sdla_t* card, void* data);
@@ -601,18 +587,8 @@
 
 	/* prepare network device data space for registration */
 
-#ifdef LINUX_2_4
 	strcpy(dev->name,card->u.c.if_name);
-#else
-	dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(chdlc_priv_area);	
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", card->u.c.if_name);
-#endif
-	
+
 	/* Attach PPP protocol layer to pppdev
 	 * The sppp_attach() will initilize the dev structure
          * and setup ppp layer protocols.
@@ -620,11 +596,7 @@
          *        if_open(), if_close(), if_send() and get_stats() functions.
          */
 	sppp_attach(pppdev);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
 	dev = pppdev->dev;
-#else
-	dev = &pppdev->dev;
-#endif
 	sp = &pppdev->sppp;
 	
 	/* Enable PPP Debugging */
@@ -684,9 +656,6 @@
 	chdlc_private_area_t* chdlc_priv_area = dev->priv;
 	sdla_t* card = chdlc_priv_area->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 	
 	/* NOTE: Most of the dev initialization was
          *       done in sppp_attach(), called by new_if() 
@@ -699,16 +668,10 @@
 	dev->stop		= &if_close;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 
-#ifdef LINUX_2_0
-	dev->family		= AF_INET;
-#endif	
- 
 	/* Initialize hardware parameters */
 	dev->irq	= wandev->irq;
 	dev->dma	= wandev->dma;
@@ -724,17 +687,10 @@
 	 */
         dev->tx_queue_len = 100;
    
-	/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-#endif
-
 	return 0;
 }
 
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -754,8 +710,6 @@
 	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
 	netif_wake_queue (dev);
 }
-#endif
-
 
 
 /*============================================================================
@@ -773,14 +727,8 @@
 	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
 
 	/* Only one open per interface is allowed */
-
-#ifdef LINUX_2_4
 	if (netif_running(dev))
 		return -EBUSY;
-#else
-	if (dev->start)
-		return -EBUSY;		/* only one open is allowed */
-#endif
 
 	/* Start PPP Layer */
 	if (sppp_open(dev)){
@@ -790,13 +738,7 @@
 	do_gettimeofday(&tv);
 	chdlc_priv_area->router_start_time = tv.tv_sec;
  
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 	
 	wanpipe_open(card);
 
@@ -817,11 +759,7 @@
 
 	/* Stop the PPP Layer */
 	sppp_close(dev);
-	stop_net_queue(dev);
-
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 
 	wanpipe_close(card);
 	
@@ -855,9 +793,7 @@
 	unsigned long smp_flags;
 	int err=0;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 
 	
 	if (skb == NULL){
@@ -867,32 +803,10 @@
 		printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",
 			card->devname, dev->name);
 
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
-#ifndef LINUX_2_4
-	if (dev->tbusy){
-
-		/* If our device stays busy for at least 5 seconds then we will
-		 * kick start the device by making dev->tbusy = 0.  We expect 
-		 * that our device never stays busy more than 5 seconds. So this
-		 * is only used as a last resort. 
-		 */
-                ++card->wandev.stats.collisions;
-
-		if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) {
-			return 1;
-		}
-
-		printk (KERN_INFO "%s: Transmit (tbusy) timeout !\n",
-			card->devname);
-
-		/* unbusy the interface */
-		dev->tbusy = 0;
-	}
-#endif
-
    	if (ntohs(skb->protocol) != htons(PVC_PROT)){
 		/* check the udp packet type */
 		
@@ -903,7 +817,7 @@
 				chdlc_int->interrupt_permission |=
 					APP_INT_ON_TIMER;
 			}
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			return 0;
 		}
         }
@@ -918,33 +832,29 @@
 		printk(KERN_INFO "%s: Critical in if_send: %lx\n",
 					card->wandev.name,card->wandev.critical);
                 ++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_crit_exit;
 	}
 
 	if (card->wandev.state != WAN_CONNECTED){
 		++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_crit_exit;
 	}
 	
 	if (chdlc_send(card, skb->data, skb->len)){
-		stop_net_queue(dev);
+		netif_stop_queue(dev);
 
 	}else{
 		++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
        		card->wandev.stats.tx_bytes += skb->len;
-#endif
-#ifdef LINUX_2_4
 		dev->trans_start = jiffies;
-#endif
-		start_net_queue(dev);
+		netif_start_queue(dev);
 	}	
 
 if_send_crit_exit:
-	if (!(err=is_queue_stopped(dev))){
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+	if (!(err=netif_queue_stopped(dev))){
+                dev_kfree_skb_any(skb);
 	}else{
 		chdlc_priv_area->tick_counter = jiffies;
 		chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
@@ -1063,7 +973,6 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct enet_statistics.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats* if_stats (netdevice_t* dev)
 {
 	sdla_t *my_card;
@@ -1079,23 +988,7 @@
 	my_card = chdlc_priv_area->card;
 	return &my_card->wandev.stats; 
 }
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev)
-{
-        sdla_t *my_card;
-        chdlc_private_area_t* chdlc_priv_area = dev->priv;
 
-	/* Shutdown bug fix. In del_if() we kill
-         * dev->priv pointer. This function, gets
-         * called after del_if(), thus check
-         * if pointer has been deleted */
-	if ((chdlc_priv_area=dev->priv) == NULL)
-		return NULL;
-
-        my_card = chdlc_priv_area->card;
-        return &my_card->wandev.stats;
-}
-#endif
 
 /****** Cisco HDLC Firmware Interface Functions *******************************/
 
@@ -1417,7 +1310,7 @@
 			flags->interrupt_info_struct.interrupt_permission &=
 				 ~APP_INT_ON_TX_FRAME;
 
-			wake_net_dev(dev);
+			netif_wake_queue(dev);
 			break;
 
 		case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
@@ -1505,15 +1398,9 @@
 		goto rx_exit;
 	}
 	
-#ifdef LINUX_2_4
 	if (!netif_running(dev)){
 		goto rx_exit;
 	}
-#else
-	if (!dev->start){ 
-		goto rx_exit;
-	}
-#endif
 
 	chdlc_priv_area = dev->priv;
 
@@ -1555,9 +1442,7 @@
 	skb->protocol = htons(ETH_P_WAN_PPP);
 
 	card->wandev.stats.rx_packets ++;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	card->wandev.stats.rx_bytes += skb->len;
-#endif
 	udp_type = udp_pkt_type( skb, card );
 
 	if(udp_type == UDP_CPIPE_TYPE) {
@@ -1795,9 +1680,9 @@
 	}
 
 	if(udp_pkt_src == UDP_PKT_FRM_STACK)
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+		dev_kfree_skb_any(skb);
 	else
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	
 	return(udp_pkt_stored);
 }
@@ -2156,9 +2041,7 @@
      	if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
 		if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
 			++ card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			card->wandev.stats.tx_bytes += len;
-#endif
 		}
 	} else {	
 	
@@ -2360,28 +2243,20 @@
 
 void s508_lock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
         if (card->next){
 		/* It is ok to use spin_lock here, since we
 		 * already turned off interrupts */
         	spin_lock(&card->next->wandev.lock);
 	}
-#else
-	disable_irq(card->hw.irq);
-#endif
 }
 
 void s508_unlock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	if (card->next){
 		spin_unlock(&card->next->wandev.lock);
 	}
 	spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-#else
-	enable_irq(card->hw.irq);
-#endif           
 }
 
 
diff -Nru a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
--- a/drivers/oprofile/buffer_sync.c	Thu Feb 20 10:06:22 2003
+++ b/drivers/oprofile/buffer_sync.c	Sun Mar  2 22:46:44 2003
@@ -277,10 +277,7 @@
  */
 static struct mm_struct * take_task_mm(struct task_struct * task)
 {
-	struct mm_struct * mm;
-	task_lock(task);
-	mm = task->mm;
-	task_unlock(task);
+	struct mm_struct * mm = task->mm;
  
 	/* if task->mm !NULL, mm_count must be at least 1. It cannot
 	 * drop to 0 without the task exiting, which will have to sleep
@@ -310,6 +307,32 @@
 }
  
 
+/* compute number of filled slots in cpu_buffer queue */
+static unsigned long nr_filled_slots(struct oprofile_cpu_buffer * b)
+{
+	unsigned long head = b->head_pos;
+	unsigned long tail = b->tail_pos;
+
+	if (head >= tail)
+		return head - tail;
+
+	return head + (b->buffer_size - tail);
+}
+
+
+static void increment_tail(struct oprofile_cpu_buffer * b)
+{
+	unsigned long new_tail = b->tail_pos + 1;
+
+	rmb();
+
+	if (new_tail < (b->buffer_size))
+		b->tail_pos = new_tail;
+	else
+		b->tail_pos = 0;
+}
+
+
 /* Sync one of the CPU's buffers into the global event buffer.
  * Here we need to go through each batch of samples punctuated
  * by context switch notes, taking the task's mmap_sem and doing
@@ -322,10 +345,14 @@
 	struct task_struct * new;
 	unsigned long cookie;
 	int in_kernel = 1;
-	int i;
+	unsigned int i;
  
-	for (i=0; i < cpu_buf->pos; ++i) {
-		struct op_sample * s = &cpu_buf->buffer[i];
+	/* Remember, only we can modify tail_pos */
+
+	unsigned long const available_elements = nr_filled_slots(cpu_buf);
+  
+	for (i=0; i < available_elements; ++i) {
+		struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
  
 		if (is_ctx_switch(s->eip)) {
 			if (s->event <= 1) {
@@ -345,6 +372,8 @@
 		} else {
 			add_sample(mm, s, in_kernel);
 		}
+
+		increment_tail(cpu_buf);
 	}
 	release_mm(mm);
 
@@ -369,17 +398,8 @@
  
 		cpu_buf = &cpu_buffer[i];
  
-		/* We take a spin lock even though we might
-		 * sleep. It's OK because other users are try
-		 * lockers only, and this region is already
-		 * protected by buffer_sem. It's raw to prevent
-		 * the preempt bogometer firing. Fruity, huh ? */
-		if (cpu_buf->pos > 0) {
-			_raw_spin_lock(&cpu_buf->int_lock);
-			add_cpu_switch(i);
-			sync_buffer(cpu_buf);
-			_raw_spin_unlock(&cpu_buf->int_lock);
-		}
+		add_cpu_switch(i);
+		sync_buffer(cpu_buf);
 	}
 
 	up(&buffer_sem);
diff -Nru a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
--- a/drivers/oprofile/cpu_buffer.c	Thu Jan 23 12:24:53 2003
+++ b/drivers/oprofile/cpu_buffer.c	Thu Mar  6 08:24:34 2003
@@ -26,8 +26,6 @@
 
 struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
 
-static unsigned long buffer_size;
- 
 static void __free_cpu_buffers(int num)
 {
 	int i;
@@ -47,7 +45,7 @@
 {
 	int i;
  
-	buffer_size = fs_cpu_buffer_size;
+	unsigned long buffer_size = fs_cpu_buffer_size;
  
 	for (i=0; i < NR_CPUS; ++i) {
 		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
@@ -59,12 +57,12 @@
 		if (!b->buffer)
 			goto fail;
  
-		spin_lock_init(&b->int_lock);
-		b->pos = 0;
 		b->last_task = 0;
 		b->last_is_kernel = -1;
+		b->buffer_size = buffer_size;
+		b->tail_pos = 0;
+		b->head_pos = 0;
 		b->sample_received = 0;
-		b->sample_lost_locked = 0;
 		b->sample_lost_overflow = 0;
 		b->sample_lost_task_exit = 0;
 	}
@@ -80,11 +78,38 @@
 	__free_cpu_buffers(NR_CPUS);
 }
 
- 
-/* Note we can't use a semaphore here as this is supposed to
- * be safe from any context. Instead we trylock the CPU's int_lock.
- * int_lock is taken by the processing code in sync_cpu_buffers()
- * so we avoid disturbing that.
+
+/* compute number of available slots in cpu_buffer queue */
+static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b)
+{
+	unsigned long head = b->head_pos;
+	unsigned long tail = b->tail_pos;
+
+	if (tail > head)
+		return tail - head;
+
+	return tail + (b->buffer_size - head);
+}
+
+
+static void increment_head(struct oprofile_cpu_buffer * b)
+{
+	unsigned long new_head = b->head_pos + 1;
+
+	/* Ensure anything written to the slot before we
+	 * increment is visible */
+	wmb();
+
+	if (new_head < (b->buffer_size))
+		b->head_pos = new_head;
+	else
+		b->head_pos = 0;
+}
+
+
+/* This must be safe from any context. It's safe writing here
+ * because of the head/tail separation of the writer and reader
+ * of the CPU buffer.
  *
  * is_kernel is needed because on some architectures you cannot
  * tell if you are in kernel or user space simply by looking at
@@ -101,14 +126,10 @@
 
 	cpu_buf->sample_received++;
  
-	if (!spin_trylock(&cpu_buf->int_lock)) {
-		cpu_buf->sample_lost_locked++;
-		return;
-	}
 
-	if (cpu_buf->pos > buffer_size - 2) {
+	if (nr_available_slots(cpu_buf) < 3) {
 		cpu_buf->sample_lost_overflow++;
-		goto out;
+		return;
 	}
 
 	task = current;
@@ -116,18 +137,18 @@
 	/* notice a switch from user->kernel or vice versa */
 	if (cpu_buf->last_is_kernel != is_kernel) {
 		cpu_buf->last_is_kernel = is_kernel;
-		cpu_buf->buffer[cpu_buf->pos].eip = ~0UL;
-		cpu_buf->buffer[cpu_buf->pos].event = is_kernel;
-		cpu_buf->pos++;
+		cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
+		cpu_buf->buffer[cpu_buf->head_pos].event = is_kernel;
+		increment_head(cpu_buf);
 	}
 
 	/* notice a task switch */
 	if (cpu_buf->last_task != task) {
 		cpu_buf->last_task = task;
 		if (!(task->flags & PF_EXITING)) {
-			cpu_buf->buffer[cpu_buf->pos].eip = ~0UL;
-			cpu_buf->buffer[cpu_buf->pos].event = (unsigned long)task;
-			cpu_buf->pos++;
+			cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
+			cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task;
+			increment_head(cpu_buf);
 		}
 	}
  
@@ -138,23 +159,20 @@
 	 */
 	if (task->flags & PF_EXITING) {
 		cpu_buf->sample_lost_task_exit++;
-		goto out;
+		return;
 	}
  
-	cpu_buf->buffer[cpu_buf->pos].eip = eip;
-	cpu_buf->buffer[cpu_buf->pos].event = event;
-	cpu_buf->pos++;
-out:
-	spin_unlock(&cpu_buf->int_lock);
+	cpu_buf->buffer[cpu_buf->head_pos].eip = eip;
+	cpu_buf->buffer[cpu_buf->head_pos].event = event;
+	increment_head(cpu_buf);
 }
 
+
 /* resets the cpu buffer to a sane state - should be called with 
  * cpu_buf->int_lock held
  */
 void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf)
 {
-	cpu_buf->pos = 0;
-
 	/* reset these to invalid values; the next sample
 	 * collected will populate the buffer with proper
 	 * values to initialize the buffer
@@ -162,4 +180,3 @@
 	cpu_buf->last_is_kernel = -1;
 	cpu_buf->last_task = 0;
 }
-
diff -Nru a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
--- a/drivers/oprofile/cpu_buffer.h	Thu Jan 23 12:24:53 2003
+++ b/drivers/oprofile/cpu_buffer.h	Wed Mar  5 13:56:22 2003
@@ -30,14 +30,13 @@
 };
  
 struct oprofile_cpu_buffer {
-	spinlock_t int_lock;
-	/* protected by int_lock */
-	unsigned long pos;
+	volatile unsigned long head_pos;
+	volatile unsigned long tail_pos;
+	unsigned long buffer_size;
 	struct task_struct * last_task;
 	int last_is_kernel;
 	struct op_sample * buffer;
 	unsigned long sample_received;
-	unsigned long sample_lost_locked;
 	unsigned long sample_lost_overflow;
 	unsigned long sample_lost_task_exit;
 } ____cacheline_aligned;
diff -Nru a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
--- a/drivers/oprofile/oprofile_stats.c	Sun Dec 22 04:53:01 2002
+++ b/drivers/oprofile/oprofile_stats.c	Tue Feb 25 05:56:06 2003
@@ -27,7 +27,6 @@
 
 		cpu_buf = &cpu_buffer[i]; 
 		cpu_buf->sample_received = 0;
-		cpu_buf->sample_lost_locked = 0;
 		cpu_buf->sample_lost_overflow = 0;
 		cpu_buf->sample_lost_task_exit = 0;
 	}
@@ -63,8 +62,6 @@
 		 */
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_received",
 			&cpu_buf->sample_received);
-		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_locked",
-			&cpu_buf->sample_lost_locked);
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow",
 			&cpu_buf->sample_lost_overflow);
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit",
diff -Nru a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
--- a/drivers/parport/ieee1284.c	Mon Nov 18 14:18:05 2002
+++ b/drivers/parport/ieee1284.c	Wed Mar  5 21:39:37 2003
@@ -170,7 +170,7 @@
 {
 	int ret;
 	int usec;
-	long deadline;
+	unsigned long deadline;
 	unsigned char status;
 
 	usec = port->physport->spintime; /* usecs of fast polling */
diff -Nru a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
--- a/drivers/parport/ieee1284_ops.c	Sat Nov 23 06:29:46 2002
+++ b/drivers/parport/ieee1284_ops.c	Wed Mar  5 21:39:37 2003
@@ -58,7 +58,7 @@
 	parport_write_control (port, ctl);
 	parport_data_forward (port);
 	while (count < len) {
-		long expire = jiffies + dev->timeout;
+		unsigned long expire = jiffies + dev->timeout;
 		long wait = (HZ + 99) / 100;
 		unsigned char mask = (PARPORT_STATUS_ERROR
 				      | PARPORT_STATUS_BUSY);
@@ -431,7 +431,7 @@
 			      | PARPORT_CONTROL_INIT,
 			      PARPORT_CONTROL_INIT);
 	for (written = 0; written < len; written++, buf++) {
-		long expire = jiffies + port->cad->timeout;
+		unsigned long expire = jiffies + port->cad->timeout;
 		unsigned char byte;
 
 		byte = *buf;
@@ -520,7 +520,7 @@
 	parport_write_control (port,
 			       ctl | PARPORT_CONTROL_AUTOFD);
 	while (count < len) {
-		long expire = jiffies + dev->timeout;
+		unsigned long expire = jiffies + dev->timeout;
 		unsigned char byte;
 		int command;
 
@@ -668,7 +668,7 @@
 			      PARPORT_CONTROL_AUTOFD
 			      | PARPORT_CONTROL_INIT);
 	for (written = 0; written < len; written++, buf++) {
-		long expire = jiffies + port->cad->timeout;
+		unsigned long expire = jiffies + port->cad->timeout;
 		unsigned char byte;
 
 		byte = *buf;
diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile	Tue Feb 18 18:58:56 2003
+++ b/drivers/pci/Makefile	Sat Mar  1 07:41:20 2003
@@ -2,7 +2,7 @@
 # Makefile for the PCI bus specific drivers.
 #
 
-obj-y		+= access.o probe.o pci.o pool.o quirks.o \
+obj-y		+= access.o bus.o probe.o pci.o pool.o quirks.o \
 			names.o pci-driver.o search.o hotplug.o \
 			pci-sysfs.o
 obj-$(CONFIG_PM)  += power.o
diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/bus.c	Mon Mar  3 13:26:41 2003
@@ -0,0 +1,127 @@
+/*
+ *	drivers/pci/bus.c
+ *
+ * From setup-res.c, by:
+ *	Dave Rusling (david.rusling@reo.mts.dec.com)
+ *	David Mosberger (davidm@cs.arizona.edu)
+ *	David Miller (davem@redhat.com)
+ *	Ivan Kokshaysky (ink@jurassic.park.msu.ru)
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include "pci.h"
+
+/**
+ * pci_bus_alloc_resource - allocate a resource from a parent bus
+ * @bus: PCI bus
+ * @res: resource to allocate
+ * @size: size of resource to allocate
+ * @align: alignment of resource to allocate
+ * @min: minimum /proc/iomem address to allocate
+ * @type_mask: IORESOURCE_* type flags
+ * @alignf: resource alignment function
+ * @alignf_data: data argument for resource alignment function
+ *
+ * Given the PCI bus a device resides on, the size, minimum address,
+ * alignment and type, try to find an acceptable resource allocation
+ * for a specific device resource.
+ */
+int
+pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+	unsigned long size, unsigned long align, unsigned long min,
+	unsigned int type_mask,
+	void (*alignf)(void *, struct resource *,
+			unsigned long, unsigned long),
+	void *alignf_data)
+{
+	int i, ret = -ENOMEM;
+
+	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
+
+	for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
+		struct resource *r = bus->resource[i];
+		if (!r)
+			continue;
+
+		/* type_mask must match */
+		if ((res->flags ^ r->flags) & type_mask)
+			continue;
+
+		/* We cannot allocate a non-prefetching resource
+		   from a pre-fetching area */
+		if ((r->flags & IORESOURCE_PREFETCH) &&
+		    !(res->flags & IORESOURCE_PREFETCH))
+			continue;
+
+		/* Ok, try it out.. */
+		ret = allocate_resource(r, res, size, min, -1, align,
+					alignf, alignf_data);
+		if (ret == 0)
+			break;
+	}
+	return ret;
+}
+
+/**
+ * pci_bus_add_devices - insert newly discovered PCI devices
+ * @bus: bus to check for new devices
+ *
+ * Add newly discovered PCI devices (which are on the bus->devices
+ * list) to the global PCI device list, add the sysfs and procfs
+ * entries.  Where a bridge is found, add the discovered bus to
+ * the parents list of child buses, and recurse.
+ *
+ * Call hotplug for each new devices.
+ */
+void __devinit pci_bus_add_devices(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		/*
+		 * Skip already-present devices (which are on the
+		 * global device list.)
+		 */
+		if (!list_empty(&dev->global_list))
+			continue;
+
+		device_register(&dev->dev);
+		list_add_tail(&dev->global_list, &pci_devices);
+#ifdef CONFIG_PROC_FS
+		pci_proc_attach_device(dev);
+#endif
+		pci_create_sysfs_dev_files(dev);
+
+		/*
+		 * If there is an unattached subordinate bus, attach
+		 * it and then scan for unattached PCI devices.
+		 */
+		if (dev->subordinate && list_empty(&dev->subordinate->node)) {
+			list_add_tail(&dev->subordinate->node, &dev->bus->children);
+			pci_bus_add_devices(dev->subordinate);
+		}
+	}
+}
+
+void pci_enable_bridges(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		if (dev->subordinate) {
+			pci_enable_device(dev);
+			pci_set_master(dev);
+			pci_enable_bridges(dev->subordinate);
+		}
+	}
+}
+
+EXPORT_SYMBOL(pci_bus_alloc_resource);
+EXPORT_SYMBOL(pci_bus_add_devices);
+EXPORT_SYMBOL(pci_enable_bridges);
diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids
--- a/drivers/pci/pci.ids	Thu Dec 26 06:03:41 2002
+++ b/drivers/pci/pci.ids	Sun Mar 16 15:23:56 2003
@@ -5440,6 +5440,11 @@
 		14f1 2004  Dynalink 56PMi
 	8234  RS8234 ATM SAR Controller [ServiceSAR Plus]
 14f2  MOBILITY Electronics
+	0120  EV1000 bridge
+	0121  EV1000 Parallel port
+	0122  EV1000 Serial port
+	0123  EV1000 Keyboard controller
+	0124  EV1000 Mouse controller
 14f3  BROADLOGIC
 14f4  TOKYO Electronic Industry CO Ltd
 14f5  SOPAC Ltd
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	Mon Feb 24 08:17:19 2003
+++ b/drivers/pci/probe.c	Sun Mar 16 15:20:31 2003
@@ -15,6 +15,9 @@
 #define DBG(x...)
 #endif
 
+#define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
+#define CARDBUS_RESERVE_BUSNR	3
+
 LIST_HEAD(pci_root_buses);
 LIST_HEAD(pci_devices);
 
@@ -221,47 +224,64 @@
 	b = kmalloc(sizeof(*b), GFP_KERNEL);
 	if (b) {
 		memset(b, 0, sizeof(*b));
+		INIT_LIST_HEAD(&b->node);
 		INIT_LIST_HEAD(&b->children);
 		INIT_LIST_HEAD(&b->devices);
 	}
 	return b;
 }
 
-struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+static struct pci_bus * __devinit
+pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 {
 	struct pci_bus *child;
-	int i;
 
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 */
 	child = pci_alloc_bus();
 
-	list_add_tail(&child->node, &parent->children);
-	child->self = dev;
-	dev->subordinate = child;
-	child->parent = parent;
-	child->ops = parent->ops;
-	child->sysdata = parent->sysdata;
-	child->dev = &dev->dev;
+	if (child) {
+		int i;
 
-	/*
-	 * Set up the primary, secondary and subordinate
-	 * bus numbers.
-	 */
-	child->number = child->secondary = busnr;
-	child->primary = parent->secondary;
-	child->subordinate = 0xff;
+		child->self = bridge;
+		child->parent = parent;
+		child->ops = parent->ops;
+		child->sysdata = parent->sysdata;
+		child->dev = &bridge->dev;
 
-	/* Set up default resource pointers and names.. */
-	for (i = 0; i < 4; i++) {
-		child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
-		child->resource[i]->name = child->name;
+		/*
+		 * Set up the primary, secondary and subordinate
+		 * bus numbers.
+		 */
+		child->number = child->secondary = busnr;
+		child->primary = parent->secondary;
+		child->subordinate = 0xff;
+
+		/* Set up default resource pointers and names.. */
+		for (i = 0; i < 4; i++) {
+			child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i];
+			child->resource[i]->name = child->name;
+		}
+
+		bridge->subordinate = child;
 	}
 
 	return child;
 }
 
+struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+{
+	struct pci_bus *child;
+
+	child = pci_alloc_child_bus(parent, dev, busnr);
+	if (child)
+		list_add_tail(&child->node, &parent->children);
+	return child;
+}
+
+static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
+
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
@@ -274,12 +294,15 @@
  */
 int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
 {
-	unsigned int buses;
 	struct pci_bus *child;
 	int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
+	u32 buses;
 
 	pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
-	DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass);
+
+	DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n",
+	    dev->slot_name, buses & 0xffffff, pass);
+
 	if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
 		unsigned int cmax;
 		/*
@@ -288,12 +311,12 @@
 		 */
 		if (pass)
 			return max;
-		child = pci_add_new_bus(bus, dev, 0);
+		child = pci_alloc_child_bus(bus, dev, 0);
 		child->primary = buses & 0xFF;
 		child->secondary = (buses >> 8) & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
 		child->number = child->secondary;
-		cmax = pci_do_scan_bus(child);
+		cmax = pci_scan_child_bus(child);
 		if (cmax > max) max = cmax;
 	} else {
 		/*
@@ -306,25 +329,36 @@
 		/* Clear errors */
 		pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
-		child = pci_add_new_bus(bus, dev, ++max);
+		child = pci_alloc_child_bus(bus, dev, ++max);
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->secondary)   <<  8)
 		      | ((unsigned int)(child->subordinate) << 16);
+
+		/*
+		 * yenta.c forces a secondary latency timer of 176.
+		 * Copy that behaviour here.
+		 */
+		if (is_cardbus) {
+			buses &= ~0xff000000;
+			buses |= CARDBUS_LATENCY_TIMER << 24;
+		}
+			
 		/*
 		 * We need to blast all three values with a single write.
 		 */
 		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+
 		if (!is_cardbus) {
 			/* Now we can scan all subordinate buses... */
-			max = pci_do_scan_bus(child);
+			max = pci_scan_child_bus(child);
 		} else {
 			/*
 			 * For CardBus bridges, we leave 4 bus numbers
 			 * as cards with a PCI-to-PCI bridge can be
 			 * inserted later.
 			 */
-			max += 3;
+			max += CARDBUS_RESERVE_BUSNR;
 		}
 		/*
 		 * Set the subordinate bus number to its real value.
@@ -332,6 +366,7 @@
 		child->subordinate = max;
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 	}
+
 	sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
 
 	return max;
@@ -365,16 +400,20 @@
 {
 	u32 class;
 
-	sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-	sprintf(dev->dev.name, "PCI device %04x:%04x", dev->vendor, dev->device);
+	sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number,
+		PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	sprintf(dev->dev.name, "PCI device %04x:%04x",
+		dev->vendor, dev->device);
+
 	INIT_LIST_HEAD(&dev->pools);
-	
+
 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
 	class >>= 8;				    /* upper 3 bytes */
 	dev->class = class;
 	class >>= 8;
 
-	DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, class, dev->hdr_type);
+	DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number,
+	    dev->devfn, dev->vendor, dev->device, class, dev->hdr_type);
 
 	/* "Unknown power state" */
 	dev->current_state = 4;
@@ -427,23 +466,36 @@
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
  */
-struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp)
+static struct pci_dev * __devinit
+pci_scan_device(struct pci_bus *bus, int devfn)
 {
 	struct pci_dev *dev;
 	u32 l;
+	u8 hdr_type;
 
-	if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l))
+	if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
+		return NULL;
+
+	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
 		return NULL;
 
 	/* some broken boards return 0 or ~0 if a slot is empty: */
-	if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
+	if (l == 0xffffffff || l == 0x00000000 ||
+	    l == 0x0000ffff || l == 0xffff0000)
 		return NULL;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
 
-	memcpy(dev, temp, sizeof(*dev));
+	memset(dev, 0, sizeof(struct pci_dev));
+	dev->bus = bus;
+	dev->sysdata = bus->sysdata;
+	dev->dev.parent = bus->dev;
+	dev->dev.bus = &pci_bus_type;
+	dev->devfn = devfn;
+	dev->hdr_type = hdr_type & 0x7f;
+	dev->multifunction = !!(hdr_type & 0x80);
 	dev->vendor = l & 0xffff;
 	dev->device = (l >> 16) & 0xffff;
 
@@ -461,74 +513,66 @@
 	strcpy(dev->dev.bus_id,dev->slot_name);
 	dev->dev.dma_mask = &dev->dma_mask;
 
-	device_register(&dev->dev);
 	return dev;
 }
 
-struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp)
+/**
+ * pci_scan_slot - scan a PCI slot on a bus for devices.
+ * @bus: PCI bus to scan
+ * @devfn: slot number to scan (must have zero function.)
+ *
+ * Scan a PCI slot on the specified PCI bus for devices, adding
+ * discovered devices to the @bus->devices list.  New devices
+ * will have an empty dev->global_list head.
+ */
+int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
 {
-	struct pci_bus *bus = temp->bus;
-	struct pci_dev *dev;
-	struct pci_dev *first_dev = NULL;
-	int func = 0;
-	int is_multi = 0;
-	u8 hdr_type;
+	int func, nr = 0;
 
-	for (func = 0; func < 8; func++, temp->devfn++) {
-		if (func && !is_multi)		/* not a multi-function device */
-			continue;
-		if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type))
-			continue;
-		temp->hdr_type = hdr_type & 0x7f;
+	for (func = 0; func < 8; func++, devfn++) {
+		struct pci_dev *dev;
 
-		dev = pci_scan_device(temp);
-		if (!dev)
-			continue;
-		if (!func) {
-			is_multi = hdr_type & 0x80;
-			first_dev = dev;
+		dev = pci_scan_device(bus, devfn);
+		if (func == 0) {
+			if (!dev)
+				break;
+		} else {
+			if (!dev)
+				continue;
+			dev->multifunction = 1;
 		}
 
+		/* Fix up broken headers */
+		pci_fixup_device(PCI_FIXUP_HEADER, dev);
+
 		/*
-		 * Link the device to both the global PCI device chain and
-		 * the per-bus list of devices and add the /proc entry.
+		 * Add the device to our list of discovered devices
+		 * and the bus list for fixup functions, etc.
 		 */
-		pci_insert_device (dev, bus);
+		INIT_LIST_HEAD(&dev->global_list);
+		list_add_tail(&dev->bus_list, &bus->devices);
+		nr++;
 
-		/* Fix up broken headers */
-		pci_fixup_device(PCI_FIXUP_HEADER, dev);
+		/*
+		 * If this is a single function device,
+		 * don't scan past the first function.
+		 */
+		if (!dev->multifunction)
+			break;
 	}
-	return first_dev;
+	return nr;
 }
 
-unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
+static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
 {
-	unsigned int devfn, max, pass;
-	struct list_head *ln;
+	unsigned int devfn, pass, max = bus->secondary;
 	struct pci_dev *dev;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev) {
-		printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
-		return 0;
-	}
-
 	DBG("Scanning bus %02x\n", bus->number);
-	max = bus->secondary;
-
-	/* Create a device template */
-	memset(dev, 0, sizeof(*dev));
-	dev->bus = bus;
-	dev->sysdata = bus->sysdata;
-	dev->dev.parent = bus->dev;
-	dev->dev.bus = &pci_bus_type;
 
 	/* Go find them, Rover! */
-	for (devfn = 0; devfn < 0x100; devfn += 8) {
-		dev->devfn = devfn;
-		pci_scan_slot(dev);
-	}
-	kfree(dev);
+	for (devfn = 0; devfn < 0x100; devfn += 8)
+		pci_scan_slot(bus, devfn);
 
 	/*
 	 * After performing arch-dependent fixup of the bus, look behind
@@ -537,9 +581,9 @@
 	DBG("Fixups for bus %02x\n", bus->number);
 	pcibios_fixup_bus(bus);
 	for (pass=0; pass < 2; pass++)
-		for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
-			dev = pci_dev_b(ln);
-			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+		list_for_each_entry(dev, &bus->devices, bus_list) {
+			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 				max = pci_scan_bridge(bus, dev, max, pass);
 		}
 
@@ -554,6 +598,20 @@
 	return max;
 }
 
+unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
+{
+	unsigned int max;
+
+	max = pci_scan_child_bus(bus);
+
+	/*
+	 * Make the discovered devices available.
+	 */
+	pci_bus_add_devices(bus);
+
+	return max;
+}
+
 int __devinit pci_bus_exists(const struct list_head *list, int nr)
 {
 	const struct pci_bus *b;
@@ -605,7 +663,8 @@
 	if (b) {
 		b->sysdata = sysdata;
 		b->ops = ops;
-		b->subordinate = pci_do_scan_bus(b);
+		b->subordinate = pci_scan_child_bus(b);
+		pci_bus_add_devices(b);
 	}
 	return b;
 }
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Sat Feb 15 04:56:07 2003
+++ b/drivers/pci/quirks.c	Thu Feb 20 08:59:29 2003
@@ -167,6 +167,22 @@
 	}
 }
 
+/*
+ *	Ali Magik requires workarounds to be used by the drivers
+ *	that DMA to AGP space. Latency must be set to 0xA and triton
+ *	workaround applied too
+ *	[Info kindly provided by ALi]
+ */	
+ 
+static void __init quirk_alimagik(struct pci_dev *dev)
+{
+	if((pci_pci_problems&PCIPCI_ALIMAGIK)==0)
+	{
+		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+		pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON;
+	}
+}
+
 
 /*
  *	Natoma has some interesting boundary conditions with Zoran stuff
@@ -219,7 +235,7 @@
 static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
 {
 	printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
-	/* Mae rhaid in i beidio a edrych ar y lleoliad I/O hyn */
+	/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
 	request_region(0x3b0, 0x0C, "RadeonIGP");
 	request_region(0x3d3, 0x01, "RadeonIGP");
 }
@@ -535,6 +551,92 @@
 	}
 }
 
+/*
+ * As per PCI spec, ignore base address registers 0-3 of the IDE controllers
+ * running in Compatible mode (bits 0 and 2 in the ProgIf for primary and
+ * secondary channels respectively). If the device reports Compatible mode
+ * but does use BAR0-3 for address decoding, we assume that firmware has
+ * programmed these BARs with standard values (0x1f0,0x3f4 and 0x170,0x374).
+ * Exceptions (if they exist) must be handled in chip/architecture specific
+ * fixups.
+ *
+ * Note: for non x86 people. You may need an arch specific quirk to handle
+ * moving IDE devices to native mode as well. Some plug in card devices power
+ * up in compatible mode and assume the BIOS will adjust them.
+ *
+ * Q: should we load the 0x1f0,0x3f4 into the registers or zap them as
+ * we do now ? We don't want is pci_enable_device to come along
+ * and assign new resources. Both approaches work for that.
+ */ 
+
+static void __devinit quirk_ide_bases(struct pci_dev *dev)
+{
+       struct resource *res;
+       int first_bar = 2, last_bar = 0;
+
+       if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+               return;
+
+       res = &dev->resource[0];
+
+       /* primary channel: ProgIf bit 0, BAR0, BAR1 */
+       if (!(dev->class & 1) && (res[0].flags || res[1].flags)) { 
+               res[0].start = res[0].end = res[0].flags = 0;
+               res[1].start = res[1].end = res[1].flags = 0;
+               first_bar = 0;
+               last_bar = 1;
+       }
+
+       /* secondary channel: ProgIf bit 2, BAR2, BAR3 */
+       if (!(dev->class & 4) && (res[2].flags || res[3].flags)) { 
+               res[2].start = res[2].end = res[2].flags = 0;
+               res[3].start = res[3].end = res[3].flags = 0;
+               last_bar = 3;
+       }
+
+       if (!last_bar)
+               return;
+
+       printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n",
+              first_bar, last_bar, dev->slot_name);
+}
+
+/*
+ *	Ensure C0 rev restreaming is off. This is normally done by
+ *	the BIOS but in the odd case it is not the results are corruption
+ *	hence the presence of a Linux check
+ */
+ 
+static void __init quirk_disable_pxb(struct pci_dev *pdev)
+{
+	u16 config;
+	u8 rev;
+	
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+	if(rev != 0x04)		/* Only C0 requires this */
+		return;
+	pci_read_config_word(pdev, 0x40, &config);
+	if(config & (1<<6))
+	{
+		config &= ~(1<<6);
+		pci_write_config_word(pdev, 0x40, config);
+		printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");
+	}
+}
+
+/*
+ *	VIA northbridges care about PCI_INTERRUPT_LINE
+ */
+ 
+int interrupt_line_quirk;
+
+static void __init quirk_via_bridge(struct pci_dev *pdev)
+{
+	if(pdev->devfn == 0)
+		interrupt_line_quirk = 1;
+}
+	
+
 /* This was originally an Alpha specific thing, but it really fits here.
  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
  */
@@ -559,7 +661,10 @@
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton }, 
@@ -574,6 +679,8 @@
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,	quirk_vialatency },
@@ -586,6 +693,8 @@
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi },
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb },
+	{ PCI_FIXUP_HEADER,     PCI_ANY_ID,             PCI_ANY_ID,                     quirk_ide_bases },
+	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_VIA,	PCI_ANY_ID,                     quirk_via_bridge },
 	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy },
 
 #ifdef CONFIG_X86_IO_APIC 
diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c	Tue Feb 18 03:27:06 2003
+++ b/drivers/pci/setup-bus.c	Sun Mar 16 15:28:03 2003
@@ -72,40 +72,29 @@
    requires that if there is no I/O ports or memory behind the
    bridge, corresponding range must be turned off by writing base
    value greater than limit to the bridge's base/limit registers.  */
-static void __devinit
-pci_setup_bridge(struct pci_bus *bus)
+static void __devinit pci_setup_bridge(struct pci_bus *bus)
 {
-	struct pbus_set_ranges_data ranges;
 	struct pci_dev *bridge = bus->self;
+	struct pci_bus_region region;
 	u32 l;
 
-	if (!bridge || (bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-		return;
-
-	ranges.io_start = bus->resource[0]->start;
-	ranges.io_end = bus->resource[0]->end;
-	ranges.mem_start = bus->resource[1]->start;
-	ranges.mem_end = bus->resource[1]->end;
-	ranges.prefetch_start = bus->resource[2]->start;
-	ranges.prefetch_end = bus->resource[2]->end;
-	pcibios_fixup_pbus_ranges(bus, &ranges);
-
 	DBGC((KERN_INFO "PCI: Bus %d, bridge: %s\n",
 			bus->number, bridge->dev.name));
 
 	/* Set up the top and bottom of the PCI I/O segment for this bus. */
+	pcibios_resource_to_bus(bridge, &region, bus->resource[0]);
 	if (bus->resource[0]->flags & IORESOURCE_IO) {
 		pci_read_config_dword(bridge, PCI_IO_BASE, &l);
 		l &= 0xffff0000;
-		l |= (ranges.io_start >> 8) & 0x00f0;
-		l |= ranges.io_end & 0xf000;
+		l |= (region.start >> 8) & 0x00f0;
+		l |= region.end & 0xf000;
 		/* Set up upper 16 bits of I/O base/limit. */
 		pci_write_config_word(bridge, PCI_IO_BASE_UPPER16,
-				      ranges.io_start >> 16);
+				      region.start >> 16);
 		pci_write_config_word(bridge, PCI_IO_LIMIT_UPPER16,
-				      ranges.io_end >> 16);
+				      region.end >> 16);
 		DBGC((KERN_INFO "  IO window: %04lx-%04lx\n",
-				ranges.io_start, ranges.io_end));
+				region.start, region.end));
 	}
 	else {
 		/* Clear upper 16 bits of I/O base/limit. */
@@ -117,11 +106,12 @@
 
 	/* Set up the top and bottom of the PCI Memory segment
 	   for this bus. */
+	pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
 	if (bus->resource[1]->flags & IORESOURCE_MEM) {
-		l = (ranges.mem_start >> 16) & 0xfff0;
-		l |= ranges.mem_end & 0xfff00000;
+		l = (region.start >> 16) & 0xfff0;
+		l |= region.end & 0xfff00000;
 		DBGC((KERN_INFO "  MEM window: %08lx-%08lx\n",
-				ranges.mem_start, ranges.mem_end));
+				region.start, region.end));
 	}
 	else {
 		l = 0x0000fff0;
@@ -134,11 +124,12 @@
 	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 
 	/* Set up PREF base/limit. */
+	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
-		l = (ranges.prefetch_start >> 16) & 0xfff0;
-		l |= ranges.prefetch_end & 0xfff00000;
+		l = (region.start >> 16) & 0xfff0;
+		l |= region.end & 0xfff00000;
 		DBGC((KERN_INFO "  PREFETCH window: %08lx-%08lx\n",
-				ranges.prefetch_start, ranges.prefetch_end));
+				region.start, region.end));
 	}
 	else {
 		l = 0x0000fff0;
@@ -284,7 +275,7 @@
 				order = 0;
 			/* Exclude ranges with size > align from
 			   calculation of the alignment. */
-			if (size == align)
+			if (r_size == align)
 				aligns[order] += align;
 			if (order > max_order)
 				max_order = order;
@@ -350,6 +341,7 @@
 {
 	struct pci_bus *b;
 	int found_vga = pbus_assign_resources_sorted(bus);
+	struct pci_dev *dev;
 
 	if (found_vga) {
 		/* Propagate presence of the VGA to upstream bridges */
@@ -357,9 +349,12 @@
 			b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA;
 		}
 	}
-	list_for_each_entry(b, &bus->children, node) {
-		pci_bus_assign_resources(b);
-		pci_setup_bridge(b);
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		b = dev->subordinate;
+		if (b) {
+			pci_bus_assign_resources(b);
+			pci_setup_bridge(b);
+		}
 	}
 }
 EXPORT_SYMBOL(pci_bus_assign_resources);
diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c	Tue Dec 10 01:15:16 2002
+++ b/drivers/pci/setup-res.c	Sun Mar 16 14:16:33 2003
@@ -33,6 +33,59 @@
 #endif
 
 
+static void
+pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
+{
+	struct pci_bus_region region;
+	u32 new, check, mask;
+	int reg;
+
+	pcibios_resource_to_bus(dev, &region, res);
+
+	DBGC((KERN_ERR "  got res [%lx:%lx] bus [%lx:%lx] for "
+	      "resource %d of %s\n", res->start, res->end,
+	      region.start, region.end, resno, dev->dev.name));
+
+	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (res->flags & IORESOURCE_IO)
+		mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
+	else
+		mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
+
+	if (resno < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4 * resno;
+	} else if (resno == PCI_ROM_RESOURCE) {
+		new |= res->flags & PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+		/* Hmm, non-standard resource. */
+		printk("PCI: trying to set non-standard region %s/%d\n",
+		       dev->slot_name, resno);
+		return;
+	}
+
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+
+	if ((new ^ check) & mask) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resno,
+		       new, check);
+	}
+
+	if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
+	    (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+		new = 0; /* currently everyone zeros the high address */
+		pci_write_config_dword(dev, reg + 4, new);
+		pci_read_config_dword(dev, reg + 4, &check);
+		if (check != new) {
+			printk(KERN_ERR "PCI: Error updating region "
+			       "%s/%d (high %08x != %08x)\n",
+			       dev->slot_name, resno, new, check);
+		}
+	}
+}
+
 int __init
 pci_claim_resource(struct pci_dev *dev, int resource)
 {
@@ -55,84 +108,44 @@
 	return err;
 }
 
-/*
- * Given the PCI bus a device resides on, try to
- * find an acceptable resource allocation for a
- * specific device resource..
- */
-static int pci_assign_bus_resource(const struct pci_bus *bus,
-	struct pci_dev *dev,
-	struct resource *res,
-	unsigned long size,
-	unsigned long min,
-	unsigned int type_mask,
-	int resno)
+int pci_assign_resource(struct pci_dev *dev, int resno)
 {
-	unsigned long align;
-	int i;
-
-	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
-	for (i = 0 ; i < PCI_BUS_NUM_RESOURCES; i++) {
-		struct resource *r = bus->resource[i];
-		if (!r)
-			continue;
-
-		/* type_mask must match */
-		if ((res->flags ^ r->flags) & type_mask)
-			continue;
-
-		/* We cannot allocate a non-prefetching resource
-		   from a pre-fetching area */
-		if ((r->flags & IORESOURCE_PREFETCH) &&
-		    !(res->flags & IORESOURCE_PREFETCH))
-			continue;
-
-		/* The bridge resources are special, as their
-		   size != alignment. Sizing routines return
-		   required alignment in the "start" field. */
-		align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
-
-		/* Ok, try it out.. */
-		if (allocate_resource(r, res, size, min, -1, align,
-				      pcibios_align_resource, dev) < 0)
-			continue;
-
-		/* Update PCI config space.  */
-		pcibios_update_resource(dev, r, res, resno);
-		return 0;
-	}
-	return -EBUSY;
-}
-
-int 
-pci_assign_resource(struct pci_dev *dev, int i)
-{
-	const struct pci_bus *bus = dev->bus;
-	struct resource *res = dev->resource + i;
-	unsigned long size, min;
+	struct pci_bus *bus = dev->bus;
+	struct resource *res = dev->resource + resno;
+	unsigned long size, min, align;
+	int ret;
 
 	size = res->end - res->start + 1;
 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+	/* The bridge resources are special, as their
+	   size != alignment. Sizing routines return
+	   required alignment in the "start" field. */
+	align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
 
 	/* First, try exact prefetching match.. */
-	if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) {
+	ret = pci_bus_alloc_resource(bus, res, size, align, min,
+				     IORESOURCE_PREFETCH,
+				     pcibios_align_resource, dev);
+
+	if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
 		/*
 		 * That failed.
 		 *
 		 * But a prefetching area can handle a non-prefetching
 		 * window (it will just not perform as well).
 		 */
-		if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
-			printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
-			       i, res->start, res->end, dev->slot_name);
-			return -EBUSY;
-		}
+		ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
+					     pcibios_align_resource, dev);
 	}
 
-	DBGC((KERN_ERR "  got res[%lx:%lx] for resource %d of %s\n", res->start,
-						res->end, i, dev->dev.name));
+	if (ret) {
+		printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
+		       resno, res->start, res->end, dev->slot_name);
+	} else {
+		pci_update_resource(dev, res, resno);
+	}
 
-	return 0;
+	return ret;
 }
 
 /* Sort resources by alignment */
diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
--- a/drivers/pcmcia/hd64465_ss.c	Fri Feb 21 13:05:18 2003
+++ b/drivers/pcmcia/hd64465_ss.c	Tue Mar  4 22:35:34 2003
@@ -1070,8 +1070,8 @@
 	}
 
 /*	hd64465_io_debug = 0; */
-	platform_device_register(&hd64465_device);
 	hd64465_device.dev.class_data = &hd64465_data;
+	platform_device_register(&hd64465_device);
 
 	return 0;
 }
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/pcmcia/i82365.c	Tue Mar  4 22:35:34 2003
@@ -1628,11 +1628,11 @@
 	request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
 #endif
     
-    platform_device_register(&i82365_device);
-
     i82365_data.nsock = sockets;
     i82365_device.dev.class_data = &i82365_data;
     
+    platform_device_register(&i82365_device);
+
     /* Finally, schedule a polling interrupt */
     if (poll_interval != 0) {
 	poll_timer.function = pcic_interrupt_wrapper;
diff -Nru a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
--- a/drivers/pcmcia/sa1100_generic.c	Sun Mar  2 12:59:19 2003
+++ b/drivers/pcmcia/sa1100_generic.c	Thu Mar  6 08:48:29 2003
@@ -47,7 +47,6 @@
 #include <linux/notifier.h>
 #include <linux/proc_fs.h>
 #include <linux/version.h>
-#include <linux/cpufreq.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
--- a/drivers/pcmcia/tcic.c	Fri Feb 21 13:05:24 2003
+++ b/drivers/pcmcia/tcic.c	Tue Mar  4 22:35:34 2003
@@ -452,8 +452,6 @@
 	sockets++;
     }
 
-    platform_device_register(&tcic_device);
-
     switch (socket_table[0].id) {
     case TCIC_ID_DB86082:
 	printk("DB86082"); break;
@@ -526,6 +524,8 @@
 
     tcic_data.nsock = sockets;
     tcic_device.dev.class_data = &tcic_data;
+
+    platform_device_register(&tcic_device);
 
     return 0;
     
diff -Nru a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
--- a/drivers/pnp/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/drivers/pnp/Kconfig	Sun Mar  9 15:37:55 2003
@@ -30,15 +30,6 @@
 
 	  If unsure, say Y.
 
-config PNP_CARD
-	bool "Plug and Play card services"
-	depends on PNP
-	help
-	  Select Y if you want the PnP Layer to manage cards.  Cards are groups
-	  of PnP devices.  Some drivers, especially PnP sound card drivers, use
-	  these cards.  If you want to use the protocol ISAPNP you will need to
-	  say Y here.
-
 config PNP_DEBUG
 	bool "PnP Debug Messages"
 	depends on PNP
@@ -51,7 +42,7 @@
 
 config ISAPNP
 	bool "ISA Plug and Play support (EXPERIMENTAL)"
-	depends on PNP && EXPERIMENTAL && PNP_CARD
+	depends on PNP && EXPERIMENTAL
 	help
 	  Say Y here if you would like support for ISA Plug and Play devices.
 	  Some information is in <file:Documentation/isapnp.txt>.
diff -Nru a/drivers/pnp/Makefile b/drivers/pnp/Makefile
--- a/drivers/pnp/Makefile	Wed Feb 19 08:45:42 2003
+++ b/drivers/pnp/Makefile	Sun Mar  9 15:37:55 2003
@@ -2,9 +2,7 @@
 # Makefile for the Linux Plug-and-Play Support.
 #
 
-pnp-card-$(CONFIG_PNP_CARD) = card.o
-
-obj-y		:= core.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o $(pnp-card-y)
+obj-y		:= core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o
 
 obj-$(CONFIG_PNPBIOS)		+= pnpbios/
 obj-$(CONFIG_ISAPNP)		+= isapnp/
diff -Nru a/drivers/pnp/card.c b/drivers/pnp/card.c
--- a/drivers/pnp/card.c	Wed Feb 19 09:51:16 2003
+++ b/drivers/pnp/card.c	Sun Mar  9 15:44:14 2003
@@ -16,15 +16,14 @@
 #endif
 
 #include <linux/pnp.h>
-#include <linux/init.h>
 #include "base.h"
 
-
 LIST_HEAD(pnp_cards);
 
-static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp_card *card)
+
+static const struct pnp_card_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card)
 {
-	const struct pnp_card_id *drv_id = drv->id_table;
+	const struct pnp_card_id * drv_id = drv->id_table;
 	while (*drv_id->id){
 		if (compare_pnp_id(card->id,drv_id->id))
 			return drv_id;
@@ -33,31 +32,33 @@
 	return NULL;
 }
 
-static int card_bus_match(struct device *dev, struct device_driver *drv)
+static void generic_card_remove(struct pnp_dev * dev)
 {
-	struct pnp_card * card = to_pnp_card(dev);
-	struct pnpc_driver * pnp_drv = to_pnpc_driver(drv);
-	if (match_card(pnp_drv, card) == NULL)
-		return 0;
-	return 1;
+	dev->card_link = NULL;
 }
 
-struct bus_type pnpc_bus_type = {
-	.name	= "pnp_card",
-	.match	= card_bus_match,
-};
-
+static void generic_card_remove_first(struct pnp_dev * dev)
+{
+	struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver);
+	if (!dev->card || !drv)
+		return;
+	if (drv->remove)
+		drv->remove(dev->card_link);
+	drv->link.remove = &generic_card_remove;
+	kfree(dev->card_link);
+	generic_card_remove(dev);
+}
 
 /**
- * pnpc_add_id - adds an EISA id to the specified card
+ * pnp_add_card_id - adds an EISA id to the specified card
  * @id: pointer to a pnp_id structure
  * @card: pointer to the desired card
  *
  */
 
-int pnpc_add_id(struct pnp_id *id, struct pnp_card *card)
+int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card)
 {
-	struct pnp_id *ptr;
+	struct pnp_id * ptr;
 	if (!id)
 		return -EINVAL;
 	if (!card)
@@ -73,7 +74,7 @@
 	return 0;
 }
 
-static void pnpc_free_ids(struct pnp_card *card)
+static void pnp_free_card_ids(struct pnp_card * card)
 {
 	struct pnp_id * id;
 	struct pnp_id *next;
@@ -90,47 +91,51 @@
 static void pnp_release_card(struct device *dmdev)
 {
 	struct pnp_card * card = to_pnp_card(dmdev);
-	pnpc_free_ids(card);
+	pnp_free_card_ids(card);
 	kfree(card);
 }
 
 /**
- * pnpc_add_card - adds a PnP card to the PnP Layer
+ * pnp_add_card - adds a PnP card to the PnP Layer
  * @card: pointer to the card to add
  */
 
-int pnpc_add_card(struct pnp_card *card)
+int pnp_add_card(struct pnp_card * card)
 {
-	int error = 0;
+	int error;
+	struct list_head * pos;
 	if (!card || !card->protocol)
 		return -EINVAL;
+
 	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number);
-	INIT_LIST_HEAD(&card->rdevs);
 	card->dev.parent = &card->protocol->dev;
-	card->dev.bus = &pnpc_bus_type;
+	card->dev.bus = NULL;
 	card->dev.release = &pnp_release_card;
-	card->status = PNP_READY;
 	error = device_register(&card->dev);
-	if (error == 0){
-		struct list_head *pos;
+	if (error == 0) {
 		spin_lock(&pnp_lock);
 		list_add_tail(&card->global_list, &pnp_cards);
 		list_add_tail(&card->protocol_list, &card->protocol->cards);
 		spin_unlock(&pnp_lock);
+
+		/* we wait until now to add devices in order to ensure the drivers
+		 * will be able to use all of the related devices on the card
+		 * without waiting any unresonable length of time */
 		list_for_each(pos,&card->devices){
 			struct pnp_dev *dev = card_to_pnp_dev(pos);
 			__pnp_add_device(dev);
 		}
-	}
+	} else
+		pnp_err("sysfs failure, card '%s' will be unavailable", card->dev.bus_id);
 	return error;
 }
 
 /**
- * pnpc_remove_card - removes a PnP card from the PnP Layer
+ * pnp_remove_card - removes a PnP card from the PnP Layer
  * @card: pointer to the card to remove
  */
 
-void pnpc_remove_card(struct pnp_card *card)
+void pnp_remove_card(struct pnp_card * card)
 {
 	struct list_head *pos, *temp;
 	if (!card)
@@ -142,22 +147,24 @@
 	spin_unlock(&pnp_lock);
 	list_for_each_safe(pos,temp,&card->devices){
 		struct pnp_dev *dev = card_to_pnp_dev(pos);
-		pnpc_remove_device(dev);
+		pnp_remove_card_device(dev);
 	}
 }
 
 /**
- * pnpc_add_device - adds a device to the specified card
+ * pnp_add_card_device - adds a device to the specified card
  * @card: pointer to the card to add to
  * @dev: pointer to the device to add
  */
 
-int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev)
+int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev)
 {
-	if (!dev || !dev->protocol || !card)
+	if (!card || !dev || !dev->protocol)
 		return -EINVAL;
 	dev->dev.parent = &card->dev;
-	sprintf(dev->dev.bus_id, "%02x:%02x.%02x", dev->protocol->number, card->number,dev->number);
+	dev->card_link = NULL;
+	snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", dev->protocol->number,
+		 card->number,dev->number);
 	spin_lock(&pnp_lock);
 	dev->card = card;
 	list_add_tail(&dev->card_list, &card->devices);
@@ -166,12 +173,12 @@
 }
 
 /**
- * pnpc_remove_device- removes a device from the specified card
+ * pnp_remove_card_device- removes a device from the specified card
  * @card: pointer to the card to remove from
  * @dev: pointer to the device to remove
  */
 
-void pnpc_remove_device(struct pnp_dev *dev)
+void pnp_remove_card_device(struct pnp_dev * dev)
 {
 	spin_lock(&pnp_lock);
 	dev->card = NULL;
@@ -182,20 +189,21 @@
 
 /**
  * pnp_request_card_device - Searches for a PnP device under the specified card
- * @card: pointer to the card to search under, cannot be NULL
+ * @lcard: pointer to the card link, cannot be NULL
  * @id: pointer to a PnP ID structure that explains the rules for finding the device
  * @from: Starting place to search from. If NULL it will start from the begining.
- *
- * Will activate the device
  */
 
-struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from)
+struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from)
 {
-	struct list_head *pos;
-	struct pnp_dev *dev;
-	struct pnpc_driver *cdrv;
-	if (!card || !id)
+	struct list_head * pos;
+	struct pnp_dev * dev;
+	struct pnp_card_driver * drv;
+	struct pnp_card * card;
+	if (!clink || !id)
 		goto done;
+	card = clink->card;
+	drv = clink->driver;
 	if (!from) {
 		pos = card->devices.next;
 	} else {
@@ -205,7 +213,7 @@
 	}
 	while (pos != &card->devices) {
 		dev = card_to_pnp_dev(pos);
-		if (compare_pnp_id(dev->id,id))
+		if ((!dev->card_link) && compare_pnp_id(dev->id,id))
 			goto found;
 		pos = pos->next;
 	}
@@ -214,168 +222,93 @@
 	return NULL;
 
 found:
-	if (pnp_device_attach(dev) < 0)
-		return NULL;
-	cdrv = to_pnpc_driver(card->dev.driver);
-	if (dev->active == 0) {
-		if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) {
-			if(pnp_activate_dev(dev)<0) {
-				pnp_device_detach(dev);
-				return NULL;
-			}
+	down_write(&dev->dev.bus->subsys.rwsem);
+	dev->card_link = clink;
+	dev->dev.driver = &drv->link.driver;
+	if (drv->link.driver.probe) {
+		if (drv->link.driver.probe(&dev->dev)) {
+			dev->dev.driver = NULL;
+			return NULL;
 		}
-	} else {
-		if ((cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE))
-			pnp_disable_dev(dev);
 	}
-	spin_lock(&pnp_lock);
-	list_add_tail(&dev->rdev_list, &card->rdevs);
-	spin_unlock(&pnp_lock);
+	device_bind_driver(&dev->dev);
+	up_write(&dev->dev.bus->subsys.rwsem);
+
 	return dev;
 }
 
 /**
  * pnp_release_card_device - call this when the driver no longer needs the device
  * @dev: pointer to the PnP device stucture
- *
- * Will disable the device
  */
 
-void pnp_release_card_device(struct pnp_dev *dev)
-{
-	spin_lock(&pnp_lock);
-	list_del(&dev->rdev_list);
-	spin_unlock(&pnp_lock);
-	pnp_device_detach(dev);
-}
-
-static void pnpc_recover_devices(struct pnp_card *card)
-{
-	struct list_head *pos, *temp;
-	list_for_each_safe(pos,temp,&card->rdevs){
-		struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list);
-		pnp_release_card_device(dev);
-	}
-}
-
-int pnpc_attach(struct pnp_card *pnp_card)
-{
-	spin_lock(&pnp_lock);
-	if(pnp_card->status != PNP_READY){
-		spin_unlock(&pnp_lock);
-		return -EBUSY;
-	}
-	pnp_card->status = PNP_ATTACHED;
-	spin_unlock(&pnp_lock);
-	return 0;
-}
- 
-void pnpc_detach(struct pnp_card *pnp_card)
-{
-	spin_lock(&pnp_lock);
-	if (pnp_card->status == PNP_ATTACHED)
-		pnp_card->status = PNP_READY;
-	spin_unlock(&pnp_lock);
-	pnpc_recover_devices(pnp_card);
-}
-
-static int pnpc_card_probe(struct device *dev)
-{
-	int error = 0;
-	struct pnpc_driver *drv = to_pnpc_driver(dev->driver);
-	struct pnp_card *card = to_pnp_card(dev);
-	const struct pnp_card_id *card_id = NULL;
-
-	pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name);
-
-	error = pnpc_attach(card);
-	if (error < 0)
-		return error;
-	if (drv->probe) {
-		card_id = match_card(drv, card);
-		if (card_id != NULL)
-			error = drv->probe(card, card_id);
-		if (error >= 0){
-			card->driver = drv;
-			error = 0;
-		} else
-			pnpc_detach(card);
-	}
-	return error;
-}
-
-static int pnpc_card_remove(struct device *dev)
+void pnp_release_card_device(struct pnp_dev * dev)
 {
-	struct pnp_card * card = to_pnp_card(dev);
-	struct pnpc_driver * drv = card->driver;
-
-	if (drv) {
-		if (drv->remove)
-			drv->remove(card);
-		card->driver = NULL;
-	}
-	pnpc_detach(card);
-	return 0;
+	struct pnp_card_driver * drv = dev->card_link->driver;
+	if (!drv)
+		return;
+	down_write(&dev->dev.bus->subsys.rwsem);
+	drv->link.remove = &generic_card_remove;
+	device_release_driver(&dev->dev);
+	drv->link.remove = &generic_card_remove_first;
+	up_write(&dev->dev.bus->subsys.rwsem);
 }
 
 /**
- * pnpc_register_driver - registers a PnP card driver with the PnP Layer
- * @cdrv: pointer to the driver to register
+ * pnp_register_card_driver - registers a PnP card driver with the PnP Layer
+ * @drv: pointer to the driver to register
  */
 
-int pnpc_register_driver(struct pnpc_driver * drv)
+int pnp_register_card_driver(struct pnp_card_driver * drv)
 {
-	int count;
-	struct list_head *pos;
-
-	drv->driver.name = drv->name;
-	drv->driver.bus = &pnpc_bus_type;
-	drv->driver.probe = pnpc_card_probe;
-	drv->driver.remove = pnpc_card_remove;
-
-	pnp_dbg("the card driver '%s' has been registered", drv->name);
-
-	count = driver_register(&drv->driver);
+	int count = 0;
+	struct list_head *pos, *temp;
 
-	/* get the number of initial matches */
-	if (count >= 0){
-		count = 0;
-		list_for_each(pos,&drv->driver.devices){
-			count++;
+	drv->link.name = drv->name;
+	drv->link.id_table = NULL;	/* this will disable auto matching */
+	drv->link.flags = drv->flags;
+	drv->link.probe = NULL;
+	drv->link.remove = &generic_card_remove_first;
+
+	pnp_register_driver(&drv->link);
+
+	list_for_each_safe(pos,temp,&pnp_cards){
+		struct pnp_card *card = list_entry(pos, struct pnp_card, global_list);
+		const struct pnp_card_id *id = match_card(drv,card);
+		if (id) {
+			struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link));
+			if (!clink)
+				continue;
+			clink->card = card;
+			clink->driver = drv;
+			if (drv->probe) {
+				if (drv->probe(clink, id)>=0)
+					count++;
+			} else
+				count++;
 		}
 	}
 	return count;
 }
 
 /**
- * pnpc_unregister_driver - unregisters a PnP card driver from the PnP Layer
- * @cdrv: pointer to the driver to unregister
- *
- * Automatically disables requested devices
+ * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer
+ * @drv: pointer to the driver to unregister
  */
 
-void pnpc_unregister_driver(struct pnpc_driver *drv)
+void pnp_unregister_card_driver(struct pnp_card_driver * drv)
 {
-	driver_unregister(&drv->driver);
-	pnp_dbg("the card driver '%s' has been unregistered", drv->name);
-}
+	pnp_unregister_driver(&drv->link);
 
-static int __init pnp_card_init(void)
-{
-	printk(KERN_INFO "pnp: Enabling Plug and Play Card Services.\n");
-	return bus_register(&pnpc_bus_type);
+	pnp_dbg("the card driver '%s' has been unregistered", drv->name);
 }
 
-subsys_initcall(pnp_card_init);
-
-EXPORT_SYMBOL(pnpc_add_card);
-EXPORT_SYMBOL(pnpc_remove_card);
-EXPORT_SYMBOL(pnpc_add_device);
-EXPORT_SYMBOL(pnpc_remove_device);
+EXPORT_SYMBOL(pnp_add_card);
+EXPORT_SYMBOL(pnp_remove_card);
+EXPORT_SYMBOL(pnp_add_card_device);
+EXPORT_SYMBOL(pnp_remove_card_device);
+EXPORT_SYMBOL(pnp_add_card_id);
 EXPORT_SYMBOL(pnp_request_card_device);
 EXPORT_SYMBOL(pnp_release_card_device);
-EXPORT_SYMBOL(pnpc_register_driver);
-EXPORT_SYMBOL(pnpc_unregister_driver);
-EXPORT_SYMBOL(pnpc_add_id);
-EXPORT_SYMBOL(pnpc_attach);
-EXPORT_SYMBOL(pnpc_detach);
+EXPORT_SYMBOL(pnp_register_card_driver);
+EXPORT_SYMBOL(pnp_unregister_card_driver);
diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c
--- a/drivers/pnp/driver.c	Wed Feb 19 09:54:46 2003
+++ b/drivers/pnp/driver.c	Sun Mar  9 15:44:14 2003
@@ -53,12 +53,11 @@
 static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev)
 {
 	const struct pnp_device_id *drv_id = drv->id_table;
-	if (!drv)
+	if (!drv_id)
 		return NULL;
-	if (!dev)
-		return NULL;
-	while (*drv_id->id){
-		if (compare_pnp_id(dev->id,drv_id->id))
+
+	while (*drv_id->id) {
+		if (compare_pnp_id(dev->id, drv_id->id))
 			return drv_id;
 		drv_id++;
 	}
@@ -102,14 +101,19 @@
 		return error;
 
 	if (pnp_dev->active == 0) {
-		if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) {
+		if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
 			error = pnp_activate_dev(pnp_dev);
 			if (error < 0)
 				return error;
 		}
+	} else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE)
+		    == PNP_DRIVER_RES_DISABLE) {
+		error = pnp_disable_dev(pnp_dev);
+		if (error < 0)
+			return error;
 	}
 	error = 0;
-	if (pnp_drv->probe && pnp_dev->active) {
+	if (pnp_drv->probe) {
 		dev_id = match_device(pnp_drv, pnp_dev);
 		if (dev_id != NULL)
 			error = pnp_drv->probe(pnp_dev, dev_id);
@@ -117,9 +121,8 @@
 	if (error >= 0){
 		pnp_dev->driver = pnp_drv;
 		error = 0;
-	}
-	else
-	goto fail;
+	} else
+		goto fail;
 	return error;
 
 fail:
diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- a/drivers/pnp/interface.c	Tue Mar  4 09:12:57 2003
+++ b/drivers/pnp/interface.c	Sun Mar  9 15:17:52 2003
@@ -332,11 +332,18 @@
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
 
+	pnp_printf(buffer,"mode = ");
+	if (dev->config_mode & PNP_CONFIG_MANUAL)
+		pnp_printf(buffer,"manual\n");
+	else
+		pnp_printf(buffer,"auto\n");
+
 	pnp_printf(buffer,"state = ");
 	if (dev->active)
 		pnp_printf(buffer,"active\n");
 	else
 		pnp_printf(buffer,"disabled\n");
+
 	for (i = 0; i < PNP_MAX_PORT; i++) {
 		if (pnp_port_valid(dev, i)) {
 			pnp_printf(buffer,"io");
@@ -402,13 +409,13 @@
 		retval = pnp_activate_dev(dev);
 		goto done;
 	}
-	if (!strnicmp(buf,"auto-config",11)) {
+	if (!strnicmp(buf,"auto",4)) {
 		if (dev->active)
 			goto done;
 		retval = pnp_auto_config_dev(dev);
 		goto done;
 	}
-	if (!strnicmp(buf,"clear-config",12)) {
+	if (!strnicmp(buf,"clear",5)) {
 		if (dev->active)
 			goto done;
 		spin_lock(&pnp_lock);
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	Wed Feb 19 09:54:46 2003
+++ b/drivers/pnp/isapnp/core.c	Sun Mar  9 15:37:55 2003
@@ -626,7 +626,7 @@
 		isapnp_peek(name, size1);
 		name[size1] = '\0';
 		*size -= size1;
-		
+
 		/* clean whitespace from end of string */
 		while (size1 > 0  &&  name[--size1] == ' ')
 			name[size1] = '\0';
@@ -647,7 +647,7 @@
 		return 1;
 	if (pnp_build_resource(dev, 0) == NULL)
 		return 1;
-	pnpc_add_device(card,dev);
+	pnp_add_card_device(card,dev);
 	while (1) {
 		if (isapnp_read_tag(&type, &size)<0)
 			return 1;
@@ -659,7 +659,7 @@
 				if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 					return 1;
 				pnp_build_resource(dev,0);
-				pnpc_add_device(card,dev);
+				pnp_add_card_device(card,dev);
 				size = 0;
 				skip = 0;
 			} else {
@@ -852,7 +852,7 @@
 			device & 0x0f,
 			(device >> 12) & 0x0f,
 			(device >> 8) & 0x0f);
-	pnpc_add_id(id,card);
+	pnp_add_card_id(id,card);
 }
 
 
@@ -962,7 +962,7 @@
 			isapnp_parse_current_resources(dev, &dev->res);
 		}
 
-		pnpc_add_card(card);
+		pnp_add_card(card);
 	}
 	isapnp_wait();
 	return 0;
diff -Nru a/drivers/pnp/manager.c b/drivers/pnp/manager.c
--- a/drivers/pnp/manager.c	Sat Feb 22 13:40:31 2003
+++ b/drivers/pnp/manager.c	Thu Mar  6 13:50:22 2003
@@ -532,6 +532,39 @@
 	return error;
 }
 
+static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab)
+{
+	int idx;
+	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
+		if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->irq_resource[idx].start = ntab->irq_resource[idx].start;
+		ctab->irq_resource[idx].end = ntab->irq_resource[idx].end;
+		ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags;
+	}
+	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
+		if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->dma_resource[idx].start = ntab->dma_resource[idx].start;
+		ctab->dma_resource[idx].end = ntab->dma_resource[idx].end;
+		ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags;
+	}
+	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
+		if (ntab->port_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->port_resource[idx].start = ntab->port_resource[idx].start;
+		ctab->port_resource[idx].end = ntab->port_resource[idx].end;
+		ctab->port_resource[idx].flags = ntab->port_resource[idx].flags;
+	}
+	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
+		if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->irq_resource[idx].start = ntab->mem_resource[idx].start;
+		ctab->irq_resource[idx].end = ntab->mem_resource[idx].end;
+		ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags;
+	}
+}
+
 /**
  * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
  * @dev: pointer to the desired device
@@ -554,7 +587,7 @@
 	*bak = dev->res;
 
 	spin_lock(&pnp_lock);
-	dev->res = *res;
+	pnp_process_manual_resources(&dev->res, res);
 	if (!(mode & PNP_CONFIG_FORCE)) {
 		for (i = 0; i < PNP_MAX_PORT; i++) {
 			if(pnp_check_port(dev,i))
@@ -681,7 +714,7 @@
 		return -1;
 	}
 	dev->active = 0; /* just in case the protocol doesn't do this */
-	pnp_dbg("the device '%s' has been disabled.", dev->dev.bus_id);
+	pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id);
 	return 0;
 }
 
diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c
--- a/drivers/pnp/resource.c	Sat Feb 22 13:40:31 2003
+++ b/drivers/pnp/resource.c	Thu Mar  6 13:50:22 2003
@@ -558,25 +558,25 @@
 		table->irq_resource[idx].name = NULL;
 		table->irq_resource[idx].start = -1;
 		table->irq_resource[idx].end = -1;
-		table->irq_resource[idx].flags = 0;
+		table->irq_resource[idx].flags = IORESOURCE_AUTO;
 	}
 	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
 		table->dma_resource[idx].name = NULL;
 		table->dma_resource[idx].start = -1;
 		table->dma_resource[idx].end = -1;
-		table->dma_resource[idx].flags = 0;
+		table->dma_resource[idx].flags = IORESOURCE_AUTO;
 	}
 	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
 		table->port_resource[idx].name = NULL;
 		table->port_resource[idx].start = 0;
 		table->port_resource[idx].end = 0;
-		table->port_resource[idx].flags = 0;
+		table->port_resource[idx].flags = IORESOURCE_AUTO;
 	}
 	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
 		table->mem_resource[idx].name = NULL;
 		table->mem_resource[idx].start = 0;
 		table->mem_resource[idx].end = 0;
-		table->mem_resource[idx].flags = 0;
+		table->mem_resource[idx].flags = IORESOURCE_AUTO;
 	}
 }
 
diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c
--- a/drivers/pnp/system.c	Wed Feb 19 09:54:46 2003
+++ b/drivers/pnp/system.c	Sun Mar  9 15:44:14 2003
@@ -93,8 +93,8 @@
 
 static struct pnp_driver system_pnp_driver = {
 	.name		= "system",
-	.flags		= PNP_DRIVER_DO_NOT_ACTIVATE, 
 	.id_table	= pnp_dev_table,
+	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
 	.probe		= system_pnp_probe,
 	.remove		= NULL,
 };
diff -Nru a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
--- a/drivers/s390/block/dasd_3990_erp.c	Mon Feb 24 10:29:29 2003
+++ b/drivers/s390/block/dasd_3990_erp.c	Thu Mar  6 09:25:58 2003
@@ -2445,7 +2445,7 @@
  *     - exit with permanent error
  *
  * PARAMETER
- *   erp		ERP which is in progress wiht no retry left
+ *   erp		ERP which is in progress with no retry left
  *
  * RETURN VALUES
  *   erp		modified/additional ERP
diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
--- a/drivers/s390/block/dasd_genhd.c	Fri Dec  6 11:37:54 2002
+++ b/drivers/s390/block/dasd_genhd.c	Sat Mar  8 14:50:22 2003
@@ -60,11 +60,8 @@
 	}
 
 	/* Register block device. */
-	new_major = register_blkdev(major, "dasd", &dasd_device_operations);
+	new_major = register_blkdev(major, "dasd");
 	if (new_major < 0) {
-		MESSAGE(KERN_WARNING,
-			"Cannot register to major no %d, rc = %d",
-			major, new_major);
 		kfree(mi);
 		return new_major;
 	}
diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
--- a/drivers/s390/block/xpram.c	Tue Dec  3 09:21:05 2002
+++ b/drivers/s390/block/xpram.c	Sat Mar  8 14:50:22 2003
@@ -430,13 +430,11 @@
 	/*
 	 * Register xpram major.
 	 */
-	rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops);
-	if (rc < 0) {
-		PRINT_ERR("Can't get xpram major %d\n", XPRAM_MAJOR);
+	rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME);
+	if (rc < 0)
 		goto out;
-	}
 
-	devfs_mk_dir (NULL, "slram", NULL);
+	devfs_mk_dir(NULL, "slram", NULL);
 
 	/*
 	 * Assign the other needed values: make request function, sizes and
@@ -452,6 +450,7 @@
 	for (i = 0; i < xpram_devs; i++) {
 		struct gendisk *disk = xpram_disks[i];
 		char name[16];
+
 		xpram_devices[i].size = xpram_sizes[i] / 4;
 		xpram_devices[i].offset = offset;
 		offset += xpram_devices[i].size;
diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
--- a/drivers/s390/char/con3215.c	Tue Feb 25 10:27:52 2003
+++ b/drivers/s390/char/con3215.c	Thu Mar  6 09:25:58 2003
@@ -862,7 +862,7 @@
 	spin_unlock_irqrestore(raw->lock, flags);
 }
 
-static int __init
+static int __init 
 con3215_consetup(struct console *co, char *options)
 {
 	return 0;
@@ -884,7 +884,7 @@
  * 3215 console initialization code called from console_init().
  * NOTE: This is called before kmalloc is available.
  */
-void __init
+static void __init
 con3215_init(void)
 {
 	struct ccw_device *cdev;
@@ -1122,6 +1122,7 @@
 		spin_unlock_irqrestore(raw->lock, flags);
 	}
 }
+console_initcall(con3215_init);
 
 /*
  * Disable writing to a 3215 tty
diff -Nru a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
--- a/drivers/s390/char/sclp_con.c	Thu Dec 12 10:03:31 2002
+++ b/drivers/s390/char/sclp_con.c	Fri Feb 14 15:23:21 2003
@@ -237,3 +237,5 @@
 	/* enable printk-access to this driver */
 	register_console(&sclp_console);
 }
+
+console_initcall(sclp_console_init);
diff -Nru a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
--- a/drivers/s390/char/sclp_tty.c	Thu Feb  6 07:33:47 2003
+++ b/drivers/s390/char/sclp_tty.c	Fri Feb 14 15:23:21 2003
@@ -797,3 +797,6 @@
 	if (tty_register_driver(&sclp_tty_driver))
 		panic("Couldn't register sclp_tty driver\n");
 }
+
+console_initcall(sclp_tty_init);
+
diff -Nru a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
--- a/drivers/s390/char/tape_block.c	Fri Dec  6 16:20:07 2002
+++ b/drivers/s390/char/tape_block.c	Sat Mar  8 14:50:22 2003
@@ -333,12 +333,10 @@
 	int rc;
 
 	/* Register the tape major number to the kernel */
-	rc = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);
-	if (rc < 0) {
-		PRINT_ERR("can't get major %d for block device\n",
-			  tapeblock_major);
+	rc = register_blkdev(tapeblock_major, "tBLK");
+	if (rc < 0)
 		return rc;
-	}
+
 	if (tapeblock_major == 0)
 		tapeblock_major = rc;
 	PRINT_INFO("tape gets major %d for block device\n", tapeblock_major);
diff -Nru a/drivers/s390/char/tuball.c b/drivers/s390/char/tuball.c
--- a/drivers/s390/char/tuball.c	Wed Oct  9 07:01:46 2002
+++ b/drivers/s390/char/tuball.c	Fri Feb 14 15:24:00 2003
@@ -131,7 +131,7 @@
 #else
 #define tub3270_con_devno console_device
 
-void __init tub3270_con_init(void)
+static void __init tub3270_con_init(void)
 {
 	tub3270_con_bcb.bc_len = 65536;
 	if (!CONSOLE_IS_3270)
@@ -140,6 +140,8 @@
 		tub3270_con_bcb.bc_len);
 	register_console(&tub3270_con);
 }
+console_initcall(tub3270_con_init);
+
 #endif
 
 static kdev_t
diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
--- a/drivers/sbus/char/jsflash.c	Mon Oct 28 11:57:56 2002
+++ b/drivers/sbus/char/jsflash.c	Sat Mar  8 14:50:22 2003
@@ -570,9 +570,7 @@
 		jsfd_disk[i] = disk;
 	}
 
-	if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) {
-		printk("jsfd_init: unable to get major number %d\n",
-		    JSFD_MAJOR);
+	if (register_blkdev(JSFD_MAJOR, "jsfd")) {
 		err = -EIO;
 		goto out;
 	}
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	Tue Feb 18 01:04:49 2003
+++ b/drivers/scsi/Kconfig	Wed Mar  5 23:02:07 2003
@@ -946,16 +946,6 @@
 	  Please read <file:drivers/scsi/sym53c8xx_2/Documentation.txt> for more
 	  information.
 
-config SCSI_ZALON
-	tristate "Zalon SCSI support"
-	depends on GSC && SCSI
-	help
-	  The Zalon is a GSC/HSC bus interface chip that sits between the
-	  PA-RISC processor and the NCR 53c720 SCSI controller on C100,
-	  C110, J200, J210 and some D, K & R-class machines.  It's also
-	  used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
-	  Say Y here if you have one of these machines or cards.
-
 config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
 	int "DMA addressing mode"
 	depends on SCSI_SYM53C8XX_2
@@ -1010,9 +1000,19 @@
 	  If you say Y here, the driver will preferently use normal IO rather than 
 	  memory mapped IO.
 
+config SCSI_ZALON
+	tristate "Zalon SCSI support"
+	depends on GSC && SCSI
+	help
+	  The Zalon is a GSC/HSC bus interface chip that sits between the
+	  PA-RISC processor and the NCR 53c720 SCSI controller on C100,
+	  C110, J200, J210 and some D, K & R-class machines.  It's also
+	  used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
+	  Say Y here if you have one of these machines or cards.
+
 config SCSI_NCR53C8XX
 	tristate "NCR53C8XX SCSI support"
-	depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI
+	depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI_ZALON!=y && SCSI
 	---help---
 	  This is the BSD ncr driver adapted to Linux for the NCR53C8XX family
 	  of PCI-SCSI controllers.  This driver supports parity checking,
diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c	Mon Feb 24 13:03:30 2003
+++ b/drivers/scsi/aacraid/linit.c	Fri Mar 14 00:04:51 2003
@@ -679,27 +679,26 @@
  */
  
 static Scsi_Host_Template driver_template = {
-	module:			THIS_MODULE,
-	name:           	"AAC",
-	proc_info:      	aac_procinfo,
-	detect:         	aac_detect,
-	release:        	aac_release,
-	info:           	aac_driverinfo,
-	ioctl:          	aac_ioctl,
-	queuecommand:   	aac_queuecommand,
-	bios_param:     	aac_biosparm,	
-	slave_configure:	aac_slave_configure,
-	can_queue:      	AAC_NUM_IO_FIB,	
-	this_id:        	16,
-	sg_tablesize:   	16,
-	max_sectors:    	128,
-	cmd_per_lun:    	AAC_NUM_IO_FIB,
-	eh_abort_handler:       aac_eh_abort,
-	eh_device_reset_handler:aac_eh_device_reset,
-	eh_bus_reset_handler:	aac_eh_bus_reset,
-	eh_host_reset_handler:	aac_eh_reset,
-
-	use_clustering:		ENABLE_CLUSTERING,
+	.module				= THIS_MODULE,
+	.name           		= "AAC",
+	.proc_info      		= aac_procinfo,
+	.detect         		= aac_detect,
+	.release        		= aac_release,
+	.info           		= aac_driverinfo,
+	.ioctl          		= aac_ioctl,
+	.queuecommand   		= aac_queuecommand,
+	.bios_param     		= aac_biosparm,	
+	.slave_configure		= aac_slave_configure,
+	.can_queue      		= AAC_NUM_IO_FIB,	
+	.this_id        		= 16,
+	.sg_tablesize   		= 16,
+	.max_sectors    		= 128,
+	.cmd_per_lun    		= 1,
+	.eh_abort_handler       	= aac_eh_abort,
+	.eh_device_reset_handler 	= aac_eh_device_reset,
+	.eh_bus_reset_handler		= aac_eh_bus_reset,
+	.eh_host_reset_handler		= aac_eh_reset,
+	.use_clustering			= ENABLE_CLUSTERING,
 };
 
 #include "scsi_module.c"
diff -Nru a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
--- a/drivers/scsi/aic7xxx/aicasm/Makefile	Tue Dec 10 11:02:52 2002
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile	Thu Feb 20 08:39:57 2003
@@ -10,9 +10,10 @@
 GENSRCS=	$(YSRCS:.y=.c) $(LSRCS:.l=.c)
 
 SRCS=	${CSRCS} ${GENSRCS}
+LIBS=	-ldb
 CLEANFILES= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output)
 # Override default kernel CFLAGS.  This is a userland app.
-AICASM_CFLAGS:= -I/usr/include -I. -ldb
+AICASM_CFLAGS:= -I/usr/include -I.
 YFLAGS= -d
 
 NOMAN=	noman
@@ -30,7 +31,7 @@
 endif
 
 $(PROG):  ${GENHDRS} $(SRCS)
-	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG)
+	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
 
 aicdb.h:
 	@if [ -e "/usr/include/db3/db_185.h" ]; then		\
@@ -45,8 +46,9 @@
 		echo "*** Install db development libraries";	\
 	 fi
 
+clean-files := $(CLEANFILES) $(PROG)
 clean:
-	rm -f $(CLEANFILES) $(PROG)
+	rm -f $(clean-files)
 
 aicasm_gram.c aicasm_gram.h: aicasm_gram.y
 	$(YACC) $(YFLAGS) -b $(<:.y=) $<
diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
--- a/drivers/scsi/fdomain.c	Thu Feb 20 04:16:32 2003
+++ b/drivers/scsi/fdomain.c	Thu Feb 27 09:39:04 2003
@@ -271,13 +271,8 @@
 
  **************************************************************************/
 
+#include <linux/config.h>
 #include <linux/module.h>
-
-#ifdef PCMCIA
-#undef MODULE
-#endif
-
-#include <linux/config.h>	/* for CONFIG_PCI */
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/blk.h>
@@ -295,9 +290,13 @@
 
 #include "scsi.h"
 #include "hosts.h"
-#include "fdomain.h"
+
+MODULE_AUTHOR("Rickard E. Faith");
+MODULE_DESCRIPTION("Future domain SCSI driver");
+MODULE_LICENSE("GPL");
+
   
-#define VERSION          "$Revision: 5.50 $"
+#define VERSION          "$Revision: 5.51 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -421,15 +420,12 @@
 
 static void              do_fdomain_16x0_intr( int irq, void *dev_id,
 					    struct pt_regs * regs );
+int		 	fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
 
-#ifdef MODULE
-				/* Allow insmod parameters to be like LILO
-                                   parameters.  For example:
-				   insmod fdomain fdomain=0x140,11
-				*/
+/* Allow insmod parameters to be like LILO parameters.  For example:
+   insmod fdomain fdomain=0x140,11 */
 static char * fdomain = NULL;
 MODULE_PARM(fdomain, "s");
-#endif
 
 static unsigned long addresses[] = {
    0xc8000,
@@ -561,7 +557,7 @@
    printk( "\n" );
 }
 
-static int __init fdomain_setup(char *str)
+int __init fdomain_setup(char *str)
 {
 	int ints[4];
 
@@ -862,7 +858,7 @@
 }
 #endif
 
-static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
 {
    int              retcode;
    struct Scsi_Host *shpnt;
@@ -879,13 +875,6 @@
    unsigned char    buf[buflen];
 #endif
 
-   tpnt->proc_name = "fdomain";
-
-#ifdef MODULE
-	if (fdomain)
-		fdomain_setup(fdomain);
-#endif
-   
    if (setup_called) {
 #if DEBUG_DETECT
       printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
@@ -895,7 +884,7 @@
 	 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
 		 port_base );
 	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
-	 return 0;
+	 return NULL;
       }
    } else {
       int flag = 0;
@@ -910,7 +899,7 @@
 
 	 if (!flag) {
 	    printk( "scsi: <fdomain> Detection failed (no card)\n" );
-	    return 0;
+	    return NULL;
 	 }
       }
    }
@@ -936,7 +925,7 @@
       if (setup_called) {
 	 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
       }
-      return 0;
+      return NULL;
    }
 
    if (this_id) {
@@ -957,7 +946,7 @@
 
    shpnt = scsi_register( tpnt, 0 );
    if(shpnt == NULL)
-   	return 0;
+   	return NULL;
    shpnt->irq = interrupt_level;
    shpnt->io_port = port_base;
    scsi_set_device(shpnt, &pdev->dev);
@@ -967,7 +956,7 @@
    /* Log IRQ with kernel */   
    if (!interrupt_level) {
       printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
-      return 0;
+      return NULL;
    } else {
       /* Register the IRQ with the kernel */
 
@@ -988,7 +977,7 @@
 	    printk(KERN_ERR "                Send mail to faith@acm.org\n" );
 	 }
 	 printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
-	 return 0;
+	 return NULL;
       }
    }
 
@@ -1048,7 +1037,14 @@
    }
 #endif
 
-   return 1;			/* Maximum of one adapter will be detected. */
+   return shpnt;
+}
+
+static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+{
+	if (fdomain)
+		fdomain_setup(fdomain);
+	return (__fdomain_16x0_detect(tpnt) != NULL);
 }
 
 static const char *fdomain_16x0_info( struct Scsi_Host *ignore )
@@ -1150,8 +1146,9 @@
 {
    int           status;
    unsigned long timeout;
+#if ERRORS_ONLY
    static int    flag = 0;
-
+#endif
 
    outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
    outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
@@ -1574,6 +1571,7 @@
 
 /* End of code derived from Tommy Thorn's work. */
 
+#if DEBUG_ABORT
 static void print_info(Scsi_Cmnd *SCpnt)
 {
    unsigned int imr;
@@ -1643,6 +1641,7 @@
 	 printk( "Configuration 2  = 0x%02x\n",
 		 inb( port_base + Configuration2 ) );
 }
+#endif
 
 static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
 {
@@ -1670,7 +1669,7 @@
    return SUCCESS;
 }
 
-static int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
+int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
 {
    outb( 1, SCSI_Cntl_port );
    do_pause( 2 );
@@ -1866,9 +1865,29 @@
 	return 0;
 }
 
-MODULE_LICENSE("GPL");
-
-/* Eventually this will go into an include file, but this will be later */
-static Scsi_Host_Template driver_template = FDOMAIN_16X0;
+Scsi_Host_Template fdomain_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "fdomain",
+	.proc_name		= "fdomain",
+	.proc_info		= fdomain_16x0_proc_info,
+	.detect			= fdomain_16x0_detect,
+	.info			= fdomain_16x0_info,
+	.command		= fdomain_16x0_command,
+	.queuecommand		= fdomain_16x0_queue,
+	.eh_abort_handler	= fdomain_16x0_abort,
+	.eh_bus_reset_handler	= fdomain_16x0_bus_reset,
+	.eh_device_reset_handler = fdomain_16x0_device_reset,
+	.eh_host_reset_handler	= fdomain_16x0_host_reset,
+	.bios_param		= fdomain_16x0_biosparam,
+	.release		= fdomain_16x0_release,
+	.can_queue		= 1,
+	.this_id		= 6,
+	.sg_tablesize		= 64,
+	.cmd_per_lun		= 1,
+	.use_clustering		= DISABLE_CLUSTERING,
+};
 
+#ifndef PCMCIA
+#define driver_template fdomain_driver_template
 #include "scsi_module.c"
+#endif
diff -Nru a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h
--- a/drivers/scsi/fdomain.h	Tue Dec 10 12:28:33 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,59 +0,0 @@
-/* fdomain.h -- Header for Future Domain TMC-16x0 driver
- * Created: Sun May  3 18:47:33 1992 by faith@cs.unc.edu
- * Revised: Thu Oct 12 13:21:35 1995 by faith@acm.org
- * Author: Rickard E. Faith, faith@cs.unc.edu
- * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith
- *
- * $Id: fdomain.h,v 5.12 1995/10/12 19:01:09 root Exp $
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
-
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#ifndef _FDOMAIN_H
-#define _FDOMAIN_H
-
-static int        fdomain_16x0_detect( Scsi_Host_Template *);
-static int        fdomain_16x0_command( Scsi_Cmnd *);
-static int        fdomain_16x0_abort(Scsi_Cmnd *);
-static const char *fdomain_16x0_info(struct Scsi_Host *);
-static int        fdomain_16x0_bus_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_host_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_device_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int        fdomain_16x0_biosparam(struct scsi_device *,
-		struct block_device *, sector_t, int * );
-static int        fdomain_16x0_proc_info(char *buffer, char **start, off_t offset,
-				   int length, int hostno, int inout );
-static int        fdomain_16x0_release(struct Scsi_Host *shpnt);
-
-#define FDOMAIN_16X0 { .proc_info      		= fdomain_16x0_proc_info,           \
-		       .detect         		= fdomain_16x0_detect,              \
-		       .info           		= fdomain_16x0_info,                \
-		       .command        		= fdomain_16x0_command,             \
-		       .queuecommand   		= fdomain_16x0_queue,               \
-		       .eh_abort_handler	= fdomain_16x0_abort,               \
-		       .eh_bus_reset_handler	= fdomain_16x0_bus_reset,           \
-		       .eh_device_reset_handler	= fdomain_16x0_device_reset,        \
-		       .eh_host_reset_handler	= fdomain_16x0_host_reset,          \
-		       .bios_param		= fdomain_16x0_biosparam,           \
-		       .release			= fdomain_16x0_release,		  \
-		       .can_queue		= 1, 				  \
-		       .this_id  		= 6, 				  \
-		       .sg_tablesize		= 64, 				  \
-		       .cmd_per_lun		= 1, 				  \
-		       .use_clustering		= DISABLE_CLUSTERING		  \
-}
-#endif
diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
--- a/drivers/scsi/hosts.h	Fri Feb 21 16:41:13 2003
+++ b/drivers/scsi/hosts.h	Mon Mar  3 10:48:16 2003
@@ -549,6 +549,7 @@
     void (*detach)(Scsi_Device *);
     int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. 
                                            Selects command for blkdevs */
+    void (*rescan)(Scsi_Device *);
     struct device_driver scsi_driverfs_driver;
 };
 
diff -Nru a/drivers/scsi/i91uscsi.h b/drivers/scsi/i91uscsi.h
--- a/drivers/scsi/i91uscsi.h	Mon Feb  4 23:52:37 2002
+++ b/drivers/scsi/i91uscsi.h	Sun Feb 16 16:20:08 2003
@@ -70,12 +70,6 @@
 #ifndef NULL
 #define NULL     0		/* zero          */
 #endif
-#ifndef TRUE
-#define TRUE     (1)		/* boolean true  */
-#endif
-#ifndef FALSE
-#define FALSE    (0)		/* boolean false */
-#endif
 #ifndef FAILURE
 #define FAILURE  (-1)
 #endif
@@ -597,11 +591,9 @@
 	TCS HCS_Tcs[MAX_TARGETS];	/* 78 */
 	ULONG pSRB_head;	/* SRB save queue header     */
 	ULONG pSRB_tail;	/* SRB save queue tail       */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spinlock_t HCS_AvailLock;
 	spinlock_t HCS_SemaphLock;
 	spinlock_t pSRB_lock;	/* SRB queue lock            */
-#endif
 } HCS;
 
 /* Bit Definition for HCB_Config */
diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c
--- a/drivers/scsi/imm.c	Mon Feb 17 17:02:24 2003
+++ b/drivers/scsi/imm.c	Thu Mar  6 15:50:31 2003
@@ -174,6 +174,7 @@
 	    parport_unregister_device(imm_hosts[i].dev);
 	    continue;
 	}
+
 	/* now the glue ... */
 	switch (imm_hosts[i].mode) {
 	case IMM_NIBBLE:
@@ -218,7 +219,7 @@
 
 /* This is to give the imm driver a way to modify the timings (and other
  * parameters) by writing to the /proc/scsi/imm/0 file.
- * Very simple method really... (To simple, no error checking :( )
+ * Very simple method really... (Too simple, no error checking :( )
  * Reason: Kernel hackers HATE having to unload and reload modules for
  * testing...
  * Also gives a method to use a script to obtain optimum timings (TODO)
@@ -948,7 +949,7 @@
     unsigned char l = 0, h = 0;
     int retv, x;
 
-    /* First check for any errors that may of occurred
+    /* First check for any errors that may have occurred
      * Here we check for internal errors
      */
     if (tmp->failed)
diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c
--- a/drivers/scsi/inia100.c	Fri Jan  3 10:58:49 2003
+++ b/drivers/scsi/inia100.c	Sun Feb 16 16:18:17 2003
@@ -67,12 +67,6 @@
  *          - Fix allocation of scsi host structs and private data
  **************************************************************************/
 
-#define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
 #include <linux/module.h>
 
 #include <linux/errno.h>
diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h
--- a/drivers/scsi/inia100.h	Tue Dec 10 12:28:32 2002
+++ b/drivers/scsi/inia100.h	Sun Feb 16 16:18:17 2003
@@ -63,14 +63,6 @@
  *		   merged them into a single header used by both .c files.
  ****************************************************************************/
 
-#ifndef	CVT_LINUX_VERSION
-#define	CVT_LINUX_VERSION(V,P,S)	(((V) * 65536) + ((P) * 256) + (S))
-#endif
-
-#ifndef	LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -116,12 +108,6 @@
 
 #ifndef NULL
 #define NULL     0		/* zero          */
-#endif
-#ifndef TRUE
-#define TRUE     (1)		/* boolean true  */
-#endif
-#ifndef FALSE
-#define FALSE    (0)		/* boolean false */
 #endif
 #ifndef FAILURE
 #define FAILURE  (-1)
diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
--- a/drivers/scsi/ncr53c8xx.c	Tue Feb 25 02:46:22 2003
+++ b/drivers/scsi/ncr53c8xx.c	Wed Mar  5 23:02:17 2003
@@ -5024,7 +5024,6 @@
 **==========================================================
 */
 
-#ifdef MODULE
 static int ncr_detach(ncb_p np)
 {
 	ccb_p cp;
@@ -5160,7 +5159,6 @@
 
 	return 1;
 }
-#endif
 
 /*==========================================================
 **
@@ -8935,7 +8933,6 @@
 }
 
 
-#ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *host)
 {
 #ifdef DEBUG_NCR53C8XX
@@ -8945,7 +8942,6 @@
 
      return 1;
 }
-#endif
 
 
 /*
diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
--- a/drivers/scsi/ncr53c8xx.h	Tue Dec 10 12:28:33 2002
+++ b/drivers/scsi/ncr53c8xx.h	Mon Feb 17 12:02:10 2003
@@ -60,17 +60,12 @@
 int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int);
 int ncr53c8xx_slave_configure(Scsi_Device *);
-
-#ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *);
-#else
-#define ncr53c8xx_release NULL
-#endif
 
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
 
-#define NCR53C8XX {     .name           = "",			\
+#define NCR53C8XX {     .name           = "ncr53c8xx",		\
 			.detect         = ncr53c8xx_detect,	\
 			.release        = ncr53c8xx_release,	\
 			.info           = ncr53c8xx_info, 	\
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	Sun Feb  2 08:50:23 2003
+++ b/drivers/scsi/osst.c	Fri Mar 14 16:41:06 2003
@@ -606,7 +606,7 @@
 {
 	unsigned char	cmd[MAX_COMMAND_SIZE];
 	Scsi_Request  * SRpnt;
-	long		startwait = jiffies;
+	unsigned long	startwait = jiffies;
 #if DEBUG
 	int		dbg  = debugging;
 	char          * name = tape_name(STp);
@@ -673,7 +673,7 @@
 {
 	unsigned char	cmd[MAX_COMMAND_SIZE];
 	Scsi_Request  * SRpnt;
-	long		startwait = jiffies;
+	unsigned long	startwait = jiffies;
 #if DEBUG
 	int		dbg = debugging;
 	char          * name = tape_name(STp);
@@ -777,8 +777,8 @@
 #define OSST_POLL_PER_SEC 10
 static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
 {
-	long	startwait     = jiffies;
-	char  * name          = tape_name(STp);
+	unsigned long	startwait     = jiffies;
+	char	      * name          = tape_name(STp);
 #if DEBUG
 	char	notyetprinted = 1;
 #endif
@@ -1288,7 +1288,7 @@
 	int             logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
 						- (nframes + pending - 1) * blks_per_frame;
 	char          * name             = tape_name(STp);
-	long		startwait        = jiffies;
+	unsigned long	startwait        = jiffies;
 #if DEBUG
 	int		dbg              = debugging;
 #endif
@@ -1477,7 +1477,7 @@
 	int		expected  = 0;
 	int		attempts  = 1000 / skip;
 	int		flag      = 1;
-	long		startwait = jiffies;
+	unsigned long	startwait = jiffies;
 #if DEBUG
 	int		dbg       = debugging;
 #endif
diff -Nru a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
--- a/drivers/scsi/pcmcia/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/drivers/scsi/pcmcia/Kconfig	Thu Feb 27 08:33:17 2003
@@ -3,22 +3,11 @@
 #
 
 menu "PCMCIA SCSI adapter support"
-	depends on SCSI!=n && HOTPLUG && PCMCIA!=n
-
-config SCSI_PCMCIA
-	bool "PCMCIA SCSI adapter support"
-	help
-	  Say Y here if you intend to attach a PCMCIA or CardBus card to your
-	  computer which acts as a SCSI host adapter. These are credit card
-	  size devices often used with laptops.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions PCMCIA SCSI host adapters.
+	depends on SCSI!=n && PCMCIA!=n
 
 config PCMCIA_AHA152X
 	tristate "Adaptec AHA152X PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -30,7 +19,7 @@
 
 config PCMCIA_FDOMAIN
 	tristate "Future Domain PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -42,7 +31,7 @@
 
 config PCMCIA_NINJA_SCSI
 	tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  If you intend to attach this type of PCMCIA SCSI host adapter to
 	  your computer, say Y here and read
@@ -55,7 +44,7 @@
 
 config PCMCIA_QLOGIC
 	tristate "Qlogic PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -65,10 +54,4 @@
 	  whenever you want).  If you want to compile it as a module, say M
 	  here and read <file:Documentation/modules.txt>.
 
-config PCMCIA_SCSICARD
-	bool
-	depends on PCMCIA_QLOGIC=y || PCMCIA_AHA152X=y || PCMCIA_FDOMAIN=y || PCMCIA_NINJA_SCSI=y
-	default y
-
 endmenu
-
diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
--- a/drivers/scsi/pcmcia/fdomain_stub.c	Tue Feb  4 12:12:27 2003
+++ b/drivers/scsi/pcmcia/fdomain_stub.c	Thu Feb 27 09:35:58 2003
@@ -61,15 +61,15 @@
 MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
 MODULE_LICENSE("Dual MPL/GPL");
 
-#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
 /* Bit map of interrupts to choose from */
-INT_MODULE_PARM(irq_mask, 0xdeb8);
+static int irq_mask = 0xdeb8;
+MODULE_PARM(irq_mask, "i");
 static int irq_list[4] = { -1 };
 MODULE_PARM(irq_list, "1-4i");
 
 #ifdef PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)";
@@ -81,11 +81,15 @@
 
 typedef struct scsi_info_t {
     dev_link_t		link;
+    struct Scsi_Host	*host;
     int			ndev;
     dev_node_t		node[8];
 } scsi_info_t;
 
+extern Scsi_Host_Template fdomain_driver_template;
 extern void fdomain_setup(char *str, int *ints);
+extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt );
+extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
 
 static void fdomain_release(u_long arg);
 static int fdomain_event(event_t event, int priority,
@@ -94,8 +98,6 @@
 static dev_link_t *fdomain_attach(void);
 static void fdomain_detach(dev_link_t *);
 
-#define driver_template fdomain_driver_template
-extern Scsi_Host_Template fdomain_driver_template;
 
 static dev_link_t *dev_list = NULL;
 
@@ -231,7 +233,6 @@
     link->conf.ConfigBase = parse.config.base;
 
     /* Configure card */
-    driver_template.module = &__this_module;
     link->state |= DEV_CONFIG;
     
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -260,14 +261,18 @@
     sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
     fdomain_setup(str, ints);
     
-    scsi_register_host(&driver_template);
+    host = __fdomain_16x0_detect(&fdomain_driver_template);
+    if (!host) {
+        printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
+	goto cs_failed;
+    }
+ 
+    scsi_add_host(host, NULL);
 
     tail = &link->dev;
     info->ndev = 0;
-    for (host = scsi_host_get_next(NULL); host;
-	 host = scsi_host_get_next(host))
-	if (host->hostt == &driver_template)
-	    list_for_each_entry (dev, &host->my_devices, siblings) {
+   
+    list_for_each_entry (dev, &host->my_devices, siblings) {
 	    u_long arg[2], id;
 	    kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
 	    id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
@@ -296,10 +301,11 @@
 	    }
 	    *tail = node; tail = &node->next;
 	    info->ndev++;
-	}
+
+    }
+
     *tail = NULL;
-    if (info->ndev == 0)
-	printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
+    info->host = host;
     
     link->state &= ~DEV_CONFIG_PENDING;
     return;
@@ -316,30 +322,22 @@
 static void fdomain_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *)arg;
+    scsi_info_t *info = link->priv;
 
     DEBUG(0, "fdomain_release(0x%p)\n", link);
 
-#warning This does not protect you.  You need some real fix for your races.
-#if 0
-    if (GET_USE_COUNT(&__this_module) != 0) {
-	DEBUG(1, "fdomain_cs: release postponed, "
-	      "device still open\n");
-	link->state |= DEV_STALE_CONFIG;
-	return;
-    }
-#endif
-
-    scsi_unregister_host(&driver_template);
+    scsi_remove_host(info->host);
     link->dev = NULL;
     
     CardServices(ReleaseConfiguration, link->handle);
     CardServices(ReleaseIO, link->handle, &link->io);
     CardServices(ReleaseIRQ, link->handle, &link->irq);
-    
+
+    scsi_unregister(info->host);
+
     link->state &= ~DEV_CONFIG;
     if (link->state & DEV_STALE_LINK)
 	fdomain_detach(link);
-    
 } /* fdomain_release */
 
 /*====================================================================*/
@@ -374,7 +372,7 @@
     case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
 	    CardServices(RequestConfiguration, link->handle, &link->conf);
-	    fdomain_16x0_reset(NULL, 0);
+	    fdomain_16x0_bus_reset(NULL);
 	}
 	break;
     }
diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
--- a/drivers/scsi/pcmcia/qlogic_stub.c	Mon Feb  3 23:47:00 2003
+++ b/drivers/scsi/pcmcia/qlogic_stub.c	Thu Feb 27 09:12:48 2003
@@ -55,7 +55,11 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
 
+
+extern Scsi_Host_Template qlogicfas_driver_template;
 extern void qlogicfas_preset(int port, int irq);
+extern struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *);
+extern int qlogicfas_bus_reset(Scsi_Cmnd *);
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
@@ -81,6 +85,7 @@
 
 typedef struct scsi_info_t {
 	dev_link_t link;
+	struct Scsi_Host *host;
 	unsigned short manf_id;
 	int ndev;
 	dev_node_t node[8];
@@ -92,9 +97,6 @@
 static dev_link_t *qlogic_attach(void);
 static void qlogic_detach(dev_link_t *);
 
-/* Import our driver template */
-extern Scsi_Host_Template qlogicfas_driver_template;
-#define driver_template qlogicfas_driver_template
 
 static dev_link_t *dev_list = NULL;
 
@@ -233,7 +235,6 @@
 		info->manf_id = le16_to_cpu(tuple.TupleData[0]);
 
 	/* Configure card */
-	driver_template.module = &__this_module;
 	link->state |= DEV_CONFIG;
 
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -272,46 +273,52 @@
 	else
 		qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ);
 
-	scsi_register_host(&driver_template);
-
 	tail = &link->dev;
 	info->ndev = 0;
-	for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host))
-		if (host->hostt == &driver_template)
-			list_for_each_entry (dev, &host->my_devices, siblings) {
-				u_long arg[2], id;
-				kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
-				id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000);
-				node = &info->node[info->ndev];
-				node->minor = 0;
-				switch (dev->type) {
-				case TYPE_TAPE:
-					node->major = SCSI_TAPE_MAJOR;
-					sprintf(node->dev_name, "st#%04lx", id);
-					break;
-				case TYPE_DISK:
-				case TYPE_MOD:
-					node->major = SCSI_DISK0_MAJOR;
-					sprintf(node->dev_name, "sd#%04lx", id);
-					break;
-				case TYPE_ROM:
-				case TYPE_WORM:
-					node->major = SCSI_CDROM_MAJOR;
-					sprintf(node->dev_name, "sr#%04lx", id);
-					break;
-				default:
-					node->major = SCSI_GENERIC_MAJOR;
-					sprintf(node->dev_name, "sg#%04lx", id);
-					break;
-				}
-				*tail = node;
-				tail = &node->next;
-				info->ndev++;
-			}
-	*tail = NULL;
-	if (info->ndev == 0)
+
+	host = __qlogicfas_detect(&qlogicfas_driver_template);
+	if (!host) {
 		printk(KERN_INFO "qlogic_cs: no SCSI devices found\n");
+		goto out;
+	}
+
+	scsi_add_host(host, NULL);
+
+	list_for_each_entry(dev, &host->my_devices, siblings) {
+		u_long arg[2], id;
+		kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
+		id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000);
+		node = &info->node[info->ndev];
+		node->minor = 0;
+		switch (dev->type) {
+		case TYPE_TAPE:
+			node->major = SCSI_TAPE_MAJOR;
+			sprintf(node->dev_name, "st#%04lx", id);
+			break;
+		case TYPE_DISK:
+		case TYPE_MOD:
+			node->major = SCSI_DISK0_MAJOR;
+			sprintf(node->dev_name, "sd#%04lx", id);
+			break;
+		case TYPE_ROM:
+		case TYPE_WORM:
+			node->major = SCSI_CDROM_MAJOR;
+			sprintf(node->dev_name, "sr#%04lx", id);
+			break;
+		default:
+			node->major = SCSI_GENERIC_MAJOR;
+			sprintf(node->dev_name, "sg#%04lx", id);
+			break;
+		}
+		*tail = node;
+		tail = &node->next;
+		info->ndev++;
+	}
 
+	*tail = NULL;
+	info->host = host;
+
+out:
 	link->state &= ~DEV_CONFIG_PENDING;
 	return;
 
@@ -327,29 +334,22 @@
 static void qlogic_release(u_long arg)
 {
 	dev_link_t *link = (dev_link_t *) arg;
+	scsi_info_t *info = link->priv;
 
 	DEBUG(0, "qlogic_release(0x%p)\n", link);
 
-#warning This does not protect you.  You need some real fix for your races.
-#if 0
-	if (GET_USE_COUNT(&__this_module) != 0) {
-		DEBUG(0, "qlogic_cs: release postponed, device still open\n");
-		link->state |= DEV_STALE_CONFIG;
-		return;
-	}
-#endif
-
-	scsi_unregister_host(&driver_template);
+	scsi_remove_host(info->host);
 	link->dev = NULL;
 
 	CardServices(ReleaseConfiguration, link->handle);
 	CardServices(ReleaseIO, link->handle, &link->io);
 	CardServices(ReleaseIRQ, link->handle, &link->irq);
 
+	scsi_unregister(info->host);
+
 	link->state &= ~DEV_CONFIG;
 	if (link->state & DEV_STALE_LINK)
 		qlogic_detach(link);
-
 }				/* qlogic_release */
 
 /*====================================================================*/
@@ -390,7 +390,7 @@
 				outb(0x04, link->io.BasePort1 + 0xd);
 			}
 			/* Ugggglllyyyy!!! */
-			driver_template.eh_bus_reset_handler(NULL);
+			qlogicfas_bus_reset(NULL);
 		}
 		break;
 	}
diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
--- a/drivers/scsi/qlogicfas.c	Tue Feb  4 01:41:00 2003
+++ b/drivers/scsi/qlogicfas.c	Thu Feb 27 09:13:04 2003
@@ -127,11 +127,6 @@
 #endif
 
 #include <linux/module.h>
-
-#ifdef PCMCIA
-#undef MODULE
-#endif
-
 #include <linux/blk.h>		/* to get disk capacity */
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -148,7 +143,6 @@
 
 #include "scsi.h"
 #include "hosts.h"
-#include "qlogicfas.h"
 
 /*----------------------------------------------------------------*/
 /* driver state info, local to driver */
@@ -166,6 +160,8 @@
 static int qlcfg9 = ((XTALFREQ + 4) / 5);
 static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4);
 
+int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
+
 /*----------------------------------------------------------------*/
 /* The qlogic card uses two register maps - These macros select which one */
 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
@@ -631,14 +627,12 @@
  *	Look for qlogic card and init if found 
  */
  
-int __devinit qlogicfas_detect(Scsi_Host_Template * host)
+struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host)
 {
 	int i, j;		/* these are only used by IRQ detect */
 	int qltyp;		/* type of chip */
 	struct Scsi_Host *hreg;	/* registered host structure */
 
-	host->proc_name = "qlogicfas";
-
 	/*	Qlogic Cards only exist at 0x230 or 0x330 (the chip itself
 	 *	decodes the address - I check 230 first since MIDI cards are
 	 *	typically at 0x330
@@ -659,7 +653,7 @@
 			release_region(qbase, 0x10);
 		}
 		if (qbase == 0x430)
-			return 0;
+			return NULL;;
 	} else
 		printk(KERN_INFO "Ql: Using preset base address of %03x\n", qbase);
 
@@ -726,16 +720,21 @@
 		qltyp, qbase, qlirq, QL_TURBO_PDMA);
 	host->name = qinfo;
 
-	return 1;
+	return hreg;
 
 err_release_mem:
 	release_region(qbase, 0x10);
 	if (host->can_queue)
 		free_irq(qlirq, do_ql_ihandl);
-	return 0;
+	return NULL;;
 
 }
 
+int __devinit qlogicfas_detect(Scsi_Host_Template *sht)
+{
+	return (__qlogicfas_detect(sht) != NULL);
+}
+
 /* 
  *	Return bios parameters 
  */
@@ -777,7 +776,7 @@
  *	the PCMCIA qlogic_stub code. This wants fixing
  */
 
-static int qlogicfas_bus_reset(Scsi_Cmnd * cmd)
+int qlogicfas_bus_reset(Scsi_Cmnd * cmd)
 {
 	qabort = 2;
 	ql_zap();
@@ -818,9 +817,27 @@
 /*
  *	The driver template is also needed for PCMCIA
  */
- 
-Scsi_Host_Template qlogicfas_driver_template = QLOGICFAS;
-#define driver_template qlogicfas_driver_template
+Scsi_Host_Template qlogicfas_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "qlogicfas",
+	.proc_name		= "qlogicfas",
+	.detect			= qlogicfas_detect,
+	.info			= qlogicfas_info,
+	.command		= qlogicfas_command,
+	.queuecommand		= qlogicfas_queuecommand,
+	.eh_abort_handler	= qlogicfas_abort,
+	.eh_bus_reset_handler	= qlogicfas_bus_reset,
+	.eh_device_reset_handler= qlogicfas_device_reset,
+	.eh_host_reset_handler	= qlogicfas_host_reset,
+	.bios_param		= qlogicfas_biosparam,
+	.can_queue		= 0,
+	.this_id		= -1,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 1,
+	.use_clustering		= DISABLE_CLUSTERING,
+};
 
+#ifndef PCMCIA
+#define driver_template qlogicfas_driver_template
 #include "scsi_module.c"
-
+#endif
diff -Nru a/drivers/scsi/qlogicfas.h b/drivers/scsi/qlogicfas.h
--- a/drivers/scsi/qlogicfas.h	Tue Dec 10 12:28:33 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,34 +0,0 @@
-#ifndef _QLOGICFAS_H
-#define _QLOGICFAS_H
-
-static int qlogicfas_detect(Scsi_Host_Template * );
-static const char * qlogicfas_info(struct Scsi_Host *);
-static int qlogicfas_command(Scsi_Cmnd *);
-static int qlogicfas_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-static int qlogicfas_abort(Scsi_Cmnd *);
-static int qlogicfas_bus_reset(Scsi_Cmnd *);
-static int qlogicfas_device_reset(Scsi_Cmnd *);
-static int qlogicfas_host_reset(Scsi_Cmnd *);
-static int qlogicfas_biosparam(struct scsi_device *, struct block_device *,
-			       sector_t, int[]);
-
-#define QLOGICFAS {						\
-	.detect         		= qlogicfas_detect,	\
-	.info           		= qlogicfas_info,		\
-	.command     			= qlogicfas_command, 	\
-	.queuecommand			= qlogicfas_queuecommand,	\
-	.eh_abort_handler          	= qlogicfas_abort,	\
-	.eh_bus_reset_handler		= qlogicfas_bus_reset,	\
-	.eh_device_reset_handler        = qlogicfas_device_reset,	\
-	.eh_host_reset_handler          = qlogicfas_host_reset,	\
-	.bios_param     = qlogicfas_biosparam,			\
-	.can_queue      = 0,					\
-	.this_id        = -1,					\
-	.sg_tablesize   = SG_ALL,					\
-	.cmd_per_lun    = 1,					\
-	.use_clustering = DISABLE_CLUSTERING			\
-}
-#endif /* _QLOGICFAS_H */
-
-
-
diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
--- a/drivers/scsi/qlogicfc.c	Tue Feb 25 02:46:27 2003
+++ b/drivers/scsi/qlogicfc.c	Tue Mar 11 13:50:31 2003
@@ -694,7 +694,7 @@
 int isp2x00_detect(Scsi_Host_Template * tmpt)
 {
 	int hosts = 0;
-	int wait_time;
+	unsigned long wait_time;
 	struct Scsi_Host *host = NULL;
 	struct isp2x00_hostdata *hostdata;
 	struct pci_dev *pdev;
@@ -836,14 +836,22 @@
 
 	short param[8];
 	int i, j;
-	struct id_name_map temp[QLOGICFC_MAX_ID + 1];
+	struct id_name_map *map; /* base of array [QLOGICFC_MAX_ID + 1] */
+	struct id_name_map *mapx; /* array entry pointer */
 	struct isp2x00_hostdata *hostdata;
 
-	isp2x00_disable_irqs(host);
-
-	memset(temp, 0, sizeof(temp));
 	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
+	map = kmalloc((QLOGICFC_MAX_ID + 1) * sizeof(struct id_name_map), GFP_ATOMIC);
+	if (!map) {
+	        printk("qlogicfc%d : error getting memory -- cannot make port database.\n",
+				hostdata->host_id);
+		goto fini;
+	}
+	memset(map, 0, (QLOGICFC_MAX_ID + 1) * sizeof(struct id_name_map));
+
+	isp2x00_disable_irqs(host);
+
 #if ISP2x00_FABRIC
 	for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {
 		param[0] = MBOX_PORT_LOGOUT;
@@ -868,72 +876,74 @@
 	if (param[0] == MBOX_COMMAND_COMPLETE) {
 		hostdata->port_id = ((u_int) param[3]) << 16;
 		hostdata->port_id |= param[2];
-		temp[0].loop_id = param[1];
-		temp[0].wwn = hostdata->wwn;
+		map->loop_id = param[1];
+		map->wwn = hostdata->wwn;
 	}
 	else {
 	        printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id);
 	}
 
-        for (i = 0; i <=QLOGICFC_MAX_ID; i++)
-                temp[i].loop_id = temp[0].loop_id;
+        for (i = 0, mapx = map; i <= QLOGICFC_MAX_ID; i++, mapx++)
+                mapx->loop_id = map->loop_id;
    
-        for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) {
+        for (i = 0, j = 1, mapx = map + 1; i <= QLOGICFC_MAX_LOOP_ID; i++) {
                 param[0] = MBOX_GET_PORT_NAME;
 		param[1] = (i << 8) & 0xff00;
 
 		isp2x00_mbox_command(host, param);
 
 		if (param[0] == MBOX_COMMAND_COMPLETE) {
-			temp[j].loop_id = i;
-			temp[j].wwn = ((u64) (param[2] & 0xff)) << 56;
-			temp[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48;
-			temp[j].wwn |= ((u64) (param[3] & 0xff)) << 40;
-			temp[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32;
-			temp[j].wwn |= ((u64) (param[6] & 0xff)) << 24;
-			temp[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16;
-			temp[j].wwn |= ((u64) (param[7] & 0xff)) << 8;
-			temp[j].wwn |= ((u64) ((param[7] >> 8) & 0xff));
+			mapx->loop_id = i;
+			mapx->wwn = ((u64) (param[2] & 0xff)) << 56;
+			mapx->wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48;
+			mapx->wwn |= ((u64) (param[3] & 0xff)) << 40;
+			mapx->wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32;
+			mapx->wwn |= ((u64) (param[6] & 0xff)) << 24;
+			mapx->wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16;
+			mapx->wwn |= ((u64) (param[7] & 0xff)) << 8;
+			mapx->wwn |= ((u64) ((param[7] >> 8) & 0xff));
 
 			j++;
-
+			mapx++;
 		}
 	}
 
 
 #if ISP2x00_FABRIC
-	isp2x00_init_fabric(host, temp, j);
+	isp2x00_init_fabric(host, map, j);
 #endif
 
-	for (i = 0; i <= QLOGICFC_MAX_ID; i++) {
-		if (temp[i].wwn != hostdata->port_db[i].wwn) {
-			for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
-				if (temp[j].wwn == hostdata->port_db[i].wwn) {
-					hostdata->port_db[i].loop_id = temp[j].loop_id;
+	for (i = 0, mapx = map; i <= QLOGICFC_MAX_ID; i++, mapx++) {
+		struct id_name_map *tmap; /* second array entry pointer */
+		if (mapx->wwn != hostdata->port_db[i].wwn) {
+			for (j = 0, tmap = map; j <= QLOGICFC_MAX_ID; j++, tmap++) {
+				if (tmap->wwn == hostdata->port_db[i].wwn) {
+					hostdata->port_db[i].loop_id = tmap->loop_id;
 					break;
 				}
 			}
 			if (j == QLOGICFC_MAX_ID + 1)
-				hostdata->port_db[i].loop_id = temp[0].loop_id;
+				hostdata->port_db[i].loop_id = map->loop_id;
 
 			for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
-				if (hostdata->port_db[j].wwn == temp[i].wwn || !hostdata->port_db[j].wwn) {
+				if (hostdata->port_db[j].wwn == mapx->wwn || !hostdata->port_db[j].wwn) {
 					break;
 				}
 			}
 			if (j == QLOGICFC_MAX_ID + 1)
 				printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id);
 			if (!hostdata->port_db[j].wwn) {
-				hostdata->port_db[j].loop_id = temp[i].loop_id;
-				hostdata->port_db[j].wwn = temp[i].wwn;
+				hostdata->port_db[j].loop_id = mapx->loop_id;
+				hostdata->port_db[j].wwn = mapx->wwn;
 			}
 		} else
-			hostdata->port_db[i].loop_id = temp[i].loop_id;
+			hostdata->port_db[i].loop_id = mapx->loop_id;
 
 	}
 
 	isp2x00_enable_irqs(host);
-
+	kfree(map);
+fini:
 	return 0;
 }
 
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Wed Feb 26 00:00:06 2003
+++ b/drivers/scsi/scsi.c	Mon Mar  3 10:48:16 2003
@@ -96,12 +96,7 @@
 Scsi_Cmnd *last_cmnd;
 static unsigned long serial_number;
 
-struct softscsi_data {
-	Scsi_Cmnd *head;
-	Scsi_Cmnd *tail;
-};
-
-static struct softscsi_data softscsi_data[NR_CPUS] __cacheline_aligned;
+static struct list_head done_q[NR_CPUS] __cacheline_aligned;
 
 /*
  * List of all highlevel drivers.
@@ -637,79 +632,60 @@
 }
 
 /**
- * scsi_done - Mark this command as done
- * @SCpnt: The SCSI Command which we think we've completed.
+ * scsi_done - Enqueue the finished SCSI command into the done queue.
+ * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
+ * ownership back to SCSI Core -- i.e. the LLDD has finished with it.
  *
- * This function is the mid-level interrupt routine, which decides how
- * to handle error conditions.  Each invocation of this function must
- * do one and *only* one of the following:
+ * This function is the mid-level's (SCSI Core) interrupt routine, which
+ * regains ownership of the SCSI command (de facto) from a LLDD, and enqueues
+ * the command to the done queue for further processing.
  *
- *      1) Insert command in BH queue.
- *      2) Activate error handler for host.
+ * This is the producer of the done queue who enqueues at the tail.
  *
- * There is no longer a problem with stack overflow.  Interrupts queue
- * Scsi_Cmnd on a per-CPU queue and the softirq handler removes them
- * from the queue one at a time.
- *
- * This function is sometimes called from interrupt context, but sometimes
- * from task context.
+ * This function is interrupt context safe.
  */
-void scsi_done(Scsi_Cmnd * SCpnt)
+void scsi_done(struct scsi_cmnd *cmd)
 {
+	int cpu;
 	unsigned long flags;
-	int cpu, tstatus;
-	struct softscsi_data *queue;
+	struct list_head *pdone_q;
 
 	/*
 	 * We don't have to worry about this one timing out any more.
-	 */
-	tstatus = scsi_delete_timer(SCpnt);
-
-	/*
-	 * If we are unable to remove the timer, it means that the command
-	 * has already timed out.  In this case, we have no choice but to
+	 * If we are unable to remove the timer, then the command
+	 * has already timed out.  In which case, we have no choice but to
 	 * let the timeout function run, as we have no idea where in fact
 	 * that function could really be.  It might be on another processor,
 	 * etc, etc.
 	 */
-	if (!tstatus) {
+	if (!scsi_delete_timer(cmd))
 		return;
-	}
 
 	/* Set the serial numbers back to zero */
-	SCpnt->serial_number = 0;
-	SCpnt->serial_number_at_timeout = 0;
-	SCpnt->state = SCSI_STATE_BHQUEUE;
-	SCpnt->owner = SCSI_OWNER_BH_HANDLER;
-	SCpnt->bh_next = NULL;
+	cmd->serial_number = 0;
+	cmd->serial_number_at_timeout = 0;
+	cmd->state = SCSI_STATE_BHQUEUE;
+	cmd->owner = SCSI_OWNER_BH_HANDLER;
 
 	/*
-	 * Next, put this command in the softirq queue.
-	 *
-	 * This is a per-CPU queue, so we just disable local interrupts
+	 * Next, enqueue the command into the done queue.
+	 * It is a per-CPU queue, so we just disable local interrupts
 	 * and need no spinlock.
 	 */
-
 	local_irq_save(flags);
 
 	cpu = smp_processor_id();
-	queue = &softscsi_data[cpu];
-
-	if (!queue->head) {
-		queue->head = SCpnt;
-		queue->tail = SCpnt;
-	} else {
-		queue->tail->bh_next = SCpnt;
-		queue->tail = SCpnt;
-	}
-
+	pdone_q = &done_q[cpu];
+	list_add_tail(&cmd->eh_entry, pdone_q);
 	cpu_raise_softirq(cpu, SCSI_SOFTIRQ);
 
 	local_irq_restore(flags);
 }
 
 /**
- * scsi_softirq - Perform post-interrupt handling for completed commands
+ * scsi_softirq - Perform post-interrupt processing of finished SCSI commands.
+ *
+ * This is the consumer of the done queue.
  *
  * This is called with all interrupts enabled.  This should reduce
  * interrupt latency, stack depth, and reentrancy of the low-level
@@ -717,88 +693,92 @@
  */
 static void scsi_softirq(struct softirq_action *h)
 {
-	int cpu = smp_processor_id();
-	struct softscsi_data *queue = &softscsi_data[cpu];
+	LIST_HEAD(local_q);
 
-	while (queue->head) {
-		Scsi_Cmnd *SCpnt, *SCnext;
+	local_irq_disable();
+	list_splice_init(&done_q[smp_processor_id()], &local_q);
+	local_irq_enable();
+
+	while (!list_empty(&local_q)) {
+		struct scsi_cmnd *cmd = list_entry(local_q.next,
+						   struct scsi_cmnd, eh_entry);
+		list_del_init(&cmd->eh_entry);
 
-		local_irq_disable();
-		SCpnt = queue->head;
-		queue->head = NULL;
-		local_irq_enable();
+		switch (scsi_decide_disposition(cmd)) {
+		case SUCCESS:
+			/*
+			 * Add to BH queue.
+			 */
+			SCSI_LOG_MLCOMPLETE(3,
+					    printk("Command finished %d %d "
+						   "0x%x\n",
+					   cmd->device->host->host_busy,
+					   cmd->device->host->host_failed,
+						   cmd->result));
 
-		for (; SCpnt; SCpnt = SCnext) {
-			SCnext = SCpnt->bh_next;
+			scsi_finish_command(cmd);
+			break;
+		case NEEDS_RETRY:
+			/*
+			 * We only come in here if we want to retry a
+			 * command.  The test to see whether the
+			 * command should be retried should be keeping
+			 * track of the number of tries, so we don't
+			 * end up looping, of course.
+			 */
+			SCSI_LOG_MLCOMPLETE(3, printk("Command needs retry "
+						      "%d %d 0x%x\n",
+					      cmd->device->host->host_busy,
+					      cmd->device->host->host_failed,
+						      cmd->result));
 
-			switch (scsi_decide_disposition(SCpnt)) {
-			case SUCCESS:
-				/*
-				 * Add to BH queue.
-				 */
-				SCSI_LOG_MLCOMPLETE(3, printk("Command finished %d %d 0x%x\n", SCpnt->device->host->host_busy,
-						SCpnt->device->host->host_failed,
-							 SCpnt->result));
-
-				scsi_finish_command(SCpnt);
-				break;
-			case NEEDS_RETRY:
-				/*
-				 * We only come in here if we want to retry a
-				 * command.  The test to see whether the
-				 * command should be retried should be keeping
-				 * track of the number of tries, so we don't
-				 * end up looping, of course.
-				 */
-				SCSI_LOG_MLCOMPLETE(3, printk("Command needs retry %d %d 0x%x\n", SCpnt->device->host->host_busy,
-				SCpnt->device->host->host_failed, SCpnt->result));
+			scsi_retry_command(cmd);
+			break;
+		case ADD_TO_MLQUEUE:
+			/* 
+			 * This typically happens for a QUEUE_FULL
+			 * message - typically only when the queue
+			 * depth is only approximate for a given
+			 * device.  Adding a command to the queue for
+			 * the device will prevent further commands
+			 * from being sent to the device, so we
+			 * shouldn't end up with tons of things being
+			 * sent down that shouldn't be.
+			 */
+			SCSI_LOG_MLCOMPLETE(3, printk("Command rejected as "
+						      "device queue full, "
+						      "put on ml queue %p\n",
+						      cmd));
+			scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
+			break;
+		default:
+			/*
+			 * Here we have a fatal error of some sort.
+			 * Turn it over to the error handler.
+			 */
+			SCSI_LOG_MLCOMPLETE(3,
+					    printk("Command failed %p %x "
+						   "busy=%d failed=%d\n",
+						   cmd, cmd->result,
+					   cmd->device->host->host_busy,
+					   cmd->device->host->host_failed));
 
-				scsi_retry_command(SCpnt);
-				break;
-			case ADD_TO_MLQUEUE:
-				/* 
-				 * This typically happens for a QUEUE_FULL
-				 * message - typically only when the queue
-				 * depth is only approximate for a given
-				 * device.  Adding a command to the queue for
-				 * the device will prevent further commands
-				 * from being sent to the device, so we
-				 * shouldn't end up with tons of things being
-				 * sent down that shouldn't be.
-				 */
-				SCSI_LOG_MLCOMPLETE(3, printk("Command rejected as device queue full, put on ml queue %p\n",
-                                                              SCpnt));
-				scsi_queue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);
-				break;
-			default:
-				/*
-				 * Here we have a fatal error of some sort.
-				 * Turn it over to the error handler.
-				 */
-				SCSI_LOG_MLCOMPLETE(3,
-					printk("Command failed %p %x busy=%d failed=%d\n",
-						SCpnt, SCpnt->result,
-						SCpnt->device->host->host_busy,
-						SCpnt->device->host->host_failed));
+			/*
+			 * Dump the sense information too.
+			 */
+			if ((status_byte(cmd->result)&CHECK_CONDITION) != 0) {
+				SCSI_LOG_MLCOMPLETE(3, print_sense("bh", cmd));
+			}
 
+			if (!scsi_eh_scmd_add(cmd, 0)) {
 				/*
-				 * Dump the sense information too.
+				 * We only get here if the error
+				 * recovery thread has died.
 				 */
-				if ((status_byte(SCpnt->result) & CHECK_CONDITION) != 0) {
-					SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt));
-				}
-
-				if (!scsi_eh_scmd_add(SCpnt, 0))
-				{
-					/*
-					 * We only get here if the error
-					 * recovery thread has died.
-					 */
-					scsi_finish_command(SCpnt);
-				}
-			}	/* switch */
-		}		/* for(; SCpnt...) */
-	}			/* while(queue->head) */
+				scsi_finish_command(cmd);
+			}
+		}
+	}
 }
 
 /*
@@ -1284,6 +1264,21 @@
 	up_read(&scsi_devicelist_mutex);
 }
 
+void scsi_rescan_device(struct scsi_device *sdev)
+{
+	struct Scsi_Device_Template *sdt;
+
+	down_read(&scsi_devicelist_mutex);
+	list_for_each_entry(sdt, &scsi_devicelist, list) {
+		if (!try_module_get(sdt->module))
+			continue;
+		if (*sdt->rescan)
+			(*sdt->rescan)(sdev);
+		module_put(sdt->module);
+	}
+	up_read(&scsi_devicelist_mutex);
+}
+
 int scsi_device_get(struct scsi_device *sdev)
 {
 	if (!try_module_get(sdev->host->hostt->module))
@@ -1481,7 +1476,7 @@
 
 static int __init init_scsi(void)
 {
-	int error;
+	int error, i;
 
 	error = scsi_init_queue();
 	if (error)
@@ -1495,6 +1490,9 @@
 	error = scsi_sysfs_register();
 	if (error)
 		goto cleanup_devlist;
+
+	for (i = 0; i < NR_CPUS; i++)
+		INIT_LIST_HEAD(&done_q[i]);
 
 	scsi_host_init();
 	devfs_mk_dir(NULL, "scsi", NULL);
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Sun Feb 23 10:34:55 2003
+++ b/drivers/scsi/scsi.h	Fri Mar 14 16:35:26 2003
@@ -280,26 +280,7 @@
 #define SCSI_SET_IOCTL_LOGGING(LEVEL)  \
         SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL);
 
-/*
- *  the return of the status word will be in the following format :
- *  The low byte is the status returned by the SCSI command, 
- *  with vendor specific bits masked.
- *  
- *  The next byte is the message which followed the SCSI status.
- *  This allows a stos to be used, since the Intel is a little
- *  endian machine.
- *  
- *  The final byte is a host return code, which is one of the following.
- *  
- *  IE 
- *  lsb     msb
- *  status  msg host code   
- *  
- *  Our errors returned by OUR driver, NOT SCSI message.  Or'd with
- *  SCSI message passed back to driver <IF any>.
- */
-
-
+/* host byte codes */
 #define DID_OK          0x00	/* NO error                                */
 #define DID_NO_CONNECT  0x01	/* Couldn't connect before timeout period  */
 #define DID_BUS_BUSY    0x02	/* BUS stayed busy through time out period */
@@ -760,8 +741,7 @@
 	 * abort, etc are in process. 
 	 */
 	unsigned volatile char internal_timeout;
-	struct scsi_cmnd *bh_next;	/* To enumerate the commands waiting 
-					   to be processed. */
+
 	unsigned char cmd_len;
 	unsigned char old_cmd_len;
 	unsigned char sc_data_direction;
diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
--- a/drivers/scsi/scsi_debug.c	Tue Jan 28 08:15:52 2003
+++ b/drivers/scsi/scsi_debug.c	Sun Mar 16 07:05:12 2003
@@ -11,7 +11,7 @@
  *  (or disk like devices) sharing a common amount of RAM 
  *  
  *
- *  For documentation see http://www.torque.net/sg/sdebug.html
+ *  For documentation see http://www.torque.net/sg/sdebug25.html
  *
  *   D. Gilbert (dpg) work for Magneto-Optical device test [20010421]
  *   dpg: work for devfs large number of disks [20010809]
@@ -54,38 +54,37 @@
 
 #include "scsi_debug.h"
 
-static const char * scsi_debug_version_str = "Version: 1.67 (20021221)";
-
-#ifndef SCSI_CMD_READ_16
-#define SCSI_CMD_READ_16 0x88
-#endif
-#ifndef SCSI_CMD_WRITE_16
-#define SCSI_CMD_WRITE_16 0x8a
-#endif
+static const char * scsi_debug_version_str = "Version: 1.68 (20030314)";
 
 #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 
 /* Default values for driver parameters */
 #define DEF_NUM_DEVS   1
 #define DEF_DEV_SIZE_MB   8
-#define DEF_EVERY_NTH   100
+#define DEF_EVERY_NTH   0
 #define DEF_DELAY   1
 #define DEF_MAX_LUNS   2
 #define DEF_SCSI_LEVEL   3
 #define DEF_NUM_HOST   1
 #define DEF_OPTS   0
 
-#define MAX_NUM_HOSTS   128
-
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
 #define SCSI_DEBUG_OPT_MEDIUM_ERR   2
-#define SCSI_DEBUG_OPT_EVERY_NTH   4
+#define SCSI_DEBUG_OPT_TIMEOUT   4
+#define SCSI_DEBUG_OPT_RECOVERED_ERR   8
+/* When "every_nth" > 0 then modulo "every_nth" commands:
+ *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
+ *   - a RECOVERED_ERROR is simulated on successful read and write
+ *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ */
 
-#define OPT_MEDIUM_ERR_ADDR   0x1234
+/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
+ * sector on read commands: */
+#define OPT_MEDIUM_ERR_ADDR   0x1234 /* that's sector 4660 in decimal */
 
 static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
-static int scsi_debug_num_devs = DEF_NUM_DEVS;
+static int scsi_debug_num_devs = DEF_NUM_DEVS; /* max devs per host */
 static int scsi_debug_opts = DEF_OPTS;
 static int scsi_debug_every_nth = DEF_EVERY_NTH;
 static int scsi_debug_cmnd_count = 0;
@@ -112,25 +111,28 @@
 #define SECT_SIZE (1 << POW2_SECT_SIZE)
 #define SECT_SIZE_PER(TGT) SECT_SIZE
 
-struct sdebug_host_info {
-	struct Scsi_Host *shost;
-	struct device *dev;
-};
-
-struct sdebug_host_info * scsi_debug_hosts;
-
 #define SDEBUG_SENSE_LEN 32
 
 struct sdebug_dev_info {
+	struct list_head dev_list;
 	unsigned char sense_buff[SDEBUG_SENSE_LEN];	/* weak nexus */
 	unsigned int channel;
 	unsigned int target;
 	unsigned int lun;
-	struct Scsi_Host *host;
+	struct sdebug_host_info *sdbg_host;
 	char reset;
 	char used;
 };
-static struct sdebug_dev_info * devInfop;
+
+struct sdebug_host_info {
+	struct list_head host_list;
+	struct Scsi_Host *shost;
+	struct device *dev;
+	struct list_head dev_info_list;
+};
+
+static LIST_HEAD(sdebug_host_list);
+static spinlock_t sdebug_host_list_lock = SPIN_LOCK_UNLOCKED;
 
 typedef void (* done_funct_t) (struct scsi_cmnd *);
 
@@ -156,11 +158,20 @@
 static rwlock_t atomic_rw = RW_LOCK_UNLOCKED;
 
 static char sdebug_proc_name[] = "scsi_debug";
+
+static int sdebug_driver_probe(struct device *);
+static int sdebug_driver_remove(struct device *);
+
 static struct device_driver sdebug_driverfs_driver = {
-	.name = sdebug_proc_name,
-	.devclass = &shost_devclass,
+	.name 		= sdebug_proc_name,
+	.probe          = sdebug_driver_probe,
+	.remove         = sdebug_driver_remove,
+	.devclass 	= &shost_devclass,
 };
 
+static const int check_condition_result = 
+		(DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
 /* function declarations */
 static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
 			int bufflen, struct sdebug_dev_info * devip);
@@ -174,7 +185,7 @@
 static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
 			    int bufflen, struct sdebug_dev_info * devip);
 static void timer_intr_handler(unsigned long);
-static struct sdebug_dev_info * devInfoReg(struct scsi_cmnd *scmd);
+static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev);
 static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, 
 			    int asc, int asq, int inbandLen);
 static int check_reset(struct scsi_cmnd * SCpnt, 
@@ -189,15 +200,29 @@
                            const char * dev_id_str, int dev_id_str_len);
 static void do_create_driverfs_files(void);
 static void do_remove_driverfs_files(void);
-static void sdebug_add_shost(int num);
-static void sdebug_remove_shost(int num);
 
-static int sdebug_add_adapter(int num);
-static void sdebug_remove_adapter(int num);
+static int sdebug_add_adapter(void);
+static void sdebug_remove_adapter(void);
 static struct device pseudo_primary;
 static struct bus_type pseudo_lld_bus;
-int scsi_debug_register_driver(struct device_driver *);
-int scsi_debug_unregister_driver(struct device_driver *);
+static int scsi_debug_register_driver(struct device_driver *);
+static int scsi_debug_unregister_driver(struct device_driver *);
+
+static struct sdebug_host_info * 
+		sdebug_shost_to_host_info(struct Scsi_Host *shost)
+{
+	struct sdebug_host_info * sdbg_host, * found = NULL;
+
+	spin_lock(&sdebug_host_list_lock);
+	list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+		if (sdbg_host->shost == shost) {
+			found = sdbg_host;
+			break;
+		}
+	}
+	spin_unlock(&sdebug_host_list_lock);
+	return found;
+}
 
 static unsigned char * scatg2virt(const struct scatterlist * sclp)
 {
@@ -222,6 +247,7 @@
 	unsigned long capac;
 	struct sdebug_dev_info * devip = NULL;
 	unsigned char * sbuff;
+	int inj_recovered = 0;
 
 	if (done == NULL)
 		return 0;	/* assume mid level reprocessing command */
@@ -250,16 +276,18 @@
 	if (SCpnt->device->lun >= scsi_debug_max_luns)
 		return schedule_resp(SCpnt, NULL, done, 
 				     DID_NO_CONNECT << 16, 0);
-	devip = devInfoReg(SCpnt);
+	devip = devInfoReg(SCpnt->device);
 	if (NULL == devip)
 		return schedule_resp(SCpnt, NULL, done, 
 				     DID_NO_CONNECT << 16, 0);
 
-        if ((SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts) &&
-            (scsi_debug_every_nth > 0) &&
+        if ((scsi_debug_every_nth > 0) &&
             (++scsi_debug_cmnd_count >= scsi_debug_every_nth)) {
                 scsi_debug_cmnd_count =0;
-                return 0; /* ignore command causing timeout */
+		if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
+			return 0; /* ignore command causing timeout */
+		else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
+			inj_recovered = 1; /* to reads and writes below */
         }
 
 	switch (*cmd) {
@@ -269,8 +297,8 @@
 	case REQUEST_SENSE:	/* mandatory */
 		/* Since this driver indicates autosense by placing the
 		 * sense buffer in the scsi_cmnd structure in the response
-		 * (when CHECK_CONDITION is set), the mid level shouldn't
-		 * need to call REQUEST_SENSE */
+		 * (when SAM_STAT_CHECK_CONDITION is set), the mid level
+		 * shouldn't need to call REQUEST_SENSE */
 		if (devip) {
 			sbuff = devip->sense_buff;
 			memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? 
@@ -326,14 +354,14 @@
 			buff[7] = SECT_SIZE_PER(target) & 0xff;
 		}
 		break;
-	case SCSI_CMD_READ_16:	/* SBC-2 */
+	case READ_16:
 	case READ_12:
 	case READ_10:
 	case READ_6:
 		if ((errsts = check_reset(SCpnt, devip)))
 			break;
 		upper_blk = 0;
-		if ((*cmd) == SCSI_CMD_READ_16) {
+		if ((*cmd) == READ_16) {
 			upper_blk = cmd[5] + (cmd[4] << 8) + 
 				    (cmd[3] << 16) + (cmd[2] << 24);
 			block = cmd[9] + (cmd[8] << 8) + 
@@ -355,18 +383,22 @@
 			num = cmd[4];
 		}
 		errsts = resp_read(SCpnt, upper_blk, block, num, devip);
+		if (inj_recovered && (0 == errsts)) {
+			mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14);
+			errsts = check_condition_result;
+		}
 		break;
 	case REPORT_LUNS:
 		errsts = resp_report_luns(cmd, buff, bufflen, devip);
 		break;
-	case SCSI_CMD_WRITE_16:	/* SBC-2 */
+	case WRITE_16:
 	case WRITE_12:
 	case WRITE_10:
 	case WRITE_6:
 		if ((errsts = check_reset(SCpnt, devip)))
 			break;
 		upper_blk = 0;
-		if ((*cmd) == SCSI_CMD_WRITE_16) {
+		if ((*cmd) == WRITE_16) {
 			upper_blk = cmd[5] + (cmd[4] << 8) + 
 				    (cmd[3] << 16) + (cmd[2] << 24);
 			block = cmd[9] + (cmd[8] << 8) + 
@@ -388,6 +420,10 @@
 			num = cmd[4];
 		}
 		errsts = resp_write(SCpnt, upper_blk, block, num, devip);
+		if (inj_recovered && (0 == errsts)) {
+			mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14);
+			errsts = check_condition_result;
+		}
 		break;
 	case MODE_SENSE:
 	case MODE_SENSE_10:
@@ -400,7 +436,7 @@
 		if ((errsts = check_reset(SCpnt, devip)))
 			break;
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14);
-		errsts = (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		errsts = check_condition_result;
 		break;
 	}
 	return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay);
@@ -420,7 +456,7 @@
 	if (devip->reset) {
 		devip->reset = 0;
 		mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14);
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	}
 	return 0;
 }
@@ -481,12 +517,12 @@
 	arr[0] = pq_pdt;
 	if (0x2 & cmd[1]) {  /* CMDDT bit set */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	} else if (0x1 & cmd[1]) {  /* EVPD bit set */
 		int dev_id_num, len;
 		char dev_id_str[6];
 		
-		dev_id_num = ((devip->host->host_no + 1) * 2000) +
+		dev_id_num = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
 			     (devip->target * 1000) + devip->lun;
 		len = snprintf(dev_id_str, 6, "%d", dev_id_num);
 		len = (len > 6) ? 6 : len;
@@ -506,7 +542,7 @@
 		} else {
 			/* Illegal request, invalid field in cdb */
 			mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-			return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+			return check_condition_result;
 		}
 		memcpy(buff, arr, min_len); 
 		return 0;
@@ -619,7 +655,7 @@
 	memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
 	if (0x3 == pcontrol) {  /* Saving values not supported */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14);
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	}
 	dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
 	if (msense_6) {
@@ -662,7 +698,7 @@
 		break;
 	default:
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	}
 	if (msense_6)
 		arr[0] = offset - 1;
@@ -686,14 +722,14 @@
 
 	if (upper_blk || (block + num > sdebug_capacity)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	}
 	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
-	    (block >= OPT_MEDIUM_ERR_ADDR) && 
-	    (block < (OPT_MEDIUM_ERR_ADDR + num))) {
+	    (block <= OPT_MEDIUM_ERR_ADDR) && 
+	    ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
 		mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14);
 		/* claim unrecoverable read error */
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	}
 	read_lock_irqsave(&atomic_rw, iflags);
         sgcount = 0;
@@ -735,7 +771,7 @@
 
 	if (upper_blk || (block + num > sdebug_capacity)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	}
 
 	write_lock_irqsave(&atomic_rw, iflags);
@@ -776,7 +812,7 @@
 	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
 	if ((alloc_len < 16) || (select_report > 2)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+		return check_condition_result;
 	}
 	if (bufflen > 3) {
 		lun_cnt = min((int)(bufflen / sizeof(ScsiLun)),
@@ -810,15 +846,24 @@
 		return;
 	}
 	sqcp->in_use = 0;
-	if (sqcp->done_funct)
+	if (sqcp->done_funct) {
+		sqcp->a_cmnd->result = sqcp->scsi_result;
 		sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */
+	}
 	sqcp->done_funct = NULL;
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
+static int scsi_debug_slave_alloc(struct scsi_device * sdp)
+{
+	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+		printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
+		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
+	return 0;
+}
+
 static int scsi_debug_slave_configure(struct scsi_device * sdp)
 {
-	int k;
 	struct sdebug_dev_info * devip; 
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
@@ -826,16 +871,8 @@
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
 		sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
-	for (k = 0; k < scsi_debug_num_devs; ++k) {
-		devip = &devInfop[k];
-		if ((devip->channel == sdp->channel) &&
-		    (devip->target == sdp->id) &&
-		    (devip->lun == sdp->lun) &&
-		    (devip->host == sdp->host)) {
-			sdp->hostdata = devip;
-			break;
-		}
-	}
+	devip = devInfoReg(sdp);
+	sdp->hostdata = devip;
 	if (sdp->host->cmd_per_lun)
 		scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, 
 					sdp->host->cmd_per_lun);
@@ -852,43 +889,47 @@
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (devip) {
 		/* make this slot avaliable for re-use */
-		memset(devip, 0, sizeof(struct sdebug_dev_info));
+		devip->used = 0;
 		sdp->hostdata = NULL;
 	}
 }
 
-static struct sdebug_dev_info * devInfoReg(struct scsi_cmnd *scmd)
+static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
 {
-	int k;
-	struct scsi_device * sdp = scmd->device;
+	struct sdebug_host_info * sdbg_host;
+	struct sdebug_dev_info * open_devip = NULL;
 	struct sdebug_dev_info * devip =
-			(struct sdebug_dev_info *)sdp->hostdata;
+			(struct sdebug_dev_info *)sdev->hostdata;
 
 	if (devip)
 		return devip;
-	for (k = 0; k < scsi_debug_num_devs; ++k) {
-		devip = &devInfop[k];
-		if ((devip->channel == scmd->device->channel) &&
-		    (devip->target == scmd->device->id) &&
-		    (devip->lun == scmd->device->lun) &&
-		    (devip->host == scmd->device->host))
-			return devip;
-	}
-	for (k = 0; k < scsi_debug_num_devs; ++k) {
-		devip = &devInfop[k];
-		if (!devip->used) {
-			devip->channel = scmd->device->channel;
-			devip->target = scmd->device->id;
-			devip->lun = scmd->device->lun;
-			devip->host = scmd->device->host;
-			devip->reset = 1;
-			devip->used = 1;
-			memset(devip->sense_buff, 0, SDEBUG_SENSE_LEN);
-			devip->sense_buff[0] = 0x70;
-			return devip;
+	sdbg_host = sdebug_shost_to_host_info(sdev->host);
+        if(! sdbg_host) {
+                printk(KERN_ERR "Unable to locate host info\n");
+		return NULL;
+        }
+	list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
+		if ((devip->used) && (devip->channel == sdev->channel) &&
+                    (devip->target == sdev->id) &&
+                    (devip->lun == sdev->lun))
+                        return devip;
+		else {
+			if ((!devip->used) && (!open_devip))
+				open_devip = devip;
 		}
 	}
-	return NULL;
+        if (open_devip) {
+		open_devip->channel = sdev->channel;
+		open_devip->target = sdev->id;
+		open_devip->lun = sdev->lun;
+		open_devip->sdbg_host = sdbg_host;
+		open_devip->reset = 1;
+		open_devip->used = 1;
+		memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
+		open_devip->sense_buff[0] = 0x70;
+		return open_devip;
+        }
+        return NULL;
 }
 
 static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, 
@@ -946,7 +987,7 @@
 		printk(KERN_INFO "scsi_debug: device_reset\n");
 	++num_dev_resets;
 	if (SCpnt) {
-		devip = devInfoReg(SCpnt);
+		devip = devInfoReg(SCpnt->device);
 		if (devip)
 			devip->reset = 1;
 	}
@@ -955,17 +996,21 @@
 
 static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
 {
-	struct scsi_device * sdp;
-	struct Scsi_Host * hp;
-	int k;
+	struct sdebug_host_info *sdbg_host;
+        struct sdebug_dev_info * dev_info;
+        struct scsi_device * sdp;
+        struct Scsi_Host * hp;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 		printk(KERN_INFO "scsi_debug: bus_reset\n");
 	++num_bus_resets;
-	if (SCpnt && ((sdp = SCpnt->device)) && ((hp = SCpnt->device->host))) {
-		for (k = 0; k < scsi_debug_num_devs; ++k) {
-			if (hp == devInfop[k].host)
-				devInfop[k].reset = 1;
+	if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+		sdbg_host = sdebug_shost_to_host_info(hp);
+		if (sdbg_host) {
+			list_for_each_entry(dev_info,
+                                            &sdbg_host->dev_info_list,
+                                            dev_list)
+				dev_info->reset = 1;
 		}
 	}
 	return SUCCESS;
@@ -973,15 +1018,20 @@
 
 static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
 {
-	int k;
+	struct sdebug_host_info * sdbg_host;
+        struct sdebug_dev_info * dev_info;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 		printk(KERN_INFO "scsi_debug: host_reset\n");
 	++num_host_resets;
-	for (k = 0; k < scsi_debug_num_devs; ++k)
-		devInfop[k].reset = 1;
+        spin_lock(&sdebug_host_list_lock);
+        list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+                list_for_each_entry(dev_info, &sdbg_host->dev_info_list,
+                                    dev_list)
+                        dev_info->reset = 1;
+        }
+        spin_unlock(&sdebug_host_list_lock);
 	stop_all_queued();
-
 	return SUCCESS;
 }
 
@@ -1063,7 +1113,7 @@
 	}
 	if (cmnd && devip) {
 		/* simulate autosense by this driver */
-		if (CHECK_CONDITION == status_byte(scsi_result))
+		if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff))
 			memcpy(cmnd->sense_buffer, devip->sense_buff, 
 			       (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ?
 			       SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE);
@@ -1099,6 +1149,8 @@
 		sqcp->cmnd_timer.expires = jiffies + delta_jiff;
 		add_timer(&sqcp->cmnd_timer);
 		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		if (cmnd)
+			cmnd->result = 0;
 		return 0;
 	}
 }
@@ -1120,7 +1172,7 @@
 MODULE_DESCRIPTION("SCSI debug adapter driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM_DESC(num_devs, "number of SCSI devices to simulate");
+MODULE_PARM_DESC(num_devs, "number of SCSI devices per host to simulate");
 MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate");
 MODULE_PARM_DESC(scsi_level, "SCSI level to simulate");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs");
@@ -1163,7 +1215,7 @@
 		if (1 != sscanf(arr, "%d", &pos))
 			return -EINVAL;
 		scsi_debug_opts = pos;
-		if (SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts)
+		if (scsi_debug_every_nth > 0)
                         scsi_debug_cmnd_count = 0;
 		return length;
 	}
@@ -1192,12 +1244,12 @@
 	return len;
 }
 
-static ssize_t sdebug_delay_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) 
 {
-        return sprintf(buf, "%d\n", scsi_debug_delay);
+        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
 }
 
-static ssize_t sdebug_delay_write(struct device_driver * ddp, 
+static ssize_t sdebug_delay_store(struct device_driver * ddp, 
 				  const char * buf, size_t count)
 {
         int delay;
@@ -1211,15 +1263,15 @@
 	}
 	return -EINVAL;
 }
-DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_read, 
-	    sdebug_delay_write)
+DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show, 
+	    sdebug_delay_store)
 
-static ssize_t sdebug_opts_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) 
 {
-        return sprintf(buf, "0x%x\n", scsi_debug_opts);
+        return snprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
 }
 
-static ssize_t sdebug_opts_write(struct device_driver * ddp, 
+static ssize_t sdebug_opts_store(struct device_driver * ddp, 
 				 const char * buf, size_t count)
 {
         int opts;
@@ -1237,50 +1289,76 @@
 	return -EINVAL;
 opts_done:
 	scsi_debug_opts = opts;
+	scsi_debug_cmnd_count = 0;
 	return count;
 }
-DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_read, 
-	    sdebug_opts_write)
+DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, 
+	    sdebug_opts_store)
 
-static ssize_t sdebug_num_devs_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_num_devs_show(struct device_driver * ddp, char * buf) 
+{
+        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_devs);
+}
+static ssize_t sdebug_num_devs_store(struct device_driver * ddp, 
+				     const char * buf, size_t count)
 {
-        return sprintf(buf, "%d\n", scsi_debug_num_devs);
+        int n;
+
+	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+		scsi_debug_num_devs = n;
+		return count;
+	}
+	return -EINVAL;
 }
-DRIVER_ATTR(num_devs, S_IRUGO, sdebug_num_devs_read, NULL) 
+DRIVER_ATTR(num_devs, S_IRUGO | S_IWUSR, sdebug_num_devs_show, 
+	    sdebug_num_devs_store) 
 
-static ssize_t sdebug_dev_size_mb_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) 
 {
-        return sprintf(buf, "%d\n", scsi_debug_dev_size_mb);
+        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
 }
-DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_read, NULL) 
+DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) 
 
-static ssize_t sdebug_every_nth_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) 
 {
-        return sprintf(buf, "%d\n", scsi_debug_every_nth);
+        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
+}
+static ssize_t sdebug_every_nth_store(struct device_driver * ddp, 
+				      const char * buf, size_t count)
+{
+        int nth;
+
+	if ((count > 0) && (1 == sscanf(buf, "%d", &nth)) && (nth >= 0)) {
+		scsi_debug_every_nth = nth;
+		scsi_debug_cmnd_count = 0;
+		return count;
+	}
+	return -EINVAL;
 }
-DRIVER_ATTR(every_nth, S_IRUGO, sdebug_every_nth_read, NULL) 
+DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show,
+	    sdebug_every_nth_store) 
 
-static ssize_t sdebug_max_luns_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) 
 {
-        return sprintf(buf, "%d\n", scsi_debug_max_luns);
+        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
 }
-DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_read, NULL) 
+DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_show, NULL) 
 
-static ssize_t sdebug_scsi_level_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) 
 {
-        return sprintf(buf, "%d\n", scsi_debug_scsi_level);
+        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
 }
-DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_read, NULL) 
+DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) 
 
-static ssize_t sdebug_add_host_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) 
 {
-        return sprintf(buf, "%d\n", scsi_debug_add_host);
+        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
 }
 
-static ssize_t sdebug_add_host_write(struct device_driver * ddp, 
-				  const char * buf, size_t count)
+static ssize_t sdebug_add_host_store(struct device_driver * ddp, 
+				     const char * buf, size_t count)
 {
-        int delta_hosts, k;
+        int delta_hosts;
 	char work[20];
 
         if (1 != sscanf(buf, "%10s", work))
@@ -1297,33 +1375,17 @@
 	}
 	if (delta_hosts > 0) {
 		do {
-			for (k = 0; k < MAX_NUM_HOSTS; ++k) {
-				if (NULL == scsi_debug_hosts[k].shost) {
-					sdebug_add_shost(k);
-					break;
-				}
-			}
-			if (k == MAX_NUM_HOSTS)
-				break;
-			++scsi_debug_add_host;
+			sdebug_add_adapter();
 		} while (--delta_hosts);
 	} else if (delta_hosts < 0) {
 		do {
-			for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) {
-				if (scsi_debug_hosts[k].shost) {
-					sdebug_remove_shost(k);
-					break;
-				}
-			}
-			if (k < 0)
-				break;
-			--scsi_debug_add_host;
+			sdebug_remove_adapter();
 		} while (++delta_hosts);
 	}
 	return count;
 }
-DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_read, 
-	    sdebug_add_host_write)
+DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, 
+	    sdebug_add_host_store)
 
 static void do_create_driverfs_files()
 {
@@ -1349,44 +1411,10 @@
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay);
 }
 
-static void sdebug_add_shost(int num)
-{
-	struct Scsi_Host * hpnt;
-	int err;
-
-	if (sdebug_add_adapter(num)){
-		printk(KERN_ERR "sdebug_add_shost: sdebug_add_adapter failed\n");
-		return;
-	}
-	hpnt = scsi_register(&sdebug_driver_template, 0);
-	if (NULL == hpnt) {
-		sdebug_remove_adapter(num);
-		printk(KERN_ERR "sdebug_add_shost: scsi_register failed\n");
-		return;
-	}
-	err = scsi_add_host(hpnt, scsi_debug_hosts[num].dev);
-	if (err) {
-		printk(KERN_ERR "sdebug_add_shost: scsi_add_host failed\n");
-		scsi_unregister(hpnt);
-		sdebug_remove_adapter(num);
-		return;
-	}
-	hpnt->max_lun = scsi_debug_max_luns;
-
-	scsi_debug_hosts[num].shost = hpnt;
-}
-
-static void sdebug_remove_shost(int num)
-{
-	scsi_remove_host(scsi_debug_hosts[num].shost);
-	scsi_unregister(scsi_debug_hosts[num].shost);
-	sdebug_remove_adapter(num);
-	scsi_debug_hosts[num].shost = NULL;
-}
-
 static int __init scsi_debug_init(void)
 {
 	unsigned long sz;
+	int host_to_add;
 	int k;
 
 	sdebug_store_size = (unsigned long)scsi_debug_dev_size_mb * 1048576;
@@ -1409,30 +1437,10 @@
 			       (sdebug_sectors_per * sdebug_heads);
 	}
 
-	if (scsi_debug_num_devs > 0) {
-		sz = sizeof(struct sdebug_dev_info) * scsi_debug_num_devs;
-		devInfop = vmalloc(sz);
-		if (NULL == devInfop) {
-			printk(KERN_ERR "scsi_debug_init: out of memory\n");
-			return -ENOMEM;
-		}
-		memset(devInfop, 0, sz);
-	}
-
-	sz = sizeof(struct sdebug_host_info) * MAX_NUM_HOSTS;
-	scsi_debug_hosts = vmalloc(sz);
-	if (NULL == scsi_debug_hosts) {
-		printk(KERN_ERR "scsi_debug_init: out of memory 1\n");
-		return -ENOMEM;
-	}
-	memset(scsi_debug_hosts, 0, sz);
-
 	sz = sdebug_store_size;
 	fake_storep = vmalloc(sz);
 	if (NULL == fake_storep) {
 		printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
-		if (devInfop)
-			vfree(devInfop);
 		return -ENOMEM;
 	}
 	memset(fake_storep, 0, sz);
@@ -1446,15 +1454,16 @@
 
 	sdebug_driver_template.proc_name = (char *)sdebug_proc_name;
 
-	for (k = 0; (k < scsi_debug_add_host) && (k < MAX_NUM_HOSTS); k++) {
-		sdebug_add_shost(k);
-		if (NULL == scsi_debug_hosts[k].shost) {
-			printk(KERN_ERR "scsi_debug_init: "
-			       "sdebug_add_shost failed k=%d\n", k);
-			break;
-		}
-	}
-	scsi_debug_add_host = k;        // number of hosts actually present
+	host_to_add = scsi_debug_add_host;
+        scsi_debug_add_host = 0;
+
+        for (k = 0; k < host_to_add; k++) {
+                if (sdebug_add_adapter()) {
+                        printk(KERN_ERR "scsi_debug_init: "
+                               "sdebug_add_adapter failed k=%d\n", k);
+                        break;
+                }
+        }
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
 		printk(KERN_INFO "scsi_debug: ... built %d host(s)\n",
@@ -1465,13 +1474,7 @@
 
 static void __exit scsi_debug_exit(void)
 {
-	int k;
-
-	for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) {
-		if (scsi_debug_hosts[k].shost) {
-			sdebug_remove_shost(k);
-		}
-	}
+	/* free up adapters here ?? */
 	stop_all_queued();
 	do_remove_driverfs_files();
 	scsi_debug_unregister_driver(&sdebug_driverfs_driver);
@@ -1479,8 +1482,6 @@
 	device_unregister(&pseudo_primary);
 
 	vfree(fake_storep);
-	if (devInfop)
-		vfree(devInfop);
 }
 
 device_initcall(scsi_debug_init);
@@ -1502,7 +1503,7 @@
         .match = pseudo_lld_bus_match,
 };
 
-int scsi_debug_register_driver(struct device_driver *dev_driver)
+static int scsi_debug_register_driver(struct device_driver *dev_driver)
 {
 	dev_driver->bus = &pseudo_lld_bus;
 	driver_register(dev_driver);
@@ -1510,36 +1511,168 @@
 	return 0;
 }
 
-int scsi_debug_unregister_driver(struct device_driver *dev_driver)
+static int scsi_debug_unregister_driver(struct device_driver *dev_driver)
 {
 	driver_unregister(dev_driver);
 	return 0;
 }
 
-static int sdebug_add_adapter(int num)
+static void sdebug_release_adapter(struct device * dev)
 {
-	struct device * dev;
+        kfree(dev);
+}
 
-	dev = kmalloc(sizeof(*dev),GFP_KERNEL);
-	if (NULL == dev) {
-		printk(KERN_ERR "%s: out of memory\n", __FUNCTION__);
-		return 1;
-	}
+static int sdebug_add_adapter()
+{
+        struct device * dev;
+        int error;
+
+        dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+        if (NULL == dev) {
+                printk(KERN_ERR "%s: out of memory at line %d\n",
+                       __FUNCTION__, __LINE__);
+                return -ENOMEM;
+        }
+        memset(dev, 0, sizeof(*dev));
 
-	memset(dev, 0, sizeof(*dev));
-	dev->bus = &pseudo_lld_bus;
-	dev->parent = &pseudo_primary;
-	sprintf(dev->name, "scsi debug adapter");
-	sprintf(dev->bus_id, "adapter%d", num);
+        dev->bus = &pseudo_lld_bus;
+        dev->parent = &pseudo_primary;
+        dev->release = &sdebug_release_adapter;
+        sprintf(dev->name, "scsi debug adapter");
+        sprintf(dev->bus_id, "adapter%d", scsi_debug_add_host);
 
-	device_register(dev);
+        error = device_register(dev);
 
-	scsi_debug_hosts[num].dev = dev;
+        if (error)
+                kfree(dev);
+        else
+                ++scsi_debug_add_host;
 
-	return 0;
+        return error;
+}
+
+static void sdebug_remove_adapter()
+{
+        struct sdebug_host_info * sdbg_host = NULL;
+
+        spin_lock(&sdebug_host_list_lock);
+        if (!list_empty(&sdebug_host_list))
+                sdbg_host = list_entry(sdebug_host_list.prev,
+                                       struct sdebug_host_info, host_list);
+        spin_unlock(&sdebug_host_list_lock);
+
+        device_unregister(sdbg_host->dev);
+        --scsi_debug_add_host;
+}
+
+static int sdebug_driver_probe(struct device * dev)
+{
+	int k;
+        int error = 0;
+        struct sdebug_host_info *sdbg_host;
+        struct sdebug_dev_info *sdbg_devinfo;
+        struct list_head *lh, *lh_sf;
+        struct Scsi_Host *hpnt;
+
+        sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL);
+        if (NULL == sdbg_host) {
+                printk(KERN_ERR "%s: out of memory at line %d\n",
+                       __FUNCTION__, __LINE__);
+                return -ENOMEM;
+        }
+        memset(sdbg_host, 0, sizeof(*sdbg_host));
+
+        INIT_LIST_HEAD(&sdbg_host->dev_info_list);
+
+        for (k = 0; k < scsi_debug_num_devs; k++) {
+                sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
+                if (NULL == sdbg_devinfo) {
+                        printk(KERN_ERR "%s: out of memory at line %d\n",
+                               __FUNCTION__, __LINE__);
+                        error = -ENOMEM;
+                }
+                memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo));
+                sdbg_devinfo->sdbg_host = sdbg_host;
+                list_add_tail(&sdbg_devinfo->dev_list,
+                              &sdbg_host->dev_info_list);
+        }
+
+        list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
+
+        hpnt = scsi_register(&sdebug_driver_template, 0);
+        if (NULL == hpnt) {
+                printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__);
+                error = -ENODEV;
+                goto clean1;
+        }
+
+        sdbg_host->shost = hpnt;
+        sdbg_host->dev = dev;
+        hpnt->max_lun = scsi_debug_max_luns;
+
+        error = scsi_add_host(hpnt, sdbg_host->dev);
+        if (error) {
+                printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__);
+                error = -ENODEV;
+                goto clean2;
+        }
+
+
+        return 0;
+
+clean2:
+        scsi_unregister(hpnt);
+clean1:
+        list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
+                sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
+                                          dev_list);
+                list_del(&sdbg_devinfo->dev_list);
+                kfree(sdbg_devinfo);
+        }
+
+        kfree(sdbg_host);
+
+        return error;
 }
 
-static void sdebug_remove_adapter(int num)
+static int sdebug_driver_remove(struct device * dev)
 {
-	device_unregister(scsi_debug_hosts[num].dev);
+        struct list_head *lh, *lh_sf;
+        struct sdebug_dev_info *sdbg_devinfo;
+        struct sdebug_host_info *sdbg_host, *found = NULL;
+
+        spin_lock(&sdebug_host_list_lock);
+        list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+                if (sdbg_host->dev == dev) {
+                        list_del(&sdbg_host->host_list);
+                        found = sdbg_host;
+                        break;
+                }
+        }
+        spin_unlock(&sdebug_host_list_lock);
+
+        if (!found) {
+                printk(KERN_ERR "%s: sdebug_host_info not found\n",
+                       __FUNCTION__);
+                return -ENODEV;
+        }
+
+
+        if (scsi_remove_host(sdbg_host->shost)) {
+                printk(KERN_ERR "%s: scsi_remove_host failed\n", __FUNCTION__);
+                return -EBUSY;
+        }
+
+        scsi_unregister(sdbg_host->shost);
+
+        list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
+                sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
+                                          dev_list);
+                list_del(&sdbg_devinfo->dev_list);
+                kfree(sdbg_devinfo);
+        }
+
+        kfree(sdbg_host);
+
+        return 0;
 }
diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
--- a/drivers/scsi/scsi_debug.h	Thu Nov 21 21:34:45 2002
+++ b/drivers/scsi/scsi_debug.h	Sun Mar 16 07:05:12 2003
@@ -2,6 +2,7 @@
 
 #include <linux/types.h>
 
+static int scsi_debug_slave_alloc(struct scsi_device *);
 static int scsi_debug_slave_configure(struct scsi_device *);
 static void scsi_debug_slave_destroy(struct scsi_device *);
 static int scsi_debug_queuecommand(struct scsi_cmnd *, 
@@ -27,8 +28,9 @@
 	.proc_info =		scsi_debug_proc_info,
 	.name =			"SCSI DEBUG",
 	.info =			scsi_debug_info,
+	.slave_alloc =		scsi_debug_slave_alloc,
 	.slave_configure =	scsi_debug_slave_configure,
-	.slave_destroy =		scsi_debug_slave_destroy,
+	.slave_destroy =	scsi_debug_slave_destroy,
 	.ioctl =		scsi_debug_ioctl,
 	.queuecommand =		scsi_debug_queuecommand,
 	.eh_abort_handler =	scsi_debug_abort,
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	Sat Feb 22 08:17:01 2003
+++ b/drivers/scsi/scsi_error.c	Mon Mar 10 22:26:33 2003
@@ -92,10 +92,8 @@
  *
  * Notes:
  *    This should be turned into an inline function.  Each scsi command
- *    has it's own timer, and as it is added to the queue, we set up the
- *    timer.  When the command completes, we cancel the timer.  Pretty
- *    simple, really, especially compared to the old way of handling this
- *    crap.
+ *    has its own timer, and as it is added to the queue, we set up the
+ *    timer.  When the command completes, we cancel the timer.
  **/
 void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
 		    void (*complete)(struct scsi_cmnd *))
@@ -249,6 +247,7 @@
 {
 	if (!SCSI_SENSE_VALID(scmd))
 		return FAILED;
+
 	if (scmd->sense_buffer[2] & 0xe0)
 		return SUCCESS;
 
@@ -515,7 +514,7 @@
 	 * actually did complete normally.
 	 */
 	if (rtn == SUCCESS) {
-		int rtn = scsi_eh_completed_normally(scmd);
+		rtn = scsi_eh_completed_normally(scmd);
 		SCSI_LOG_ERROR_RECOVERY(3,
 			printk("%s: scsi_eh_completed_normally %x\n",
 			       __FUNCTION__, rtn));
@@ -545,20 +544,20 @@
 static int scsi_request_sense(struct scsi_cmnd *scmd)
 {
 	static unsigned char generic_sense[6] =
-	{REQUEST_SENSE, 0, 0, 0, 255, 0};
-	unsigned char scsi_result0[256], *scsi_result = &scsi_result0[0];
+	{REQUEST_SENSE, 0, 0, 0, 254, 0};
+	unsigned char *scsi_result;
 	int saved_result;
 	int rtn;
 
 	memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
 
-	if (scmd->device->host->hostt->unchecked_isa_dma) {
-		scsi_result = kmalloc(512, GFP_ATOMIC | __GFP_DMA);
-		if (unlikely(!scsi_result)) {
-			printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
-					__FUNCTION__);
-			return FAILED;
-		}
+	scsi_result = kmalloc(254, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0);
+
+
+	if (unlikely(!scsi_result)) {
+		printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
+		       __FUNCTION__);
+		return FAILED;
 	}
 
 	/*
@@ -568,11 +567,11 @@
 	 * address (db).  0 is not a valid sense code. 
 	 */
 	memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
-	memset(scsi_result, 0, 256);
+	memset(scsi_result, 0, 254);
 
 	saved_result = scmd->result;
 	scmd->request_buffer = scsi_result;
-	scmd->request_bufflen = 256;
+	scmd->request_bufflen = 254;
 	scmd->use_sg = 0;
 	scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 	scmd->sc_data_direction = SCSI_DATA_READ;
@@ -581,13 +580,12 @@
 	rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
 
 	/* last chance to have valid sense data */
-	if (!SCSI_SENSE_VALID(scmd)) {
+	if(!SCSI_SENSE_VALID(scmd)) {
 		memcpy(scmd->sense_buffer, scmd->request_buffer,
-				sizeof(scmd->sense_buffer));
+		       sizeof(scmd->sense_buffer));
 	}
 
-	if (scsi_result != &scsi_result0[0])
-		kfree(scsi_result);
+	kfree(scsi_result);
 
 	/*
 	 * when we eventually call scsi_finish, we really wish to complete
@@ -599,28 +597,6 @@
 }
 
 /**
- * scsi_eh_retry_cmd - Retry the original command
- * @scmd:	Original failed SCSI cmd.
- *
- * Notes:
- *    This function will *not* return until the command either times out,
- *    or it completes.
- **/
-static int scsi_eh_retry_cmd(struct scsi_cmnd *scmd)
-{
-	int rtn = SUCCESS;
-
-	for (; scmd->retries < scmd->allowed; scmd->retries++) {
-		scsi_setup_cmd_retry(scmd);
-		rtn = scsi_send_eh_cmnd(scmd, scmd->timeout_per_command);
-		if (rtn != NEEDS_RETRY)
-			break;
-	}
-
-	return rtn;
-}
-
-/**
  * scsi_eh_finish_cmd - Handle a cmd that eh is finished with.
  * @scmd:	Original SCSI cmd that eh has finished.
  * @done_q:	Queue for processed commands.
@@ -703,25 +679,14 @@
 		 * upper level.
 		 */
 		if (rtn == SUCCESS)
-			scsi_eh_finish_cmd(scmd, done_q);
-		if (rtn != NEEDS_RETRY)
-			continue;
-
-		/*
-		 * we only come in here if we want to retry a
-		 * command.  the test to see whether the command
-		 * should be retried should be keeping track of the
-		 * number of tries, so we don't end up looping, of
-		 * course.
-		 */
-		scmd->state = NEEDS_RETRY;
-		rtn = scsi_eh_retry_cmd(scmd);
-		if (rtn != SUCCESS)
+			/* we don't want this command reissued, just
+			 * finished with the sense data, so set
+			 * retries to the max allowed to ensure it
+			 * won't get reissued */
+			scmd->retries = scmd->allowed;
+		else if (rtn != NEEDS_RETRY)
 			continue;
 
-		/*
-		 * we eventually hand this one back to the top level.
-		 */
 		scsi_eh_finish_cmd(scmd, done_q);
 	}
 
@@ -1193,12 +1158,12 @@
  * Notes:
  *    This is *only* called when we are examining the status after sending
  *    out the actual data command.  any commands that are queued for error
- *    recovery (i.e. test_unit_ready) do *not* come through here.
+ *    recovery (e.g. test_unit_ready) do *not* come through here.
  *
  *    When this routine returns failed, it means the error handler thread
- *    is woken.  in cases where the error code indicates an error that
+ *    is woken.  In cases where the error code indicates an error that
  *    doesn't require the error handler read (i.e. we don't need to
- *    abort/reset), then this function should return SUCCESS.
+ *    abort/reset), this function should return SUCCESS.
  **/
 int scsi_decide_disposition(struct scsi_cmnd *scmd)
 {
@@ -1214,11 +1179,11 @@
 						  __FUNCTION__));
 		return SUCCESS;
 	}
+
 	/*
 	 * first check the host byte, to see if there is anything in there
 	 * that would indicate what we need to do.
 	 */
-
 	switch (host_byte(scmd->result)) {
 	case DID_PASSTHROUGH:
 		/*
@@ -1296,11 +1261,11 @@
 	/*
 	 * next, check the message byte.
 	 */
-	if (msg_byte(scmd->result) != COMMAND_COMPLETE) {
+	if (msg_byte(scmd->result) != COMMAND_COMPLETE)
 		return FAILED;
-	}
+
 	/*
-	 * now, check the status byte to see if this indicates anything special.
+	 * check the status byte to see if this indicates anything special.
 	 */
 	switch (status_byte(scmd->result)) {
 	case QUEUE_FULL:
@@ -1321,9 +1286,12 @@
 		return SUCCESS;
 	case CHECK_CONDITION:
 		rtn = scsi_check_sense(scmd);
-		if (rtn == NEEDS_RETRY) {
+		if (rtn == NEEDS_RETRY)
 			goto maybe_retry;
-		}
+		/* if rtn == FAILED, we have no sense information;
+		 * returning FAILED will wake the error handler thread
+		 * to collect the sense and redo the decide
+		 * disposition */
 		return rtn;
 	case CONDITION_GOOD:
 	case INTERMEDIATE_GOOD:
@@ -1490,9 +1458,9 @@
 			       struct list_head *work_q,
 			       struct list_head *done_q)
 {
-	if (scsi_eh_bus_device_reset(shost, work_q, done_q))
-		if (scsi_eh_bus_reset(shost, work_q, done_q))
-			if (scsi_eh_host_reset(work_q, done_q))
+	if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
+		if (!scsi_eh_bus_reset(shost, work_q, done_q))
+			if (!scsi_eh_host_reset(work_q, done_q))
 				scsi_eh_offline_sdevs(work_q, done_q);
 }
 
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Sat Feb 22 12:35:33 2003
+++ b/drivers/scsi/scsi_lib.c	Fri Mar 14 16:35:27 2003
@@ -125,7 +125,6 @@
 	 */
 	cmd->state = SCSI_STATE_MLQUEUE;
 	cmd->owner = SCSI_OWNER_MIDLEVEL;
-	cmd->bh_next = NULL;
 
 	/*
 	 * Decrement the counters, since these commands are no longer
@@ -265,7 +264,6 @@
 	cmd->serial_number = 0;
 	cmd->serial_number_at_timeout = 0;
 	cmd->flags = 0;
-	cmd->retries = 0;
 	cmd->abort_reason = 0;
 
 	memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Fri Feb 28 12:45:00 2003
+++ b/drivers/scsi/scsi_scan.c	Mon Mar 10 06:23:23 2003
@@ -385,83 +385,92 @@
 	struct scsi_device *sdev, *device;
 
 	sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC);
-	if (sdev != NULL) {
-		memset(sdev, 0, sizeof(Scsi_Device));
-		sdev->vendor = scsi_null_device_strs;
-		sdev->model = scsi_null_device_strs;
-		sdev->rev = scsi_null_device_strs;
-		sdev->host = shost;
-		sdev->id = id;
-		sdev->lun = lun;
-		sdev->channel = channel;
-		sdev->online = TRUE;
-		INIT_LIST_HEAD(&sdev->siblings);
-		INIT_LIST_HEAD(&sdev->same_target_siblings);
-		INIT_LIST_HEAD(&sdev->cmd_list);
-		spin_lock_init(&sdev->list_lock);
-		/*
-		 * Some low level driver could use device->type
-		 */
-		sdev->type = -1;
-		/*
-		 * Assume that the device will have handshaking problems,
-		 * and then fix this field later if it turns out it
-		 * doesn't
-		 */
-		sdev->borken = 1;
+	if (!sdev)
+		goto out;
 
-		if (!q || *q == NULL) {
-			sdev->request_queue = scsi_alloc_queue(shost);
-			if (!sdev->request_queue)
-				goto out_bail;
-		} else {
-			sdev->request_queue = *q;
-			*q = NULL;
-		}
+	memset(sdev, 0, sizeof(*sdev));
+	sdev->vendor = scsi_null_device_strs;
+	sdev->model = scsi_null_device_strs;
+	sdev->rev = scsi_null_device_strs;
+	sdev->host = shost;
+	sdev->id = id;
+	sdev->lun = lun;
+	sdev->channel = channel;
+	sdev->online = TRUE;
+	INIT_LIST_HEAD(&sdev->siblings);
+	INIT_LIST_HEAD(&sdev->same_target_siblings);
+	INIT_LIST_HEAD(&sdev->cmd_list);
+	spin_lock_init(&sdev->list_lock);
+
+	/*
+	 * Some low level driver could use device->type
+	 */
+	sdev->type = -1;
+
+	/*
+	 * Assume that the device will have handshaking problems,
+	 * and then fix this field later if it turns out it
+	 * doesn't
+	 */
+	sdev->borken = 1;
+
+	if (!q || *q == NULL) {
+		sdev->request_queue = scsi_alloc_queue(shost);
+		if (!sdev->request_queue)
+			goto out_free_dev;
+	} else {
+		sdev->request_queue = *q;
+		*q = NULL;
+	}
 
-		sdev->request_queue->queuedata = sdev;
-		scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
-		init_waitqueue_head(&sdev->scpnt_wait);
-
-		if (shost->hostt->slave_alloc)
-			if (shost->hostt->slave_alloc(sdev)) {
-				goto out_bail;
-			}
-		/*
-		 * If there are any same target siblings, add this to the
-		 * sibling list
-		 */
-		list_for_each_entry(device, &shost->my_devices, siblings) {
-			if(device->id == sdev->id &&
-			   device->channel == sdev->channel) {
-				list_add_tail(&sdev->same_target_siblings,
-					      &device->same_target_siblings);
-				sdev->scsi_level = device->scsi_level;
-				break;
-			}
+	sdev->request_queue->queuedata = sdev;
+	scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+	init_waitqueue_head(&sdev->scpnt_wait);
+
+	if (shost->hostt->slave_alloc) {
+		if (shost->hostt->slave_alloc(sdev))
+			goto out_free_queue;
+	}
+
+	/*
+	 * If there are any same target siblings, add this to the
+	 * sibling list
+	 */
+	list_for_each_entry(device, &shost->my_devices, siblings) {
+		if (device->id == sdev->id &&
+		    device->channel == sdev->channel) {
+			list_add_tail(&sdev->same_target_siblings,
+				      &device->same_target_siblings);
+			sdev->scsi_level = device->scsi_level;
+			break;
 		}
-		/*
-		 * If there wasn't another lun already configured at this
-		 * target, then default this device to SCSI_2 until we
-		 * know better
-		 */
-		if(!sdev->scsi_level)
-			sdev->scsi_level = SCSI_2;
-		/*
-		 * Add it to the end of the shost->my_devices list.
-		 */
-		list_add_tail(&sdev->siblings, &shost->my_devices);
-		return (sdev);
 	}
-out_bail:
-	printk(ALLOC_FAILURE_MSG, __FUNCTION__);
+
+	/*
+	 * If there wasn't another lun already configured at this
+	 * target, then default this device to SCSI_2 until we
+	 * know better
+	 */
+	if (!sdev->scsi_level)
+		sdev->scsi_level = SCSI_2;
+
+	/*
+	 * Add it to the end of the shost->my_devices list.
+	 */
+	list_add_tail(&sdev->siblings, &shost->my_devices);
+	return sdev;
+
+out_free_queue:
 	if (q && sdev->request_queue) {
 		*q = sdev->request_queue;
 		sdev->request_queue = NULL;
 	} else if (sdev->request_queue)
 		scsi_free_queue(sdev->request_queue);
 
+out_free_dev:
 	kfree(sdev);
+out:
+	printk(ALLOC_FAILURE_MSG, __FUNCTION__);
 	return NULL;
 }
 
@@ -960,7 +969,6 @@
 	SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: host %d channel %d"
 	    " id %d lun %d name/id: '%s'\n", sdev->host->host_no,
 	    sdev->channel, sdev->id, sdev->lun, sdev->sdev_driverfs_dev.name));
-	return;
 }
 
 /**
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	Fri Feb 21 15:08:59 2003
+++ b/drivers/scsi/scsi_sysfs.c	Tue Mar  4 01:15:42 2003
@@ -266,6 +266,25 @@
 sdev_rd_attr (rev, "%.4s\n");
 sdev_rw_attr_bit (online);
 
+static ssize_t
+show_rescan_field (struct device *dev, char *buf)
+{
+	return 0; 
+}
+
+static ssize_t
+store_rescan_field (struct device *dev, const char *buf, size_t count) 
+{
+	int ret = ENODEV;
+	struct scsi_device *sdev;
+	sdev = to_scsi_device(dev);
+	if (sdev)
+		ret = scsi_rescan_device(sdev);
+	return ret;
+}
+
+static DEVICE_ATTR(rescan, S_IRUGO | S_IWUSR, show_rescan_field, store_rescan_field)
+
 static struct device_attribute * const sdev_attrs[] = {
 	&dev_attr_device_blocked,
 	&dev_attr_queue_depth,
@@ -276,6 +295,7 @@
 	&dev_attr_model,
 	&dev_attr_rev,
 	&dev_attr_online,
+	&dev_attr_rescan,
 };
 
 /**
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Mon Feb 24 10:18:07 2003
+++ b/drivers/scsi/sd.c	Mon Mar  3 11:19:25 2003
@@ -93,10 +93,12 @@
 
 static int sd_attach(struct scsi_device *);
 static void sd_detach(struct scsi_device *);
+static void sd_rescan(struct scsi_device *);
 static int sd_init_command(struct scsi_cmnd *);
 static int sd_synchronize_cache(struct scsi_disk *, int);
 static int sd_notifier(struct notifier_block *, unsigned long, void *);
-
+static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
+		 struct scsi_request *SRpnt, unsigned char *buffer);
 static struct notifier_block sd_notifier_block = {sd_notifier, NULL, 0}; 
 
 static struct Scsi_Device_Template sd_template = {
@@ -106,6 +108,7 @@
 	.scsi_type	= TYPE_DISK,
 	.attach		= sd_attach,
 	.detach		= sd_detach,
+	.rescan		= sd_rescan,
 	.init_command	= sd_init_command,
 	.scsi_driverfs_driver = {
 		.name   = "sd",
@@ -629,6 +632,38 @@
 	return 1;
 }
 
+static void sd_rescan(struct scsi_device * sdp)
+{
+	unsigned char *buffer;
+	struct scsi_disk *sdkp = sd_find_by_sdev(sdp);
+	struct gendisk *gd;
+	struct scsi_request *SRpnt;
+
+	if (!sdkp || sdp->online == FALSE || !sdkp->media_present)
+		return;
+		
+	gd = sdkp->disk;
+	
+	SCSI_LOG_HLQUEUE(3, printk("sd_rescan: disk=%s\n", gd->disk_name));
+	
+	SRpnt = scsi_allocate_request(sdp);
+	if (!SRpnt) {
+		printk(KERN_WARNING "(sd_rescan:) Request allocation "
+		       "failure.\n");
+		return;
+	}
+
+	if (sdkp->device->host->unchecked_isa_dma)
+		buffer = kmalloc(512, GFP_DMA);
+	else
+		buffer = kmalloc(512, GFP_KERNEL);
+
+    	sd_read_capacity(sdkp, gd->disk_name, SRpnt, buffer);
+	set_capacity(gd, sdkp->capacity);	
+	scsi_release_request(SRpnt);
+	kfree(buffer);
+}
+
 static int sd_revalidate_disk(struct gendisk *disk)
 {
 	struct scsi_disk *sdkp = scsi_disk(disk);
@@ -1197,7 +1232,7 @@
 		return;
 	}
 
-	buffer = kmalloc(512, GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
 		printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation "
 		       "failure.\n");
@@ -1389,14 +1424,9 @@
 
 	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
 
-	for (i = 0; i < SD_MAJORS; i++) {
-		if (register_blkdev(sd_major(i), "sd", &sd_fops))
-			printk(KERN_NOTICE
-			       "Unable to get major %d for SCSI disk\n",
-			       sd_major(i));
-		else
+	for (i = 0; i < SD_MAJORS; i++)
+		if (register_blkdev(sd_major(i), "sd") == 0)
 			majors++;
-	}
 
 	if (!majors)
 		return -ENODEV;
@@ -1409,7 +1439,7 @@
 }
 
 /**
- *	exit_sd - exit point for this driver (when it is	a module).
+ *	exit_sd - exit point for this driver (when it is a module).
  *
  *	Note: this function unregisters this driver from the scsi mid-level.
  **/
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Fri Feb 21 10:16:35 2003
+++ b/drivers/scsi/sg.c	Sat Mar  8 04:41:31 2003
@@ -18,10 +18,8 @@
  *
  */
 #include <linux/config.h>
-#ifdef CONFIG_PROC_FS
-static char *sg_version_str = "Version: 3.5.27 (20030130)";
-#endif
-static int sg_version_num = 30527;	/* 2 digits for each component */
+static char *sg_version_str = "3.5.28 [20030308]";
+static int sg_version_num = 30528;	/* 2 digits for each component */
 /*
  *  D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
  *      - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
@@ -56,6 +54,7 @@
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
+#include <linux/moduleparam.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -1327,27 +1326,6 @@
 	.fasync = sg_fasync,
 };
 
-#ifndef MODULE
-static int __init
-sg_def_reserved_size_setup(char *str)
-{
-	int tmp;
-
-	if (get_option(&str, &tmp) == 1) {
-		def_reserved_size = tmp;
-		if (tmp >= 0)
-			sg_big_buff = tmp;
-		return 1;
-	} else {
-		printk(KERN_WARNING "sg_def_reserved_size : usage "
-		       "sg_def_reserved_size=n (n could be 65536, 131072 or 262144)\n");
-		return 0;
-	}
-}
-
-__setup("sg_def_reserved_size=", sg_def_reserved_size_setup);
-#endif
-
 /* Driverfs file support */
 static ssize_t
 sg_device_kdev_read(struct device *driverfs_dev, char *page)
@@ -1564,16 +1542,77 @@
 		scsi_sleep(2);	/* dirty detach so delay device destruction */
 }
 
+/* Set 'perm' (4th argument) to 0 to disable module_param's definition
+ * of sysfs parameters (which module_param doesn't yet support).
+ * Sysfs parameters defined explicitly below.
+ */
+module_param_named(def_reserved_size, def_reserved_size, int, 0);
+module_param_named(allow_dio, sg_allow_dio, int, 0);
+
 MODULE_AUTHOR("Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI generic (sg) driver");
-
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
-#endif
 
-MODULE_PARM(def_reserved_size, "i");
 MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
 
+static ssize_t sg_allow_dio_show(struct device_driver * ddp, char * buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", sg_allow_dio);
+}
+static ssize_t sg_allow_dio_store(struct device_driver * ddp,
+				  const char * buf, size_t count)
+{
+	if (1 == sscanf(buf, "%d", &sg_allow_dio)) {
+		sg_allow_dio = sg_allow_dio ? 1 : 0;
+		return count;
+	}
+	return -EINVAL;
+}
+DRIVER_ATTR(allow_dio, S_IRUGO | S_IWUSR, sg_allow_dio_show, 
+	    sg_allow_dio_store)
+
+static ssize_t sg_def_reserved_show(struct device_driver * ddp, char * buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", sg_big_buff);
+}
+static ssize_t sg_def_reserved_store(struct device_driver * ddp,
+				     const char * buf, size_t count)
+{
+	if (1 == sscanf(buf, "%d", &def_reserved_size)) {
+		if (def_reserved_size >= 0) {
+			sg_big_buff = def_reserved_size;
+			return count;
+		}
+	}
+	return -EINVAL;
+}
+DRIVER_ATTR(def_reserved_size, S_IRUGO | S_IWUSR, sg_def_reserved_show, 
+	    sg_def_reserved_store)
+
+static ssize_t sg_version_show(struct device_driver * ddp, char * buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", sg_version_str);
+}
+DRIVER_ATTR(version, S_IRUGO, sg_version_show, NULL)
+
+static void do_create_driverfs_files(void)
+{
+	struct device_driver * driverfs = &sg_template.scsi_driverfs_driver;
+
+	driver_create_file(driverfs, &driver_attr_allow_dio);
+	driver_create_file(driverfs, &driver_attr_def_reserved_size);
+	driver_create_file(driverfs, &driver_attr_version);
+}
+
+static void do_remove_driverfs_files(void)
+{
+	struct device_driver * driverfs = &sg_template.scsi_driverfs_driver;
+
+	driver_remove_file(driverfs, &driver_attr_version);
+	driver_remove_file(driverfs, &driver_attr_def_reserved_size);
+	driver_remove_file(driverfs, &driver_attr_allow_dio);
+}
+
 static int __init
 init_sg(void)
 {
@@ -1591,12 +1630,14 @@
 #ifdef CONFIG_PROC_FS
 	sg_proc_init();
 #endif				/* CONFIG_PROC_FS */
+	do_create_driverfs_files();
 	return 0;
 }
 
 static void __exit
 exit_sg(void)
 {
+	do_remove_driverfs_files();
 #ifdef CONFIG_PROC_FS
 	sg_proc_cleanup();
 #endif				/* CONFIG_PROC_FS */
@@ -2656,10 +2697,6 @@
 static struct proc_dir_entry *sg_proc_sgp = NULL;
 
 static char sg_proc_sg_dirname[] = "sg";
-static const char *sg_proc_leaf_names[] = { "allow_dio", "def_reserved_size",
-	"debug", "devices", "device_hdr", "device_strs",
-	"hosts", "host_hdr", "host_strs", "version"
-};
 
 static int sg_proc_adio_read(char *buffer, char **start, off_t offset,
 			     int size, int *eof, void *data);
@@ -2693,13 +2730,21 @@
 				int size, int *eof, void *data);
 static int sg_proc_version_info(char *buffer, int *len, off_t * begin,
 				off_t offset, int size);
-static read_proc_t *sg_proc_leaf_reads[] = {
-	sg_proc_adio_read, sg_proc_dressz_read, sg_proc_debug_read,
-	sg_proc_dev_read, sg_proc_devhdr_read, sg_proc_devstrs_read,
-	sg_proc_version_read
+
+struct sg_proc_leaf {
+	const char * name;
+	read_proc_t * rf;
+	write_proc_t * wf;
 };
-static write_proc_t *sg_proc_leaf_writes[] = {
-	sg_proc_adio_write, sg_proc_dressz_write, 0, 0, 0, 0, 0, 0, 0, 0
+
+static struct sg_proc_leaf sg_proc_leaf_arr[] = {
+	{"allow_dio", sg_proc_adio_read, sg_proc_adio_write},
+	{"def_reserved_size", sg_proc_dressz_read, sg_proc_dressz_write},
+	{"debug", sg_proc_debug_read, NULL},
+	{"devices", sg_proc_dev_read, NULL},
+	{"device_hdr", sg_proc_devhdr_read, NULL},
+	{"device_strs", sg_proc_devstrs_read, NULL},
+	{"version", sg_proc_version_read, NULL}
 };
 
 #define PRINT_PROC(fmt,args...)                                 \
@@ -2729,9 +2774,10 @@
 sg_proc_init()
 {
 	int k, mask;
-	int leaves =
-	    sizeof (sg_proc_leaf_names) / sizeof (sg_proc_leaf_names[0]);
+	int num_leaves =
+	    sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]);
 	struct proc_dir_entry *pdep;
+	struct sg_proc_leaf * leaf;
 
 	if (!proc_scsi)
 		return 1;
@@ -2739,14 +2785,14 @@
 					S_IFDIR | S_IRUGO | S_IXUGO, proc_scsi);
 	if (!sg_proc_sgp)
 		return 1;
-	for (k = 0; k < leaves; ++k) {
-		mask = sg_proc_leaf_writes[k] ? S_IRUGO | S_IWUSR : S_IRUGO;
-		pdep =
-		    create_proc_entry(sg_proc_leaf_names[k], mask, sg_proc_sgp);
+	for (k = 0; k < num_leaves; ++k) {
+		leaf = &sg_proc_leaf_arr[k];
+		mask = leaf->wf ? S_IRUGO | S_IWUSR : S_IRUGO;
+		pdep = create_proc_entry(leaf->name, mask, sg_proc_sgp);
 		if (pdep) {
-			pdep->read_proc = sg_proc_leaf_reads[k];
-			if (sg_proc_leaf_writes[k])
-				pdep->write_proc = sg_proc_leaf_writes[k];
+			pdep->read_proc = leaf->rf;
+			if (leaf->wf)
+				pdep->write_proc = leaf->wf;
 		}
 	}
 	return 0;
@@ -2756,13 +2802,13 @@
 sg_proc_cleanup()
 {
 	int k;
-	int leaves =
-	    sizeof (sg_proc_leaf_names) / sizeof (sg_proc_leaf_names[0]);
+	int num_leaves =
+	    sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]);
 
 	if ((!proc_scsi) || (!sg_proc_sgp))
 		return;
-	for (k = 0; k < leaves; ++k)
-		remove_proc_entry(sg_proc_leaf_names[k], sg_proc_sgp);
+	for (k = 0; k < num_leaves; ++k)
+		remove_proc_entry(sg_proc_leaf_arr[k].name, sg_proc_sgp);
 	remove_proc_entry(sg_proc_sg_dirname, proc_scsi);
 }
 
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Mon Feb 24 12:16:14 2003
+++ b/drivers/scsi/sr.c	Sun Mar  9 06:48:19 2003
@@ -604,7 +604,7 @@
 	struct scsi_request *SRpnt = NULL;
 	request_queue_t *queue;
 
-	buffer = kmalloc(512, GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		goto Enomem;
 	SRpnt = scsi_allocate_request(cd->device);
@@ -698,7 +698,7 @@
 	goto out;
 }
 
-void get_capabilities(struct scsi_cd *cd)
+static void get_capabilities(struct scsi_cd *cd)
 {
 	struct cdrom_generic_command cgc;
 	unsigned char *buffer;
@@ -716,9 +716,8 @@
 		""
 	};
 
-	buffer = kmalloc(512, GFP_DMA);
-	if (!buffer)
-	{
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
 		printk(KERN_ERR "sr: out of memory.\n");
 		return;
 	}
@@ -835,7 +834,7 @@
 {
 	int rc;
 
-	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr", &sr_bdops);
+	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr");
 	if (rc)
 		return rc;
 	return scsi_register_device(&sr_template);
diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
--- a/drivers/scsi/sym53c8xx.c	Wed Feb 26 19:03:06 2003
+++ b/drivers/scsi/sym53c8xx.c	Wed Mar  5 23:02:24 2003
@@ -112,8 +112,8 @@
 #include <asm/spinlock.h>
 #endif
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/string.h>
@@ -7214,7 +7214,6 @@
 **==========================================================
 */
 
-#ifdef MODULE
 static int ncr_detach(ncb_p np)
 {
 	int i;
@@ -7260,7 +7259,6 @@
 
 	return 1;
 }
-#endif
 
 /*==========================================================
 **
@@ -12958,6 +12956,7 @@
 		}
 		if (i != count)	/* Ignore this device if we already have it */
 			continue;
+		pci_set_master(pcidev);
 		devp = &devtbl[count];
 		devp->host_id = driver_setup.host_id;
 		devp->attach_done = 0;
@@ -13798,7 +13797,6 @@
 }
 
 
-#ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *host)
 {
 #ifdef DEBUG_SYM53C8XX
@@ -13808,7 +13806,6 @@
 
      return 1;
 }
-#endif
 
 
 /*
diff -Nru a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h
--- a/drivers/scsi/sym53c8xx.h	Tue Dec 10 12:28:33 2002
+++ b/drivers/scsi/sym53c8xx.h	Mon Feb 17 12:02:12 2003
@@ -75,17 +75,11 @@
 int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int sym53c8xx_reset(Scsi_Cmnd *, unsigned int);
 int sym53c8xx_slave_configure(Scsi_Device *);
-
-#ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *);
-#else
-#define sym53c8xx_release NULL
-#endif
-
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
 
-#define SYM53C8XX {     .name           = "",			\
+#define SYM53C8XX {     .name           = "sym53c8xx",		\
 			.detect         = sym53c8xx_detect,	\
 			.release        = sym53c8xx_release,	\
 			.info           = sym53c8xx_info, 	\
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c	Mon Feb 24 07:25:23 2003
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c	Sat Mar  8 14:50:22 2003
@@ -221,7 +221,7 @@
  */
 static void sym_soft_reset (hcb_p np)
 {
-	u_char istat;
+	u_char istat = 0;
 	int i;
 
 	if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN))
diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
--- a/drivers/scsi/zalon.c	Sat Jan  4 12:04:10 2003
+++ b/drivers/scsi/zalon.c	Mon Feb 17 12:02:12 2003
@@ -151,7 +151,6 @@
 	return (hosts_used != 0);
 }
 
-#ifdef MODULE
 extern int ncr53c8xx_release(struct Scsi_Host *host);
 
 int zalon7xx_release(struct Scsi_Host *host)
@@ -160,4 +159,3 @@
 	unregister_parisc_driver(&zalon_driver);
 	return 1;
 }
-#endif
diff -Nru a/drivers/scsi/zalon.h b/drivers/scsi/zalon.h
--- a/drivers/scsi/zalon.h	Sat Jan  4 12:04:11 2003
+++ b/drivers/scsi/zalon.h	Mon Feb 17 12:02:12 2003
@@ -15,12 +15,7 @@
 int zalon7xx_detect(Scsi_Host_Template *tpnt);
 const char *ncr53c8xx_info(struct Scsi_Host *host);
 int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-
-#ifdef MODULE
 int zalon7xx_release(struct Scsi_Host *);
-#else
-#define zalon7xx_release NULL
-#endif
 
 #define GSC_SCSI_ZALON_OFFSET 0x800
 
diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c
--- a/drivers/serial/21285.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/21285.c	Thu Mar  6 09:27:42 2003
@@ -501,11 +501,12 @@
 	.index		= -1,
 };
 
-void __init rs285_console_init(void)
+static void __init rs285_console_init(void)
 {
 	serial21285_setup_ports();
 	register_console(&serial21285_console);
 }
+console_initcall(rs285_console_init);
 
 #define SERIAL_21285_CONSOLE	&serial21285_console
 #else
diff -Nru a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
--- a/drivers/serial/68328serial.c	Sun Nov 17 23:09:28 2002
+++ b/drivers/serial/68328serial.c	Fri Feb 14 15:26:21 2003
@@ -1691,8 +1691,9 @@
 };
 
 
-void m68328_console_init(void)
+static void __init m68328_console_init(void)
 {
 	register_console(&m68328_driver);
 }
 
+console_initcall(m68328_console_init);
diff -Nru a/drivers/serial/68328serial.h b/drivers/serial/68328serial.h
--- a/drivers/serial/68328serial.h	Mon Feb 24 12:16:14 2003
+++ b/drivers/serial/68328serial.h	Mon Mar 10 16:26:26 2003
@@ -161,8 +161,8 @@
 	int			xmit_head;
 	int			xmit_tail;
 	int			xmit_cnt;
-	struct workqueue	tqueue;
-	struct workqueue	tqueue_hangup;
+	struct work_struct	tqueue;
+	struct work_struct	tqueue_hangup;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
 	wait_queue_head_t	open_wait;
diff -Nru a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
--- a/drivers/serial/68360serial.c	Mon Feb  3 05:47:46 2003
+++ b/drivers/serial/68360serial.c	Mon Mar 10 16:26:26 2003
@@ -74,8 +74,6 @@
 static char *serial_name = "CPM UART driver";
 static char *serial_version = "0.03";
 
-static DECLARE_TASK_QUEUE(tq_serial);
-
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
 int serial_console_setup(struct console *co, char *options);
@@ -243,7 +241,7 @@
 	int			magic;
 	int			flags;
 
-	struct serial_state		*state;
+	struct serial_state	*state;
  	/* struct serial_struct	*state; */
  	/* struct async_struct	*state; */
 	
@@ -261,12 +259,10 @@
 	int			blocked_open; /* # of blocked opens */
 	long			session; /* Session of opening process */
 	long			pgrp; /* pgrp of opening process */
-	struct tq_struct	tqueue;
-	struct tq_struct	tqueue_hangup;
+	struct work_struct	tqueue;
+	struct work_struct	tqueue_hangup;
  	wait_queue_head_t	open_wait; 
  	wait_queue_head_t	close_wait; 
-/*	struct wait_queue     *open_wait; */
-/*	struct wait_queue	   *close_wait;i */
 
 	
 /* CPM Buffer Descriptor pointers.
@@ -324,7 +320,7 @@
 #elif defined(CONFIG_CONSOLE_115200)
   #define CONSOLE_BAUDRATE 115200
 #else
-  #warn "console baud rate undefined"
+  #warning "console baud rate undefined"
   #define CONSOLE_BAUDRATE 9600
 #endif
 
@@ -405,18 +401,6 @@
  * -----------------------------------------------------------------------
  */
 
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static _INLINE_ void rs_sched_event(ser_info_t *info,
-				  int event)
-{
-	info->event |= 1 << event;
-	queue_task(&info->tqueue, &tq_serial);
-	mark_bh(SERIAL_BH);
-}
-
 static _INLINE_ void receive_chars(ser_info_t *info)
 {
 	struct tty_struct *tty = info->tty;
@@ -556,7 +540,7 @@
 
 	info->rx_cur = (QUICC_BD *)bdp;
 
-	queue_task(&tty->flip.tqueue, &tq_timer);
+	schedule_work(&tty->flip.work);
 }
 
 static _INLINE_ void receive_break(ser_info_t *info)
@@ -573,7 +557,7 @@
 	*(tty->flip.char_buf_ptr++) = 0;
 	tty->flip.count++;
 
-	queue_task(&tty->flip.tqueue, &tq_timer);
+	schedule_work(&tty->flip.work);
 }
 
 static _INLINE_ void transmit_chars(ser_info_t *info)
@@ -581,7 +565,7 @@
 
 	if ((info->flags & TX_WAKEUP) ||
 	    (info->tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) {
-		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+		schedule_work(&info->tqueue);
 	}
 
 #ifdef SERIAL_DEBUG_INTR
@@ -717,19 +701,6 @@
  * -------------------------------------------------------------------
  */
 
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using rs_sched_event(), and they get done here.
- */
-static void do_serial_bh(void)
-{
-	run_task_queue(&tq_serial);
-}
 
 static void do_softint(void *private_)
 {
@@ -749,8 +720,6 @@
 }
 
 
-
-
 /*
  * This routine is called from the scheduler tqueue when the interrupt
  * routine has signalled that a hangup has occurred.  The path of
@@ -772,11 +741,6 @@
 	tty_hangup(tty);
 }
 
-/*static void rs_360_timer(void)
-{
-	printk("rs_360_timer\n");
-}*/
-
 
 static int startup(ser_info_t *info)
 {
@@ -1841,7 +1805,7 @@
 	 */
 	char_time = 1;
 	if (timeout)
-		char_time = min(char_time, timeout);
+		char_time = min(char_time, (unsigned long)timeout);
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
 	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
 	printk("jiff=%lu...", jiffies);
@@ -2078,7 +2042,7 @@
 	ser_info_t	*info;
 	int 		retval, line;
 
-	line = MINOR(tty->device) - tty->driver.minor_start;
+	line = minor(tty->device) - tty->driver.minor_start;
 	if ((line < 0) || (line >= NR_PORTS))
 		return -ENODEV;
 	retval = get_async_struct(line, &info);
@@ -2612,8 +2576,6 @@
 	volatile	struct uart_pram	*sup;
 	/* volatile	immap_t		*immap; */
 	
-	init_bh(SERIAL_BH, do_serial_bh);
-
 	show_serial_version();
 
 	/* Initialize the tty_driver structure */
@@ -2763,17 +2725,14 @@
 		/* info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); */
 		info = &quicc_ser_info[i];
 		if (info) {
-			/* __clear_user(info,sizeof(ser_info_t)); */
 			memset (info, 0, sizeof(ser_info_t));
-			init_waitqueue_head(&info->open_wait);
-			init_waitqueue_head(&info->close_wait);
 			info->magic = SERIAL_MAGIC;
-			info->flags = state->flags;
-			info->tqueue.routine = do_softint;
-			info->tqueue.data = info;
-			info->tqueue_hangup.routine = do_serial_hangup;
-			info->tqueue_hangup.data = info;
 			info->line = i;
+			info->flags = state->flags;
+			INIT_WORK(&info->tqueue, do_softint, info);
+			INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
+			init_waitqueue_head(&info->open_wait);
+			init_waitqueue_head(&info->close_wait);
 			info->state = state;
 			state->info = (struct async_struct *)info;
 
@@ -2818,15 +2777,6 @@
 				*(uint *)_periph_base = sipex_mode_bits;
 				/* printk ("sipex bits = 0x%08x\n", sipex_mode_bits); */
 #endif
-
-				scp = &pquicc->scc_regs[idx];
-				sup = &pquicc->pram[info->state->port].scc.pscc.u;
-				sup->rbase = dp_addr;
-			}
-			else {
-				sp = &cp->smc_regs[idx];
-				up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
-				up->rbase = dp_addr;
 			}
 
 			dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * TX_NUM_FIFO);
@@ -2856,6 +2806,9 @@
 			bdp->status = (BD_SC_WRAP | BD_SC_INTRPT);
 
 			if (info->state->smc_scc_num & NUM_IS_SCC) {
+				scp = &pquicc->scc_regs[idx];
+				sup = &pquicc->pram[info->state->port].scc.pscc.u;
+				sup->rbase = dp_addr;
 				sup->tbase = dp_addr;
 
 				/* Set up the uart parameters in the
@@ -2919,6 +2872,8 @@
 				/* Configure SMCs Tx/Rx instead of port B
 				 * parallel I/O.
 				 */
+				up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
+				up->rbase = dp_addr;
 
 				iobits = 0xc0 << (idx * 4);
 				cp->pip_pbpar |= iobits;
@@ -2964,6 +2919,7 @@
 				/* Set UART mode, 8 bit, no parity, one stop.
 				 * Enable receive and transmit.
 				 */
+				sp = &cp->smc_regs[idx];
 				sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
 
 				/* Disable all interrupts and clear all pending
@@ -3008,8 +2964,7 @@
 int serial_console_setup( struct console *co, char *options)
 {
 	struct		serial_state	*ser;
-	uint       mem_addr, dp_addr, bidx, idx, iobits;
-	int i;
+	uint		mem_addr, dp_addr, bidx, idx, iobits;
 	ushort		chan;
 	QUICC_BD	*bdp;
 	volatile	QUICC			*cp;
@@ -3038,18 +2993,11 @@
 
 	idx = PORT_NUM(ser->smc_scc_num);
 	if (ser->smc_scc_num & NUM_IS_SCC) {
-		scp = &cp->scc_regs[idx];
-		/* sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; */
-		sup = &pquicc->pram[ser->port].scc.pscc.u;
 
 		/* TODO: need to set up SCC pin assignment etc. here */
 		
 	}
 	else {
-		sp = &cp->smc_regs[idx];
-		/* up = (smc_uart_t *)&cp->cp_dparam[ser->port]; */
-		up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u;
-
 		iobits = 0xc0 << (idx * 4);
 		cp->pip_pbpar |= iobits;
 		cp->pip_pbdir &= ~iobits;
@@ -3096,6 +3044,9 @@
 	/* Set up the uart parameters in the parameter ram.
 	 */
 	if (ser->smc_scc_num & NUM_IS_SCC) {
+		scp = &cp->scc_regs[idx];
+		/* sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; */
+		sup = &pquicc->pram[ser->port].scc.pscc.u;
 
 		sup->rbase = dp_addr;
 		sup->tbase = dp_addr + sizeof(QUICC_BD);
@@ -3153,6 +3104,9 @@
 
 	}
 	else {
+		/* up = (smc_uart_t *)&cp->cp_dparam[ser->port]; */
+		up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u;
+
 		up->rbase = dp_addr;	/* Base of receive buffer desc. */
 		up->tbase = dp_addr+sizeof(QUICC_BD);	/* Base of xmt buffer desc. */
 		up->rfcr = SMC_EB;
@@ -3167,12 +3121,12 @@
 		*/
 		chan = smc_chan_map[idx];
 		cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG;
-		printk("");
 		while (cp->cp_cr & CPM_CR_FLG);
 
 		/* Set UART mode, 8 bit, no parity, one stop.
 		 * Enable receive and transmit.
 		 */
+		sp = &cp->smc_regs[idx];
 		sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
 
 		/* And finally, enable Rx and Tx.
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c	Tue Feb 25 18:39:37 2003
+++ b/drivers/serial/8250.c	Sat Mar 15 17:15:06 2003
@@ -93,13 +93,15 @@
 #ifdef CONFIG_SERIAL_8250_MULTIPORT
 #define CONFIG_SERIAL_MULTIPORT 1
 #endif
+#ifdef CONFIG_SERIAL_8250_MANY_PORTS
+#define CONFIG_SERIAL_MANY_PORTS 1
+#endif
 
 /*
  * HUB6 is always on.  This will be removed once the header
  * files have been cleaned.
  */
 #define CONFIG_HUB6 1
-#define CONFIG_SERIAL_MANY_PORTS 1
 
 #include <asm/serial.h>
 
@@ -1982,11 +1984,13 @@
 	.index		= -1,
 };
 
-void __init serial8250_console_init(void)
+static int __init serial8250_console_init(void)
 {
 	serial8250_isa_init_ports();
 	register_console(&serial8250_console);
+	return 0;
 }
+console_initcall(serial8250_console_init);
 
 #define SERIAL8250_CONSOLE	&serial8250_console
 #else
@@ -2093,6 +2097,28 @@
 	}
 }
 
+/**
+ *	serial8250_suspend_port - suspend one serial port
+ *	@line: serial line number
+ *
+ *	Suspend one serial port.
+ */
+void serial8250_suspend_port(int line, u32 level)
+{
+	uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port, level);
+}
+
+/**
+ *	serial8250_resume_port - resume one serial port
+ *	@line: serial line number
+ *
+ *	Resume one serial port.
+ */
+void serial8250_resume_port(int line, u32 level)
+{
+	uart_resume_port(&serial8250_reg, &serial8250_ports[line].port, level);
+}
+
 static int __init serial8250_init(void)
 {
 	int ret, i;
@@ -2126,6 +2152,8 @@
 EXPORT_SYMBOL(register_serial);
 EXPORT_SYMBOL(unregister_serial);
 EXPORT_SYMBOL(serial8250_get_irq_map);
+EXPORT_SYMBOL(serial8250_suspend_port);
+EXPORT_SYMBOL(serial8250_resume_port);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $");
diff -Nru a/drivers/serial/8250.h b/drivers/serial/8250.h
--- a/drivers/serial/8250.h	Sat Oct  5 15:29:37 2002
+++ b/drivers/serial/8250.h	Tue Mar 11 14:24:03 2003
@@ -27,6 +27,8 @@
 int serial8250_register_probe(struct serial8250_probe *probe);
 void serial8250_unregister_probe(struct serial8250_probe *probe);
 void serial8250_get_irq_map(unsigned int *map);
+void serial8250_suspend_port(int line, u32 level);
+void serial8250_resume_port(int line, u32 level);
 
 struct old_serial_port {
 	unsigned int uart;
diff -Nru a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c
--- a/drivers/serial/8250_acorn.c	Sun Nov 24 15:14:23 2002
+++ b/drivers/serial/8250_acorn.c	Sat Mar  8 11:24:57 2003
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/serial/acorn.c
  *
- *  Copyright (C) 1996-2002 Russell King.
+ *  Copyright (C) 1996-2003 Russell King.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -9,6 +9,8 @@
  */
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
@@ -16,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 
+#include <asm/io.h>
 #include <asm/ecard.h>
 #include <asm/string.h>
 
@@ -24,36 +27,41 @@
 struct serial_card_type {
 	unsigned int	num_ports;
 	unsigned int	baud_base;
-	int		type;
-	int		speed;
-	int		offset[MAX_PORTS];
+	unsigned int	type;
+	unsigned int	offset[MAX_PORTS];
 };
 
 struct serial_card_info {
 	unsigned int	num_ports;
 	int		ports[MAX_PORTS];
-	unsigned long	base[MAX_PORTS];
 };
 
-static inline int serial_register_onedev(unsigned long port, int irq, unsigned int baud_base)
+static inline int
+serial_register_onedev(unsigned long baddr, void *vaddr, int irq, unsigned int baud_base)
 {
 	struct serial_struct req;
 
 	memset(&req, 0, sizeof(req));
-	req.baud_base = baud_base;
-	req.irq = irq;
-	req.port = port;
-	req.flags = 0;
+	req.irq			= irq;
+	req.flags		= UPF_AUTOPROBE | UPF_RESOURCES |
+				  UPF_SHARE_IRQ;
+	req.baud_base		= baud_base;
+	req.io_type		= UPIO_MEM;
+	req.iomem_base		= vaddr;
+	req.iomem_reg_shift	= 2;
+	req.iomap_base		= baddr;
 
 	return register_serial(&req);
 }
 
-static int __devinit serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int __devinit
+serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
 	struct serial_card_info *info;
 	struct serial_card_type *type = id->data;
-	unsigned long cardaddr, address;
-	int port;
+	unsigned long bus_addr;
+	unsigned char *virt_addr;
+	unsigned int port;
 
 	info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
 	if (!info)
@@ -64,20 +72,19 @@
 
 	ecard_set_drvdata(ec, info);
 
-	cardaddr = ecard_address(ec, type->type, type->speed);
+	bus_addr = ec->resource[type->type].start;
+	virt_addr = ioremap(bus_addr, ec->resource[type->type].end - bus_addr + 1);
+	if (!virt_addr) {
+		kfree(info);
+		return -ENOMEM;
+	}
 
 	for (port = 0; port < info->num_ports; port ++) {
-		address = cardaddr + type->offset[port];
-
-		info->ports[port] = -1;
-		info->base[port] = address;
+		unsigned long baddr = bus_addr + type->offset[port];
+		unsigned char *vaddr = virt_addr + type->offset[port];
 
-		if (!request_region(address, 8, "acornserial"))
-			continue;
-
-		info->ports[port] = serial_register_onedev(address, ec->irq, type->baud_base);
-		if (info->ports[port] < 0)
-			break;
+		info->ports[port] = serial_register_onedev(baddr, vaddr,
+						ec->irq, type->baud_base);
 	}
 
 	return 0;
@@ -90,12 +97,9 @@
 
 	ecard_set_drvdata(ec, NULL);
 
-	for (i = 0; i < info->num_ports; i++) {
-		if (info->ports[i] > 0) {
+	for (i = 0; i < info->num_ports; i++)
+		if (info->ports[i] > 0)
 			unregister_serial(info->ports[i]);
-			release_region(info->base[i], 8);
-		}
-	}
 
 	kfree(info);
 }
@@ -103,17 +107,15 @@
 static struct serial_card_type atomwide_type = {
 	.num_ports	= 3,
 	.baud_base	= 7372800 / 16,
-	.type		= ECARD_IOC,
-	.speed		= ECARD_SLOW,
-	.offset		= { 0xa00, 0x900, 0x800 },
+	.type		= ECARD_RES_IOCSLOW,
+	.offset		= { 0x2800, 0x2400, 0x2000 },
 };
 
 static struct serial_card_type serport_type = {
 	.num_ports	= 2,
 	.baud_base	= 3686400 / 16,
-	.type		= ECARD_IOC,
-	.speed		= ECARD_SLOW,
-	.offset		= { 0x800, 0x808 },
+	.type		= ECARD_RES_IOCSLOW,
+	.offset		= { 0x2000, 0x2020 },
 };
 
 static const struct ecard_id serial_cids[] = {
@@ -127,7 +129,8 @@
 	.remove 	= __devexit_p(serial_card_remove),
 	.id_table	= serial_cids,
 	.drv = {
-		.name	= "acornserial",
+		.devclass	= &tty_devclass,
+		.name		= "8250_acorn",
 	},
 };
 
@@ -142,6 +145,7 @@
 }
 
 MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver");
 MODULE_LICENSE("GPL");
 
 module_init(serial_card_init);
diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
--- a/drivers/serial/8250_pci.c	Wed Feb 19 12:18:54 2003
+++ b/drivers/serial/8250_pci.c	Tue Mar 11 14:24:03 2003
@@ -20,8 +20,9 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/tty.h>
 #include <linux/serial.h>
-#include <linux/serialP.h>
+#include <linux/serial_core.h>
 
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
@@ -30,174 +31,213 @@
 
 #include "8250.h"
 
+/*
+ * Definitions for PCI support.
+ */
+#define FL_BASE_MASK		0x0007
+#define FL_BASE0		0x0000
+#define FL_BASE1		0x0001
+#define FL_BASE2		0x0002
+#define FL_BASE3		0x0003
+#define FL_BASE4		0x0004
+#define FL_GET_BASE(x)		(x & FL_BASE_MASK)
+
+#define FL_IRQ_MASK		(0x0007 << 4)
+#define FL_IRQBASE0		(0x0000 << 4)
+#define FL_IRQBASE1		(0x0001 << 4)
+#define FL_IRQBASE2		(0x0002 << 4)
+#define FL_IRQBASE3		(0x0003 << 4)
+#define FL_IRQBASE4		(0x0004 << 4)
+#define FL_GET_IRQBASE(x)	((x & FL_IRQ_MASK) >> 4)
+
+/* Use successive BARs (PCI base address registers),
+   else use offset into some specified BAR */
+#define FL_BASE_BARS		0x0008
 
-#ifndef IS_PCI_REGION_IOPORT
-#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
-				      IORESOURCE_IO)
-#endif
-#ifndef IS_PCI_REGION_IOMEM
-#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
-				      IORESOURCE_MEM)
-#endif
-#ifndef PCI_IRQ_RESOURCE
-#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
-#endif
+/* Use the irq resource table instead of dev->irq */
+#define FL_IRQRESOURCE		0x0080
 
-#ifndef pci_get_subvendor
-#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
-#define pci_get_subdevice(dev)  ((dev)->subsystem_device)
-#endif
+/* Use the Base address register size to cap number of ports */
+#define FL_REGION_SZ_CAP	0x0100
 
-struct serial_private {
-	unsigned int nr;
-	struct pci_board *board;
-	int line[0];
+struct pci_board {
+	unsigned int flags;
+	unsigned int num_ports;
+	unsigned int base_baud;
+	unsigned int uart_offset;
+	unsigned int reg_shift;
+	unsigned int first_offset;
 };
 
 /*
- * init_fn returns:
+ * init function returns:
  *  > 0 - number of ports
  *  = 0 - use board->num_ports
  *  < 0 - error
  */
-struct pci_board {
-	int flags;
-	int num_ports;
-	int base_baud;
-	int uart_offset;
-	int reg_shift;
-	int (*init_fn)(struct pci_dev *dev, int enable);
-	int first_uart_offset;
+struct pci_serial_quirk {
+	u32	vendor;
+	u32	device;
+	u32	subvendor;
+	u32	subdevice;
+	int	(*init)(struct pci_dev *dev);
+	int	(*setup)(struct pci_dev *dev, struct pci_board *board,
+			 struct serial_struct *req, int idx);
+	void	(*exit)(struct pci_dev *dev);
+};
+
+#define PCI_NUM_BAR_RESOURCES	6
+
+struct serial_private {
+	unsigned int		nr;
+	void			*remapped_bar[PCI_NUM_BAR_RESOURCES];
+	struct pci_serial_quirk	*quirk;
+	int			line[0];
 };
 
+static void moan_device(const char *str, struct pci_dev *dev)
+{
+	printk(KERN_WARNING "%s: %s\n"
+	       KERN_WARNING "Please send the output of lspci -vv, this\n"
+	       KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
+	       KERN_WARNING "manufacturer and name of serial board or\n"
+	       KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n",
+	       dev->slot_name, str, dev->vendor, dev->device,
+	       dev->subsystem_vendor, dev->subsystem_device);
+}
+
 static int
-get_pci_port(struct pci_dev *dev, struct pci_board *board,
-	     struct serial_struct *req, int idx)
+setup_port(struct pci_dev *dev, struct serial_struct *req,
+	   int bar, int offset, int regshift)
 {
-	unsigned long port;
-	int base_idx;
-	int max_port;
-	int offset;
+	struct serial_private *priv = pci_get_drvdata(dev);
+	unsigned long port, len;
+
+	if (bar >= PCI_NUM_BAR_RESOURCES)
+		return -EINVAL;
 
-	base_idx = SPCI_FL_GET_BASE(board->flags);
-	if (board->flags & SPCI_FL_BASE_TABLE)
-		base_idx += idx;
-
-	if (board->flags & SPCI_FL_REGION_SZ_CAP) {
-		max_port = pci_resource_len(dev, base_idx) / 8;
-		if (idx >= max_port)
-			return 1;
+	if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
+		port = pci_resource_start(dev, bar);
+		len =  pci_resource_len(dev, bar);
+
+		if (!priv->remapped_bar[bar])
+			priv->remapped_bar[bar] = ioremap(port, len);
+		if (!priv->remapped_bar[bar])
+			return -ENOMEM;
+
+		req->io_type = UPIO_MEM;
+		req->iomap_base = port;
+		req->iomem_base = priv->remapped_bar[bar] + offset;
+		req->iomem_reg_shift = regshift;
+	} else {
+		port = pci_resource_start(dev, bar) + offset;
+		req->io_type = UPIO_PORT;
+		req->port = port;
+		if (HIGH_BITS_OFFSET)
+			req->port_high = port >> HIGH_BITS_OFFSET;
 	}
-			
-	offset = board->first_uart_offset;
+	return 0;
+}
 
-	/*
-	 * Timedia/SUNIX uses a mixture of BARs and offsets
-	 * Ugh, this is ugly as all hell --- TYT
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_TIMEDIA)
-		switch(idx) {
-		case 0:
-			base_idx = 0;
-			break;
-		case 1:
-			base_idx = 0;
-			offset = 8;
-			break;
-		case 2:
-			base_idx = 1; 
-			break;
-		case 3:
-			base_idx = 1;
-			offset = 8;
-			break;
-		case 4: /* BAR 2 */
-		case 5: /* BAR 3 */
-		case 6: /* BAR 4 */
-		case 7: /* BAR 5 */
-			base_idx = idx - 2;
-		}
+/*
+ * AFAVLAB uses a different mixture of BARs and offsets
+ * Not that ugly ;) -- HW
+ */
+static int
+afavlab_setup(struct pci_dev *dev, struct pci_board *board,
+	      struct serial_struct *req, int idx)
+{
+	unsigned int bar, offset = board->first_offset;
+	
+	bar = FL_GET_BASE(board->flags);
+	if (idx < 4)
+		bar += idx;
+	else
+		offset += (idx - 4) * board->uart_offset;
 
-	/* AFAVLAB uses a different mixture of BARs and offsets */
-	/* Not that ugly ;) -- HW */
-	if (dev->vendor == PCI_VENDOR_ID_AFAVLAB && idx >= 4) {
-		base_idx = 4;
-		offset = (idx - 4) * 8;
-	}
+	return setup_port(dev, req, bar, offset, board->reg_shift);
+}
 
-	/* Some Titan cards are also a little weird */
-	if (dev->vendor == PCI_VENDOR_ID_TITAN &&
-	    (dev->device == PCI_DEVICE_ID_TITAN_400L ||
-	     dev->device == PCI_DEVICE_ID_TITAN_800L)) {
-		switch (idx) {
-		case 0: base_idx = 1;
-			break;
-		case 1: base_idx = 2;
-			break;
-		default:
-			base_idx = 4;
-			offset = 8 * (idx - 2);
-		}
-	}
+/*
+ * HP's Remote Management Console.  The Diva chip came in several
+ * different versions.  N-class, L2000 and A500 have two Diva chips, each
+ * with 3 UARTs (the third UART on the second chip is unused).  Superdome
+ * and Keystone have one Diva chip with 3 UARTs.  Some later machines have
+ * one Diva chip, but it has been expanded to 5 UARTs.
+ */
+static int __devinit pci_hp_diva_init(struct pci_dev *dev)
+{
+	int rc = 0;
 
-	/* HP's Diva chip puts the 4th/5th serial port further out, and
-	 * some serial ports are supposed to be hidden on certain models.
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_HP &&
-	    dev->device == PCI_DEVICE_ID_HP_DIVA) {
-		switch (dev->subsystem_device) {
-		case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
-			if (idx == 3)
-				idx++;
-			break;
-		case PCI_DEVICE_ID_HP_DIVA_EVEREST:
-			if (idx > 0)
-				idx++;
-			if (idx > 2)
-				idx++;
-			break;
-		}
-		if (idx > 2) {
-			offset = 0x18;
-		}
+	switch (dev->subsystem_device) {
+	case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
+	case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
+	case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
+	case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+		rc = 3;
+		break;
+	case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
+		rc = 2;
+		break;
+	case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+		rc = 4;
+		break;
+	case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
+		rc = 1;
+		break;
 	}
 
-	port =  pci_resource_start(dev, base_idx) + offset;
+	return rc;
+}
 
-	if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
-		port += idx * (board->uart_offset ? board->uart_offset : 8);
+/*
+ * HP's Diva chip puts the 4th/5th serial port further out, and
+ * some serial ports are supposed to be hidden on certain models.
+ */
+static int
+pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
+	      struct serial_struct *req, int idx)
+{
+	unsigned int offset = board->first_offset;
+	unsigned int bar = FL_GET_BASE(board->flags);
 
-	if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
-		req->port = port;
-		if (HIGH_BITS_OFFSET)
-			req->port_high = port >> HIGH_BITS_OFFSET;
-		else
-			req->port_high = 0;
-		return 0;
+	switch (dev->subsystem_device) {
+	case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+		if (idx == 3)
+			idx++;
+		break;
+	case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+		if (idx > 0)
+			idx++;
+		if (idx > 2)
+			idx++;
+		break;
 	}
-	req->io_type = SERIAL_IO_MEM;
-	req->iomap_base = port;
-	req->iomem_base = ioremap(port, board->uart_offset);
-	if (req->iomem_base == NULL)
-		return -ENOMEM;
-	req->iomem_reg_shift = board->reg_shift;
-	req->port = 0;
-	return 0;
+	if (idx > 2)
+		offset = 0x18;
+
+	offset += idx * board->uart_offset;
+
+	return setup_port(dev, req, bar, offset, board->reg_shift);
 }
 
-static _INLINE_ int
-get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)
+/*
+ * Added for EKF Intel i960 serial boards
+ */
+static int __devinit pci_inteli960ni_init(struct pci_dev *dev)
 {
-	int base_idx;
+	unsigned long oldval;
 
-	if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
-		return dev->irq;
+	if (!(dev->subsystem_device & 0x1000))
+		return -ENODEV;
 
-	base_idx = SPCI_FL_GET_IRQBASE(board->flags);
-	if (board->flags & SPCI_FL_IRQ_TABLE)
-		base_idx += idx;
-	
-	return PCI_IRQ_RESOURCE(dev, base_idx);
+	/* is firmware started? */
+	pci_read_config_dword(dev, 0x44, (void*) &oldval); 
+	if (oldval == 0x00001000L) { /* RESET value */ 
+		printk(KERN_DEBUG "Local i960 firmware missing");
+		return -ENODEV;
+	}
+	return 0;
 }
 
 /*
@@ -206,26 +246,29 @@
  * seems to be mainly needed on card using the PLX which also use I/O
  * mapped memory.
  */
-static int __devinit pci_plx9050_fn(struct pci_dev *dev, int enable)
+static int __devinit pci_plx9050_init(struct pci_dev *dev)
 {
-	u8 *p, irq_config = 0;
+	u8 *p, irq_config;
 
-	if (enable) {
-		irq_config = 0x41;
-		if (dev->vendor == PCI_VENDOR_ID_PANACOM)
-			irq_config = 0x43;
-		if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
-		    (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
-			/*
-			 * As the megawolf cards have the int pins active
-			 * high, and have 2 UART chips, both ints must be
-			 * enabled on the 9050. Also, the UARTS are set in
-			 * 16450 mode by default, so we have to enable the
-			 * 16C950 'enhanced' mode so that we can use the
-			 * deep FIFOs
-			 */
-			irq_config = 0x5b;
-		}
+	if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
+		moan_device("no memory in bar 0", dev);
+		return 0;
+	}
+
+	irq_config = 0x41;
+	if (dev->vendor == PCI_VENDOR_ID_PANACOM)
+		irq_config = 0x43;
+	if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
+	    (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
+		/*
+		 * As the megawolf cards have the int pins active
+		 * high, and have 2 UART chips, both ints must be
+		 * enabled on the 9050. Also, the UARTS are set in
+		 * 16450 mode by default, so we have to enable the
+		 * 16C950 'enhanced' mode so that we can use the
+		 * deep FIFOs
+		 */
+		irq_config = 0x5b;
 	}
 
 	/*
@@ -245,6 +288,27 @@
 	return 0;
 }
 
+static void __devexit pci_plx9050_exit(struct pci_dev *dev)
+{
+	u8 *p;
+
+	if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0)
+		return;
+
+	/*
+	 * disable interrupts
+	 */
+	p = ioremap(pci_resource_start(dev, 0), 0x80);
+	if (p != NULL) {
+		writel(0, p + 0x4c);
+
+		/*
+		 * Read the register back to ensure that it took effect.
+		 */
+		readl(p + 0x4c);
+		iounmap(p);
+	}
+}
 
 /*
  * SIIG serial cards have an PCI interface chip which also controls
@@ -270,23 +334,20 @@
 #define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
 #define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
 
-int pci_siig10x_fn(struct pci_dev *dev, int enable)
+static int pci_siig10x_init(struct pci_dev *dev)
 {
 	u16 data, *p;
 
-	if (!enable)
-		return 0;
-
 	switch (dev->device & 0xfff8) {
-		case PCI_DEVICE_ID_SIIG_1S_10x:	/* 1S */
-			data = 0xffdf;
-			break;
-		case PCI_DEVICE_ID_SIIG_2S_10x:	/* 2S, 2S1P */
-			data = 0xf7ff;
-			break;
-		default:			/* 1S1P, 4S */
-			data = 0xfffb;
-			break;
+	case PCI_DEVICE_ID_SIIG_1S_10x:	/* 1S */
+		data = 0xffdf;
+		break;
+	case PCI_DEVICE_ID_SIIG_2S_10x:	/* 2S, 2S1P */
+		data = 0xf7ff;
+		break;
+	default:			/* 1S1P, 4S */
+		data = 0xfffb;
+		break;
 	}
 
 	p = ioremap(pci_resource_start(dev, 0), 0x80);
@@ -294,22 +355,18 @@
 		return -ENOMEM;
 
 	writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
+	readw((unsigned long)p + 0x28);
 	iounmap(p);
 	return 0;
 }
 
-EXPORT_SYMBOL(pci_siig10x_fn);
-
 #define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
 #define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
 
-int pci_siig20x_fn(struct pci_dev *dev, int enable)
+static int pci_siig20x_init(struct pci_dev *dev)
 {
 	u8 data;
 
-	if (!enable)
-		return 0;
-
 	/* Change clock frequency for the first UART. */
 	pci_read_config_byte(dev, 0x6f, &data);
 	pci_write_config_byte(dev, 0x6f, data & 0xef);
@@ -323,28 +380,25 @@
 	return 0;
 }
 
-EXPORT_SYMBOL(pci_siig20x_fn);
-
-/* Added for EKF Intel i960 serial boards */
-static int __devinit pci_inteli960ni_fn(struct pci_dev *dev, int enable)
+int pci_siig10x_fn(struct pci_dev *dev, int enable)
 {
-	unsigned long oldval;
-
-	if (!(pci_get_subdevice(dev) & 0x1000))
-		return -ENODEV;
+	int ret = 0;
+	if (enable)
+		ret = pci_siig10x_init(dev);
+	return ret;
+}
 
-	if (!enable) /* is there something to deinit? */
-		return 0;
-   
-	/* is firmware started? */
-	pci_read_config_dword(dev, 0x44, (void*) &oldval); 
-	if (oldval == 0x00001000L) { /* RESET value */ 
-		printk(KERN_DEBUG "Local i960 firmware missing");
-		return -ENODEV;
-	}
-	return 0;
+int pci_siig20x_fn(struct pci_dev *dev, int enable)
+{
+	int ret = 0;
+	if (enable)
+		ret = pci_siig20x_init(dev);
+	return ret;
 }
 
+EXPORT_SYMBOL(pci_siig10x_fn);
+EXPORT_SYMBOL(pci_siig20x_fn);
+
 /*
  * Timedia has an explosion of boards, and to avoid the PCI table from
  * growing *huge*, we use this function to collapse some 70 entries
@@ -385,78 +439,453 @@
 	{ 0, 0 }
 };
 
-static int __devinit pci_timedia_fn(struct pci_dev *dev, int enable)
+static int __devinit pci_timedia_init(struct pci_dev *dev)
 {
-	int	i, j;
 	unsigned short *ids;
-
-	if (!enable)
-		return 0;
+	int i, j;
 
 	for (i = 0; timedia_data[i].num; i++) {
 		ids = timedia_data[i].ids;
 		for (j = 0; ids[j]; j++)
-			if (pci_get_subdevice(dev) == ids[j])
+			if (dev->subsystem_device == ids[j])
 				return timedia_data[i].num;
 	}
 	return 0;
 }
 
 /*
- * HP's Remote Management Console.  The Diva chip came in several
- * different versions.  N-class, L2000 and A500 have two Diva chips, each
- * with 3 UARTs (the third UART on the second chip is unused).  Superdome
- * and Keystone have one Diva chip with 3 UARTs.  Some later machines have
- * one Diva chip, but it has been expanded to 5 UARTs.
+ * Timedia/SUNIX uses a mixture of BARs and offsets
+ * Ugh, this is ugly as all hell --- TYT
  */
-static int __devinit pci_hp_diva(struct pci_dev *dev, int enable)
+static int
+pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
+		  struct serial_struct *req, int idx)
 {
-	int rc = 0;
-
-	if (!enable)
-		return 0;
+	unsigned int bar = 0, offset = board->first_offset;
 
-	switch (dev->subsystem_device) {
-	case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
-	case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
-	case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
-	case PCI_DEVICE_ID_HP_DIVA_EVEREST:
-		rc = 3;
+	switch (idx) {
+	case 0:
+		bar = 0;
 		break;
-	case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
-		rc = 2;
+	case 1:
+		offset = board->uart_offset;
+		bar = 0;
 		break;
-	case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
-		rc = 4;
-		break;
-	case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
-		rc = 1;
+	case 2:
+		bar = 1;
 		break;
+	case 3:
+		offset = board->uart_offset;
+		bar = 1;
+	case 4: /* BAR 2 */
+	case 5: /* BAR 3 */
+	case 6: /* BAR 4 */
+	case 7: /* BAR 5 */
+		bar = idx - 2;
 	}
 
-	return rc;
+	return setup_port(dev, req, bar, offset, board->reg_shift);
 }
 
+/*
+ * Some Titan cards are also a little weird
+ */
+static int
+titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
+		      struct serial_struct *req, int idx)
+{
+	unsigned int bar, offset = board->first_offset;
 
-static int __devinit pci_xircom_fn(struct pci_dev *dev, int enable)
+	switch (idx) {
+	case 0:
+		bar = 1;
+		break;
+	case 1:
+		bar = 2;
+		break;
+	default:
+		bar = 4;
+		offset = (idx - 2) * board->uart_offset;
+	}
+
+	return setup_port(dev, req, bar, offset, board->reg_shift);
+}
+
+static int __devinit pci_xircom_init(struct pci_dev *dev)
 {
 	__set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ/10);
 	return 0;
 }
 
+static int
+pci_default_setup(struct pci_dev *dev, struct pci_board *board,
+		  struct serial_struct *req, int idx)
+{
+	unsigned int bar, offset = board->first_offset, maxnr;
+
+	bar = FL_GET_BASE(board->flags);
+	if (board->flags & FL_BASE_BARS)
+		bar += idx;
+	else
+		offset += idx * board->uart_offset;
+
+	maxnr = (pci_resource_len(dev, bar) - board->uart_offset) /
+		(8 << board->reg_shift);
+
+	if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
+		return 1;
+			
+	return setup_port(dev, req, bar, offset, board->reg_shift);
+}
+
+/*
+ * Master list of serial port init/setup/exit quirks.
+ * This does not describe the general nature of the port.
+ * (ie, baud base, number and location of ports, etc)
+ *
+ * This list is ordered alphabetically by vendor then device.
+ * Specific entries must come before more generic entries.
+ */
+static struct pci_serial_quirk pci_serial_quirks[] = {
+	/*
+	 * AFAVLAB cards.
+	 *  It is not clear whether this applies to all products.
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_AFAVLAB,
+		.device		= PCI_ANY_ID,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= afavlab_setup,
+	},
+	/*
+	 * HP Diva
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_HP,
+		.device		= PCI_DEVICE_ID_HP_DIVA,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_hp_diva_init,
+		.setup		= pci_hp_diva_setup,
+	},
+	/*
+	 * Intel
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_80960_RP,
+		.subvendor	= 0xe4bf,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_inteli960ni_init,
+		.setup		= pci_default_setup,
+	},
+	/*
+	 * Panacom
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_PANACOM,
+		.device		= PCI_DEVICE_ID_PANACOM_QUADMODEM,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_plx9050_init,
+		.setup		= pci_default_setup,
+		.exit		= __devexit_p(pci_plx9050_exit),
+	},		
+	{
+		.vendor		= PCI_VENDOR_ID_PANACOM,
+		.device		= PCI_DEVICE_ID_PANACOM_DUALMODEM,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_plx9050_init,
+		.setup		= pci_default_setup,
+		.exit		= __devexit_p(pci_plx9050_exit),
+	},
+	/*
+	 * PLX
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_PLX,
+		.device		= PCI_DEVICE_ID_PLX_9050,
+		.subvendor	= PCI_SUBVENDOR_ID_KEYSPAN,
+		.subdevice	= PCI_SUBDEVICE_ID_KEYSPAN_SX2,
+		.init		= pci_plx9050_init,
+		.setup		= pci_default_setup,
+		.exit		= __devexit_p(pci_plx9050_exit),
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_PLX,
+		.device		= PCI_DEVICE_ID_PLX_ROMULUS,
+		.subvendor	= PCI_VENDOR_ID_PLX,
+		.subdevice	= PCI_DEVICE_ID_PLX_ROMULUS,
+		.init		= pci_plx9050_init,
+		.setup		= pci_default_setup,
+		.exit		= __devexit_p(pci_plx9050_exit),
+	},
+	/*
+	 * SIIG cards.
+	 *  It is not clear whether these could be collapsed.
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_1S_10x_550,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_1S_10x_650,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_1S_10x_850,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_2S_10x_550,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_2S_10x_650,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_2S_10x_850,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_4S_10x_550,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_4S_10x_650,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_4S_10x_850,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig10x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_1S_20x_550,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_1S_20x_650,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_1S_20x_850,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_2S_20x_550,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{	.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_2S_20x_650,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_2S_20x_850,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_4S_20x_550,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_4S_20x_650,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_SIIG,
+		.device		= PCI_DEVICE_ID_SIIG_4S_20x_850,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_siig20x_init,
+		.setup		= pci_default_setup,
+	},
+	/*
+	 * Titan cards
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_TITAN,
+		.device		= PCI_DEVICE_ID_TITAN_400L,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= titan_400l_800l_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_TITAN,
+		.device		= PCI_DEVICE_ID_TITAN_800L,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= titan_400l_800l_setup,
+	},
+	/*
+	 * Timedia cards
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_TIMEDIA,
+		.device		= PCI_DEVICE_ID_TIMEDIA_1889,
+		.subvendor	= PCI_VENDOR_ID_TIMEDIA,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_timedia_init,
+		.setup		= pci_timedia_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_TIMEDIA,
+		.device		= PCI_ANY_ID,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_timedia_setup,
+	},
+	/*
+	 * Xircom cards
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_XIRCOM,
+		.device		= PCI_DEVICE_ID_XIRCOM_X3201_MDM,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_xircom_init,
+		.setup		= pci_default_setup,
+	},
+	/*
+	 * Default "match everything" terminator entry
+	 */
+	{
+		.vendor		= PCI_ANY_ID,
+		.device		= PCI_ANY_ID,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_default_setup,
+	}
+};
+
+static inline int quirk_id_matches(u32 quirk_id, u32 dev_id)
+{
+	return quirk_id == PCI_ANY_ID || quirk_id == dev_id;
+}
+
+static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
+{
+	struct pci_serial_quirk *quirk;
+
+	for (quirk = pci_serial_quirks; ; quirk++)
+		if (quirk_id_matches(quirk->vendor, dev->vendor) &&
+		    quirk_id_matches(quirk->device, dev->device) &&
+		    quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
+		    quirk_id_matches(quirk->subdevice, dev->subsystem_device))
+		 	break;
+	return quirk;
+}
+
+static _INLINE_ int
+get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)
+{
+	int base_idx;
+
+	if ((board->flags & FL_IRQRESOURCE) == 0)
+		return dev->irq;
+
+	base_idx = FL_GET_IRQBASE(board->flags);
+
+	if (base_idx > DEVICE_COUNT_IRQ)
+		return 0;
+	
+	return dev->irq_resource[base_idx].start;
+}
+
 /*
  * This is the configuration table for all of the PCI serial boards
  * which we support.  It is directly indexed by the pci_board_num_t enum
  * value, which is encoded in the pci_device_id PCI probe table's
  * driver_data member.
+ *
+ * The makeup of these names are:
+ *  pbn_bn{_bt}_n_baud
+ *
+ *  bn   = PCI BAR number
+ *  bt   = Index using PCI BARs
+ *  n    = number of serial ports
+ *  baud = baud rate
+ *
+ * Please note: in theory if n = 1, _bt infix should make no difference.
+ * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
  */
 enum pci_board_num_t {
-	pbn_b0_1_115200,
 	pbn_default = 0,
 
+	pbn_b0_1_115200,
 	pbn_b0_2_115200,
 	pbn_b0_4_115200,
+	pbn_b0_5_115200,
 
 	pbn_b0_1_921600,
 	pbn_b0_2_921600,
@@ -465,171 +894,465 @@
 	pbn_b0_bt_1_115200,
 	pbn_b0_bt_2_115200,
 	pbn_b0_bt_8_115200,
+
 	pbn_b0_bt_1_460800,
 	pbn_b0_bt_2_460800,
 
+	pbn_b0_bt_1_921600,
+	pbn_b0_bt_2_921600,
+	pbn_b0_bt_4_921600,
+	pbn_b0_bt_8_921600,
+
 	pbn_b1_1_115200,
 	pbn_b1_2_115200,
 	pbn_b1_4_115200,
 	pbn_b1_8_115200,
 
+	pbn_b1_1_921600,
 	pbn_b1_2_921600,
 	pbn_b1_4_921600,
 	pbn_b1_8_921600,
 
+	pbn_b1_bt_2_921600,
+
 	pbn_b1_2_1382400,
 	pbn_b1_4_1382400,
 	pbn_b1_8_1382400,
 
 	pbn_b2_1_115200,
 	pbn_b2_8_115200,
+
+	pbn_b2_1_460800,
 	pbn_b2_4_460800,
 	pbn_b2_8_460800,
 	pbn_b2_16_460800,
+
+	pbn_b2_1_921600,
 	pbn_b2_4_921600,
 	pbn_b2_8_921600,
 
 	pbn_b2_bt_1_115200,
 	pbn_b2_bt_2_115200,
 	pbn_b2_bt_4_115200,
+
 	pbn_b2_bt_2_921600,
+	pbn_b2_bt_4_921600,
+
+	pbn_b3_4_115200,
+	pbn_b3_8_115200,
 
+	/*
+	 * Board-specific versions.
+	 */
 	pbn_panacom,
 	pbn_panacom2,
 	pbn_panacom4,
 	pbn_plx_romulus,
 	pbn_oxsemi,
-	pbn_timedia,
 	pbn_intel_i960,
 	pbn_sgi_ioc3,
-	pbn_hp_diva,
 	pbn_nec_nile4,
-
-	pbn_dci_pccom4,
-	pbn_dci_pccom8,
-
-	pbn_xircom_combo,
-
-	pbn_siig10x_0,
-	pbn_siig10x_1,
-	pbn_siig10x_2,
-	pbn_siig10x_4,
-	pbn_siig20x_0,
-	pbn_siig20x_2,
-	pbn_siig20x_4,
-	
 	pbn_computone_4,
 	pbn_computone_6,
 	pbn_computone_8,
 };
 
 static struct pci_board pci_boards[] __devinitdata = {
+	[pbn_default] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_1_115200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_2_115200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_4_115200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_5_115200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 5,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b0_1_921600] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_2_921600] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_4_921600] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b0_bt_1_115200] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_bt_2_115200] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_bt_8_115200] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 8,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b0_bt_1_460800] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 460800,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_bt_2_460800] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 2,
+		.base_baud	= 460800,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b0_bt_1_921600] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_bt_2_921600] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_bt_4_921600] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b0_bt_8_921600] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 8,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b1_1_115200] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_2_115200] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_4_115200] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 4,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_8_115200] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 8,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b1_1_921600] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_2_921600] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_4_921600] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_8_921600] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 8,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b1_bt_2_921600] = {
+		.flags		= FL_BASE1|FL_BASE_BARS,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b1_2_1382400] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 2,
+		.base_baud	= 1382400,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_4_1382400] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 4,
+		.base_baud	= 1382400,
+		.uart_offset	= 8,
+	},
+	[pbn_b1_8_1382400] = {
+		.flags		= FL_BASE1,
+		.num_ports	= 8,
+		.base_baud	= 1382400,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b2_1_115200] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_8_115200] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 8,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b2_1_460800] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 1,
+		.base_baud	= 460800,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_4_460800] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 4,
+		.base_baud	= 460800,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_8_460800] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 8,
+		.base_baud	= 460800,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_16_460800] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 16,
+		.base_baud	= 460800,
+		.uart_offset	= 8,
+	 },
+
+	[pbn_b2_1_921600] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_4_921600] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_8_921600] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 8,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b2_bt_1_115200] = {
+		.flags		= FL_BASE2|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_bt_2_115200] = {
+		.flags		= FL_BASE2|FL_BASE_BARS,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_bt_4_115200] = {
+		.flags		= FL_BASE2|FL_BASE_BARS,
+		.num_ports	= 4,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b2_bt_2_921600] = {
+		.flags		= FL_BASE2|FL_BASE_BARS,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[pbn_b2_bt_4_921600] = {
+		.flags		= FL_BASE2|FL_BASE_BARS,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+
+	[pbn_b3_4_115200] = {
+		.flags		= FL_BASE3,
+		.num_ports	= 4,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[pbn_b3_8_115200] = {
+		.flags		= FL_BASE3,
+		.num_ports	= 8,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+
 	/*
-	 * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
-	 * Offset to get to next UART's registers,
-	 * Register shift to use for memory-mapped I/O,
-	 * Initialization function, first UART offset
-	 */
-
-	/* Generic serial board, pbn_b0_1_115200, pbn_default */
-	{ SPCI_FL_BASE0, 1, 115200 },		/* pbn_b0_1_115200,
-						   pbn_default */
-
-	{ SPCI_FL_BASE0, 2, 115200 },		/* pbn_b0_2_115200 */
-	{ SPCI_FL_BASE0, 4, 115200 },		/* pbn_b0_4_115200 */
-
-	{ SPCI_FL_BASE0, 1, 921600 },		/* pbn_b0_1_921600 */
-	{ SPCI_FL_BASE0, 2, 921600 },		/* pbn_b0_2_921600 */
-	{ SPCI_FL_BASE0, 4, 921600 },		/* pbn_b0_4_921600 */
-
-	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
-	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
-	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 8, 115200 }, /* pbn_b0_bt_8_115200 */
-	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
-	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
-
-	{ SPCI_FL_BASE1, 1, 115200 },		/* pbn_b1_1_115200 */
-	{ SPCI_FL_BASE1, 2, 115200 },		/* pbn_b1_2_115200 */
-	{ SPCI_FL_BASE1, 4, 115200 },		/* pbn_b1_4_115200 */
-	{ SPCI_FL_BASE1, 8, 115200 },		/* pbn_b1_8_115200 */
-
-	{ SPCI_FL_BASE1, 2, 921600 },		/* pbn_b1_2_921600 */
-	{ SPCI_FL_BASE1, 4, 921600 },		/* pbn_b1_4_921600 */
-	{ SPCI_FL_BASE1, 8, 921600 },		/* pbn_b1_8_921600 */
-
-	{ SPCI_FL_BASE1, 2, 1382400 },		/* pbn_b1_2_1382400 */
-	{ SPCI_FL_BASE1, 4, 1382400 },		/* pbn_b1_4_1382400 */
-	{ SPCI_FL_BASE1, 8, 1382400 },		/* pbn_b1_8_1382400 */
-
-	{ SPCI_FL_BASE2, 1, 115200 },		/* pbn_b2_1_115200 */
-	{ SPCI_FL_BASE2, 8, 115200 },		/* pbn_b2_8_115200 */
-	{ SPCI_FL_BASE2, 4, 460800 },		/* pbn_b2_4_460800 */
-	{ SPCI_FL_BASE2, 8, 460800 },		/* pbn_b2_8_460800 */
-	{ SPCI_FL_BASE2, 16, 460800 },		/* pbn_b2_16_460800 */
-	{ SPCI_FL_BASE2, 4, 921600 },		/* pbn_b2_4_921600 */
-	{ SPCI_FL_BASE2, 8, 921600 },		/* pbn_b2_8_921600 */
-
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
-
-	{ SPCI_FL_BASE2, 2, 921600, /* IOMEM */		   /* pbn_panacom */
-		0x400, 7, pci_plx9050_fn },
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,   /* pbn_panacom2 */
-		0x400, 7, pci_plx9050_fn },
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,   /* pbn_panacom4 */
-		0x400, 7, pci_plx9050_fn },
-	{ SPCI_FL_BASE2, 4, 921600,			   /* pbn_plx_romulus */
-		0x20, 2, pci_plx9050_fn, 0x03 },
+	 * Entries following this are board-specific.
+	 */
+
+	/*
+	 * Panacom - IOMEM
+	 */
+	[pbn_panacom] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 0x400,
+		.reg_shift	= 7,
+	},
+	[pbn_panacom2] = {
+		.flags		= FL_BASE2|FL_BASE_BARS,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 0x400,
+		.reg_shift	= 7,
+	},
+	[pbn_panacom4] = {
+		.flags		= FL_BASE2|FL_BASE_BARS,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 0x400,
+		.reg_shift	= 7,
+	},
+
+	/* I think this entry is broken - the first_offset looks wrong --rmk */
+	[pbn_plx_romulus] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 8 << 2,
+		.reg_shift	= 2,
+		.first_offset	= 0x03,
+	},
 
 	/*
 	 * This board uses the size of PCI Base region 0 to
 	 * signal now many ports are available
 	 */
-	{ SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
-	{ SPCI_FL_BASE_TABLE, 1, 921600,		   /* pbn_timedia */
-		0, 0, pci_timedia_fn },
-	/* EKF addition for i960 Boards form EKF with serial port */
-	{ SPCI_FL_BASE0, 32, 921600, /* max 256 ports */   /* pbn_intel_i960 */
-		8<<2, 2, pci_inteli960ni_fn, 0x10000},
-	{ SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE,		   /* pbn_sgi_ioc3 */
-		1, 458333, 0, 0, 0, 0x20178 },
-	{ SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0 },/* pbn_hp_diva */
+	[pbn_oxsemi] = {
+		.flags		= FL_BASE0|FL_REGION_SZ_CAP,
+		.num_ports	= 32,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
 
 	/*
-	 * NEC Vrc-5074 (Nile 4) builtin UART.
+	 * EKF addition for i960 Boards form EKF with serial port.
+	 * Max 256 ports.
 	 */
-	{ SPCI_FL_BASE0, 1, 520833,			   /* pbn_nec_nile4 */
-		64, 3, NULL, 0x300 },
-
-	{ SPCI_FL_BASE3, 4, 115200, 8 },		   /* pbn_dci_pccom4 */
-	{ SPCI_FL_BASE3, 8, 115200, 8 },		   /* pbn_dci_pccom8 */
+	[pbn_intel_i960] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 32,
+		.base_baud	= 921600,
+		.uart_offset	= 8 << 2,
+		.reg_shift	= 2,
+		.first_offset	= 0x10000,
+	},
+	[pbn_sgi_ioc3] = {
+		.flags		= FL_BASE0|FL_IRQRESOURCE,
+		.num_ports	= 1,
+		.base_baud	= 458333,
+		.uart_offset	= 8,
+		.reg_shift	= 0,
+		.first_offset	= 0x20178,
+	},
 
-	{ SPCI_FL_BASE0, 1, 115200,			   /* pbn_xircom_combo */
-		0, 0, pci_xircom_fn },
+	/*
+	 * NEC Vrc-5074 (Nile 4) builtin UART.
+	 */
+	[pbn_nec_nile4] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 520833,
+		.uart_offset	= 8 << 3,
+		.reg_shift	= 3,
+		.first_offset	= 0x300,
+	},
 
-	{ SPCI_FL_BASE2, 1, 460800,			   /* pbn_siig10x_0 */
-		0, 0, pci_siig10x_fn },
-	{ SPCI_FL_BASE2, 1, 921600,			   /* pbn_siig10x_1 */
-		0, 0, pci_siig10x_fn },
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,   /* pbn_siig10x_2 */
-		0, 0, pci_siig10x_fn },
-	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,   /* pbn_siig10x_4 */
-		0, 0, pci_siig10x_fn },
-	{ SPCI_FL_BASE0, 1, 921600,			   /* pbn_siix20x_0 */
-		0, 0, pci_siig20x_fn },
-	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,   /* pbn_siix20x_2 */
-		0, 0, pci_siig20x_fn },
-	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600,   /* pbn_siix20x_4 */
-		0, 0, pci_siig20x_fn },
-
-	{ SPCI_FL_BASE0, 4, 921600, /* IOMEM */		   /* pbn_computone_4 */
-		0x40, 2, NULL, 0x200 },
-	{ SPCI_FL_BASE0, 6, 921600, /* IOMEM */		   /* pbn_computone_6 */
-		0x40, 2, NULL, 0x200 },
-	{ SPCI_FL_BASE0, 8, 921600, /* IOMEM */		   /* pbn_computone_8 */
-		0x40, 2, NULL, 0x200 },
+	/*
+	 * Computone - uses IOMEM.
+	 */
+	[pbn_computone_4] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 0x40,
+		.reg_shift	= 2,
+		.first_offset	= 0x200,
+	},
+	[pbn_computone_6] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 6,
+		.base_baud	= 921600,
+		.uart_offset	= 0x40,
+		.reg_shift	= 2,
+		.first_offset	= 0x200,
+	},
+	[pbn_computone_8] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 8,
+		.base_baud	= 921600,
+		.uart_offset	= 0x40,
+		.reg_shift	= 2,
+		.first_offset	= 0x200,
+	},
 };
 
 /*
@@ -640,8 +1363,7 @@
 static int __devinit
 serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
 {
-	int num_iomem = 0, num_port = 0, first_port = -1;
-	int i;
+	int num_iomem, num_port, first_port = -1, i;
 	
 	/*
 	 * If it is not a communications device or the programming
@@ -655,36 +1377,63 @@
 	    (dev->class & 0xff) > 6)
 		return -ENODEV;
 
-	for (i = 0; i < 6; i++) {
-		if (IS_PCI_REGION_IOPORT(dev, i)) {
+	num_iomem = num_port = 0;
+	for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+		if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
 			num_port++;
 			if (first_port == -1)
 				first_port = i;
 		}
-		if (IS_PCI_REGION_IOMEM(dev, i))
+		if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
 			num_iomem++;
 	}
 
 	/*
-	 * If there is 1 or 0 iomem regions, and exactly one port, use
-	 * it.
+	 * If there is 1 or 0 iomem regions, and exactly one port,
+	 * use it.  We guess the number of ports based on the IO
+	 * region size.
 	 */
 	if (num_iomem <= 1 && num_port == 1) {
 		board->flags = first_port;
+		board->num_ports = pci_resource_len(dev, first_port) / 8;
 		return 0;
 	}
+
+	/*
+	 * Now guess if we've got a board which indexes by BARs.
+	 * Each IO BAR should be 8 bytes, and they should follow
+	 * consecutively.
+	 */
+	first_port = -1;
+	num_port = 0;
+	for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+		if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
+		    pci_resource_len(dev, i) == 8 &&
+		    (first_port == -1 || (first_port + num_port) == i)) {
+			num_port++;
+			if (first_port == -1)
+				first_port = i;
+		}
+	}
+
+	if (num_port > 1) {
+		board->flags = first_port | FL_BASE_BARS;
+		board->num_ports = num_port;
+		return 0;
+	}
+
 	return -ENODEV;
 }
 
 static inline int
-serial_pci_matches(struct pci_board *board, int index)
+serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
 {
 	return
-	    board->base_baud == pci_boards[index].base_baud &&
-	    board->num_ports == pci_boards[index].num_ports &&
-	    board->uart_offset == pci_boards[index].uart_offset &&
-	    board->reg_shift == pci_boards[index].reg_shift &&
-	    board->first_uart_offset == pci_boards[index].first_uart_offset;
+	    board->num_ports == guessed->num_ports &&
+	    board->base_baud == guessed->base_baud &&
+	    board->uart_offset == guessed->uart_offset &&
+	    board->reg_shift == guessed->reg_shift &&
+	    board->first_offset == guessed->first_offset;
 }
 
 /*
@@ -692,10 +1441,11 @@
  * to the arrangement of serial ports on a PCI card.
  */
 static int __devinit
-pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 {
 	struct serial_private *priv;
 	struct pci_board *board, tmp;
+	struct pci_serial_quirk *quirk;
 	struct serial_struct serial_req;
 	int base_baud, rc, nr_ports, i;
 
@@ -732,92 +1482,109 @@
 		 * detect this boards settings with our heuristic,
 		 * then we no longer need this entry.
 		 */
+		memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board));
 		rc = serial_pci_guess_board(dev, &tmp);
-		if (rc == 0 && serial_pci_matches(board, pbn_default)) {
-			printk(KERN_INFO
-		"Redundant entry in serial pci_table.  Please send the output\n"
-		"of lspci -vv, this message (0x%04x,0x%04x,0x%04x,0x%04x),\n"
-		"the manufacturer and name of serial board or modem board to\n"
-		"rmk@arm.linux.org.uk.\n",
-			       dev->vendor, dev->device,
-			       pci_get_subvendor(dev), pci_get_subdevice(dev));
-		}
+		if (rc == 0 && serial_pci_matches(board, &tmp))
+			moan_device("Redundant entry in serial pci_table.",
+				    dev);
 	}
 
 	nr_ports = board->num_ports;
 
 	/*
-	 * Run the initialization function, if any.  The initialization
-	 * function returns:
+	 * Find an init and setup quirks.
+	 */
+	quirk = find_quirk(dev);
+
+	/*
+	 * Run the new-style initialization function.
+	 * The initialization function returns:
 	 *  <0  - error
 	 *   0  - use board->num_ports
 	 *  >0  - number of ports
 	 */
-	if (board->init_fn) {
-		rc = board->init_fn(dev, 1);
+	if (quirk->init) {
+		rc = quirk->init(dev);
 		if (rc < 0)
 			goto disable;
-
 		if (rc)
 			nr_ports = rc;
 	}
 
 	priv = kmalloc(sizeof(struct serial_private) +
-			      sizeof(unsigned int) * nr_ports,
-			      GFP_KERNEL);
+		       sizeof(unsigned int) * nr_ports,
+		       GFP_KERNEL);
 	if (!priv) {
 		rc = -ENOMEM;
 		goto deinit;
 	}
 
+	memset(priv, 0, sizeof(struct serial_private) +
+			sizeof(unsigned int) * nr_ports);
+
+	priv->quirk = quirk;
+	pci_set_drvdata(dev, priv);
+
 	base_baud = board->base_baud;
-	if (!base_baud)
+	if (!base_baud) {
+		moan_device("Board entry does not specify baud rate.", dev);
 		base_baud = BASE_BAUD;
-	memset(&serial_req, 0, sizeof(serial_req));
+	}
 	for (i = 0; i < nr_ports; i++) {
+		memset(&serial_req, 0, sizeof(serial_req));
+		serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE |
+				   UPF_RESOURCES | UPF_SHARE_IRQ;
+		serial_req.baud_base = base_baud;
 		serial_req.irq = get_pci_irq(dev, board, i);
-		if (get_pci_port(dev, board, &serial_req, i))
+		if (quirk->setup(dev, board, &serial_req, i))
 			break;
 #ifdef SERIAL_DEBUG_PCI
 		printk("Setup PCI port: port %x, irq %d, type %d\n",
 		       serial_req.port, serial_req.irq, serial_req.io_type);
 #endif
-		serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-		serial_req.baud_base = base_baud;
 		
 		priv->line[i] = register_serial(&serial_req);
 		if (priv->line[i] < 0)
 			break;
 	}
 
-	priv->board = board;
 	priv->nr = i;
 
-	pci_set_drvdata(dev, priv);
-
 	return 0;
 
  deinit:
-	if (board->init_fn)
-		board->init_fn(dev, 0);
+	if (quirk->exit)
+		quirk->exit(dev);
  disable:
 	pci_disable_device(dev);
 	return rc;
 }
 
-static void __devexit pci_remove_one(struct pci_dev *dev)
+static void __devexit pciserial_remove_one(struct pci_dev *dev)
 {
 	struct serial_private *priv = pci_get_drvdata(dev);
-	int i;
 
 	pci_set_drvdata(dev, NULL);
 
 	if (priv) {
+		struct pci_serial_quirk *quirk;
+		int i;
+
 		for (i = 0; i < priv->nr; i++)
 			unregister_serial(priv->line[i]);
 
-		if (priv->board->init_fn)
-			priv->board->init_fn(dev, 0);
+		for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
+			if (priv->remapped_bar[i])
+				iounmap(priv->remapped_bar[i]);
+			priv->remapped_bar[i] = NULL;
+		}
+
+		/*
+		 * Find the exit quirks.
+		 */
+		quirk = find_quirk(dev);
+		if (quirk->exit)
+			quirk->exit(dev);
 
 		pci_disable_device(dev);
 
@@ -825,6 +1592,53 @@
 	}
 }
 
+static int pciserial_save_state_one(struct pci_dev *dev, u32 state)
+{
+	struct serial_private *priv = pci_get_drvdata(dev);
+
+	if (priv) {
+		int i;
+
+		for (i = 0; i < priv->nr; i++)
+			serial8250_suspend_port(priv->line[i], SUSPEND_SAVE_STATE);
+	}
+	return 0;
+}
+
+static int pciserial_suspend_one(struct pci_dev *dev, u32 state)
+{
+	struct serial_private *priv = pci_get_drvdata(dev);
+
+	if (priv) {
+		int i;
+
+		for (i = 0; i < priv->nr; i++)
+			serial8250_suspend_port(priv->line[i], SUSPEND_POWER_DOWN);
+	}
+	return 0;
+}
+
+static int pciserial_resume_one(struct pci_dev *dev)
+{
+	struct serial_private *priv = pci_get_drvdata(dev);
+
+	if (priv) {
+		int i;
+
+		/*
+		 * Ensure that the board is correctly configured.
+		 */
+		if (priv->quirk->init)
+			priv->quirk->init(dev);
+
+		for (i = 0; i < priv->nr; i++) {
+			serial8250_resume_port(priv->line[i], RESUME_POWER_ON);
+			serial8250_resume_port(priv->line[i], RESUME_RESTORE_STATE);
+		}
+	}
+	return 0;
+}
+
 static struct pci_device_id serial_pci_tbl[] __devinitdata = {
 	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
@@ -908,7 +1722,9 @@
 	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b2_bt_2_921600 },
-	/* VScom SPCOM800, from sl@s.pl */
+	/*
+	 * VScom SPCOM800, from sl@s.pl
+	 */
 	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, 
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 		pbn_b2_8_921600 },
@@ -949,8 +1765,10 @@
 		PCI_SUBVENDOR_ID_CHASE_PCIRAS,
 		PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, 
 		pbn_b2_8_460800 },
-	/* Megawolf Romulus PCI Serial Card, from Mike Hudson */
-	/* (Exoray@isys.ca) */
+	/*
+	 * Megawolf Romulus PCI Serial Card, from Mike Hudson
+	 * (Exoray@isys.ca)
+	 */
 	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
 		0x10b5, 0x106a, 0, 0,
 		pbn_plx_romulus },
@@ -976,16 +1794,24 @@
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 		pbn_b0_2_115200 },
 
-	/* Digitan DS560-558, from jimd@esoft.com */
+	/*
+	 * Digitan DS560-558, from jimd@esoft.com
+	 */
 	{	PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 		pbn_b1_1_115200 },
 
-	/* 3Com US Robotics 56k Voice Internal PCI model 5610 */
+	/*
+	 * 3Com US Robotics 56k Voice Internal PCI model 5610
+	 */
 	{	PCI_VENDOR_ID_USR, 0x1008,
-		PCI_ANY_ID, PCI_ANY_ID, },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_1_115200 },
 
-	/* Titan Electronic cards */
+	/*
+	 * Titan Electronic cards
+	 *  The 400L and 800L have a custom setup quirk.
+	 */
 	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 		pbn_b0_1_921600 },
@@ -999,120 +1825,76 @@
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 		pbn_b0_4_921600 },
 	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
-		PCI_ANY_ID, PCI_ANY_ID,
-		SPCI_FL_BASE1, 1, 921600 },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b1_1_921600 },
 	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
-		PCI_ANY_ID, PCI_ANY_ID,
-		SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-	/* The 400L and 800L have a custom hack in get_pci_port */
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b1_bt_2_921600 },
 	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
-		PCI_ANY_ID, PCI_ANY_ID,
-		SPCI_FL_BASE_TABLE, 4, 921600 },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_bt_4_921600 },
 	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
-		PCI_ANY_ID, PCI_ANY_ID,
-		SPCI_FL_BASE_TABLE, 8, 921600 },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_bt_8_921600 },
 
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_0 },
+		pbn_b2_1_460800 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_0 },
+		pbn_b2_1_460800 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_0 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_1 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_1 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_1 },
+		pbn_b2_1_460800 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_2 },
+		pbn_b2_bt_2_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_2 },
+		pbn_b2_bt_2_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_2 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_2 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_2 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_2 },
+		pbn_b2_bt_2_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_4 },
+		pbn_b2_bt_4_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_4 },
+		pbn_b2_bt_4_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig10x_4 },
+		pbn_b2_bt_4_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
+		pbn_b0_1_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
+		pbn_b0_1_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_0 },
+		pbn_b0_1_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_2 },
+		pbn_b0_bt_2_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_2 },
+		pbn_b0_bt_2_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_2 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_2 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_2 },
-	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_2 },
+		pbn_b0_bt_2_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_4 },
+		pbn_b0_bt_4_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_4 },
+		pbn_b0_bt_4_921600 },
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_siig20x_4 },
+		pbn_b0_bt_4_921600 },
 
-	/* Computone devices submitted by Doug McNash dmcnash@computone.com */
+	/*
+	 * Computone devices submitted by Doug McNash dmcnash@computone.com
+	 */
 	{	PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
 		PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
 		0, 0, pbn_computone_4 },
@@ -1124,18 +1906,22 @@
 		0, 0, pbn_computone_6 },
 
 	{	PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_oxsemi },
 	{	PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
-		PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
+		PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
+		pbn_b0_bt_1_921600 },
 
-	{	PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_b0_bt_2_115200 },
-	/* AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org> */
+	/*
+	 * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org>
+	 */
 	{	PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b0_bt_8_115200 },
 
+	{	PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_bt_2_115200 },
 	{	PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b0_bt_2_115200 },
@@ -1158,26 +1944,40 @@
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b0_bt_1_460800 },
 
-	/* RAStel 2 port modem, gerg@moreton.com.au */
+	/*
+	 * RAStel 2 port modem, gerg@moreton.com.au
+	 */
 	{	PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b2_bt_2_115200 },
 
-	/* EKF addition for i960 Boards form EKF with serial port */
-	{	PCI_VENDOR_ID_INTEL, 0x1960,
+	/*
+	 * EKF addition for i960 Boards form EKF with serial port
+	 */
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP,
 		0xE4BF, PCI_ANY_ID, 0, 0,
 		pbn_intel_i960 },
 
-	/* Xircom Cardbus/Ethernet combos */
+	/*
+	 * Xircom Cardbus/Ethernet combos
+	 */
 	{	PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_xircom_combo },
+		pbn_b0_1_115200 },
+	/*
+	 * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry)
+	 */
+	{	PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_1_115200 },
 
 	/*
 	 * Untested PCI modems, sent in from various folks...
 	 */
 
-	/* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
+	/*
+	 * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de>
+	 */
 	{	PCI_VENDOR_ID_ROCKWELL, 0x1004,
 		0x1048, 0x1500, 0, 0,
 		pbn_b1_1_115200 },
@@ -1186,10 +1986,12 @@
 		0xFF00, 0, 0, 0,
 		pbn_sgi_ioc3 },
 
-	/* HP Diva card */
+	/*
+	 * HP Diva card
+	 */
 	{	PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_hp_diva },
+		pbn_b0_5_115200 },
 	{	PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b2_1_115200 },
@@ -1203,15 +2005,14 @@
 
 	{	PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_dci_pccom4 },
+		pbn_b3_4_115200 },
 	{	PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-		pbn_dci_pccom8 },
+		pbn_b3_8_115200 },
 
 	/*
-	 * These entries match devices with class
-	 * COMMUNICATION_SERIAL, COMMUNICATION_MODEM
-	 * or COMMUNICATION_MULTISERIAL
+	 * These entries match devices with class COMMUNICATION_SERIAL,
+	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
 	 */
 	{	PCI_ANY_ID, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
@@ -1230,9 +2031,15 @@
 
 static struct pci_driver serial_pci_driver = {
 	.name		= "serial",
-	.probe		= pci_init_one,
-	.remove		= __devexit_p(pci_remove_one),
+	.probe		= pciserial_init_one,
+	.remove		= __devexit_p(pciserial_remove_one),
+	.save_state	= pciserial_save_state_one,
+	.suspend	= pciserial_suspend_one,
+	.resume		= pciserial_resume_one,
 	.id_table	= serial_pci_tbl,
+	.driver = {
+		.devclass = &tty_devclass,
+	},
 };
 
 static int __init serial8250_pci_init(void)
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/drivers/serial/Kconfig	Mon Mar 10 16:26:26 2003
@@ -412,9 +412,10 @@
 	help
 	  This driver supports the SCC serial ports of the Motorola 68360 CPU.
 
-config 68360_SERIAL
+config SERIAL_68360
 	bool
-	depends on SERIAL_68360_SMC || SERIAL_68630_SCC
+	depends on SERIAL_68360_SMC || SERIAL_68360_SCC
+	default y
 
 endmenu
 
diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c
--- a/drivers/serial/amba.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/amba.c	Thu Mar  6 09:28:07 2003
@@ -705,10 +705,11 @@
 	.index		= -1,
 };
 
-void __init ambauart_console_init(void)
+static void __init ambauart_console_init(void)
 {
 	register_console(&amba_console);
 }
+console_initcall(ambauart_console_init);
 
 #define AMBA_CONSOLE	&amba_console
 #else
diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c
--- a/drivers/serial/anakin.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/anakin.c	Thu Mar  6 09:28:07 2003
@@ -502,11 +502,12 @@
 	.index		= -1,
 };
 
-void __init
+static void __init
 anakin_console_init(void)
 {
 	register_console(&anakin_console);
 }
+console_initcall(anakin_console_init);
 
 #define ANAKIN_CONSOLE		&anakin_console
 #else
diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
--- a/drivers/serial/clps711x.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/clps711x.c	Thu Mar  6 09:28:07 2003
@@ -567,10 +567,11 @@
 	.index		= -1,
 };
 
-void __init clps711xuart_console_init(void)
+static void __init clps711xuart_console_init(void)
 {
 	register_console(&clps711x_console);
 }
+console_initcall(clps711xuart_console_init);
 
 #define CLPS711X_CONSOLE	&clps711x_console
 #else
diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c
--- a/drivers/serial/core.c	Mon Feb 24 15:32:22 2003
+++ b/drivers/serial/core.c	Wed Mar 12 01:53:30 2003
@@ -21,9 +21,6 @@
  * 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
- *
- *  $Id: core.c,v 1.100 2002/07/28 10:03:28 rmk Exp $
- *
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -31,9 +28,9 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/console.h>
-#include <linux/pm.h>
 #include <linux/serial_core.h>
 #include <linux/smp_lock.h>
+#include <linux/device.h>
 #include <linux/serial.h> /* for serial_state and serial_icounter_struct */
 
 #include <asm/irq.h>
@@ -46,11 +43,6 @@
 #define DPRINTK(x...)	do { } while (0)
 #endif
 
-#ifndef CONFIG_PM
-#define pm_access(pm)		do { } while (0)
-#define pm_unregister(pm)	do { } while (0)
-#endif
-
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -58,8 +50,17 @@
 
 #define HIGH_BITS_OFFSET	((sizeof(long)-sizeof(int))*8)
 
-static void uart_change_speed(struct uart_info *info, struct termios *old_termios);
+#define uart_users(state)	((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
+
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+#define uart_console(port)	((port)->cons && (port)->cons->index == (port)->line)
+#else
+#define uart_console(port)	(0)
+#endif
+
+static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
 static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
+static void uart_change_pm(struct uart_state *state, int pm_state);
 
 /*
  * This routine is used by the interrupt handler to schedule processing in
@@ -73,8 +74,8 @@
 
 static void uart_stop(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
-	struct uart_port *port = info->port;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 	unsigned long flags;
 
 	spin_lock_irqsave(&port->lock, flags);
@@ -84,32 +85,31 @@
 
 static void __uart_start(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
-	struct uart_port *port = info->port;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 
-	if (!uart_circ_empty(&info->xmit) && info->xmit.buf &&
+	if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
 	    !tty->stopped && !tty->hw_stopped)
 		port->ops->start_tx(port, 1);
 }
 
 static void uart_start(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 	unsigned long flags;
 
-	pm_access(info->state->pm);
-
-	spin_lock_irqsave(&info->port->lock, flags);
+	spin_lock_irqsave(&port->lock, flags);
 	__uart_start(tty);
-	spin_unlock_irqrestore(&info->port->lock, flags);
+	spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void uart_tasklet_action(unsigned long data)
 {
-	struct uart_info *info = (struct uart_info *)data;
+	struct uart_state *state = (struct uart_state *)data;
 	struct tty_struct *tty;
 
-	tty = info->tty;
+	tty = state->info->tty;
 	if (tty) {
 		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 		    tty->ldisc.write_wakeup)
@@ -137,11 +137,12 @@
 
 /*
  * Startup the port.  This will be called once per open.  All calls
- * will be serialised by the global port semaphore.
+ * will be serialised by the per-port semaphore.
  */
-static int uart_startup(struct uart_info *info, int init_hw)
+static int uart_startup(struct uart_state *state, int init_hw)
 {
-	struct uart_port *port = info->port;
+	struct uart_info *info = state->info;
+	struct uart_port *port = state->port;
 	unsigned long page;
 	int retval = 0;
 
@@ -182,7 +183,7 @@
 			/*
 			 * Initialise the hardware port settings.
 			 */
-			uart_change_speed(info, NULL);
+			uart_change_speed(state, NULL);
 
 			/*
 			 * Setup the RTS and DTR signals once the
@@ -194,8 +195,7 @@
 
 		info->flags |= UIF_INITIALIZED;
 
-		if (info->tty)
-			clear_bit(TTY_IO_ERROR, &info->tty->flags);
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
 	}
 
 	if (retval && capable(CAP_SYS_ADMIN))
@@ -207,11 +207,12 @@
 /*
  * This routine will shutdown a serial port; interrupts are disabled, and
  * DTR is dropped if the hangup on close termio flag is on.  Calls to
- * uart_shutdown are serialised by port_sem.
+ * uart_shutdown are serialised by the per-port semaphore.
  */
-static void uart_shutdown(struct uart_info *info)
+static void uart_shutdown(struct uart_state *state)
 {
-	struct uart_port *port = info->port;
+	struct uart_info *info = state->info;
+	struct uart_port *port = state->port;
 
 	if (!(info->flags & UIF_INITIALIZED))
 		return;
@@ -220,7 +221,7 @@
 	 * Turn off DTR and RTS early.
 	 */
 	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-		uart_clear_mctrl(info->port, TIOCM_DTR | TIOCM_RTS);
+		uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 
 	/*
 	 * clear delta_msr_wait queue to avoid mem leaks: we may free
@@ -412,10 +413,10 @@
 EXPORT_SYMBOL(uart_get_divisor);
 
 static void
-uart_change_speed(struct uart_info *info, struct termios *old_termios)
+uart_change_speed(struct uart_state *state, struct termios *old_termios)
 {
-	struct tty_struct *tty = info->tty;
-	struct uart_port *port = info->port;
+	struct tty_struct *tty = state->info->tty;
+	struct uart_port *port = state->port;
 	struct termios *termios;
 
 	/*
@@ -431,14 +432,14 @@
 	 * Set flags based on termios cflag
 	 */
 	if (termios->c_cflag & CRTSCTS)
-		info->flags |= UIF_CTS_FLOW;
+		state->info->flags |= UIF_CTS_FLOW;
 	else
-		info->flags &= ~UIF_CTS_FLOW;
+		state->info->flags &= ~UIF_CTS_FLOW;
 
 	if (termios->c_cflag & CLOCAL)
-		info->flags &= ~UIF_CHECK_CD;
+		state->info->flags &= ~UIF_CHECK_CD;
 	else
-		info->flags |= UIF_CHECK_CD;
+		state->info->flags |= UIF_CHECK_CD;
 
 	port->ops->set_termios(port, termios, old_termios);
 }
@@ -526,10 +527,10 @@
 
 static void uart_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
 
 	if (tty)
-		__uart_put_char(info->port, &info->xmit, ch);
+		__uart_put_char(state->port, &state->info->xmit, ch);
 }
 
 static void uart_flush_chars(struct tty_struct *tty)
@@ -541,16 +542,16 @@
 uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf,
 	   int count)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
 	int ret;
 
-	if (!tty || !info->xmit.buf)
+	if (!tty || !state->info->xmit.buf)
 		return 0;
 
 	if (from_user)
-		ret = __uart_user_write(info->port, &info->xmit, buf, count);
+		ret = __uart_user_write(state->port, &state->info->xmit, buf, count);
 	else
-		ret = __uart_kern_write(info->port, &info->xmit, buf, count);
+		ret = __uart_kern_write(state->port, &state->info->xmit, buf, count);
 
 	uart_start(tty);
 	return ret;
@@ -558,29 +559,30 @@
 
 static int uart_write_room(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
 
-	return uart_circ_chars_free(&info->xmit);
+	return uart_circ_chars_free(&state->info->xmit);
 }
 
 static int uart_chars_in_buffer(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
 
-	return uart_circ_chars_pending(&info->xmit);
+	return uart_circ_chars_pending(&state->info->xmit);
 }
 
 static void uart_flush_buffer(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 	unsigned long flags;
 
 	DPRINTK("uart_flush_buffer(%d) called\n",
 	        minor(tty->device) - tty->driver.minor_start);
 
-	spin_lock_irqsave(&info->port->lock, flags);
-	uart_circ_clear(&info->xmit);
-	spin_unlock_irqrestore(&info->port->lock, flags);
+	spin_lock_irqsave(&port->lock, flags);
+	uart_circ_clear(&state->info->xmit);
+	spin_unlock_irqrestore(&port->lock, flags);
 	wake_up_interruptible(&tty->write_wait);
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 	    tty->ldisc.write_wakeup)
@@ -593,8 +595,8 @@
  */
 static void uart_send_xchar(struct tty_struct *tty, char ch)
 {
-	struct uart_info *info = tty->driver_data;
-	struct uart_port *port = info->port;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 	unsigned long flags;
 
 	if (port->ops->send_xchar)
@@ -611,19 +613,19 @@
 
 static void uart_throttle(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
 
 	if (I_IXOFF(tty))
 		uart_send_xchar(tty, STOP_CHAR(tty));
 
 	if (tty->termios->c_cflag & CRTSCTS)
-		uart_clear_mctrl(info->port, TIOCM_RTS);
+		uart_clear_mctrl(state->port, TIOCM_RTS);
 }
 
 static void uart_unthrottle(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
-	struct uart_port *port = info->port;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 
 	if (I_IXOFF(tty)) {
 		if (port->x_char)
@@ -636,10 +638,9 @@
 		uart_set_mctrl(port, TIOCM_RTS);
 }
 
-static int uart_get_info(struct uart_info *info, struct serial_struct *retinfo)
+static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo)
 {
-	struct uart_state *state = info->state;
-	struct uart_port *port = info->port;
+	struct uart_port *port = state->port;
 	struct serial_struct tmp;
 
 	memset(&tmp, 0, sizeof(tmp));
@@ -649,7 +650,7 @@
 	if (HIGH_BITS_OFFSET)
 		tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
 	tmp.irq		    = port->irq;
-	tmp.flags	    = port->flags | info->flags;
+	tmp.flags	    = port->flags;
 	tmp.xmit_fifo_size  = port->fifosize;
 	tmp.baud_base	    = port->uartclk / 16;
 	tmp.close_delay	    = state->close_delay;
@@ -666,11 +667,10 @@
 }
 
 static int
-uart_set_info(struct uart_info *info, struct serial_struct *newinfo)
+uart_set_info(struct uart_state *state, struct serial_struct *newinfo)
 {
 	struct serial_struct new_serial;
-	struct uart_state *state = info->state;
-	struct uart_port *port = info->port;
+	struct uart_port *port = state->port;
 	unsigned long new_port;
 	unsigned int change_irq, change_port, old_flags;
 	unsigned int old_custom_divisor;
@@ -692,7 +692,7 @@
 	 * module insertion/removal doesn't change anything
 	 * under us.
 	 */
-	down(&port_sem);
+	down(&state->sem);
 
 	change_irq  = new_serial.irq != port->irq;
 
@@ -745,14 +745,14 @@
 		/*
 		 * Make sure that we are the sole user of this port.
 		 */
-		if (state->count > 1 || info->blocked_open != 0)
+		if (uart_users(state) > 1)
 			goto exit;
 
 		/*
 		 * We need to shutdown the serial port at the old
 		 * port/type/irq combination.
 		 */
-		uart_shutdown(info);
+		uart_shutdown(state);
 	}
 
 	if (change_port) {
@@ -813,18 +813,21 @@
 
 	port->irq              = new_serial.irq;
 	port->uartclk          = new_serial.baud_base * 16;
-	port->flags            = new_serial.flags & UPF_CHANGE_MASK;
+	port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
+				 (new_serial.flags & UPF_CHANGE_MASK);
 	port->custom_divisor   = new_serial.custom_divisor;
 	state->close_delay     = new_serial.close_delay * HZ / 100;
 	state->closing_wait    = new_serial.closing_wait * HZ / 100;
 	port->fifosize         = new_serial.xmit_fifo_size;
-	info->tty->low_latency = (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
+	if (state->info->tty)
+		state->info->tty->low_latency =
+			(port->flags & UPF_LOW_LATENCY) ? 1 : 0;
 
  check_and_exit:
 	retval = 0;
 	if (port->type == PORT_UNKNOWN)
 		goto exit;
-	if (info->flags & UIF_INITIALIZED) {
+	if (state->info->flags & UIF_INITIALIZED) {
 		if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
 		    old_custom_divisor != port->custom_divisor) {
 			/* If they're setting up a custom divisor or speed,
@@ -832,25 +835,26 @@
 			 * need to rate-limit; it's CAP_SYS_ADMIN only. */
 			if (port->flags & UPF_SPD_MASK) {
 				printk(KERN_NOTICE "%s sets custom speed on %s%d. This is deprecated.\n",
-				       current->comm, info->tty->driver.name, 
-				       info->port->line);
+				       current->comm, state->info->tty->driver.name, 
+				       state->port->line);
 			}
-			uart_change_speed(info, NULL);
+			uart_change_speed(state, NULL);
 		}
 	} else
-		retval = uart_startup(info, 1);
+		retval = uart_startup(state, 1);
  exit:
-	up(&port_sem);
+	up(&state->sem);
 	return retval;
 }
 
 
 /*
- * uart_get_lsr_info - get line status register info
+ * uart_get_lsr_info - get line status register info.
+ * Note: uart_ioctl protects us against hangups.
  */
-static int uart_get_lsr_info(struct uart_info *info, unsigned int *value)
+static int uart_get_lsr_info(struct uart_state *state, unsigned int *value)
 {
-	struct uart_port *port = info->port;
+	struct uart_port *port = state->port;
 	unsigned int result;
 
 	result = port->ops->tx_empty(port);
@@ -861,9 +865,9 @@
 	 * avoid a race condition (depending on when the transmit
 	 * interrupt happens).
 	 */
-	if (info->port->x_char ||
-	    ((uart_circ_chars_pending(&info->xmit) > 0) &&
-	     !info->tty->stopped && !info->tty->hw_stopped))
+	if (port->x_char ||
+	    ((uart_circ_chars_pending(&state->info->xmit) > 0) &&
+	     !state->info->tty->stopped && !state->info->tty->hw_stopped))
 		result &= ~TIOCSER_TEMT;
 	
 	return put_user(result, value);
@@ -888,6 +892,8 @@
 	if (get_user(arg, value))
 		return -EFAULT;
 
+	arg &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2;
+
 	set = clear = 0;
 	switch (cmd) {
 	case TIOCMBIS:
@@ -911,8 +917,8 @@
 
 static void uart_break_ctl(struct tty_struct *tty, int break_state)
 {
-	struct uart_info *info = tty->driver_data;
-	struct uart_port *port = info->port;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 
 	BUG_ON(!kernel_locked());
 
@@ -920,25 +926,25 @@
 		port->ops->break_ctl(port, break_state);
 }
 
-static int uart_do_autoconfig(struct uart_info *info)
+static int uart_do_autoconfig(struct uart_state *state)
 {
-	struct uart_port *port = info->port;
+	struct uart_port *port = state->port;
 	int flags, ret;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
 	/*
-	 * Take the 'count' lock.  This prevents count
-	 * from incrementing, and hence any extra opens
-	 * of the port while we're auto-configging.
+	 * Take the per-port semaphore.  This prevents count from
+	 * changing, and hence any extra opens of the port while
+	 * we're auto-configuring.
 	 */
-	if (down_interruptible(&port_sem))
+	if (down_interruptible(&state->sem))
 		return -ERESTARTSYS;
 
 	ret = -EBUSY;
-	if (info->state->count == 1 && info->blocked_open == 0) {
-		uart_shutdown(info);
+	if (uart_users(state) == 1) {
+		uart_shutdown(state);
 
 		/*
 		 * If we already have a port type configured,
@@ -957,16 +963,22 @@
 		 */
 		port->ops->config_port(port, flags);
 
-		ret = uart_startup(info, 1);
+		ret = uart_startup(state, 1);
 	}
-	up(&port_sem);
+	up(&state->sem);
 	return ret;
 }
 
+/*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
 static int
-uart_wait_modem_status(struct uart_info *info, unsigned long arg)
+uart_wait_modem_status(struct uart_state *state, unsigned long arg)
 {
-	struct uart_port *port = info->port;
+	struct uart_port *port = state->port;
 	DECLARE_WAITQUEUE(wait, current);
 	struct uart_icount cprev, cnow;
 	int ret;
@@ -983,7 +995,7 @@
 	port->ops->enable_ms(port);
 	spin_unlock_irq(&port->lock);
 
-	add_wait_queue(&info->delta_msr_wait, &wait);
+	add_wait_queue(&state->info->delta_msr_wait, &wait);
 	for (;;) {
 		spin_lock_irq(&port->lock);
 		memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
@@ -1011,117 +1023,144 @@
 	}
 
 	current->state = TASK_RUNNING;
-	remove_wait_queue(&info->delta_msr_wait, &wait);
+	remove_wait_queue(&state->info->delta_msr_wait, &wait);
 
 	return ret;
 }
 
 /*
- * Called via sys_ioctl under the BKL.  We can use spin_lock_irq() here.
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ *     RI where only 0->1 is counted.
  */
 static int
-uart_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
-	   unsigned long arg)
+uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt)
 {
-	struct uart_info *info = tty->driver_data;
 	struct serial_icounter_struct icount;
 	struct uart_icount cnow;
+	struct uart_port *port = state->port;
+
+	spin_lock_irq(&port->lock);
+	memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
+	spin_unlock_irq(&port->lock);
+
+	icount.cts         = cnow.cts;
+	icount.dsr         = cnow.dsr;
+	icount.rng         = cnow.rng;
+	icount.dcd         = cnow.dcd;
+	icount.rx          = cnow.rx;
+	icount.tx          = cnow.tx;
+	icount.frame       = cnow.frame;
+	icount.overrun     = cnow.overrun;
+	icount.parity      = cnow.parity;
+	icount.brk         = cnow.brk;
+	icount.buf_overrun = cnow.buf_overrun;
+
+	return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+}
+
+/*
+ * Called via sys_ioctl under the BKL.  We can use spin_lock_irq() here.
+ */
+static int
+uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
+	   unsigned long arg)
+{
+	struct uart_state *state = tty->driver_data;
 	int ret = -ENOIOCTLCMD;
 
 	BUG_ON(!kernel_locked());
 
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-			return -EIO;
+	/*
+	 * These ioctls don't rely on the hardware to be present.
+	 */
+	switch (cmd) {
+	case TIOCGSERIAL:
+		ret = uart_get_info(state, (struct serial_struct *)arg);
+		break;
+
+	case TIOCSSERIAL:
+		ret = uart_set_info(state, (struct serial_struct *)arg);
+		break;
+
+	case TIOCSERCONFIG:
+		ret = uart_do_autoconfig(state);
+		break;
+
+	case TIOCSERGWILD: /* obsolete */
+	case TIOCSERSWILD: /* obsolete */
+		ret = 0;
+		break;
 	}
 
-	switch (cmd) {
-		case TIOCMGET:
-			ret = uart_get_modem_info(info->port,
-						  (unsigned int *)arg);
-			break;
+	if (ret != -ENOIOCTLCMD)
+		goto out;
 
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			ret = uart_set_modem_info(info->port, cmd,
-						  (unsigned int *)arg);
-			break;
+	if (tty->flags & (1 << TTY_IO_ERROR)) {
+		ret = -EIO;
+		goto out;
+	}
 
-		case TIOCGSERIAL:
-			ret = uart_get_info(info, (struct serial_struct *)arg);
-			break;
+	/*
+	 * The following should only be used when hardware is present.
+	 */
+	switch (cmd) {
+	case TIOCMIWAIT:
+		ret = uart_wait_modem_status(state, arg);
+		break;
 
-		case TIOCSSERIAL:
-			ret = uart_set_info(info, (struct serial_struct *)arg);
-			break;
+	case TIOCGICOUNT:
+		ret = uart_get_count(state, (struct serial_icounter_struct *)arg);
+		break;
+	}
 
-		case TIOCSERCONFIG:
-			ret = uart_do_autoconfig(info);
-			break;
+	if (ret != -ENOIOCTLCMD)
+		goto out;
 
-		case TIOCSERGETLSR: /* Get line status register */
-			ret = uart_get_lsr_info(info, (unsigned int *)arg);
-			break;
+	down(&state->sem);
 
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
-		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-		case TIOCMIWAIT:
-			ret = uart_wait_modem_status(info, arg);
-			break;
+	if (tty_hung_up_p(filp)) {
+		ret = -EIO;
+		goto out_up;
+	}
 
-		/*
-		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-		 * Return: write counters to the user passed counter struct
-		 * NB: both 1->0 and 0->1 transitions are counted except for
-		 *     RI where only 0->1 is counted.
-		 */
-		case TIOCGICOUNT:
-			spin_lock_irq(&info->port->lock);
-			memcpy(&cnow, &info->port->icount,
-			       sizeof(struct uart_icount));
-			spin_unlock_irq(&info->port->lock);
-
-			icount.cts         = cnow.cts;
-			icount.dsr         = cnow.dsr;
-			icount.rng         = cnow.rng;
-			icount.dcd         = cnow.dcd;
-			icount.rx          = cnow.rx;
-			icount.tx          = cnow.tx;
-			icount.frame       = cnow.frame;
-			icount.overrun     = cnow.overrun;
-			icount.parity      = cnow.parity;
-			icount.brk         = cnow.brk;
-			icount.buf_overrun = cnow.buf_overrun;
+	/*
+	 * All these rely on hardware being present and need to be
+	 * protected against the tty being hung up.
+	 */
+	switch (cmd) {
+	case TIOCMGET:
+		ret = uart_get_modem_info(state->port, (unsigned int *)arg);
+		break;
 
-			ret = copy_to_user((void *)arg, &icount, sizeof(icount))
-					? -EFAULT : 0;
-			break;
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		ret = uart_set_modem_info(state->port, cmd,
+					  (unsigned int *)arg);
+		break;
 
-		case TIOCSERGWILD: /* obsolete */
-		case TIOCSERSWILD: /* obsolete */
-			ret = 0;
-			break;
+	case TIOCSERGETLSR: /* Get line status register */
+		ret = uart_get_lsr_info(state, (unsigned int *)arg);
+		break;
 
-		default: {
-			struct uart_port *port = info->port;
-			if (port->ops->ioctl)
-				ret = port->ops->ioctl(port, cmd, arg);
-			break;
-		}
+	default: {
+		struct uart_port *port = state->port;
+		if (port->ops->ioctl)
+			ret = port->ops->ioctl(port, cmd, arg);
+		break;
+	}
 	}
+ out_up:
+	up(&state->sem);
+ out:
 	return ret;
 }
 
 static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
 {
-	struct uart_info *info = tty->driver_data;
+	struct uart_state *state = tty->driver_data;
 	unsigned long flags;
 	unsigned int cflag = tty->termios->c_cflag;
 
@@ -1137,11 +1176,11 @@
 	    RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
 		return;
 
-	uart_change_speed(info, old_termios);
+	uart_change_speed(state, old_termios);
 
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-		uart_clear_mctrl(info->port, TIOCM_RTS | TIOCM_DTR);
+		uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
 
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
@@ -1149,15 +1188,15 @@
 		if (!(cflag & CRTSCTS) ||
 		    !test_bit(TTY_THROTTLED, &tty->flags))
 			mask |= TIOCM_RTS;
-		uart_set_mctrl(info->port, mask);
+		uart_set_mctrl(state->port, mask);
 	}
 
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-		spin_lock_irqsave(&info->port->lock, flags);
+		spin_lock_irqsave(&state->port->lock, flags);
 		tty->hw_stopped = 0;
 		__uart_start(tty);
-		spin_unlock_irqrestore(&info->port->lock, flags);
+		spin_unlock_irqrestore(&state->port->lock, flags);
 	}
 
 #if 0
@@ -1169,7 +1208,7 @@
 	 */
 	if (!(old_termios->c_cflag & CLOCAL) &&
 	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
+		wake_up_interruptible(&state->info->open_wait);
 #endif
 }
 
@@ -1180,29 +1219,17 @@
  */
 static void uart_close(struct tty_struct *tty, struct file *filp)
 {
-	struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
-	struct uart_info *info = tty->driver_data;
-	struct uart_port *port = info->port;
-	struct uart_state *state;
-	unsigned long flags;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 
 	BUG_ON(!kernel_locked());
+	DPRINTK("uart_close(%d) called\n", port->line);
 
-	if (!info)
-		return;
-
-	state = info->state;
-
-	DPRINTK("uart_close() called\n");
+	down(&state->sem);
 
-	/*
-	 * This is safe, as long as the BKL exists in
-	 * do_tty_hangup(), and we're protected by the BKL.
-	 */
 	if (tty_hung_up_p(filp))
 		goto done;
 
-	spin_lock_irqsave(&info->port->lock, flags);
 	if ((tty->count == 1) && (state->count != 1)) {
 		/*
 		 * Uh, oh.  tty->count is 1, which means that the tty
@@ -1217,34 +1244,28 @@
 	}
 	if (--state->count < 0) {
 		printk("rs_close: bad serial port count for %s%d: %d\n",
-		       tty->driver.name, info->port->line, state->count);
+		       tty->driver.name, port->line, state->count);
 		state->count = 0;
 	}
-	if (state->count) {
-		spin_unlock_irqrestore(&info->port->lock, flags);
+	if (state->count)
 		goto done;
-	}
-
-	/*
-	 * The UIF_CLOSING flag protects us against further opens
-	 * of this port.
-	 */
-	info->flags |= UIF_CLOSING;
-	spin_unlock_irqrestore(&info->port->lock, flags);
 
 	/*
 	 * Now we wait for the transmit buffer to clear; and we notify
-	 * the line discipline to only process XON/XOFF characters.
+	 * the line discipline to only process XON/XOFF characters by
+	 * setting tty->closing.
 	 */
 	tty->closing = 1;
-	if (info->state->closing_wait != USF_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->state->closing_wait);
+
+	if (state->closing_wait != USF_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, state->closing_wait);
 
 	/*
 	 * At this point, we stop accepting input.  To do this, we
 	 * disable the receive line status interrupts.
 	 */
-	if (info->flags & UIF_INITIALIZED) {
+	if (state->info->flags & UIF_INITIALIZED) {
+		unsigned long flags;
 		spin_lock_irqsave(&port->lock, flags);
 		port->ops->stop_rx(port);
 		spin_unlock_irqrestore(&port->lock, flags);
@@ -1255,46 +1276,38 @@
 		 */
 		uart_wait_until_sent(tty, port->timeout);
 	}
-	down(&port_sem);
-	uart_shutdown(info);
-	up(&port_sem);
+
+	uart_shutdown(state);
 	uart_flush_buffer(tty);
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 	tty->closing = 0;
-	info->tty = NULL;
-	if (info->blocked_open) {
-		if (info->state->close_delay) {
+	state->info->tty = NULL;
+
+	if (state->info->blocked_open) {
+		if (state->close_delay) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(info->state->close_delay);
+			schedule_timeout(state->close_delay);
 			set_current_state(TASK_RUNNING);
 		}
-	} else {
-#ifdef CONFIG_PM
-		/*
-		 * Put device into D3 state.
-		 */
-		pm_send(info->state->pm, PM_SUSPEND, (void *)3);
-#else
-		if (port->ops->pm)
-			port->ops->pm(port, 3, 0);
-#endif
+	} else if (!uart_console(port)) {
+		uart_change_pm(state, 3);
 	}
 
 	/*
 	 * Wake up anyone trying to open this port.
 	 */
-	info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CLOSING);
-	wake_up_interruptible(&info->open_wait);
+	state->info->flags &= ~UIF_NORMAL_ACTIVE;
+	wake_up_interruptible(&state->info->open_wait);
 
  done:
-	module_put(drv->owner);
+	up(&state->sem);
 }
 
 static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
 {
-	struct uart_info *info = tty->driver_data;
-	struct uart_port *port = info->port;
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
 	unsigned long char_time, expire;
 
 	BUG_ON(!kernel_locked());
@@ -1358,23 +1371,22 @@
  */
 static void uart_hangup(struct tty_struct *tty)
 {
-	struct uart_info *info = tty->driver_data;
-	struct uart_state *state = info->state;
+	struct uart_state *state = tty->driver_data;
 
 	BUG_ON(!kernel_locked());
+	DPRINTK("uart_hangup(%d)\n", state->port->line);
 
-	uart_flush_buffer(tty);
-	down(&port_sem);
-	if (info->flags & UIF_CLOSING) {
-		up(&port_sem);
-		return;
+	down(&state->sem);
+	if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
+		uart_flush_buffer(tty);
+		uart_shutdown(state);
+		state->count = 0;
+		state->info->flags &= ~UIF_NORMAL_ACTIVE;
+		state->info->tty = NULL;
+		wake_up_interruptible(&state->info->open_wait);
+		wake_up_interruptible(&state->info->delta_msr_wait);
 	}
-	uart_shutdown(info);
-	state->count = 0;
-	info->flags &= ~UIF_NORMAL_ACTIVE;
-	info->tty = NULL;
-	up(&port_sem);
-	wake_up_interruptible(&info->open_wait);
+	up(&state->sem);
 }
 
 /*
@@ -1383,18 +1395,15 @@
  * kernel settings, and the settings init adopts when it opens the port
  * for the first time.
  */
-static void uart_update_termios(struct uart_info *info)
+static void uart_update_termios(struct uart_state *state)
 {
-	struct tty_struct *tty = info->tty;
-
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-	struct console *c = info->port->cons;
+	struct tty_struct *tty = state->info->tty;
+	struct uart_port *port = state->port;
 
-	if (c && c->cflag && c->index == info->port->line) {
-		tty->termios->c_cflag = c->cflag;
-		c->cflag = 0;
+	if (uart_console(port) && port->cons->cflag) {
+		tty->termios->c_cflag = port->cons->cflag;
+		port->cons->cflag = 0;
 	}
-#endif
 
 	/*
 	 * If the device failed to grab its irq resources,
@@ -1405,22 +1414,26 @@
 		/*
 		 * Make termios settings take effect.
 		 */
-		uart_change_speed(info, NULL);
+		uart_change_speed(state, NULL);
 
 		/*
 		 * And finally enable the RTS and DTR signals.
 		 */
 		if (tty->termios->c_cflag & CBAUD)
-			uart_set_mctrl(info->port, TIOCM_DTR | TIOCM_RTS);
+			uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	}
 }
 
+/*
+ * Block the open until the port is ready.  We must be called with
+ * the per-port semaphore held.
+ */
 static int
-uart_block_til_ready(struct file *filp, struct uart_info *info)
+uart_block_til_ready(struct file *filp, struct uart_state *state)
 {
 	DECLARE_WAITQUEUE(wait, current);
-	struct uart_state *state = info->state;
-	struct uart_port *port = info->port;
+	struct uart_info *info = state->info;
+	struct uart_port *port = state->port;
 
 	info->blocked_open++;
 	state->count--;
@@ -1432,18 +1445,10 @@
 		/*
 		 * If we have been hung up, tell userspace/restart open.
 		 */
-		if (tty_hung_up_p(filp))
+		if (tty_hung_up_p(filp) || info->tty == NULL)
 			break;
 
 		/*
-		 * If the device is in the middle of being closed, block
-		 * until it's done.  We will need to re-initialise the
-		 * port.  Hmm, is it legal to block a non-blocking open?
-		 */
-		if (info->flags & UIF_CLOSING)
-			goto wait;
-
-		/*
 		 * If the port has been closed, tell userspace/restart open.
 		 */
 		if (!(info->flags & UIF_INITIALIZED))
@@ -1470,7 +1475,7 @@
 		 * the data from the modem.
 		 */
 		if (info->tty->termios->c_cflag & CBAUD)
-			uart_set_mctrl(info->port, TIOCM_DTR);
+			uart_set_mctrl(port, TIOCM_DTR);
 
 		/*
 		 * and wait for the carrier to indicate that the
@@ -1479,8 +1484,9 @@
 		if (port->ops->get_mctrl(port) & TIOCM_CAR)
 			break;
 
-	 wait:
+		up(&state->sem);
 		schedule();
+		down(&state->sem);
 
 		if (signal_pending(current))
 			break;
@@ -1494,52 +1500,56 @@
 	if (signal_pending(current))
 		return -ERESTARTSYS;
 
-	if (info->tty->flags & (1 << TTY_IO_ERROR))
-		return 0;
-
-	if (tty_hung_up_p(filp) || !(info->flags & UIF_INITIALIZED))
+	if (!info->tty || tty_hung_up_p(filp))
 		return (port->flags & UPF_HUP_NOTIFY) ?
 			-EAGAIN : -ERESTARTSYS;
 
 	return 0;
 }
 
-static struct uart_info *uart_get(struct uart_driver *drv, int line)
+static struct uart_state *uart_get(struct uart_driver *drv, int line)
 {
-	struct uart_state *state = drv->state + line;
-	struct uart_info *info = NULL;
+	struct uart_state *state;
 
 	down(&port_sem);
-	if (!state->port)
+	state = drv->state + line;
+	if (down_interruptible(&state->sem)) {
+		state = ERR_PTR(-ERESTARTSYS);
 		goto out;
+	}
 
 	state->count++;
-	info = state->info;
+	if (!state->port) {
+		state->count--;
+		up(&state->sem);
+		state = ERR_PTR(-ENXIO);
+		goto out;
+	}
 
-	if (!info) {
-		info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
-		if (info) {
-			memset(info, 0, sizeof(struct uart_info));
-			init_waitqueue_head(&info->open_wait);
-			init_waitqueue_head(&info->delta_msr_wait);
+	if (!state->info) {
+		state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
+		if (state->info) {
+			memset(state->info, 0, sizeof(struct uart_info));
+			init_waitqueue_head(&state->info->open_wait);
+			init_waitqueue_head(&state->info->delta_msr_wait);
 
 			/*
 			 * Link the info into the other structures.
 			 */
-			info->port  = state->port;
-			info->state = state;
-			state->port->info = info;
-
-			tasklet_init(&info->tlet, uart_tasklet_action,
-				     (unsigned long)info);
-			state->info = info;
-		} else
+			state->port->info = state->info;
+
+			tasklet_init(&state->info->tlet, uart_tasklet_action,
+				     (unsigned long)state);
+		} else {
 			state->count--;
+			up(&state->sem);
+			state = ERR_PTR(-ENOMEM);
+		}
 	}
 
  out:
 	up(&port_sem);
-	return info;
+	return state;
 }
 
 /*
@@ -1555,11 +1565,10 @@
 static int uart_open(struct tty_struct *tty, struct file *filp)
 {
 	struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
-	struct uart_info *info;
+	struct uart_state *state;
 	int retval, line = minor(tty->device) - tty->driver.minor_start;
 
 	BUG_ON(!kernel_locked());
-
 	DPRINTK("uart_open(%d) called\n", line);
 
 	/*
@@ -1572,92 +1581,66 @@
 		goto fail;
 
 	/*
-	 * If we fail to increment the module use count, we can't have
-	 * any other users of this tty (since this implies that the module
-	 * is about to be unloaded).  Therefore, it is safe to set
-	 * tty->driver_data to be NULL, so uart_close() doesn't bite us.
-	 */
-	if (!try_module_get(drv->owner)) {
-		tty->driver_data = NULL;
+	 * We take the semaphore inside uart_get to guarantee that we won't
+	 * be re-entered while allocating the info structure, or while we
+	 * request any IRQs that the driver may need.  This also has the nice
+	 * side-effect that it delays the action of uart_hangup, so we can
+	 * guarantee that info->tty will always contain something reasonable.
+	 */
+	state = uart_get(drv, line);
+	if (IS_ERR(state)) {
+		retval = PTR_ERR(state);
 		goto fail;
 	}
 
 	/*
-	 * FIXME: This one isn't fun.  We can't guarantee that the tty isn't
-	 * already in open, nor can we guarantee the state of tty->driver_data
-	 */
-	info = uart_get(drv, line);
-	retval = -ENOMEM;
-	if (!info) {
-		if (tty->driver_data)
-			goto fail;
-		else
-			goto out;
-	}
-
-	/*
 	 * Once we set tty->driver_data here, we are guaranteed that
 	 * uart_close() will decrement the driver module use count.
 	 * Any failures from here onwards should not touch the count.
 	 */
-	tty->driver_data = info;
-	tty->low_latency = (info->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
+	tty->driver_data = state;
+	tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
 	tty->alt_speed = 0;
-	info->tty = tty;
+	state->info->tty = tty;
 
 	/*
 	 * If the port is in the middle of closing, bail out now.
 	 */
-	if (tty_hung_up_p(filp) || (info->flags & UIF_CLOSING)) {
-	    	wait_event_interruptible(info->open_wait,
-					 !(info->flags & UIF_CLOSING));
-		retval = (info->port->flags & UPF_HUP_NOTIFY) ?
+	if (tty_hung_up_p(filp)) {
+		retval = (state->port->flags & UPF_HUP_NOTIFY) ?
 			-EAGAIN : -ERESTARTSYS;
+		state->count--;
+		up(&state->sem);
 		goto fail;
 	}
 
 	/*
 	 * Make sure the device is in D0 state.
 	 */
-	if (info->state->count == 1) {
-#ifdef CONFIG_PM
-		pm_send(info->state->pm, PM_RESUME, (void *)0);
-#else
-		struct uart_port *port = info->port;
-		if (port->ops->pm)
-			port->ops->pm(port, 0, 3);
-#endif
-	}
+	if (state->count == 1)
+		uart_change_pm(state, 0);
 
 	/*
-	 * Start up the serial port.  We have this semaphore here to
-	 * prevent uart_startup or uart_shutdown being re-entered if
-	 * we sleep while requesting an IRQ.
+	 * Start up the serial port.
 	 */
-	down(&port_sem);
-	retval = uart_startup(info, 0);
-	up(&port_sem);
-	if (retval)
-		goto fail;
+	retval = uart_startup(state, 0);
 
 	/*
-	 * Wait until the port is ready.
+	 * If we succeeded, wait until the port is ready.
 	 */
-	retval = uart_block_til_ready(filp, info);
+	if (retval == 0)
+		retval = uart_block_til_ready(filp, state);
+	up(&state->sem);
 
 	/*
 	 * If this is the first open to succeed, adjust things to suit.
 	 */
-	if (retval == 0 && !(info->flags & UIF_NORMAL_ACTIVE)) {
-		info->flags |= UIF_NORMAL_ACTIVE;
+	if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) {
+		state->info->flags |= UIF_NORMAL_ACTIVE;
 
-		uart_update_termios(info);
+		uart_update_termios(state);
 	}
 
-	return retval;
-
- out:
-	module_put(drv->owner);
  fail:
 	return retval;
 }
@@ -1890,153 +1873,100 @@
 
 	return 0;
 }
+#endif /* CONFIG_SERIAL_CORE_CONSOLE */
 
-extern void ambauart_console_init(void);
-extern void anakin_console_init(void);
-extern void clps711xuart_console_init(void);
-extern void rs285_console_init(void);
-extern void sa1100_rs_console_init(void);
-extern void serial8250_console_init(void);
-extern void uart00_console_init(void);
-
-/*
- * Central "initialise all serial consoles" container.  Needs to be killed.
- */
-void __init uart_console_init(void)
+static void uart_change_pm(struct uart_state *state, int pm_state)
 {
-#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-	ambauart_console_init();
-#endif
-#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
-	anakin_console_init();
-#endif
-#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-	clps711xuart_console_init();
-#endif
-#ifdef CONFIG_SERIAL_21285_CONSOLE
-	rs285_console_init();
-#endif
-#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-	sa1100_rs_console_init();
-#endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-	serial8250_console_init();
-#endif
-#ifdef CONFIG_SERIAL_UART00_CONSOLE
-	uart00_console_init();
-#endif
+	struct uart_port *port = state->port;
+	if (port->ops->pm)
+		port->ops->pm(port, pm_state, state->pm_state);
+	state->pm_state = pm_state;
 }
-#endif /* CONFIG_SERIAL_CORE_CONSOLE */
 
-#ifdef CONFIG_PM
-/*
- *  Serial port power management.
- *
- * This is pretty coarse at the moment - either all on or all off.  We
- * should probably some day do finer power management here some day.
- *
- * We don't actually save any state; the serial driver already has the
- * state held internally to re-setup the port when we come out of D3.
- */
-static int uart_pm_set_state(struct uart_state *state, int pm_state, int oldstate)
+int uart_suspend_port(struct uart_driver *drv, struct uart_port *port, u32 level)
 {
-	struct uart_port *port;
-	struct uart_ops *ops;
-	int running = state->info &&
-		      state->info->flags & UIF_INITIALIZED;
+	struct uart_state *state = drv->state + port->line;
 
-	down(&port_sem);
+	down(&state->sem);
 
-	if (!state->port || state->port->type == PORT_UNKNOWN) {
-		up(&port_sem);
-		return 0;
-	}
-
-	port = state->port;
-	ops = port->ops;
+	switch (level) {
+	case SUSPEND_SAVE_STATE:
+		if (state->info && state->info->flags & UIF_INITIALIZED) {
+			struct uart_ops *ops = port->ops;
 
-	DPRINTK("pm: %08x: %d -> %d, %srunning\n",
-		port->iobase, dev->state, pm_state, running ? "" : "not ");
+			spin_lock_irq(&port->lock);
+			ops->stop_tx(port, 0);
+			ops->set_mctrl(port, 0);
+			ops->stop_rx(port);
+			spin_unlock_irq(&port->lock);
 
-	if (pm_state == 0) {
-		if (ops->pm)
-			ops->pm(port, pm_state, oldstate);
-		if (running) {
 			/*
-			 * The port lock isn't taken here -
-			 * the port isn't initialised.
+			 * Wait for the transmitter to empty.
 			 */
-			ops->set_mctrl(port, 0);
-			ops->startup(port);
-			uart_change_speed(state->info, NULL);
-			spin_lock_irq(&port->lock);
-			ops->set_mctrl(port, port->mctrl);
-			ops->start_tx(port, 0);
-			spin_unlock_irq(&port->lock);
+			while (!ops->tx_empty(port)) {
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(10*HZ/1000);
+			}
+			set_current_state(TASK_RUNNING);
+
+			ops->shutdown(port);
 		}
+		break;
 
-		/*
-		 * Re-enable the console device after suspending.
-		 */
-		if (port->cons && port->cons->index == port->line)
-			port->cons->flags |= CON_ENABLED;
-	} else if (pm_state == 1) {
-		if (ops->pm)
-			ops->pm(port, pm_state, oldstate);
-	} else {
+	case SUSPEND_POWER_DOWN:
 		/*
 		 * Disable the console device before suspending.
 		 */
-		if (port->cons && port->cons->index == port->line)
+		if (uart_console(port))
 			port->cons->flags &= ~CON_ENABLED;
 
-		if (running) {
-			spin_lock_irq(&port->lock);
-			ops->stop_tx(port, 0);
-			ops->set_mctrl(port, 0);
-			ops->stop_rx(port);
-			spin_unlock_irq(&port->lock);
-			ops->shutdown(port);
-		}
-		if (ops->pm)
-			ops->pm(port, pm_state, oldstate);
+		uart_change_pm(state, 3);
+		break;
 	}
-	up(&port_sem);
+
+	up(&state->sem);
 
 	return 0;
 }
 
-/*
- *  Wakeup support.
- */
-static int uart_pm_set_wakeup(struct uart_state *state, int data)
+int uart_resume_port(struct uart_driver *drv, struct uart_port *port, u32 level)
 {
-	int err = 0;
+	struct uart_state *state = drv->state + port->line;
 
-	if (state->port->ops->set_wake)
-		err = state->port->ops->set_wake(state->port, data);
+	down(&state->sem);
 
-	return err;
-}
-
-static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-	struct uart_state *state = dev->data;
-	int err = 0;
+	switch (level) {
+	case RESUME_POWER_ON:
+		uart_change_pm(state, 0);
 
-	switch (rqst) {
-	case PM_SUSPEND:
-	case PM_RESUME:
-		err = uart_pm_set_state(state, (int)(long)data, dev->state);
+		/*
+		 * Re-enable the console device after suspending.
+		 */
+		if (uart_console(port)) {
+			uart_change_speed(state, NULL);
+			port->cons->flags |= CON_ENABLED;
+		}
 		break;
 
-	case PM_SET_WAKEUP:
-		err = uart_pm_set_wakeup(state, (int)(long)data);
+	case RESUME_RESTORE_STATE:
+		if (state->info && state->info->flags & UIF_INITIALIZED) {
+			struct uart_ops *ops = port->ops;
+
+			ops->set_mctrl(port, 0);
+			ops->startup(port);
+			uart_change_speed(state, NULL);
+			spin_lock_irq(&port->lock);
+			ops->set_mctrl(port, port->mctrl);
+			ops->start_tx(port, 0);
+			spin_unlock_irq(&port->lock);
+		}
 		break;
 	}
-	return err;
+
+	up(&state->sem);
+
+	return 0;
 }
-#endif
 
 static inline void
 uart_report_port(struct uart_driver *drv, struct uart_port *port)
@@ -2058,17 +1988,11 @@
 }
 
 static void
-__uart_register_port(struct uart_driver *drv, struct uart_state *state,
-		     struct uart_port *port)
+uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+		    struct uart_port *port)
 {
 	unsigned int flags;
 
-	state->port = port;
-
-	spin_lock_init(&port->lock);
-	port->cons = drv->cons;
-	port->info = state->info;
-
 	/*
 	 * If there isn't a port here, don't do anything further.
 	 */
@@ -2087,12 +2011,6 @@
 		port->ops->config_port(port, flags);
 	}
 
-	/*
-	 * Register the port whether it's detected or not.  This allows
-	 * setserial to be used to alter this ports parameters.
-	 */
-	tty_register_device(drv->tty_driver, drv->minor + port->line);
-
 	if (port->type != PORT_UNKNOWN) {
 		unsigned long flags;
 
@@ -2106,51 +2024,33 @@
 		port->ops->set_mctrl(port, 0);
 		spin_unlock_irqrestore(&port->lock, flags);
 
-#ifdef CONFIG_PM
 		/*
 		 * Power down all ports by default, except the
-		 * console if we have one.  We need to drop the
-		 * port semaphore here.
+		 * console if we have one.
 		 */
-		if (state->pm && (!drv->cons || port->line != drv->cons->index)) {
-			up(&port_sem);
-			pm_send(state->pm, PM_SUSPEND, (void *)3);
-			down(&port_sem);
-		}
-#endif
+		if (!uart_console(port))
+			uart_change_pm(state, 3);
 	}
 }
 
 /*
- *	Hangup the port.  This must be done outside the port_sem
- *	since uart_hangup() grabs this same semaphore.  Grr.
+ * This reverses the affects of uart_configure_port, hanging up the
+ * port before removal.
  */
 static void
-__uart_hangup_port(struct uart_driver *drv, struct uart_state *state)
+uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
 {
+	struct uart_port *port = state->port;
 	struct uart_info *info = state->info;
 
 	if (info && info->tty)
 		tty_vhangup(info->tty);
-}
 
-/*
- * This reverses the affects of __uart_register_port.
- */
-static void
-__uart_unregister_port(struct uart_driver *drv, struct uart_state *state)
-{
-	struct uart_port *port = state->port;
-	struct uart_info *info = state->info;
+	down(&state->sem);
 
 	state->info = NULL;
 
 	/*
-	 * Remove the devices from devfs
-	 */
-	tty_unregister_device(drv->tty_driver, drv->minor + port->line);
-
-	/*
 	 * Free the port IO and memory resources, if any.
 	 */
 	if (port->type != PORT_UNKNOWN)
@@ -2168,6 +2068,8 @@
 		tasklet_kill(&info->tlet);
 		kfree(info);
 	}
+
+	up(&state->sem);
 }
 
 /**
@@ -2222,6 +2124,7 @@
 	drv->tty_driver = normal;
 
 	normal->magic		= TTY_DRIVER_MAGIC;
+	normal->owner		= drv->owner;
 	normal->driver_name	= drv->driver_name;
 	normal->name		= drv->dev_name;
 	normal->major		= drv->major;
@@ -2268,20 +2171,13 @@
 
 		state->close_delay     = 5 * HZ / 10;
 		state->closing_wait    = 30 * HZ;
-#ifdef CONFIG_PM
-		state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
-		if (state->pm)
-			state->pm->data = state;
-#endif
+
+		init_MUTEX(&state->sem);
 	}
 
 	retval = tty_register_driver(normal);
  out:
 	if (retval < 0) {
-#ifdef CONFIG_PM
-		for (i = 0; i < drv->nr; i++)
-			pm_unregister(drv->state[i].pm);
-#endif
 		kfree(normal);
 		kfree(drv->state);
 		kfree(termios);
@@ -2300,11 +2196,6 @@
  */
 void uart_unregister_driver(struct uart_driver *drv)
 {
-	int i;
-
-	for (i = 0; i < drv->nr; i++)
-		pm_unregister(drv->state[i].pm);
-
 	tty_unregister_driver(drv->tty_driver);
 
 	kfree(drv->state);
@@ -2325,6 +2216,7 @@
 int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
 {
 	struct uart_state *state;
+	int ret = 0;
 
 	BUG_ON(in_interrupt());
 
@@ -2334,10 +2226,29 @@
 	state = drv->state + port->line;
 
 	down(&port_sem);
-	__uart_register_port(drv, state, port);
+	if (state->port) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	state->port = port;
+
+	spin_lock_init(&port->lock);
+	port->cons = drv->cons;
+	port->info = state->info;
+
+	uart_configure_port(drv, state, port);
+
+	/*
+	 * Register the port whether it's detected or not.  This allows
+	 * setserial to be used to alter this ports parameters.
+	 */
+	tty_register_device(drv->tty_driver, drv->minor + port->line);
+
+ out:
 	up(&port_sem);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -2359,10 +2270,14 @@
 		printk(KERN_ALERT "Removing wrong port: %p != %p\n",
 			state->port, port);
 
-	__uart_hangup_port(drv, state);
-
 	down(&port_sem);
-	__uart_unregister_port(drv, state);
+
+	/*
+	 * Remove the devices from devfs
+	 */
+	tty_unregister_device(drv->tty_driver, drv->minor + port->line);
+
+	uart_unconfigure_port(drv, state);
 	state->port = NULL;
 	up(&port_sem);
 
@@ -2462,8 +2377,7 @@
 		 * alter it underneath itself - the port may be open and
 		 * trying to do useful work.
 		 */
-		if (state->count != 0 ||
-		    (state->info && state->info->blocked_open != 0)) {
+		if (uart_users(state) != 0) {
 			ret = -EBUSY;
 			goto out;
 		}
@@ -2483,7 +2397,7 @@
 			state->port->line     = state - drv->state;
 			state->port->mapbase  = port->mapbase;
 
-			__uart_register_port(drv, state, state->port);
+			uart_configure_port(drv, state, state->port);
 		}
 
 		ret = state->port->line;
@@ -2515,16 +2429,16 @@
 
 	state = drv->state + line;
 
-	__uart_hangup_port(drv, state);
-
 	down(&port_sem);
-	__uart_unregister_port(drv, state);
+	uart_unconfigure_port(drv, state);
 	up(&port_sem);
 }
 
 EXPORT_SYMBOL(uart_write_wakeup);
 EXPORT_SYMBOL(uart_register_driver);
 EXPORT_SYMBOL(uart_unregister_driver);
+EXPORT_SYMBOL(uart_suspend_port);
+EXPORT_SYMBOL(uart_resume_port);
 EXPORT_SYMBOL(uart_register_port);
 EXPORT_SYMBOL(uart_unregister_port);
 EXPORT_SYMBOL(uart_add_one_port);
diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
--- a/drivers/serial/mcfserial.c	Tue Feb 18 02:28:34 2003
+++ b/drivers/serial/mcfserial.c	Mon Mar  3 12:25:14 2003
@@ -1853,9 +1853,11 @@
 	.index		= -1,
 };
 
-void __init mcfrs_console_init(void)
+static void __init mcfrs_console_init(void)
 {
 	register_console(&mcfrs_console);
 }
+
+console_initcall(mcfrs_console_init);
 
 /****************************************************************************/
diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
--- a/drivers/serial/sa1100.c	Tue Feb 25 18:39:37 2003
+++ b/drivers/serial/sa1100.c	Tue Mar 11 13:08:27 2003
@@ -32,6 +32,7 @@
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -835,11 +836,12 @@
 	.index		= -1,
 };
 
-void __init sa1100_rs_console_init(void)
+static void __init sa1100_rs_console_init(void)
 {
 	sa1100_init_ports();
 	register_console(&sa1100_console);
 }
+console_initcall(sa1100_rs_console_init);
 
 #define SA1100_CONSOLE	&sa1100_console
 #else
@@ -856,11 +858,53 @@
 	.cons			= SA1100_CONSOLE,
 };
 
+static int sa1100_serial_suspend(struct device *dev, u32 state, u32 level)
+{
+	int i;
+
+	for (i = 0; i < NR_PORTS; i++)
+		uart_suspend_port(&sa1100_reg, &sa1100_ports[i].port, level);
+
+	return 0;
+}
+
+static int sa1100_serial_resume(struct device *dev, u32 level)
+{
+	int i;
+
+	for (i = 0; i < NR_PORTS; i++)
+		uart_resume_port(&sa1100_reg, &sa1100_ports[i].port, level);
+
+	return 0;
+}
+
+static struct device_driver sa11x0_serial_driver = {
+	.name		= "sa11x0_serial",
+	.bus		= &system_bus_type,
+	.devclass	= &tty_devclass,
+	.suspend	= sa1100_serial_suspend,
+	.resume		= sa1100_serial_resume,
+};
+
+/*
+ * This "device" covers _all_ ISA 8250-compatible serial devices.
+ */
+static struct sys_device sa11x0_serial_devs = {
+	.name		= "sa11x0_serial",
+	.id		= 0,
+	.dev = {
+		.driver	= &sa11x0_serial_driver,
+	},
+};
+
 static int __init sa1100_serial_init(void)
 {
 	int ret;
 
 	printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.50 $\n");
+
+	driver_register(&sa11x0_serial_driver);
+	sys_device_register(&sa11x0_serial_devs);
 
 	sa1100_init_ports();
 	ret = uart_register_driver(&sa1100_reg);
diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c
--- a/drivers/serial/uart00.c	Sun Feb 16 11:33:25 2003
+++ b/drivers/serial/uart00.c	Thu Mar  6 09:30:07 2003
@@ -645,10 +645,11 @@
 	.index		= 0,
 };
 
-void __init uart00_console_init(void)
+static void __init uart00_console_init(void)
 {
 	register_console(&uart00_console);
 }
+console_initcall(uart00_console_init);
 
 #define UART00_CONSOLE	&uart00_console
 #else
diff -Nru a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
--- a/drivers/sgi/char/sgiserial.c	Sun Nov 17 23:09:37 2002
+++ b/drivers/sgi/char/sgiserial.c	Fri Feb 14 15:27:26 2003
@@ -2269,8 +2269,10 @@
 /*
  *	Register console.
  */
-void __init sgi_serial_console_init(void)
+static void __init sgi_serial_console_init(void)
 {
 	register_console(&sgi_console_driver);
 }
+console_initcall(sgi_serial_console_init);
+
 __initcall(rs_init);
diff -Nru a/drivers/usb/class/usb-midi.h b/drivers/usb/class/usb-midi.h
--- a/drivers/usb/class/usb-midi.h	Fri Feb 21 03:06:06 2003
+++ b/drivers/usb/class/usb-midi.h	Wed Mar  5 03:07:27 2003
@@ -54,6 +54,10 @@
 #define USB_VENDOR_ID_STEINBERG		0x0763
 #define USBMIDI_STEINBERG_USB2MIDI	0x1001
 
+/* Mark of the Unicorn MIDI Devices */
+#define USB_VENDOR_ID_MOTU		0x07fd
+#define USBMIDI_MOTU_FASTLANE		0x0001
+
 /* ------------------------------------------------------------------------- */
 /* Supported devices */
 
@@ -101,8 +105,15 @@
   { /* Roland SC8850 */
     "Roland SC8850",
     USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1,
-    { { 0x81, 15 }, {-1, -1} }, /** cables 0,1,2, and 3 **/
-    { { 0x01, 15 }, {-1, -1} },
+    { { 0x81, 0x3f }, {-1, -1} },
+    { { 0x01, 0x3f }, {-1, -1} },
+  },
+
+  { /* Roland SC8820 */
+    "Roland SC8820",
+    USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1,
+    { { 0x81, 0x13 }, {-1, -1} },
+    { { 0x01, 0x13 }, {-1, -1} },
   },
 
   { /* Roland SC8820 */
@@ -123,6 +134,12 @@
     USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1, 
     { { 0x81, 1 }, {-1, -1} },
     { { 0x01, 1 }, {-1, -1} },
+  },
+  { /* MOTU Fastlane USB */
+    "MOTU Fastlane USB",
+    USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0,
+    { { 0x82, 3 }, {-1, -1} },
+    { { 0x02, 3 }, {-1, -1} },
   }
 };
 
@@ -138,7 +155,9 @@
 	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) },
 	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) },
 	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) },
+	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) },
 	{ USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) },
+	{ USB_DEVICE( USB_VENDOR_ID_MOTU,   USBMIDI_MOTU_FASTLANE ) },
 /*	{ USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/
 	{ } /* Terminating entry */
 };
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Wed Feb 26 03:17:57 2003
+++ b/drivers/usb/core/hub.c	Wed Mar  5 07:24:34 2003
@@ -876,6 +876,7 @@
 		}
 
 		hub->children[port] = dev;
+		dev->state = USB_STATE_POWERED;
 
 		/* Reset the device, and detect its speed */
 		if (usb_hub_port_reset(hub, port, dev, delay)) {
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	Sat Feb 15 04:07:33 2003
+++ b/drivers/usb/core/message.c	Wed Mar  5 07:24:34 2003
@@ -904,17 +904,29 @@
 			break;
 		}
 	}
-	if (!cp) {
+	if ((!cp && configuration != 0) || (cp && configuration == 0)) {
 		warn("selecting invalid configuration %d", configuration);
 		return -EINVAL;
 	}
 
+	/* if it's already configured, clear out old state first. */
+	if (dev->state != USB_STATE_ADDRESS) {
+		/* FIXME unbind drivers from all "old" interfaces.
+		 * handshake with hcd to reset cached hc endpoint state.
+		 */
+	}
+
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
 			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
 		return ret;
-
+	if (configuration)
+		dev->state = USB_STATE_CONFIGURED;
+	else
+		dev->state = USB_STATE_ADDRESS;
 	dev->actconfig = cp;
+
+	/* reset more hc/hcd endpoint state */
 	dev->toggle[0] = 0;
 	dev->toggle[1] = 0;
 	usb_set_maxpacket(dev);
diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c	Tue Feb 18 07:50:22 2003
+++ b/drivers/usb/core/urb.c	Thu Mar  6 07:46:03 2003
@@ -195,7 +195,9 @@
 
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
-	if (!(dev = urb->dev) || !dev->present || !dev->bus || dev->devnum <= 0)
+	if (!(dev = urb->dev) ||
+	    (dev->state < USB_STATE_DEFAULT) ||
+	    (!dev->bus) || (dev->devnum <= 0))
 		return -ENODEV;
 	if (!(op = dev->bus->op) || !op->submit_urb)
 		return -ENODEV;
@@ -211,6 +213,9 @@
 	temp = usb_pipetype (pipe);
 	is_out = usb_pipeout (pipe);
 
+	if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
+		return -ENODEV;
+
 	/* (actually HCDs may need to duplicate this, endpoint might yet
 	 * stall due to queued bulk/intr transactions that complete after
 	 * we check)
@@ -376,7 +381,16 @@
  */
 int usb_unlink_urb(struct urb *urb)
 {
-	if (urb && urb->dev && urb->dev->present && urb->dev->bus && urb->dev->bus->op)
+	/* FIXME
+	 * We should not care about the state here, but the host controllers
+	 * die a horrible death if we submit a urb for a device that has been
+	 * physically removed.
+	 */
+	if (urb &&
+	    urb->dev &&
+	    (urb->dev->state >= USB_STATE_DEFAULT) &&
+	    urb->dev->bus &&
+	    urb->dev->bus->op)
 		return urb->dev->bus->op->unlink_urb(urb);
 	else
 		return -ENODEV;
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Tue Feb 18 07:50:22 2003
+++ b/drivers/usb/core/usb.c	Wed Mar  5 07:29:53 2003
@@ -679,7 +679,7 @@
 	memset(dev, 0, sizeof(*dev));
 
 	device_initialize(&dev->dev);
-	dev->present = 1;
+	dev->state = USB_STATE_ATTACHED;
 
 	usb_bus_get(bus);
 
@@ -828,6 +828,11 @@
 
 	*pdev = NULL;
 
+	/* mark the device as inactive, so any further urb submissions for
+	 * this device will fail.
+	 */
+	dev->state = USB_STATE_NOTATTACHED;
+
 	dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum);
 
 	/* Free up all the children before we remove this device */
@@ -855,10 +860,6 @@
 	}
 	device_unregister(&dev->dev);
 
-	/* mark the device as not present so any further urb submissions for
-	 * this device will fail. */
-	dev->present = 0;
-
 	/* Decrement the reference count, it'll auto free everything when */
 	/* it hits 0 which could very well be now */
 	usb_put_dev(dev);
@@ -906,9 +907,17 @@
 // otherwise used internally, for usb_new_device()
 int usb_set_address(struct usb_device *dev)
 {
-	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
-		// FIXME USB_CTRL_SET_TIMEOUT
-		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
+	int retval;
+
+	if (dev->devnum == 0)
+		return -EINVAL;
+	if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS)
+		return -EINVAL;
+	retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
+		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+	if (retval == 0)
+		dev->state = USB_STATE_ADDRESS;
+	return retval;
 }
 
 
@@ -1014,7 +1023,8 @@
 	/* dma masks come from the controller; readonly, except to hcd */
 	dev->dev.dma_mask = parent->dma_mask;
 
-	/* USB device state == default ... it's not usable yet */
+	/* it's not usable yet */
+	dev->state = USB_STATE_DEFAULT;
 
 	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
 	 * it's fixed size except for full speed devices.
@@ -1049,6 +1059,7 @@
 		if (err < 0) {
 			dev_err(&dev->dev, "USB device not accepting new address=%d (error=%d)\n",
 				dev->devnum, err);
+			dev->state = USB_STATE_DEFAULT;
 			clear_bit(dev->devnum, dev->bus->devmap.devicemap);
 			dev->devnum = -1;
 			return 1;
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	Mon Feb 24 03:30:39 2003
+++ b/drivers/usb/host/ohci-pci.c	Thu Mar  6 20:32:12 2003
@@ -18,6 +18,7 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/pci-bridge.h>
+#include <asm/prom.h>
 #ifndef CONFIG_PM
 #	define CONFIG_PM
 #endif
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	Tue Jan  7 06:50:11 2003
+++ b/drivers/usb/serial/io_edgeport.c	Wed Mar  5 03:35:49 2003
@@ -522,7 +522,7 @@
 		case EDGE_DOWNLOAD_FILE_I930:
 			BootMajorVersion	= BootCodeImageVersion_GEN1.MajorVersion;
 			BootMinorVersion	= BootCodeImageVersion_GEN1.MinorVersion;
-			BootBuildNumber		= BootCodeImageVersion_GEN1.BuildNumber;
+			BootBuildNumber		= cpu_to_le16(BootCodeImageVersion_GEN1.BuildNumber);
 			BootImage		= &BootCodeImage_GEN1[0];
 			BootSize		= sizeof( BootCodeImage_GEN1 );
 			break;
@@ -530,7 +530,7 @@
 		case EDGE_DOWNLOAD_FILE_80251:
 			BootMajorVersion	= BootCodeImageVersion_GEN2.MajorVersion;
 			BootMinorVersion	= BootCodeImageVersion_GEN2.MinorVersion;
-			BootBuildNumber		= BootCodeImageVersion_GEN2.BuildNumber;
+			BootBuildNumber		= cpu_to_le16(BootCodeImageVersion_GEN2.BuildNumber);
 			BootImage		= &BootCodeImage_GEN2[0];
 			BootSize		= sizeof( BootCodeImage_GEN2 );
 			break;
@@ -542,26 +542,26 @@
 	// Check Boot Image Version
 	BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) +
 		     (edge_serial->boot_descriptor.MinorVersion << 16) +
-		      edge_serial->boot_descriptor.BuildNumber;
+		      le16_to_cpu(edge_serial->boot_descriptor.BuildNumber);
 
 	BootNewVer = (BootMajorVersion << 24) +
 		     (BootMinorVersion << 16) +
-		      BootBuildNumber;
+		      le16_to_cpu(BootBuildNumber);
 
 	dbg("Current Boot Image version %d.%d.%d",
 	    edge_serial->boot_descriptor.MajorVersion,
 	    edge_serial->boot_descriptor.MinorVersion,
-	    edge_serial->boot_descriptor.BuildNumber);
+	    le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
 
 
 	if (BootNewVer > BootCurVer) {
 		dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d",
 		    edge_serial->boot_descriptor.MajorVersion,
 		    edge_serial->boot_descriptor.MinorVersion,
-		    edge_serial->boot_descriptor.BuildNumber,
+		    le16_to_cpu(edge_serial->boot_descriptor.BuildNumber),
 		    BootMajorVersion,
 		    BootMinorVersion,
-		    BootBuildNumber);
+		    le16_to_cpu(BootBuildNumber));
 
 
 		dbg("Downloading new Boot Image");
@@ -570,12 +570,12 @@
 
 		for (;;) {
 			record = (struct edge_firmware_image_record *)firmware;
-			response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
+			response = rom_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]);
 			if (response < 0) {
-				dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len);
+				dev_err(&edge_serial->serial->dev->dev, "rom_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len));
 				break;
 			}
-			firmware += sizeof (struct edge_firmware_image_record) + record->Len;
+			firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len);
 			if (firmware >= &BootImage[BootSize]) {
 				break;
 			}
@@ -678,12 +678,12 @@
 	if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) {
 		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN2.MajorVersion;
 		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN2.MinorVersion;
-		product_info->FirmwareBuildNumber	= OperationalCodeImageVersion_GEN2.BuildNumber;
+		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber);
 		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_80251;
 	} else {
 		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN1.MajorVersion;
 		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN1.MinorVersion;
-		product_info->FirmwareBuildNumber	= OperationalCodeImageVersion_GEN1.BuildNumber;
+		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN1.BuildNumber);
 		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_I930;
 	}
 
@@ -729,10 +729,10 @@
 	dbg("  BoardRev              %x", product_info->BoardRev);
 	dbg("  BootMajorVersion      %d.%d.%d", product_info->BootMajorVersion,
 	    product_info->BootMinorVersion,
-	    product_info->BootBuildNumber);
+	    le16_to_cpu(product_info->BootBuildNumber));
 	dbg("  FirmwareMajorVersion  %d.%d.%d", product_info->FirmwareMajorVersion,
 	    product_info->FirmwareMinorVersion,
-	    product_info->FirmwareBuildNumber);
+	    le16_to_cpu(product_info->FirmwareBuildNumber));
 	dbg("  ManufactureDescDate   %d/%d/%d", product_info->ManufactureDescDate[0],
 	    product_info->ManufactureDescDate[1],
 	    product_info->ManufactureDescDate[2]+1900);
@@ -2326,7 +2326,7 @@
 	__u16 current_length;
 	unsigned char *transfer_buffer;
 
-//	dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
+	dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
 
 	transfer_buffer =  kmalloc (64, GFP_KERNEL);
 	if (!transfer_buffer) {
@@ -2811,12 +2811,13 @@
  *	Turns a string from Unicode into ASCII.
  *	Doesn't do a good job with any characters that are outside the normal
  *	ASCII range, but it's only for debugging...
+ *	NOTE: expects the unicode in LE format
  ****************************************************************************/
 static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
 {
 	int i;
 	for (i = 0; i < unicode_size; ++i) {
-		string[i] = (char)(unicode[i]);
+		string[i] = (char)(le16_to_cpu(unicode[i]));
 	}
 	string[unicode_size] = 0x00;
 }
@@ -2880,11 +2881,11 @@
 		dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n");
 	} else {
 		dbg("**Boot Descriptor:");
-		dbg("  BootCodeLength: %d", edge_serial->boot_descriptor.BootCodeLength);
+		dbg("  BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
 		dbg("  MajorVersion:   %d", edge_serial->boot_descriptor.MajorVersion);
 		dbg("  MinorVersion:   %d", edge_serial->boot_descriptor.MinorVersion);
-		dbg("  BuildNumber:    %d", edge_serial->boot_descriptor.BuildNumber);
-		dbg("  Capabilities:   0x%x", edge_serial->boot_descriptor.Capabilities);
+		dbg("  BuildNumber:    %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
+		dbg("  Capabilities:   0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
 		dbg("  UConfig0:       %d", edge_serial->boot_descriptor.UConfig0);
 		dbg("  UConfig1:       %d", edge_serial->boot_descriptor.UConfig1);
 	}
@@ -2936,12 +2937,12 @@
 
 	for (;;) {
 		record = (struct edge_firmware_image_record *)firmware;
-		response = sram_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
+		response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]);
 		if (response < 0) {
-			dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len);
+			dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), record->Len);
 			break;
 		}
-		firmware += sizeof (struct edge_firmware_image_record) + record->Len;
+		firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len);
 		if (firmware >= &FirmwareImage[ImageSize]) {
 			break;
 		}
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	Fri Feb 21 09:00:54 2003
+++ b/drivers/usb/serial/pl2303.c	Wed Mar  5 04:06:21 2003
@@ -75,6 +75,7 @@
 	{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
 	{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
+	{ USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
diff -Nru a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
--- a/drivers/usb/serial/pl2303.h	Tue Feb  4 06:10:14 2003
+++ b/drivers/usb/serial/pl2303.h	Wed Mar  5 04:06:21 2003
@@ -31,3 +31,6 @@
 
 #define TRIPP_VENDOR_ID		0x2478
 #define TRIPP_PRODUCT_ID	0x2008
+
+#define RADIOSHACK_VENDOR_ID	0x1453
+#define RADIOSHACK_PRODUCT_ID	0x4026
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	Tue Feb 18 07:50:15 2003
+++ b/drivers/usb/serial/usb-serial.c	Thu Mar  6 21:31:07 2003
@@ -634,6 +634,7 @@
 		serial->type->throttle(port);
 
 exit:
+	;
 }
 
 static void serial_unthrottle (struct tty_struct * tty)
@@ -656,6 +657,7 @@
 		serial->type->unthrottle(port);
 
 exit:
+	;
 }
 
 static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
@@ -704,6 +706,7 @@
 		serial->type->set_termios(port, old);
 
 exit:
+	;
 }
 
 static void serial_break (struct tty_struct *tty, int break_state)
@@ -726,6 +729,7 @@
 		serial->type->break_ctl(port, break_state);
 
 exit:
+	;
 }
 
 static void serial_shutdown (struct usb_serial *serial)
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Fri Feb 21 09:00:45 2003
+++ b/drivers/usb/serial/visor.c	Wed Mar  5 03:04:53 2003
@@ -12,6 +12,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (03/05/2003) gkh
+ *	Think Treo support is now working.
+ *
  * (04/03/2002) gkh
  *	Added support for the Sony OS 4.1 devices.  Thanks to Hiroyuki ARAKI
  *	<hiro@zob.ne.jp> for the information.
@@ -156,7 +159,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.0"
+#define DRIVER_VERSION "v2.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver"
 
@@ -177,6 +180,7 @@
 static void visor_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
 static void visor_read_int_callback	(struct urb *urb, struct pt_regs *regs);
 static int  clie_3_5_startup	(struct usb_serial *serial);
+static int  treo_attach		(struct usb_serial *serial);
 static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id);
 static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id);
 
@@ -262,6 +266,7 @@
 	.close =		visor_close,
 	.throttle =		visor_throttle,
 	.unthrottle =		visor_unthrottle,
+	.attach =		treo_attach,
 	.probe =		visor_probe,
 	.calc_num_ports =	visor_calc_num_ports,
 	.shutdown =		visor_shutdown,
@@ -797,6 +802,48 @@
 	if (result != 1) {
 		dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result);
 		return -EIO;
+	}
+
+	return 0;
+}
+ 
+static int treo_attach (struct usb_serial *serial)
+{
+	struct usb_serial_port *port;
+	int i;
+
+	/* Only do this endpoint hack for the Handspring devices with
+	 * interrupt in endpoints, which for now are the Treo devices. */
+	if ((serial->dev->descriptor.idVendor != HANDSPRING_VENDOR_ID) ||
+	    (serial->num_interrupt_in == 0))
+		return 0;
+
+	dbg("%s", __FUNCTION__);
+
+	/* Ok, this is pretty ugly, but these devices want to use the
+	 * interrupt endpoint as paired up with a bulk endpoint for a
+	 * "virtual serial port".  So let's force the endpoints to be
+	 * where we want them to be. */
+	for (i = serial->num_bulk_in; i < serial->num_ports; ++i) {
+		port = &serial->port[i];
+		port->read_urb = serial->port[0].read_urb;
+		port->bulk_in_endpointAddress = serial->port[0].bulk_in_endpointAddress;
+		port->bulk_in_buffer = serial->port[0].bulk_in_buffer;
+	}
+
+	for (i = serial->num_bulk_out; i < serial->num_ports; ++i) {
+		port = &serial->port[i];
+		port->write_urb = serial->port[0].write_urb;
+		port->bulk_out_size = serial->port[0].bulk_out_size;
+		port->bulk_out_endpointAddress = serial->port[0].bulk_out_endpointAddress;
+		port->bulk_out_buffer = serial->port[0].bulk_out_buffer;
+	}
+
+	for (i = serial->num_interrupt_in; i < serial->num_ports; ++i) {
+		port = &serial->port[i];
+		port->interrupt_in_urb = serial->port[0].interrupt_in_urb;
+		port->interrupt_in_endpointAddress = serial->port[0].interrupt_in_endpointAddress;
+		port->interrupt_in_buffer = serial->port[0].interrupt_in_buffer;
 	}
 
 	return 0;
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	Sun Nov  3 06:52:41 2002
+++ b/drivers/usb/storage/sddr09.c	Tue Mar 11 15:59:21 2003
@@ -65,6 +65,7 @@
  * NAND Flash Manufacturer ID Codes
  */
 #define NAND_MFR_AMD		0x01
+#define NAND_MFR_NS		0x8f
 #define NAND_MFR_TOSHIBA	0x98
 #define NAND_MFR_SAMSUNG	0xec
 
@@ -72,6 +73,8 @@
 	switch(manuf_id) {
 	case NAND_MFR_AMD:
 		return "AMD";
+	case NAND_MFR_NS:
+		return "NS";
 	case NAND_MFR_TOSHIBA:
 		return "Toshiba";
 	case NAND_MFR_SAMSUNG:
@@ -84,10 +87,12 @@
 /*
  * It looks like it is unnecessary to attach manufacturer to the
  * remaining data: SSFDC prescribes manufacturer-independent id codes.
+ *
+ * 256 MB NAND flash has a 5-byte ID with 2nd byte 0xaa, 0xba, 0xca or 0xda.
  */
 
 static struct nand_flash_dev nand_flash_ids[] = {
-	/* NAND flash - these I verified */
+	/* NAND flash */
 	{ 0x6e, 20, 8, 4, 8, 2},	/* 1 MB */
 	{ 0xe8, 20, 8, 4, 8, 2},	/* 1 MB */
 	{ 0xec, 20, 8, 4, 8, 2},	/* 1 MB */
@@ -101,12 +106,13 @@
 	{ 0x75, 25, 9, 5, 10, 2},	/* 32 MB */
 	{ 0x76, 26, 9, 5, 10, 3},	/* 64 MB */
 	{ 0x79, 27, 9, 5, 10, 3},	/* 128 MB */
-	/* There do also exist 96 MB (from Datafab) and 256 MB cards */
 
-	/* MASK ROM - from unknown source */
+	/* MASK ROM */
 	{ 0x5d, 21, 9, 4, 8, 2},	/* 2 MB */
 	{ 0xd5, 22, 9, 4, 9, 2},	/* 4 MB */
 	{ 0xd6, 23, 9, 4, 10, 2},	/* 8 MB */
+	{ 0x57, 24, 9, 4, 11, 2},	/* 16 MB */
+	{ 0x58, 25, 9, 4, 12, 2},	/* 32 MB */
 	{ 0,}
 };
 
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Wed Jan 22 03:55:34 2003
+++ b/drivers/usb/storage/transport.c	Tue Mar  4 01:58:24 2003
@@ -582,20 +582,26 @@
 		unsigned short old_sg;
 		unsigned old_request_bufflen;
 		unsigned char old_sc_data_direction;
+		unsigned char old_cmd_len;
 		unsigned char old_cmnd[MAX_COMMAND_SIZE];
 
 		US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
 
 		/* save the old command */
 		memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
+		old_cmd_len = srb->cmd_len;
 
 		/* set the command and the LUN */
+		memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
 		srb->cmnd[0] = REQUEST_SENSE;
 		srb->cmnd[1] = old_cmnd[1] & 0xE0;
-		srb->cmnd[2] = 0;
-		srb->cmnd[3] = 0;
 		srb->cmnd[4] = 18;
-		srb->cmnd[5] = 0;
+
+		/* FIXME: we must do the protocol translation here */
+		if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)
+			srb->cmd_len = 6;
+		else
+			srb->cmd_len = 12;
 
 		/* set the transfer direction */
 		old_sc_data_direction = srb->sc_data_direction;
@@ -621,6 +627,7 @@
 		srb->request_bufflen = old_request_bufflen;
 		srb->use_sg = old_sg;
 		srb->sc_data_direction = old_sc_data_direction;
+		srb->cmd_len = old_cmd_len;
 		memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
 
 		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	Sun Mar  2 23:19:23 2003
+++ b/drivers/video/Makefile	Tue Mar 11 05:57:06 2003
@@ -19,6 +19,7 @@
 obj-$(CONFIG_FB_APOLLO)           += dnfb.o cfbfillrect.o cfbimgblt.o
 obj-$(CONFIG_FB_Q40)              += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_ATARI)            += atafb.o
+obj-$(CONFIG_FB_68328)            += 68328fb.o
 obj-$(CONFIG_FB_ATY128)           += aty128fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_RADEON)		  += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
@@ -70,9 +71,6 @@
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
-# One by one these are being converted over to the new APIs
-#obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
-
 obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_CG6)               += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_CG3)               += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
@@ -84,6 +82,8 @@
 obj-$(CONFIG_FB_P9100)             += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
 				      cfbfillrect.o
 obj-$(CONFIG_FB_TCX)               += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				      cfbfillrect.o
+obj-$(CONFIG_FB_LEO)               += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
 				      cfbfillrect.o
 
 # Files generated that shall be removed upon make clean
diff -Nru a/drivers/video/bw2.c b/drivers/video/bw2.c
--- a/drivers/video/bw2.c	Thu Feb 27 12:32:45 2003
+++ b/drivers/video/bw2.c	Tue Mar  4 09:55:26 2003
@@ -33,11 +33,11 @@
  * Local functions.
  */
 
-static int bw2_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int bw2_set_par(struct fb_info *);
 static int bw2_blank(int, struct fb_info *);
 
 static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int bw2_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -45,13 +45,12 @@
 
 static struct fb_ops bw2_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= bw2_check_var,
-	.fb_set_par		= bw2_set_par,
 	.fb_blank		= bw2_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= bw2_mmap,
+	.fb_ioctl		= bw2_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -124,39 +123,6 @@
 };
 
 /**
- *      bw2_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int bw2_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      bw2_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-bw2_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      bw2_blank - Optional function.  Blanks the display.
  *      @blank_mode: the blank mode we want.
  *      @info: frame buffer structure that represents a single frame buffer
@@ -212,6 +178,15 @@
 				  vma);
 }
 
+static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct bw2_par *par = (struct bw2_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN2BW, 1, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -387,7 +362,6 @@
 
 	bw2_blank(0, &all->info);
 
-	bw2_set_par(&all->info);
 	bw2_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/cg14.c b/drivers/video/cg14.c
--- a/drivers/video/cg14.c	Sun Mar  2 22:28:03 2003
+++ b/drivers/video/cg14.c	Tue Mar  4 09:55:26 2003
@@ -28,8 +28,6 @@
  * Local functions.
  */
 
-static int cg14_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int cg14_set_par(struct fb_info *);
 static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 
@@ -43,8 +41,6 @@
 
 static struct fb_ops cg14_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= cg14_check_var,
-	.fb_set_par		= cg14_set_par,
 	.fb_setcolreg		= cg14_setcolreg,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
@@ -220,39 +216,6 @@
 }
 
 /**
- *      cg14_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int cg14_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      cg14_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-cg14_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      cg14_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -358,7 +321,8 @@
 		break;
 
 	default:
-		ret = -EINVAL;
+		ret = sbusfb_ioctl_helper(cmd, arg, info,
+					  FBTYPE_MDICOLOR, 24, par->fbsize);
 		break;
 	};
 
@@ -523,7 +487,6 @@
 		return;
 	}
 
-	cg14_set_par(&all->info);
 	cg14_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/cg3.c b/drivers/video/cg3.c
--- a/drivers/video/cg3.c	Thu Feb 27 12:32:45 2003
+++ b/drivers/video/cg3.c	Tue Mar  4 09:55:26 2003
@@ -29,13 +29,13 @@
  * Local functions.
  */
 
-static int cg3_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int cg3_set_par(struct fb_info *);
 static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int cg3_blank(int, struct fb_info *);
 
 static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int cg3_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -43,14 +43,13 @@
 
 static struct fb_ops cg3_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= cg3_check_var,
-	.fb_set_par		= cg3_set_par,
 	.fb_setcolreg		= cg3_setcolreg,
 	.fb_blank		= cg3_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= cg3_mmap,
+	.fb_ioctl		= cg3_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -127,39 +126,6 @@
 };
 
 /**
- *      cg3_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int cg3_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      cg3_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-cg3_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      cg3_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -269,6 +235,15 @@
 				  vma);
 }
 
+static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct cg3_par *par = (struct cg3_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN3COLOR, 8, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -445,7 +420,6 @@
 		return;
 	}
 
-	cg3_set_par(&all->info);
 	cg3_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/cg6.c b/drivers/video/cg6.c
--- a/drivers/video/cg6.c	Thu Feb 27 12:32:45 2003
+++ b/drivers/video/cg6.c	Tue Mar  4 09:55:26 2003
@@ -29,8 +29,6 @@
  * Local functions.
  */
 
-static int cg6_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int cg6_set_par(struct fb_info *);
 static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int cg6_blank(int, struct fb_info *);
@@ -39,6 +37,8 @@
 static void cg6_fillrect(struct fb_info *, struct fb_fillrect *);
 static int cg6_sync(struct fb_info *);
 static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int cg6_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -46,8 +46,6 @@
 
 static struct fb_ops cg6_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= cg6_check_var,
-	.fb_set_par		= cg6_set_par,
 	.fb_setcolreg		= cg6_setcolreg,
 	.fb_blank		= cg6_blank,
 	.fb_fillrect		= cg6_fillrect,
@@ -55,6 +53,7 @@
 	.fb_imageblit		= cg6_imageblit,
 	.fb_sync		= cg6_sync,
 	.fb_mmap		= cg6_mmap,
+	.fb_ioctl		= cg6_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -406,39 +405,6 @@
 }
 
 /**
- *      cg6_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int cg6_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      cg6_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-cg6_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      cg6_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -535,6 +501,15 @@
 				  vma);
 }
 
+static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct cg6_par *par = (struct cg6_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUNFAST_COLOR, 8, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -731,7 +706,6 @@
 		return;
 	}
 
-	cg6_set_par(&all->info);
 	cg6_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	Sun Mar  2 23:19:23 2003
+++ b/drivers/video/fbmem.c	Fri Mar  7 18:42:54 2003
@@ -158,6 +158,8 @@
 extern int p9100_setup(char*);
 extern int tcx_init(void);
 extern int tcx_setup(char*);
+extern int leo_init(void);
+extern int leo_setup(char*);
 
 static struct {
 	const char *name;
@@ -269,6 +271,9 @@
 #endif
 #ifdef CONFIG_FB_TCX
 	{ "tcx", tcx_init, tcx_setup },
+#endif
+#ifdef CONFIG_FB_LEO
+	{ "leo", leo_init, leo_setup },
 #endif
 
 	/*
diff -Nru a/drivers/video/ffb.c b/drivers/video/ffb.c
--- a/drivers/video/ffb.c	Thu Feb 27 04:19:27 2003
+++ b/drivers/video/ffb.c	Tue Mar  4 09:55:26 2003
@@ -20,6 +20,7 @@
 #include <asm/io.h>
 #include <asm/upa.h>
 #include <asm/oplib.h>
+#include <asm/fbio.h>
 
 #include "sbuslib.h"
 
@@ -27,8 +28,6 @@
  * Local functions.
  */
 
-static int ffb_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int ffb_set_par(struct fb_info *);
 static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int ffb_blank(int, struct fb_info *);
@@ -39,6 +38,8 @@
 static void ffb_copyarea(struct fb_info *, struct fb_copyarea *);
 static int ffb_sync(struct fb_info *);
 static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int ffb_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -46,8 +47,6 @@
 
 static struct fb_ops ffb_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= ffb_check_var,
-	.fb_set_par		= ffb_set_par,
 	.fb_setcolreg		= ffb_setcolreg,
 	.fb_blank		= ffb_blank,
 	.fb_fillrect		= ffb_fillrect,
@@ -55,6 +54,7 @@
 	.fb_imageblit		= ffb_imageblit,
 	.fb_sync		= ffb_sync,
 	.fb_mmap		= ffb_mmap,
+	.fb_ioctl		= ffb_ioctl,
 
 	/* XXX Use FFB hw cursor once fb cursor API is better understood... */
 	.fb_cursor		= soft_cursor,
@@ -673,41 +673,6 @@
 }
 
 /**
- *      ffb_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int ffb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 32)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	ffb_fixup_var_rgb(var);
-
-	return 0;
-}
-
-/**
- *      ffb_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-ffb_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      ffb_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -818,6 +783,15 @@
 				  0, vma);
 }
 
+static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct ffb_par *par = (struct ffb_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_CREATOR, 24, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -972,7 +946,6 @@
 		return;
 	}
 
-	ffb_set_par(&all->info);
 	ffb_init_fix(&all->info);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/leo.c b/drivers/video/leo.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/video/leo.c	Fri Mar  7 18:42:32 2003
@@ -0,0 +1,587 @@
+/* leo.c: LEO frame buffer driver
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/sbus.h>
+#include <asm/oplib.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int leo_blank(int, struct fb_info *);
+
+static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int leo_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops leo_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= leo_setcolreg,
+	.fb_blank		= leo_blank,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= leo_mmap,
+	.fb_ioctl		= leo_ioctl,
+	.fb_cursor		= soft_cursor,
+};
+
+#define LEO_OFF_LC_SS0_KRN	0x00200000UL
+#define LEO_OFF_LC_SS0_USR	0x00201000UL
+#define LEO_OFF_LC_SS1_KRN	0x01200000UL
+#define LEO_OFF_LC_SS1_USR	0x01201000UL
+#define LEO_OFF_LD_SS0		0x00400000UL
+#define LEO_OFF_LD_SS1		0x01400000UL
+#define LEO_OFF_LD_GBL		0x00401000UL
+#define LEO_OFF_LX_KRN		0x00600000UL
+#define LEO_OFF_LX_CURSOR	0x00601000UL
+#define LEO_OFF_SS0		0x00800000UL
+#define LEO_OFF_SS1		0x01800000UL
+#define LEO_OFF_UNK		0x00602000UL
+#define LEO_OFF_UNK2		0x00000000UL
+
+#define LEO_CUR_ENABLE		0x00000080
+#define LEO_CUR_UPDATE		0x00000030
+#define LEO_CUR_PROGRESS	0x00000006
+#define LEO_CUR_UPDATECMAP	0x00000003
+
+#define LEO_CUR_TYPE_MASK	0x00000000
+#define LEO_CUR_TYPE_IMAGE	0x00000020
+#define LEO_CUR_TYPE_CMAP	0x00000050
+
+struct leo_cursor {
+	u8		xxx0[16];
+	volatile u32	cur_type;
+	volatile u32	cur_misc;
+	volatile u32	cur_cursxy;
+	volatile u32	cur_data;
+};
+
+#define LEO_KRN_TYPE_CLUT0	0x00001000
+#define LEO_KRN_TYPE_CLUT1	0x00001001
+#define LEO_KRN_TYPE_CLUT2	0x00001002
+#define LEO_KRN_TYPE_WID	0x00001003
+#define LEO_KRN_TYPE_UNK	0x00001006
+#define LEO_KRN_TYPE_VIDEO	0x00002003
+#define LEO_KRN_TYPE_CLUTDATA	0x00004000
+#define LEO_KRN_CSR_ENABLE	0x00000008
+#define LEO_KRN_CSR_PROGRESS	0x00000004
+#define LEO_KRN_CSR_UNK		0x00000002
+#define LEO_KRN_CSR_UNK2	0x00000001
+
+struct leo_lx_krn {
+	volatile u32	krn_type;
+	volatile u32	krn_csr;
+	volatile u32	krn_value;
+};
+
+struct leo_lc_ss0_krn {
+	volatile u32 	misc;
+	u8		xxx0[0x800-4];
+	volatile u32	rev;
+};
+
+struct leo_lc_ss0_usr {
+	volatile u32	csr;
+	volatile u32	addrspace;
+	volatile u32 	fontmsk;
+	volatile u32	fontt;
+	volatile u32	extent;
+	volatile u32	src;
+	u32		dst;
+	volatile u32	copy;
+	volatile u32	fill;
+};
+
+struct leo_lc_ss1_krn {
+	u8	unknown;
+};
+
+struct leo_lc_ss1_usr {
+	u8	unknown;
+};
+
+struct leo_ld {
+	u8		xxx0[0xe00];
+	volatile u32	csr;
+	volatile u32	wid;
+	volatile u32	wmask;
+	volatile u32	widclip;
+	volatile u32	vclipmin;
+	volatile u32	vclipmax;
+	volatile u32	pickmin;	/* SS1 only */
+	volatile u32	pickmax;	/* SS1 only */
+	volatile u32	fg;
+	volatile u32	bg;
+	volatile u32	src;		/* Copy/Scroll (SS0 only) */
+	volatile u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
+	volatile u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
+	u32		xxx1[3];
+	volatile u32	setsem;		/* SS1 only */
+	volatile u32	clrsem;		/* SS1 only */
+	volatile u32	clrpick;	/* SS1 only */
+	volatile u32	clrdat;		/* SS1 only */
+	volatile u32	alpha;		/* SS1 only */
+	u8		xxx2[0x2c];
+	volatile u32	winbg;
+	volatile u32	planemask;
+	volatile u32	rop;
+	volatile u32	z;
+	volatile u32	dczf;		/* SS1 only */
+	volatile u32	dczb;		/* SS1 only */
+	volatile u32	dcs;		/* SS1 only */
+	volatile u32	dczs;		/* SS1 only */
+	volatile u32	pickfb;		/* SS1 only */
+	volatile u32	pickbb;		/* SS1 only */
+	volatile u32	dcfc;		/* SS1 only */
+	volatile u32	forcecol;	/* SS1 only */
+	volatile u32	door[8];	/* SS1 only */
+	volatile u32	pick[5];	/* SS1 only */
+};
+
+#define LEO_SS1_MISC_ENABLE	0x00000001
+#define LEO_SS1_MISC_STEREO	0x00000002
+struct leo_ld_ss1 {
+	u8		xxx0[0xef4];
+	volatile u32	ss1_misc;
+};
+
+struct leo_ld_gbl {
+	u8	unknown;
+};
+
+struct leo_par {
+	spinlock_t		lock;
+	struct leo_lx_krn	*lx_krn;
+	struct leo_lc_ss0_usr	*lc_ss0_usr;
+	struct leo_ld_ss0	*ld_ss0;
+	struct leo_ld_ss1	*ld_ss1;
+	struct leo_cursor	*cursor;
+	u32			extent;
+	u32			clut_data[256];
+
+	u32			flags;
+#define LEO_FLAG_BLANKED	0x00000001
+
+	unsigned long		physbase;
+	unsigned long		fbsize;
+
+	struct sbus_dev		*sdev;
+	struct list_head	list;
+};
+
+static void leo_wait(struct leo_lx_krn *lx_krn)
+{
+	int i;
+	
+	for (i = 0;
+	     (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000;
+	     i++)
+		udelay (1); /* Busy wait at most 0.3 sec */
+	return;
+}
+
+/**
+ *      leo_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int leo_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+        struct leo_lx_krn *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+	int i;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	par->clut_data[regno] = red | (green << 8) | (blue << 16);
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
+	for (i = 0; i < 256; i++)
+		sbus_writel(par->clut_data[i], &lx_krn->krn_value);
+	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *      leo_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int leo_blank(int blank, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	switch (blank) {
+	case 0: /* Unblanking */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val |= LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags &= ~LEO_FLAG_BLANKED;
+		break;
+
+	case 1: /* Normal blanking */
+	case 2: /* VESA blank (vsync off) */
+	case 3: /* VESA blank (hsync off) */
+	case 4: /* Poweroff */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val &= ~LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags |= LEO_FLAG_BLANKED;
+		break;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map leo_mmap_map[] = {
+	{ LEO_SS0_MAP,		LEO_OFF_SS0,		0x800000	},
+	{ LEO_LC_SS0_USR_MAP,	LEO_OFF_LC_SS0_USR,	0x1000		},
+	{ LEO_LD_SS0_MAP,	LEO_OFF_LD_SS0,		0x1000		},
+	{ LEO_LX_CURSOR_MAP,	LEO_OFF_LX_CURSOR,	0x1000		},
+	{ LEO_SS1_MAP,		LEO_OFF_SS1,		0x800000	},
+	{ LEO_LC_SS1_USR_MAP,	LEO_OFF_LC_SS1_USR,	0x1000		},
+	{ LEO_LD_SS1_MAP,	LEO_OFF_LD_SS1,		0x1000		},
+	{ LEO_UNK_MAP,		LEO_OFF_UNK,		0x1000		},
+	{ LEO_LX_KRN_MAP,	LEO_OFF_LX_KRN,		0x1000		},
+	{ LEO_LC_SS0_KRN_MAP,	LEO_OFF_LC_SS0_KRN,	0x1000		},
+	{ LEO_LC_SS1_KRN_MAP,	LEO_OFF_LC_SS1_KRN,	0x1000		},
+	{ LEO_LD_GBL_MAP,	LEO_OFF_LD_GBL,		0x1000		},
+	{ LEO_UNK2_MAP,		LEO_OFF_UNK2,		0x100000	},
+	{ 0,			0,			0	  	}
+};
+
+static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+	struct leo_par *par = (struct leo_par *)info->par;
+
+	return sbusfb_mmap_helper(leo_mmap_map,
+				  par->physbase, par->fbsize,
+				  par->sdev->reg_addrs[0].which_io,
+				  vma);
+}
+
+static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUNLEO, 32, par->fbsize);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+leo_init_fix(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *)info->par;
+
+	strncpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id) - 1);
+	info->fix.id[sizeof(info->fix.id)-1] = 0;
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	info->fix.line_length = 8192;
+
+	info->fix.accel = FB_ACCEL_SUN_LEO;
+}
+
+static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn *lx_krn = par->lx_krn;
+	struct fb_wid_item *wi;
+	unsigned long flags;
+	u32 val;
+	int i, j;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
+		switch(wi->wi_type) {
+		case FB_WID_DBL_8:
+			j = (wi->wi_index & 0xf) + 0x40;
+			break;
+
+		case FB_WID_DBL_24:
+			j = wi->wi_index & 0x3f;
+			break;
+
+		default:
+			continue;
+		};
+		sbus_writel(0x5800 + j, &lx_krn->krn_type);
+		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
+	}
+	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static void leo_init_wids(struct fb_info *info)
+{
+	struct fb_wid_item wi;
+	struct fb_wid_list wl;
+
+	wl.wl_count = 1;
+	wl.wl_list = &wi;
+	wi.wi_type = FB_WID_DBL_8;
+	wi.wi_index = 0;
+	wi.wi_values [0] = 0x2c0;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 2;
+	wi.wi_values [0] = 0x20;
+	leo_wid_put(info, &wl);
+	wi.wi_type = FB_WID_DBL_24;
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+
+}
+
+static void leo_init_hw(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_ld *ss = (struct leo_ld *) par->ld_ss0;
+	u32 val;
+
+	val = sbus_readl(&par->ld_ss1->ss1_misc);
+	val |= LEO_SS1_MISC_ENABLE;
+	sbus_writel(val, &par->ld_ss1->ss1_misc);
+
+	par->extent = ((info->var.xres - 1) |
+		       ((info->var.yres - 1) << 16));
+
+	sbus_writel(0xffffffff, &ss->wid);
+	sbus_writel(0xffff, &ss->wmask);
+	sbus_writel(0, &ss->vclipmin);
+	sbus_writel(par->extent, &ss->vclipmax);
+	sbus_writel(0, &ss->fg);
+	sbus_writel(0xff000000, &ss->planemask);
+	sbus_writel(0x310850, &ss->rop);
+	sbus_writel(0, &ss->widclip);
+	sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
+		    &par->lc_ss0_usr->extent);
+	sbus_writel(4, &par->lc_ss0_usr->addrspace);
+	sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
+	sbus_writel(0, &par->lc_ss0_usr->fontt);
+	do {
+		val = sbus_readl(&par->lc_ss0_usr->csr);
+	} while (val & 0x20000000);
+}
+
+static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
+{
+	var->red.offset = 0;
+	var->red.length = 8;
+	var->green.offset = 8;
+	var->green.length = 8;
+	var->blue.offset = 16;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+}
+
+struct all_info {
+	struct fb_info info;
+	struct leo_par par;
+	struct list_head list;
+};
+static LIST_HEAD(leo_list);
+
+static void leo_init_one(struct sbus_dev *sdev)
+{
+	struct all_info *all;
+	int linebytes;
+
+	all = kmalloc(sizeof(*all), GFP_KERNEL);
+	if (!all) {
+		printk(KERN_ERR "leo: Cannot allocate memory.\n");
+		return;
+	}
+	memset(all, 0, sizeof(*all));
+
+	INIT_LIST_HEAD(&all->list);
+
+	spin_lock_init(&all->par.lock);
+	all->par.sdev = sdev;
+
+	all->par.physbase = sdev->reg_addrs[0].phys_addr;
+
+	sbusfb_fill_var(&all->info.var, sdev->prom_node, 32);
+	leo_fixup_var_rgb(&all->info.var);
+
+	linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
+				       all->info.var.xres);
+	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+
+#ifdef CONFIG_SPARC32
+	all->info.screen_base = (char *)
+		prom_getintdefault(sdev->prom_node, "address", 0);
+#endif
+	if (!all->info.screen_base)
+		all->info.screen_base = (char *)
+			sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
+				     0x800000, "leo ram");
+
+	all->par.lc_ss0_usr = (struct leo_lc_ss0_usr *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
+			     0x1000, "leolc ss0usr");
+	all->par.ld_ss0 = (struct leo_ld_ss0 *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
+			     0x1000, "leold ss0");
+	all->par.ld_ss1 = (struct leo_ld_ss1 *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
+			     0x1000, "leold ss1");
+	all->par.lx_krn = (struct leo_lx_krn *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
+			     0x1000, "leolx krn");
+	all->par.cursor = (struct leo_cursor *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
+			     sizeof(struct leo_cursor), "leolx cursor");
+
+	all->info.node = NODEV;
+	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.fbops = &leo_ops;
+	all->info.currcon = -1;
+	all->info.par = &all->par;
+
+	leo_init_wids(&all->info);
+	leo_init_hw(&all->info);
+
+	leo_blank(0, &all->info);
+
+	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+		printk(KERN_ERR "leo: Could not allocate color map.\n");
+		kfree(all);
+		return;
+	}
+
+	leo_init_fix(&all->info);
+
+	if (register_framebuffer(&all->info) < 0) {
+		printk(KERN_ERR "leo: Could not register framebuffer.\n");
+		fb_dealloc_cmap(&all->info.cmap);
+		kfree(all);
+		return;
+	}
+
+	list_add(&all->list, &leo_list);
+
+	printk("leo: %s at %lx:%lx\n",
+	       sdev->prom_name,
+	       (long) sdev->reg_addrs[0].which_io,
+	       (long) sdev->reg_addrs[0].phys_addr);
+}
+
+int __init leo_init(void)
+{
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
+
+	for_all_sbusdev(sdev, sbus) {
+		if (!strcmp(sdev->prom_name, "leo"))
+			leo_init_one(sdev);
+	}
+
+	return 0;
+}
+
+void __exit leo_exit(void)
+{
+	struct list_head *pos, *tmp;
+
+	list_for_each_safe(pos, tmp, &leo_list) {
+		struct all_info *all = list_entry(pos, typeof(*all), list);
+
+		unregister_framebuffer(&all->info);
+		fb_dealloc_cmap(&all->info.cmap);
+		kfree(all);
+	}
+}
+
+int __init
+leo_setup(char *arg)
+{
+	/* No cmdline options yet... */
+	return 0;
+}
+
+#ifdef MODULE
+module_init(leo_init);
+module_exit(leo_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/leofb.c b/drivers/video/leofb.c
--- a/drivers/video/leofb.c	Mon Oct 28 05:41:23 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,764 +0,0 @@
-/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $
- * leofb.c: Leo (ZX) 24/8bit frame buffer driver
- *
- * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-
-#include <video/sbusfb.h>
-#include <asm/io.h>
-
-#define LEO_OFF_LC_SS0_KRN	0x00200000UL
-#define LEO_OFF_LC_SS0_USR	0x00201000UL
-#define LEO_OFF_LC_SS1_KRN	0x01200000UL
-#define LEO_OFF_LC_SS1_USR	0x01201000UL
-#define LEO_OFF_LD_SS0		0x00400000UL
-#define LEO_OFF_LD_SS1		0x01400000UL
-#define LEO_OFF_LD_GBL		0x00401000UL
-#define LEO_OFF_LX_KRN		0x00600000UL
-#define LEO_OFF_LX_CURSOR	0x00601000UL
-#define LEO_OFF_SS0		0x00800000UL
-#define LEO_OFF_SS1		0x01800000UL
-#define LEO_OFF_UNK		0x00602000UL
-#define LEO_OFF_UNK2		0x00000000UL
-
-#define LEO_CUR_ENABLE		0x00000080
-#define LEO_CUR_UPDATE		0x00000030
-#define LEO_CUR_PROGRESS	0x00000006
-#define LEO_CUR_UPDATECMAP	0x00000003
-
-#define LEO_CUR_TYPE_MASK	0x00000000
-#define LEO_CUR_TYPE_IMAGE	0x00000020
-#define LEO_CUR_TYPE_CMAP	0x00000050
-
-struct leo_cursor {
-	u8		xxx0[16];
-	volatile u32	cur_type;
-	volatile u32	cur_misc;
-	volatile u32	cur_cursxy;
-	volatile u32	cur_data;
-};
-
-#define LEO_KRN_TYPE_CLUT0	0x00001000
-#define LEO_KRN_TYPE_CLUT1	0x00001001
-#define LEO_KRN_TYPE_CLUT2	0x00001002
-#define LEO_KRN_TYPE_WID	0x00001003
-#define LEO_KRN_TYPE_UNK	0x00001006
-#define LEO_KRN_TYPE_VIDEO	0x00002003
-#define LEO_KRN_TYPE_CLUTDATA	0x00004000
-#define LEO_KRN_CSR_ENABLE	0x00000008
-#define LEO_KRN_CSR_PROGRESS	0x00000004
-#define LEO_KRN_CSR_UNK		0x00000002
-#define LEO_KRN_CSR_UNK2	0x00000001
-
-struct leo_lx_krn {
-	volatile u32	krn_type;
-	volatile u32	krn_csr;
-	volatile u32	krn_value;
-};
-
-struct leo_lc_ss0_krn {
-	volatile u32 	misc;
-	u8		xxx0[0x800-4];
-	volatile u32	rev;
-};
-
-struct leo_lc_ss0_usr {
-	volatile u32	csr;
-	volatile u32	addrspace;
-	volatile u32 	fontmsk;
-	volatile u32	fontt;
-	volatile u32	extent;
-	volatile u32	src;
-	u32		dst;
-	volatile u32	copy;
-	volatile u32	fill;
-};
-
-struct leo_lc_ss1_krn {
-	u8	unknown;
-};
-
-struct leo_lc_ss1_usr {
-	u8	unknown;
-};
-
-struct leo_ld {
-	u8		xxx0[0xe00];
-	volatile u32	csr;
-	volatile u32	wid;
-	volatile u32	wmask;
-	volatile u32	widclip;
-	volatile u32	vclipmin;
-	volatile u32	vclipmax;
-	volatile u32	pickmin;	/* SS1 only */
-	volatile u32	pickmax;	/* SS1 only */
-	volatile u32	fg;
-	volatile u32	bg;
-	volatile u32	src;		/* Copy/Scroll (SS0 only) */
-	volatile u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
-	volatile u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
-	u32		xxx1[3];
-	volatile u32	setsem;		/* SS1 only */
-	volatile u32	clrsem;		/* SS1 only */
-	volatile u32	clrpick;	/* SS1 only */
-	volatile u32	clrdat;		/* SS1 only */
-	volatile u32	alpha;		/* SS1 only */
-	u8		xxx2[0x2c];
-	volatile u32	winbg;
-	volatile u32	planemask;
-	volatile u32	rop;
-	volatile u32	z;
-	volatile u32	dczf;		/* SS1 only */
-	volatile u32	dczb;		/* SS1 only */
-	volatile u32	dcs;		/* SS1 only */
-	volatile u32	dczs;		/* SS1 only */
-	volatile u32	pickfb;		/* SS1 only */
-	volatile u32	pickbb;		/* SS1 only */
-	volatile u32	dcfc;		/* SS1 only */
-	volatile u32	forcecol;	/* SS1 only */
-	volatile u32	door[8];	/* SS1 only */
-	volatile u32	pick[5];	/* SS1 only */
-};
-
-#define LEO_SS1_MISC_ENABLE	0x00000001
-#define LEO_SS1_MISC_STEREO	0x00000002
-struct leo_ld_ss1 {
-	u8		xxx0[0xef4];
-	volatile u32	ss1_misc;
-};
-
-struct leo_ld_gbl {
-	u8	unknown;
-};
-
-static struct sbus_mmap_map leo_mmap_map[] = {
-	{ LEO_SS0_MAP,		LEO_OFF_SS0,		0x800000	},
-	{ LEO_LC_SS0_USR_MAP,	LEO_OFF_LC_SS0_USR,	0x1000		},
-	{ LEO_LD_SS0_MAP,	LEO_OFF_LD_SS0,		0x1000		},
-	{ LEO_LX_CURSOR_MAP,	LEO_OFF_LX_CURSOR,	0x1000		},
-	{ LEO_SS1_MAP,		LEO_OFF_SS1,		0x800000	},
-	{ LEO_LC_SS1_USR_MAP,	LEO_OFF_LC_SS1_USR,	0x1000		},
-	{ LEO_LD_SS1_MAP,	LEO_OFF_LD_SS1,		0x1000		},
-	{ LEO_UNK_MAP,		LEO_OFF_UNK,		0x1000		},
-	{ LEO_LX_KRN_MAP,	LEO_OFF_LX_KRN,		0x1000		},
-	{ LEO_LC_SS0_KRN_MAP,	LEO_OFF_LC_SS0_KRN,	0x1000		},
-	{ LEO_LC_SS1_KRN_MAP,	LEO_OFF_LC_SS1_KRN,	0x1000		},
-	{ LEO_LD_GBL_MAP,	LEO_OFF_LD_GBL,		0x1000		},
-	{ LEO_UNK2_MAP,		LEO_OFF_UNK2,		0x100000	},
-	{ 0,			0,			0	  	}
-};
-
-static void leo_setup(struct display *p)
-{
-	p->next_line = 8192;
-	p->next_plane = 0;
-}
-
-static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-		      int height, int width)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int x, y, w, h;
-	int i;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg);
-	if (fontheightlog(p)) {
-		y = sy << fontheightlog(p); h = height << fontheightlog(p);
-	} else {
-		y = sy * fontheight(p); h = height * fontheight(p);
-	}
-	if (fontwidthlog(p)) {
-		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
-	} else {
-		x = sx * fontwidth(p); w = width * fontwidth(p);
-	}
-	sbus_writel((w - 1) | ((h - 1) << 11), &us->extent);
-	sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000,
-		    &us->fill);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
-		     int count, unsigned short *boxes)
-{
-	int i;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel((attr_bgcol(p,s)<<24), &ss->fg);
-	while (count-- > 0) {
-		do {
-			i = sbus_readl(&us->csr);
-		} while (i & 0x20000000);
-		sbus_writel((boxes[2] - boxes[0] - 1) | 
-			    ((boxes[3] - boxes[1] - 1) << 11),
-			    &us->extent);
-		sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000,
-			    &us->fill);
-		boxes += 4;
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int i, x, y;
-	u8 *fd;
-	u32 *u;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	if (fontheightlog(p)) {
-		y = yy << (fontheightlog(p) + 11);
-		i = (c & p->charmask) << fontheightlog(p);
-	} else {
-		y = (yy * fontheight(p)) << 11;
-		i = (c & p->charmask) * fontheight(p);
-	}
-	if (fontwidth(p) <= 8)
-		fd = p->fontdata + i;
-	else
-		fd = p->fontdata + (i << 1);
-	if (fontwidthlog(p))
-		x = xx << fontwidthlog(p);
-	else
-		x = xx * fontwidth(p);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	sbus_writel(attr_fgcol(p,c) << 24, &ss->fg);
-	sbus_writel(attr_bgcol(p,c) << 24, &ss->bg);
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)),
-		    &us->fontmsk);
-	u = ((u32 *)fb->info.screen_base) + y + x;
-	if (fontwidth(p) <= 8) {
-		for (i = 0; i < fontheight(p); i++, u += 2048) {
-			u32 val = *fd++ << 24;
-
-			sbus_writel(val, u);
-		}
-	} else {
-		for (i = 0; i < fontheight(p); i++, u += 2048) {
-			u32 val = *(u16 *)fd << 16;
-
-			sbus_writel(val, u);
-			fd += 2;
-		}
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
-		      int count, int yy, int xx)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int i, x, y;
-	u8 *fd1, *fd2, *fd3, *fd4;
-	u16 c;
-	u32 *u;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	c = scr_readw(s);
-	sbus_writel(attr_fgcol(p, c) << 24, &ss->fg);
-	sbus_writel(attr_bgcol(p, c) << 24, &ss->bg);
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
-	if (fontwidthlog(p))
-		x = (xx << fontwidthlog(p));
-	else
-		x = xx * fontwidth(p);
-	if (fontheightlog(p))
-		y = yy << (fontheightlog(p) + 11);
-	else
-		y = (yy * fontheight(p)) << 11;
-	u = ((u32 *)fb->info.screen_base) + y + x;
-	if (fontwidth(p) <= 8) {
-		sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk);
-		x = 4*fontwidth(p) - fontheight(p)*2048;
-		while (count >= 4) {
-			count -= 4;
-			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-			} else {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-			}
-			if (fontwidth(p) == 8) {
-				for (i = 0; i < fontheight(p); i++, u += 2048) {
-					u32 val;
-
-					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< 8)) << 8)) << 8);
-					sbus_writel(val, u);
-				}
-				u += x;
-			} else {
-				for (i = 0; i < fontheight(p); i++, u += 2048) {
-					u32 val;
-
-					val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
-					sbus_writel(val, u);
-				}
-				u += x;
-			}
-		}
-	} else {
-		sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
-		x = 2*fontwidth(p) - fontheight(p)*2048;
-		while (count >= 2) {
-			count -= 2;
-			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-			} else {
-				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-			}
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val;
-
-				val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
-				sbus_writel(val, u);
-				fd1 += 2; fd2 += 2;
-			}
-			u += x;
-		}
-	}
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
-	x = fontwidth(p) - fontheight(p)*2048;
-	while (count) {
-		count--;
-		if (fontheightlog(p))
-			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-		else
-			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
-		if (fontwidth(p) <= 8) {
-			fd1 = p->fontdata + i;
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val = *fd1++ << 24;
-
-				sbus_writel(val, u);
-			}
-		} else {
-			fd1 = p->fontdata + (i << 1);
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val = *(u16 *)fd1 << 16;
-
-				sbus_writel(val, u);
-				fd1 += 2;
-			}
-		}
-		u += x;
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_revc(struct display *p, int xx, int yy)
-{
-	/* Not used if hw cursor */
-}
-
-static int leo_wait (struct leo_lx_krn *lx_krn)
-{
-	int i;
-	
-	for (i = 0; (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
-		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000)
-		return -EFAULT; /* Timed out - should we print some message? */
-	return 0;
-}
-
-static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
-{
-        struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
-	unsigned long flags;
-	u32 tmp;
-	int i;
-	
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
-	i = leo_wait (lx_krn);
-	if (i)
-		goto out;
-	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
-	for (i = 0; i < 256; i++) {
-		u32 val;
-
-		val = fb->color_map CM(i,0) |
-			(fb->color_map CM(i,1) << 8) |
-			(fb->color_map CM(i,2) << 16);
-
-		sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */
-	}
-	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
-	tmp = sbus_readl(&lx_krn->krn_csr);
-	tmp |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
-	sbus_writel(tmp, &lx_krn->krn_csr);
-out:
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_restore_palette (struct fb_info_sbusfb *fb)
-{
-	u32 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
-	tmp &= ~(LEO_SS1_MISC_ENABLE);
-	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static struct display_switch leo_dispsw __initdata = {
-	.setup =	leo_setup,
-	.bmove =	fbcon_redraw_bmove,
-	.clear =	leo_clear,
-	.putc =		leo_putc,
-	.putcs =	leo_putcs,
-	.revc =		leo_revc, 
-	.fontwidthmask =FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
-};
-
-static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
-{
-        struct leo_cursor *l = fb->s.leo.cursor;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++)
-		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000)
-		goto out; /* Timed out - should we print some message? */
-	sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type);
-	sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data);
-	sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data);
-	sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc);
-out:
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Set cursor shape */
-static void leo_setcurshape (struct fb_info_sbusfb *fb)
-{
-	int i, j, k;
-	u32 m, n, mask;
-	struct leo_cursor *l = fb->s.leo.cursor;
-	u32 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&l->cur_misc);
-	tmp &= ~LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	for (k = 0; k < 2; k ++) {
-		sbus_writel((k * LEO_CUR_TYPE_IMAGE), &l->cur_type);
-		for (i = 0; i < 32; i++) {
-			mask = 0;
-			m = fb->cursor.bits[k][i];
-			/* mask = m with reversed bit order */
-			for (j = 0, n = 1; j < 32; j++, n <<= 1)
-				if (m & n)
-					mask |= (0x80000000 >> j);
-			sbus_writel(mask, &l->cur_data);
-		}
-	}
-	tmp = sbus_readl(&l->cur_misc);
-	tmp |= LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Load cursor information */
-static void leo_setcursor (struct fb_info_sbusfb *fb)
-{
-	struct cg_cursor *c = &fb->cursor;
-	struct leo_cursor *l = fb->s.leo.cursor;
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&l->cur_misc);
-	tmp &= ~LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-
-	sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) |
-		    (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11),
-		    &l->cur_cursxy);
-
-	tmp = sbus_readl(&l->cur_misc);
-	tmp |= LEO_CUR_UPDATE;
-	if (c->enable)
-		tmp |= LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int leo_blank (struct fb_info_sbusfb *fb)
-{
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
-
-	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
-	tmp &= ~LEO_KRN_CSR_ENABLE;
-	sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
-	spin_unlock_irqrestore(&fb->lock, flags);
-	return 0;
-}
-
-static int leo_unblank (struct fb_info_sbusfb *fb)
-{
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
-
-	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
-	if (!(tmp & LEO_KRN_CSR_ENABLE)) {
-		tmp |= LEO_KRN_CSR_ENABLE;
-		sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-	return 0;
-}
-
-static int __init
-leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)
-{
-	struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
-	struct fb_wid_item *wi;
-	int i, j;
-
-	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
-	i = leo_wait (lx_krn);
-	if (i)
-		return i;
-	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
-		switch (wi->wi_type) {
-		case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
-		case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
-		default: return -EINVAL;
-		}
-		sbus_writel(0x5800 + j, &lx_krn->krn_type);
-		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
-	}
-	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
-	sbus_writel(3, &lx_krn->krn_csr);
-	return 0;
-}
-
-static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
-{
-	fb->info.screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
-}
-
-static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
-{
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(0xffffffff, &ss->wid);
-	sbus_writel(0xffff, &ss->wmask);
-	sbus_writel(0, &ss->vclipmin);
-	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
-	sbus_writel(0xff000000, &ss->planemask);
-	sbus_writel(0x310850, &ss->rop);
-	sbus_writel(0, &ss->widclip);
-	sbus_writel(4, &us->addrspace);
-	sbus_writel(0, &us->fontt);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int __init leo_rasterimg (struct fb_info *info, int start)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-
-	if (start) {
-		sbus_writel(1, &ss->wid);
-		sbus_writel(0xffffff, &ss->planemask); 
-		sbus_writel(0x310b90, &ss->rop);
-		sbus_writel(0, &us->addrspace);
-	} else {
-		sbus_writel(0xffffffff, &ss->wid);
-		sbus_writel(0xff000000, &ss->planemask);
-		sbus_writel(0x310850, &ss->rop);
-		sbus_writel(4, &us->addrspace);
-	}
-	return 0;
-}
-
-static char idstring[40] __initdata = { 0 };
-
-char * __init leofb_init(struct fb_info_sbusfb *fb)
-{
-	struct fb_fix_screeninfo *fix = &fb->info.fix;
-	struct fb_var_screeninfo *var = &fb->info.var;
-	struct display *disp = &fb->disp;
-	struct fbtype *type = &fb->type;
-	struct sbus_dev *sdev = fb->sbdp;
-	unsigned long phys = sdev->reg_addrs[0].phys_addr;
-	struct fb_wid_item wi;
-	struct fb_wid_list wl;
-	int i;
-	register struct leo_lc_ss0_usr *us;
-	register struct leo_ld *ss;
-	struct fb_ops *fbops;
-	u32 tmp;
-
-	strcpy(fb->info.modename, "Leo");
-		
-	strcpy(fix->id, "Leo");
-	fix->visual = FB_VISUAL_TRUECOLOR;
-	fix->line_length = 8192;
-	fix->accel = FB_ACCEL_SUN_LEO;
-	
-	var->bits_per_pixel = 32;
-	var->green.offset = 8;
-	var->blue.offset = 16;
-	var->accel_flags = FB_ACCELF_TEXT;
-	
-	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-	if (fbops == NULL)
-		return NULL;
-	
-	*fbops = *fb->info.fbops;
-	fbops->fb_rasterimg = leo_rasterimg;
-	fb->info.fbops = fbops;
-	
-	disp->scrollmode = SCROLL_YREDRAW;
-	if (!fb->info.screen_base) {
-		fb->info.screen_base = (char *)
-			sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
-				     0x800000, "leo ram");
-	}
-	fb->info.screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
-	us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
-			     0x1000, "leolc ss0usr");
-	fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
-			     0x1000, "leold ss0");
-	ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
-			     0x1000, "leold ss1");
-	fb->s.leo.lx_krn = (struct leo_lx_krn *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
-			     0x1000, "leolx krn");
-	fb->s.leo.cursor = (struct leo_cursor *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
-			     sizeof(struct leo_cursor), "leolx cursor");
-	fb->dispsw = leo_dispsw;
-	
-	fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
-
-	wl.wl_count = 1;
-	wl.wl_list = &wi;
-	wi.wi_type = FB_WID_DBL_8;
-	wi.wi_index = 0;
-	wi.wi_values [0] = 0x2c0;
-	leo_wid_put (fb, &wl);
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put (fb, &wl);
-	wi.wi_index = 2;
-	wi.wi_values [0] = 0x20;
-	leo_wid_put (fb, &wl);
-	wi.wi_type = FB_WID_DBL_24;
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put (fb, &wl);
-
-	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
-	tmp |= LEO_SS1_MISC_ENABLE;
-	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
-
-	sbus_writel(0xffffffff, &ss->wid);
-	sbus_writel(0xffff, &ss->wmask);
-	sbus_writel(0, &ss->vclipmin);
-	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
-	sbus_writel(0, &ss->fg);
-	sbus_writel(0xff000000, &ss->planemask);
-	sbus_writel(0x310850, &ss->rop);
-	sbus_writel(0, &ss->widclip);
-	sbus_writel((type->fb_width-1) | ((type->fb_height-1) << 11), &us->extent);
-	sbus_writel(4, &us->addrspace);
-	sbus_writel(0x80000000, &us->fill);
-	sbus_writel(0, &us->fontt);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-
-	fb->margins = leo_margins;
-	fb->loadcmap = leo_loadcmap;
-	fb->setcursor = leo_setcursor;
-	fb->setcursormap = leo_setcursormap;
-	fb->setcurshape = leo_setcurshape;
-	fb->restore_palette = leo_restore_palette;
-	fb->switch_from_graph = leo_switch_from_graph;
-	fb->fill = leo_fill;
-	fb->blank = leo_blank;
-	fb->unblank = leo_unblank;
-	
-	fb->physbase = phys;
-	fb->mmap_map = leo_mmap_map;
-	
-#ifdef __sparc_v9__
-	sprintf(idstring, "leo at %016lx", phys);
-#else	
-	sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
-#endif
-		    
-	return idstring;
-}
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/p9100.c b/drivers/video/p9100.c
--- a/drivers/video/p9100.c	Sun Mar  2 22:51:11 2003
+++ b/drivers/video/p9100.c	Tue Mar  4 09:55:26 2003
@@ -27,13 +27,13 @@
  * Local functions.
  */
 
-static int p9100_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int p9100_set_par(struct fb_info *);
 static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			   unsigned, struct fb_info *);
 static int p9100_blank(int, struct fb_info *);
 
 static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int p9100_ioctl(struct inode *, struct file *, unsigned int,
+		       unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -41,14 +41,13 @@
 
 static struct fb_ops p9100_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= p9100_check_var,
-	.fb_set_par		= p9100_set_par,
 	.fb_setcolreg		= p9100_setcolreg,
 	.fb_blank		= p9100_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= p9100_mmap,
+	.fb_ioctl		= p9100_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -143,39 +142,6 @@
 };
 
 /**
- *      p9100_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int p9100_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      p9100_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-p9100_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      p9100_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -265,6 +231,16 @@
 				  vma);
 }
 
+static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		       unsigned long arg, struct fb_info *info)
+{
+	struct p9100_par *par = (struct p9100_par *) info->par;
+
+	/* Make it look like a cg3. */
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN3COLOR, 8, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -344,7 +320,6 @@
 		return;
 	}
 
-	p9100_set_par(&all->info);
 	p9100_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
--- a/drivers/video/sa1100fb.c	Tue Feb 25 02:46:52 2003
+++ b/drivers/video/sa1100fb.c	Thu Mar  6 08:48:29 2003
@@ -1590,11 +1590,21 @@
 	struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
 	struct cpufreq_policy *policy = data;
 
-	if (val == CPUFREQ_INCOMPATIBLE) {
+	switch (val) {
+	case CPUFREQ_ADJUST:
+	case CPUFREQ_INCOMPATIBLE:
 		printk(KERN_DEBUG "min dma period: %d ps, "
 			"new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
 			policy->max);
 		/* todo: fill in min/max values */
+		break;
+	case CPUFREQ_NOTIFY:
+		do {} while(0);
+		/* todo: panic if min/max values aren't fulfilled 
+		 * [can't really happen unless there's a bug in the
+		 * CPU policy verififcation process *
+		 */
+		break;
 	}
 	return 0;
 }
diff -Nru a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
--- a/drivers/video/sbuslib.c	Thu Feb 27 04:19:21 2003
+++ b/drivers/video/sbuslib.c	Tue Mar  4 09:55:26 2003
@@ -9,6 +9,7 @@
 #include <linux/fb.h>
 
 #include <asm/oplib.h>
+#include <asm/fbio.h>
 
 #include "sbuslib.h"
 
@@ -83,3 +84,84 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(sbusfb_mmap_helper);
+
+int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
+			struct fb_info *info,
+			int type, int fb_depth, unsigned long fb_size)
+{
+	switch(cmd) {
+	case FBIOGTYPE: {
+		struct fbtype *f = (struct fbtype *) arg;
+
+		if (put_user(type, &f->fb_type) ||
+		    __put_user(info->var.yres, &f->fb_height) ||
+		    __put_user(info->var.xres, &f->fb_width) ||
+		    __put_user(fb_depth, &f->fb_depth) ||
+		    __put_user(0, &f->fb_cmsize) ||
+		    __put_user(fb_size, &f->fb_cmsize))
+			return -EFAULT;
+		return 0;
+	}
+	case FBIOPUTCMAP_SPARC: {
+		struct fbcmap *c = (struct fbcmap *) arg;
+		struct fb_cmap cmap;
+		u16 red, green, blue;
+		unsigned char *ured, *ugreen, *ublue;
+		int index, count, i;
+
+		if (get_user(index, &c->index) ||
+		    __get_user(count, &c->count) ||
+		    __get_user(ured, &c->red) ||
+		    __get_user(ugreen, &c->green) ||
+		    __get_user(ublue, &c->blue))
+			return -EFAULT;
+
+		cmap.len = 1;
+		cmap.red = &red;
+		cmap.green = &green;
+		cmap.blue = &blue;
+		for (i = 0; i < count; i++) {
+			int err;
+
+			if (get_user(red, &ured[i]) ||
+			    get_user(green, &ugreen[i]) ||
+			    get_user(blue, &ublue[i]))
+				return -EFAULT;
+
+			cmap.start = index + i;
+			err = fb_set_cmap(&cmap, 0, info);
+			if (err)
+				return err;
+		}
+		return 0;
+	}
+	case FBIOGETCMAP_SPARC: {
+		struct fbcmap *c = (struct fbcmap *) arg;
+		unsigned char *ured, *ugreen, *ublue;
+		struct fb_cmap *cmap = &info->cmap;
+		int index, count, i;
+
+		if (get_user(index, &c->index) ||
+		    __get_user(count, &c->count) ||
+		    __get_user(ured, &c->red) ||
+		    __get_user(ugreen, &c->green) ||
+		    __get_user(ublue, &c->blue))
+			return -EFAULT;
+
+		if (index + count > cmap->len)
+			return -EINVAL;
+
+		for (i = 0; i < count; i++) {
+			if (put_user(cmap->red[index + i], &ured[i]) ||
+			    put_user(cmap->green[index + i], &ugreen[i]) ||
+			    put_user(cmap->blue[index + i], &ublue[i]))
+				return -EFAULT;
+		}
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	};
+}
+EXPORT_SYMBOL(sbusfb_ioctl_helper);
diff -Nru a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h
--- a/drivers/video/sbuslib.h	Thu Feb 27 04:19:22 2003
+++ b/drivers/video/sbuslib.h	Tue Mar  4 09:55:26 2003
@@ -17,5 +17,8 @@
 			      unsigned long physbase, unsigned long fbsize,
 			      unsigned long iospace,
 			      struct vm_area_struct *vma);
+int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
+			struct fb_info *info,
+			int type, int fb_depth, unsigned long fb_size);
 
 #endif /* _SBUSLIB_H */
diff -Nru a/drivers/video/tcx.c b/drivers/video/tcx.c
--- a/drivers/video/tcx.c	Sun Mar  2 23:19:15 2003
+++ b/drivers/video/tcx.c	Tue Mar  4 09:55:26 2003
@@ -29,13 +29,13 @@
  * Local functions.
  */
 
-static int tcx_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int tcx_set_par(struct fb_info *);
 static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int tcx_blank(int, struct fb_info *);
 
 static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int tcx_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -43,14 +43,13 @@
 
 static struct fb_ops tcx_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= tcx_check_var,
-	.fb_set_par		= tcx_set_par,
 	.fb_setcolreg		= tcx_setcolreg,
 	.fb_blank		= tcx_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= tcx_mmap,
+	.fb_ioctl		= tcx_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -155,39 +154,6 @@
 }
 
 /**
- *      tcx_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int tcx_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      tcx_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-tcx_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      tcx_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -298,6 +264,17 @@
 				  vma);
 }
 
+static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct tcx_par *par = (struct tcx_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_TCXCOLOR,
+				   (par->lowdepth ? 8 : 24),
+				   par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -431,7 +408,6 @@
 		return;
 	}
 
-	tcx_set_par(&all->info);
 	tcx_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/fs/Kconfig b/fs/Kconfig
--- a/fs/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/fs/Kconfig	Sun Mar 16 11:38:31 2003
@@ -4,89 +4,180 @@
 
 menu "File systems"
 
-config QUOTA
-	bool "Quota support"
+config EXT2_FS
+	tristate "Second extended fs support"
 	help
-	  If you say Y here, you will be able to set per user limits for disk
-	  usage (also called disk quotas). Currently, it works for the
-	  ext2, ext3, and reiserfs file system. You need additional software
-	  in order to use quota support (you can download sources from
-	  <http://www.sf.net/projects/linuxquota/>). For further details, read
-	  the Quota mini-HOWTO, available from
-	  <http://www.linuxdoc.org/docs.html#howto>. Probably the quota
-	  support is only useful for multi user systems. If unsure, say N.
+	  This is the de facto standard Linux file system (method to organize
+	  files on a storage device) for hard disks.
 
-config QFMT_V1
-	tristate "Old quota format support"
-	depends on QUOTA
+	  You want to say Y here, unless you intend to use Linux exclusively
+	  from inside a DOS partition using the UMSDOS file system. The
+	  advantage of the latter is that you can get away without
+	  repartitioning your hard drive (which often implies backing
+	  everything up and restoring afterwards); the disadvantage is that
+	  Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat
+	  slower than ext2fs. Even if you want to run Linux in this fashion,
+	  it might be a good idea to have ext2fs around: it enables you to
+	  read more floppy disks and facilitates the transition to a *real*
+	  Linux partition later. Another (rare) case which doesn't require
+	  ext2fs is a diskless Linux box which mounts all files over the
+	  network using NFS (in this case it's sufficient to say Y to "NFS
+	  file system support" below). Saying Y here will enlarge your kernel
+	  by about 44 KB.
+
+	  The Ext2fs-Undeletion mini-HOWTO, available from
+	  <http://www.linuxdoc.org/docs.html#howto>, gives information about
+	  how to retrieve deleted files on ext2fs file systems.
+
+	  To change the behavior of ext2 file systems, you can use the tune2fs
+	  utility ("man tune2fs"). To modify attributes of files and
+	  directories on ext2 file systems, use chattr ("man chattr").
+
+	  Ext2fs partitions can be read from within DOS using the ext2tool
+	  command line tool package (available from
+	  <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from
+	  within Windows NT using the ext2nt command line tool package from
+	  <ftp://ibiblio.org/pub/Linux/utils/dos/>.  Explore2fs is a
+	  graphical explorer for ext2fs partitions which runs on Windows 95
+	  and Windows NT and includes experimental write support; it is
+	  available from
+	  <http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm>.
+
+	  If you want to compile this file system as a module ( = code which
+	  can be inserted in and removed from the running kernel whenever you
+	  want), say M here and read <file:Documentation/modules.txt>.  The
+	  module will be called ext2.  Be aware however that the file system
+	  of your root partition (the one containing the directory /) cannot
+	  be compiled as a module, and so this could be dangerous.  Most
+	  everyone wants to say Y here.
+
+config EXT2_FS_XATTR
+	bool "Ext2 extended attributes"
+	depends on EXT2_FS
 	help
-	  This quota format was (is) used by kernels earlier than 2.4.??. If
-	  you have quota working and you don't want to convert to new quota
-	  format say Y here.
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
 
-config QFMT_V2
-	tristate "Quota format v2 support"
-	depends on QUOTA
+	  If unsure, say N.
+
+config EXT2_FS_POSIX_ACL
+	bool "Ext2 POSIX Access Control Lists"
+	depends on EXT2_FS_XATTR
 	help
-	  This quota format allows using quotas with 32-bit UIDs/GIDs. If you
-	  need this functionality say Y here. Note that you will need latest
-	  quota utilities for new quota format with this kernel.
+	  Posix Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
 
-config QUOTACTL
-	bool
-	depends on XFS_QUOTA || QUOTA
+	  To learn more about Access Control Lists, visit the Posix ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+
+	  If you don't know what Access Control Lists are, say N
+
+config EXT3_FS
+	tristate "Ext3 journalling file system support"
+	help
+	  This is the journaling version of the Second extended file system
+	  (often called ext3), the de facto standard Linux file system
+	  (method to organize files on a storage device) for hard disks.
+
+	  The journaling code included in this driver means you do not have
+	  to run e2fsck (file system checker) on your file systems after a
+	  crash.  The journal keeps track of any changes that were being made
+	  at the time the system crashed, and can ensure that your file system
+	  is consistent without the need for a lengthy check.
+
+	  Other than adding the journal to the file system, the on-disk format
+	  of ext3 is identical to ext2.  It is possible to freely switch
+	  between using the ext3 driver and the ext2 driver, as long as the
+	  file system has been cleanly unmounted, or e2fsck is run on the file
+	  system.
+
+	  To add a journal on an existing ext2 file system or change the
+	  behavior of ext3 file systems, you can use the tune2fs utility ("man
+	  tune2fs").  To modify attributes of files and directories on ext3
+	  file systems, use chattr ("man chattr").  You need to be using
+	  e2fsprogs version 1.20 or later in order to create ext3 journals
+	  (available at <http://sourceforge.net/projects/e2fsprogs/>).
+
+	  If you want to compile this file system as a module ( = code which
+	  can be inserted in and removed from the running kernel whenever you
+	  want), say M here and read <file:Documentation/modules.txt>.  The
+	  module will be called ext3.  Be aware however that the file system
+	  of your root partition (the one containing the directory /) cannot
+	  be compiled as a module, and so this may be dangerous.
+
+config EXT3_FS_XATTR
+	bool "Ext3 extended attributes"
+	depends on EXT3_FS
 	default y
+	help
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
 
-config AUTOFS_FS
-	tristate "Kernel automounter support"
-	---help---
-	  The automounter is a tool to automatically mount remote file systems
-	  on demand. This implementation is partially kernel-based to reduce
-	  overhead in the already-mounted case; this is unlike the BSD
-	  automounter (amd), which is a pure user space daemon.
+	  If unsure, say N.
 
-	  To use the automounter you need the user-space tools from the autofs
-	  package; you can find the location in <file:Documentation/Changes>.
-	  You also want to answer Y to "NFS file system support", below.
+	  You need this for POSIX ACL support on ext3.
 
-	  If you want to use the newer version of the automounter with more
-	  features, say N here and say Y to "Kernel automounter v4 support",
-	  below.
+config EXT3_FS_POSIX_ACL
+	bool "Ext3 POSIX Access Control Lists"
+	depends on EXT3_FS_XATTR
+	help
+	  Posix Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
 
-	  If you want to compile this as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called autofs.
+	  To learn more about Access Control Lists, visit the Posix ACLs for
+	  Linux website <http://acl.bestbits.at/>.
 
-	  If you are not a part of a fairly large, distributed network, you
-	  probably do not need an automounter, and can say N here.
+	  If you don't know what Access Control Lists are, say N
 
-config AUTOFS4_FS
-	tristate "Kernel automounter version 4 support (also supports v3)"
-	---help---
-	  The automounter is a tool to automatically mount remote file systems
-	  on demand. This implementation is partially kernel-based to reduce
-	  overhead in the already-mounted case; this is unlike the BSD
-	  automounter (amd), which is a pure user space daemon.
+config JBD
+# CONFIG_JBD could be its own option (even modular), but until there are
+# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
+# dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
+	bool
+	default EXT3_FS
+	help
+	  This is a generic journaling layer for block devices.  It is
+	  currently used by the ext3 file system, but it could also be used to
+	  add journal support to other file systems or block devices such as
+	  RAID or LVM.
 
-	  To use the automounter you need the user-space tools from
-	  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also
-	  want to answer Y to "NFS file system support", below.
+	  If you are using the ext3 file system, you need to say Y here. If
+	  you are not using ext3 then you will probably want to say N.
 
-	  If you want to compile this as a module ( = code which can be
+	  If you want to compile this device as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called autofs4.  You will need to add "alias autofs
-	  autofs4" to your modules configuration file.
+	  will be called jbd.  If you are compiling ext3 into the kernel,
+	  you cannot compile this code as a module.
 
-	  If you are not a part of a fairly large, distributed network or
-	  don't have a laptop which needs to dynamically reconfigure to the
-	  local network, you probably do not need an automounter, and can say
-	  N here.
+config JBD_DEBUG
+	bool "JBD (ext3) debugging support"
+	depends on JBD
+	help
+	  If you are using the ext3 journaled file system (or potentially any
+	  other file system/device using JBD), this option allows you to
+	  enable debugging output while the system is running, in order to
+	  help track down any problems you are having.  By default the
+	  debugging output will be turned off.
+
+	  If you select Y here, then you will be able to turn on debugging
+	  with "echo N > /proc/sys/fs/jbd-debug", where N is a number between
+	  1 and 5, the higher the number, the more debugging output is
+	  generated.  To turn debugging off again, do
+	  "echo 0 > /proc/sys/fs/jbd-debug".
+
+config FS_MBCACHE
+# Meta block cache for Extended Attributes (ext2/ext3)
+	tristate
+	depends on EXT2_FS_XATTR || EXT3_FS_XATTR
+	default y if EXT2_FS=y || EXT3_FS=y
+	default m if EXT2_FS=m || EXT3_FS=m
 
 config REISERFS_FS
 	tristate "Reiserfs support"
-	---help---
+	help
 	  Stores not just filenames but the files themselves in a balanced
 	  tree.  Uses journaling.
 
@@ -135,226 +226,308 @@
 	  Almost everyone but ReiserFS developers and people fine-tuning
 	  reiserfs or tracing problems should say N.
 
-config ADFS_FS
-	tristate "ADFS file system support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  The Acorn Disc Filing System is the standard file system of the
-	  RiscOS operating system which runs on Acorn's ARM-based Risc PC
-	  systems and the Acorn Archimedes range of machines. If you say Y
-	  here, Linux will be able to read from ADFS partitions on hard drives
-	  and from ADFS-formatted floppy discs. If you also want to be able to
-	  write to those devices, say Y to "ADFS write support" below.
+config JFS_FS
+	tristate "JFS filesystem support"
+	help
+	  This is a port of IBM's Journaled Filesystem .  More information is
+	  available in the file Documentation/filesystems/jfs.txt.
 
-	  The ADFS partition should be the first partition (i.e.,
-	  /dev/[hs]d?1) on each of your drives. Please read the file
-	  <file:Documentation/filesystems/adfs.txt> for further details.
+	  If you do not intend to use the JFS filesystem, say N.
 
-	  This code is also available as a module called adfs ( = code which
+config JFS_POSIX_ACL
+	bool "JFS POSIX Access Control Lists"
+	depends on JFS_FS
+	help
+	  Posix Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
+
+	  To learn more about Access Control Lists, visit the Posix ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+
+	  If you don't know what Access Control Lists are, say N
+
+config JFS_DEBUG
+	bool "JFS debugging"
+	depends on JFS_FS
+	help
+	  If you are experiencing any problems with the JFS filesystem, say
+	  Y here.  This will result in additional debugging messages to be
+	  written to the system log.  Under normal circumstances, this
+	  results in very little overhead.
+
+config JFS_STATISTICS
+	bool "JFS statistics"
+	depends on JFS_FS
+	help
+	  Enabling this option will cause statistics from the JFS file system
+	  to be made available to the user in the /proc/fs/jfs/ directory.
+
+config FS_POSIX_ACL
+# Posix ACL utility routines (for now, only ext2/ext3/jfs)
+#
+# NOTE: you can implement Posix ACLs without these helpers (XFS does).
+# 	Never use this symbol for ifdefs.
+#
+	bool
+	depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL
+	default y
+
+config XFS_FS
+	tristate "XFS filesystem support"
+	help
+	  XFS is a high performance journaling filesystem which originated
+	  on the SGI IRIX platform.  It is completely multi-threaded, can
+	  support large files and large filesystems, extended attributes,
+	  variable block sizes, is extent based, and makes extensive use of
+	  Btrees (directories, extents, free space) to aid both performance
+	  and scalability.
+
+	  Refer to the documentation at <http://oss.sgi.com/projects/xfs/>
+	  for complete details.  This implementation is on-disk compatible
+	  with the IRIX version of XFS.
+
+	  If you want to compile this file system as a module ( = code which
 	  can be inserted in and removed from the running kernel whenever you
-	  want). If you want to compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.
+	  want), say M here and read <file:Documentation/modules.txt>. The
+	  module will be called xfs.  Be aware, however, that if the file
+	  system of your root partition is compiled as a module, you'll need
+	  to use an initial ramdisk (initrd) to boot.
+
+config XFS_RT
+	bool "Realtime support (EXPERIMENTAL)"
+	depends on XFS_FS && EXPERIMENTAL
+	help
+	  If you say Y here you will be able to mount and use XFS filesystems
+	  which contain a realtime subvolume. The realtime subvolume is a
+	  separate area of disk space where only file data is stored. The
+	  realtime subvolume is designed to provide very deterministic
+	  data rates suitable for media streaming applications.
+
+	  See the xfs man page in section 5 for a bit more information.
+
+	  This feature is unsupported at this time, is not yet fully
+	  functional, and may cause serious problems.
 
 	  If unsure, say N.
 
-config ADFS_FS_RW
-	bool "ADFS write support (DANGEROUS)"
-	depends on ADFS_FS
+config XFS_QUOTA
+	bool "Quota support"
+	depends on XFS_FS
 	help
-	  If you say Y here, you will be able to write to ADFS partitions on
-	  hard drives and ADFS-formatted floppy disks. This is experimental
-	  codes, so if you're unsure, say N.
+	  If you say Y here, you will be able to set limits for disk usage on
+	  a per user and/or a per group basis under XFS.  XFS considers quota
+	  information as filesystem metadata and uses journaling to provide a
+	  higher level guarantee of consistency.  The on-disk data format for
+	  quota is also compatible with the IRIX version of XFS, allowing a
+	  filesystem to be migrated between Linux and IRIX without any need
+	  for conversion.
 
-config AFFS_FS
-	tristate "Amiga FFS file system support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  The Fast File System (FFS) is the common file system used on hard
-	  disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20).  Say Y
-	  if you want to be able to read and write files from and to an Amiga
-	  FFS partition on your hard drive.  Amiga floppies however cannot be
-	  read with this driver due to an incompatibility of the floppy
-	  controller used in an Amiga and the standard floppy controller in
-	  PCs and workstations. Read <file:Documentation/filesystems/affs.txt>
-	  and <file:fs/affs/Changes>.
+	  If unsure, say N.  More comprehensive documentation can be found in
+	  README.quota in the xfsprogs package.  XFS quota can be used either
+	  with or without the generic quota support enabled (CONFIG_QUOTA) -
+	  they are completely independent subsystems.
 
-	  With this driver you can also mount disk files used by Bernd
-	  Schmidt's Un*X Amiga Emulator
-	  (<http://www.freiburg.linux.de/~uae/>).
-	  If you want to do this, you will also need to say Y or M to "Loop
-	  device support", above.
+config XFS_POSIX_ACL
+	bool "ACL support"
+	depends on XFS_FS
+	help
+	  Posix Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
 
-	  This file system is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module is called affs.  If you want to compile it as a module,
-	  say M here and read <file:Documentation/modules.txt>.  If unsure,
-	  say N.
+	  To learn more about Access Control Lists, visit the Posix ACLs for
+	  Linux website <http://acl.bestbits.at/>.
 
-config HFS_FS
-	tristate "Apple Macintosh file system support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	  If you don't know what Access Control Lists are, say N
+
+config MINIX_FS
+	tristate "Minix fs support"
+	help
+	  Minix is a simple operating system used in many classes about OS's.
+	  The minix file system (method to organize files on a hard disk
+	  partition or a floppy disk) was the original file system for Linux,
+	  but has been superseded by the second extended file system ext2fs.
+	  You don't want to use the minix file system on your hard disk
+	  because of certain built-in restrictions, but it is sometimes found
+	  on older Linux floppy disks.  This option will enlarge your kernel
+	  by about 28 KB. If unsure, say N.
+
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>. The module
+	  will be called minix.  Note that the file system of your root
+	  partition (the one containing the directory /) cannot be compiled as
+	  a module.
+
+config ROMFS_FS
+	tristate "ROM file system support"
 	---help---
-	  If you say Y here, you will be able to mount Macintosh-formatted
-	  floppy disks and hard drive partitions with full read-write access.
-	  Please read <file:fs/hfs/HFS.txt> to learn about the available mount
-	  options.
+	  This is a very small read-only file system mainly intended for
+	  initial ram disks of installation disks, but it could be used for
+	  other read-only media as well.  Read
+	  <file:Documentation/filesystems/romfs.txt> for details.
 
 	  This file system support is also available as a module ( = code
 	  which can be inserted in and removed from the running kernel
-	  whenever you want). The module is called hfs.  If you want to
+	  whenever you want). The module is called romfs.  If you want to
 	  compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.
+	  <file:Documentation/modules.txt>.  Note that the file system of your
+	  root partition (the one containing the directory /) cannot be a
+	  module.
 
-config BEFS_FS
-	tristate "BeOS file systemv(BeFS) support (read only) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  The BeOS File System (BeFS) is the native file system of Be, Inc's
-	  BeOS. Notable features include support for arbitrary attributes
-	  on files and directories, and database-like indices on selected
-	  attributes. (Also note that this driver doesn't make those features
-	  available at this time). It is a 64 bit filesystem, so it supports
-	  extreemly large volumes and files.
+	  If you don't know whether you need it, then you don't need it:
+	  answer N.
 
-	  If you use this filesystem, you should also say Y to at least one
-	  of the NLS (native language support) options below.
+config QUOTA
+	bool "Quota support"
+	help
+	  If you say Y here, you will be able to set per user limits for disk
+	  usage (also called disk quotas). Currently, it works for the
+	  ext2, ext3, and reiserfs file system. You need additional software
+	  in order to use quota support (you can download sources from
+	  <http://www.sf.net/projects/linuxquota/>). For further details, read
+	  the Quota mini-HOWTO, available from
+	  <http://www.linuxdoc.org/docs.html#howto>. Probably the quota
+	  support is only useful for multi user systems. If unsure, say N.
 
-	  If you don't know what this is about, say N.
+config QFMT_V1
+	tristate "Old quota format support"
+	depends on QUOTA
+	help
+	  This quota format was (is) used by kernels earlier than 2.4.??. If
+	  you have quota working and you don't want to convert to new quota
+	  format say Y here.
 
-	  If you want to compile this as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read Documentation/modules.txt. The module will be
-	  called befs.
+config QFMT_V2
+	tristate "Quota format v2 support"
+	depends on QUOTA
+	help
+	  This quota format allows using quotas with 32-bit UIDs/GIDs. If you
+	  need this functionality say Y here. Note that you will need latest
+	  quota utilities for new quota format with this kernel.
 
-config BEFS_DEBUG
-	bool "Debug BeFS"
-	depends on BEFS_FS
+config QUOTACTL
+	bool
+	depends on XFS_QUOTA || QUOTA
+	default y
+
+config AUTOFS_FS
+	tristate "Kernel automounter support"
 	help
-	  If you say Y here, you can use the 'debug' mount option to enable
-	  debugging output from the driver. 
+	  The automounter is a tool to automatically mount remote file systems
+	  on demand. This implementation is partially kernel-based to reduce
+	  overhead in the already-mounted case; this is unlike the BSD
+	  automounter (amd), which is a pure user space daemon.
 
-config BFS_FS
-	tristate "BFS file system support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  Boot File System (BFS) is a file system used under SCO UnixWare to
-	  allow the bootloader access to the kernel image and other important
-	  files during the boot process.  It is usually mounted under /stand
-	  and corresponds to the slice marked as "STAND" in the UnixWare
-	  partition.  You should say Y if you want to read or write the files
-	  on your /stand slice from within Linux.  You then also need to say Y
-	  to "UnixWare slices support", below.  More information about the BFS
-	  file system is contained in the file
-	  <file:Documentation/filesystems/bfs.txt>.
+	  To use the automounter you need the user-space tools from the autofs
+	  package; you can find the location in <file:Documentation/Changes>.
+	  You also want to answer Y to "NFS file system support", below.
 
-	  If you don't know what this is about, say N.
+	  If you want to use the newer version of the automounter with more
+	  features, say N here and say Y to "Kernel automounter v4 support",
+	  below.
 
 	  If you want to compile this as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called bfs.  Note that the file system of your root
-	  partition (the one containing the directory /) cannot be compiled as
-	  a module.
+	  will be called autofs.
 
-config EXT3_FS
-	tristate "Ext3 journalling file system support"
-	---help---
-	  This is the journaling version of the Second extended file system
-	  (often called ext3), the de facto standard Linux file system
-	  (method to organize files on a storage device) for hard disks.
+	  If you are not a part of a fairly large, distributed network, you
+	  probably do not need an automounter, and can say N here.
 
-	  The journaling code included in this driver means you do not have
-	  to run e2fsck (file system checker) on your file systems after a
-	  crash.  The journal keeps track of any changes that were being made
-	  at the time the system crashed, and can ensure that your file system
-	  is consistent without the need for a lengthy check.
+config AUTOFS4_FS
+	tristate "Kernel automounter version 4 support (also supports v3)"
+	help
+	  The automounter is a tool to automatically mount remote file systems
+	  on demand. This implementation is partially kernel-based to reduce
+	  overhead in the already-mounted case; this is unlike the BSD
+	  automounter (amd), which is a pure user space daemon.
 
-	  Other than adding the journal to the file system, the on-disk format
-	  of ext3 is identical to ext2.  It is possible to freely switch
-	  between using the ext3 driver and the ext2 driver, as long as the
-	  file system has been cleanly unmounted, or e2fsck is run on the file
-	  system.
+	  To use the automounter you need the user-space tools from
+	  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also
+	  want to answer Y to "NFS file system support", below.
 
-	  To add a journal on an existing ext2 file system or change the
-	  behavior of ext3 file systems, you can use the tune2fs utility ("man
-	  tune2fs").  To modify attributes of files and directories on ext3
-	  file systems, use chattr ("man chattr").  You need to be using
-	  e2fsprogs version 1.20 or later in order to create ext3 journals
-	  (available at <http://sourceforge.net/projects/e2fsprogs/>).
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>.  The module
+	  will be called autofs4.  You will need to add "alias autofs
+	  autofs4" to your modules configuration file.
 
-	  If you want to compile this file system as a module ( = code which
-	  can be inserted in and removed from the running kernel whenever you
-	  want), say M here and read <file:Documentation/modules.txt>.  The
-	  module will be called ext3.  Be aware however that the file system
-	  of your root partition (the one containing the directory /) cannot
-	  be compiled as a module, and so this may be dangerous.
+	  If you are not a part of a fairly large, distributed network or
+	  don't have a laptop which needs to dynamically reconfigure to the
+	  local network, you probably do not need an automounter, and can say
+	  N here.
 
-config EXT3_FS_XATTR
-	bool "Ext3 extended attributes"
-	depends on EXT3_FS
-	default y
-	---help---
-	  Extended attributes are name:value pairs associated with inodes by
-	  the kernel or by users (see the attr(5) manual page, or visit
-	  <http://acl.bestbits.at/> for details).
+menu "CD-ROM/DVD Filesystems"
 
-	  If unsure, say N.
+config ISO9660_FS
+	tristate "ISO 9660 CDROM file system support"
+	help
+	  This is the standard file system used on CD-ROMs.  It was previously
+	  known as "High Sierra File System" and is called "hsfs" on other
+	  Unix systems.  The so-called Rock-Ridge extensions which allow for
+	  long Unix filenames and symbolic links are also supported by this
+	  driver.  If you have a CD-ROM drive and want to do more with it than
+	  just listen to audio CDs and watch its LEDs, say Y (and read
+	  <file:Documentation/filesystems/isofs.txt> and the CD-ROM-HOWTO,
+	  available from <http://www.linuxdoc.org/docs.html#howto>), thereby
+	  enlarging your kernel by about 27 KB; otherwise say N.
 
-	  You need this for POSIX ACL support on ext3.
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>.  The module
+	  will be called isofs.
 
-config EXT3_FS_POSIX_ACL
-	bool "Ext3 POSIX Access Control Lists"
-	depends on EXT3_FS_XATTR
-	---help---
-	  Posix Access Control Lists (ACLs) support permissions for users and
-	  groups beyond the owner/group/world scheme.
+config JOLIET
+	bool "Microsoft Joliet CDROM extensions"
+	depends on ISO9660_FS
+	help
+	  Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system
+	  which allows for long filenames in unicode format (unicode is the
+	  new 16 bit character code, successor to ASCII, which encodes the
+	  characters of almost all languages of the world; see
+	  <http://www.unicode.org/> for more information).  Say Y here if you
+	  want to be able to read Joliet CD-ROMs under Linux.
 
-	  To learn more about Access Control Lists, visit the Posix ACLs for
-	  Linux website <http://acl.bestbits.at/>.
+config ZISOFS
+	bool "Transparent decompression extension"
+	depends on ISO9660_FS
+	help
+	  This is a Linux-specific extension to RockRidge which lets you store
+	  data in compressed form on a CD-ROM and have it transparently
+	  decompressed when the CD-ROM is accessed.  See
+	  <http://www.kernel.org/pub/linux/utils/fs/zisofs/> for the tools
+	  necessary to create such a filesystem.  Say Y here if you want to be
+	  able to read such compressed CD-ROMs.
 
-	  If you don't know what Access Control Lists are, say N
+config ZISOFS_FS
+# for fs/nls/Config.in
+	tristate
+	depends on ZISOFS
+	default ISO9660_FS
 
-# CONFIG_JBD could be its own option (even modular), but until there are
-# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
-# dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
-config JBD
-	bool
-	default EXT3_FS
-	---help---
-	  This is a generic journaling layer for block devices.  It is
-	  currently used by the ext3 file system, but it could also be used to
-	  add journal support to other file systems or block devices such as
-	  RAID or LVM.
+config UDF_FS
+	tristate "UDF file system support"
+	help
+	  This is the new file system used on some CD-ROMs and DVDs. Say Y if
+	  you intend to mount DVD discs or CDRW's written in packet mode, or
+	  if written to by other UDF utilities, such as DirectCD.
+	  Please read <file:Documentation/filesystems/udf.txt>.
 
-	  If you are using the ext3 file system, you need to say Y here. If
-	  you are not using ext3 then you will probably want to say N.
+	  This file system support is also available as a module ( = code
+	  which can be inserted in and removed from the running kernel
+	  whenever you want). The module is called udf. If you want to
+	  compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.
 
-	  If you want to compile this device as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called jbd.  If you are compiling ext3 into the kernel,
-	  you cannot compile this code as a module.
+	  If unsure, say N.
 
-config JBD_DEBUG
-	bool "JBD (ext3) debugging support"
-	depends on JBD
-	---help---
-	  If you are using the ext3 journaled file system (or potentially any
-	  other file system/device using JBD), this option allows you to
-	  enable debugging output while the system is running, in order to
-	  help track down any problems you are having.  By default the
-	  debugging output will be turned off.
+endmenu
 
-	  If you select Y here, then you will be able to turn on debugging
-	  with "echo N > /proc/sys/fs/jbd-debug", where N is a number between
-	  1 and 5, the higher the number, the more debugging output is
-	  generated.  To turn debugging off again, do
-	  "echo 0 > /proc/sys/fs/jbd-debug".
+menu "DOS/FAT/NT Filesystems"
 
-# msdos file systems
 config FAT_FS
 	tristate "DOS FAT fs support"
-	---help---
+	help
 	  If you want to use one of the FAT-based file systems (the MS-DOS,
 	  VFAT (Windows 95) and UMSDOS (used to run Linux on top of an
 	  ordinary DOS partition) file systems), then you must say Y or M here
@@ -398,7 +571,7 @@
 config MSDOS_FS
 	tristate "MSDOS fs support"
 	depends on FAT_FS
-	---help---
+	help
 	  This allows you to mount MSDOS partitions of your hard drive (unless
 	  they are compressed; to access compressed MSDOS partitions under
 	  Linux, you can either use the DOS emulator DOSEMU, described in the
@@ -427,11 +600,35 @@
 	  <file:Documentation/modules.txt>.
 	  The module will be called msdos.
 
+config VFAT_FS
+	tristate "VFAT (Windows-95) fs support"
+	depends on FAT_FS
+	help
+	  This option provides support for normal Windows file systems with
+	  long filenames.  That includes non-compressed FAT-based file systems
+	  used by Windows 95, Windows 98, Windows NT 4.0, and the Unix
+	  programs from the mtools package.
+
+	  You cannot use the VFAT file system for your Linux root partition
+	  (the one containing the directory /); use UMSDOS instead if you
+	  want to run Linux from within a DOS partition (i.e. say Y to
+	  "Unix like fs on top of std MSDOS fs", below).
+
+	  The VFAT support enlarges your kernel by about 10 KB and it only
+	  works if you said Y to the "DOS FAT fs support" above.  Please read
+	  the file <file:Documentation/filesystems/vfat.txt> for details.  If
+	  unsure, say Y.
+
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>.  The module
+	  will be called vfat.
+
+config UMSDOS_FS
 #dep_tristate '    UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
 # UMSDOS is temprory broken
-config UMSDOS_FS
 	bool
-	---help---
+	help
 	  Say Y here if you want to run Linux from within an existing DOS
 	  partition of your hard drive. The advantage of this is that you can
 	  get away without repartitioning your hard drive (which often implies
@@ -458,34 +655,317 @@
 	  root partition (the one containing the directory /) cannot be a
 	  module, so saying M could be dangerous.  If unsure, say N.
 
-config VFAT_FS
-	tristate "VFAT (Windows-95) fs support"
-	depends on FAT_FS
+config NTFS_FS
+	tristate "NTFS file system support (read only)"
+	help
+	  NTFS is the file system of Microsoft Windows NT/2000/XP. For more
+	  information see <file:Documentation/filesystems/ntfs.txt>. Saying Y
+	  here would allow you to read from NTFS partitions.
+
+	  This file system 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 ntfs. If you want to compile it as a
+	  module, say M here and read <file:Documentation/modules.txt>.
+
+	  If you are not using Windows NT/2000/XP in addition to Linux on your
+	  computer it is safe to say N.
+
+config NTFS_DEBUG
+	bool "NTFS debugging support"
+	depends on NTFS_FS
+	help
+	  If you are experiencing any problems with the NTFS file system, say
+	  Y here. This will result in additional consistency checks to be
+	  performed by the driver as well as additional debugging messages to
+	  be written to the system log. Note that debugging messages are
+	  disabled by default. To enable them, supply the option debug_msgs=1
+	  at the kernel command line when booting the kernel or as an option
+	  to insmod when loading the ntfs module. Once the driver is active,
+	  you can enable debugging messages by doing (as root):
+	  echo 1 > /proc/sys/fs/ntfs-debug
+	  Replacing the "1" with "0" would disable debug messages.
+
+	  If you leave debugging messages disabled, this results in little
+	  overhead, but enabling debug messages results in very significant
+	  slowdown of the system.
+
+	  When reporting bugs, please try to have available a full dump of
+	  debugging messages while the misbehaviour was occurring.
+
+config NTFS_RW
+	bool "NTFS write support (DANGEROUS)"
+	depends on NTFS_FS && EXPERIMENTAL
+	help
+	  This enables the experimental write support in the NTFS driver.
+
+	  WARNING: Do not use this option unless you are actively developing
+	  NTFS as it is currently guaranteed to be broken and you
+	  may lose all your data!
+
+	  It is strongly recommended and perfectly safe to say N here.
+
+endmenu
+
+menu "Pseudo filesystems"
+
+config PROC_FS
+	bool "/proc file system support"
+	help
+	  This is a virtual file system providing information about the status
+	  of the system. "Virtual" means that it doesn't take up any space on
+	  your hard disk: the files are created on the fly by the kernel when
+	  you try to access them. Also, you cannot read the files with older
+	  version of the program less: you need to use more or cat.
+
+	  It's totally cool; for example, "cat /proc/interrupts" gives
+	  information about what the different IRQs are used for at the moment
+	  (there is a small number of Interrupt ReQuest lines in your computer
+	  that are used by the attached devices to gain the CPU's attention --
+	  often a source of trouble if two devices are mistakenly configured
+	  to use the same IRQ). The program procinfo to display some
+	  information about your system gathered from the /proc file system.
+
+	  Before you can use the /proc file system, it has to be mounted,
+	  meaning it has to be given a location in the directory hierarchy.
+	  That location should be /proc. A command such as "mount -t proc proc
+	  /proc" or the equivalent line in /etc/fstab does the job.
+
+	  The /proc file system is explained in the file
+	  <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage
+	  ("man 5 proc").
+
+	  This option will enlarge your kernel by about 67 KB. Several
+	  programs depend on this, so everyone should say Y here.
+
+config DEVFS_FS
+	bool "/dev file system support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  This is support for devfs, a virtual file system (like /proc) which
+	  provides the file system interface to device drivers, normally found
+	  in /dev. Devfs does not depend on major and minor number
+	  allocations. Device drivers register entries in /dev which then
+	  appear automatically, which means that the system administrator does
+	  not have to create character and block special device files in the
+	  /dev directory using the mknod command (or MAKEDEV script) anymore.
+
+	  This is work in progress. If you want to use this, you *must* read
+	  the material in <file:Documentation/filesystems/devfs/>, especially
+	  the file README there.
+
+	  If unsure, say N.
+
+config DEVFS_MOUNT
+	bool "Automatically mount at boot"
+	depends on DEVFS_FS
+	help
+	  This option appears if you have CONFIG_DEVFS_FS enabled. Setting
+	  this to 'Y' will make the kernel automatically mount devfs onto /dev
+	  when the system is booted, before the init thread is started.
+	  You can override this with the "devfs=nomount" boot option.
+
+	  If unsure, say N.
+
+config DEVFS_DEBUG
+	bool "Debug devfs"
+	depends on DEVFS_FS
+	help
+	  If you say Y here, then the /dev file system code will generate
+	  debugging messages. See the file
+	  <file:Documentation/filesystems/devfs/boot-options> for more
+	  details.
+
+	  If unsure, say N.
+
+config DEVPTS_FS
+# It compiles as a module for testing only.  It should not be used
+# as a module in general.  If we make this "tristate", a bunch of people
+# who don't know what they are doing turn it on and complain when it
+# breaks.
+	bool "/dev/pts file system for Unix98 PTYs"
+	depends on UNIX98_PTYS
 	---help---
-	  This option provides support for normal Windows file systems with
-	  long filenames.  That includes non-compressed FAT-based file systems
-	  used by Windows 95, Windows 98, Windows NT 4.0, and the Unix
-	  programs from the mtools package.
+	  You should say Y here if you said Y to "Unix98 PTY support" above.
+	  You'll then get a virtual file system which can be mounted on
+	  /dev/pts with "mount -t devpts". This, together with the pseudo
+	  terminal master multiplexer /dev/ptmx, is used for pseudo terminal
+	  support as described in The Open Group's Unix98 standard: in order
+	  to acquire a pseudo terminal, a process opens /dev/ptmx; the number
+	  of the pseudo terminal is then made available to the process and the
+	  pseudo terminal slave can be accessed as /dev/pts/<number>. What was
+	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
 
-	  You cannot use the VFAT file system for your Linux root partition
-	  (the one containing the directory /); use UMSDOS instead if you
-	  want to run Linux from within a DOS partition (i.e. say Y to
-	  "Unix like fs on top of std MSDOS fs", below).
+	  The GNU C library glibc 2.1 contains the requisite support for this
+	  mode of operation; you also need client programs that use the Unix98
+	  API. Please read <file:Documentation/Changes> for more information
+	  about the Unix98 pty devices.
 
-	  The VFAT support enlarges your kernel by about 10 KB and it only
-	  works if you said Y to the "DOS FAT fs support" above.  Please read
-	  the file <file:Documentation/filesystems/vfat.txt> for details.  If
-	  unsure, say Y.
+	  Note that the experimental "/dev file system support"
+	  (CONFIG_DEVFS_FS)  is a more general facility.
+
+config TMPFS
+	bool "Virtual memory file system support (former shm fs)"
+	help
+	  Tmpfs is a file system which keeps all files in virtual memory.
+
+	  Everything in tmpfs is temporary in the sense that no files will be
+	  created on your hard drive. The files live in memory and swap
+	  space. If you unmount a tmpfs instance, everything stored therein is
+	  lost.
+
+	  See <file:Documentation/filesystems/tmpfs.txt> for details.
+
+config HUGETLBFS
+	bool "HugeTLB file system support"
+	depends on HUGETLB_PAGE
+
+config RAMFS
+	bool
+	default y
+	---help---
+	  Ramfs is a file system which keeps all files in RAM. It allows
+	  read and write access.
+
+	  It is more of an programming example than a useable file system.  If
+	  you need a file system which lives in RAM with limit checking use
+	  tmpfs.
 
 	  If you want to compile this as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called vfat.
+	  will be called ramfs.
+
+endmenu
+
+menu "Miscellaneous filesystems"
+
+config ADFS_FS
+	tristate "ADFS file system support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  The Acorn Disc Filing System is the standard file system of the
+	  RiscOS operating system which runs on Acorn's ARM-based Risc PC
+	  systems and the Acorn Archimedes range of machines. If you say Y
+	  here, Linux will be able to read from ADFS partitions on hard drives
+	  and from ADFS-formatted floppy discs. If you also want to be able to
+	  write to those devices, say Y to "ADFS write support" below.
+
+	  The ADFS partition should be the first partition (i.e.,
+	  /dev/[hs]d?1) on each of your drives. Please read the file
+	  <file:Documentation/filesystems/adfs.txt> for further details.
+
+	  This code is also available as a module called adfs ( = code which
+	  can be inserted in and removed from the running kernel whenever you
+	  want). If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.
+
+	  If unsure, say N.
+
+config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	help
+	  If you say Y here, you will be able to write to ADFS partitions on
+	  hard drives and ADFS-formatted floppy disks. This is experimental
+	  codes, so if you're unsure, say N.
+
+config AFFS_FS
+	tristate "Amiga FFS file system support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  The Fast File System (FFS) is the common file system used on hard
+	  disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20).  Say Y
+	  if you want to be able to read and write files from and to an Amiga
+	  FFS partition on your hard drive.  Amiga floppies however cannot be
+	  read with this driver due to an incompatibility of the floppy
+	  controller used in an Amiga and the standard floppy controller in
+	  PCs and workstations. Read <file:Documentation/filesystems/affs.txt>
+	  and <file:fs/affs/Changes>.
+
+	  With this driver you can also mount disk files used by Bernd
+	  Schmidt's Un*X Amiga Emulator
+	  (<http://www.freiburg.linux.de/~uae/>).
+	  If you want to do this, you will also need to say Y or M to "Loop
+	  device support", above.
+
+	  This file system is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module is called affs.  If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.  If unsure,
+	  say N.
+
+config HFS_FS
+	tristate "Apple Macintosh file system support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  If you say Y here, you will be able to mount Macintosh-formatted
+	  floppy disks and hard drive partitions with full read-write access.
+	  Please read <file:fs/hfs/HFS.txt> to learn about the available mount
+	  options.
+
+	  This file system support is also available as a module ( = code
+	  which can be inserted in and removed from the running kernel
+	  whenever you want). The module is called hfs.  If you want to
+	  compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.
+
+config BEFS_FS
+	tristate "BeOS file systemv(BeFS) support (read only) (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  The BeOS File System (BeFS) is the native file system of Be, Inc's
+	  BeOS. Notable features include support for arbitrary attributes
+	  on files and directories, and database-like indices on selected
+	  attributes. (Also note that this driver doesn't make those features
+	  available at this time). It is a 64 bit filesystem, so it supports
+	  extreemly large volumes and files.
+
+	  If you use this filesystem, you should also say Y to at least one
+	  of the NLS (native language support) options below.
+
+	  If you don't know what this is about, say N.
+
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read Documentation/modules.txt. The module will be
+	  called befs.
+
+config BEFS_DEBUG
+	bool "Debug BeFS"
+	depends on BEFS_FS
+	help
+	  If you say Y here, you can use the 'debug' mount option to enable
+	  debugging output from the driver. 
+
+config BFS_FS
+	tristate "BFS file system support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  Boot File System (BFS) is a file system used under SCO UnixWare to
+	  allow the bootloader access to the kernel image and other important
+	  files during the boot process.  It is usually mounted under /stand
+	  and corresponds to the slice marked as "STAND" in the UnixWare
+	  partition.  You should say Y if you want to read or write the files
+	  on your /stand slice from within Linux.  You then also need to say Y
+	  to "UnixWare slices support", below.  More information about the BFS
+	  file system is contained in the file
+	  <file:Documentation/filesystems/bfs.txt>.
+
+	  If you don't know what this is about, say N.
+
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>.  The module
+	  will be called bfs.  Note that the file system of your root
+	  partition (the one containing the directory /) cannot be compiled as
+	  a module.
+
+
 
 config EFS_FS
 	tristate "EFS file system support (read only) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-	---help---
+	help
 	  EFS is an older file system used for non-ISO9660 CD-ROMs and hard
 	  disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
 	  uses the XFS file system for hard disk partitions however).
@@ -538,7 +1018,7 @@
 	int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)"
 	depends on JFFS2_FS
 	default "0"
-	---help---
+	help
 	  This controls the amount of debugging messages produced by the JFFS2
 	  code. Set it to zero for use in production systems. For evaluation,
 	  testing and debugging, it's advisable to set it to one. This will
@@ -555,7 +1035,7 @@
 	bool "JFFS2 support for NAND flash (EXPERIMENTAL)"
 	depends on JFFS2_FS && EXPERIMENTAL
 	default n
-	---help---
+	help
 	  This enables the experimental support for NAND flash in JFFS2. NAND
 	  is a newer type of flash chip design than the traditional NOR flash,
 	  with higher density but a handful of characteristics which make it
@@ -570,7 +1050,7 @@
 
 config CRAMFS
 	tristate "Compressed ROM file system support"
-	---help---
+	help
 	  Saying Y here includes support for CramFs (Compressed ROM File
 	  System).  CramFs is designed to be a simple, small, and compressed
 	  file system for ROM based embedded systems.  CramFs is read-only,
@@ -588,136 +1068,9 @@
 
 	  If unsure, say N.
 
-config TMPFS
-	bool "Virtual memory file system support (former shm fs)"
-	help
-	  Tmpfs is a file system which keeps all files in virtual memory.
-
-	  Everything in tmpfs is temporary in the sense that no files will be
-	  created on your hard drive. The files live in memory and swap
-	  space. If you unmount a tmpfs instance, everything stored therein is
-	  lost.
-
-	  See <file:Documentation/filesystems/tmpfs.txt> for details.
-
-config RAMFS
-	bool
-	default y
-	---help---
-	  Ramfs is a file system which keeps all files in RAM. It allows
-	  read and write access.
-
-	  It is more of an programming example than a useable file system.  If
-	  you need a file system which lives in RAM with limit checking use
-	  tmpfs.
-
-	  If you want to compile this as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called ramfs.
-
-config HUGETLBFS
-	bool "HugeTLB file system support"
-	depends on HUGETLB_PAGE
-
-config ISO9660_FS
-	tristate "ISO 9660 CDROM file system support"
-	---help---
-	  This is the standard file system used on CD-ROMs.  It was previously
-	  known as "High Sierra File System" and is called "hsfs" on other
-	  Unix systems.  The so-called Rock-Ridge extensions which allow for
-	  long Unix filenames and symbolic links are also supported by this
-	  driver.  If you have a CD-ROM drive and want to do more with it than
-	  just listen to audio CDs and watch its LEDs, say Y (and read
-	  <file:Documentation/filesystems/isofs.txt> and the CD-ROM-HOWTO,
-	  available from <http://www.linuxdoc.org/docs.html#howto>), thereby
-	  enlarging your kernel by about 27 KB; otherwise say N.
-
-	  If you want to compile this as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called isofs.
-
-config JOLIET
-	bool "Microsoft Joliet CDROM extensions"
-	depends on ISO9660_FS
-	help
-	  Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system
-	  which allows for long filenames in unicode format (unicode is the
-	  new 16 bit character code, successor to ASCII, which encodes the
-	  characters of almost all languages of the world; see
-	  <http://www.unicode.org/> for more information).  Say Y here if you
-	  want to be able to read Joliet CD-ROMs under Linux.
-
-config ZISOFS
-	bool "Transparent decompression extension"
-	depends on ISO9660_FS
-	help
-	  This is a Linux-specific extension to RockRidge which lets you store
-	  data in compressed form on a CD-ROM and have it transparently
-	  decompressed when the CD-ROM is accessed.  See
-	  <http://www.kernel.org/pub/linux/utils/fs/zisofs/> for the tools
-	  necessary to create such a filesystem.  Say Y here if you want to be
-	  able to read such compressed CD-ROMs.
-
-config JFS_FS
-	tristate "JFS filesystem support"
-	help
-	  This is a port of IBM's Journaled Filesystem .  More information is
-	  available in the file Documentation/filesystems/jfs.txt.
-
-	  If you do not intend to use the JFS filesystem, say N.
-
-config JFS_POSIX_ACL
-	bool "JFS POSIX Access Control Lists"
-	depends on JFS_FS
-	---help---
-	  Posix Access Control Lists (ACLs) support permissions for users and
-	  groups beyond the owner/group/world scheme.
-
-	  To learn more about Access Control Lists, visit the Posix ACLs for
-	  Linux website <http://acl.bestbits.at/>.
-
-	  If you don't know what Access Control Lists are, say N
-
-config JFS_DEBUG
-	bool "JFS debugging"
-	depends on JFS_FS
-	help
-	  If you are experiencing any problems with the JFS filesystem, say
-	  Y here.  This will result in additional debugging messages to be
-	  written to the system log.  Under normal circumstances, this
-	  results in very little overhead.
-
-config JFS_STATISTICS
-	bool "JFS statistics"
-	depends on JFS_FS
-	help
-	  Enabling this option will cause statistics from the JFS file system
-	  to be made available to the user in the /proc/fs/jfs/ directory.
-
-config MINIX_FS
-	tristate "Minix fs support"
-	---help---
-	  Minix is a simple operating system used in many classes about OS's.
-	  The minix file system (method to organize files on a hard disk
-	  partition or a floppy disk) was the original file system for Linux,
-	  but has been superseded by the second extended file system ext2fs.
-	  You don't want to use the minix file system on your hard disk
-	  because of certain built-in restrictions, but it is sometimes found
-	  on older Linux floppy disks.  This option will enlarge your kernel
-	  by about 28 KB. If unsure, say N.
-
-	  If you want to compile this as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>. The module
-	  will be called minix.  Note that the file system of your root
-	  partition (the one containing the directory /) cannot be compiled as
-	  a module.
-
 config VXFS_FS
 	tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
-	---help---
+	help
 	  FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
 	  file system format.  VERITAS VxFS(TM) is the standard file system
 	  of SCO UnixWare (and possibly others) and optionally available
@@ -734,58 +1087,10 @@
 	  module, say M here and read <file:Documentation/modules.txt>.  If
 	  unsure, say N.
 
-config NTFS_FS
-	tristate "NTFS file system support (read only)"
-	---help---
-	  NTFS is the file system of Microsoft Windows NT/2000/XP. For more
-	  information see <file:Documentation/filesystems/ntfs.txt>. Saying Y
-	  here would allow you to read from NTFS partitions.
-
-	  This file system 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 ntfs. If you want to compile it as a
-	  module, say M here and read <file:Documentation/modules.txt>.
-
-	  If you are not using Windows NT/2000/XP in addition to Linux on your
-	  computer it is safe to say N.
-
-config NTFS_DEBUG
-	bool "NTFS debugging support"
-	depends on NTFS_FS
-	---help---
-	  If you are experiencing any problems with the NTFS file system, say
-	  Y here. This will result in additional consistency checks to be
-	  performed by the driver as well as additional debugging messages to
-	  be written to the system log. Note that debugging messages are
-	  disabled by default. To enable them, supply the option debug_msgs=1
-	  at the kernel command line when booting the kernel or as an option
-	  to insmod when loading the ntfs module. Once the driver is active,
-	  you can enable debugging messages by doing (as root):
-	  echo 1 > /proc/sys/fs/ntfs-debug
-	  Replacing the "1" with "0" would disable debug messages.
-
-	  If you leave debugging messages disabled, this results in little
-	  overhead, but enabling debug messages results in very significant
-	  slowdown of the system.
-
-	  When reporting bugs, please try to have available a full dump of
-	  debugging messages while the misbehaviour was occurring.
-
-config NTFS_RW
-	bool "NTFS write support (DANGEROUS)"
-	depends on NTFS_FS && EXPERIMENTAL
-	help
-	  This enables the experimental write support in the NTFS driver.
-
-	  WARNING: Do not use this option unless you are actively developing
-	  NTFS as it is currently guaranteed to be broken and you
-	  may lose all your data!
-
-	  It is strongly recommended and perfectly safe to say N here.
 
 config HPFS_FS
 	tristate "OS/2 HPFS file system support"
-	---help---
+	help
 	  OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
 	  is the file system used for organizing files on OS/2 hard disk
 	  partitions. Say Y if you want to be able to read files from and
@@ -800,104 +1105,11 @@
 	  say M here and read <file:Documentation/modules.txt>.  If unsure,
 	  say N.
 
-config PROC_FS
-	bool "/proc file system support"
-	---help---
-	  This is a virtual file system providing information about the status
-	  of the system. "Virtual" means that it doesn't take up any space on
-	  your hard disk: the files are created on the fly by the kernel when
-	  you try to access them. Also, you cannot read the files with older
-	  version of the program less: you need to use more or cat.
-
-	  It's totally cool; for example, "cat /proc/interrupts" gives
-	  information about what the different IRQs are used for at the moment
-	  (there is a small number of Interrupt ReQuest lines in your computer
-	  that are used by the attached devices to gain the CPU's attention --
-	  often a source of trouble if two devices are mistakenly configured
-	  to use the same IRQ). The program procinfo to display some
-	  information about your system gathered from the /proc file system.
-
-	  Before you can use the /proc file system, it has to be mounted,
-	  meaning it has to be given a location in the directory hierarchy.
-	  That location should be /proc. A command such as "mount -t proc proc
-	  /proc" or the equivalent line in /etc/fstab does the job.
-
-	  The /proc file system is explained in the file
-	  <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage
-	  ("man 5 proc").
-
-	  This option will enlarge your kernel by about 67 KB. Several
-	  programs depend on this, so everyone should say Y here.
-
-config DEVFS_FS
-	bool "/dev file system support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  This is support for devfs, a virtual file system (like /proc) which
-	  provides the file system interface to device drivers, normally found
-	  in /dev. Devfs does not depend on major and minor number
-	  allocations. Device drivers register entries in /dev which then
-	  appear automatically, which means that the system administrator does
-	  not have to create character and block special device files in the
-	  /dev directory using the mknod command (or MAKEDEV script) anymore.
-
-	  This is work in progress. If you want to use this, you *must* read
-	  the material in <file:Documentation/filesystems/devfs/>, especially
-	  the file README there.
-
-	  If unsure, say N.
-
-config DEVFS_MOUNT
-	bool "Automatically mount at boot"
-	depends on DEVFS_FS
-	help
-	  This option appears if you have CONFIG_DEVFS_FS enabled. Setting
-	  this to 'Y' will make the kernel automatically mount devfs onto /dev
-	  when the system is booted, before the init thread is started.
-	  You can override this with the "devfs=nomount" boot option.
-
-	  If unsure, say N.
-
-config DEVFS_DEBUG
-	bool "Debug devfs"
-	depends on DEVFS_FS
-	help
-	  If you say Y here, then the /dev file system code will generate
-	  debugging messages. See the file
-	  <file:Documentation/filesystems/devfs/boot-options> for more
-	  details.
-
-	  If unsure, say N.
-
-# It compiles as a module for testing only.  It should not be used
-# as a module in general.  If we make this "tristate", a bunch of people
-# who don't know what they are doing turn it on and complain when it
-# breaks.
-config DEVPTS_FS
-	bool "/dev/pts file system for Unix98 PTYs"
-	depends on UNIX98_PTYS
-	---help---
-	  You should say Y here if you said Y to "Unix98 PTY support" above.
-	  You'll then get a virtual file system which can be mounted on
-	  /dev/pts with "mount -t devpts". This, together with the pseudo
-	  terminal master multiplexer /dev/ptmx, is used for pseudo terminal
-	  support as described in The Open Group's Unix98 standard: in order
-	  to acquire a pseudo terminal, a process opens /dev/ptmx; the number
-	  of the pseudo terminal is then made available to the process and the
-	  pseudo terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  The GNU C library glibc 2.1 contains the requisite support for this
-	  mode of operation; you also need client programs that use the Unix98
-	  API. Please read <file:Documentation/Changes> for more information
-	  about the Unix98 pty devices.
 
-	  Note that the experimental "/dev file system support"
-	  (CONFIG_DEVFS_FS)  is a more general facility.
 
 config QNX4FS_FS
 	tristate "QNX4 file system support (read only)"
-	---help---
+	help
 	  This is the file system used by the real-time operating systems
 	  QNX 4 and QNX 6 (the latter is also called QNX RTP).
 	  Further information is available at <http://www.qnx.com/>.
@@ -923,97 +1135,11 @@
 	  It's currently broken, so for now:
 	  answer N.
 
-config ROMFS_FS
-	tristate "ROM file system support"
-	---help---
-	  This is a very small read-only file system mainly intended for
-	  initial ram disks of installation disks, but it could be used for
-	  other read-only media as well.  Read
-	  <file:Documentation/filesystems/romfs.txt> for details.
 
-	  This file system support is also available as a module ( = code
-	  which can be inserted in and removed from the running kernel
-	  whenever you want). The module is called romfs.  If you want to
-	  compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.  Note that the file system of your
-	  root partition (the one containing the directory /) cannot be a
-	  module.
-
-	  If you don't know whether you need it, then you don't need it:
-	  answer N.
-
-config EXT2_FS
-	tristate "Second extended fs support"
-	---help---
-	  This is the de facto standard Linux file system (method to organize
-	  files on a storage device) for hard disks.
-
-	  You want to say Y here, unless you intend to use Linux exclusively
-	  from inside a DOS partition using the UMSDOS file system. The
-	  advantage of the latter is that you can get away without
-	  repartitioning your hard drive (which often implies backing
-	  everything up and restoring afterwards); the disadvantage is that
-	  Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat
-	  slower than ext2fs. Even if you want to run Linux in this fashion,
-	  it might be a good idea to have ext2fs around: it enables you to
-	  read more floppy disks and facilitates the transition to a *real*
-	  Linux partition later. Another (rare) case which doesn't require
-	  ext2fs is a diskless Linux box which mounts all files over the
-	  network using NFS (in this case it's sufficient to say Y to "NFS
-	  file system support" below). Saying Y here will enlarge your kernel
-	  by about 44 KB.
-
-	  The Ext2fs-Undeletion mini-HOWTO, available from
-	  <http://www.linuxdoc.org/docs.html#howto>, gives information about
-	  how to retrieve deleted files on ext2fs file systems.
-
-	  To change the behavior of ext2 file systems, you can use the tune2fs
-	  utility ("man tune2fs"). To modify attributes of files and
-	  directories on ext2 file systems, use chattr ("man chattr").
-
-	  Ext2fs partitions can be read from within DOS using the ext2tool
-	  command line tool package (available from
-	  <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from
-	  within Windows NT using the ext2nt command line tool package from
-	  <ftp://ibiblio.org/pub/Linux/utils/dos/>.  Explore2fs is a
-	  graphical explorer for ext2fs partitions which runs on Windows 95
-	  and Windows NT and includes experimental write support; it is
-	  available from
-	  <http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm>.
-
-	  If you want to compile this file system as a module ( = code which
-	  can be inserted in and removed from the running kernel whenever you
-	  want), say M here and read <file:Documentation/modules.txt>.  The
-	  module will be called ext2.  Be aware however that the file system
-	  of your root partition (the one containing the directory /) cannot
-	  be compiled as a module, and so this could be dangerous.  Most
-	  everyone wants to say Y here.
-
-config EXT2_FS_XATTR
-	bool "Ext2 extended attributes"
-	depends on EXT2_FS
-	---help---
-	  Extended attributes are name:value pairs associated with inodes by
-	  the kernel or by users (see the attr(5) manual page, or visit
-	  <http://acl.bestbits.at/> for details).
-
-	  If unsure, say N.
-
-config EXT2_FS_POSIX_ACL
-	bool "Ext2 POSIX Access Control Lists"
-	depends on EXT2_FS_XATTR
-	---help---
-	  Posix Access Control Lists (ACLs) support permissions for users and
-	  groups beyond the owner/group/world scheme.
-
-	  To learn more about Access Control Lists, visit the Posix ACLs for
-	  Linux website <http://acl.bestbits.at/>.
-
-	  If you don't know what Access Control Lists are, say N
 
 config SYSV_FS
 	tristate "System V/Xenix/V7/Coherent file system support"
-	---help---
+	help
 	  SCO, Xenix and Coherent are commercial Unix systems for Intel
 	  machines, and Version 7 was used on the DEC PDP-11. Saying Y
 	  here would allow you to read from their floppies and hard disk
@@ -1049,25 +1175,11 @@
 
 	  If you haven't heard about all of this before, it's safe to say N.
 
-config UDF_FS
-	tristate "UDF file system support"
-	---help---
-	  This is the new file system used on some CD-ROMs and DVDs. Say Y if
-	  you intend to mount DVD discs or CDRW's written in packet mode, or
-	  if written to by other UDF utilities, such as DirectCD.
-	  Please read <file:Documentation/filesystems/udf.txt>.
 
-	  This file system support is also available as a module ( = code
-	  which can be inserted in and removed from the running kernel
-	  whenever you want). The module is called udf. If you want to
-	  compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.
-
-	  If unsure, say N.
 
 config UFS_FS
 	tristate "UFS file system support (read only)"
-	---help---
+	help
 	  BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
 	  OpenBSD and NeXTstep) use a file system called UFS. Some System V
 	  Unixes can create and mount hard disk partitions and diskettes using
@@ -1103,118 +1215,15 @@
 	  Say Y here if you want to try writing to UFS partitions. This is
 	  experimental, so you should back up your UFS partitions beforehand.
 
-config XFS_FS
-	tristate "XFS filesystem support"
-	---help---
-	  XFS is a high performance journaling filesystem which originated
-	  on the SGI IRIX platform.  It is completely multi-threaded, can
-	  support large files and large filesystems, extended attributes,
-	  variable block sizes, is extent based, and makes extensive use of
-	  Btrees (directories, extents, free space) to aid both performance
-	  and scalability.
-
-	  Refer to the documentation at <http://oss.sgi.com/projects/xfs/>
-	  for complete details.  This implementation is on-disk compatible
-	  with the IRIX version of XFS.
-
-	  If you want to compile this file system as a module ( = code which
-	  can be inserted in and removed from the running kernel whenever you
-	  want), say M here and read <file:Documentation/modules.txt>. The
-	  module will be called xfs.  Be aware, however, that if the file
-	  system of your root partition is compiled as a module, you'll need
-	  to use an initial ramdisk (initrd) to boot.
-
-config XFS_RT
-	bool "Realtime support (EXPERIMENTAL)"
-	depends on XFS_FS && EXPERIMENTAL
-	---help---
-	  If you say Y here you will be able to mount and use XFS filesystems
-	  which contain a realtime subvolume. The realtime subvolume is a
-	  separate area of disk space where only file data is stored. The
-	  realtime subvolume is designed to provide very deterministic
-	  data rates suitable for media streaming applications.
-
-	  See the xfs man page in section 5 for a bit more information.
-
-	  This feature is unsupported at this time, is not yet fully
-	  functional, and may cause serious problems.
-
-	  If unsure, say N.
-
-config XFS_QUOTA
-	bool "Quota support"
-	depends on XFS_FS
-	---help---
-	  If you say Y here, you will be able to set limits for disk usage on
-	  a per user and/or a per group basis under XFS.  XFS considers quota
-	  information as filesystem metadata and uses journaling to provide a
-	  higher level guarantee of consistency.  The on-disk data format for
-	  quota is also compatible with the IRIX version of XFS, allowing a
-	  filesystem to be migrated between Linux and IRIX without any need
-	  for conversion.
-
-	  If unsure, say N.  More comprehensive documentation can be found in
-	  README.quota in the xfsprogs package.  XFS quota can be used either
-	  with or without the generic quota support enabled (CONFIG_QUOTA) -
-	  they are completely independent subsystems.
-
-config XFS_POSIX_ACL
-	bool "ACL support"
-	depends on XFS_FS
-	---help---
-	  Posix Access Control Lists (ACLs) support permissions for users and
-	  groups beyond the owner/group/world scheme.
-
-	  To learn more about Access Control Lists, visit the Posix ACLs for
-	  Linux website <http://acl.bestbits.at/>.
-
-	  If you don't know what Access Control Lists are, say N
-
+endmenu
 
 menu "Network File Systems"
 	depends on NET
 
-config CODA_FS
-	tristate "Coda file system support (advanced network fs)"
-	depends on INET
-	---help---
-	  Coda is an advanced network file system, similar to NFS in that it
-	  enables you to mount file systems of a remote server and access them
-	  with regular Unix commands as if they were sitting on your hard
-	  disk.  Coda has several advantages over NFS: support for
-	  disconnected operation (e.g. for laptops), read/write server
-	  replication, security model for authentication and encryption,
-	  persistent client caches and write back caching.
-
-	  If you say Y here, your Linux box will be able to act as a Coda
-	  *client*.  You will need user level code as well, both for the
-	  client and server.  Servers are currently user level, i.e. they need
-	  no kernel support.  Please read
-	  <file:Documentation/filesystems/coda.txt> and check out the Coda
-	  home page <http://www.coda.cs.cmu.edu/>.
-
-	  If you want to compile the coda client support as a module ( = code
-	  which can be inserted in and removed from the running kernel
-	  whenever you want), say M here and read
-	  <file:Documentation/modules.txt>.  The module will be called coda.
-
-config INTERMEZZO_FS
-	tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
-	help
-	  InterMezzo is a networked file system with disconnected operation
-	  and kernel level write back caching.  It is most often used for
-	  replicating potentially large trees or keeping laptop/desktop copies
-	  in sync.
-
-	  If you say Y or M your kernel or module will provide InterMezzo
-	  support.  You will also need a file server daemon, which you can get
-	  from <http://www.inter-mezzo.org/>.
-
 config NFS_FS
 	tristate "NFS file system support"
 	depends on INET
-	---help---
+	help
 	  If you are connected to some other (usually local) Unix computer
 	  (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
 	  on that computer (the NFS server) using the Network File Sharing
@@ -1268,24 +1277,10 @@
 
 	  If unsure, say N.
 
-config ROOT_NFS
-	bool "Root file system on NFS"
-	depends on NFS_FS=y && IP_PNP
-	help
-	  If you want your Linux box to mount its whole root file system (the
-	  one containing the directory /) from some other computer over the
-	  net via NFS (presumably because your box doesn't have a hard disk),
-	  say Y. Read <file:Documentation/nfsroot.txt> for details. It is
-	  likely that in this case, you also want to say Y to "Kernel level IP
-	  autoconfiguration" so that your box can discover its network address
-	  at boot time.
-
-	  Most people say N here.
-
 config NFSD
 	tristate "NFS server support"
 	depends on INET
-	---help---
+	help
 	  If you want your Linux box to act as an NFS *server*, so that other
 	  computers on your local network which support NFS can access certain
 	  directories on your box transparently, you have two options: you can
@@ -1334,34 +1329,19 @@
 	  Enable NFS service over TCP connections.  This the officially
 	  still experimental, but seems to work well.
 
-config SUNRPC
-	tristate
-	default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m)
-	default y if NFS_FS=y || NFSD=y
-
-config SUNRPC_GSS
-	tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)"
-	depends on SUNRPC && EXPERIMENTAL
-	default SUNRPC if NFS_V4=y
-	help
-	  Provides cryptographic authentication for NFS rpc requests.  To
-	  make this useful, you must also select at least one rpcsec_gss
-	  mechanism.
-	  Note: You should always select this option if you wish to use
-	  NFSv4.
-
-config RPCSEC_GSS_KRB5
-	tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)"
-	depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5
-	default SUNRPC_GSS if NFS_V4=y
+config ROOT_NFS
+	bool "Root file system on NFS"
+	depends on NFS_FS=y && IP_PNP
 	help
-	  Provides a gss-api mechanism based on Kerberos V5 (this is
-	  mandatory for RFC3010-compliant NFSv4 implementations).
-	  Requires a userspace daemon;
-		see http://www.citi.umich.edu/projects/nfsv4/.
+	  If you want your Linux box to mount its whole root file system (the
+	  one containing the directory /) from some other computer over the
+	  net via NFS (presumably because your box doesn't have a hard disk),
+	  say Y. Read <file:Documentation/nfsroot.txt> for details. It is
+	  likely that in this case, you also want to say Y to "Kernel level IP
+	  autoconfiguration" so that your box can discover its network address
+	  at boot time.
 
-	  Note: If you select this option, please ensure that you also
-	  enable the MD5 and DES crypto ciphers.
+	  Most people say N here.
 
 config LOCKD
 	tristate
@@ -1377,32 +1357,10 @@
 	tristate
 	default NFSD
 
-config CIFS
-	tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)"
-	depends on INET
-	---help---
-	  This is the client VFS module for the Common Internet File System
-	  (CIFS) protocol which is the successor to the Server Message Block 
-	  (SMB) protocol, the native file sharing mechanism for most early
-	  PC operating systems.  CIFS is fully supported by current network
-	  file servers such as Windows 2000 (including Windows NT version 4 
-	  and Windows XP) as well by Samba (which provides excellent CIFS
-	  server support for Linux and many other operating systems).  For
-	  production systems the smbfs module may be used instead of this
-	  cifs module since smbfs is currently more stable and provides
-	  support for older servers.  The intent of this module is to provide the
-	  most advanced network file system function for CIFS compliant servers, 
-	  including support for dfs (heirarchical name space), secure per-user
-	  session establishment, safe distributed caching (oplock), optional
-	  packet signing, Unicode and other internationalization improvements, and
-	  optional Winbind (nsswitch) integration.  This module is in an early
-	  development stage, so unless you are specifically interested in this
-	  filesystem, just say N.
-
 config SMB_FS
 	tristate "SMB file system support (to mount Windows shares etc.)"
 	depends on INET
-	---help---
+	help
 	  SMB (Server Message Block) is the protocol Windows for Workgroups
 	  (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share
 	  files and printers over local networks.  Saying Y here allows you to
@@ -1456,10 +1414,32 @@
 
 	  smbmount from samba 2.2.0 or later supports this.
 
+config CIFS
+	tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)"
+	depends on INET
+	help
+	  This is the client VFS module for the Common Internet File System
+	  (CIFS) protocol which is the successor to the Server Message Block 
+	  (SMB) protocol, the native file sharing mechanism for most early
+	  PC operating systems.  CIFS is fully supported by current network
+	  file servers such as Windows 2000 (including Windows NT version 4 
+	  and Windows XP) as well by Samba (which provides excellent CIFS
+	  server support for Linux and many other operating systems).  For
+	  production systems the smbfs module may be used instead of this
+	  cifs module since smbfs is currently more stable and provides
+	  support for older servers.  The intent of this module is to provide the
+	  most advanced network file system function for CIFS compliant servers, 
+	  including support for dfs (heirarchical name space), secure per-user
+	  session establishment, safe distributed caching (oplock), optional
+	  packet signing, Unicode and other internationalization improvements, and
+	  optional Winbind (nsswitch) integration.  This module is in an early
+	  development stage, so unless you are specifically interested in this
+	  filesystem, just say N.
+
 config NCP_FS
 	tristate "NCP file system support (to mount NetWare volumes)"
 	depends on IPX!=n || INET
-	---help---
+	help
 	  NCP (NetWare Core Protocol) is a protocol that runs over IPX and is
 	  used by Novell NetWare clients to talk to file servers.  It is to
 	  IPX what NFS is to TCP/IP, if that helps.  Saying Y here allows you
@@ -1480,10 +1460,76 @@
 	  will be called ncpfs.  Say N unless you are connected to a Novell
 	  network.
 
+config CODA_FS
+	tristate "Coda file system support (advanced network fs)"
+	depends on INET
+	help
+	  Coda is an advanced network file system, similar to NFS in that it
+	  enables you to mount file systems of a remote server and access them
+	  with regular Unix commands as if they were sitting on your hard
+	  disk.  Coda has several advantages over NFS: support for
+	  disconnected operation (e.g. for laptops), read/write server
+	  replication, security model for authentication and encryption,
+	  persistent client caches and write back caching.
+
+	  If you say Y here, your Linux box will be able to act as a Coda
+	  *client*.  You will need user level code as well, both for the
+	  client and server.  Servers are currently user level, i.e. they need
+	  no kernel support.  Please read
+	  <file:Documentation/filesystems/coda.txt> and check out the Coda
+	  home page <http://www.coda.cs.cmu.edu/>.
+
+	  If you want to compile the coda client support as a module ( = code
+	  which can be inserted in and removed from the running kernel
+	  whenever you want), say M here and read
+	  <file:Documentation/modules.txt>.  The module will be called coda.
+
+config INTERMEZZO_FS
+	tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)"
+	depends on INET && EXPERIMENTAL
+	help
+	  InterMezzo is a networked file system with disconnected operation
+	  and kernel level write back caching.  It is most often used for
+	  replicating potentially large trees or keeping laptop/desktop copies
+	  in sync.
+
+	  If you say Y or M your kernel or module will provide InterMezzo
+	  support.  You will also need a file server daemon, which you can get
+	  from <http://www.inter-mezzo.org/>.
+
+config SUNRPC
+	tristate
+	default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m)
+	default y if NFS_FS=y || NFSD=y
+
+config SUNRPC_GSS
+	tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)"
+	depends on SUNRPC && EXPERIMENTAL
+	default SUNRPC if NFS_V4=y
+	help
+	  Provides cryptographic authentication for NFS rpc requests.  To
+	  make this useful, you must also select at least one rpcsec_gss
+	  mechanism.
+	  Note: You should always select this option if you wish to use
+	  NFSv4.
+
+config RPCSEC_GSS_KRB5
+	tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)"
+	depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5
+	default SUNRPC_GSS if NFS_V4=y
+	help
+	  Provides a gss-api mechanism based on Kerberos V5 (this is
+	  mandatory for RFC3010-compliant NFSv4 implementations).
+	  Requires a userspace daemon;
+		see http://www.citi.umich.edu/projects/nfsv4/.
+
+	  Note: If you select this option, please ensure that you also
+	  enable the MD5 and DES crypto ciphers.
+
 source "fs/ncpfs/Kconfig"
 
-# for fs/nls/Config.in
 config AFS_FS
+# for fs/nls/Config.in
 	tristate "Andrew File System support (AFS) (Experimental)"
 	depends on INET && EXPERIMENTAL
 	help
@@ -1500,29 +1546,6 @@
 	default y if AFS_FS=y
 
 endmenu
-
-# for fs/nls/Config.in
-config ZISOFS_FS
-	tristate
-	depends on ZISOFS
-	default ISO9660_FS
-
-# Meta block cache for Extended Attributes (ext2/ext3)
-config FS_MBCACHE
-	tristate
-	depends on EXT2_FS_XATTR || EXT3_FS_XATTR
-	default y if EXT2_FS=y || EXT3_FS=y
-	default m if EXT2_FS=m || EXT3_FS=m
-
-# Posix ACL utility routines (for now, only ext2/ext3/jfs)
-#
-# NOTE: you can implement Posix ACLs without these helpers (XFS does).
-# 	Never use this symbol for ifdefs.
-#
-config FS_POSIX_ACL
-	bool
-	depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL
-	default y
 
 menu "Partition Types"
 
diff -Nru a/fs/affs/Changes b/fs/affs/Changes
--- a/fs/affs/Changes	Sun Feb  3 10:33:21 2002
+++ b/fs/affs/Changes	Sun Mar 16 22:33:20 2003
@@ -28,6 +28,11 @@
 
 Please direct bug reports to: zippel@linux-m68k.org
 
+Version 3.20
+------------
+- kill kernel lock
+- fix for a possible bitmap corruption
+
 Version 3.19
 ------------
 
diff -Nru a/fs/affs/bitmap.c b/fs/affs/bitmap.c
--- a/fs/affs/bitmap.c	Thu May 23 06:18:41 2002
+++ b/fs/affs/bitmap.c	Sun Mar 16 22:33:20 2003
@@ -185,6 +185,8 @@
 	/* search for the next bmap buffer with free bits */
 	i = sbi->s_bmap_count;
 	do {
+		if (--i < 0)
+			goto err_full;
 		bmap++;
 		bm++;
 		if (bmap < sbi->s_bmap_count)
@@ -192,8 +194,6 @@
 		/* restart search at zero */
 		bmap = 0;
 		bm = sbi->s_bitmap;
-		if (--i <= 0)
-			goto err_full;
 	} while (!bm->bm_free);
 	blk = bmap * sbi->s_bmap_bits;
 
@@ -216,8 +216,8 @@
 	mask = ~0UL << (bit & 31);
 	blk &= ~31UL;
 
-	tmp = be32_to_cpu(*data) & mask;
-	if (tmp)
+	tmp = be32_to_cpu(*data);
+	if (tmp & mask)
 		goto find_bit;
 
 	/* scan the rest of the buffer */
@@ -230,10 +230,11 @@
 			goto find_bmap;
 	} while (!(tmp = *data));
 	tmp = be32_to_cpu(tmp);
+	mask = ~0;
 
 find_bit:
 	/* finally look for a free bit in the word */
-	bit = ffs(tmp) - 1;
+	bit = ffs(tmp & mask) - 1;
 	blk += bit + sbi->s_reserved;
 	mask2 = mask = 1 << (bit & 31);
 	AFFS_I(inode)->i_lastalloc = blk;
@@ -266,8 +267,8 @@
 	sbi->s_bmap_bh = NULL;
 	sbi->s_last_bmap = ~0;
 err_full:
-	pr_debug("failed\n");
 	up(&sbi->s_bmlock);
+	pr_debug("failed\n");
 	return 0;
 }
 
diff -Nru a/fs/affs/dir.c b/fs/affs/dir.c
--- a/fs/affs/dir.c	Tue Nov  5 07:35:59 2002
+++ b/fs/affs/dir.c	Sun Mar 16 22:33:20 2003
@@ -65,8 +65,6 @@
 	int			 stored;
 	int			 res;
 
-	lock_kernel();
-	
 	pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)filp->f_pos);
 
 	stored = 0;
@@ -162,7 +160,6 @@
 	affs_brelse(dir_bh);
 	affs_brelse(fh_bh);
 	affs_unlock_dir(inode);
-	unlock_kernel();
 	pr_debug("AFFS: readdir()=%d\n", stored);
 	return res;
 }
diff -Nru a/fs/affs/inode.c b/fs/affs/inode.c
--- a/fs/affs/inode.c	Sun Nov 17 11:53:57 2002
+++ b/fs/affs/inode.c	Sun Mar 16 22:33:20 2003
@@ -195,11 +195,9 @@
 	if (!inode->i_nlink)
 		// possibly free block
 		return;
-	lock_kernel();
 	bh = affs_bread(sb, inode->i_ino);
 	if (!bh) {
 		affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
-		unlock_kernel();
 		return;
 	}
 	tail = AFFS_TAIL(sb, bh);
@@ -227,7 +225,7 @@
 	affs_fix_checksum(sb, bh);
 	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
-	unlock_kernel();
+	affs_free_prealloc(inode);
 }
 
 int
@@ -236,8 +234,6 @@
 	struct inode *inode = dentry->d_inode;
 	int error;
 
-	lock_kernel();
-
 	pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
 
 	error = inode_change_ok(inode,attr);
@@ -257,7 +253,6 @@
 	if (!error && (attr->ia_valid & ATTR_MODE))
 		mode_to_prot(inode);
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -265,15 +260,13 @@
 affs_put_inode(struct inode *inode)
 {
 	pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
-	lock_kernel();
 	affs_free_prealloc(inode);
 	if (atomic_read(&inode->i_count) == 1) {
+		down(&inode->i_sem);
 		if (inode->i_size != AFFS_I(inode)->mmu_private)
 			affs_truncate(inode);
-		//if (inode->i_nlink)
-		//	affs_clear_inode(inode);
+		up(&inode->i_sem);
 	}
-	unlock_kernel();
 }
 
 void
@@ -284,9 +277,7 @@
 	if (S_ISREG(inode->i_mode))
 		affs_truncate(inode);
 	clear_inode(inode);
-	lock_kernel();
 	affs_free_block(inode->i_sb, inode->i_ino);
-	unlock_kernel();
 }
 
 void
diff -Nru a/fs/affs/namei.c b/fs/affs/namei.c
--- a/fs/affs/namei.c	Tue Nov  5 07:35:59 2002
+++ b/fs/affs/namei.c	Sun Mar 16 22:33:20 2003
@@ -218,12 +218,10 @@
 
 	pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name);
 
-	lock_kernel();
 	affs_lock_dir(dir);
 	bh = affs_find_entry(dir, dentry);
 	affs_unlock_dir(dir);
 	if (IS_ERR(bh)) {
-		unlock_kernel();
 		return ERR_PTR(PTR_ERR(bh));
 	}
 	if (bh) {
@@ -240,12 +238,10 @@
 		affs_brelse(bh);
 		inode = iget(sb, ino);
 		if (!inode) {
-			unlock_kernel();
 			return ERR_PTR(-EACCES);
 		}
 	}
 	dentry->d_op = AFFS_SB(sb)->s_flags & SF_INTL ? &affs_intl_dentry_operations : &affs_dentry_operations;
-	unlock_kernel();
 	d_add(dentry, inode);
 	return NULL;
 }
@@ -253,17 +249,10 @@
 int
 affs_unlink(struct inode *dir, struct dentry *dentry)
 {
-	int res;
 	pr_debug("AFFS: unlink(dir=%d, \"%.*s\")\n", (u32)dir->i_ino,
 		 (int)dentry->d_name.len, dentry->d_name.name);
 
-	if (!dentry->d_inode)
-		return -ENOENT;
-
-	lock_kernel();
-	res = affs_remove_header(dentry);
-	unlock_kernel();
-	return res;
+	return affs_remove_header(dentry);
 }
 
 int
@@ -276,12 +265,9 @@
 	pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,(int)dentry->d_name.len,
 		 dentry->d_name.name,mode);
 
-	lock_kernel();
 	inode = affs_new_inode(dir);
-	if (!inode) {
-		unlock_kernel();
+	if (!inode)
 		return -ENOSPC;
-	}
 
 	inode->i_mode = mode;
 	mode_to_prot(inode);
@@ -294,10 +280,8 @@
 	if (error) {
 		inode->i_nlink = 0;
 		iput(inode);
-		unlock_kernel();
 		return error;
 	}
-	unlock_kernel();
 	return 0;
 }
 
@@ -310,12 +294,9 @@
 	pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%o)\n",dir->i_ino,
 		 (int)dentry->d_name.len,dentry->d_name.name,mode);
 
-	lock_kernel();
 	inode = affs_new_inode(dir);
-	if (!inode) {
-		unlock_kernel();
+	if (!inode)
 		return -ENOSPC;
-	}
 
 	inode->i_mode = S_IFDIR | mode;
 	mode_to_prot(inode);
@@ -328,10 +309,8 @@
 		inode->i_nlink = 0;
 		mark_inode_dirty(inode);
 		iput(inode);
-		unlock_kernel();
 		return error;
 	}
-	unlock_kernel();
 	return 0;
 }
 
@@ -357,14 +336,10 @@
 	pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino,
 		 (int)dentry->d_name.len,dentry->d_name.name,symname);
 
-	lock_kernel();
 	maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1;
-	error = -ENOSPC;
 	inode  = affs_new_inode(dir);
-	if (!inode) {
-		unlock_kernel();
+	if (!inode)
 		return -ENOSPC;
-	}
 
 	inode->i_op = &affs_symlink_inode_operations;
 	inode->i_data.a_ops = &affs_symlink_aops;
@@ -410,7 +385,6 @@
 	error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK);
 	if (error)
 		goto err;
-	unlock_kernel();
 
 	return 0;
 
@@ -418,7 +392,6 @@
 	inode->i_nlink = 0;
 	mark_inode_dirty(inode);
 	iput(inode);
-	unlock_kernel();
 	return error;
 }
 
@@ -426,23 +399,11 @@
 affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = old_dentry->d_inode;
-	int error;
 
 	pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino,
 		 (int)dentry->d_name.len,dentry->d_name.name);
 
-	lock_kernel();
-	error = affs_add_entry(dir, inode, dentry, ST_LINKFILE);
-	if (error) {
-		/* WTF??? */
-		inode->i_nlink = 0;
-		mark_inode_dirty(inode);
-		iput(inode);
-		unlock_kernel();
-		return error;
-	}
-	unlock_kernel();
-	return 0;
+	return affs_add_entry(dir, inode, dentry, ST_LINKFILE);
 }
 
 int
@@ -453,21 +414,19 @@
 	struct buffer_head *bh = NULL;
 	int retval;
 
-	lock_kernel();
 	pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
 		 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
 		 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
 
-	if ((retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len)))
-		goto done;
+	retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len);
+	if (retval)
+		return retval;
 
 	/* Unlink destination if it already exists */
 	if (new_dentry->d_inode) {
 		retval = affs_remove_header(new_dentry);
-		if (retval) {
-			unlock_kernel();
+		if (retval)
 			return retval;
-		}
 	}
 
 	retval = -EIO;
@@ -493,6 +452,5 @@
 done:
 	mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir);
 	affs_brelse(bh);
-	unlock_kernel();
 	return retval;
 }
diff -Nru a/fs/affs/super.c b/fs/affs/super.c
--- a/fs/affs/super.c	Tue Dec 31 17:32:02 2002
+++ b/fs/affs/super.c	Sun Mar 16 22:33:20 2003
@@ -40,7 +40,6 @@
 affs_put_super(struct super_block *sb)
 {
 	struct affs_sb_info *sbi = AFFS_SB(sb);
-	lock_kernel();
 	pr_debug("AFFS: put_super()\n");
 
 	if (!(sb->s_flags & MS_RDONLY)) {
@@ -58,7 +57,6 @@
 	affs_brelse(sbi->s_root_bh);
 	kfree(sbi);
 	sb->s_fs_info = NULL;
-	unlock_kernel();
 	return;
 }
 
@@ -67,7 +65,7 @@
 {
 	int clean = 2;
 	struct affs_sb_info *sbi = AFFS_SB(sb);
-	lock_kernel();
+
 	if (!(sb->s_flags & MS_RDONLY)) {
 		//	if (sbi->s_bitmap[i].bm_bh) {
 		//		if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) {
@@ -81,7 +79,7 @@
 	} else
 		sb->s_dirt = 0;
 
-	unlock_kernel();
+	pr_debug("AFFS: write_super() at %lu, clean=%d\n", get_seconds(), clean);
 }
 
 static kmem_cache_t * affs_inode_cachep;
diff -Nru a/fs/affs/symlink.c b/fs/affs/symlink.c
--- a/fs/affs/symlink.c	Tue Nov  5 07:35:59 2002
+++ b/fs/affs/symlink.c	Sun Mar 16 22:33:20 2003
@@ -32,9 +32,7 @@
 	pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
 
 	err = -EIO;
-	lock_kernel();
 	bh = affs_bread(inode->i_sb, inode->i_ino);
-	unlock_kernel();
 	if (!bh)
 		goto fail;
 	i  = 0;
@@ -63,9 +61,7 @@
 		j++;
 	}
 	link[i] = '\0';
-	lock_kernel();
 	affs_brelse(bh);
-	unlock_kernel();
 	SetPageUptodate(page);
 	kunmap(page);
 	unlock_page(page);
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	Tue Jan  7 14:52:20 2003
+++ b/fs/aio.c	Fri Mar  7 02:24:44 2003
@@ -76,7 +76,7 @@
 
 	aio_wq = create_workqueue("aio");
 
-	printk(KERN_NOTICE "aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
+	pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
 
 	return 0;
 }
@@ -1193,7 +1193,7 @@
 
 	if (NULL != cancel) {
 		struct io_event tmp;
-		printk("calling cancel\n");
+		pr_debug("calling cancel\n");
 		memset(&tmp, 0, sizeof(tmp));
 		tmp.obj = (u64)(unsigned long)kiocb->ki_user_obj;
 		tmp.data = kiocb->ki_user_data;
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Thu Feb  6 07:33:47 2003
+++ b/fs/binfmt_elf.c	Sat Mar  8 14:50:42 2003
@@ -10,7 +10,7 @@
  */
 
 #include <linux/module.h>
-
+#include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/time.h>
@@ -256,8 +256,8 @@
 
 #ifndef elf_map
 
-static inline unsigned long
-elf_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+static unsigned long elf_map(struct file *filep, unsigned long addr,
+			struct elf_phdr *eppnt, int prot, int type)
 {
 	unsigned long map_addr;
 
@@ -390,7 +390,6 @@
 	unsigned long text_data, elf_entry = ~0UL;
 	char * addr;
 	loff_t offset;
-	int retval;
 
 	current->mm->end_code = interp_ex->a_text;
 	text_data = interp_ex->a_text + interp_ex->a_data;
@@ -412,11 +411,9 @@
 	}
 
 	do_brk(0, text_data);
-	retval = -ENOEXEC;
 	if (!interpreter->f_op || !interpreter->f_op->read)
 		goto out;
-	retval = interpreter->f_op->read(interpreter, addr, text_data, &offset);
-	if (retval < 0)
+	if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
 		goto out;
 	flush_icache_range((unsigned long)addr,
 	                   (unsigned long)addr + text_data);
@@ -638,7 +635,7 @@
 	retval = setup_arg_pages(bprm);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
-		return retval;
+		goto out_free_dentry;
 	}
 	
 	current->mm->start_stack = bprm->p;
@@ -742,7 +739,8 @@
 			printk(KERN_ERR "Unable to load interpreter\n");
 			kfree(elf_phdata);
 			send_sig(SIGSEGV, current, 0);
-			return 0;
+			retval = -ENOEXEC; /* Nobody gets to see this, but.. */
+			goto out;
 		}
 	} else {
 		elf_entry = elf_ex.e_entry;
@@ -934,7 +932,7 @@
  *
  * I think we should skip something. But I am not sure how. H.J.
  */
-static inline int maydump(struct vm_area_struct *vma)
+static int maydump(struct vm_area_struct *vma)
 {
 	/*
 	 * If we may not read the contents, don't allow us to dump
@@ -1046,7 +1044,7 @@
 	return;
 }
 
-static inline void fill_note(struct memelfnote *note, const char *name, int type, 
+static void fill_note(struct memelfnote *note, const char *name, int type, 
 		unsigned int sz, void *data)
 {
 	note->name = name;
@@ -1060,7 +1058,8 @@
  * fill up all the fields in prstatus from the given task struct, except registers
  * which need to be filled up separately.
  */
-static inline void fill_prstatus(struct elf_prstatus *prstatus, struct task_struct *p, long signr) 
+static void fill_prstatus(struct elf_prstatus *prstatus,
+			struct task_struct *p, long signr) 
 {
 	prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
 	prstatus->pr_sigpend = p->pending.signal.sig[0];
@@ -1075,7 +1074,7 @@
 	jiffies_to_timeval(p->cstime, &prstatus->pr_cstime);
 }
 
-static inline void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p)
+static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p)
 {
 	int i, len;
 	
@@ -1175,41 +1174,64 @@
  */
 static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
 {
+#define	NUM_NOTES	5
 	int has_dumped = 0;
 	mm_segment_t fs;
 	int segs;
 	size_t size = 0;
 	int i;
 	struct vm_area_struct *vma;
-	struct elfhdr elf;
+	struct elfhdr *elf = NULL;
 	off_t offset = 0, dataoff;
 	unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur;
-	int numnote = 5;
-	struct memelfnote notes[5];
-	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
-	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
+	int numnote = NUM_NOTES;
+	struct memelfnote *notes = NULL;
+	struct elf_prstatus *prstatus = NULL;	/* NT_PRSTATUS */
+	struct elf_prpsinfo *psinfo = NULL;	/* NT_PRPSINFO */
  	struct task_struct *g, *p;
  	LIST_HEAD(thread_list);
  	struct list_head *t;
-	elf_fpregset_t fpu;
+	elf_fpregset_t *fpu = NULL;
 #ifdef ELF_CORE_COPY_XFPREGS
-	elf_fpxregset_t xfpu;
+	elf_fpxregset_t *xfpu = NULL;
 #endif
 	int thread_status_size = 0;
-	
-	/* We no longer stop all vm operations
+
+	/*
+	 * We no longer stop all VM operations.
 	 * 
-	 * This because those proceses that could possibly 
-	 * change map_count or the mmap / vma pages are now blocked in do_exit on current finishing
+	 * This is because those proceses that could possibly change map_count or
+	 * the mmap / vma pages are now blocked in do_exit on current finishing
 	 * this core dump.
 	 *
 	 * Only ptrace can touch these memory addresses, but it doesn't change
-	 * the map_count or the pages allocated.  So no possibility of crashing exists while dumping
-	 * the mm->vm_next areas to the core file.
-	 *
+	 * the map_count or the pages allocated.  So no possibility of crashing
+	 * exists while dumping the mm->vm_next areas to the core file.
 	 */
-  	
-	 /* capture the status of all other threads */
+  
+	/* alloc memory for large data structures: too large to be on stack */
+	elf = kmalloc(sizeof(*elf), GFP_KERNEL);
+	if (!elf)
+		goto cleanup;
+	prstatus = kmalloc(sizeof(*prstatus), GFP_KERNEL);
+	if (!prstatus)
+		goto cleanup;
+	psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
+	if (!psinfo)
+		goto cleanup;
+	notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), GFP_KERNEL);
+	if (!notes)
+		goto cleanup;
+	fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
+	if (!fpu)
+		goto cleanup;
+#ifdef ELF_CORE_COPY_XFPREGS
+	xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL);
+	if (!xfpu)
+		goto cleanup;
+#endif
+
+	/* capture the status of all other threads */
 	if (signr) {
 		read_lock(&tasklist_lock);
 		do_each_thread(g,p)
@@ -1226,14 +1248,14 @@
 	}
 
 	/* now collect the dump for the current */
-	memset(&prstatus, 0, sizeof(prstatus));
-	fill_prstatus(&prstatus, current, signr);
-	elf_core_copy_regs(&prstatus.pr_reg, regs);
+	memset(prstatus, 0, sizeof(*prstatus));
+	fill_prstatus(prstatus, current, signr);
+	elf_core_copy_regs(&prstatus->pr_reg, regs);
 	
 	segs = current->mm->map_count;
 
 	/* Set up header */
-	fill_elf_header(&elf, segs+1); /* including notes section*/
+	fill_elf_header(elf, segs+1);	/* including notes section */
 
 	has_dumped = 1;
 	current->flags |= PF_DUMPCORE;
@@ -1243,32 +1265,32 @@
 	 * with info from their /proc.
 	 */
 
-	fill_note(&notes[0], "CORE", NT_PRSTATUS, sizeof(prstatus), &prstatus);
+	fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
 	
-	fill_psinfo(&psinfo, current->group_leader);
-	fill_note(&notes[1], "CORE", NT_PRPSINFO, sizeof(psinfo), &psinfo);
+	fill_psinfo(psinfo, current->group_leader);
+	fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
 	
-	fill_note(&notes[2], "CORE", NT_TASKSTRUCT, sizeof(*current), current);
+	fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current);
   
   	/* Try to dump the FPU. */
-	if ((prstatus.pr_fpvalid = elf_core_copy_task_fpregs(current, &fpu)))
-		fill_note(&notes[3], "CORE", NT_PRFPREG, sizeof(fpu), &fpu);
+	if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, fpu)))
+		fill_note(notes +3, "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
 	else
 		--numnote;
 #ifdef ELF_CORE_COPY_XFPREGS
-	if (elf_core_copy_task_xfpregs(current, &xfpu))
-		fill_note(&notes[4], "LINUX", NT_PRXFPREG, sizeof(xfpu), &xfpu);
+	if (elf_core_copy_task_xfpregs(current, xfpu))
+		fill_note(notes +4, "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu);
 	else
 		--numnote;
 #else
-	numnote --;
+	numnote--;
 #endif	
   
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
-	DUMP_WRITE(&elf, sizeof(elf));
-	offset += sizeof(elf);				/* Elf header */
+	DUMP_WRITE(elf, sizeof(*elf));
+	offset += sizeof(*elf);				/* Elf header */
 	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
 
 	/* Write notes phdr entry */
@@ -1276,8 +1298,8 @@
 		struct elf_phdr phdr;
 		int sz = 0;
 
-		for(i = 0; i < numnote; i++)
-			sz += notesize(&notes[i]);
+		for (i = 0; i < numnote; i++)
+			sz += notesize(notes + i);
 		
 		sz += thread_status_size;
 
@@ -1290,7 +1312,7 @@
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
 	/* Write program headers for segments dump */
-	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		struct elf_phdr phdr;
 		size_t sz;
 
@@ -1312,8 +1334,8 @@
 	}
 
  	/* write out the notes section */
-	for(i = 0; i < numnote; i++)
-		if (!writenote(&notes[i], file))
+	for (i = 0; i < numnote; i++)
+		if (!writenote(notes + i, file))
 			goto end_coredump;
 
 	/* write out the thread status notes section */
@@ -1326,7 +1348,7 @@
  
 	DUMP_SEEK(dataoff);
 
-	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		unsigned long addr;
 
 		if (!maydump(vma))
@@ -1373,7 +1395,16 @@
 		kfree(list_entry(tmp, struct elf_thread_status, list));
 	}
 
+	kfree(elf);
+	kfree(prstatus);
+	kfree(psinfo);
+	kfree(notes);
+	kfree(fpu);
+#ifdef ELF_CORE_COPY_XFPREGS
+	kfree(xfpu);
+#endif
 	return has_dumped;
+#undef NUM_NOTES
 }
 
 #endif		/* USE_ELF_CORE_DUMP */
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Wed Jan 15 12:51:33 2003
+++ b/fs/block_dev.c	Sun Mar 16 08:35:51 2003
@@ -436,56 +436,6 @@
 	spin_unlock(&bdev_lock);
 }
 
-static const char *blkdevs[MAX_BLKDEV];
-
-int get_blkdev_list(char * p)
-{
-	int i;
-	int len;
-
-	len = sprintf(p, "\nBlock devices:\n");
-	for (i = 0; i < MAX_BLKDEV ; i++) {
-		if (blkdevs[i])
-			len += sprintf(p+len, "%3d %s\n", i, blkdevs[i]);
-	}
-	return len;
-}
-
-int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
-{
-	if (devfs_only())
-		return 0;
-	if (major == 0) {
-		for (major = MAX_BLKDEV-1; major > 0; major--) {
-			if (blkdevs[major] == NULL) {
-				blkdevs[major] = name;
-				return major;
-			}
-		}
-		return -EBUSY;
-	}
-	if (major >= MAX_BLKDEV)
-		return -EINVAL;
-	if (blkdevs[major])
-		return -EBUSY;
-	blkdevs[major] = name;
-	return 0;
-}
-
-int unregister_blkdev(unsigned int major, const char * name)
-{
-	if (devfs_only())
-		return 0;
-	if (major >= MAX_BLKDEV)
-		return -EINVAL;
-	if (!blkdevs[major])
-		return -EINVAL;
-	if (strcmp(blkdevs[major], name))
-		return -EINVAL;
-	blkdevs[major] = NULL;
-	return 0;
-}
-
 /*
  * This routine checks whether a removable media has been changed,
  * and invalidates all buffer-cache-entries in that case. This
@@ -784,18 +734,6 @@
 	res = blkdev_ioctl(bdev->bd_inode, NULL, cmd, arg);
 	set_fs(old_fs);
 	return res;
-}
-
-const char *__bdevname(dev_t dev)
-{
-	static char buffer[32];
-	const char * name = blkdevs[MAJOR(dev)];
-
-	if (!name)
-		name = "unknown-block";
-
-	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
-	return buffer;
 }
 
 /**
diff -Nru a/fs/char_dev.c b/fs/char_dev.c
--- a/fs/char_dev.c	Thu Feb  6 16:20:33 2003
+++ b/fs/char_dev.c	Mon Mar 10 12:22:35 2003
@@ -191,8 +191,6 @@
 
 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
 {
-	if (devfs_only())
-		return 0;
 	if (major == 0) {
 		write_lock(&chrdevs_lock);
 		for (major = MAX_CHRDEV-1; major > 0; major--) {
@@ -221,8 +219,6 @@
 
 int unregister_chrdev(unsigned int major, const char * name)
 {
-	if (devfs_only())
-		return 0;
 	if (major >= MAX_CHRDEV)
 		return -EINVAL;
 	write_lock(&chrdevs_lock);
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	Sun Feb 23 14:23:53 2003
+++ b/fs/cifs/CHANGES	Fri Mar  7 15:01:07 2003
@@ -1,3 +1,16 @@
+Version 0.70
+------------
+Fix oops in get dfs referral (triggered when null path sent in to
+mount).  Add support for overriding rsize at mount time.
+
+Version 0.69
+------------
+Fix buffer overrun in readdir which caused intermittent kernel oopses.
+Fix writepage code to release kmap on write data.  Allow "-ip=" new 
+mount option to be passed in on parameter distinct from the first part
+(server name portion of) the UNC name.  Allow override of the
+tcp port of the target server via new mount option "-port="  
+
 Version 0.68
 ------------
 Fix search handle leak on rewind.  Fix setuid and gid so that they are 
diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO
--- a/fs/cifs/TODO	Sat Feb 15 14:10:22 2003
+++ b/fs/cifs/TODO	Fri Mar  7 15:01:07 2003
@@ -42,13 +42,24 @@
 
 m) finish support for IPv6
 
-KNOWN BUGS (updated February 15, 2003)
+n) send oplock break response when sent (oplock currently disabled in
+/proc/fs/cifs)
+
+o) remove calls to set end of file by name when we already have file open
+(use the existing handle since some servers only support that and it
+reduces the oplock breaks coming from windows).  Piggyback identical
+file opens on top of each other by incrementing reference count rather
+than resending (helps reduce server resource utilization and avoid
+spurious oplock breaks).
+
+KNOWN BUGS (updated March 7, 2003)
 ====================================
 1) existing symbolic links (Windows reparse points) are recognized but
 can not be created remotely. They are implemented for Samba and those that
 support the CIFS Unix extensions but Samba has a bug currently handling
 symlink text beginning with slash
 2) delete of file with read-only attribute set will fail (may be ok)
+3) mount helper syntax not quite matching man page
 
 Misc testing to do
 =================
diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
--- a/fs/cifs/cifs_debug.c	Sat Feb 15 14:10:23 2003
+++ b/fs/cifs/cifs_debug.c	Fri Mar  7 15:01:07 2003
@@ -227,7 +227,7 @@
 	if (pde)
 		pde->write_proc = traceSMB_write;
 
-	pde = create_proc_read_entry("oplockEnabled", 0, proc_fs_cifs,
+	pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
 				     oplockEnabled_read, 0);
 	if (pde)
 		pde->write_proc = oplockEnabled_write;
@@ -269,7 +269,7 @@
 	remove_proc_entry("SimultaneousOps", proc_fs_cifs);
 	remove_proc_entry("TotalOps", proc_fs_cifs);
 	remove_proc_entry("MultiuserMount", proc_fs_cifs);
-	remove_proc_entry("oplockEnabled", proc_fs_cifs);
+	remove_proc_entry("OplockEnabled", proc_fs_cifs);
 	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
 	remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
 	remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
diff -Nru a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
--- a/fs/cifs/cifs_fs_sb.h	Thu Oct 10 12:16:09 2002
+++ b/fs/cifs/cifs_fs_sb.h	Fri Mar  7 15:01:07 2003
@@ -20,8 +20,9 @@
 
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
-	/* list of implicit mounts beneath this mount point - needed in dfs case */
 	struct list_head nested_tcon_q;
 	struct nls_table *local_nls;
+    unsigned int rsize;
+    unsigned int wsize;
 };
 #endif				/* _CIFS_FS_SB_H */
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	Sun Feb 23 14:23:53 2003
+++ b/fs/cifs/cifsfs.c	Fri Mar  7 15:01:07 2003
@@ -52,6 +52,7 @@
 unsigned int extended_security = 0;
 unsigned int ntlmv2_support = 0;
 unsigned int sign_CIFS_PDUs = 0;
+unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
 			char *);
@@ -83,8 +84,11 @@
 
 	sb->s_magic = CIFS_MAGIC_NUMBER;
 	sb->s_op = &cifs_super_ops;
-	sb->s_blocksize = CIFS_MAX_MSGSIZE;	/* BB check SMBSessSetup negotiated size */
-	sb->s_blocksize_bits = 10;	/* 2**10 = CIFS_MAX_MSGSIZE */
+	if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
+	    sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
+	else
+		sb->s_blocksize = CIFSMaximumBufferSize;
+	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
 	inode = iget(sb, ROOT_I);
 
 	if (!inode)
@@ -162,6 +166,12 @@
 	return 0;		/* always return success? what if volume is no longer available? */
 }
 
+static int cifs_permission(struct inode * inode, int mask)
+{
+	/* the server does permission checks, we do not need to do it here */
+	return 0;
+}
+
 static kmem_cache_t *cifs_inode_cachep;
 kmem_cache_t *cifs_req_cachep;
 kmem_cache_t *cifs_mid_cachep;
@@ -270,6 +280,7 @@
 	.mkdir = cifs_mkdir,
 	.rmdir = cifs_rmdir,
 	.rename = cifs_rename,
+	.permission = cifs_permission,
 /*	revalidate:cifs_revalidate,   */
 	.setattr = cifs_setattr,
 	.symlink = cifs_symlink,
@@ -280,18 +291,19 @@
 	.setattr = cifs_setattr,
 	.getattr = cifs_getattr, /* do we need this anymore? */
 	.rename = cifs_rename,
+	.permission = cifs_permission,
 #ifdef CIFS_XATTR
 	.setxattr = cifs_setxattr,
 	.getxattr = cifs_getxattr,
 	.listxattr = cifs_listxattr,
 	.removexattr = cifs_removexattr,
-	.permission = cifs_permission,
 #endif 
 };
 
 struct inode_operations cifs_symlink_inode_ops = {
 	.readlink = cifs_readlink,
 	.follow_link = cifs_follow_link,
+	.permission = cifs_permission,
 	/* BB add the following two eventually */
 	/* revalidate: cifs_revalidate,
 	   setattr:    cifs_notify_change, *//* BB do we need notify change */
@@ -318,6 +330,7 @@
 struct file_operations cifs_dir_ops = {
 	.readdir = cifs_readdir,
 	.release = cifs_closedir,
+	.read    = generic_read_dir,
 };
 
 static void
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	Wed Feb 19 15:31:55 2003
+++ b/fs/cifs/cifssmb.c	Fri Mar  7 15:01:07 2003
@@ -519,8 +519,7 @@
 	pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
 	pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
 	pSMB->Remaining = 0;
-	pSMB->MaxCount = cpu_to_le16(min_t(const unsigned int, count,
-		(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00));
+	pSMB->MaxCount = cpu_to_le16(count);
 	pSMB->MaxCountHigh = 0;
 	pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
 
@@ -710,9 +709,9 @@
 				  , nls_codepage);
 		name_len++;	/* trailing null */
 		name_len *= 2;
-		pSMB->OldFileName[name_len] = 0;	/* pad */
+		pSMB->OldFileName[name_len] = 0x04;	/* pad */
 	/* protocol requires ASCII signature byte on Unicode string */
-		pSMB->OldFileName[name_len + 1] = 0x04;
+		pSMB->OldFileName[name_len + 1] = 0x00;
 		name_len2 =
 		    cifs_strtoUCS((wchar_t *) & pSMB->
 				  OldFileName[name_len + 2], toName, 530,
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	Sun Feb 23 14:23:54 2003
+++ b/fs/cifs/connect.c	Fri Mar  7 15:01:07 2003
@@ -25,6 +25,7 @@
 #include <linux/wait.h>
 #include <linux/version.h>
 #include <linux/ipv6.h>
+#include <linux/pagemap.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include "cifspdu.h"
@@ -56,6 +57,9 @@
 	mode_t file_mode;
 	mode_t dir_mode;
 	int rw;
+    unsigned int rsize;
+    unsigned int wsize;
+	unsigned short int port;
 };
 
 int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
@@ -343,11 +347,7 @@
 	char *value;
 	char *data;
 
-	vol->username = NULL;
-	vol->password = NULL;
-	vol->domainname = NULL;
-	vol->UNC = NULL;
-	vol->UNCip = NULL;
+	memset(vol,0,sizeof(struct smb_vol));
 	vol->linux_uid = current->uid;	/* current->euid instead? */
 	vol->linux_gid = current->gid;
 	vol->rw = TRUE;
@@ -381,6 +381,15 @@
 				printk(KERN_WARNING "CIFS: password too long\n");
 				return 1;
 			}
+		} else if (strnicmp(data, "ip", 2) == 0) {
+			if (!value || !*value) {
+				vol->UNCip = NULL;
+			} else if (strnlen(value, 35) < 35) {
+				vol->UNCip = value;
+			} else {
+				printk(KERN_WARNING "CIFS: ip address too long\n");
+				return 1;
+			}
 		} else if ((strnicmp(data, "unc", 3) == 0)
 			   || (strnicmp(data, "target", 6) == 0)
 			   || (strnicmp(data, "path", 4) == 0)) {
@@ -399,7 +408,6 @@
 					       "CIFS: UNC Path does not begin with // or \\\\ \n");
 					return 1;
 				}
-				vol->UNCip = &vol->UNC[2];
 			} else {
 				printk(KERN_WARNING "CIFS: UNC name too long\n");
 				return 1;
@@ -420,22 +428,37 @@
 		} else if (strnicmp(data, "uid", 3) == 0) {
 			if (value && *value) {
 				vol->linux_uid =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "gid", 3) == 0) {
 			if (value && *value) {
 				vol->linux_gid =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "file_mode", 4) == 0) {
 			if (value && *value) {
 				vol->file_mode =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "dir_mode", 3) == 0) {
 			if (value && *value) {
 				vol->dir_mode =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "port", 4) == 0) {
+			if (value && *value) {
+				vol->port =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "rsize", 5) == 0) {
+			if (value && *value) {
+				vol->rsize =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "wsize", 5) == 0) {
+			if (value && *value) {
+				vol->wsize =
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "version", 3) == 0) {
 			/* ignore */
@@ -458,12 +481,14 @@
 				printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
 				return 1;
 			}
-			vol->UNCip = &vol->UNC[2];
 		} else {
 			printk(KERN_WARNING "CIFS: UNC name too long\n");
 			return 1;
 		}
 	}
+	if(vol->UNCip == 0)
+		vol->UNCip = &vol->UNC[2];
+
 	return 0;
 }
 
@@ -553,20 +578,16 @@
 	unsigned char *referrals = NULL;
 
 	if (pSesInfo->ipc_tid == 0) {
-		temp_unc =
-		    kmalloc(2 +
-			    strnlen(pSesInfo->serverName,
-				    SERVER_NAME_LEN_WITH_NULL * 2) + 1 +
-			    4 /* IPC$ */  + 1, GFP_KERNEL);
+		temp_unc = kmalloc(2 /* for slashes */ +
+			strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
+				 + 1 + 4 /* slash IPC$ */  + 2,
+				GFP_KERNEL);
 		if (temp_unc == NULL)
 			return -ENOMEM;
 		temp_unc[0] = '\\';
 		temp_unc[1] = '\\';
-		strncpy(temp_unc + 2, pSesInfo->serverName,
-			SERVER_NAME_LEN_WITH_NULL * 2);
-		strncpy(temp_unc + 2 +
-			strnlen(pSesInfo->serverName,
-				SERVER_NAME_LEN_WITH_NULL * 2), "\\IPC$", 6);
+		strcpy(temp_unc + 2, pSesInfo->serverName);
+		strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
 		rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
 		cFYI(1,
 		     ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
@@ -587,6 +608,7 @@
 	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
 	int ntlmv2_flag = FALSE;
 
+    /* what if server changes its buffer size after dropping the session? */
 	if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */
 		rc = CIFSSMBNegotiate(xid, pSesInfo);
 	pSesInfo->capabilities = pSesInfo->server->capabilities;
@@ -670,11 +692,23 @@
 	}
 
 	psin_server->sin_family = AF_INET;
-	psin_server->sin_port = htons(CIFS_PORT);
+	if(psin_server->sin_port) { /* user overrode default port */
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in),0);
+		if (rc >= 0) {
+			return rc;
+		}
+	}
+
+	/* do not retry on the same port we just failed on */
+	if(psin_server->sin_port != htons(CIFS_PORT)) {
+		psin_server->sin_port = htons(CIFS_PORT);
 
-	rc = (*csocket)->ops->connect(*csocket,
+		rc = (*csocket)->ops->connect(*csocket,
 					(struct sockaddr *) psin_server,
 					sizeof (struct sockaddr_in),0);
+	}
 	if (rc < 0) {
 		psin_server->sin_port = htons(RFC1001_PORT);
 		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
@@ -703,13 +737,24 @@
 	}
 
 	psin_server->sin6_family = AF_INET6;
-	psin_server->sin6_port = htons(CIFS_PORT);
+	if(psin_server->sin6_port) { /* user overrode default port */
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in6),0);
+		if (rc >= 0) {
+			return rc;
+		}
+	}
 
-	rc = (*csocket)->ops->connect(*csocket,
-				      (struct sockaddr *) psin_server,
-				      sizeof (struct sockaddr_in6), 0
-/* BB fix the timeout to be shorter - and check flags */
-	    );
+	/* do not retry on the same port we just failed on */
+	if(psin_server->sin6_port != htons(CIFS_PORT)) {
+		psin_server->sin6_port = htons(CIFS_PORT);
+
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in6), 0);
+/* BB fix the timeout to be shorter above - and check flags */
+	}
 	if (rc < 0) {
 		psin_server->sin6_port = htons(RFC1001_PORT);
 		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
@@ -744,7 +789,7 @@
 	struct TCP_Server_Info *srvTcp = NULL;
 
 	xid = GetXid();
-	cFYI(0, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
+	cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
 
 	if(parse_mount_options(mount_data, devname, &volume_info)) {
 		FreeXid(xid);
@@ -778,7 +823,9 @@
 			     volume_info.username, &srvTcp);
 	if (srvTcp) {
 		cFYI(1, ("Existing tcp session with server found "));                
-	} else {		/* create socket */
+	} else {	/* create socket */
+		if(volume_info.port)
+			sin_server.sin_port = htons(volume_info.port);
 		rc = ipv4_connect(&sin_server, &csocket);
 		if (rc < 0) {
 			cERROR(1,
@@ -839,9 +886,23 @@
 				atomic_inc(&srvTcp->socketUseCount);
 		}
 	}
-
+    
 	/* search for existing tcon to this server share */
 	if (!rc) {
+		if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+			cifs_sb->rsize = volume_info.rsize;
+		else
+			cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+		if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+			cifs_sb->wsize = volume_info.wsize;
+		else
+			cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+		if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
+			cifs_sb->rsize = PAGE_CACHE_SIZE;
+			cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
+		}
+
+
 		tcon =
 		    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
 			     volume_info.username);
@@ -944,7 +1005,7 @@
 	if (smb_buffer == 0) {
 		return -ENOMEM;
 	}
-    smb_buffer_response = smb_buffer;
+	smb_buffer_response = smb_buffer;
 	pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
 
 	/* send SMBsessionSetup here */
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	Sun Feb 23 14:23:54 2003
+++ b/fs/cifs/file.c	Fri Mar  7 15:01:07 2003
@@ -393,7 +393,7 @@
 {
 	struct address_space *mapping = page->mapping;
 	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
-	char * write_data = kmap(page);
+	char * write_data;
 	int rc = -EFAULT;
 	int bytes_written = 0;
 	struct cifs_sb_info *cifs_sb;
@@ -411,8 +411,9 @@
 
 	/* figure out which file struct to use 
 	if (file->private_data == NULL) {
-	   FreeXid(xid);
-	   return -EBADF;
+		kunmap(page);
+		FreeXid(xid);
+		return -EBADF;
 	}     
 	 */
 	if (!mapping) {
@@ -424,15 +425,17 @@
 	}
 
 	offset += (loff_t)from;
+	write_data = kmap(page);
 	write_data += from;
 
 	if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) {
+		kunmap(page);
 		FreeXid(xid);
 		return -EIO;
 	}
 
 	/* check to make sure that we are not extending the file */
-    if(mapping->host->i_size - offset < (loff_t)to)
+	if(mapping->host->i_size - offset < (loff_t)to)
 		to = (unsigned)(mapping->host->i_size - offset); 
 		
 
@@ -459,6 +462,7 @@
 		rc = -EIO;
 	}
 
+	kunmap(page);
 	FreeXid(xid);
 	return rc;
 }
@@ -604,6 +608,7 @@
 	int rc = -EACCES;
 	int bytes_read = 0;
 	int total_read;
+	int current_read_size;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 	int xid;
@@ -620,10 +625,11 @@
 
 	for (total_read = 0,current_offset=read_data; read_size > total_read;
 				total_read += bytes_read,current_offset+=bytes_read) {
+		current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
 		rc = CIFSSMBRead(xid, pTcon,
 				 ((struct cifsFileInfo *) file->
 				  private_data)->netfid,
-				 read_size - total_read, *poffset,
+				 current_read_size, *poffset,
 				 &bytes_read, &current_offset);
 		if (rc || (bytes_read == 0)) {
 			if (total_read) {
@@ -740,6 +746,8 @@
 			num_pages-i, (unsigned long) offset)); 
 		
 		read_size = (num_pages - i) * PAGE_CACHE_SIZE;
+		/* Read size needs to be in multiples of one page */
+		read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
 		rc = CIFSSMBRead(xid, pTcon,
 			((struct cifsFileInfo *) file->
 			 private_data)->netfid,
@@ -1061,11 +1069,11 @@
 
 	xid = GetXid();
 
-	data = kmalloc(4096, GFP_KERNEL);
-	pfindData = (FILE_DIRECTORY_INFO *) data;
-
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
+	data = kmalloc(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE,
+			GFP_KERNEL);
+	pfindData = (FILE_DIRECTORY_INFO *) data;
 
 	full_path = build_wildcard_path_from_dentry(file->f_dentry);
 
diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c
--- a/fs/cifs/misc.c	Tue Feb 18 19:15:11 2003
+++ b/fs/cifs/misc.c	Fri Mar  7 15:01:07 2003
@@ -153,7 +153,8 @@
 
 /* We could use negotiated size instead of max_msgsize - 
    but it may be more efficient to always alloc same size 
-   albeit slightly larger */
+   albeit slightly larger than necessary and maxbuffersize 
+   defaults to this and can not be bigger */
 	ret_buf =
 	    (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
 
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	Tue Feb 18 19:15:11 2003
+++ b/fs/cifs/transport.c	Fri Mar  7 15:01:07 2003
@@ -159,7 +159,7 @@
 	midQ = AllocMidQEntry(in_buf, ses);
 	if (midQ == NULL)
 		return -EIO;
-	if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
+	if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
 		cERROR(1,
 		       ("Illegal length, greater than maximum frame, %d ",
 			in_buf->smb_buf_length));
diff -Nru a/fs/compat.c b/fs/compat.c
--- a/fs/compat.c	Mon Jan 13 01:16:26 2003
+++ b/fs/compat.c	Sun Mar  9 01:34:45 2003
@@ -75,36 +75,6 @@
 	return error;
 }
 
-int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
-	int err;
-
-	if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)))
-		return -EFAULT;
-
-	err = __get_user(kfl->l_type, &ufl->l_type);
-	err |= __get_user(kfl->l_whence, &ufl->l_whence);
-	err |= __get_user(kfl->l_start, &ufl->l_start);
-	err |= __get_user(kfl->l_len, &ufl->l_len);
-	err |= __get_user(kfl->l_pid, &ufl->l_pid);
-	return err;
-}
-
-int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)))
-		return -EFAULT;
-
-	err = __put_user(kfl->l_type, &ufl->l_type);
-	err |= __put_user(kfl->l_whence, &ufl->l_whence);
-	err |= __put_user(kfl->l_start, &ufl->l_start);
-	err |= __put_user(kfl->l_len, &ufl->l_len);
-	err |= __put_user(kfl->l_pid, &ufl->l_pid);
-	return err;
-}
-
 static int put_compat_statfs(struct compat_statfs *ubuf, struct statfs *kbuf)
 {
 	if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
@@ -159,3 +129,120 @@
 out:
 	return error;
 }
+
+static int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+	if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+	    __get_user(kfl->l_type, &ufl->l_type) ||
+	    __get_user(kfl->l_whence, &ufl->l_whence) ||
+	    __get_user(kfl->l_start, &ufl->l_start) ||
+	    __get_user(kfl->l_len, &ufl->l_len) ||
+	    __get_user(kfl->l_pid, &ufl->l_pid))
+		return -EFAULT;
+	return 0;
+}
+
+static int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+	if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+	    __put_user(kfl->l_type, &ufl->l_type) ||
+	    __put_user(kfl->l_whence, &ufl->l_whence) ||
+	    __put_user(kfl->l_start, &ufl->l_start) ||
+	    __put_user(kfl->l_len, &ufl->l_len) ||
+	    __put_user(kfl->l_pid, &ufl->l_pid))
+		return -EFAULT;
+	return 0;
+}
+
+static int get_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+	if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+	    __get_user(kfl->l_type, &ufl->l_type) ||
+	    __get_user(kfl->l_whence, &ufl->l_whence) ||
+	    __get_user(kfl->l_start, &ufl->l_start) ||
+	    __get_user(kfl->l_len, &ufl->l_len) ||
+	    __get_user(kfl->l_pid, &ufl->l_pid))
+		return -EFAULT;
+	return 0;
+}
+
+static int put_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+	if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+	    __put_user(kfl->l_type, &ufl->l_type) ||
+	    __put_user(kfl->l_whence, &ufl->l_whence) ||
+	    __put_user(kfl->l_start, &ufl->l_start) ||
+	    __put_user(kfl->l_len, &ufl->l_len) ||
+	    __put_user(kfl->l_pid, &ufl->l_pid))
+		return -EFAULT;
+	return 0;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
+
+asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
+		unsigned long arg)
+{
+	mm_segment_t old_fs;
+	struct flock f;
+	long ret;
+
+	switch (cmd) {
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		ret = get_compat_flock(&f, (struct compat_flock *)arg);
+		if (ret != 0)
+			break;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+		set_fs(old_fs);
+		if ((cmd == F_GETLK) && (ret == 0)) {
+			if ((f.l_start >= COMPAT_OFF_T_MAX) ||
+			    ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
+				ret = -EOVERFLOW;
+			if (ret == 0)
+				ret = put_compat_flock(&f,
+						(struct compat_flock *)arg);
+		}
+		break;
+
+	case F_GETLK64:
+	case F_SETLK64:
+	case F_SETLKW64:
+		ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+		if (ret != 0)
+			break;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		ret = sys_fcntl(fd, F_GETLK, (unsigned long)&f);
+		ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
+				((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
+				(unsigned long)&f);
+		set_fs(old_fs);
+		if ((cmd == F_GETLK64) && (ret == 0)) {
+			if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
+			    ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
+				ret = -EOVERFLOW;
+			if (ret == 0)
+				ret = put_compat_flock64(&f,
+						(struct compat_flock64 *)arg);
+		}
+		break;
+
+	default:
+		ret = sys_fcntl(fd, cmd, arg);
+		break;
+	}
+	return ret;
+}
+
+asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
+		unsigned long arg)
+{
+	if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
+		return -EINVAL;
+	return compat_sys_fcntl64(fd, cmd, arg);
+}
+
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	Tue Mar  4 14:30:07 2003
+++ b/fs/dcache.c	Mon Mar 10 10:49:26 2003
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <asm/uaccess.h>
+#include <linux/security.h>
 
 #define DCACHE_PARANOIA 1
 /* #define DCACHE_DEBUG 1 */
@@ -760,6 +761,7 @@
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
 	if (!list_empty(&entry->d_alias)) BUG();
+	security_d_instantiate(entry, inode);
 	spin_lock(&dcache_lock);
 	if (inode)
 		list_add(&entry->d_alias, &inode->i_dentry);
@@ -890,6 +892,7 @@
 	struct dentry *new = NULL;
 
 	if (inode && S_ISDIR(inode->i_mode)) {
+		security_d_instantiate(dentry, inode);
 		spin_lock(&dcache_lock);
 		if (!list_empty(&inode->i_dentry)) {
 			new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Tue Feb 25 10:47:06 2003
+++ b/fs/devfs/base.c	Sun Mar 16 22:33:08 2003
@@ -729,7 +729,6 @@
 
 #define OPTION_NONE             0x00
 #define OPTION_MOUNT            0x01
-#define OPTION_ONLY             0x02
 
 #define PRINTK(format, args...) \
    {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
@@ -763,17 +762,10 @@
     unsigned char no_more_additions:1;
 };
 
-struct file_type
-{
-    struct file_operations *ops;
-    unsigned long size;
-};
-
 struct bdev_type
 {
     struct block_device_operations *ops;
     dev_t dev;
-    unsigned char autogen:1;
     unsigned char removable:1;
 };
 
@@ -811,7 +803,6 @@
     union 
     {
 	struct directory_type dir;
-	struct file_type file;
 	struct bdev_type bdev;
 	struct cdev_type cdev;
 	struct symlink_type symlink;
@@ -938,8 +929,6 @@
     if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname);
     if ( S_ISCHR (de->mode) && de->u.cdev.autogen )
 	devfs_dealloc_devnum (de->mode, de->u.cdev.dev);
-    if ( S_ISBLK (de->mode) && de->u.bdev.autogen )
-	devfs_dealloc_devnum (de->mode, de->u.bdev.dev);
     WRITE_ENTRY_MAGIC (de, 0);
 #ifdef CONFIG_DEVFS_DEBUG
     spin_lock (&stat_lock);
@@ -1495,17 +1484,6 @@
 	PRINTK ("(%s): creating symlinks is not allowed\n", name);
 	return NULL;
     }
-    if ( ( S_ISCHR (mode) || S_ISBLK (mode) ) &&
-	 (flags & DEVFS_FL_AUTO_DEVNUM) )
-    {
-	devnum = devfs_alloc_devnum (mode);
-	if (!devnum) {
-	    PRINTK ("(%s): exhausted %s device numbers\n",
-		    name, S_ISCHR (mode) ? "char" : "block");
-	    return NULL;
-	}
-	dev = devnum;
-    }
     if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL )
     {
 	PRINTK ("(%s): could not prepare leaf\n", name);
@@ -1521,8 +1499,6 @@
 	de->u.cdev.autogen = devnum != 0;
 	de->u.bdev.ops = ops;
 	if (flags & DEVFS_FL_REMOVABLE) de->u.bdev.removable = TRUE;
-    } else if ( S_ISREG (mode) ) {
-	de->u.file.ops = ops;
     } else {
 	PRINTK ("(%s): illegal mode: %x\n", name, mode);
 	devfs_put (de);
@@ -1825,15 +1801,9 @@
 
 static struct file_operations *devfs_get_ops (devfs_handle_t de)
 {
+    struct file_operations *ops = de->u.cdev.ops;
     struct module *owner;
-    struct file_operations *ops;
 
-    if (de == NULL) return NULL;
-    VERIFY_ENTRY (de);
-    if (S_ISCHR (de->mode))
-	ops = de->u.cdev.ops;
-    else
-	ops = de->u.file.ops;
     if (!ops)
 	return NULL;
     owner = ops->owner;
@@ -1848,40 +1818,6 @@
 }   /*  End Function devfs_get_ops  */
 
 /**
- *	devfs_set_file_size - Set the file size for a devfs regular file.
- *	@de: The handle to the device entry.
- *	@size: The new file size.
- *
- *	Returns 0 on success, else a negative error code.
- */
-
-int devfs_set_file_size (devfs_handle_t de, unsigned long size)
-{
-    if (de == NULL) return -EINVAL;
-    VERIFY_ENTRY (de);
-    if ( !S_ISREG (de->mode) ) return -EINVAL;
-    if (de->u.file.size == size) return 0;
-    de->u.file.size = size;
-    if (de->inode.dentry == NULL) return 0;
-    if (de->inode.dentry->d_inode == NULL) return 0;
-    de->inode.dentry->d_inode->i_size = size;
-    return 0;
-}   /*  End Function devfs_set_file_size  */
-
-
-/**
- *	devfs_only - returns true if "devfs=only" is a boot option
- *
- *	If "devfs=only" this function will return 1, otherwise 0 is returned.
- */
-
-int devfs_only (void)
-{
-    return (boot_options & OPTION_ONLY) ? 1 : 0;
-}   /*  End Function devfs_only  */
-
-
-/**
  *	devfs_setup - Process kernel boot options.
  *	@str: The boot options after the "devfs=".
  */
@@ -1909,7 +1845,6 @@
 	{"dilookup",  DEBUG_I_LOOKUP,     &devfs_debug_init},
 	{"diunlink",  DEBUG_I_UNLINK,     &devfs_debug_init},
 #endif  /*  CONFIG_DEVFS_DEBUG  */
-	{"only",      OPTION_ONLY,        &boot_options},
 	{"mount",     OPTION_MOUNT,       &boot_options},
 	{NULL,        0,                  NULL}
     };
@@ -2192,11 +2127,8 @@
 	if (bd_acquire (inode) != 0)
 		PRINTK ("(%d): no block device from bdget()\n",(int)inode->i_ino);
     }
-    else if ( S_ISFIFO (de->mode) ) inode->i_fop = &def_fifo_fops;
-    else if ( S_ISREG (de->mode) )
-    {
-	inode->i_size = de->u.file.size;
-    }
+    else if ( S_ISFIFO (de->mode) )
+    	inode->i_fop = &def_fifo_fops;
     else if ( S_ISDIR (de->mode) )
     {
 	inode->i_op = &devfs_dir_iops;
@@ -2309,15 +2241,6 @@
 	}
 	else
 	    err = chrdev_open (inode, file);
-    } else if (S_ISREG(inode->i_mode)) {
-	ops = devfs_get_ops (de);  /*  Now have module refcount  */
-	file->f_op = ops;
-	if (file->f_op)
-	{
-	    lock_kernel ();
-	    err = file->f_op->open ? (*file->f_op->open) (inode, file) : 0;
-	    unlock_kernel ();
-	}
     }
     return err;
 }   /*  End Function devfs_open  */
diff -Nru a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
--- a/fs/exportfs/expfs.c	Thu Oct 10 16:07:34 2002
+++ b/fs/exportfs/expfs.c	Wed Jan 15 05:40:50 2003
@@ -353,7 +353,7 @@
 	/*
 	 * Open the directory ...
 	 */
-	error = init_private_file(&file, dentry, FMODE_READ);
+	error = open_private_file(&file, dentry, O_RDONLY);
 	if (error)
 		goto out;
 	error = -EINVAL;
@@ -381,8 +381,7 @@
 	}
 
 out_close:
-	if (file.f_op->release)
-		file.f_op->release(dir, &file);
+	close_private_file(&file);
 out:
 	return error;
 }
diff -Nru a/fs/ext2/balloc.c b/fs/ext2/balloc.c
--- a/fs/ext2/balloc.c	Wed Feb  5 08:27:03 2003
+++ b/fs/ext2/balloc.c	Sun Mar 16 22:33:17 2003
@@ -395,7 +395,7 @@
 			goto io_error;
 		group_alloc = group_reserve_blocks(desc, gdp_bh, es_alloc);
 	}
-	if (bit >= sbi->s_groups_count) {
+	if (!group_alloc) {
 		*err = -ENOSPC;
 		goto out_release;
 	}
diff -Nru a/fs/ext2/dir.c b/fs/ext2/dir.c
--- a/fs/ext2/dir.c	Sun Mar  2 18:14:28 2003
+++ b/fs/ext2/dir.c	Mon Mar 10 22:34:32 2003
@@ -337,6 +337,9 @@
 	struct ext2_inode_info *ei = EXT2_I(dir);
 	ext2_dirent * de;
 
+	if (npages == 0)
+		goto out;
+
 	/* OFFSET_CACHE */
 	*res_page = NULL;
 
diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h
--- a/fs/ext2/ext2.h	Sat Dec 21 08:24:40 2002
+++ b/fs/ext2/ext2.h	Sun Mar 16 22:33:16 2003
@@ -112,6 +112,7 @@
 extern void ext2_discard_prealloc (struct inode *);
 extern void ext2_truncate (struct inode *);
 extern int ext2_setattr (struct dentry *, struct iattr *);
+extern void ext2_set_inode_flags(struct inode *inode);
 
 /* ioctl.c */
 extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
--- a/fs/ext2/ialloc.c	Sun Mar  2 18:14:28 2003
+++ b/fs/ext2/ialloc.c	Sun Mar 16 22:33:16 2003
@@ -545,10 +545,7 @@
 	ei->i_prealloc_count = 0;
 	ei->i_dir_start_lookup = 0;
 	ei->i_state = EXT2_STATE_NEW;
-	if (ei->i_flags & EXT2_SYNC_FL)
-		inode->i_flags |= S_SYNC;
-	if (ei->i_flags & EXT2_DIRSYNC_FL)
-		inode->i_flags |= S_DIRSYNC;
+	ext2_set_inode_flags(inode);
 	inode->i_generation = EXT2_SB(sb)->s_next_generation++;
 	insert_inode_hash(inode);
 
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	Wed Feb  5 08:27:03 2003
+++ b/fs/ext2/inode.c	Sun Mar 16 22:33:16 2003
@@ -1011,6 +1011,23 @@
 	return ERR_PTR(-EIO);
 }
 
+void ext2_set_inode_flags(struct inode *inode)
+{
+	unsigned int flags = EXT2_I(inode)->i_flags;
+
+	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+	if (flags & EXT2_SYNC_FL)
+		inode->i_flags |= S_SYNC;
+	if (flags & EXT2_APPEND_FL)
+		inode->i_flags |= S_APPEND;
+	if (flags & EXT2_IMMUTABLE_FL)
+		inode->i_flags |= S_IMMUTABLE;
+	if (flags & EXT2_NOATIME_FL)
+		inode->i_flags |= S_NOATIME;
+	if (flags & EXT2_DIRSYNC_FL)
+		inode->i_flags |= S_DIRSYNC;
+}
+
 void ext2_read_inode (struct inode * inode)
 {
 	struct ext2_inode_info *ei = EXT2_I(inode);
@@ -1108,14 +1125,7 @@
 				   le32_to_cpu(raw_inode->i_block[0]));
 	}
 	brelse (bh);
-	if (ei->i_flags & EXT2_SYNC_FL)
-		inode->i_flags |= S_SYNC;
-	if (ei->i_flags & EXT2_APPEND_FL)
-		inode->i_flags |= S_APPEND;
-	if (ei->i_flags & EXT2_IMMUTABLE_FL)
-		inode->i_flags |= S_IMMUTABLE;
-	if (ei->i_flags & EXT2_NOATIME_FL)
-		inode->i_flags |= S_NOATIME;
+	ext2_set_inode_flags(inode);
 	return;
 	
 bad_inode:
diff -Nru a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
--- a/fs/ext2/ioctl.c	Sat Nov 23 06:29:46 2002
+++ b/fs/ext2/ioctl.c	Sun Mar 16 22:33:16 2003
@@ -58,22 +58,7 @@
 		flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
 		ei->i_flags = flags;
 
-		if (flags & EXT2_SYNC_FL)
-			inode->i_flags |= S_SYNC;
-		else
-			inode->i_flags &= ~S_SYNC;
-		if (flags & EXT2_APPEND_FL)
-			inode->i_flags |= S_APPEND;
-		else
-			inode->i_flags &= ~S_APPEND;
-		if (flags & EXT2_IMMUTABLE_FL)
-			inode->i_flags |= S_IMMUTABLE;
-		else
-			inode->i_flags &= ~S_IMMUTABLE;
-		if (flags & EXT2_NOATIME_FL)
-			inode->i_flags |= S_NOATIME;
-		else
-			inode->i_flags &= ~S_NOATIME;
+		ext2_set_inode_flags(inode);
 		inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(inode);
 		return 0;
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	Wed Feb  5 08:27:03 2003
+++ b/fs/ext2/super.c	Sat Mar  8 14:50:40 2003
@@ -781,7 +781,6 @@
 		if (!sbi->s_group_desc[i]) {
 			for (j = 0; j < i; j++)
 				brelse (sbi->s_group_desc[j]);
-			kfree(sbi->s_group_desc);
 			printk ("EXT2-fs: unable to read group descriptors\n");
 			goto failed_mount_group_desc;
 		}
diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c
--- a/fs/ext2/xattr.c	Tue Feb 25 08:21:08 2003
+++ b/fs/ext2/xattr.c	Sat Mar  8 14:50:42 2003
@@ -731,7 +731,7 @@
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(old_bh, "reusing block %ld",
+			ea_bdebug(new_bh, "reusing block %ld",
 				new_bh->b_blocknr);
 			
 			error = -EDQUOT;
diff -Nru a/fs/ext3/dir.c b/fs/ext3/dir.c
--- a/fs/ext3/dir.c	Mon Feb 24 23:13:19 2003
+++ b/fs/ext3/dir.c	Tue Mar  4 08:34:07 2003
@@ -105,8 +105,10 @@
 
 	if (is_dx(inode)) {
 		err = ext3_dx_readdir(filp, dirent, filldir);
-		if (err != ERR_BAD_DX_DIR)
+		if (err != ERR_BAD_DX_DIR) {
+			unlock_kernel();
 			return err;
+		}
 		/*
 		 * We don't set the inode dirty flag since it's not
 		 * critical that it get flushed back to the disk.
diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
--- a/fs/ext3/ialloc.c	Fri Feb 14 18:24:09 2003
+++ b/fs/ext3/ialloc.c	Sun Mar 16 22:33:16 2003
@@ -568,10 +568,7 @@
 #endif
 	ei->i_block_group = group;
 	
-	if (ei->i_flags & EXT3_SYNC_FL)
-		inode->i_flags |= S_SYNC;
-	if (ei->i_flags & EXT3_DIRSYNC_FL)
-		inode->i_flags |= S_DIRSYNC;
+	ext3_set_inode_flags(inode);
 	if (IS_DIRSYNC(inode))
 		handle->h_sync = 1;
 	insert_inode_hash(inode);
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Fri Feb 14 18:24:09 2003
+++ b/fs/ext3/inode.c	Sun Mar 16 22:33:16 2003
@@ -2209,6 +2209,24 @@
 	return -EIO;
 }
 
+void ext3_set_inode_flags(struct inode *inode)
+{
+	unsigned int flags = EXT3_I(inode)->i_flags;
+
+	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+	if (flags & EXT3_SYNC_FL)
+		inode->i_flags |= S_SYNC;
+	if (flags & EXT3_APPEND_FL)
+		inode->i_flags |= S_APPEND;
+	if (flags & EXT3_IMMUTABLE_FL)
+		inode->i_flags |= S_IMMUTABLE;
+	if (flags & EXT3_NOATIME_FL)
+		inode->i_flags |= S_NOATIME;
+	if (flags & EXT3_DIRSYNC_FL)
+		inode->i_flags |= S_DIRSYNC;
+}
+
+
 void ext3_read_inode(struct inode * inode)
 {
 	struct ext3_iloc iloc;
@@ -2320,14 +2338,7 @@
 		init_special_inode(inode, inode->i_mode,
 				   le32_to_cpu(iloc.raw_inode->i_block[0]));
 	}
-	if (ei->i_flags & EXT3_SYNC_FL)
-		inode->i_flags |= S_SYNC;
-	if (ei->i_flags & EXT3_APPEND_FL)
-		inode->i_flags |= S_APPEND;
-	if (ei->i_flags & EXT3_IMMUTABLE_FL)
-		inode->i_flags |= S_IMMUTABLE;
-	if (ei->i_flags & EXT3_NOATIME_FL)
-		inode->i_flags |= S_NOATIME;
+	ext3_set_inode_flags(inode);
 	return;
 	
 bad_inode:
diff -Nru a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
--- a/fs/ext3/ioctl.c	Sun Sep 15 14:04:13 2002
+++ b/fs/ext3/ioctl.c	Sun Mar 16 22:33:16 2003
@@ -85,22 +85,7 @@
 		flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
 		ei->i_flags = flags;
 
-		if (flags & EXT3_SYNC_FL)
-			inode->i_flags |= S_SYNC;
-		else
-			inode->i_flags &= ~S_SYNC;
-		if (flags & EXT3_APPEND_FL)
-			inode->i_flags |= S_APPEND;
-		else
-			inode->i_flags &= ~S_APPEND;
-		if (flags & EXT3_IMMUTABLE_FL)
-			inode->i_flags |= S_IMMUTABLE;
-		else
-			inode->i_flags &= ~S_IMMUTABLE;
-		if (flags & EXT3_NOATIME_FL)
-			inode->i_flags |= S_NOATIME;
-		else
-			inode->i_flags &= ~S_NOATIME;
+		ext3_set_inode_flags(inode);
 		inode->i_ctime = CURRENT_TIME;
 
 		err = ext3_mark_iloc_dirty(handle, inode, &iloc);
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	Mon Feb 10 19:42:01 2003
+++ b/fs/ext3/super.c	Mon Mar 10 22:34:32 2003
@@ -141,8 +141,11 @@
 		printk (KERN_CRIT "Remounting filesystem read-only\n");
 		sb->s_flags |= MS_RDONLY;
 	} else {
+		journal_t *journal = EXT3_SB(sb)->s_journal;
+
 		EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
-		journal_abort(EXT3_SB(sb)->s_journal, -EIO);
+		if (journal)
+			journal_abort(journal, -EIO);
 	}
 	ext3_commit_super(sb, es, 1);
 }
@@ -1154,7 +1157,7 @@
 		if (!bh) {
 			printk(KERN_ERR 
 			       "EXT3-fs: Can't read superblock on 2nd try.\n");
-			return -EINVAL;
+			goto failed_mount;
 		}
 		es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
 		sbi->s_es = es;
@@ -1622,11 +1625,15 @@
 			       struct ext3_super_block * es,
 			       int sync)
 {
+	struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
+
+	if (!sbh)
+		return;
 	es->s_wtime = cpu_to_le32(get_seconds());
-	BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "marking dirty");
-	mark_buffer_dirty(EXT3_SB(sb)->s_sbh);
+	BUFFER_TRACE(sbh, "marking dirty");
+	mark_buffer_dirty(sbh);
 	if (sync)
-		sync_dirty_buffer(EXT3_SB(sb)->s_sbh);
+		sync_dirty_buffer(sbh);
 }
 
 
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	Tue Feb 25 08:21:08 2003
+++ b/fs/ext3/xattr.c	Sat Mar  8 14:50:42 2003
@@ -732,7 +732,7 @@
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(old_bh, "reusing block %ld",
+			ea_bdebug(new_bh, "reusing block %ld",
 				new_bh->b_blocknr);
 			
 			error = -EDQUOT;
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Fri Feb 21 11:46:34 2003
+++ b/fs/file_table.c	Mon Mar 10 10:49:27 2003
@@ -27,7 +27,7 @@
 /* And here the free ones sit */
 static LIST_HEAD(free_list);
 /* public *and* exported. Not pretty! */
-spinlock_t files_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t files_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Find an unused file structure and return a pointer to it.
  * Returns NULL, if there are no more free file structures or
@@ -93,23 +93,42 @@
 
 /*
  * Clear and initialize a (private) struct file for the given dentry,
- * and call the open function (if any).  The caller must verify that
- * inode->i_fop is not NULL.
+ * allocate the security structure, and call the open function (if any).  
+ * The file should be released using close_private_file.
  */
-int init_private_file(struct file *filp, struct dentry *dentry, int mode)
+int open_private_file(struct file *filp, struct dentry *dentry, int flags)
 {
+	int error;
 	memset(filp, 0, sizeof(*filp));
 	eventpoll_init_file(filp);
-	filp->f_mode   = mode;
+	filp->f_flags  = flags;
+	filp->f_mode   = (flags+1) & O_ACCMODE;
 	atomic_set(&filp->f_count, 1);
 	filp->f_dentry = dentry;
 	filp->f_uid    = current->fsuid;
 	filp->f_gid    = current->fsgid;
 	filp->f_op     = dentry->d_inode->i_fop;
-	if (filp->f_op->open)
-		return filp->f_op->open(dentry->d_inode, filp);
-	else
-		return 0;
+	error = security_file_alloc(filp);
+	if (!error)
+		if (filp->f_op && filp->f_op->open) {
+			error = filp->f_op->open(dentry->d_inode, filp);
+			if (error)
+				security_file_free(filp);
+		}
+	return error;
+}
+
+/*
+ * Release a private file by calling the release function (if any) and
+ * freeing the security structure.
+ */
+void close_private_file(struct file *file)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+
+	if (file->f_op && file->f_op->release)
+		file->f_op->release(inode, file);
+	security_file_free(file);
 }
 
 void fput(struct file * file)
diff -Nru a/fs/filesystems.c b/fs/filesystems.c
--- a/fs/filesystems.c	Tue Mar  4 10:13:12 2003
+++ b/fs/filesystems.c	Wed Mar  5 15:38:04 2003
@@ -125,9 +125,7 @@
 	if (!res) {
 		/* we implicitly possess reference to @fs during registration,
 		 * so it cannot be unregister from under us. */
-		if (register_fs_subsys(fs))
-			printk(KERN_WARNING "Failed to register '%s' in sysfs\n",
-			       fs->name);
+		register_fs_subsys(fs);
 	}
 	return res;
 }
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Tue Mar  4 14:30:07 2003
+++ b/fs/inode.c	Sun Mar 16 22:33:19 2003
@@ -129,6 +129,7 @@
 		inode->i_pipe = NULL;
 		inode->i_bdev = NULL;
 		inode->i_cdev = NULL;
+		inode->i_rdev = to_kdev_t(0);
 		inode->i_security = NULL;
 		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
@@ -453,8 +454,13 @@
 }
 
 /*
- * This is called from kswapd when we think we need some
- * more memory. 
+ * shrink_icache_memory() will attempt to reclaim some unused inodes.  Here,
+ * "unused" means that no dentries are referring to the inodes: the files are
+ * not open and the dcache references to those inodes have already been
+ * reclaimed.
+ *
+ * This function is passed the number of inodes to scan, and it returns the
+ * total number of remaining possibly-reclaimable inodes.
  */
 static int shrink_icache_memory(int nr, unsigned int gfp_mask)
 {
@@ -467,7 +473,7 @@
 		if (gfp_mask & __GFP_FS)
 			prune_icache(nr);
 	}
-	return inodes_stat.nr_inodes;
+	return inodes_stat.nr_unused;
 }
 
 /*
diff -Nru a/fs/intermezzo/cache.c b/fs/intermezzo/cache.c
--- a/fs/intermezzo/cache.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/cache.c	Sun Feb 16 16:14:54 2003
@@ -22,7 +22,6 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <stdarg.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c
--- a/fs/intermezzo/dir.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/dir.c	Sun Feb 16 16:14:54 2003
@@ -22,8 +22,6 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/ioctls.h>
 #include <asm/uaccess.h>
diff -Nru a/fs/intermezzo/file.c b/fs/intermezzo/file.c
--- a/fs/intermezzo/file.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/file.c	Sun Feb 16 16:14:54 2003
@@ -29,8 +29,6 @@
  * 
  */
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/intermezzo/fileset.c b/fs/intermezzo/fileset.c
--- a/fs/intermezzo/fileset.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/fileset.c	Sun Feb 16 16:14:54 2003
@@ -23,7 +23,6 @@
  */
 
 #define __NO_VERSION__
-#include <stdarg.h>
 
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
diff -Nru a/fs/intermezzo/intermezzo_lib.h b/fs/intermezzo/intermezzo_lib.h
--- a/fs/intermezzo/intermezzo_lib.h	Fri Dec 13 17:17:29 2002
+++ b/fs/intermezzo/intermezzo_lib.h	Sun Feb 16 16:14:54 2003
@@ -32,12 +32,6 @@
 # include <sys/types.h>
 #endif
 
-#undef MIN
-#define MIN(a,b) (((a)<(b)) ? (a): (b))
-#undef MAX
-#define MAX(a,b) (((a)>(b)) ? (a): (b))
-#define MKSTR(ptr) ((ptr))? (ptr) : ""
-
 static inline int size_round (int val)
 {
 	return (val + 3) & (~0x3);
diff -Nru a/fs/intermezzo/methods.c b/fs/intermezzo/methods.c
--- a/fs/intermezzo/methods.c	Fri Dec 13 17:27:19 2002
+++ b/fs/intermezzo/methods.c	Sun Feb 16 16:14:54 2003
@@ -25,8 +25,6 @@
  *
  */
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/intermezzo/replicator.c b/fs/intermezzo/replicator.c
--- a/fs/intermezzo/replicator.c	Fri Dec 13 17:27:19 2002
+++ b/fs/intermezzo/replicator.c	Sun Feb 16 16:14:54 2003
@@ -25,7 +25,6 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <stdarg.h>
 #include <asm/uaccess.h>
 
 #include <linux/errno.h>
diff -Nru a/fs/intermezzo/super.c b/fs/intermezzo/super.c
--- a/fs/intermezzo/super.c	Sun Mar  2 18:13:30 2003
+++ b/fs/intermezzo/super.c	Thu Mar  6 09:33:04 2003
@@ -26,8 +26,6 @@
 static char rcsid[] __attribute ((unused)) = "$Id: super.c,v 1.4 2002/10/12 02:16:19 rread Exp $";
 #define INTERMEZZO_VERSION "$Revision: 1.4 $"
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c	Mon Feb 17 10:08:54 2003
+++ b/fs/jfs/jfs_logmgr.c	Mon Mar 10 10:31:45 2003
@@ -674,28 +674,29 @@
 	}
 	jfs_info("lmGroup Commit: tblk = 0x%p, gcrtc = %d", tblk, log->gcrtc);
 
-	if (tblk->xflag & COMMIT_LAZY) {
-		/*
-		 * Lazy transactions can leave now
-		 */
+	if (tblk->xflag & COMMIT_LAZY)
 		tblk->flag |= tblkGC_LAZY;
-		LOGGC_UNLOCK(log);
-		return 0;
-	}
-	/*
-	 * group commit pageout in progress
-	 */
-	if ((!(log->cflag & logGC_PAGEOUT)) && log->cqueue.head) {
+
+	if ((!(log->cflag & logGC_PAGEOUT)) && log->cqueue.head &&
+	    (!(tblk->xflag & COMMIT_LAZY) || test_bit(log_FLUSH, &log->flag))) {
 		/*
-		 * only transaction in the commit queue:
+		 * No pageout in progress
 		 *
-		 * start one-transaction group commit as
-		 * its group leader.
+		 * start group commit as its group leader.
 		 */
 		log->cflag |= logGC_PAGEOUT;
 
 		lmGCwrite(log, 0);
 	}
+
+	if (tblk->xflag & COMMIT_LAZY) {
+		/*
+		 * Lazy transactions can leave now
+		 */
+		LOGGC_UNLOCK(log);
+		return 0;
+	}
+
 	/* lmGCwrite gives up LOGGC_LOCK, check again */
 
 	if (tblk->flag & tblkGC_COMMITTED) {
@@ -894,11 +895,8 @@
 	 * the first transaction entering group commit
 	 * will elect herself as new group leader.
 	 */
-	else {
+	else
 		log->cflag &= ~logGC_PAGEOUT;
-		clear_bit(log_FLUSH, &log->flag);
-		WARN_ON(log->flush_tblk);
-	}
 
 	//LOGGC_UNLOCK(log);
 	spin_unlock_irqrestore(&log->gclock, flags);
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	Mon Feb 17 10:08:54 2003
+++ b/fs/jfs/jfs_txnmgr.c	Mon Mar 10 10:31:45 2003
@@ -518,22 +518,24 @@
 	/*
 	 * mark the tblock not active
 	 */
-	--log->active;
+	if (--log->active == 0) {
+		clear_bit(log_FLUSH, &log->flag);
 
-	/*
-	 * synchronize with logsync barrier
-	 */
-	if (test_bit(log_SYNCBARRIER, &log->flag) && log->active == 0) {
-		/* forward log syncpt */
-		/* lmSync(log); */
+		/*
+		 * synchronize with logsync barrier
+		 */
+		if (test_bit(log_SYNCBARRIER, &log->flag)) {
+			/* forward log syncpt */
+			/* lmSync(log); */
 
-		jfs_info("     log barrier off: 0x%x", log->lsn);
+			jfs_info("log barrier off: 0x%x", log->lsn);
 
-		/* enable new transactions start */
-		clear_bit(log_SYNCBARRIER, &log->flag);
+			/* enable new transactions start */
+			clear_bit(log_SYNCBARRIER, &log->flag);
 
-		/* wakeup all waitors for logsync barrier */
-		TXN_WAKEUP(&log->syncwait);
+			/* wakeup all waitors for logsync barrier */
+			TXN_WAKEUP(&log->syncwait);
+		}
 	}
 
 	/*
diff -Nru a/fs/lockd/svclock.c b/fs/lockd/svclock.c
--- a/fs/lockd/svclock.c	Sat Sep  7 22:07:43 2002
+++ b/fs/lockd/svclock.c	Tue Mar 11 20:03:18 2003
@@ -305,8 +305,6 @@
 				(long long)lock->fl.fl_end,
 				wait);
 
-	/* Lock file against concurrent access */
-	down(&file->f_sema);
 
 	/* Get existing block (in case client is busy-waiting) */
 	block = nlmsvc_lookup_block(file, lock, 0);
@@ -314,6 +312,9 @@
 	lock->fl.fl_flags |= FL_LOCKD;
 
 again:
+	/* Lock file against concurrent access */
+	down(&file->f_sema);
+
 	if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) {
 		error = posix_lock_file(&file->f_file, &lock->fl);
 
@@ -346,7 +347,10 @@
 
 	/* If we don't have a block, create and initialize it. Then
 	 * retry because we may have slept in kmalloc. */
+	/* We have to release f_sema as nlmsvc_create_block may try to
+	 * to claim it while doing host garbage collection */
 	if (block == NULL) {
+		up(&file->f_sema);
 		dprintk("lockd: blocking on this lock (allocating).\n");
 		if (!(block = nlmsvc_create_block(rqstp, file, lock, cookie)))
 			return nlm_lck_denied_nolocks;
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Thu Feb 13 09:25:01 2003
+++ b/fs/locks.c	Mon Mar 10 12:09:00 2003
@@ -107,22 +107,22 @@
  *  Use slab allocator instead of kmalloc/kfree.
  *  Use generic list implementation from <linux/list.h>.
  *  Sped up posix_locks_deadlock by only considering blocked locks.
- *  Matthew Wilcox <willy@thepuffingroup.com>, March, 2000.
+ *  Matthew Wilcox <willy@debian.org>, March, 2000.
  *
  *  Leases and LOCK_MAND
- *  Matthew Wilcox <willy@linuxcare.com>, June, 2000.
+ *  Matthew Wilcox <willy@debian.org>, June, 2000.
  *  Stephen Rothwell <sfr@canb.auug.org.au>, June, 2000.
  */
 
-#include <linux/slab.h>
-#include <linux/file.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
 #include <linux/capability.h>
-#include <linux/timer.h>
-#include <linux/time.h>
+#include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/security.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/time.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -143,15 +143,9 @@
 static kmem_cache_t *filelock_cache;
 
 /* Allocate an empty lock structure. */
-static struct file_lock *locks_alloc_lock(int account)
+static struct file_lock *locks_alloc_lock(void)
 {
-	struct file_lock *fl;
-	if (account && current->locks >= current->rlim[RLIMIT_LOCKS].rlim_cur)
-		return NULL;
-	fl = kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
-	if (fl)
-		current->locks++;
-	return fl;
+	return kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
 }
 
 /* Free a lock which is not in use. */
@@ -161,7 +155,6 @@
 		BUG();
 		return;
 	}
-	current->locks--;
 	if (waitqueue_active(&fl->fl_wait))
 		panic("Attempting to free lock with active wait queue");
 
@@ -248,7 +241,7 @@
 	if (type < 0)
 		return type;
 	
-	fl = locks_alloc_lock(1);
+	fl = locks_alloc_lock();
 	if (fl == NULL)
 		return -ENOMEM;
 
@@ -382,7 +375,7 @@
 /* Allocate a file_lock initialised to this type of lease */
 static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
 {
-	struct file_lock *fl = locks_alloc_lock(1);
+	struct file_lock *fl = locks_alloc_lock();
 	if (fl == NULL)
 		return -ENOMEM;
 
@@ -427,13 +420,22 @@
 /* Remove waiter from blocker's block list.
  * When blocker ends up pointing to itself then the list is empty.
  */
-static void locks_delete_block(struct file_lock *waiter)
+static inline void __locks_delete_block(struct file_lock *waiter)
 {
 	list_del_init(&waiter->fl_block);
 	list_del_init(&waiter->fl_link);
 	waiter->fl_next = NULL;
 }
 
+/*
+ */
+static void locks_delete_block(struct file_lock *waiter)
+{
+	lock_kernel();
+	__locks_delete_block(waiter);
+	unlock_kernel();
+}
+
 /* Insert waiter into blocker's block list.
  * We use a circular list so that processes can be easily woken up in
  * the order they blocked. The documentation doesn't require this but
@@ -446,7 +448,7 @@
 		printk(KERN_ERR "locks_insert_block: removing duplicated lock "
 			"(pid=%d %Ld-%Ld type=%d)\n", waiter->fl_pid,
 			waiter->fl_start, waiter->fl_end, waiter->fl_type);
-		locks_delete_block(waiter);
+		__locks_delete_block(waiter);
 	}
 	list_add_tail(&waiter->fl_block, &blocker->fl_block);
 	waiter->fl_next = blocker;
@@ -462,7 +464,7 @@
 	while (!list_empty(&blocker->fl_block)) {
 		struct file_lock *waiter = list_entry(blocker->fl_block.next,
 				struct file_lock, fl_block);
-		locks_delete_block(waiter);
+		__locks_delete_block(waiter);
 		if (waiter->fl_notify)
 			waiter->fl_notify(waiter);
 		else
@@ -517,19 +519,11 @@
  */
 static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
 {
-	switch (caller_fl->fl_type) {
-	case F_RDLCK:
-		return (sys_fl->fl_type == F_WRLCK);
-
-	case F_WRLCK:
-		return (1);
-
-	default:
-		printk(KERN_ERR "locks_conflict(): impossible lock type - %d\n",
-		       caller_fl->fl_type);
-		break;
-	}
-	return (0);	/* This should never happen */
+	if (sys_fl->fl_type == F_WRLCK)
+		return 1;
+	if (caller_fl->fl_type == F_WRLCK)
+		return 1;
+	return 0;
 }
 
 /* Determine if lock sys_fl blocks lock caller_fl. POSIX specific
@@ -589,7 +583,7 @@
 	int result;
 	locks_insert_block(blocker, waiter);
 	result = interruptible_sleep_on_locked(&waiter->fl_wait, time);
-	locks_delete_block(waiter);
+	__locks_delete_block(waiter);
 	return result;
 }
 
@@ -726,8 +720,8 @@
 	 * We may need two file_lock structures for this operation,
 	 * so we get them in advance to avoid races.
 	 */
-	new_fl = locks_alloc_lock(0);
-	new_fl2 = locks_alloc_lock(0);
+	new_fl = locks_alloc_lock();
+	new_fl2 = locks_alloc_lock();
 
 	lock_kernel();
 	if (request->fl_type != F_UNLCK) {
@@ -977,9 +971,7 @@
 				continue;
 		}
 
-		lock_kernel();
 		locks_delete_block(&fl);
-		unlock_kernel();
 		break;
 	}
 
@@ -1332,9 +1324,7 @@
 		if (!error)
 			continue;
 
-		lock_kernel();
 		locks_delete_block(lock);
-		unlock_kernel();
 		break;
 	}
 
@@ -1416,7 +1406,7 @@
  */
 int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
 {
-	struct file_lock *file_lock = locks_alloc_lock(0);
+	struct file_lock *file_lock = locks_alloc_lock();
 	struct flock flock;
 	struct inode *inode;
 	int error;
@@ -1489,9 +1479,7 @@
 		if (!error)
 			continue;
 
-		lock_kernel();
 		locks_delete_block(file_lock);
-		unlock_kernel();
 		break;
 	}
 
@@ -1556,7 +1544,7 @@
  */
 int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 *l)
 {
-	struct file_lock *file_lock = locks_alloc_lock(0);
+	struct file_lock *file_lock = locks_alloc_lock();
 	struct flock64 flock;
 	struct inode *inode;
 	int error;
@@ -1629,9 +1617,7 @@
 		if (!error)
 			continue;
 
-		lock_kernel();
 		locks_delete_block(file_lock);
-		unlock_kernel();
 		break;
 	}
 
@@ -1648,14 +1634,15 @@
  */
 void locks_remove_posix(struct file *filp, fl_owner_t owner)
 {
-	struct file_lock lock;
+	struct file_lock lock, **before;
 
 	/*
 	 * If there are no locks held on this file, we don't need to call
 	 * posix_lock_file().  Another process could be setting a lock on this
 	 * file at the same time, but we wouldn't remove that lock anyway.
 	 */
-	if (!filp->f_dentry->d_inode->i_flock)
+	before = &filp->f_dentry->d_inode->i_flock;
+	if (*before == NULL)
 		return;
 
 	lock.fl_type = F_UNLCK;
@@ -1671,7 +1658,19 @@
 		/* Ignore any error -- we must remove the locks anyway */
 	}
 
-	posix_lock_file(filp, &lock);
+	/* Can't use posix_lock_file here; we need to remove it no matter
+	 * which pid we have.
+	 */
+	lock_kernel();
+	while (*before != NULL) {
+		struct file_lock *fl = *before;
+		if (IS_POSIX(fl) && (fl->fl_owner == owner)) {
+			locks_delete_lock(before);
+			continue;
+		}
+		before = &fl->fl_next;
+	}
+	unlock_kernel();
 }
 
 /*
@@ -1699,6 +1698,7 @@
 				lease_modify(before, F_UNLCK);
 				continue;
 			}
+			BUG();
  		}
 		before = &fl->fl_next;
 	}
@@ -1733,7 +1733,7 @@
 	 */
 	lock_kernel();
 	if (waiter->fl_next) {
-		locks_delete_block(waiter);
+		__locks_delete_block(waiter);
 		unlock_kernel();
 	} else {
 		unlock_kernel();
@@ -1785,19 +1785,19 @@
 			       ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ "
 			       : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ ");
 	}
-#if WE_CAN_BREAK_LSLK_NOW
 	if (inode) {
+#if WE_CAN_BREAK_LSLK_NOW
 		out += sprintf(out, "%d %s:%ld ", fl->fl_pid,
 				inode->i_sb->s_id, inode->i_ino);
+#else
+		/* userspace relies on this representation of dev_t ;-( */
+		out += sprintf(out, "%d %02x:%02x:%ld ", fl->fl_pid,
+				MAJOR(inode->i_sb->s_dev),
+				MINOR(inode->i_sb->s_dev), inode->i_ino);
+#endif
 	} else {
 		out += sprintf(out, "%d <none>:0 ", fl->fl_pid);
 	}
-#else
-	/* kdevname is a broken interface.  but we expose it to userspace */
-	out += sprintf(out, "%d %s:%ld ", fl->fl_pid,
-			inode ? kdevname(to_kdev_t(inode->i_sb->s_dev)) : "<none>",
-			inode ? inode->i_ino : 0);
-#endif
 	if (IS_POSIX(fl)) {
 		if (fl->fl_end == OFFSET_MAX)
 			out += sprintf(out, "%Ld EOF\n", fl->fl_start);
@@ -1958,3 +1958,13 @@
 }
 
 module_init(filelock_init)
+
+EXPORT_SYMBOL(file_lock_list);
+EXPORT_SYMBOL(locks_init_lock);
+EXPORT_SYMBOL(locks_copy_lock);
+EXPORT_SYMBOL(posix_lock_file);
+EXPORT_SYMBOL(posix_test_lock);
+EXPORT_SYMBOL(posix_block_lock);
+EXPORT_SYMBOL(posix_unblock_lock);
+EXPORT_SYMBOL(posix_locks_deadlock);
+EXPORT_SYMBOL(locks_mandatory_area);
diff -Nru a/fs/mbcache.c b/fs/mbcache.c
--- a/fs/mbcache.c	Thu Nov 14 14:03:01 2002
+++ b/fs/mbcache.c	Sat Mar  8 14:50:42 2003
@@ -433,6 +433,7 @@
 		list_add(&ce->e_indexes[n].o_list,
 			 &cache->c_indexes_hash[n][bucket]);
 	}
+	error = 0;
 out:
 	spin_unlock(&mb_cache_spinlock);
 	return error;
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Fri Feb 14 18:23:59 2003
+++ b/fs/namei.c	Wed Mar 12 11:10:29 2003
@@ -342,8 +342,18 @@
 	 *
 	 * FIXME! This could use version numbering or similar to
 	 * avoid unnecessary cache lookups.
+	 *
+	 * The "dcache_lock" is purely to protect the RCU list walker
+	 * from concurrent renames at this point (we mustn't get false
+	 * negatives from the RCU list walk here, unlike the optimistic
+	 * fast walk).
+	 *
+	 * We really should do a sequence number thing to avoid this
+	 * all.
 	 */
+	spin_lock(&dcache_lock);
 	result = d_lookup(parent, name);
+	spin_unlock(&dcache_lock);
 	if (!result) {
 		struct dentry * dentry = d_alloc(parent, name);
 		result = ERR_PTR(-ENOMEM);
@@ -351,10 +361,8 @@
 			result = dir->i_op->lookup(dir, dentry);
 			if (result)
 				dput(dentry);
-			else {
+			else
 				result = dentry;
-				security_inode_post_lookup(dir, result);
-			}
 		}
 		up(&dir->i_sem);
 		return result;
@@ -388,10 +396,7 @@
 		goto loop;
 	if (current->total_link_count >= 40)
 		goto loop;
-	if (need_resched()) {
-		current->state = TASK_RUNNING;
-		schedule();
-	}
+	cond_resched();
 	err = security_inode_follow_link(dentry, nd);
 	if (err)
 		goto loop;
@@ -887,10 +892,9 @@
 		if (!new)
 			goto out;
 		dentry = inode->i_op->lookup(inode, new);
-		if (!dentry) {
+		if (!dentry)
 			dentry = new;
-			security_inode_post_lookup(inode, dentry);
-		} else
+		else
 			dput(new);
 	}
 out:
diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
--- a/fs/ncpfs/ioctl.c	Fri Sep 20 11:13:41 2002
+++ b/fs/ncpfs/ioctl.c	Mon Mar 10 22:34:29 2003
@@ -440,7 +440,7 @@
 			oldprivatelen = server->priv.len;
 			server->auth.auth_type = user.auth_type;
 			server->auth.object_name_len = user.object_name_len;
-			server->auth.object_name = user.object_name;
+			server->auth.object_name = newname;
 			server->priv.len = 0;
 			server->priv.data = NULL;
 			/* leave critical section */
diff -Nru a/fs/nfs/file.c b/fs/nfs/file.c
--- a/fs/nfs/file.c	Wed Dec 18 09:37:07 2002
+++ b/fs/nfs/file.c	Sat Mar  8 14:50:27 2003
@@ -35,6 +35,7 @@
 #define NFSDBG_FACILITY		NFSDBG_FILE
 
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
+static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 static ssize_t nfs_file_read(struct kiocb *, char *, size_t, loff_t);
 static ssize_t nfs_file_write(struct kiocb *, const char *, size_t, loff_t);
 static int  nfs_file_flush(struct file *);
@@ -52,6 +53,7 @@
 	.release	= nfs_release,
 	.fsync		= nfs_fsync,
 	.lock		= nfs_lock,
+	.sendfile	= nfs_file_sendfile,
 };
 
 struct inode_operations nfs_file_inode_operations = {
@@ -100,6 +102,24 @@
 	if (!result)
 		result = generic_file_aio_read(iocb, buf, count, pos);
 	return result;
+}
+
+static ssize_t
+nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
+		read_actor_t actor, void *target)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct inode *inode = dentry->d_inode;
+	ssize_t res;
+
+	dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name,
+		(unsigned long) count, (unsigned long long) *ppos);
+
+	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (!res)
+		res = generic_file_sendfile(filp, ppos, count, actor, target);
+	return res;
 }
 
 static int
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	Tue Feb 25 02:08:50 2003
+++ b/fs/nfsd/export.c	Tue Mar 11 20:07:11 2003
@@ -294,7 +294,9 @@
 
 	/* client */
 	len = qword_get(&mesg, buf, PAGE_SIZE);
-	if (len <= 0) return -EINVAL;
+	err = -EINVAL;
+	if (len <= 0) goto out;
+
 	err = -ENOENT;
 	dom = auth_domain_find(buf);
 	if (!dom)
@@ -473,8 +475,14 @@
 
 	exp = svc_export_lookup(&key, 0);
 	if (exp != NULL) 
-		if (cache_check(&svc_export_cache, &exp->h, reqp))
+		switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
+		case 0: break;
+		case -EAGAIN:
+			exp = ERR_PTR(-EAGAIN);
+			break;
+		default:
 			exp = NULL;
+		}
 
 	return exp;
 }
@@ -915,7 +923,8 @@
 	{ NFSEXP_UIDMAP, {"uidmap", ""}},
 	{ NFSEXP_KERBEROS, { "kerberos", ""}},
 	{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
-	{ NFSEXP_CROSSMNT, {"nohide", ""}},
+	{ NFSEXP_NOHIDE, {"nohide", ""}},
+	{ NFSEXP_CROSSMNT, {"crossmnt", ""}},
 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
 	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
 #ifdef MSNFS
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Fri Jan 10 17:00:12 2003
+++ b/fs/nfsd/vfs.c	Sat Mar 15 20:55:43 2003
@@ -79,7 +79,7 @@
  * N.B. After this call _both_ fhp and resfh need an fh_put
  *
  * If the lookup would cross a mountpoint, and the mounted filesystem
- * is exported to the client with NFSEXP_CROSSMNT, then the lookup is
+ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
  * accepted as it stands and the mounted directory is
  * returned. Otherwise the covered directory is returned.
  * NOTE: this mountpoint crossing is not supported properly by all
@@ -115,7 +115,7 @@
 			read_lock(&dparent_lock);
 			dentry = dget(dparent->d_parent);
 			read_unlock(&dparent_lock);
-		} else  if (!EX_CROSSMNT(exp))
+		} else  if (!EX_NOHIDE(exp))
 			dentry = dget(dparent); /* .. == . just like at / */
 		else {
 			/* checking mountpoint crossing is very different when stepping up */
@@ -133,6 +133,12 @@
 
 			exp2 = exp_parent(exp->ex_client, mnt, dentry,
 					  &rqstp->rq_chandle);
+			if (IS_ERR(exp2)) {
+				err = PTR_ERR(exp2);
+				dput(dentry);
+				mntput(mnt);
+				goto out;
+			}
 			if (!exp2) {
 				dput(dentry);
 				dentry = dget(dparent);
@@ -157,9 +163,19 @@
 			struct dentry *mounts = dget(dentry);
 			while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts))
 				;
+
 			exp2 = exp_get_by_name(exp->ex_client, mnt, 
 					       mounts, &rqstp->rq_chandle);
-			if (exp2 && EX_CROSSMNT(exp2)) {
+			if (IS_ERR(exp2)) {
+				err = PTR_ERR(exp2);
+				dput(mounts);
+				dput(dentry);
+				mntput(mnt);
+				goto out;
+			}
+			if (exp2 &&
+			    ((exp->ex_flags & NFSEXP_CROSSMNT)
+			     || EX_NOHIDE(exp2))) {
 				/* successfully crossed mount point */
 				exp_put(exp);
 				exp = exp2;
@@ -426,7 +442,7 @@
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
-	int		flags = O_RDONLY|O_LARGEFILE, mode = FMODE_READ, err;
+	int		flags = O_RDONLY|O_LARGEFILE, err;
 
 	/*
 	 * If we get here, then the client has already done an "open",
@@ -463,14 +479,12 @@
 			goto out_nfserr;
 
 		flags = O_WRONLY|O_LARGEFILE;
-		mode  = FMODE_WRITE;
 
 		DQUOT_INIT(inode);
 	}
 
-	err = init_private_file(filp, dentry, mode);
+	err = open_private_file(filp, dentry, flags);
 	if (!err) {
-		filp->f_flags = flags;
 		filp->f_vfsmnt = fhp->fh_export->ex_mnt;
 	} else if (access & MAY_WRITE)
 		put_write_access(inode);
@@ -491,8 +505,7 @@
 	struct dentry	*dentry = filp->f_dentry;
 	struct inode	*inode = dentry->d_inode;
 
-	if (filp->f_op->release)
-		filp->f_op->release(inode, filp);
+	close_private_file(filp);
 	if (filp->f_mode & FMODE_WRITE)
 		put_write_access(inode);
 }
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Mon Feb 10 23:22:51 2003
+++ b/fs/partitions/check.c	Sat Mar  8 14:50:30 2003
@@ -503,13 +503,7 @@
 	disk->capacity = 0;
 	disk->flags &= ~GENHD_FL_UP;
 	unlink_gendisk(disk);
-	disk->reads = disk->writes = 0;
-	disk->read_sectors = disk->write_sectors = 0;
-	disk->read_merges = disk->write_merges = 0;
-	disk->read_ticks = disk->write_ticks = 0;
-	disk->in_flight = 0;
-	disk->io_ticks = 0;
-	disk->time_in_queue = 0;
+	disk_stat_set_all(disk, 0);
 	disk->stamp = disk->stamp_idle = 0;
 	devfs_remove_partitions(disk);
 	if (disk->driverfs_dev) {
diff -Nru a/fs/partitions/ldm.c b/fs/partitions/ldm.c
--- a/fs/partitions/ldm.c	Fri Feb  7 00:20:33 2003
+++ b/fs/partitions/ldm.c	Mon Mar 10 22:34:29 2003
@@ -1162,8 +1162,10 @@
 		return FALSE;
 	}
 
-	if (!ldm_parse_vblk (data, len, vb))
+	if (!ldm_parse_vblk (data, len, vb)) {
+		kfree(vb);
 		return FALSE;			/* Already logged */
+	}
 
 	/* Put vblk into the correct list. */
 	switch (vb->type) {
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Mon Feb 24 23:13:09 2003
+++ b/fs/proc/proc_misc.c	Sat Mar  8 14:50:46 2003
@@ -389,11 +389,7 @@
 extern int show_interrupts(struct seq_file *p, void *v);
 static int interrupts_open(struct inode *inode, struct file *file)
 {
-	unsigned size = PAGE_SIZE;
-	/*
-	 * probably should depend on NR_CPUS, but that's only rough estimate;
-	 * if we'll need more it will be given,
-	 */
+	unsigned size = PAGE_SIZE * (1 + NR_CPUS / 8);
 	char *buf = kmalloc(size, GFP_KERNEL);
 	struct seq_file *m;
 	int res;
diff -Nru a/fs/readdir.c b/fs/readdir.c
--- a/fs/readdir.c	Sun Jan  5 07:28:41 2003
+++ b/fs/readdir.c	Sat Mar  8 14:50:39 2003
@@ -72,11 +72,16 @@
 		return -EINVAL;
 	buf->count++;
 	dirent = buf->dirent;
-	put_user(ino, &dirent->d_ino);
-	put_user(offset, &dirent->d_offset);
-	put_user(namlen, &dirent->d_namlen);
-	copy_to_user(dirent->d_name, name, namlen);
-	put_user(0, dirent->d_name + namlen);
+	if (!access_ok(VERIFY_WRITE, (unsigned long)dirent,
+			(unsigned long)(dirent->d_name + namlen + 1) -
+				(unsigned long)dirent))
+		return -EFAULT;
+	if (	__put_user(ino, &dirent->d_ino) ||
+		__put_user(offset, &dirent->d_offset) ||
+		__put_user(namlen, &dirent->d_namlen) ||
+		__copy_to_user(dirent->d_name, name, namlen) ||
+		__put_user(0, dirent->d_name + namlen))
+		return -EFAULT;
 	return 0;
 }
 
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	Mon Feb  3 05:47:46 2003
+++ b/fs/reiserfs/journal.c	Fri Mar 14 08:16:39 2003
@@ -1310,6 +1310,10 @@
   if (SB_JOURNAL(p_s_sb)->j_header_bh) {
     brelse(SB_JOURNAL(p_s_sb)->j_header_bh) ;
   }
+  /* j_header_bh is on the journal dev, make sure not to release the journal
+   * dev until we brelse j_header_bh
+   */
+  release_journal_dev(p_s_sb, SB_JOURNAL(p_s_sb));
   vfree(SB_JOURNAL(p_s_sb)) ;
 }
 
@@ -1341,7 +1345,6 @@
     commit_wq = NULL;
   }
 
-  release_journal_dev( p_s_sb, SB_JOURNAL( p_s_sb ) );
   free_journal_ram(p_s_sb) ;
 
   return 0 ;
@@ -1867,24 +1870,18 @@
     int result;
     
     result = 0;
-	
 
     if( journal -> j_dev_file != NULL ) {
-	/*
-	 * journal block device was taken via filp_open
-	 */
 	result = filp_close( journal -> j_dev_file, NULL );
 	journal -> j_dev_file = NULL;
 	journal -> j_dev_bd = NULL;
     } else if( journal -> j_dev_bd != NULL ) {
-	/*
-	 * journal block device was taken via bdget and blkdev_get
-	 */
 	result = blkdev_put( journal -> j_dev_bd, BDEV_FS );
 	journal -> j_dev_bd = NULL;
     }
+
     if( result != 0 ) {
-	reiserfs_warning("sh-457: release_journal_dev: Cannot release journal device: %i", result );
+	reiserfs_warning("sh-457: release_journal_dev: Cannot release journal device: %i\n", result );
     }
     return result;
 }
@@ -1895,6 +1892,7 @@
 {
 	int result;
 	dev_t jdev;
+	int blkdev_mode = FMODE_READ | FMODE_WRITE;
 
 	result = 0;
 
@@ -1902,12 +1900,16 @@
 	journal -> j_dev_file = NULL;
 	jdev = SB_ONDISK_JOURNAL_DEVICE( super ) ?
 		SB_ONDISK_JOURNAL_DEVICE( super ) : super->s_dev;	
+
+	if (bdev_read_only(super->s_bdev))
+	    blkdev_mode = FMODE_READ;
+
 	/* there is no "jdev" option and journal is on separate device */
 	if( ( !jdev_name || !jdev_name[ 0 ] ) ) {
 		journal -> j_dev_bd = bdget(jdev);
 		if( journal -> j_dev_bd )
 			result = blkdev_get( journal -> j_dev_bd, 
-					     FMODE_READ | FMODE_WRITE, 0, 
+					     blkdev_mode, 0, 
 					     BDEV_FS );
 		else
 			result = -ENOMEM;
@@ -1928,10 +1930,10 @@
 		jdev_inode = journal -> j_dev_file -> f_dentry -> d_inode;
 		journal -> j_dev_bd = jdev_inode -> i_bdev;
 		if( !S_ISBLK( jdev_inode -> i_mode ) ) {
-			printk( "journal_init_dev: '%s' is not a block device", jdev_name );
+			printk( "journal_init_dev: '%s' is not a block device\n", jdev_name );
 			result = -ENOTBLK;
 		} else if( jdev_inode -> i_bdev == NULL ) {
-			printk( "journal_init_dev: bdev uninitialized for '%s'", jdev_name );
+			printk( "journal_init_dev: bdev uninitialized for '%s'\n", jdev_name );
 			result = -ENOMEM;
 		} else  {
 			/* ok */
@@ -1941,12 +1943,12 @@
 	} else {
 		result = PTR_ERR( journal -> j_dev_file );
 		journal -> j_dev_file = NULL;
-		printk( "journal_init_dev: Cannot open '%s': %i", jdev_name, result );
+		printk( "journal_init_dev: Cannot open '%s': %i\n", jdev_name, result );
 	}
 	if( result != 0 ) {
 		release_journal_dev( super, journal );
 	}
-	printk( "journal_init_dev: journal device: %s", bdevname(journal->j_dev_bd));
+	printk( "journal_init_dev: journal device: %s\n", bdevname(journal->j_dev_bd));
 	return result;
 }
 
@@ -1960,20 +1962,24 @@
     struct reiserfs_journal_header *jh;
     struct reiserfs_journal *journal;
 
-  if (sizeof(struct reiserfs_journal_commit) != 4096 ||
-      sizeof(struct reiserfs_journal_desc) != 4096
-     ) {
-    printk("journal-1249: commit or desc struct not 4096 %Zd %Zd\n", sizeof(struct reiserfs_journal_commit), 
+    if (sizeof(struct reiserfs_journal_commit) != 4096 ||
+      sizeof(struct reiserfs_journal_desc) != 4096) {
+	printk("journal-1249: commit or desc struct not 4096 %Zd %Zd\n", sizeof(struct reiserfs_journal_commit), 
         sizeof(struct reiserfs_journal_desc)) ;
-    return 1 ;
-  }
+	return 1 ;
+    }
 
     journal = SB_JOURNAL(p_s_sb) = vmalloc(sizeof (struct reiserfs_journal)) ;
     if (!journal) {
 	printk("journal-1256: unable to get memory for journal structure\n") ;
-    return 1 ;
-  }
+	return 1 ;
+    }
     memset(journal, 0, sizeof(struct reiserfs_journal)) ;
+    INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_bitmap_nodes) ;
+    INIT_LIST_HEAD (&SB_JOURNAL(p_s_sb)->j_prealloc_list);
+    reiserfs_allocate_list_bitmaps(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_bitmap, 
+ 				   SB_BMAP_NR(p_s_sb)) ;
+    allocate_bitmap_nodes(p_s_sb) ;
 
     /* reserved for journal area support */
     SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) = (old_format ?
@@ -1983,7 +1989,7 @@
     
     if( journal_init_dev( p_s_sb, journal, j_dev_name ) != 0 ) {
       printk( "sh-462: unable to initialize jornal device\n");
-      return 1;
+      goto free_and_return;
     }
 
      rs = SB_DISK_SUPER_BLOCK(p_s_sb);
@@ -1993,8 +1999,7 @@
 		   SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + SB_ONDISK_JOURNAL_SIZE(p_s_sb));
      if (!bhjh) {
 	 printk("sh-459: unable to read  journal header\n") ;
-	 release_journal_dev(p_s_sb, journal);
-	 return 1 ;
+	 goto free_and_return;
      }
      jh = (struct reiserfs_journal_header *)(bhjh->b_data);
      
@@ -2005,8 +2010,7 @@
 		jh->jh_journal.jp_journal_magic, bdevname( SB_JOURNAL(p_s_sb)->j_dev_bd ),
 		sb_jp_journal_magic(rs), reiserfs_bdevname (p_s_sb));
 	 brelse (bhjh);
-	 release_journal_dev(p_s_sb, journal);
-	 return 1 ;
+	 goto free_and_return;
   }
      
   SB_JOURNAL_TRANS_MAX(p_s_sb)      = le32_to_cpu (jh->jh_journal.jp_journal_trans_max);
@@ -2064,7 +2068,6 @@
 
   brelse (bhjh);
      
-
   SB_JOURNAL(p_s_sb)->j_list_bitmap_index = 0 ;
   SB_JOURNAL_LIST_INDEX(p_s_sb) = -10000 ; /* make sure flush_old_commits does not try to flush a list while replay is on */
 
@@ -2075,12 +2078,8 @@
   memset(SB_JOURNAL(p_s_sb)->j_list_hash_table, 0, JOURNAL_HASH_SIZE * sizeof(struct reiserfs_journal_cnode *)) ;
   memset(journal_writers, 0, sizeof(char *) * 512) ; /* debug code */
 
-  INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_bitmap_nodes) ;
   INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_dirty_buffers) ;
   spin_lock_init(&SB_JOURNAL(p_s_sb)->j_dirty_buffers_lock) ;
-  reiserfs_allocate_list_bitmaps(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_bitmap, 
-                                 SB_BMAP_NR(p_s_sb)) ;
-  allocate_bitmap_nodes(p_s_sb) ;
 
   SB_JOURNAL(p_s_sb)->j_start = 0 ;
   SB_JOURNAL(p_s_sb)->j_len = 0 ;
@@ -2107,20 +2106,15 @@
   SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap = get_list_bitmap(p_s_sb, SB_JOURNAL_LIST(p_s_sb)) ;
   if (!(SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap)) {
     reiserfs_warning("journal-2005, get_list_bitmap failed for journal list 0\n") ;
-    release_journal_dev(p_s_sb, journal);
-    return 1 ;
+    goto free_and_return;
   }
   if (journal_read(p_s_sb) < 0) {
     reiserfs_warning("Replay Failure, unable to mount\n") ;
-    free_journal_ram(p_s_sb) ;
-    release_journal_dev(p_s_sb, journal);
-    return 1 ;
+    goto free_and_return;
   }
   SB_JOURNAL_LIST_INDEX(p_s_sb) = 0 ; /* once the read is done, we can set this
                                          where it belongs */
 
-  INIT_LIST_HEAD (&SB_JOURNAL(p_s_sb)->j_prealloc_list);
-
   if (reiserfs_dont_log (p_s_sb))
     return 0;
 
@@ -2129,7 +2123,9 @@
     commit_wq = create_workqueue("reiserfs");
 
   return 0 ;
-
+free_and_return:
+  free_journal_ram(p_s_sb);
+  return 1;
 }
 
 /*
diff -Nru a/fs/seq_file.c b/fs/seq_file.c
--- a/fs/seq_file.c	Mon Feb 24 10:22:56 2003
+++ b/fs/seq_file.c	Fri Mar 14 15:22:12 2003
@@ -1,7 +1,7 @@
 /*
  * linux/fs/seq_file.c
  *
- * helper functions for making syntetic files from sequences of records.
+ * helper functions for making synthetic files from sequences of records.
  * initial implementation -- AV, Oct 2001.
  */
 
@@ -215,7 +215,7 @@
 				while ((retval=traverse(m, offset)) == -EAGAIN)
 					;
 				if (retval) {
-					/* with extreme perjudice... */
+					/* with extreme prejudice... */
 					file->f_pos = 0;
 					m->index = 0;
 					m->count = 0;
diff -Nru a/fs/smbfs/sock.c b/fs/smbfs/sock.c
--- a/fs/smbfs/sock.c	Sun Nov 17 12:38:34 2002
+++ b/fs/smbfs/sock.c	Thu Mar  6 11:06:44 2003
@@ -41,8 +41,6 @@
 {
 	struct iovec iov;
 	struct msghdr msg;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	mm_segment_t fs;
 
 	fs = get_fs();
@@ -58,21 +56,7 @@
 	iov.iov_base = ubuf;
 	iov.iov_len = size;
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->sock = socket;
-	si->scm = &si->async_scm;
-	si->msg = &msg;
-	si->size = size;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	size = socket->ops->recvmsg(&iocb, socket, &msg, size, flags, si->scm);
-	if (size >= 0)
-		scm_recv(socket, &msg, si->scm, flags);
-	if (-EIOCBQUEUED == size)
-		size = wait_on_sync_kiocb(&iocb);
+	size = sock_recvmsg(socket, &msg, size, flags);
 
 	set_fs(fs);
 	return size;
@@ -299,8 +283,6 @@
 	unsigned int flags;
 	struct iovec iov;
 	struct msghdr msg;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	mm_segment_t fs;
 	int rlen = smb_len(server->header) - server->smb_read + 4;
 	int result = -EIO;
@@ -327,21 +309,7 @@
 	if (rlen > PAGE_SIZE)
 		rlen = PAGE_SIZE;
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->msg = &msg;
-	si->size = rlen;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm);
-	if (result >= 0)
-		scm_recv(sock, &msg, si->scm, flags);
-	if (-EIOCBQUEUED == result)
-		result = wait_on_sync_kiocb(&iocb);
+	result = sock_recvmsg(sock, &msg, rlen, flags);
 
 	set_fs(fs);
 
@@ -370,8 +338,6 @@
 	unsigned int flags;
 	struct iovec iov[4];
 	struct msghdr msg;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	mm_segment_t fs;
 	int rlen;
 	int result = -EIO;
@@ -398,21 +364,7 @@
 	if (req->rq_rlen < rlen)
 		rlen = req->rq_rlen;
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->msg = &msg;
-	si->size = rlen;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm);
-	if (result >= 0)
-		scm_recv(sock, &msg, si->scm, flags);
-	if (-EIOCBQUEUED == result)
-		result = wait_on_sync_kiocb(&iocb);
+	result = sock_recvmsg(sock, &msg, rlen, flags);
 
 	set_fs(fs);
 
@@ -440,8 +392,6 @@
 	mm_segment_t fs;
 	struct smb_sb_info *server = req->rq_server;
 	struct socket *sock;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct msghdr msg;
         int slen = req->rq_slen - req->rq_bytes_sent;
 	int result = -EIO;
@@ -465,23 +415,9 @@
 	if (req->rq_bytes_sent)
 		smb_move_iov(&msg, iov, req->rq_bytes_sent);
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = &si->async_scm;
-	si->sock = sock;
-	si->msg = &msg;
-	si->size = slen;
-
 	fs = get_fs();
 	set_fs(get_ds());
-	result = scm_send(sock, &msg, si->scm);
-	if (result >= 0) {
-		result = sock->ops->sendmsg(&iocb, sock, &msg, slen, si->scm);
-		if (-EIOCBQUEUED != result)
-			scm_destroy(si->scm);
-	}
-	if (-EIOCBQUEUED == result)
-		result = wait_on_sync_kiocb(&iocb);
+	result = sock_sendmsg(sock, &msg, slen);
 	set_fs(fs);
 
 	if (result >= 0) {
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	Tue Mar  4 05:33:19 2003
+++ b/fs/super.c	Mon Mar 10 10:49:27 2003
@@ -611,6 +611,7 @@
 	struct file_system_type *type = get_fs_type(fstype);
 	struct super_block *sb = ERR_PTR(-ENOMEM);
 	struct vfsmount *mnt;
+	int error;
 
 	if (!type)
 		return ERR_PTR(-ENODEV);
@@ -621,6 +622,9 @@
 	sb = type->get_sb(type, flags, name, data);
 	if (IS_ERR(sb))
 		goto out_mnt;
+ 	error = security_sb_kern_mount(sb);
+ 	if (error) 
+ 		goto out_sb;
 	mnt->mnt_sb = sb;
 	mnt->mnt_root = dget(sb->s_root);
 	mnt->mnt_mountpoint = sb->s_root;
@@ -628,6 +632,10 @@
 	up_write(&sb->s_umount);
 	put_filesystem(type);
 	return mnt;
+out_sb:
+	up_write(&sb->s_umount);
+	deactivate_super(sb);
+	sb = ERR_PTR(error);
 out_mnt:
 	free_vfsmnt(mnt);
 out:
diff -Nru a/fs/sysfs/bin.c b/fs/sysfs/bin.c
--- a/fs/sysfs/bin.c	Tue Mar  4 06:57:37 2003
+++ b/fs/sysfs/bin.c	Thu Mar  6 18:21:39 2003
@@ -50,6 +50,10 @@
 		ret = count;
 	}
  Done:
+	if (buffer && buffer->data) {
+		kfree(buffer->data);
+		buffer->data = NULL;
+	}
 	return ret;
 }
 
@@ -66,7 +70,7 @@
 static int fill_write(struct file * file, const char * userbuf, 
 		      struct sysfs_bin_buffer * buffer)
 {
-	return copy_from_user(buffer,userbuf,buffer->count) ?
+	return copy_from_user(buffer->data,userbuf,buffer->count) ?
 		-EFAULT : 0;
 }
 
diff -Nru a/fs/sysfs/dir.c b/fs/sysfs/dir.c
--- a/fs/sysfs/dir.c	Thu Jan 30 15:10:06 2003
+++ b/fs/sysfs/dir.c	Tue Mar 11 13:30:18 2003
@@ -71,7 +71,7 @@
 
 void sysfs_remove_dir(struct kobject * kobj)
 {
-	struct list_head * node, * next;
+	struct list_head * node;
 	struct dentry * dentry = dget(kobj->dentry);
 	struct dentry * parent;
 
@@ -83,44 +83,35 @@
 	down(&parent->d_inode->i_sem);
 	down(&dentry->d_inode->i_sem);
 
-	list_for_each_safe(node,next,&dentry->d_subdirs) {
-		struct dentry * d = dget(list_entry(node,struct dentry,d_child));
-		/** 
-		 * Make sure dentry is still there 
-		 */
-		pr_debug(" o %s: ",d->d_name.name);
-		if (d->d_inode) {
+	spin_lock(&dcache_lock);
+	node = dentry->d_subdirs.next;
+	while (node != &dentry->d_subdirs) {
+		struct dentry * d = list_entry(node,struct dentry,d_child);
+		list_del_init(node);
 
+		pr_debug(" o %s (%d): ",d->d_name.name,atomic_read(&d->d_count));
+		if (d->d_inode) {
+			d = dget_locked(d);
 			pr_debug("removing");
+
 			/**
 			 * Unlink and unhash.
 			 */
+			spin_unlock(&dcache_lock);
 			simple_unlink(dentry->d_inode,d);
-			d_delete(d);
-
-			/**
-			 * Drop reference from initial sysfs_get_dentry().
-			 */
 			dput(d);
+			spin_lock(&dcache_lock);
 		}
-		pr_debug(" done (%d)\n",atomic_read(&d->d_count));
-		/**
-		 * drop reference from dget() above.
-		 */
-		dput(d);
+		pr_debug(" done\n");
+		node = dentry->d_subdirs.next;
 	}
-
+	spin_unlock(&dcache_lock);
 	up(&dentry->d_inode->i_sem);
-	d_invalidate(dentry);
-	simple_rmdir(parent->d_inode,dentry);
 	d_delete(dentry);
+	simple_rmdir(parent->d_inode,dentry);
 
 	pr_debug(" o %s removing done (%d)\n",dentry->d_name.name,
 		 atomic_read(&dentry->d_count));
-	/**
-	 * Drop reference from initial sysfs_get_dentry().
-	 */
-	dput(dentry);
 
 	/**
 	 * Drop reference from dget() on entrance.
diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
--- a/fs/sysfs/inode.c	Mon Mar  3 15:11:29 2003
+++ b/fs/sysfs/inode.c	Tue Mar 11 13:30:18 2003
@@ -93,19 +93,14 @@
 		/* make sure dentry is really there */
 		if (victim->d_inode && 
 		    (victim->d_parent->d_inode == dir->d_inode)) {
-			simple_unlink(dir->d_inode,victim);
-			d_delete(victim);
-
 			pr_debug("sysfs: Removing %s (%d)\n", victim->d_name.name,
 				 atomic_read(&victim->d_count));
-			/*
-			 * Drop reference from initial sysfs_get_dentry().
-			 */
-			dput(victim);
+
+			simple_unlink(dir->d_inode,victim);
+
 		}
-		
-		/**
-		 * Drop the reference acquired from sysfs_get_dentry() above.
+		/*
+		 * Drop reference from sysfs_get_dentry() above.
 		 */
 		dput(victim);
 	}
diff -Nru a/fs/sysfs/mount.c b/fs/sysfs/mount.c
--- a/fs/sysfs/mount.c	Tue Mar  4 10:17:14 2003
+++ b/fs/sysfs/mount.c	Wed Mar  5 15:26:59 2003
@@ -33,7 +33,7 @@
 	sb->s_op = &sysfs_ops;
 	sysfs_sb = sb;
 
-	inode = sysfs_new_inode(S_IFDIR | S_IRUGO | S_IWUSR);
+	inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
 	if (inode) {
 		inode->i_op = &simple_dir_inode_operations;
 		inode->i_fop = &simple_dir_operations;
diff -Nru a/include/asm-alpha/core_cia.h b/include/asm-alpha/core_cia.h
--- a/include/asm-alpha/core_cia.h	Sun Dec  8 03:50:30 2002
+++ b/include/asm-alpha/core_cia.h	Sun Feb 16 16:35:48 2003
@@ -293,7 +293,7 @@
 #ifdef __KERNEL__
 
 #ifndef __EXTERN_INLINE
-#define __EXTERN_INLINE extern inline
+#define __EXTERN_INLINE static inline
 #define __IO_EXTERN_INLINE
 #endif
 
diff -Nru a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
--- a/include/asm-alpha/pci.h	Tue Feb 25 09:18:05 2003
+++ b/include/asm-alpha/pci.h	Sun Mar 16 13:55:57 2003
@@ -190,6 +190,11 @@
 
 /* Return the index of the PCI controller for device PDEV. */
 extern int pci_controller_num(struct pci_dev *pdev);
+
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res);
+
 #endif /* __KERNEL__ */
 
 /* Values for the `which' argument to sys_pciconfig_iobase.  */
diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
--- a/include/asm-alpha/pgtable.h	Mon Dec 30 07:03:59 2002
+++ b/include/asm-alpha/pgtable.h	Thu Mar  6 08:19:03 2003
@@ -273,7 +273,6 @@
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)	((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
-#define __pgd_offset(address)	pgd_index(address)
 #define pgd_offset(mm, address)	((mm)->pgd+pgd_index(address))
 
 /* Find an entry in the second-level page table.. */
diff -Nru a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h
--- a/include/asm-alpha/processor.h	Thu Nov 21 10:03:05 2002
+++ b/include/asm-alpha/processor.h	Mon Mar 10 10:20:30 2003
@@ -51,6 +51,9 @@
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /* Create a kernel thread without removing it from tasklists.  */
 extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 
diff -Nru a/include/asm-arm/arch-anakin/time.h b/include/asm-arm/arch-anakin/time.h
--- a/include/asm-arm/arch-anakin/time.h	Mon Feb 25 11:43:22 2002
+++ b/include/asm-arm/arch-anakin/time.h	Thu Mar  6 05:40:54 2003
@@ -23,7 +23,6 @@
 void __init time_init(void)
 {
 	timer_irq.handler = anakin_timer_interrupt;
-	timer_irq.flags = SA_INTERRUPT;
 	setup_irq(IRQ_TICK, &timer_irq);
 }
 
diff -Nru a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h
--- a/include/asm-arm/arch-sa1100/time.h	Sat Feb 15 11:11:56 2003
+++ b/include/asm-arm/arch-sa1100/time.h	Thu Mar  6 05:40:54 2003
@@ -75,15 +75,12 @@
 static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned int next_match;
-	unsigned long flags;
 
 	do {
 		do_leds();
-		local_irq_save(flags);
 		do_timer(regs);
 		OSSR = OSSR_M0;  /* Clear match on timer 0 */
 		next_match = (OSMR0 += LATCH);
-		local_irq_restore(flags);
 		do_set_rtc();
 	} while ((signed long)(next_match - OSCR) <= 0);
 
diff -Nru a/include/asm-arm/arch-shark/time.h b/include/asm-arm/arch-shark/time.h
--- a/include/asm-arm/arch-shark/time.h	Mon Feb 25 15:24:09 2002
+++ b/include/asm-arm/arch-shark/time.h	Thu Mar  6 05:40:55 2003
@@ -34,6 +34,5 @@
 	xtime.tv_sec = 0;
 
 	timer_irq.handler = timer_interrupt;
-	timer_irq.flags = SA_INTERRUPT; /* FIXME: really? */
 	setup_irq(IRQ_TIMER, &timer_irq);
 }
diff -Nru a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
--- a/include/asm-arm/ecard.h	Sun Jan 26 06:44:21 2003
+++ b/include/asm-arm/ecard.h	Thu Mar  6 05:14:05 2003
@@ -267,6 +267,7 @@
 struct ecard_driver {
 	int			(*probe)(struct expansion_card *, const struct ecard_id *id);
 	void			(*remove)(struct expansion_card *);
+	void			(*shutdown)(struct expansion_card *);
 	const struct ecard_id	*id_table;
 	unsigned int		id;
 	struct device_driver	drv;
diff -Nru a/include/asm-arm/ide.h b/include/asm-arm/ide.h
--- a/include/asm-arm/ide.h	Tue Jan 14 15:31:20 2003
+++ b/include/asm-arm/ide.h	Thu Mar  6 06:43:42 2003
@@ -26,16 +26,10 @@
 #define ide_default_io_base(i)		((ide_ioreg_t)0)
 #define ide_default_irq(b)		(0)
 
-#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
-#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
-#define ide_check_region(from,extent)		check_region((from), (extent))
-#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
-#define ide_release_region(from,extent)		release_region((from), (extent))
-
-/*
- * The following are not needed for the non-m68k ports
- */
-#define ide_ack_intr(hwif)		(1)
+#define __ide_mm_insw(port,addr,len)	readsw(port,addr,len)
+#define __ide_mm_insl(port,addr,len)	readsl(port,addr,len)
+#define __ide_mm_outsw(port,addr,len)	writesw(port,addr,len)
+#define __ide_mm_outsl(port,addr,len)	writesl(port,addr,len)
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-arm/pci.h b/include/asm-arm/pci.h
--- a/include/asm-arm/pci.h	Fri Jan 10 13:40:12 2003
+++ b/include/asm-arm/pci.h	Sun Mar 16 13:55:58 2003
@@ -131,7 +131,10 @@
 /*
  * Return the index of the PCI controller for device PDEV.
  */
-#define pci_controller_num(PDEV)	(0)
+static inline int pci_controller_num(struct pci_dev *dev)
+{
+	return 0;
+}
 
 
 #if defined(CONFIG_SA1111) && !defined(CONFIG_PCI)
@@ -171,6 +174,10 @@
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                                enum pci_mmap_state mmap_state, int write_combine);
+
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res);
 
 #endif /* __KERNEL__ */
  
diff -Nru a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
--- a/include/asm-arm/pgtable.h	Sun Oct 13 03:46:44 2002
+++ b/include/asm-arm/pgtable.h	Thu Mar  6 08:19:03 2003
@@ -110,13 +110,13 @@
 #define pgd_bad(pgd)		(0)
 #define pgd_present(pgd)	(1)
 #define pgd_clear(pgdp)		do { } while (0)
+#define set_pgd(pgd,pgdp)	do { } while (0)
 
 #define page_pte_prot(page,prot)	mk_pte(page, prot)
 #define page_pte(page)		mk_pte(page, __pgprot(0))
 
 /* to find an entry in a page-table-directory */
 #define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
-#define __pgd_offset(addr)	pgd_index(addr)
 
 #define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
 
diff -Nru a/include/asm-arm/posix_types.h b/include/asm-arm/posix_types.h
--- a/include/asm-arm/posix_types.h	Tue Feb  5 09:39:52 2002
+++ b/include/asm-arm/posix_types.h	Thu Mar  6 05:53:11 2003
@@ -34,6 +34,8 @@
 typedef long			__kernel_time_t;
 typedef long			__kernel_suseconds_t;
 typedef long			__kernel_clock_t;
+typedef int			__kernel_timer_t;
+typedef int			__kernel_clockid_t;
 typedef int			__kernel_daddr_t;
 typedef char *			__kernel_caddr_t;
 typedef unsigned short		__kernel_uid16_t;
diff -Nru a/include/asm-arm/proc-armv/tlbflush.h b/include/asm-arm/proc-armv/tlbflush.h
--- a/include/asm-arm/proc-armv/tlbflush.h	Sun Oct 13 03:46:44 2002
+++ b/include/asm-arm/proc-armv/tlbflush.h	Thu Mar  6 06:52:18 2003
@@ -1,7 +1,7 @@
 /*
  *  linux/include/asm-arm/proc-armv/tlbflush.h
  *
- *  Copyright (C) 1999-2002 Russell King
+ *  Copyright (C) 1999-2003 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -38,21 +38,31 @@
 #define v3_tlb_flags	(TLB_V3_FULL | TLB_V3_PAGE)
 
 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+# define v3_possible_flags	v3_tlb_flags
+# define v3_always_flags	v3_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v3
 # endif
+#else
+# define v3_possible_flags	0
+# define v3_always_flags	(-1UL)
 #endif
 
 #define v4_tlb_flags	(TLB_V4_U_FULL | TLB_V4_U_PAGE)
 
 #if defined(CONFIG_CPU_ARM720T)
+# define v4_possible_flags	v4_tlb_flags
+# define v4_always_flags	v4_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v4
 # endif
+#else
+# define v4_possible_flags	0
+# define v4_always_flags	(-1UL)
 #endif
 
 #define v4wbi_tlb_flags	(TLB_WB | \
@@ -62,11 +72,16 @@
 #if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
     defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \
     defined(CONFIG_CPU_XSCALE)
+# define v4wbi_possible_flags	v4wbi_tlb_flags
+# define v4wbi_always_flags	v4wbi_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v4wbi
 # endif
+#else
+# define v4wbi_possible_flags	0
+# define v4wbi_always_flags	(-1UL)
 #endif
 
 #define v4wb_tlb_flags	(TLB_WB | \
@@ -74,11 +89,16 @@
 			 TLB_V4_D_PAGE)
 
 #if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
+# define v4wb_possible_flags	v4wb_tlb_flags
+# define v4wb_always_flags	v4wb_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v4wb
 # endif
+#else
+# define v4wb_possible_flags	0
+# define v4wb_always_flags	(-1UL)
 #endif
 
 #ifndef _TLB
@@ -98,23 +118,23 @@
  */
 #ifdef MULTI_TLB
 
-extern struct cpu_tlb_fns cpu_tlb;
-
 #define __cpu_flush_user_tlb_range	cpu_tlb.flush_user_range
 #define __cpu_flush_kern_tlb_range	cpu_tlb.flush_kern_range
-#define __cpu_tlb_flags			cpu_tlb.tlb_flags
 
 #else
 
 #define __cpu_flush_user_tlb_range	__glue(_TLB,_flush_user_tlb_range)
 #define __cpu_flush_kern_tlb_range	__glue(_TLB,_flush_kern_tlb_range)
-#define __cpu_tlb_flags			__glue(_TLB,_tlb_flags)
 
 extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
 extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
 
 #endif
 
+extern struct cpu_tlb_fns cpu_tlb;
+
+#define __cpu_tlb_flags			cpu_tlb.tlb_flags
+
 /*
  *	TLB Management
  *	==============
@@ -158,11 +178,34 @@
  *		- kaddr - Kernel virtual memory address
  */
 
-#define tlb_flag(f)	(__cpu_tlb_flags & (f))
+/*
+ * We optimise the code below by:
+ *  - building a set of TLB flags that might be set in __cpu_tlb_flags
+ *  - building a set of TLB flags that will always be set in __cpu_tlb_flags
+ *  - if we're going to need __cpu_tlb_flags, access it once and only once
+ *
+ * This allows us to build optimal assembly for the single-CPU type case,
+ * and as close to optimal given the compiler constrants for multi-CPU
+ * case.  We could do better for the multi-CPU case if the compiler
+ * implemented the "%?" method, but this has been discontinued due to too
+ * many people getting it wrong.
+ */
+#define possible_tlb_flags	(v3_possible_flags | \
+				 v4_possible_flags | \
+				 v4wbi_possible_flags | \
+				 v4wb_possible_flags)
+
+#define always_tlb_flags	(v3_always_flags & \
+				 v4_always_flags & \
+				 v4wbi_always_flags & \
+				 v4wb_always_flags)
+
+#define tlb_flag(f)	((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
 
 static inline void flush_tlb_all(void)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
 		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
@@ -180,6 +223,7 @@
 static inline void flush_tlb_mm(struct mm_struct *mm)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
 		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
@@ -200,6 +244,7 @@
 flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	uaddr &= PAGE_MASK;
 
@@ -223,6 +268,7 @@
 static inline void flush_tlb_kernel_page(unsigned long kaddr)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	kaddr &= PAGE_MASK;
 
@@ -240,6 +286,10 @@
 	if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
 		asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
 }
+
+#undef tlb_flag
+#undef always_tlb_flags
+#undef possible_tlb_flags
 
 /*
  * Convert calls to our calling convention.
diff -Nru a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
--- a/include/asm-arm/proc-fns.h	Tue Feb 25 02:23:37 2003
+++ b/include/asm-arm/proc-fns.h	Thu Mar  6 06:06:19 2003
@@ -122,15 +122,4 @@
 #include CPU_INCLUDE_NAME
 
 #endif /* __KERNEL__ */
-
-#if 0
- * The following is to fool mkdep into generating the correct
- * dependencies.  Without this, it can't figure out that this
- * file does indeed depend on the cpu-*.h files.
-#include <asm/cpu-single.h>
-#include <asm/cpu-multi26.h>
-#include <asm/cpu-multi32.h>
- *
-#endif
-
 #endif /* __ASM_PROCFNS_H */
diff -Nru a/include/asm-arm/processor.h b/include/asm-arm/processor.h
--- a/include/asm-arm/processor.h	Mon Nov  4 02:28:26 2002
+++ b/include/asm-arm/processor.h	Mon Mar 10 10:20:30 2003
@@ -62,6 +62,9 @@
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()			barrier()
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	Wed Oct 30 03:55:14 2002
+++ b/include/asm-arm/system.h	Thu Mar  6 08:26:25 2003
@@ -14,16 +14,6 @@
 extern unsigned int system_serial_high;
 extern unsigned int mem_fclk_21285;
 
-/*
- * This tells us if we have an ISA bridge
- * present in a PCI system.
- */
-#ifdef CONFIG_PCI
-extern int have_isa_bridge;
-#else
-#define have_isa_bridge		(0)
-#endif
-
 struct pt_regs;
 
 void die(const char *msg, struct pt_regs *regs, int err)
@@ -75,7 +65,7 @@
  * The `mb' is to tell GCC not to cache `current' across this call.
  */
 struct thread_info;
-extern struct task_struct *__switch_to(struct thread_info *, struct thread_info *);
+extern struct thread_info *__switch_to(struct thread_info *, struct thread_info *);
 
 #define switch_to(prev,next,last)					\
 	do {			 					\
diff -Nru a/include/asm-cris/processor.h b/include/asm-cris/processor.h
--- a/include/asm-cris/processor.h	Mon Feb 24 10:10:20 2003
+++ b/include/asm-cris/processor.h	Mon Mar 10 10:20:30 2003
@@ -123,6 +123,9 @@
         /* Nothing needs to be done.  */
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Return saved PC of a blocked thread.
  */
diff -Nru a/include/asm-generic/pci.h b/include/asm-generic/pci.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-generic/pci.h	Sun Mar 16 13:55:59 2003
@@ -0,0 +1,25 @@
+/*
+ * linux/include/asm-generic/pci.h
+ *
+ *  Copyright (C) 2003 Russell King
+ */
+#ifndef _ASM_GENERIC_PCI_H
+#define _ASM_GENERIC_PCI_H
+
+/**
+ * pcibios_resource_to_bus - convert resource to PCI bus address
+ * @dev: device which owns this resource
+ * @region: converted bus-centric region (start,end)
+ * @res: resource to convert
+ *
+ * Convert a resource to a PCI device bus address or bus window.
+ */
+static inline void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res)
+{
+	region->start = res->start;
+	region->end = res->end;
+}
+
+#endif
diff -Nru a/include/asm-generic/xor.h b/include/asm-generic/xor.h
--- a/include/asm-generic/xor.h	Mon Oct 21 01:13:10 2002
+++ b/include/asm-generic/xor.h	Tue Mar 11 14:49:53 2003
@@ -678,35 +678,35 @@
 }
 
 static struct xor_block_template xor_block_8regs = {
-	name: "8regs",
-	do_2: xor_8regs_2,
-	do_3: xor_8regs_3,
-	do_4: xor_8regs_4,
-	do_5: xor_8regs_5,
+	.name = "8regs",
+	.do_2 = xor_8regs_2,
+	.do_3 = xor_8regs_3,
+	.do_4 = xor_8regs_4,
+	.do_5 = xor_8regs_5,
 };
 
 static struct xor_block_template xor_block_32regs = {
-	name: "32regs",
-	do_2: xor_32regs_2,
-	do_3: xor_32regs_3,
-	do_4: xor_32regs_4,
-	do_5: xor_32regs_5,
+	.name = "32regs",
+	.do_2 = xor_32regs_2,
+	.do_3 = xor_32regs_3,
+	.do_4 = xor_32regs_4,
+	.do_5 = xor_32regs_5,
 };
 
 static struct xor_block_template xor_block_8regs_p = {
-	name: "8regs_prefetch",
-	do_2: xor_8regs_p_2,
-	do_3: xor_8regs_p_3,
-	do_4: xor_8regs_p_4,
-	do_5: xor_8regs_p_5,
+	.name = "8regs_prefetch",
+	.do_2 = xor_8regs_p_2,
+	.do_3 = xor_8regs_p_3,
+	.do_4 = xor_8regs_p_4,
+	.do_5 = xor_8regs_p_5,
 };
 
 static struct xor_block_template xor_block_32regs_p = {
-	name: "32regs_prefetch",
-	do_2: xor_32regs_p_2,
-	do_3: xor_32regs_p_3,
-	do_4: xor_32regs_p_4,
-	do_5: xor_32regs_p_5,
+	.name = "32regs_prefetch",
+	.do_2 = xor_32regs_p_2,
+	.do_3 = xor_32regs_p_3,
+	.do_4 = xor_32regs_p_4,
+	.do_5 = xor_32regs_p_5,
 };
 
 #define XOR_TRY_TEMPLATES			\
diff -Nru a/include/asm-i386/bug.h b/include/asm-i386/bug.h
--- a/include/asm-i386/bug.h	Tue Feb 26 05:19:26 2002
+++ b/include/asm-i386/bug.h	Sun Feb 16 15:52:20 2003
@@ -4,8 +4,7 @@
 #include <linux/config.h>
 
 /*
- * Tell the user there is some problem. Beep too, so we can
- * see^H^H^Hhear bugs in early bootup as well!
+ * Tell the user there is some problem.
  * The offending file and line are encoded after the "officially
  * undefined" opcode for parsing in the trap handler.
  */
diff -Nru a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
--- a/include/asm-i386/cpufeature.h	Tue Dec 24 07:45:04 2002
+++ b/include/asm-i386/cpufeature.h	Thu Mar 13 15:47:14 2003
@@ -9,9 +9,9 @@
 
 #include <linux/bitops.h>
 
-#define NCAPINTS	4	/* Currently we have 4 32-bit words worth of info */
+#define NCAPINTS	6	/* Currently we have 6 32-bit words worth of info */
 
-/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
+/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
 #define X86_FEATURE_VME		(0*32+ 1) /* Virtual Mode Extensions */
 #define X86_FEATURE_DE		(0*32+ 2) /* Debugging Extensions */
@@ -64,6 +64,11 @@
 #define X86_FEATURE_CYRIX_ARR	(3*32+ 2) /* Cyrix ARRs (= MTRRs) */
 #define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
 
+/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
+
+/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
+#define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
+
 
 #define cpu_has(c, bit)		test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)	test_bit(bit, boot_cpu_data.x86_capability)
@@ -87,6 +92,7 @@
 #define cpu_has_k6_mtrr		boot_cpu_has(X86_FEATURE_K6_MTRR)
 #define cpu_has_cyrix_arr	boot_cpu_has(X86_FEATURE_CYRIX_ARR)
 #define cpu_has_centaur_mcr	boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
+#define cpu_has_xstore		boot_cpu_has(X86_FEATURE_XSTORE)
 
 #endif /* __ASM_I386_CPUFEATURE_H */
 
diff -Nru a/include/asm-i386/hdreg.h b/include/asm-i386/hdreg.h
--- a/include/asm-i386/hdreg.h	Wed Sep 11 00:06:00 2002
+++ b/include/asm-i386/hdreg.h	Tue Feb 18 06:32:42 2003
@@ -7,6 +7,5 @@
 #ifndef __ASMi386_HDREG_H
 #define __ASMi386_HDREG_H
 
-typedef unsigned long ide_ioreg_t;
 
 #endif /* __ASMi386_HDREG_H */
diff -Nru a/include/asm-i386/i387.h b/include/asm-i386/i387.h
--- a/include/asm-i386/i387.h	Fri Apr 19 12:34:03 2002
+++ b/include/asm-i386/i387.h	Mon Mar 10 10:20:30 2003
@@ -21,23 +21,41 @@
 /*
  * FPU lazy state save handling...
  */
-extern void save_init_fpu( struct task_struct *tsk );
 extern void restore_fpu( struct task_struct *tsk );
 
 extern void kernel_fpu_begin(void);
 #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
 
 
+static inline void __save_init_fpu( struct task_struct *tsk )
+{
+	if ( cpu_has_fxsr ) {
+		asm volatile( "fxsave %0 ; fnclex"
+			      : "=m" (tsk->thread.i387.fxsave) );
+	} else {
+		asm volatile( "fnsave %0 ; fwait"
+			      : "=m" (tsk->thread.i387.fsave) );
+	}
+	tsk->thread_info->status &= ~TS_USEDFPU;
+}
+
+static inline void save_init_fpu( struct task_struct *tsk )
+{
+	__save_init_fpu(tsk);
+	stts();
+}
+
+
 #define unlazy_fpu( tsk ) do { \
-	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) \
+	if ((tsk)->thread_info->status & TS_USEDFPU) \
 		save_init_fpu( tsk ); \
 } while (0)
 
 #define clear_fpu( tsk )					\
 do {								\
-	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {		\
+	if ((tsk)->thread_info->status & TS_USEDFPU) {		\
 		asm volatile("fwait");				\
-		clear_tsk_thread_flag(tsk, TIF_USEDFPU);	\
+		(tsk)->thread_info->status &= ~TS_USEDFPU;	\
 		stts();						\
 	}							\
 } while (0)
diff -Nru a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
--- a/include/asm-i386/mmzone.h	Mon Feb 24 23:13:14 2003
+++ b/include/asm-i386/mmzone.h	Tue Mar  4 23:41:55 2003
@@ -10,14 +10,6 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
-#ifdef CONFIG_X86_NUMAQ
-#include <asm/numaq.h>
-#elif CONFIG_X86_SUMMIT
-#include <asm/srat.h>
-#else
-#define pfn_to_nid(pfn)		(0)
-#endif /* CONFIG_X86_NUMAQ */
-
 extern struct pglist_data *node_data[];
 
 /*
@@ -101,5 +93,41 @@
  * ( pfn_to_pgdat(pfn) && ((pfn) < node_end_pfn(pfn_to_nid(pfn))) ) 
  */ 
 #define pfn_valid(pfn)          ((pfn) < num_physpages)
+
+/*
+ * generic node memory support, the following assumptions apply:
+ *
+ * 1) memory comes in 256Mb contigious chunks which are either present or not
+ * 2) we will not have more than 64Gb in total
+ *
+ * for now assume that 64Gb is max amount of RAM for whole system
+ *    64Gb / 4096bytes/page = 16777216 pages
+ */
+#define MAX_NR_PAGES 16777216
+#define MAX_ELEMENTS 256
+#define PAGES_PER_ELEMENT (MAX_NR_PAGES/MAX_ELEMENTS)
+
+extern u8 physnode_map[];
+
+static inline int pfn_to_nid(unsigned long pfn)
+{
+	return(physnode_map[(pfn) / PAGES_PER_ELEMENT]);
+}
+static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+	return(NODE_DATA(pfn_to_nid(pfn)));
+}
+
+#ifdef CONFIG_X86_NUMAQ
+#include <asm/numaq.h>
+#elif CONFIG_X86_SUMMIT
+#include <asm/srat.h>
+#elif CONFIG_X86_PC
+#define get_memcfg_numa get_memcfg_numa_flat
+#define get_zholes_size(n) (0)
+#else
+#define pfn_to_nid(pfn)		(0)
+#endif /* CONFIG_X86_NUMAQ */
+
 #endif /* CONFIG_DISCONTIGMEM */
 #endif /* _ASM_MMZONE_H_ */
diff -Nru a/include/asm-i386/msr.h b/include/asm-i386/msr.h
--- a/include/asm-i386/msr.h	Thu Jan  2 19:18:54 2003
+++ b/include/asm-i386/msr.h	Thu Mar 13 15:47:14 2003
@@ -218,6 +218,7 @@
 /* VIA Cyrix defined MSRs*/
 #define MSR_VIA_FCR			0x1107
 #define MSR_VIA_LONGHAUL		0x110a
+#define MSR_VIA_RNG			0x110b
 #define MSR_VIA_BCR2			0x1147
 
 /* Transmeta defined MSRs */
diff -Nru a/include/asm-i386/numaq.h b/include/asm-i386/numaq.h
--- a/include/asm-i386/numaq.h	Fri Feb 28 15:03:59 2003
+++ b/include/asm-i386/numaq.h	Tue Mar  4 23:43:31 2003
@@ -28,18 +28,6 @@
 
 #ifdef CONFIG_X86_NUMAQ
 
-/*
- * for now assume that 64Gb is max amount of RAM for whole system
- *    64Gb / 4096bytes/page = 16777216 pages
- */
-#define MAX_NR_PAGES 16777216
-#define MAX_ELEMENTS 256
-#define PAGES_PER_ELEMENT (16777216/256)
-
-extern int physnode_map[];
-#define pfn_to_nid(pfn)	({ physnode_map[(pfn) / PAGES_PER_ELEMENT]; })
-#define pfn_to_pgdat(pfn) NODE_DATA(pfn_to_nid(pfn))
-#define PHYSADDR_TO_NID(pa) pfn_to_nid(pa >> PAGE_SHIFT)
 #define MAX_NUMNODES		8
 extern void get_memcfg_numaq(void);
 #define get_memcfg_numa() get_memcfg_numaq()
@@ -169,7 +157,7 @@
         struct	eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */
 };
 
-static inline unsigned long get_zholes_size(int nid)
+static inline unsigned long *get_zholes_size(int nid)
 {
 	return 0;
 }
diff -Nru a/include/asm-i386/pci.h b/include/asm-i386/pci.h
--- a/include/asm-i386/pci.h	Sun Dec 22 08:56:26 2002
+++ b/include/asm-i386/pci.h	Sun Mar 16 13:55:58 2003
@@ -105,4 +105,7 @@
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
 #endif /* __i386_PCI_H */
diff -Nru a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
--- a/include/asm-i386/pgtable-3level.h	Mon Feb  3 23:46:49 2003
+++ b/include/asm-i386/pgtable-3level.h	Thu Mar  6 08:19:07 2003
@@ -69,7 +69,7 @@
 
 /* Find an entry in the second-level page table.. */
 #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \
-			__pmd_offset(address))
+			pmd_index(address))
 
 static inline pte_t ptep_get_and_clear(pte_t *ptep)
 {
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	Tue Feb 18 18:58:46 2003
+++ b/include/asm-i386/pgtable.h	Thu Mar  6 17:44:46 2003
@@ -49,8 +49,6 @@
 
 #endif
 
-#define __beep() asm("movb $0x3,%al; outb %al,$0x61")
-
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
@@ -236,32 +234,30 @@
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
-#define __pgd_offset(address) pgd_index(address)
-
 #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-#define __pmd_offset(address) \
+#define pmd_index(address) \
 		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) \
+#define pte_index(address) \
 		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
-	((pte_t *) pmd_page_kernel(*(dir)) +  __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
 
 #if defined(CONFIG_HIGHPTE)
 #define pte_offset_map(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address))
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
 #define pte_offset_map_nested(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address))
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
 #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
 #else
 #define pte_offset_map(dir, address) \
-	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
 #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte) do { } while (0)
 #define pte_unmap_nested(pte) do { } while (0)
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Wed Feb 19 17:48:55 2003
+++ b/include/asm-i386/processor.h	Mon Mar 10 14:41:23 2003
@@ -347,7 +347,7 @@
 	unsigned long	esp0;
 	unsigned short	ss0,__ss0h;
 	unsigned long	esp1;
-	unsigned short	ss1,__ss1h;
+	unsigned short	ss1,__ss1h;	/* ss1 is used to cache MSR_IA32_SYSENTER_CS */
 	unsigned long	esp2;
 	unsigned short	ss2,__ss2h;
 	unsigned long	__cr3;
@@ -404,6 +404,8 @@
 #define INIT_TSS  {							\
 	.esp0		= sizeof(init_stack) + (long)&init_stack,	\
 	.ss0		= __KERNEL_DS,					\
+	.esp1		= sizeof(init_tss[0]) + (long)&init_tss[0],	\
+	.ss1		= __KERNEL_CS,					\
 	.ldt		= GDT_ENTRY_LDT,				\
 	.bitmap		= INVALID_IO_BITMAP_OFFSET,			\
 	.io_bitmap	= { [ 0 ... IO_BITMAP_SIZE ] = ~0 },		\
@@ -412,16 +414,19 @@
 static inline void load_esp0(struct tss_struct *tss, unsigned long esp0)
 {
 	tss->esp0 = esp0;
-	if (cpu_has_sep) {
+	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
+	if (tss->ss1 != __KERNEL_CS) {
+		tss->ss1 = __KERNEL_CS;
 		wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
-		wrmsr(MSR_IA32_SYSENTER_ESP, esp0, 0);
 	}
 }
 
-static inline void disable_sysenter(void)
+static inline void disable_sysenter(struct tss_struct *tss)
 {
-	if (cpu_has_sep)  
+	if (cpu_has_sep)  {
+		tss->ss1 = 0;
 		wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
+	}
 }
 
 #define start_thread(regs, new_eip, new_esp) do {		\
@@ -441,6 +446,10 @@
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+extern void prepare_to_copy(struct task_struct *tsk);
+
 /*
  * create a kernel thread without removing it from tasklists
  */
diff -Nru a/include/asm-i386/serial.h b/include/asm-i386/serial.h
--- a/include/asm-i386/serial.h	Mon Feb  4 23:43:09 2002
+++ b/include/asm-i386/serial.h	Thu Feb 20 08:30:58 2003
@@ -50,12 +50,19 @@
 
 #define C_P(card,port) (((card)<<6|(port)<<3) + 1)
 
+#ifndef CONFIG_X86_PC9800
 #define STD_SERIAL_PORT_DEFNS			\
 	/* UART CLK   PORT IRQ     FLAGS        */			\
 	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
 	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
 	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
+#else
+#define STD_SERIAL_PORT_DEFNS			\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, BASE_BAUD, 0x30, 4, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x238, 5, STD_COM_FLAGS },	/* ttyS1 */
+#endif /* CONFIG_X86_PC9800 */
 
 
 #ifdef CONFIG_SERIAL_MANY_PORTS
diff -Nru a/include/asm-i386/srat.h b/include/asm-i386/srat.h
--- a/include/asm-i386/srat.h	Mon Feb 24 23:13:14 2003
+++ b/include/asm-i386/srat.h	Tue Mar  4 23:41:55 2003
@@ -27,17 +27,6 @@
 #ifndef _ASM_SRAT_H_
 #define _ASM_SRAT_H_
 
-/*
- * each element in pfnnode_map represents 256 MB (2^28) of pages.
- * so, to represent 64GB we need 256 elements.
- */
-#define MAX_ELEMENTS 256
-#define PFN_TO_ELEMENT(pfn) ((pfn)>>(28 - PAGE_SHIFT))
-
-extern int pfnnode_map[];
-#define pfn_to_nid(pfn) ({ pfnnode_map[PFN_TO_ELEMENT(pfn)]; })
-#define pfn_to_pgdat(pfn) NODE_DATA(pfn_to_nid(pfn))
-#define PHYSADDR_TO_NID(pa) pfn_to_nid(pa >> PAGE_SHIFT)
 #define MAX_NUMNODES		8
 extern void get_memcfg_from_srat(void);
 extern unsigned long *get_zholes_size(int);
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Sat Jan  4 10:06:07 2003
+++ b/include/asm-i386/thread_info.h	Mon Mar 10 10:20:30 2003
@@ -25,6 +25,7 @@
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
+	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
 
@@ -43,10 +44,11 @@
 #define TI_TASK		0x00000000
 #define TI_EXEC_DOMAIN	0x00000004
 #define TI_FLAGS	0x00000008
-#define TI_CPU		0x0000000C
-#define TI_PRE_COUNT	0x00000010
-#define TI_ADDR_LIMIT	0x00000014
-#define TI_RESTART_BLOCK 0x0000018
+#define TI_STATUS	0x0000000C
+#define TI_CPU		0x00000010
+#define TI_PRE_COUNT	0x00000014
+#define TI_ADDR_LIMIT	0x00000018
+#define TI_RESTART_BLOCK 0x000001C
 
 #endif
 
@@ -111,8 +113,7 @@
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
-#define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
-#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -120,11 +121,19 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
-#define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-i386/xor.h b/include/asm-i386/xor.h
--- a/include/asm-i386/xor.h	Wed Nov 20 14:42:33 2002
+++ b/include/asm-i386/xor.h	Tue Mar 11 18:15:03 2003
@@ -18,22 +18,6 @@
  * Copyright (C) 1998 Ingo Molnar.
  */
 
-#define FPU_SAVE							\
-  do {									\
-	preempt_disable();						\
-	if (!test_thread_flag(TIF_USEDFPU))				\
-		__asm__ __volatile__ (" clts;\n");			\
-	__asm__ __volatile__ ("fsave %0; fwait": "=m"(fpu_save[0]));	\
-  } while (0)
-
-#define FPU_RESTORE							\
-  do {									\
-	__asm__ __volatile__ ("frstor %0": : "m"(fpu_save[0]));		\
-	if (!test_thread_flag(TIF_USEDFPU))				\
-		stts();							\
-	preempt_enable();						\
-  } while (0)
-
 #define LD(x,y)		"       movq   8*("#x")(%1), %%mm"#y"   ;\n"
 #define ST(x,y)		"       movq %%mm"#y",   8*("#x")(%1)   ;\n"
 #define XO1(x,y)	"       pxor   8*("#x")(%2), %%mm"#y"   ;\n"
@@ -41,14 +25,14 @@
 #define XO3(x,y)	"       pxor   8*("#x")(%4), %%mm"#y"   ;\n"
 #define XO4(x,y)	"       pxor   8*("#x")(%5), %%mm"#y"   ;\n"
 
+#include <asm/i387.h>
 
 static void
 xor_pII_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 #undef BLOCK
@@ -83,7 +67,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -91,9 +75,8 @@
 	      unsigned long *p3)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 #undef BLOCK
@@ -133,7 +116,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -141,9 +124,8 @@
 	      unsigned long *p3, unsigned long *p4)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 #undef BLOCK
@@ -188,7 +170,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 
@@ -197,9 +179,8 @@
 	      unsigned long *p3, unsigned long *p4, unsigned long *p5)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	/* need to save/restore p4/p5 manually otherwise gcc's 10 argument
 	   limit gets exceeded (+ counts as two arguments) */
@@ -255,7 +236,7 @@
 	: "r" (p4), "r" (p5) 
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 #undef LD
@@ -270,9 +251,8 @@
 xor_p5_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 	" .align 32	             ;\n"
@@ -311,7 +291,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -319,9 +299,8 @@
 	     unsigned long *p3)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 	" .align 32,0x90             ;\n"
@@ -369,7 +348,7 @@
 	:
 	: "memory" );
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -377,9 +356,8 @@
 	     unsigned long *p3, unsigned long *p4)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 	" .align 32,0x90             ;\n"
@@ -436,7 +414,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -444,9 +422,8 @@
 	     unsigned long *p3, unsigned long *p4, unsigned long *p5)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	/* need to save p4/p5 manually to not exceed gcc's 10 argument limit */
 	__asm__ __volatile__ (
@@ -517,7 +494,7 @@
 	: "r" (p4), "r" (p5)
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static struct xor_block_template xor_block_pII_mmx = {
@@ -535,9 +512,6 @@
 	.do_4 = xor_p5_mmx_4,
 	.do_5 = xor_p5_mmx_5,
 };
-
-#undef FPU_SAVE
-#undef FPU_RESTORE
 
 /*
  * Cache avoiding checksumming functions utilizing KNI instructions
diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
--- a/include/asm-ia64/hardirq.h	Tue Sep 17 23:22:09 2002
+++ b/include/asm-ia64/hardirq.h	Wed Feb  5 03:03:22 2003
@@ -32,18 +32,18 @@
  *
  * - bits 0-7 are the preemption count (max preemption depth: 256)
  * - bits 8-15 are the softirq count (max # of softirqs: 256)
- * - bits 16-31 are the hardirq count (max # of hardirqs: 65536)
+ * - bits 16-29 are the hardirq count (max # of hardirqs: 16384)
  *
  * - (bit 63 is the PREEMPT_ACTIVE flag---not currently implemented.)
  *
  * PREEMPT_MASK: 0x000000ff
  * SOFTIRQ_MASK: 0x0000ff00
- * HARDIRQ_MASK: 0xffff0000
+ * HARDIRQ_MASK: 0x3fff0000
  */
 
 #define PREEMPT_BITS	8
 #define SOFTIRQ_BITS	8
-#define HARDIRQ_BITS	16
+#define HARDIRQ_BITS	14
 
 #define PREEMPT_SHIFT	0
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
@@ -83,13 +83,13 @@
 #define hardirq_trylock()	(!in_interrupt())
 #define hardirq_endlock()	do { } while (0)
 
-#define in_atomic()		(preempt_count() != 0)
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
 #if CONFIG_PREEMPT
-# error CONFIG_PREEMT currently not supported.
+# define in_atomic()		((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
+# define in_atomic()		(preempt_count() != 0)
 # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
 #endif
 
diff -Nru a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
--- a/include/asm-ia64/ide.h	Thu Oct 31 21:45:22 2002
+++ b/include/asm-ia64/ide.h	Thu Mar  6 21:11:46 2003
@@ -91,6 +91,8 @@
 #endif
 }
 
+#include <asm-generic/ide_iops.h>
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_IA64_IDE_H */
diff -Nru a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h
--- a/include/asm-ia64/intrinsics.h	Wed Jan 15 16:26:26 2003
+++ b/include/asm-ia64/intrinsics.h	Thu Mar  6 11:22:21 2003
@@ -35,24 +35,34 @@
 	}									\
 })
 
-#define ia64_fetch_and_add(i,v)							\
-({										\
-	__u64 _tmp;								\
-	volatile __typeof__(*(v)) *_v = (v);					\
-	switch (i) {								\
-	      case -16:	IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); break;	\
-	      case  -8:	IA64_FETCHADD(_tmp, _v,  -8, sizeof(*(v))); break;	\
-	      case  -4:	IA64_FETCHADD(_tmp, _v,  -4, sizeof(*(v))); break;	\
-	      case  -1:	IA64_FETCHADD(_tmp, _v,  -1, sizeof(*(v))); break;	\
-	      case   1:	IA64_FETCHADD(_tmp, _v,   1, sizeof(*(v))); break;	\
-	      case   4:	IA64_FETCHADD(_tmp, _v,   4, sizeof(*(v))); break;	\
-	      case   8:	IA64_FETCHADD(_tmp, _v,   8, sizeof(*(v))); break;	\
-	      case  16:	IA64_FETCHADD(_tmp, _v,  16, sizeof(*(v))); break;	\
-	      default:								\
-		_tmp = __bad_increment_for_ia64_fetch_and_add();		\
-		break;								\
-	}									\
-	(__typeof__(*(v))) (_tmp + (i));	/* return new value */		\
+#define ia64_fetch_and_add(i,v)								\
+({											\
+	__u64 _tmp;									\
+	volatile __typeof__(*(v)) *_v = (v);						\
+	/* Can't use a switch () here: gcc isn't always smart enough for that... */	\
+	if ((i) == -16)									\
+		IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)));				\
+	else if ((i) == -8)								\
+		IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)));				\
+	else if ((i) == -4)								\
+		IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)));				\
+	else if ((i) == -2)								\
+		IA64_FETCHADD(_tmp, _v, -2, sizeof(*(v)));				\
+	else if ((i) == -1)								\
+		IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)));				\
+	else if ((i) == 1)								\
+		IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)));				\
+	else if ((i) == 2)								\
+		IA64_FETCHADD(_tmp, _v, 2, sizeof(*(v)));				\
+	else if ((i) == 4)								\
+		IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)));				\
+	else if ((i) == 8)								\
+		IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)));				\
+	else if ((i) == 16)								\
+		IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)));				\
+	else										\
+		_tmp = __bad_increment_for_ia64_fetch_and_add();			\
+	(__typeof__(*(v))) (_tmp + (i));	/* return new value */			\
 })
 
 /*
diff -Nru a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
--- a/include/asm-ia64/iosapic.h	Wed Sep 25 19:04:16 2002
+++ b/include/asm-ia64/iosapic.h	Wed Feb 19 09:02:36 2003
@@ -51,26 +51,23 @@
 
 #ifndef __ASSEMBLY__
 
-extern void __devinit iosapic_init (unsigned long address,
-				    unsigned int gsi_base,
-				    int pcat_compat);
+extern void __init iosapic_system_init (int pcat_compat);
+extern void __init iosapic_init (unsigned long address,
+				    unsigned int gsi_base);
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
-extern void iosapic_parse_prt (void);
+extern void __init iosapic_parse_prt (void);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
-				  unsigned long edge_triggered,
-				  u32 gsi_base, char *iosapic_address);
-extern void iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
+				  unsigned long trigger);
+extern void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
 				      unsigned long polarity,
-				      unsigned long edge_triggered);
-extern int iosapic_register_platform_intr (u32 int_type,
+				      unsigned long trigger);
+extern int __init iosapic_register_platform_intr (u32 int_type,
 					   unsigned int gsi,
 					   int pmi_vector,
 					   u16 eid, u16 id,
 					   unsigned long polarity,
-					   unsigned long edge_triggered,
-					   unsigned int gsi_base,
-					   char *iosapic_address);
+					   unsigned long trigger);
 extern unsigned int iosapic_version (char *addr);
 
 extern void iosapic_pci_fixup (int);
diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
--- a/include/asm-ia64/machvec.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec.h	Thu Feb 20 05:59:35 2003
@@ -23,8 +23,6 @@
 typedef void ia64_mv_setup_t (char **);
 typedef void ia64_mv_cpu_init_t(void);
 typedef void ia64_mv_irq_init_t (void);
-typedef void ia64_mv_pci_fixup_t (int);
-typedef unsigned long ia64_mv_map_nr_t (unsigned long);
 typedef void ia64_mv_mca_init_t (void);
 typedef void ia64_mv_mca_handler_t (void);
 typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *);
@@ -115,13 +113,16 @@
 #  define platofrm_mmiob        ia64_mv.mmiob
 # endif
 
+/* __attribute__((__aligned__(16))) is required to make size of the
+ * structure multiple of 16 bytes.
+ * This will fillup the holes created because of section 3.3.1 in 
+ * Software Conventions guide.
+ */
 struct ia64_machine_vector {
 	const char *name;
 	ia64_mv_setup_t *setup;
 	ia64_mv_cpu_init_t *cpu_init;
 	ia64_mv_irq_init_t *irq_init;
-	ia64_mv_pci_fixup_t *pci_fixup;
-	ia64_mv_map_nr_t *map_nr;
 	ia64_mv_mca_init_t *mca_init;
 	ia64_mv_mca_handler_t *mca_handler;
 	ia64_mv_cmci_handler_t *cmci_handler;
@@ -149,7 +150,7 @@
 	ia64_mv_outw_t *outw;
 	ia64_mv_outl_t *outl;
 	ia64_mv_mmiob_t *mmiob;
-};
+} __attribute__((__aligned__(16)));
 
 #define MACHVEC_INIT(name)			\
 {						\
diff -Nru a/include/asm-ia64/machvec_dig.h b/include/asm-ia64/machvec_dig.h
--- a/include/asm-ia64/machvec_dig.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_dig.h	Thu Feb 20 03:14:25 2003
@@ -3,8 +3,6 @@
 
 extern ia64_mv_setup_t dig_setup;
 extern ia64_mv_irq_init_t dig_irq_init;
-extern ia64_mv_pci_fixup_t iosapic_pci_fixup;
-extern ia64_mv_map_nr_t map_nr_dense;
 
 /*
  * This stuff has dual use!
diff -Nru a/include/asm-ia64/machvec_hpsim.h b/include/asm-ia64/machvec_hpsim.h
--- a/include/asm-ia64/machvec_hpsim.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_hpsim.h	Thu Feb 20 03:14:12 2003
@@ -3,7 +3,6 @@
 
 extern ia64_mv_setup_t hpsim_setup;
 extern ia64_mv_irq_init_t hpsim_irq_init;
-extern ia64_mv_map_nr_t map_nr_dense;
 
 /*
  * This stuff has dual use!
diff -Nru a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h
--- a/include/asm-ia64/machvec_hpzx1.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_hpzx1.h	Thu Feb 20 03:31:21 2003
@@ -2,8 +2,6 @@
 #define _ASM_IA64_MACHVEC_HPZX1_h
 
 extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_pci_fixup_t hpzx1_pci_fixup;
-extern ia64_mv_map_nr_t map_nr_dense;
 extern ia64_mv_pci_alloc_consistent sba_alloc_consistent;
 extern ia64_mv_pci_free_consistent sba_free_consistent;
 extern ia64_mv_pci_map_single sba_map_single;
diff -Nru a/include/asm-ia64/machvec_sn1.h b/include/asm-ia64/machvec_sn1.h
--- a/include/asm-ia64/machvec_sn1.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_sn1.h	Thu Feb 20 03:34:17 2003
@@ -36,10 +36,8 @@
 extern ia64_mv_setup_t sn1_setup;
 extern ia64_mv_cpu_init_t sn_cpu_init;
 extern ia64_mv_irq_init_t sn1_irq_init;
-extern ia64_mv_map_nr_t sn1_map_nr;
 extern ia64_mv_send_ipi_t sn1_send_IPI;
 extern ia64_mv_global_tlb_purge_t sn1_global_tlb_purge;
-extern ia64_mv_pci_fixup_t sn1_pci_fixup;
 extern ia64_mv_inb_t sn1_inb;
 extern ia64_mv_inw_t sn1_inw;
 extern ia64_mv_inl_t sn1_inl;
diff -Nru a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
--- a/include/asm-ia64/machvec_sn2.h	Tue Dec  3 10:07:32 2002
+++ b/include/asm-ia64/machvec_sn2.h	Thu Feb 20 03:59:23 2003
@@ -36,13 +36,11 @@
 extern ia64_mv_setup_t sn_setup;
 extern ia64_mv_cpu_init_t sn_cpu_init;
 extern ia64_mv_irq_init_t sn_irq_init;
-extern ia64_mv_map_nr_t sn2_map_nr;
 extern ia64_mv_send_ipi_t sn2_send_IPI;
 extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge;
 extern ia64_mv_irq_desc sn_irq_desc;
 extern ia64_mv_irq_to_vector sn_irq_to_vector;
 extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
-extern ia64_mv_pci_fixup_t sn_pci_fixup;
 extern ia64_mv_inb_t sn_inb;
 extern ia64_mv_inw_t sn_inw;
 extern ia64_mv_inl_t sn_inl;
@@ -72,10 +70,8 @@
 #define platform_setup			sn_setup
 #define platform_cpu_init		sn_cpu_init
 #define platform_irq_init		sn_irq_init
-#define platform_map_nr			sn2_map_nr
 #define platform_send_ipi		sn2_send_IPI
 #define platform_global_tlb_purge       sn2_global_tlb_purge
-#define platform_pci_fixup		sn_pci_fixup
 #define platform_inb			sn_inb
 #define platform_inw			sn_inw
 #define platform_inl			sn_inl
diff -Nru a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h
--- a/include/asm-ia64/mmzone.h	Tue Feb 25 02:08:52 2003
+++ b/include/asm-ia64/mmzone.h	Thu Mar  6 11:40:52 2003
@@ -76,7 +76,7 @@
 
 #define pfn_to_page(pfn)	(struct page *)(node_mem_map(pfn_to_nid(pfn)) + node_localnr(pfn, pfn_to_nid(pfn)))
 
-#define pfn_to_nid(pfn)		 local_node_data->node_id_map[(pfn << PAGE_SHIFT) >> DIG_BANKSHIFT]
+#define pfn_to_nid(pfn)		 local_node_data->node_id_map[(pfn << PAGE_SHIFT) >> BANKSHIFT]
 
 #define page_to_pfn(page)	(long)((page - page_zone(page)->zone_mem_map) + page_zone(page)->zone_start_pfn)
 
@@ -110,15 +110,15 @@
  */
 #define NR_BANKS_PER_NODE	32
 #if defined(CONFIG_IA64_NODESIZE_16GB)
-# define DIG_BANKSHIFT		29
+# define BANKSHIFT		29
 #elif defined(CONFIG_IA64_NODESIZE_64GB)
-# define DIG_BANKSHIFT		31
+# define BANKSHIFT		31
 #elif defined(CONFIG_IA64_NODESIZE_256GB)
-# define DIG_BANKSHIFT		33
+# define BANKSHIFT		33
 #else
 # error Unsupported bank and nodesize!
 #endif
-#define BANKSIZE		(1UL << DIG_BANKSHIFT)
+#define BANKSIZE		(1UL << BANKSHIFT)
 #define BANK_OFFSET(addr)	((unsigned long)(addr) & (BANKSIZE-1))
 #define NR_BANKS		(NR_BANKS_PER_NODE * NR_NODES)
 
@@ -134,7 +134,30 @@
  * entry for the first page of the bank.
  */
 #define BANK_MEM_MAP_INDEX(kaddr) \
-	(((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> DIG_BANKSHIFT)
+	(((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT)
+
+#elif defined(CONFIG_IA64_SGI_SN2)
+/*
+ * SGI SN2 discontig definitions
+ */
+#define MAX_PHYSNODE_ID	2048	/* 2048 node ids (also called nasid) */
+#define NR_NODES	128	/* Maximum number of nodes in SSI */
+#define MAX_PHYS_MEMORY	(1UL << 49)
+
+#define BANKSHIFT		38
+#define NR_BANKS_PER_NODE	4
+#define SN2_NODE_SIZE		(64UL*1024*1024*1024)	/* 64GB per node */
+#define BANKSIZE		(SN2_NODE_SIZE/NR_BANKS_PER_NODE)
+#define BANK_OFFSET(addr)	((unsigned long)(addr) & (BANKSIZE-1))
+#define NR_BANKS		(NR_BANKS_PER_NODE * NR_NODES)
+#define VALID_MEM_KADDR(kaddr)	1
+
+/*
+ * Given a nodeid & a bank number, find the address of the mem_map
+ * entry for the first page of the bank.
+ */
+#define BANK_MEM_MAP_INDEX(kaddr) \
+	(((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT)
 
 #endif /* CONFIG_IA64_DIG */
 #endif /* _ASM_IA64_MMZONE_H */
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
--- a/include/asm-ia64/page.h	Sun Mar  2 18:14:37 2003
+++ b/include/asm-ia64/page.h	Thu Mar  6 13:34:27 2003
@@ -57,16 +57,7 @@
 # define REGION_SHIFT	61
 # define HPAGE_SIZE	(__IA64_UL_CONST(1) << HPAGE_SHIFT)
 # define HPAGE_MASK	(~(HPAGE_SIZE - 1))
-static inline int
-check_valid_hugepage_range(unsigned long addr, unsigned long len)
-{
-	if (REGION_NUMBER(addr) == REGION_HPAGE)
-		return -EINVAL;
-	if (REGION_NUMBER(addr+len) == REGION_HPAGE)
-		return -EINVAL;
-	return 0;
-}
-#define ARCH_HAS_VALID_HUGEPAGE_RANGE
+# define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 #endif /* CONFIG_HUGETLB_PAGE */
 
 #ifdef __ASSEMBLY__
@@ -133,6 +124,9 @@
 # define htlbpage_to_page(x)	((REGION_NUMBER(x) << 61)				\
 				 | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
 # define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+extern int  is_invalid_hugepage_range(unsigned long addr, unsigned long len);
+#else
+#define is_invalid_hugepage_range(addr, len) 0
 #endif
 
 static __inline__ int
diff -Nru a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
--- a/include/asm-ia64/pci.h	Fri Aug 30 06:59:50 2002
+++ b/include/asm-ia64/pci.h	Sun Mar 16 13:55:58 2003
@@ -44,6 +44,9 @@
 	/* We don't do dynamic PCI IRQ allocation */
 }
 
+#define HAVE_ARCH_PCI_MWI 1
+extern int pcibios_prep_mwi (struct pci_dev *);
+
 /*
  * Dynamic DMA mapping API.  See Documentation/DMA-mapping.txt for details.
  */
@@ -93,5 +96,8 @@
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
 				enum pci_mmap_state mmap_state, int write_combine);
+
+/* generic pci stuff */
+#include <asm-generic/pci.h>
 
 #endif /* _ASM_IA64_PCI_H */
diff -Nru a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h
--- a/include/asm-ia64/perfmon.h	Tue Jan 28 15:15:42 2003
+++ b/include/asm-ia64/perfmon.h	Thu Feb  6 08:45:24 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001-2002 Hewlett-Packard Co
+ * Copyright (C) 2001-2003 Hewlett-Packard Co
  *               Stephane Eranian <eranian@hpl.hp.com>
  */
 
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
--- a/include/asm-ia64/pgtable.h	Thu Oct 31 21:45:22 2002
+++ b/include/asm-ia64/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -317,8 +317,8 @@
  * Find an entry in the third-level page table.  This looks more complicated than it
  * should be because some platforms place page tables in high memory.
  */
-#define __pte_offset(addr)	 	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-#define pte_offset_kernel(dir,addr)	((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(addr))
+#define pte_index(addr)	 	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir,addr)	((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir,addr)	pte_offset_kernel(dir, addr)
 #define pte_offset_map_nested(dir,addr)	pte_offset_map(dir, addr)
 #define pte_unmap(pte)			do { } while (0)
diff -Nru a/include/asm-ia64/posix_types.h b/include/asm-ia64/posix_types.h
--- a/include/asm-ia64/posix_types.h	Tue Feb  5 09:39:54 2002
+++ b/include/asm-ia64/posix_types.h	Thu Mar  6 21:11:46 2003
@@ -6,8 +6,8 @@
  * be a little careful about namespace pollution etc.  Also, we cannot
  * assume GCC is being used.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 typedef unsigned int	__kernel_dev_t;
@@ -26,6 +26,8 @@
 typedef long		__kernel_time_t;
 typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
 typedef unsigned long	__kernel_sigset_t;	/* at least 32 bits */
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	Tue Jan 14 22:14:16 2003
+++ b/include/asm-ia64/processor.h	Mon Mar 10 10:20:31 2003
@@ -68,11 +68,11 @@
 
 
 /*
- * This shift should be large enough to be able to represent
- * 1000000/itc_freq with good accuracy while being small enough to fit
- * 1000000<<IA64_USEC_PER_CYC_SHIFT in 64 bits.
+ * This shift should be large enough to be able to represent 1000000000/itc_freq with good
+ * accuracy while being small enough to fit 10*1000000000<<IA64_NSEC_PER_CYC_SHIFT in 64 bits
+ * (this will give enough slack to represent 10 seconds worth of time as a scaled number).
  */
-#define IA64_USEC_PER_CYC_SHIFT	41
+#define IA64_NSEC_PER_CYC_SHIFT	30
 
 #ifndef __ASSEMBLY__
 
@@ -161,7 +161,7 @@
 	__u64 itc_freq;		/* frequency of ITC counter */
 	__u64 proc_freq;	/* frequency of processor */
 	__u64 cyc_per_usec;	/* itc_freq/1000000 */
-	__u64 usec_per_cyc;	/* 2^IA64_USEC_PER_CYC_SHIFT*1000000/itc_freq */
+	__u64 nsec_per_cyc;	/* (1000000000<<IA64_NSEC_PER_CYC_SHIFT)/itc_freq */
 	__u64 unimpl_va_mask;	/* mask of unimplemented virtual address bits (from PAL) */
 	__u64 unimpl_pa_mask;	/* mask of unimplemented physical address bits (from PAL) */
 	__u64 ptce_base;
@@ -220,8 +220,6 @@
 		 (int *) (addr));								\
 })
 
-struct siginfo;
-
 struct thread_struct {
 	__u32 flags;			/* various thread flags (see IA64_THREAD_*) */
 	/* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */
@@ -230,7 +228,6 @@
 	__u64 ksp;			/* kernel stack pointer */
 	__u64 map_base;			/* base address for get_unmapped_area() */
 	__u64 task_size;		/* limit for task size */
-	struct siginfo *siginfo;	/* current siginfo struct for ptrace() */
 	int last_fph_cpu;		/* CPU that may hold the contents of f32-f127 */
 
 #ifdef CONFIG_IA32_SUPPORT
@@ -284,7 +281,6 @@
 	.ksp =		0,			\
 	.map_base =	DEFAULT_MAP_BASE,	\
 	.task_size =	DEFAULT_TASK_SIZE,	\
-	.siginfo =	0,			\
 	.last_fph_cpu =  0,			\
 	INIT_THREAD_IA32			\
 	INIT_THREAD_PM				\
@@ -347,6 +343,9 @@
 #else
 # define release_thread(dead_task)
 #endif
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
 
 /*
  * This is the mechanism for creating a new kernel thread.
diff -Nru a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
--- a/include/asm-ia64/ptrace.h	Fri Jan 24 11:56:49 2003
+++ b/include/asm-ia64/ptrace.h	Wed Feb 12 00:11:33 2003
@@ -289,8 +289,8 @@
  * not overlap with any of the number assigned in <linux/ptrace.h>.
  */
 #define PTRACE_SINGLEBLOCK	12	/* resume execution until next branch */
-#define PTRACE_GETSIGINFO	13	/* get child's siginfo structure */
-#define PTRACE_SETSIGINFO	14	/* set child's siginfo structure */
+#define PTRACE_OLD_GETSIGINFO	13	/* (replaced by PTRACE_GETSIGINFO in <linux/ptrace.h>)  */
+#define PTRACE_OLD_SETSIGINFO	14	/* (replaced by PTRACE_SETSIGINFO in <linux/ptrace.h>)  */
 #define PTRACE_GETREGS		18	/* get all registers (pt_all_user_regs) in one shot */
 #define PTRACE_SETREGS		19	/* set all registers (pt_all_user_regs) in one shot */
 
diff -Nru a/include/asm-ia64/rwsem.h b/include/asm-ia64/rwsem.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/rwsem.h	Thu Mar  6 11:22:21 2003
@@ -0,0 +1,188 @@
+/*
+ * asm-ia64/rwsem.h: R/W semaphores for ia64
+ *
+ * Copyright (C) 2003 Ken Chen <kenneth.w.chen@intel.com>
+ * Copyright (C) 2003 Asit Mallick <asit.k.mallick@intel.com>
+ *
+ * Based on asm-i386/rwsem.h and other architecture implementation.
+ *
+ * The MSW of the count is the negated number of active writers and
+ * waiting lockers, and the LSW is the total number of active locks.
+ *
+ * The lock count is initialized to 0 (no active and no waiting lockers).
+ *
+ * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case
+ * of an uncontended lock. Readers increment by 1 and see a positive value
+ * when uncontended, negative if there are writers (and maybe) readers
+ * waiting (in which case it goes to sleep).
+ */
+
+#ifndef _ASM_IA64_RWSEM_H
+#define _ASM_IA64_RWSEM_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+	signed int		count;
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#if RWSEM_DEBUG
+	int			debug;
+#endif
+};
+
+#define RWSEM_UNLOCKED_VALUE		0x00000000
+#define RWSEM_ACTIVE_BIAS		0x00000001
+#define RWSEM_ACTIVE_MASK		0x0000ffff
+#define RWSEM_WAITING_BIAS		(-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+
+/*
+ * initialization
+ */
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT      , 0
+#else
+#define __RWSEM_DEBUG_INIT	/* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name) \
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+static inline void
+init_rwsem (struct rw_semaphore *sem)
+{
+	sem->count = RWSEM_UNLOCKED_VALUE;
+	spin_lock_init(&sem->wait_lock);
+	INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+	sem->debug = 0;
+#endif
+}
+
+/*
+ * lock for reading
+ */
+static inline void
+__down_read (struct rw_semaphore *sem)
+{
+	int result;
+	__asm__ __volatile__ ("fetchadd4.acq %0=[%1],1" :
+			      "=r"(result) : "r"(&sem->count) : "memory");
+	if (result < 0)
+		rwsem_down_read_failed(sem);
+}
+
+/*
+ * lock for writing
+ */
+static inline void
+__down_write (struct rw_semaphore *sem)
+{
+	int old, new;
+
+	do {
+		old = sem->count;
+		new = old + RWSEM_ACTIVE_WRITE_BIAS;
+	} while (cmpxchg_acq(&sem->count, old, new) != old);
+
+	if (old != 0)
+		rwsem_down_write_failed(sem);
+}
+
+/*
+ * unlock after reading
+ */
+static inline void
+__up_read (struct rw_semaphore *sem)
+{
+	int result;
+	__asm__ __volatile__ ("fetchadd4.rel %0=[%1],-1" :
+			      "=r"(result) : "r"(&sem->count) : "memory");
+	if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void
+__up_write (struct rw_semaphore *sem)
+{
+	int old, new;
+
+	do {
+		old = sem->count;
+		new = old - RWSEM_ACTIVE_WRITE_BIAS;
+	} while (cmpxchg_rel(&sem->count, old, new) != old);
+
+	if (new < 0 && (new & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * trylock for reading -- returns 1 if successful, 0 if contention
+ */
+static inline int
+__down_read_trylock (struct rw_semaphore *sem)
+{
+	int tmp;
+	while ((tmp = sem->count) >= 0) {
+		if (tmp == cmpxchg_acq(&sem->count, tmp, tmp+1)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * trylock for writing -- returns 1 if successful, 0 if contention
+ */
+static inline int
+__down_write_trylock (struct rw_semaphore *sem)
+{
+	int tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE,
+			      RWSEM_ACTIVE_WRITE_BIAS);
+	return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void
+__downgrade_write (struct rw_semaphore *sem)
+{
+	int old, new;
+
+	do {
+		old = sem->count;
+		new = old - RWSEM_WAITING_BIAS;
+	} while (cmpxchg_rel(&sem->count, old, new) != old);
+
+	if (old < 0)
+		rwsem_downgrade_wake(sem);
+}
+
+/*
+ * Implement atomic add functionality.  These used to be "inline" functions, but GCC v3.1
+ * doesn't quite optimize this stuff right and ends up with bad calls to fetchandadd.
+ */
+#define rwsem_atomic_add(delta, sem)	atomic_add(delta, (atomic_t *)(&(sem)->count))
+#define rwsem_atomic_update(delta, sem)	atomic_add_return(delta, (atomic_t *)(&(sem)->count))
+
+#endif /* _ASM_IA64_RWSEM_H */
diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
--- a/include/asm-ia64/sal.h	Mon Sep 16 09:26:30 2002
+++ b/include/asm-ia64/sal.h	Tue Mar  4 18:33:56 2003
@@ -10,8 +10,8 @@
  * Copyright (C) 2001 Intel
  * Copyright (C) 2002 Jenna Hall <jenna.s.hall@intel.com>
  * Copyright (C) 2001 Fred Lewis <frederick.v.lewis@intel.com>
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
  *
  * 02/01/04 J. Hall Updated Error Record Structures to conform to July 2001
@@ -19,7 +19,7 @@
  * 01/01/03 fvlewis Updated Error Record Structures to conform with Nov. 2000
  *                  revision of the SAL spec.
  * 99/09/29 davidm	Updated for SAL 2.6.
- * 00/03/29 cfleck      Updated SAL Error Logging info for processor (SAL 2.6) 
+ * 00/03/29 cfleck      Updated SAL Error Logging info for processor (SAL 2.6)
  *                      (plus examples of platform error info structures from smariset @ Intel)
  */
 
@@ -208,30 +208,30 @@
 
 /* SAL information type encodings */
 enum {
-	SAL_INFO_TYPE_MCA	=		0,	/* Machine check abort information */
-        SAL_INFO_TYPE_INIT	=		1,	/* Init information */
-        SAL_INFO_TYPE_CMC   =       2,  /* Corrected machine check information */
-        SAL_INFO_TYPE_CPE   =       3   /* Corrected platform error information */
+	SAL_INFO_TYPE_MCA  = 0,		/* Machine check abort information */
+        SAL_INFO_TYPE_INIT = 1,		/* Init information */
+        SAL_INFO_TYPE_CMC  = 2,		/* Corrected machine check information */
+        SAL_INFO_TYPE_CPE  = 3		/* Corrected platform error information */
 };
 
 /* Encodings for machine check parameter types */
 enum {
-        SAL_MC_PARAM_RENDEZ_INT		=	1,	/* Rendezevous interrupt */
-        SAL_MC_PARAM_RENDEZ_WAKEUP  =   2,  /* Wakeup */
-        SAL_MC_PARAM_CPE_INT        =   3   /* Corrected Platform Error Int */
+	SAL_MC_PARAM_RENDEZ_INT    = 1,	/* Rendezevous interrupt */
+	SAL_MC_PARAM_RENDEZ_WAKEUP = 2,	/* Wakeup */
+	SAL_MC_PARAM_CPE_INT	   = 3	/* Corrected Platform Error Int */
 };
 
 /* Encodings for rendezvous mechanisms */
 enum {
-        SAL_MC_PARAM_MECHANISM_INT	=	1,	/* Use interrupt */
-        SAL_MC_PARAM_MECHANISM_MEM	=	2	/* Use memory synchronization variable*/
+	SAL_MC_PARAM_MECHANISM_INT = 1,	/* Use interrupt */
+	SAL_MC_PARAM_MECHANISM_MEM = 2	/* Use memory synchronization variable*/
 };
 
 /* Encodings for vectors which can be registered by the OS with SAL */
 enum {
-	SAL_VECTOR_OS_MCA		= 0,
-	SAL_VECTOR_OS_INIT		= 1,
-	SAL_VECTOR_OS_BOOT_RENDEZ	= 2
+	SAL_VECTOR_OS_MCA	  = 0,
+	SAL_VECTOR_OS_INIT	  = 1,
+	SAL_VECTOR_OS_BOOT_RENDEZ = 2
 };
 
 /* Encodings for mca_opt parameter sent to SAL_MC_SET_PARAMS */
@@ -239,387 +239,370 @@
 #define	SAL_MC_PARAM_BINIT_ESCALATE	0x10
 
 /*
-** Definition of the SAL Error Log from the SAL spec
-*/
+ * Definition of the SAL Error Log from the SAL spec
+ */
 
 /* SAL Error Record Section GUID Definitions */
 #define SAL_PROC_DEV_ERR_SECT_GUID  \
-    EFI_GUID ( 0xe429faf1, 0x3cb7, 0x11d4,  0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf1, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_MEM_DEV_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf2, 0x3cb7, 0x11d4,  0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf2, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_SEL_DEV_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_PCI_BUS_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_PCI_COMP_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_SPECIFIC_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_HOST_CTLR_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_BUS_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 
-#define MAX_CACHE_ERRORS			6
-#define MAX_TLB_ERRORS				6
-#define MAX_BUS_ERRORS				1
+#define MAX_CACHE_ERRORS	6
+#define MAX_TLB_ERRORS		6
+#define MAX_BUS_ERRORS		1
 
 /* Definition of version  according to SAL spec for logging purposes */
-typedef struct sal_log_revision
-{
-    u8  minor;              /* BCD (0..99) */
-    u8  major;              /* BCD (0..99) */
+typedef struct sal_log_revision {
+	u8 minor;		/* BCD (0..99) */
+	u8 major;		/* BCD (0..99) */
 } sal_log_revision_t;
 
 /* Definition of timestamp according to SAL spec for logging purposes */
-typedef struct sal_log_timestamp
-{
+typedef struct sal_log_timestamp {
 	u8 slh_second;		/* Second (0..59) */
-    u8 slh_minute;      /* Minute (0..59) */
-    u8 slh_hour;        /* Hour (0..23) */
-    u8 slh_reserved;
-    u8 slh_day;         /* Day (1..31) */
-    u8 slh_month;       /* Month (1..12) */
-    u8 slh_year;        /* Year (00..99) */
-    u8 slh_century;     /* Century (19, 20, 21, ...) */
+	u8 slh_minute;		/* Minute (0..59) */
+	u8 slh_hour;		/* Hour (0..23) */
+	u8 slh_reserved;
+	u8 slh_day;		/* Day (1..31) */
+	u8 slh_month;		/* Month (1..12) */
+	u8 slh_year;		/* Year (00..99) */
+	u8 slh_century;		/* Century (19, 20, 21, ...) */
 } sal_log_timestamp_t;
 
 /* Definition of log record  header structures */
-typedef struct sal_log_record_header
-{
-    u64                 id;             /* Unique monotonically increasing ID */
-    sal_log_revision_t  revision;       /* Major and Minor revision of header */
-    u16                 severity;       /* Error Severity */
-    u32                 len;            /* Length of this error log in bytes */
-    sal_log_timestamp_t timestamp;      /* Timestamp */
-    efi_guid_t          platform_guid;  /* Unique OEM Platform ID */
+typedef struct sal_log_record_header {
+	u64 id;				/* Unique monotonically increasing ID */
+	sal_log_revision_t revision;	/* Major and Minor revision of header */
+	u16 severity;			/* Error Severity */
+	u32 len;			/* Length of this error log in bytes */
+	sal_log_timestamp_t timestamp;	/* Timestamp */
+	efi_guid_t platform_guid;	/* Unique OEM Platform ID */
 } sal_log_record_header_t;
 
 /* Definition of log section header structures */
-typedef struct sal_log_sec_header
-{
-    efi_guid_t          guid;       /* Unique Section ID */
-    sal_log_revision_t  revision;   /* Major and Minor revision of Section */
-    u16                 reserved;
-    u32                 len;        /* Section length */
+typedef struct sal_log_sec_header {
+    efi_guid_t guid;			/* Unique Section ID */
+    sal_log_revision_t revision;	/* Major and Minor revision of Section */
+    u16 reserved;
+    u32 len;				/* Section length */
 } sal_log_section_hdr_t;
 
-typedef struct sal_log_mod_error_info
-{
-    struct
-    {
-        u64 check_info              : 1,
-            requestor_identifier    : 1,
-            responder_identifier    : 1,
-            target_identifier       : 1,
-            precise_ip              : 1,
-            reserved                : 59;
-    } valid;
-    u64 check_info;
-    u64 requestor_identifier;
-    u64 responder_identifier;
-    u64 target_identifier;
-    u64 precise_ip;
+typedef struct sal_log_mod_error_info {
+	struct {
+		u64 check_info              : 1,
+		    requestor_identifier    : 1,
+		    responder_identifier    : 1,
+		    target_identifier       : 1,
+		    precise_ip              : 1,
+		    reserved                : 59;
+	} valid;
+	u64 check_info;
+	u64 requestor_identifier;
+	u64 responder_identifier;
+	u64 target_identifier;
+	u64 precise_ip;
 } sal_log_mod_error_info_t;
 
-typedef struct sal_processor_static_info
-{
-    struct
-    {
-        u64 minstate        : 1,
-            br              : 1,
-            cr              : 1,
-            ar              : 1,
-            rr              : 1,
-            fr              : 1,
-            reserved        : 58;
-    } valid;
-    pal_min_state_area_t    min_state_area;
-    u64                     br[8];
-    u64                     cr[128];
-    u64                     ar[128];
-    u64                     rr[8];
-    struct ia64_fpreg       fr[128];
+typedef struct sal_processor_static_info {
+	struct {
+		u64 minstate        : 1,
+		    br              : 1,
+		    cr              : 1,
+		    ar              : 1,
+		    rr              : 1,
+		    fr              : 1,
+		    reserved        : 58;
+	} valid;
+	pal_min_state_area_t min_state_area;
+	u64 br[8];
+	u64 cr[128];
+	u64 ar[128];
+	u64 rr[8];
+	struct ia64_fpreg fr[128];
 } sal_processor_static_info_t;
 
-typedef struct sal_log_processor_info
-{
-    sal_log_section_hdr_t       header;
-    struct
-    {
-        u64 proc_error_map      : 1,
-            proc_state_param    : 1,
-            proc_cr_lid         : 1,
-            psi_static_struct   : 1,
-            num_cache_check     : 4,
-            num_tlb_check       : 4,
-            num_bus_check       : 4,
-            num_reg_file_check  : 4,
-            num_ms_check        : 4,
-            cpuid_info          : 1,
-            reserved1           : 39;
-    } valid;
-    u64                         proc_error_map;
-    u64                         proc_state_parameter;
-    u64                         proc_cr_lid;
-    sal_log_mod_error_info_t    cache_check_info[16];
-    sal_log_mod_error_info_t    tlb_check_info[16];
-    sal_log_mod_error_info_t    bus_check_info[16];
-    sal_log_mod_error_info_t    reg_file_check_info[16];
-    sal_log_mod_error_info_t    ms_check_info[16];
-    struct
-    {
-        u64 regs[5];
-        u64 reserved;
-    } cpuid_info;
-    sal_processor_static_info_t processor_static_info;
+struct sal_cpuid_info {
+	u64 regs[5];
+	u64 reserved;
+};
+
+typedef struct sal_log_processor_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 proc_error_map      : 1,
+		    proc_state_param    : 1,
+		    proc_cr_lid         : 1,
+		    psi_static_struct   : 1,
+		    num_cache_check     : 4,
+		    num_tlb_check       : 4,
+		    num_bus_check       : 4,
+		    num_reg_file_check  : 4,
+		    num_ms_check        : 4,
+		    cpuid_info          : 1,
+		    reserved1           : 39;
+	} valid;
+	u64 proc_error_map;
+	u64 proc_state_parameter;
+	u64 proc_cr_lid;
+	/*
+	 * The rest of this structure consists of variable-length arrays, which can't be
+	 * expressed in C.
+	 */
+	sal_log_mod_error_info_t info[0];
+	/*
+	 * This is what the rest looked like if C supported variable-length arrays:
+	 *
+	 * sal_log_mod_error_info_t cache_check_info[.valid.num_cache_check];
+	 * sal_log_mod_error_info_t tlb_check_info[.valid.num_tlb_check];
+	 * sal_log_mod_error_info_t bus_check_info[.valid.num_bus_check];
+	 * sal_log_mod_error_info_t reg_file_check_info[.valid.num_reg_file_check];
+	 * sal_log_mod_error_info_t ms_check_info[.valid.num_ms_check];
+	 * struct sal_cpuid_info cpuid_info;
+	 * sal_processor_static_info_t processor_static_info;
+	 */
 } sal_log_processor_info_t;
 
+/* Given a sal_log_processor_info_t pointer, return a pointer to the processor_static_info: */
+#define SAL_LPI_PSI_INFO(l)									\
+({	sal_log_processor_info_t *_l = (l);							\
+	((sal_processor_static_info_t *)							\
+	 ((char *) _l->info + ((_l->valid.num_cache_check + _l->valid.num_tlb_check		\
+				+ _l->valid.num_bus_check + _l->valid.num_reg_file_check	\
+				+ _l->valid.num_ms_check) * sizeof(sal_log_mod_error_info_t)	\
+			       + sizeof(struct sal_cpuid_info))));				\
+})
+
 /* platform error log structures */
 
-typedef struct sal_log_mem_dev_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 error_status    : 1,
-            physical_addr   : 1,
-            addr_mask       : 1,
-            node            : 1,
-            card            : 1,
-            module          : 1,
-            bank            : 1,
-            device          : 1,
-            row             : 1,
-            column          : 1,
-            bit_position    : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            bus_spec_data   : 1,
-            oem_id          : 1,
-            oem_data        : 1,
-            reserved        : 47;
-    } valid;
-    u64             error_status;
-    u64             physical_addr;
-    u64             addr_mask;
-    u16             node;
-    u16             card;
-    u16             module;
-    u16             bank;
-    u16             device;
-    u16             row;
-    u16             column;
-    u16             bit_position;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u64             bus_spec_data;
-    u8              oem_id[16];
-    u8              oem_data[1];        /* Variable length data */
+typedef struct sal_log_mem_dev_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 error_status    : 1,
+		    physical_addr   : 1,
+		    addr_mask       : 1,
+		    node            : 1,
+		    card            : 1,
+		    module          : 1,
+		    bank            : 1,
+		    device          : 1,
+		    row             : 1,
+		    column          : 1,
+		    bit_position    : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    bus_spec_data   : 1,
+		    oem_id          : 1,
+		    oem_data        : 1,
+		    reserved        : 47;
+	} valid;
+	u64 error_status;
+	u64 physical_addr;
+	u64 addr_mask;
+	u16 node;
+	u16 card;
+	u16 module;
+	u16 bank;
+	u16 device;
+	u16 row;
+	u16 column;
+	u16 bit_position;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u64 bus_spec_data;
+	u8 oem_id[16];
+	u8 oem_data[1];			/* Variable length data */
 } sal_log_mem_dev_err_info_t;
 
-typedef struct sal_log_sel_dev_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 record_id       : 1,
-            record_type     : 1,
-            generator_id    : 1,
-            evm_rev         : 1,
-            sensor_type     : 1,
-            sensor_num      : 1,
-            event_dir       : 1,
-            event_data1     : 1,
-            event_data2     : 1,
-            event_data3     : 1,
-            reserved        : 54;
-    } valid;
-    u16             record_id;
-    u8              record_type;
-    u8              timestamp[4];
-    u16             generator_id;
-    u8              evm_rev;
-    u8              sensor_type;
-    u8              sensor_num;
-    u8              event_dir;
-    u8              event_data1;
-    u8              event_data2;
-    u8              event_data3;
+typedef struct sal_log_sel_dev_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 record_id       : 1,
+		    record_type     : 1,
+		    generator_id    : 1,
+		    evm_rev         : 1,
+		    sensor_type     : 1,
+		    sensor_num      : 1,
+		    event_dir       : 1,
+		    event_data1     : 1,
+		    event_data2     : 1,
+		    event_data3     : 1,
+		    reserved        : 54;
+	} valid;
+	u16 record_id;
+	u8 record_type;
+	u8 timestamp[4];
+	u16 generator_id;
+	u8 evm_rev;
+	u8 sensor_type;
+	u8 sensor_num;
+	u8 event_dir;
+	u8 event_data1;
+	u8 event_data2;
+	u8 event_data3;
 } sal_log_sel_dev_err_info_t;
 
-typedef struct sal_log_pci_bus_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            err_type        : 1,
-            bus_id          : 1,
-            bus_address     : 1,
-            bus_data        : 1,
-            bus_cmd         : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            oem_data        : 1,
-            reserved        : 54;
-    } valid;
-    u64             err_status;
-    u16             err_type;
-    u16             bus_id;
-    u32             reserved;
-    u64             bus_address;
-    u64             bus_data;
-    u64             bus_cmd;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u8              oem_data[1];        /* Variable length data */
+typedef struct sal_log_pci_bus_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    err_type        : 1,
+		    bus_id          : 1,
+		    bus_address     : 1,
+		    bus_data        : 1,
+		    bus_cmd         : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    oem_data        : 1,
+		    reserved        : 54;
+	} valid;
+	u64 err_status;
+	u16 err_type;
+	u16 bus_id;
+	u32 reserved;
+	u64 bus_address;
+	u64 bus_data;
+	u64 bus_cmd;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u8 oem_data[1];			/* Variable length data */
 } sal_log_pci_bus_err_info_t;
 
-typedef struct sal_log_smbios_dev_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 event_type      : 1,
-            length          : 1,
-            time_stamp      : 1,
-            data            : 1,
-            reserved1       : 60;
-    } valid;
-    u8              event_type;
-    u8              length;
-    u8              time_stamp[6];
-    u8              data[1];  // data of variable length, length == slsmb_length
+typedef struct sal_log_smbios_dev_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 event_type      : 1,
+		    length          : 1,
+		    time_stamp      : 1,
+		    data            : 1,
+		    reserved1       : 60;
+	} valid;
+	u8 event_type;
+	u8 length;
+	u8 time_stamp[6];
+	u8 data[1];			/* data of variable length, length == slsmb_length */
 } sal_log_smbios_dev_err_info_t;
 
-typedef struct sal_log_pci_comp_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            comp_info       : 1,
-            num_mem_regs    : 1,
-            num_io_regs     : 1,
-            reg_data_pairs  : 1,
-            oem_data        : 1,
-            reserved        : 58;
-    } valid;
-    u64             err_status;
-    struct
-    {
-        u16 vendor_id;
-        u16 device_id;
-	u8  class_code[3];
-        u8  func_num;
-        u8  dev_num;
-        u8  bus_num;
-        u8  seg_num;
-        u8  reserved[5];
-    }               comp_info;
-    u32             num_mem_regs;
-    u32             num_io_regs;
-    u64             reg_data_pairs[1];
-    /* array of address/data register pairs is num_mem_regs + num_io_regs
-       elements long.  Each array element consists of a u64 address followed
-       by a u64 data value.  The oem_data array immediately follows the
-       reg_data_pairs array */
-    u8              oem_data[1];        /* Variable length data */
+typedef struct sal_log_pci_comp_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    comp_info       : 1,
+		    num_mem_regs    : 1,
+		    num_io_regs     : 1,
+		    reg_data_pairs  : 1,
+		    oem_data        : 1,
+		    reserved        : 58;
+	} valid;
+	u64 err_status;
+	struct {
+		u16 vendor_id;
+		u16 device_id;
+		u8 class_code[3];
+		u8 func_num;
+		u8 dev_num;
+		u8 bus_num;
+		u8 seg_num;
+		u8 reserved[5];
+	} comp_info;
+	u32 num_mem_regs;
+	u32 num_io_regs;
+	u64 reg_data_pairs[1];
+	/*
+	 * array of address/data register pairs is num_mem_regs + num_io_regs elements
+	 * long.  Each array element consists of a u64 address followed by a u64 data
+	 * value.  The oem_data array immediately follows the reg_data_pairs array
+	 */
+	u8 oem_data[1];			/* Variable length data */
 } sal_log_pci_comp_err_info_t;
 
-typedef struct sal_log_plat_specific_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            guid            : 1,
-            oem_data        : 1,
-            reserved        : 61;
-    } valid;
-    u64             err_status;
-    efi_guid_t      guid;
-    u8              oem_data[1];      /* platform specific variable length data */
+typedef struct sal_log_plat_specific_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    guid            : 1,
+		    oem_data        : 1,
+		    reserved        : 61;
+	} valid;
+	u64 err_status;
+	efi_guid_t guid;
+	u8 oem_data[1];			/* platform specific variable length data */
 } sal_log_plat_specific_err_info_t;
 
-typedef struct sal_log_host_ctlr_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            bus_spec_data   : 1,
-            oem_data        : 1,
-            reserved        : 58;
-    } valid;
-    u64             err_status;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u64             bus_spec_data;
-    u8              oem_data[1];        /* Variable length OEM data */
+typedef struct sal_log_host_ctlr_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    bus_spec_data   : 1,
+		    oem_data        : 1,
+		    reserved        : 58;
+	} valid;
+	u64 err_status;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u64 bus_spec_data;
+	u8 oem_data[1];			/* Variable length OEM data */
 } sal_log_host_ctlr_err_info_t;
 
-typedef struct sal_log_plat_bus_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            bus_spec_data   : 1,
-            oem_data        : 1,
-            reserved        : 58;
-    } valid;
-    u64             err_status;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u64             bus_spec_data;
-    u8              oem_data[1];        /* Variable length OEM data */
+typedef struct sal_log_plat_bus_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    bus_spec_data   : 1,
+		    oem_data        : 1,
+		    reserved        : 58;
+	} valid;
+	u64 err_status;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u64 bus_spec_data;
+	u8 oem_data[1];			/* Variable length OEM data */
 } sal_log_plat_bus_err_info_t;
 
 /* Overall platform error section structure */
-typedef union sal_log_platform_err_info
-{
-    sal_log_mem_dev_err_info_t          mem_dev_err;
-    sal_log_sel_dev_err_info_t          sel_dev_err;
-    sal_log_pci_bus_err_info_t          pci_bus_err;
-    sal_log_smbios_dev_err_info_t       smbios_dev_err;
-    sal_log_pci_comp_err_info_t         pci_comp_err;
-    sal_log_plat_specific_err_info_t    plat_specific_err;
-    sal_log_host_ctlr_err_info_t        host_ctlr_err;
-    sal_log_plat_bus_err_info_t         plat_bus_err;
+typedef union sal_log_platform_err_info {
+	sal_log_mem_dev_err_info_t mem_dev_err;
+	sal_log_sel_dev_err_info_t sel_dev_err;
+	sal_log_pci_bus_err_info_t pci_bus_err;
+	sal_log_smbios_dev_err_info_t smbios_dev_err;
+	sal_log_pci_comp_err_info_t pci_comp_err;
+	sal_log_plat_specific_err_info_t plat_specific_err;
+	sal_log_host_ctlr_err_info_t host_ctlr_err;
+	sal_log_plat_bus_err_info_t plat_bus_err;
 } sal_log_platform_err_info_t;
 
 /* SAL log over-all, multi-section error record structure (processor+platform) */
-typedef struct err_rec
-{
-    sal_log_record_header_t     sal_elog_header;
-    sal_log_processor_info_t    proc_err;
-    sal_log_platform_err_info_t plat_err;
-    u8                          oem_data_pad[1024];
+typedef struct err_rec {
+	sal_log_record_header_t sal_elog_header;
+	sal_log_processor_info_t proc_err;
+	sal_log_platform_err_info_t plat_err;
+	u8 oem_data_pad[1024];
 } ia64_err_rec_t;
 
 /*
@@ -648,7 +631,6 @@
 }
 
 
-	
 /* Initialize all the processor and platform level instruction and data caches */
 static inline s64
 ia64_sal_cache_init (void)
@@ -658,8 +640,9 @@
 	return isrv.status;
 }
 
-/* Clear the processor and platform information logged by SAL with respect to the 
- * machine state at the time of MCA's, INITs, CMCs, or CPEs.
+/*
+ * Clear the processor and platform information logged by SAL with respect to the machine
+ * state at the time of MCA's, INITs, CMCs, or CPEs.
  */
 static inline s64
 ia64_sal_clear_state_info (u64 sal_info_type)
@@ -684,9 +667,11 @@
 		return 0;
 
 	return isrv.v0;
-}	
-/* Get the maximum size of the information logged by SAL with respect to the machine 
- * state at the time of MCAs, INITs, CMCs, or CPEs.
+}
+
+/*
+ * Get the maximum size of the information logged by SAL with respect to the machine state
+ * at the time of MCAs, INITs, CMCs, or CPEs.
  */
 static inline u64
 ia64_sal_get_state_info_size (u64 sal_info_type)
@@ -699,8 +684,9 @@
 	return isrv.v0;
 }
 
-/* Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup
- * from the monarch processor.
+/*
+ * Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup from
+ * the monarch processor.
  */
 static inline s64
 ia64_sal_mc_rendez (void)
@@ -710,15 +696,17 @@
 	return isrv.status;
 }
 
-/* Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
- * the machine check rendezvous sequence as well as the mechanism to wake up the 
+/*
+ * Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
+ * the machine check rendezvous sequence as well as the mechanism to wake up the
  * non-monarch processor at the end of machine check processing.
  */
 static inline s64
 ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout, u64 rz_always)
 {
 	struct ia64_sal_retval isrv;
-	SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, timeout, rz_always, 0, 0);
+	SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val,
+		 timeout, rz_always, 0, 0);
 	return isrv.status;
 }
 
@@ -744,8 +732,8 @@
 }
 
 /*
- * Register physical addresses of locations needed by SAL when SAL
- * procedures are invoked in virtual mode.
+ * Register physical addresses of locations needed by SAL when SAL procedures are invoked
+ * in virtual mode.
  */
 static inline s64
 ia64_sal_register_physical_addr (u64 phys_entry, u64 phys_addr)
@@ -756,9 +744,10 @@
 	return isrv.status;
 }
 
-/* Register software dependent code locations within SAL. These locations are handlers
- * or entry points where SAL will pass control for the specified event. These event
- * handlers are for the bott rendezvous, MCAs and INIT scenarios.
+/*
+ * Register software dependent code locations within SAL. These locations are handlers or
+ * entry points where SAL will pass control for the specified event. These event handlers
+ * are for the bott rendezvous, MCAs and INIT scenarios.
  */
 static inline s64
 ia64_sal_set_vectors (u64 vector_type,
@@ -768,10 +757,11 @@
 	struct ia64_sal_retval isrv;
 	SAL_CALL(isrv, SAL_SET_VECTORS, vector_type,
 			handler_addr1, gp1, handler_len1,
-			handler_addr2, gp2, handler_len2);			
+			handler_addr2, gp2, handler_len2);
 
 	return isrv.status;
-}		
+}
+
 /* Update the contents of PAL block in the non-volatile storage device */
 static inline s64
 ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size,
diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
--- a/include/asm-ia64/siginfo.h	Tue Sep 24 12:15:49 2002
+++ b/include/asm-ia64/siginfo.h	Thu Mar  6 21:11:46 2003
@@ -33,8 +33,11 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			char _pad[sizeof(__ARCH_SI_UID_T) - sizeof(int)];
+			sigval_t _sigval;	/* must overlay ._rt._sigval! */
+			int _sys_private;	/* not to be passed to user */
 		} _timer;
 
 		/* POSIX.1b signals */
diff -Nru a/include/asm-ia64/sn/geo.h b/include/asm-ia64/sn/geo.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/geo.h	Mon Feb 24 04:35:17 2003
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef __SYS_GEO_H__
+#define __SYS_GEO_H__
+
+/* Include a platform-specific geo.h.  It must define at least:
+ *   geoid_t:		Geographic identifier data type
+ *   geo_type_t:	Data type for the kind of geoid this is
+ *   GEO_TYPE_xxx:	Values for geo_type_t vars, eg. GEO_TYPE_NODE
+ *   GEO_MAX_LEN:	The maximum length of a geoid, formatted for printing
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IA64_SGI_SN2
+#include <asm/sn/sn2/geo.h>
+#else
+
+#error <<BOMB! need geo.h for this platform >>
+
+#endif /* !SN2 && ... */
+
+/* Declarations applicable to all platforms */
+
+/* parameter for hwcfg_format_geoid() */
+#define GEO_FORMAT_HWGRAPH	1
+#define GEO_FORMAT_BRIEF	2
+
+/* (the parameter for hwcfg_format_geoid_compt() is defined in the
+ * platform-specific geo.h file) */
+
+/* Routines for manipulating geoid_t values */
+
+extern moduleid_t geo_module(geoid_t g);
+extern slabid_t geo_slab(geoid_t g);
+extern geo_type_t geo_type(geoid_t g);
+extern int geo_valid(geoid_t g);
+extern int geo_cmp(geoid_t g0, geoid_t g1);
+extern geoid_t geo_new(geo_type_t type, ...);
+
+extern geoid_t hwcfg_parse_geoid(char *buffer);
+extern void hwcfg_format_geoid(char *buffer, geoid_t m, int fmt);
+extern void hwcfg_format_geoid_compt(char *buffer, geoid_t m, int compt);
+extern geoid_t hwcfg_geo_get_self(geo_type_t type);
+extern geoid_t hwcfg_geo_get_by_nasid(geo_type_t type, nasid_t nasid);
+
+#endif /* __SYS_GEO_H__ */
diff -Nru a/include/asm-ia64/sn/ioconfig_bus.h b/include/asm-ia64/sn/ioconfig_bus.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/ioconfig_bus.h	Mon Feb 24 04:55:34 2003
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#define IOCONFIG_PCIBUS "/boot/efi/ioconfig_pcibus"
+#define POUND_CHAR                   '#'
+#define MAX_LINE_LEN	128
+#define MAXPATHLEN	128
+
+struct ioconfig_parm {
+	unsigned long ioconfig_activated;
+        unsigned long number;
+        void *buffer;
+};
+
+struct  ascii_moduleid{
+                unsigned char   io_moduleid[8]; /* pci path name */
+};
diff -Nru a/include/asm-ia64/sn/module.h b/include/asm-ia64/sn/module.h
--- a/include/asm-ia64/sn/module.h	Tue Dec  3 10:07:33 2002
+++ b/include/asm-ia64/sn/module.h	Mon Feb 24 05:28:24 2003
@@ -273,6 +273,9 @@
     cnodeid_t		nodes[MODULE_MAX_NODES];
 #ifdef CONFIG_IA64_SGI_SN2
     geoid_t		geoid[MODULE_MAX_NODES];
+    struct {
+		char	moduleid[8];
+    } io[MODULE_MAX_NODES];
 #endif
     int			nodecnt;	/* Number of nodes in array        */
 
diff -Nru a/include/asm-ia64/sn/pci/pic.h b/include/asm-ia64/sn/pci/pic.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/pci/pic.h	Mon Feb 24 04:49:11 2003
@@ -0,0 +1,2001 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+#ifndef _ASM_SN_PCI_PIC_H
+#define _ASM_SN_PCI_PIC_H
+
+
+/*
+ * The PIC ASIC is a follow-on to the Bridge and Xbridge ASICs.
+ * It shares many of the same registers as those chips and therefore
+ * the primary structure for the PIC will be bridge_s as defined
+ * in irix/kern/sys/PCI/bridge.h.   This file is intended as a complement
+ * to bridge.h, which includes this file.  
+ */
+
+/*
+ * PIC AS DEVICE ZERO
+ * ------------------
+ *
+ * PIC handles PCI/X busses.  PCI/X requires that the 'bridge' (i.e. PIC)
+ * be designated as 'device 0'.   That is a departure from earlier SGI
+ * PCI bridges.  Because of that we use config space 1 to access the
+ * config space of the first actual PCI device on the bus. 
+ * Here's what the PIC manual says:
+ *
+ *     The current PCI-X bus specification now defines that the parent
+ *     hosts bus bridge (PIC for example) must be device 0 on bus 0. PIC
+ *     reduced the total number of devices from 8 to 4 and removed the
+ *     device registers and windows, now only supporting devices 0,1,2, and
+ *     3. PIC did leave all 8 configuration space windows. The reason was
+ *     there was nothing to gain by removing them. Here in lies the problem.
+ *     The device numbering we do using 0 through 3 is unrelated to the device
+ *     numbering which PCI-X requires in configuration space. In the past we
+ *     correlated Configs pace and our device space 0 <-> 0, 1 <-> 1, etc.
+ *     PCI-X requires we start a 1, not 0 and currently the PX brick
+ *     does associate our:
+ * 
+ *         device 0 with configuration space window 1,
+ *         device 1 with configuration space window 2, 
+ *         device 2 with configuration space window 3,
+ *         device 3 with configuration space window 4.
+ *
+ * The net effect is that all config space access are off-by-one with 
+ * relation to other per-slot accesses on the PIC.   
+ * Here is a table that shows some of that:
+ *
+ *                               Internal Slot#
+ *           |
+ *           |     0         1        2         3
+ * ----------|---------------------------------------
+ * config    |  0x21000   0x22000  0x23000   0x24000
+ *           |
+ * even rrb  |  0[0]      n/a      1[0]      n/a	[] == implied even/odd
+ *           |
+ * odd rrb   |  n/a       0[1]     n/a       1[1]
+ *           |
+ * int dev   |  00       01        10        11
+ *           |
+ * ext slot# |  1        2         3         4
+ * ----------|---------------------------------------
+ */
+
+
+#ifndef __ASSEMBLY__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// #include <sys/types.h>
+#include <asm/sn/pci/pciio.h>
+
+
+/*********************************************************************
+ *    bus provider function table
+ *
+ *	Normally, this table is only handed off explicitly
+ *	during provider initialization, and the PCI generic
+ *	layer will stash a pointer to it in the vertex; however,
+ *	exporting it explicitly enables a performance hack in
+ *	the generic PCI provider where if we know at compile
+ *	time that the only possible PCI provider is a
+ *	pcibr, we can go directly to this ops table.
+ */
+
+extern pciio_provider_t pci_pic_provider;
+
+
+/*********************************************************************
+ * misc defines
+ *
+ */
+#define PIC_WIDGET_PART_NUM_BUS0 0xd102
+#define PIC_WIDGET_PART_NUM_BUS1 0xd112
+#define PIC_WIDGET_MFGR_NUM 0x24
+#define PIC_WIDGET_REV_A  0x1
+
+#define IS_PIC_PART_REV_A(rev) \
+	((rev == (PIC_WIDGET_PART_NUM_BUS0 << 4 | PIC_WIDGET_REV_A)) || \
+	(rev == (PIC_WIDGET_PART_NUM_BUS1 << 4 | PIC_WIDGET_REV_A)))
+
+/*********************************************************************
+ * register offset defines
+ *
+ */
+	/* Identification Register  -- read-only */
+#define PIC_IDENTIFICATION 0x00000000
+
+	/* Status Register  -- read-only */
+#define PIC_STATUS 0x00000008
+
+	/* Upper Address Holding Register Bus Side Errors  -- read-only */
+#define PIC_UPPER_ADDR_REG_BUS_SIDE_ERRS 0x00000010
+
+	/* Lower Address Holding Register Bus Side Errors  -- read-only */
+#define PIC_LOWER_ADDR_REG_BUS_SIDE_ERRS 0x00000018
+
+	/* Control Register  -- read/write */
+#define PIC_CONTROL 0x00000020
+
+	/* PCI Request Time-out Value Register  -- read/write */
+#define PIC_PCI_REQ_TIME_OUT_VALUE 0x00000028
+
+	/* Interrupt Destination Upper Address Register  -- read/write */
+#define PIC_INTR_DEST_UPPER_ADDR 0x00000030
+
+	/* Interrupt Destination Lower Address Register  -- read/write */
+#define PIC_INTR_DEST_LOWER_ADDR 0x00000038
+
+	/* Command Word Holding Register Bus Side  -- read-only */
+#define PIC_CMD_WORD_REG_BUS_SIDE 0x00000040
+
+	/* LLP Configuration Register (Bus 0 Only)  -- read/write */
+#define PIC_LLP_CFG_REG_(BUS_0_ONLY) 0x00000048
+
+	/* PCI Target Flush Register  -- read-only */
+#define PIC_PCI_TARGET_FLUSH 0x00000050
+
+	/* Command Word Holding Register Link Side  -- read-only */
+#define PIC_CMD_WORD_REG_LINK_SIDE 0x00000058
+
+	/* Response Buffer Error Upper Address Holding  -- read-only */
+#define PIC_RESP_BUF_ERR_UPPER_ADDR_ 0x00000060
+
+	/* Response Buffer Error Lower Address Holding  -- read-only */
+#define PIC_RESP_BUF_ERR_LOWER_ADDR_ 0x00000068
+
+	/* Test Pin Control Register  -- read/write */
+#define PIC_TEST_PIN_CONTROL 0x00000070
+
+	/* Address Holding Register Link Side Errors  -- read-only */
+#define PIC_ADDR_REG_LINK_SIDE_ERRS 0x00000078
+
+	/* Direct Map Register  -- read/write */
+#define PIC_DIRECT_MAP 0x00000080
+
+	/* PCI Map Fault Address Register  -- read-only */
+#define PIC_PCI_MAP_FAULT_ADDR 0x00000090
+
+	/* Arbitration Priority Register  -- read/write */
+#define PIC_ARBITRATION_PRIORITY 0x000000A0
+
+	/* Internal Ram Parity Error Register  -- read-only */
+#define PIC_INTERNAL_RAM_PARITY_ERR 0x000000B0
+
+	/* PCI Time-out Register  -- read/write */
+#define PIC_PCI_TIME_OUT 0x000000C0
+
+	/* PCI Type 1 Configuration Register  -- read/write */
+#define PIC_PCI_TYPE_1_CFG 0x000000C8
+
+	/* PCI Bus Error Upper Address Holding Register  -- read-only */
+#define PIC_PCI_BUS_ERR_UPPER_ADDR_ 0x000000D0
+
+	/* PCI Bus Error Lower Address Holding Register  -- read-only */
+#define PIC_PCI_BUS_ERR_LOWER_ADDR_ 0x000000D8
+
+	/* PCIX Error Address Register  -- read-only */
+#define PIC_PCIX_ERR_ADDR 0x000000E0
+
+	/* PCIX Error Attribute Register  -- read-only */
+#define PIC_PCIX_ERR_ATTRIBUTE 0x000000E8
+
+	/* PCIX Error Data Register  -- read-only */
+#define PIC_PCIX_ERR_DATA 0x000000F0
+
+	/* PCIX Read Request Timeout Error Register  -- read-only */
+#define PIC_PCIX_READ_REQ_TIMEOUT_ERR 0x000000F8
+
+	/* Interrupt Status Register  -- read-only */
+#define PIC_INTR_STATUS 0x00000100
+
+	/* Interrupt Enable Register  -- read/write */
+#define PIC_INTR_ENABLE 0x00000108
+
+	/* Reset Interrupt Status Register  -- write-only */
+#define PIC_RESET_INTR_STATUS 0x00000110
+
+	/* Interrupt Mode Register  -- read/write */
+#define PIC_INTR_MODE 0x00000118
+
+	/* Interrupt Device Register  -- read/write */
+#define PIC_INTR_DEVICE 0x00000120
+
+	/* Host Error Field Register  -- read/write */
+#define PIC_HOST_ERR_FIELD 0x00000128
+
+	/* Interrupt Pin 0 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_0_HOST_ADDR 0x00000130
+
+	/* Interrupt Pin 1 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_1_HOST_ADDR 0x00000138
+
+	/* Interrupt Pin 2 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_2_HOST_ADDR 0x00000140
+
+	/* Interrupt Pin 3 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_3_HOST_ADDR 0x00000148
+
+	/* Interrupt Pin 4 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_4_HOST_ADDR 0x00000150
+
+	/* Interrupt Pin 5 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_5_HOST_ADDR 0x00000158
+
+	/* Interrupt Pin 6 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_6_HOST_ADDR 0x00000160
+
+	/* Interrupt Pin 7 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_7_HOST_ADDR 0x00000168
+
+	/* Error Interrupt View Register  -- read-only */
+#define PIC_ERR_INTR_VIEW 0x00000170
+
+	/* Multiple Interrupt Register  -- read-only */
+#define PIC_MULTIPLE_INTR 0x00000178
+
+	/* Force Always Interrupt 0 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_0 0x00000180
+
+	/* Force Always Interrupt 1 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_1 0x00000188
+
+	/* Force Always Interrupt 2 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_2 0x00000190
+
+	/* Force Always Interrupt 3 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_3 0x00000198
+
+	/* Force Always Interrupt 4 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_4 0x000001A0
+
+	/* Force Always Interrupt 5 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_5 0x000001A8
+
+	/* Force Always Interrupt 6 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_6 0x000001B0
+
+	/* Force Always Interrupt 7 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_7 0x000001B8
+
+	/* Force w/Pin Interrupt 0 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_0 0x000001C0
+
+	/* Force w/Pin Interrupt 1 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_1 0x000001C8
+
+	/* Force w/Pin Interrupt 2 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_2 0x000001D0
+
+	/* Force w/Pin Interrupt 3 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_3 0x000001D8
+
+	/* Force w/Pin Interrupt 4 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_4 0x000001E0
+
+	/* Force w/Pin Interrupt 5 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_5 0x000001E8
+
+	/* Force w/Pin Interrupt 6 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_6 0x000001F0
+
+	/* Force w/Pin Interrupt 7 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_7 0x000001F8
+
+	/* Device 0 Register  -- read/write */
+#define PIC_DEVICE_0 0x00000200
+
+	/* Device 1 Register  -- read/write */
+#define PIC_DEVICE_1 0x00000208
+
+	/* Device 2 Register  -- read/write */
+#define PIC_DEVICE_2 0x00000210
+
+	/* Device 3 Register  -- read/write */
+#define PIC_DEVICE_3 0x00000218
+
+	/* Device 0 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_0_WRITE_REQ_BUF 0x00000240
+
+	/* Device 1 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_1_WRITE_REQ_BUF 0x00000248
+
+	/* Device 2 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_2_WRITE_REQ_BUF 0x00000250
+
+	/* Device 3 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_3_WRITE_REQ_BUF 0x00000258
+
+	/* Even Device Response Buffer Register  -- read/write */
+#define PIC_EVEN_DEVICE_RESP_BUF 0x00000280
+
+	/* Odd Device Response Buffer Register  -- read/write */
+#define PIC_ODD_DEVICE_RESP_BUF 0x00000288
+
+	/* Read Response Buffer Status Register  -- read-only */
+#define PIC_READ_RESP_BUF_STATUS 0x00000290
+
+	/* Read Response Buffer Clear Register  -- write-only */
+#define PIC_READ_RESP_BUF_CLEAR 0x00000298
+
+	/* PCI RR 0 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_0_UPPER_ADDR_MATCH 0x00000300
+
+	/* PCI RR 0 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_0_LOWER_ADDR_MATCH 0x00000308
+
+	/* PCI RR 1 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_1_UPPER_ADDR_MATCH 0x00000310
+
+	/* PCI RR 1 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_1_LOWER_ADDR_MATCH 0x00000318
+
+	/* PCI RR 2 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_2_UPPER_ADDR_MATCH 0x00000320
+
+	/* PCI RR 2 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_2_LOWER_ADDR_MATCH 0x00000328
+
+	/* PCI RR 3 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_3_UPPER_ADDR_MATCH 0x00000330
+
+	/* PCI RR 3 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_3_LOWER_ADDR_MATCH 0x00000338
+
+	/* PCI RR 4 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_4_UPPER_ADDR_MATCH 0x00000340
+
+	/* PCI RR 4 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_4_LOWER_ADDR_MATCH 0x00000348
+
+	/* PCI RR 5 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_5_UPPER_ADDR_MATCH 0x00000350
+
+	/* PCI RR 5 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_5_LOWER_ADDR_MATCH 0x00000358
+
+	/* PCI RR 6 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_6_UPPER_ADDR_MATCH 0x00000360
+
+	/* PCI RR 6 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_6_LOWER_ADDR_MATCH 0x00000368
+
+	/* PCI RR 7 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_7_UPPER_ADDR_MATCH 0x00000370
+
+	/* PCI RR 7 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_7_LOWER_ADDR_MATCH 0x00000378
+
+	/* PCI RR 8 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_8_UPPER_ADDR_MATCH 0x00000380
+
+	/* PCI RR 8 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_8_LOWER_ADDR_MATCH 0x00000388
+
+	/* PCI RR 9 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_9_UPPER_ADDR_MATCH 0x00000390
+
+	/* PCI RR 9 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_9_LOWER_ADDR_MATCH 0x00000398
+
+	/* PCI RR 10 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_10_UPPER_ADDR_MATCH 0x000003A0
+
+	/* PCI RR 10 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_10_LOWER_ADDR_MATCH 0x000003A8
+
+	/* PCI RR 11 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_11_UPPER_ADDR_MATCH 0x000003B0
+
+	/* PCI RR 11 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_11_LOWER_ADDR_MATCH 0x000003B8
+
+	/* PCI RR 12 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_12_UPPER_ADDR_MATCH 0x000003C0
+
+	/* PCI RR 12 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_12_LOWER_ADDR_MATCH 0x000003C8
+
+	/* PCI RR 13 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_13_UPPER_ADDR_MATCH 0x000003D0
+
+	/* PCI RR 13 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_13_LOWER_ADDR_MATCH 0x000003D8
+
+	/* PCI RR 14 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_14_UPPER_ADDR_MATCH 0x000003E0
+
+	/* PCI RR 14 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_14_LOWER_ADDR_MATCH 0x000003E8
+
+	/* PCI RR 15 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_15_UPPER_ADDR_MATCH 0x000003F0
+
+	/* PCI RR 15 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_15_LOWER_ADDR_MATCH 0x000003F8
+
+	/* Buffer 0 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_0_FLUSH_CNT_WITH_DATA_TOUCH 0x00000400
+
+	/* Buffer 0 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_0_FLUSH_CNT_W_O_DATA_TOUCH 0x00000408
+
+	/* Buffer 0 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_0_REQ_IN_FLIGHT_CNT 0x00000410
+
+	/* Buffer 0 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_0_PREFETCH_REQ_CNT 0x00000418
+
+	/* Buffer 0 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_0_TOTAL_PCI_RETRY_CNT 0x00000420
+
+	/* Buffer 0 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_0_MAX_PCI_RETRY_CNT 0x00000428
+
+	/* Buffer 0 Max Latency Count Register  -- read/write */
+#define PIC_BUF_0_MAX_LATENCY_CNT 0x00000430
+
+	/* Buffer 0 Clear All Register  -- read/write */
+#define PIC_BUF_0_CLEAR_ALL 0x00000438
+
+	/* Buffer 2 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_2_FLUSH_CNT_WITH_DATA_TOUCH 0x00000440
+
+	/* Buffer 2 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_2_FLUSH_CNT_W_O_DATA_TOUCH 0x00000448
+
+	/* Buffer 2 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_2_REQ_IN_FLIGHT_CNT 0x00000450
+
+	/* Buffer 2 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_2_PREFETCH_REQ_CNT 0x00000458
+
+	/* Buffer 2 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_2_TOTAL_PCI_RETRY_CNT 0x00000460
+
+	/* Buffer 2 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_2_MAX_PCI_RETRY_CNT 0x00000468
+
+	/* Buffer 2 Max Latency Count Register  -- read/write */
+#define PIC_BUF_2_MAX_LATENCY_CNT 0x00000470
+
+	/* Buffer 2 Clear All Register  -- read/write */
+#define PIC_BUF_2_CLEAR_ALL 0x00000478
+
+	/* Buffer 4 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_4_FLUSH_CNT_WITH_DATA_TOUCH 0x00000480
+
+	/* Buffer 4 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_4_FLUSH_CNT_W_O_DATA_TOUCH 0x00000488
+
+	/* Buffer 4 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_4_REQ_IN_FLIGHT_CNT 0x00000490
+
+	/* Buffer 4 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_4_PREFETCH_REQ_CNT 0x00000498
+
+	/* Buffer 4 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_4_TOTAL_PCI_RETRY_CNT 0x000004A0
+
+	/* Buffer 4 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_4_MAX_PCI_RETRY_CNT 0x000004A8
+
+	/* Buffer 4 Max Latency Count Register  -- read/write */
+#define PIC_BUF_4_MAX_LATENCY_CNT 0x000004B0
+
+	/* Buffer 4 Clear All Register  -- read/write */
+#define PIC_BUF_4_CLEAR_ALL 0x000004B8
+
+	/* Buffer 6 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_6_FLUSH_CNT_WITH_DATA_TOUCH 0x000004C0
+
+	/* Buffer 6 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_6_FLUSH_CNT_W_O_DATA_TOUCH 0x000004C8
+
+	/* Buffer 6 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_6_REQ_IN_FLIGHT_CNT 0x000004D0
+
+	/* Buffer 6 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_6_PREFETCH_REQ_CNT 0x000004D8
+
+	/* Buffer 6 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_6_TOTAL_PCI_RETRY_CNT 0x000004E0
+
+	/* Buffer 6 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_6_MAX_PCI_RETRY_CNT 0x000004E8
+
+	/* Buffer 6 Max Latency Count Register  -- read/write */
+#define PIC_BUF_6_MAX_LATENCY_CNT 0x000004F0
+
+	/* Buffer 6 Clear All Register  -- read/write */
+#define PIC_BUF_6_CLEAR_ALL 0x000004F8
+
+	/* Buffer 8 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_8_FLUSH_CNT_WITH_DATA_TOUCH 0x00000500
+
+	/* Buffer 8 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_8_FLUSH_CNT_W_O_DATA_TOUCH 0x00000508
+
+	/* Buffer 8 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_8_REQ_IN_FLIGHT_CNT 0x00000510
+
+	/* Buffer 8 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_8_PREFETCH_REQ_CNT 0x00000518
+
+	/* Buffer 8 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_8_TOTAL_PCI_RETRY_CNT 0x00000520
+
+	/* Buffer 8 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_8_MAX_PCI_RETRY_CNT 0x00000528
+
+	/* Buffer 8 Max Latency Count Register  -- read/write */
+#define PIC_BUF_8_MAX_LATENCY_CNT 0x00000530
+
+	/* Buffer 8 Clear All Register  -- read/write */
+#define PIC_BUF_8_CLEAR_ALL 0x00000538
+
+	/* Buffer 10 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_10_FLUSH_CNT_WITH_DATA_TOUCH 0x00000540
+
+	/* Buffer 10 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_10_FLUSH_CNT_W_O_DATA_TOUCH 0x00000548
+
+	/* Buffer 10 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_10_REQ_IN_FLIGHT_CNT 0x00000550
+
+	/* Buffer 10 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_10_PREFETCH_REQ_CNT 0x00000558
+
+	/* Buffer 10 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_10_TOTAL_PCI_RETRY_CNT 0x00000560
+
+	/* Buffer 10 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_10_MAX_PCI_RETRY_CNT 0x00000568
+
+	/* Buffer 10 Max Latency Count Register  -- read/write */
+#define PIC_BUF_10_MAX_LATENCY_CNT 0x00000570
+
+	/* Buffer 10 Clear All Register  -- read/write */
+#define PIC_BUF_10_CLEAR_ALL 0x00000578
+
+	/* Buffer 12 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_12_FLUSH_CNT_WITH_DATA_TOUCH 0x00000580
+
+	/* Buffer 12 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_12_FLUSH_CNT_W_O_DATA_TOUCH 0x00000588
+
+	/* Buffer 12 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_12_REQ_IN_FLIGHT_CNT 0x00000590
+
+	/* Buffer 12 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_12_PREFETCH_REQ_CNT 0x00000598
+
+	/* Buffer 12 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_12_TOTAL_PCI_RETRY_CNT 0x000005A0
+
+	/* Buffer 12 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_12_MAX_PCI_RETRY_CNT 0x000005A8
+
+	/* Buffer 12 Max Latency Count Register  -- read/write */
+#define PIC_BUF_12_MAX_LATENCY_CNT 0x000005B0
+
+	/* Buffer 12 Clear All Register  -- read/write */
+#define PIC_BUF_12_CLEAR_ALL 0x000005B8
+
+	/* Buffer 14 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_14_FLUSH_CNT_WITH_DATA_TOUCH 0x000005C0
+
+	/* Buffer 14 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_14_FLUSH_CNT_W_O_DATA_TOUCH 0x000005C8
+
+	/* Buffer 14 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_14_REQ_IN_FLIGHT_CNT 0x000005D0
+
+	/* Buffer 14 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_14_PREFETCH_REQ_CNT 0x000005D8
+
+	/* Buffer 14 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_14_TOTAL_PCI_RETRY_CNT 0x000005E0
+
+	/* Buffer 14 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_14_MAX_PCI_RETRY_CNT 0x000005E8
+
+	/* Buffer 14 Max Latency Count Register  -- read/write */
+#define PIC_BUF_14_MAX_LATENCY_CNT 0x000005F0
+
+	/* Buffer 14 Clear All Register  -- read/write */
+#define PIC_BUF_14_CLEAR_ALL 0x000005F8
+
+	/* PCIX Read Buffer 0 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_0_ADDR 0x00000A00
+
+	/* PCIX Read Buffer 0 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_0_ATTRIBUTE 0x00000A08
+
+	/* PCIX Read Buffer 1 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_1_ADDR 0x00000A10
+
+	/* PCIX Read Buffer 1 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_1_ATTRIBUTE 0x00000A18
+
+	/* PCIX Read Buffer 2 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_2_ADDR 0x00000A20
+
+	/* PCIX Read Buffer 2 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_2_ATTRIBUTE 0x00000A28
+
+	/* PCIX Read Buffer 3 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_3_ADDR 0x00000A30
+
+	/* PCIX Read Buffer 3 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_3_ATTRIBUTE 0x00000A38
+
+	/* PCIX Read Buffer 4 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_4_ADDR 0x00000A40
+
+	/* PCIX Read Buffer 4 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_4_ATTRIBUTE 0x00000A48
+
+	/* PCIX Read Buffer 5 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_5_ADDR 0x00000A50
+
+	/* PCIX Read Buffer 5 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_5_ATTRIBUTE 0x00000A58
+
+	/* PCIX Read Buffer 6 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_6_ADDR 0x00000A60
+
+	/* PCIX Read Buffer 6 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_6_ATTRIBUTE 0x00000A68
+
+	/* PCIX Read Buffer 7 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_7_ADDR 0x00000A70
+
+	/* PCIX Read Buffer 7 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_7_ATTRIBUTE 0x00000A78
+
+	/* PCIX Read Buffer 8 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_8_ADDR 0x00000A80
+
+	/* PCIX Read Buffer 8 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_8_ATTRIBUTE 0x00000A88
+
+	/* PCIX Read Buffer 9 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_9_ADDR 0x00000A90
+
+	/* PCIX Read Buffer 9 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_9_ATTRIBUTE 0x00000A98
+
+	/* PCIX Read Buffer 10 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_10_ADDR 0x00000AA0
+
+	/* PCIX Read Buffer 10 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_10_ATTRIBUTE 0x00000AA8
+
+	/* PCIX Read Buffer 11 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_11_ADDR 0x00000AB0
+
+	/* PCIX Read Buffer 11 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_11_ATTRIBUTE 0x00000AB8
+
+	/* PCIX Read Buffer 12 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_12_ADDR 0x00000AC0
+
+	/* PCIX Read Buffer 12 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_12_ATTRIBUTE 0x00000AC8
+
+	/* PCIX Read Buffer 13 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_13_ADDR 0x00000AD0
+
+	/* PCIX Read Buffer 13 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_13_ATTRIBUTE 0x00000AD8
+
+	/* PCIX Read Buffer 14 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_14_ADDR 0x00000AE0
+
+	/* PCIX Read Buffer 14 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_14_ATTRIBUTE 0x00000AE8
+
+	/* PCIX Read Buffer 15 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_15_ADDR 0x00000AF0
+
+	/* PCIX Read Buffer 15 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_15_ATTRIBUTE 0x00000AF8
+
+	/* PCIX Write Buffer 0 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_0_ADDR 0x00000B00
+
+	/* PCIX Write Buffer 0 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_0_ATTRIBUTE 0x00000B08
+
+	/* PCIX Write Buffer 0 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_0_VALID 0x00000B10
+
+	/* PCIX Write Buffer 1 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_1_ADDR 0x00000B20
+
+	/* PCIX Write Buffer 1 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_1_ATTRIBUTE 0x00000B28
+
+	/* PCIX Write Buffer 1 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_1_VALID 0x00000B30
+
+	/* PCIX Write Buffer 2 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_2_ADDR 0x00000B40
+
+	/* PCIX Write Buffer 2 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_2_ATTRIBUTE 0x00000B48
+
+	/* PCIX Write Buffer 2 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_2_VALID 0x00000B50
+
+	/* PCIX Write Buffer 3 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_3_ADDR 0x00000B60
+
+	/* PCIX Write Buffer 3 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_3_ATTRIBUTE 0x00000B68
+
+	/* PCIX Write Buffer 3 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_3_VALID 0x00000B70
+
+	/* PCIX Write Buffer 4 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_4_ADDR 0x00000B80
+
+	/* PCIX Write Buffer 4 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_4_ATTRIBUTE 0x00000B88
+
+	/* PCIX Write Buffer 4 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_4_VALID 0x00000B90
+
+	/* PCIX Write Buffer 5 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_5_ADDR 0x00000BA0
+
+	/* PCIX Write Buffer 5 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_5_ATTRIBUTE 0x00000BA8
+
+	/* PCIX Write Buffer 5 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_5_VALID 0x00000BB0
+
+	/* PCIX Write Buffer 6 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_6_ADDR 0x00000BC0
+
+	/* PCIX Write Buffer 6 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_6_ATTRIBUTE 0x00000BC8
+
+	/* PCIX Write Buffer 6 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_6_VALID 0x00000BD0
+
+	/* PCIX Write Buffer 7 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_7_ADDR 0x00000BE0
+
+	/* PCIX Write Buffer 7 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_7_ATTRIBUTE 0x00000BE8
+
+	/* PCIX Write Buffer 7 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_7_VALID 0x00000BF0
+
+/*********************************************************************
+ * misc typedefs
+ *
+ */
+typedef uint64_t picreg_t;
+
+/*********************************************************************
+ * PIC register structures
+ *
+ */
+
+/*
+ * Identification Register
+ *
+ * The Identification register is a read only register used by the host CPU
+ * during configuration to determine the type of the widget. The format is
+ * the same as defined in IEEE 1149.1 JTAG Device Identification Register.
+ */
+	typedef union pic_id_reg_u {
+		picreg_t	pic_id_reg_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t rev_num  :	4; /* 31:28 */
+			picreg_t part_num :	16; /* 27:12 */
+			picreg_t mfg_num  :	11; /* 11:1 */
+			picreg_t          :	1; /* 0:0 */
+		} pic_id_reg_fld_s;
+	} pic_id_reg_u_t;
+/*
+ * Status Register
+ *
+ * The status register is a read register which holds status information of the
+ * Bus Subsection.
+ */
+	typedef union pic_stat_reg_u {
+		picreg_t	pic_stat_reg_regval;
+		struct {
+			picreg_t                :	28; /* 63:36 */
+			picreg_t pci_x_speed    :	2; /* 35:34 */
+			picreg_t pci_x_active   :	1; /* 33:33 */
+			picreg_t                :	1; /* 32:32 */
+			picreg_t llp_rec_cnt    :	8; /* 31:24 */
+			picreg_t llp_tx_cnt     :	8; /* 23:16 */
+			picreg_t rx_credit_cnt  :	4; /* 15:12 */
+			picreg_t tx_credit_cnt  :	4; /* 11:8 */
+			picreg_t pci_misc_input :	8; /* 7:0 */
+		} pic_stat_reg_fld_s;
+	} pic_stat_reg_u_t;
+/*
+ * Upper Address Holding Register Bus Side Errors
+ *
+ * The upper address holding register is a read only register which contains
+ * the upper 16-bits of the address when certain error occurs (see error cases
+ * chapter). Subsequent errors are not logged until the error is cleared. The
+ * last logged value is held until the group is cleared and enabled.
+ */
+	typedef union pic_upper_bus_err_u {
+		picreg_t	pic_upper_bus_err_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	16; /* 31:16 */
+			picreg_t upp_addr :	16; /* 15:0 */
+		} pic_upper_bus_err_fld_s;
+	} pic_upper_bus_err_u_t;
+/*
+ * Lower Address Holding Register Bus Side Errors
+ *
+ * The lower address holding register is a read only register which contains
+ * the address which either can be accessed as a word or double word. Sub-
+ * sequent errors are not logged until the error is cleared. The last logged
+ * value is held until the group is cleared and enabled.
+ */
+	typedef union pic_lower_bus_err_u {
+		picreg_t	pic_lower_bus_err_regval;
+		struct {
+			picreg_t          :	16; /* 63:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_lower_bus_err_fld_s;
+	} pic_lower_bus_err_u_t;
+/*
+ * Control Register
+ *
+ * The control register is a read/write register which holds control informa-
+ * tion for the bus subsection.
+ */
+	typedef union pic_control_reg_u {
+		picreg_t	pic_control_reg_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t                :	4; /* 31:28 */
+			picreg_t rst_pin_n      :	4; /* 27:24 */
+			picreg_t                :	1; /* 23:23 */
+			picreg_t mem_swap       :	1; /* 22:22 */
+			picreg_t page_size      :	1; /* 21:21 */
+			picreg_t                :	4; /* 20:17 */
+			picreg_t f_bad_pkt      :	1; /* 16:16 */
+			picreg_t llp_xbar_crd   :	4; /* 15:12 */
+			picreg_t clr_rllp_cnt   :	1; /* 11:11 */
+			picreg_t clr_tllp_cnt   :	1; /* 10:10 */
+			picreg_t sys_end        :	1; /* 9:9 */
+			picreg_t                :	3; /* 8:6 */
+			picreg_t pci_speed      :	2; /* 5:4 */
+			picreg_t widget_id      :	4; /* 3:0 */
+		} pic_control_reg_fld_s;
+	} pic_control_reg_u_t;
+/*
+ * PCI/PCI-X Request Time-out Value Register
+ *
+ * This register contains the reload value for the response timer. The request
+ * timer counts every 960 nS (32 PCI clocks)
+ */
+	typedef union pic_pci_req_to_u {
+		picreg_t	pic_pci_req_to_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	12; /* 31:20 */
+			picreg_t time_out :	20; /* 19:0 */
+		} pic_pci_req_to_fld_s;
+	} pic_pci_req_to_u_t;
+/*
+ * Interrupt Destination Upper Address Register
+ *
+ * The interrupt destination upper address register is a read/write register
+ * containing the upper 16-bits of address of the host to which the interrupt
+ * is targeted. In addition the target ID is also contained in this register for
+ * use in Crosstalk mode.
+ */
+	typedef union pic_int_desc_upper_u {
+		picreg_t	pic_int_desc_upper_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	12; /* 31:20 */
+			picreg_t target_id :	4; /* 19:16 */
+			picreg_t upp_addr  :	16; /* 15:0 */
+		} pic_int_desc_upper_fld_s;
+	} pic_int_desc_upper_u_t;
+/*
+ * Interrupt Destination Lower Address Register
+ *
+ * The interrupt destination lower address register is a read/write register
+ * which contains the entire address of the host to which the interrupt is tar-
+ * geted. In addition the target ID is also contained in this register for use in
+ * Crosstalk mode.
+ */
+	typedef union pic_int_desc_lower_u {
+		picreg_t	pic_int_desc_lower_regval;
+		struct {
+			picreg_t           :	12; /* 63:52 */
+			picreg_t target_id :	4; /* 51:48 */
+			picreg_t upp_addr  :	16; /* 47:32 */
+			picreg_t low_addr  :	32; /* 31:0 */
+		} pic_int_desc_lower_fld_s;
+	} pic_int_desc_lower_u_t;
+/*
+ * Command Word Holding Register Bus Side Errors
+ *
+ * The command word holding is a read register that holds the command
+ * word of a Crosstalk packet when errors occur on the link side (see error
+ * chapter). Errors are indicated with error bits in the interrupt status regis-
+ * ter. Subsequent errors are not logged until the interrupt is cleared..
+ */
+	typedef union pic_cmd_word_bus_err_u {
+		picreg_t	pic_cmd_word_bus_err_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t didn     :	4; /* 31:28 */
+			picreg_t sidn     :	4; /* 27:24 */
+			picreg_t pactyp   :	4; /* 23:20 */
+			picreg_t tnum     :	5; /* 19:15 */
+			picreg_t coherent :	1; /* 14:14 */
+			picreg_t ds       :	2; /* 13:12 */
+			picreg_t gbr      :	1; /* 11:11 */
+			picreg_t vbpm     :	1; /* 10:10 */
+			picreg_t error    :	1; /* 9:9 */
+			picreg_t barrier  :	1; /* 8:8 */
+			picreg_t          :	8; /* 7:0 */
+		} pic_cmd_word_bus_err_fld_s;
+	} pic_cmd_word_bus_err_u_t;
+/*
+ * LLP Configuration Register
+ *
+ * This register contains the configuration information for the LLP modules
+ * and is only valid on bus 0 side.
+ */
+	typedef union pic_llp_cfg_u {
+		picreg_t	pic_llp_cfg_regval;
+		struct {
+			picreg_t                 :	32; /* 63:32 */
+			picreg_t                 :	6; /* 31:26 */
+			picreg_t llp_maxretry    :	10; /* 25:16 */
+			picreg_t llp_nulltimeout :	6; /* 15:10 */
+			picreg_t llp_maxburst    :	10; /* 9:0 */
+		} pic_llp_cfg_fld_s;
+	} pic_llp_cfg_u_t;
+/*
+ * PCI/PCI-X Target Flush Register
+ *
+ * When read, this register will return a 0x00 after all previous transfers to
+ * the PCI bus subsection have completed.
+ */
+
+/*
+ * Command Word Holding Register Link Side Errors
+ *
+ * The command word holding is a read-only register that holds the com-
+ * mand word of a Crosstalk packet when request fifo overflow or unexpect-
+ * ed response errors occur. Errors are indicated with error bits in the
+ * interrupt status register. Subsequent errors are not logged until this inter-
+ * rupt is cleared.
+ */
+	typedef union pic_cmd_word_link_err_u {
+		picreg_t	pic_cmd_word_link_err_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t didn     :	4; /* 31:28 */
+			picreg_t sidn     :	4; /* 27:24 */
+			picreg_t pactyp   :	4; /* 23:20 */
+			picreg_t tnum     :	5; /* 19:15 */
+			picreg_t coherent :	1; /* 14:14 */
+			picreg_t ds       :	2; /* 13:12 */
+			picreg_t gbr      :	1; /* 11:11 */
+			picreg_t vbpm     :	1; /* 10:10 */
+			picreg_t error    :	1; /* 9:9 */
+			picreg_t barrier  :	1; /* 8:8 */
+			picreg_t          :	8; /* 7:0 */
+		} pic_cmd_word_link_err_fld_s;
+	} pic_cmd_word_link_err_u_t;
+/*
+ * PCI Response Buffer Error Upper Address Holding Reg
+ *
+ * The response buffer error upper address holding register is a read only
+ * register which contains the upper 16-bits of the address when error asso-
+ * ciated with response buffer entries occur. Subsequent errors are not
+ * logged until the interrupt is cleared.
+ */
+	typedef union pic_pci_rbuf_err_upper_u {
+		picreg_t	pic_pci_rbuf_err_upper_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	9; /* 31:23 */
+			picreg_t dev_num  :	3; /* 22:20 */
+			picreg_t buff_num :	4; /* 19:16 */
+			picreg_t upp_addr :	16; /* 15:0 */
+		} pic_pci_rbuf_err_upper_fld_s;
+	} pic_pci_rbuf_err_upper_u_t;
+/*
+ * PCI Response Buffer Error Lower Address Holding Reg
+ *
+ * The response buffer error lower address holding register is a read only
+ * register which contains the address of the error associated with response
+ * buffer entries. Subsequent errors are not logged until the interrupt is
+ * cleared.
+ */
+	typedef union pic_pci_rbuf_err_lower_u {
+		picreg_t	pic_pci_rbuf_err_lower_regval;
+		struct {
+			picreg_t          :	9; /* 63:55 */
+			picreg_t dev_num  :	3; /* 54:52 */
+			picreg_t buff_num :	4; /* 51:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_pci_rbuf_err_lower_fld_s;
+	} pic_pci_rbuf_err_lower_u_t;
+/*
+ * Test Pin Control Register
+ *
+ * This register selects the output function and value to the four test pins on
+ * the PIC .
+ */
+	typedef union pic_test_pin_cntl_u {
+		picreg_t	pic_test_pin_cntl_regval;
+		struct {
+			picreg_t            :	32; /* 63:32 */
+			picreg_t            :	8; /* 31:24 */
+			picreg_t tdata_out  :	8; /* 23:16 */
+			picreg_t sel_tpin_7 :	2; /* 15:14 */
+			picreg_t sel_tpin_6 :	2; /* 13:12 */
+			picreg_t sel_tpin_5 :	2; /* 11:10 */
+			picreg_t sel_tpin_4 :	2; /* 9:8 */
+			picreg_t sel_tpin_3 :	2; /* 7:6 */
+			picreg_t sel_tpin_2 :	2; /* 5:4 */
+			picreg_t sel_tpin_1 :	2; /* 3:2 */
+			picreg_t sel_tpin_0 :	2; /* 1:0 */
+		} pic_test_pin_cntl_fld_s;
+	} pic_test_pin_cntl_u_t;
+/*
+ * Address Holding Register Link Side Errors
+ *
+ * The address holding register is a read only register which contains the ad-
+ * dress which either can be accessed as a word or double word. Subsequent
+ * errors are not logged until the error is cleared. The last logged value is
+ * held until the group is cleared and enabled.
+ */
+	typedef union pic_p_addr_lkerr_u {
+		picreg_t	pic_p_addr_lkerr_regval;
+		struct {
+			picreg_t          :	16; /* 63:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_p_addr_lkerr_fld_s;
+	} pic_p_addr_lkerr_u_t;
+/*
+ * PCI Direct Mapping Register
+ *
+ * This register is used to relocate a 2 GByte region for PCI to Crosstalk
+ * transfers.
+ */
+	typedef union pic_p_dir_map_u {
+		picreg_t	pic_p_dir_map_regval;
+		struct {
+			picreg_t            :	32; /* 63:32 */
+			picreg_t            :	8; /* 31:24 */
+			picreg_t dir_w_id   :	4; /* 23:20 */
+			picreg_t            :	2; /* 19:18 */
+			picreg_t dir_add512 :	1; /* 17:17 */
+			picreg_t dir_off    :	17; /* 16:0 */
+		} pic_p_dir_map_fld_s;
+	} pic_p_dir_map_u_t;
+/*
+ * PCI Page Map Fault Address Register
+ *
+ * This register contains the address and device number when a page map
+ * fault occurred.
+ */
+	typedef union pic_p_map_fault_u {
+		picreg_t	pic_p_map_fault_regval;
+		struct {
+			picreg_t             :	32; /* 63:32 */
+			picreg_t             :	10; /* 31:22 */
+			picreg_t pci_addr    :	18; /* 21:4 */
+			picreg_t             :	1; /* 3:3 */
+			picreg_t pci_dev_num :	3; /* 2:0 */
+		} pic_p_map_fault_fld_s;
+	} pic_p_map_fault_u_t;
+/*
+ * Arbitration Register
+ *
+ * This register defines the priority and bus time out timing in PCI bus arbi-
+ * tration.
+ */
+	typedef union pic_p_arb_u {
+		picreg_t	pic_p_arb_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	8; /* 31:24 */
+			picreg_t dev_broke     :	4; /* 23:20 */
+			picreg_t               :	2; /* 19:18 */
+			picreg_t req_wait_tick :	2; /* 17:16 */
+			picreg_t               :	4; /* 15:12 */
+			picreg_t req_wait_en   :	4; /* 11:8 */
+			picreg_t disarb        :	1; /* 7:7 */
+			picreg_t freeze_gnt    :	1; /* 6:6 */
+			picreg_t               :	1; /* 5:5 */
+			picreg_t en_bridge_hi  :	2; /* 4:3 */
+			picreg_t               :	1; /* 2:2 */
+			picreg_t en_bridge_lo  :	2; /* 1:0 */
+		} pic_p_arb_fld_s;
+	} pic_p_arb_u_t;
+/*
+ * Internal Ram Parity Error Register
+ *
+ * This register logs information about parity errors on internal ram access.
+ */
+	typedef union pic_p_ram_perr_u {
+		picreg_t	pic_p_ram_perr_regval;
+		struct {
+			picreg_t         	     :	6; /* 63:58 */
+			picreg_t ate_err_addr        :	10; /* 57:48 */
+			picreg_t         	     :	7; /* 47:41 */
+			picreg_t rd_resp_err_addr    :	9; /* 40:32 */
+			picreg_t wrt_resp_err_addr   :	8; /* 31:24 */
+			picreg_t         	     :	2; /* 23:22 */
+			picreg_t ate_err 	     :	1; /* 21:21 */
+			picreg_t rd_resp_err         :	1; /* 20:20 */
+			picreg_t wrt_resp_err        :	1; /* 19:19 */
+			picreg_t dbe_ate 	     :	3; /* 18:16 */
+			picreg_t dbe_rd  	     :	8; /* 15:8 */
+			picreg_t dbe_wrt 	     :	8; /* 7:0 */
+		} pic_p_ram_perr_fld_s;
+	} pic_p_ram_perr_u_t;
+/*
+ * Time-out Register
+ *
+ * This register determines retry hold off and max retries allowed for PIO
+ * accesses to PCI/PCI-X.
+ */
+	typedef union pic_p_bus_timeout_u {
+		picreg_t	pic_p_bus_timeout_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	11; /* 31:21 */
+			picreg_t pci_retry_hld :	5; /* 20:16 */
+			picreg_t               :	6; /* 15:10 */
+			picreg_t pci_retry_cnt :	10; /* 9:0 */
+		} pic_p_bus_timeout_fld_s;
+	} pic_p_bus_timeout_u_t;
+/*
+ * PCI/PCI-X Type 1 Configuration Register
+ *
+ * This register is use during accesses to the PCI/PCI-X type 1 configuration
+ * space. The bits in this register are used to supplement the address during
+ * the configuration cycle to select the correct secondary bus and device.
+ */
+	typedef union pic_type1_cfg_u {
+		picreg_t	pic_type1_cfg_regval;
+		struct {
+			picreg_t         :	32; /* 63:32 */
+			picreg_t         :	8; /* 31:24 */
+			picreg_t bus_num :	8; /* 23:16 */
+			picreg_t dev_num :	5; /* 15:11 */
+			picreg_t         :	11; /* 10:0 */
+		} pic_type1_cfg_fld_s;
+	} pic_type1_cfg_u_t;
+/*
+ * PCI Bus Error Upper Address Holding Register
+ *
+ * This register holds the value of the upper address on the PCI Bus when an
+ * error occurs.
+ */
+	typedef union pic_p_pci_err_upper_u {
+		picreg_t	pic_p_pci_err_upper_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t                :	4; /* 31:28 */
+			picreg_t pci_xtalk_did  :	4; /* 27:24 */
+			picreg_t                :	2; /* 23:22 */
+			picreg_t pci_dac        :	1; /* 21:21 */
+			picreg_t pci_dev_master :	1; /* 20:20 */
+			picreg_t pci_vdev       :	1; /* 19:19 */
+			picreg_t pci_dev_num    :	3; /* 18:16 */
+			picreg_t pci_uaddr_err  :	16; /* 15:0 */
+		} pic_p_pci_err_upper_fld_s;
+	} pic_p_pci_err_upper_u_t;
+/*
+ * PCI Bus Error Lower Address Holding Register
+ *
+ * This register holds the value of the lower address on the PCI Bus when an
+ * error occurs.
+ */
+	typedef union pic_p_pci_err_lower_u {
+		picreg_t	pic_p_pci_err_lower_regval;
+		struct {
+			picreg_t                :	4; /* 63:60 */
+			picreg_t pci_xtalk_did  :	4; /* 59:56 */
+			picreg_t                :	2; /* 55:54 */
+			picreg_t pci_dac        :	1; /* 53:53 */
+			picreg_t pci_dev_master :	1; /* 52:52 */
+			picreg_t pci_vdev       :	1; /* 51:51 */
+			picreg_t pci_dev_num    :	3; /* 50:48 */
+			picreg_t pci_uaddr_err  :	16; /* 47:32 */
+			picreg_t pci_laddr_err  :	32; /* 31:0 */
+		} pic_p_pci_err_lower_fld_s;
+	} pic_p_pci_err_lower_u_t;
+/*
+ * PCI-X Error Address Register
+ *
+ * This register contains the address on the PCI-X bus when an error oc-
+ * curred.
+ */
+	typedef union pic_p_pcix_err_addr_u {
+		picreg_t	pic_p_pcix_err_addr_regval;
+		struct {
+			picreg_t pcix_err_addr :	64; /* 63:0 */
+		} pic_p_pcix_err_addr_fld_s;
+	} pic_p_pcix_err_addr_u_t;
+/*
+ * PCI-X Error Attribute Register
+ *
+ * This register contains the attribute data on the PCI-X bus when an error
+ * occurred.
+ */
+	typedef union pic_p_pcix_err_attr_u {
+		picreg_t	pic_p_pcix_err_attr_regval;
+		struct {
+			picreg_t            :	16; /* 63:48 */
+			picreg_t bus_cmd    :	4; /* 47:44 */
+			picreg_t byte_cnt   :	12; /* 43:32 */
+			picreg_t            :	1; /* 31:31 */
+			picreg_t ns         :	1; /* 30:30 */
+			picreg_t ro         :	1; /* 29:29 */
+			picreg_t tag        :	5; /* 28:24 */
+			picreg_t bus_num    :	8; /* 23:16 */
+			picreg_t dev_num    :	5; /* 15:11 */
+			picreg_t fun_num    :	3; /* 10:8 */
+			picreg_t l_byte_cnt :	8; /* 7:0 */
+		} pic_p_pcix_err_attr_fld_s;
+	} pic_p_pcix_err_attr_u_t;
+/*
+ * PCI-X Error Data Register
+ *
+ * This register contains the Data on the PCI-X bus when an error occurred.
+ */
+	typedef union pic_p_pcix_err_data_u {
+		picreg_t	pic_p_pcix_err_data_regval;
+		struct {
+			picreg_t pcix_err_data :	64; /* 63:0 */
+		} pic_p_pcix_err_data_fld_s;
+	} pic_p_pcix_err_data_u_t;
+/*
+ * PCI-X Read Request Timeout Error Register
+ *
+ * This register contains a pointer into the PCI-X read data structure.
+ */
+	typedef union pic_p_pcix_read_req_to_u {
+		picreg_t	pic_p_pcix_read_req_to_regval;
+		struct {
+			picreg_t                :	55; /* 63:9 */
+			picreg_t rd_buff_loc    :	5; /* 8:4 */
+			picreg_t rd_buff_struct :	4; /* 3:0 */
+		} pic_p_pcix_read_req_to_fld_s;
+	} pic_p_pcix_read_req_to_u_t;
+/*
+ * INT_STATUS Register
+ *
+ * This is the current interrupt status register which maintains the current
+ * status of all the interrupting devices which generated a n interrupt. This
+ * register is read only and all the bits are active high. A high bit at
+ * INT_STATE means the corresponding INT_N pin has been asserted
+ * (low).
+ */
+	typedef union pic_p_int_status_u {
+		picreg_t	pic_p_int_status_regval;
+		struct {
+			picreg_t                  :	22; /* 63:42 */
+			picreg_t int_ram_perr     :	1; /* 41:41 */
+			picreg_t bus_arb_broke    :	1; /* 40:40 */
+			picreg_t pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t pci_x_tabort     :	1; /* 38:38 */
+			picreg_t pci_x_perr       :	1; /* 37:37 */
+			picreg_t pci_x_serr       :	1; /* 36:36 */
+			picreg_t pci_x_mretry     :	1; /* 35:35 */
+			picreg_t pci_x_mtout      :	1; /* 34:34 */
+			picreg_t pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                  :	1; /* 31:31 */
+			picreg_t pmu_page_fault   :	1; /* 30:30 */
+			picreg_t unexpected_resp  :	1; /* 29:29 */
+			picreg_t bad_xresp_packet :	1; /* 28:28 */
+			picreg_t bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t resp_xtalk_error :	1; /* 26:26 */
+			picreg_t req_xtalk_error  :	1; /* 25:25 */
+			picreg_t invalid_access   :	1; /* 24:24 */
+			picreg_t unsupported_xop  :	1; /* 23:23 */
+			picreg_t xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t llp_rcty         :	1; /* 19:19 */
+			picreg_t llp_tx_retry     :	1; /* 18:18 */
+			picreg_t llp_tcty         :	1; /* 17:17 */
+			picreg_t                  :	1; /* 16:16 */
+			picreg_t pci_abort        :	1; /* 15:15 */
+			picreg_t pci_parity       :	1; /* 14:14 */
+			picreg_t pci_serr         :	1; /* 13:13 */
+			picreg_t pci_perr         :	1; /* 12:12 */
+			picreg_t pci_master_tout  :	1; /* 11:11 */
+			picreg_t pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t xread_req_tout   :	1; /* 9:9 */
+			picreg_t                  :	1; /* 8:8 */
+			picreg_t int_state        :	8; /* 7:0 */
+		} pic_p_int_status_fld_s;
+	} pic_p_int_status_u_t;
+/*
+ * Interrupt Enable Register
+ *
+ * This register enables the reporting of interrupt to the host. Each bit in this
+ * register corresponds to the same bit in Interrupt Status register. All bits
+ * are zero after reset.
+ */
+	typedef union pic_p_int_enable_u {
+		picreg_t	pic_p_int_enable_regval;
+		struct {
+			picreg_t                     :	22; /* 63:42 */
+			picreg_t en_int_ram_perr     :	1; /* 41:41 */
+			picreg_t en_bus_arb_broke    :	1; /* 40:40 */
+			picreg_t en_pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t en_pci_x_tabort     :	1; /* 38:38 */
+			picreg_t en_pci_x_perr       :	1; /* 37:37 */
+			picreg_t en_pci_x_serr       :	1; /* 36:36 */
+			picreg_t en_pci_x_mretry     :	1; /* 35:35 */
+			picreg_t en_pci_x_mtout      :	1; /* 34:34 */
+			picreg_t en_pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t en_pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                     :	1; /* 31:31 */
+			picreg_t en_pmu_page_fault   :	1; /* 30:30 */
+			picreg_t en_unexpected_resp  :	1; /* 29:29 */
+			picreg_t en_bad_xresp_packet :	1; /* 28:28 */
+			picreg_t en_bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t en_resp_xtalk_error :	1; /* 26:26 */
+			picreg_t en_req_xtalk_error  :	1; /* 25:25 */
+			picreg_t en_invalid_access   :	1; /* 24:24 */
+			picreg_t en_unsupported_xop  :	1; /* 23:23 */
+			picreg_t en_xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t en_llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t en_llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t en_llp_rcty         :	1; /* 19:19 */
+			picreg_t en_llp_tx_retry     :	1; /* 18:18 */
+			picreg_t en_llp_tcty         :	1; /* 17:17 */
+			picreg_t                     :	1; /* 16:16 */
+			picreg_t en_pci_abort        :	1; /* 15:15 */
+			picreg_t en_pci_parity       :	1; /* 14:14 */
+			picreg_t en_pci_serr         :	1; /* 13:13 */
+			picreg_t en_pci_perr         :	1; /* 12:12 */
+			picreg_t en_pci_master_tout  :	1; /* 11:11 */
+			picreg_t en_pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t en_xread_req_tout   :	1; /* 9:9 */
+			picreg_t                     :	1; /* 8:8 */
+			picreg_t en_int_state        :	8; /* 7:0 */
+		} pic_p_int_enable_fld_s;
+	} pic_p_int_enable_u_t;
+/*
+ * Reset Interrupt Register
+ *
+ * A write of a "1" clears the bit and rearms the error registers. Writes also
+ * clear the error view register.
+ */
+	typedef union pic_p_int_rst_u {
+		picreg_t	pic_p_int_rst_regval;
+		struct {
+			picreg_t                       :	22; /* 63:42 */
+			picreg_t logv_int_ram_perr     :	1; /* 41:41 */
+			picreg_t logv_bus_arb_broke    :	1; /* 40:40 */
+			picreg_t logv_pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t logv_pci_x_tabort     :	1; /* 38:38 */
+			picreg_t logv_pci_x_perr       :	1; /* 37:37 */
+			picreg_t logv_pci_x_serr       :	1; /* 36:36 */
+			picreg_t logv_pci_x_mretry     :	1; /* 35:35 */
+			picreg_t logv_pci_x_mtout      :	1; /* 34:34 */
+			picreg_t logv_pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t logv_pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                       :	1; /* 31:31 */
+			picreg_t logv_pmu_page_fault   :	1; /* 30:30 */
+			picreg_t logv_unexpected_resp  :	1; /* 29:29 */
+			picreg_t logv_bad_xresp_packet :	1; /* 28:28 */
+			picreg_t logv_bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t logv_resp_xtalk_error :	1; /* 26:26 */
+			picreg_t logv_req_xtalk_error  :	1; /* 25:25 */
+			picreg_t logv_invalid_access   :	1; /* 24:24 */
+			picreg_t logv_unsupported_xop  :	1; /* 23:23 */
+			picreg_t logv_xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t logv_llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t logv_llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t logv_llp_rcty         :	1; /* 19:19 */
+			picreg_t logv_llp_tx_retry     :	1; /* 18:18 */
+			picreg_t logv_llp_tcty         :	1; /* 17:17 */
+			picreg_t                       :	1; /* 16:16 */
+			picreg_t logv_pci_abort        :	1; /* 15:15 */
+			picreg_t logv_pci_parity       :	1; /* 14:14 */
+			picreg_t logv_pci_serr         :	1; /* 13:13 */
+			picreg_t logv_pci_perr         :	1; /* 12:12 */
+			picreg_t logv_pci_master_tout  :	1; /* 11:11 */
+			picreg_t logv_pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t logv_xread_req_tout   :	1; /* 9:9 */
+                        picreg_t                       :        2; /* 8:7 */
+			picreg_t multi_clr             :	1; /* 6:6 */
+			picreg_t                       :	6; /* 5:0 */
+		} pic_p_int_rst_fld_s;
+	} pic_p_int_rst_u_t;
+
+/*
+ * Interrupt Mode Register
+ *
+ * This register defines the interrupting mode of the INT_N pins.
+ */
+	typedef union pic_p_int_mode_u {
+		picreg_t	pic_p_int_mode_regval;
+		struct {
+			picreg_t            :	32; /* 63:32 */
+			picreg_t            :	24; /* 31:8 */
+			picreg_t en_clr_pkt :	8; /* 7:0 */
+		} pic_p_int_mode_fld_s;
+	} pic_p_int_mode_u_t;
+/*
+ * Interrupt Device Select Register
+ *
+ * This register associates interrupt pins with devices thus allowing buffer
+ * management (flushing) when a device interrupt occurs.
+ */
+	typedef union pic_p_int_device_u {
+		picreg_t	pic_p_int_device_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	8; /* 31:24 */
+			picreg_t int7_dev :	3; /* 23:21 */
+			picreg_t int6_dev :	3; /* 20:18 */
+			picreg_t int5_dev :	3; /* 17:15 */
+			picreg_t int4_dev :	3; /* 14:12 */
+			picreg_t int3_dev :	3; /* 11:9 */
+			picreg_t int2_dev :	3; /* 8:6 */
+			picreg_t int1_dev :	3; /* 5:3 */
+			picreg_t int0_dev :	3; /* 2:0 */
+		} pic_p_int_device_fld_s;
+	} pic_p_int_device_u_t;
+/*
+ * Host Error Interrupt Field Register
+ *
+ * This register tells which bit location in the host's Interrupt Status register
+ * to set or reset when any error condition happens.
+ */
+	typedef union pic_p_int_host_err_u {
+		picreg_t	pic_p_int_host_err_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t                :	24; /* 31:8 */
+			picreg_t bridge_err_fld :	8; /* 7:0 */
+		} pic_p_int_host_err_fld_s;
+	} pic_p_int_host_err_u_t;
+/*
+ * Interrupt (x) Host Address Register
+ *
+ * This register allow different host address to be assigned to each interrupt
+ * pin and the bit in the host.
+ */
+	typedef union pic_p_int_addr_u {
+		picreg_t	pic_p_int_addr_regval;
+		struct {
+			picreg_t          :	8; /* 63:56 */
+			picreg_t int_fld  :	8; /* 55:48 */
+			picreg_t int_addr :	48; /* 47:0 */
+		} pic_p_int_addr_fld_s;
+	} pic_p_int_addr_u_t;
+/*
+ * Error Interrupt View Register
+ *
+ * This register contains the view of which interrupt occur even if they are
+ * not currently enabled. The group clear is used to clear these bits just like
+ * the interrupt status register bits.
+ */
+	typedef union pic_p_err_int_view_u {
+		picreg_t	pic_p_err_int_view_regval;
+		struct {
+			picreg_t                  :	22; /* 63:42 */
+			picreg_t int_ram_perr     :	1; /* 41:41 */
+			picreg_t bus_arb_broke    :	1; /* 40:40 */
+			picreg_t pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t pci_x_tabort     :	1; /* 38:38 */
+			picreg_t pci_x_perr       :	1; /* 37:37 */
+			picreg_t pci_x_serr       :	1; /* 36:36 */
+			picreg_t pci_x_mretry     :	1; /* 35:35 */
+			picreg_t pci_x_mtout      :	1; /* 34:34 */
+			picreg_t pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                  :	1; /* 31:31 */
+			picreg_t pmu_page_fault   :	1; /* 30:30 */
+			picreg_t unexpected_resp  :	1; /* 29:29 */
+			picreg_t bad_xresp_packet :	1; /* 28:28 */
+			picreg_t bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t resp_xtalk_error :	1; /* 26:26 */
+			picreg_t req_xtalk_error  :	1; /* 25:25 */
+			picreg_t invalid_access   :	1; /* 24:24 */
+			picreg_t unsupported_xop  :	1; /* 23:23 */
+			picreg_t xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t llp_rcty         :	1; /* 19:19 */
+			picreg_t llp_tx_retry     :	1; /* 18:18 */
+			picreg_t llp_tcty         :	1; /* 17:17 */
+			picreg_t                  :	1; /* 16:16 */
+			picreg_t pci_abort        :	1; /* 15:15 */
+			picreg_t pci_parity       :	1; /* 14:14 */
+			picreg_t pci_serr         :	1; /* 13:13 */
+			picreg_t pci_perr         :	1; /* 12:12 */
+			picreg_t pci_master_tout  :	1; /* 11:11 */
+			picreg_t pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t xread_req_tout   :	1; /* 9:9 */
+			picreg_t                  :	9; /* 8:0 */
+		} pic_p_err_int_view_fld_s;
+	} pic_p_err_int_view_u_t;
+
+
+/*
+ * Multiple Interrupt Register
+ *
+ * This register indicates if any interrupt occurs more than once without be-
+ * ing cleared.
+ */
+	typedef union pic_p_mult_int_u {
+		picreg_t	pic_p_mult_int_regval;
+		struct {
+			picreg_t                  :	22; /* 63:42 */
+			picreg_t int_ram_perr     :	1; /* 41:41 */
+			picreg_t bus_arb_broke    :	1; /* 40:40 */
+			picreg_t pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t pci_x_tabort     :	1; /* 38:38 */
+			picreg_t pci_x_perr       :	1; /* 37:37 */
+			picreg_t pci_x_serr       :	1; /* 36:36 */
+			picreg_t pci_x_mretry     :	1; /* 35:35 */
+			picreg_t pci_x_mtout      :	1; /* 34:34 */
+			picreg_t pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                  :	1; /* 31:31 */
+			picreg_t pmu_page_fault   :	1; /* 30:30 */
+			picreg_t unexpected_resp  :	1; /* 29:29 */
+			picreg_t bad_xresp_packet :	1; /* 28:28 */
+			picreg_t bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t resp_xtalk_error :	1; /* 26:26 */
+			picreg_t req_xtalk_error  :	1; /* 25:25 */
+			picreg_t invalid_access   :	1; /* 24:24 */
+			picreg_t unsupported_xop  :	1; /* 23:23 */
+			picreg_t xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t llp_rcty         :	1; /* 19:19 */
+			picreg_t llp_tx_retry     :	1; /* 18:18 */
+			picreg_t llp_tcty         :	1; /* 17:17 */
+			picreg_t                  :	1; /* 16:16 */
+			picreg_t pci_abort        :	1; /* 15:15 */
+			picreg_t pci_parity       :	1; /* 14:14 */
+			picreg_t pci_serr         :	1; /* 13:13 */
+			picreg_t pci_perr         :	1; /* 12:12 */
+			picreg_t pci_master_tout  :	1; /* 11:11 */
+			picreg_t pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t xread_req_tout   :	1; /* 9:9 */
+			picreg_t                  :	1; /* 8:8 */
+			picreg_t int_state        :	8; /* 7:0 */
+		} pic_p_mult_int_fld_s;
+	} pic_p_mult_int_u_t;
+/*
+ * Force Always Interrupt (x) Register
+ *
+ * A write to this data independent write only register will force a set inter-
+ * rupt to occur as if the interrupt line had transitioned. If the interrupt line
+ * is already active an addition set interrupt packet is set. All buffer flush op-
+ * erations also occur on this operation.
+ */
+
+
+/*
+ * Force Interrupt (x) Register
+ *
+ * A write to this data independent write only register in conjunction with
+ * the assertion of the corresponding interrupt line will force a set interrupt
+ * to occur as if the interrupt line had transitioned. The interrupt line must
+ * be active for this operation to generate a set packet, otherwise the write
+ * PIO is ignored. All buffer flush operations also occur when the set packet
+ * is sent on this operation.
+ */
+
+
+/*
+ * Device Registers
+ *
+ * The Device registers contain device specific and mapping information.
+ */
+	typedef union pic_device_reg_u {
+		picreg_t	pic_device_reg_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	2; /* 31:30 */
+			picreg_t en_virtual1   :	1; /* 29:29 */
+			picreg_t en_error_lock :	1; /* 28:28 */
+			picreg_t en_page_chk   :	1; /* 27:27 */
+			picreg_t force_pci_par :	1; /* 26:26 */
+			picreg_t en_virtual0   :	1; /* 25:25 */
+			picreg_t               :	1; /* 24:24 */
+			picreg_t dir_wrt_gen   :	1; /* 23:23 */
+			picreg_t dev_size      :	1; /* 22:22 */
+			picreg_t real_time     :	1; /* 21:21 */
+			picreg_t               :	1; /* 20:20 */
+			picreg_t swap_direct   :	1; /* 19:19 */
+			picreg_t prefetch      :	1; /* 18:18 */
+			picreg_t precise       :	1; /* 17:17 */
+			picreg_t coherent      :	1; /* 16:16 */
+			picreg_t barrier       :	1; /* 15:15 */
+			picreg_t gbr           :	1; /* 14:14 */
+			picreg_t dev_swap      :	1; /* 13:13 */
+			picreg_t dev_io_mem    :	1; /* 12:12 */
+			picreg_t dev_off       :	12; /* 11:0 */
+		} pic_device_reg_fld_s;
+	} pic_device_reg_u_t;
+/*
+ * Device (x) Write Request Buffer Flush
+ *
+ * When read, this register will return a 0x00 after the write buffer associat-
+ * ed with the device has been flushed. (PCI Only)
+ */
+
+
+/*
+ * Even Device Read Response Buffer Register (PCI Only)
+ *
+ * This register is use to allocate the read response buffers for the even num-
+ * bered devices. (0,2)
+ */
+	typedef union pic_p_even_resp_u {
+		picreg_t	pic_p_even_resp_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t buff_14_en   :	1; /* 31:31 */
+			picreg_t buff_14_vdev :	2; /* 30:29 */
+			picreg_t buff_14_pdev :	1; /* 28:28 */
+			picreg_t buff_12_en   :	1; /* 27:27 */
+			picreg_t buff_12_vdev :	2; /* 26:25 */
+			picreg_t buff_12_pdev :	1; /* 24:24 */
+			picreg_t buff_10_en   :	1; /* 23:23 */
+			picreg_t buff_10_vdev :	2; /* 22:21 */
+			picreg_t buff_10_pdev :	1; /* 20:20 */
+			picreg_t buff_8_en    :	1; /* 19:19 */
+			picreg_t buff_8_vdev  :	2; /* 18:17 */
+			picreg_t buff_8_pdev  :	1; /* 16:16 */
+			picreg_t buff_6_en    :	1; /* 15:15 */
+			picreg_t buff_6_vdev  :	2; /* 14:13 */
+			picreg_t buff_6_pdev  :	1; /* 12:12 */
+			picreg_t buff_4_en    :	1; /* 11:11 */
+			picreg_t buff_4_vdev  :	2; /* 10:9 */
+			picreg_t buff_4_pdev  :	1; /* 8:8 */
+			picreg_t buff_2_en    :	1; /* 7:7 */
+			picreg_t buff_2_vdev  :	2; /* 6:5 */
+			picreg_t buff_2_pdev  :	1; /* 4:4 */
+			picreg_t buff_0_en    :	1; /* 3:3 */
+			picreg_t buff_0_vdev  :	2; /* 2:1 */
+			picreg_t buff_0_pdev  :	1; /* 0:0 */
+		} pic_p_even_resp_fld_s;
+	} pic_p_even_resp_u_t;
+/*
+ * Odd Device Read Response Buffer Register (PCI Only)
+ *
+ * This register is use to allocate the read response buffers for the odd num-
+ * bered devices. (1,3))
+ */
+	typedef union pic_p_odd_resp_u {
+		picreg_t	pic_p_odd_resp_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t buff_15_en   :	1; /* 31:31 */
+			picreg_t buff_15_vdev :	2; /* 30:29 */
+			picreg_t buff_15_pdev :	1; /* 28:28 */
+			picreg_t buff_13_en   :	1; /* 27:27 */
+			picreg_t buff_13_vdev :	2; /* 26:25 */
+			picreg_t buff_13_pdev :	1; /* 24:24 */
+			picreg_t buff_11_en   :	1; /* 23:23 */
+			picreg_t buff_11_vdev :	2; /* 22:21 */
+			picreg_t buff_11_pdev :	1; /* 20:20 */
+			picreg_t buff_9_en    :	1; /* 19:19 */
+			picreg_t buff_9_vdev  :	2; /* 18:17 */
+			picreg_t buff_9_pdev  :	1; /* 16:16 */
+			picreg_t buff_7_en    :	1; /* 15:15 */
+			picreg_t buff_7_vdev  :	2; /* 14:13 */
+			picreg_t buff_7_pdev  :	1; /* 12:12 */
+			picreg_t buff_5_en    :	1; /* 11:11 */
+			picreg_t buff_5_vdev  :	2; /* 10:9 */
+			picreg_t buff_5_pdev  :	1; /* 8:8 */
+			picreg_t buff_3_en    :	1; /* 7:7 */
+			picreg_t buff_3_vdev  :	2; /* 6:5 */
+			picreg_t buff_3_pdev  :	1; /* 4:4 */
+			picreg_t buff_1_en    :	1; /* 3:3 */
+			picreg_t buff_1_vdev  :	2; /* 2:1 */
+			picreg_t buff_1_pdev  :	1; /* 0:0 */
+		} pic_p_odd_resp_fld_s;
+	} pic_p_odd_resp_u_t;
+/*
+ * Read Response Buffer Status Register (PCI Only)
+ *
+ * This read only register contains the current response buffer status.
+ */
+	typedef union pic_p_resp_status_u {
+		picreg_t	pic_p_resp_status_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t rrb_valid :	16; /* 31:16 */
+			picreg_t rrb_inuse :	16; /* 15:0 */
+		} pic_p_resp_status_fld_s;
+	} pic_p_resp_status_u_t;
+/*
+ * Read Response Buffer Clear Register (PCI Only)
+ *
+ * A write to this register clears the current contents of the buffer.
+ */
+	typedef union pic_p_resp_clear_u {
+		picreg_t	pic_p_resp_clear_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	16; /* 31:16 */
+			picreg_t rrb_clear :	16; /* 15:0 */
+		} pic_p_resp_clear_fld_s;
+	} pic_p_resp_clear_u_t;
+/*
+ * PCI Read Response Buffer (x) Upper Address Match
+ *
+ * The PCI Bridge read response buffer upper address register is a read only
+ * register which contains the upper 16-bits of the address and status used to
+ * select the buffer for a PCI transaction.
+ */
+	typedef union pic_p_buf_upper_addr_match_u {
+		picreg_t	pic_p_buf_upper_addr_match_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t filled   :	1; /* 31:31 */
+			picreg_t armed    :	1; /* 30:30 */
+			picreg_t flush    :	1; /* 29:29 */
+			picreg_t xerr     :	1; /* 28:28 */
+			picreg_t pkterr   :	1; /* 27:27 */
+			picreg_t timeout  :	1; /* 26:26 */
+			picreg_t prefetch :	1; /* 25:25 */
+			picreg_t precise  :	1; /* 24:24 */
+			picreg_t dw_be    :	8; /* 23:16 */
+			picreg_t upp_addr :	16; /* 15:0 */
+		} pic_p_buf_upper_addr_match_fld_s;
+	} pic_p_buf_upper_addr_match_u_t;
+/*
+ * PCI Read Response Buffer (x) Lower Address Match
+ *
+ * The PCI Bridge read response buffer lower address Match register is a
+ * read only register which contains the address and status used to select the
+ * buffer for a PCI transaction.
+ */
+	typedef union pic_p_buf_lower_addr_match_u {
+		picreg_t	pic_p_buf_lower_addr_match_regval;
+		struct {
+			picreg_t filled   :	1; /* 63:63 */
+			picreg_t armed    :	1; /* 62:62 */
+			picreg_t flush    :	1; /* 61:61 */
+			picreg_t xerr     :	1; /* 60:60 */
+			picreg_t pkterr   :	1; /* 59:59 */
+			picreg_t timeout  :	1; /* 58:58 */
+			picreg_t prefetch :	1; /* 57:57 */
+			picreg_t precise  :	1; /* 56:56 */
+			picreg_t dw_be    :	8; /* 55:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_p_buf_lower_addr_match_fld_s;
+	} pic_p_buf_lower_addr_match_u_t;
+/*
+ * PCI Buffer (x) Flush Count with Data Touch Register
+ *
+ * This counter is incremented each time the corresponding response buffer
+ * is flushed after at least a single data element in the buffer is used. A word
+ * write to this address clears the count.
+ */
+	typedef union pic_flush_w_touch_u {
+		picreg_t	pic_flush_w_touch_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	16; /* 31:16 */
+			picreg_t touch_cnt :	16; /* 15:0 */
+		} pic_flush_w_touch_fld_s;
+	} pic_flush_w_touch_u_t;
+/*
+ * PCI Buffer (x) Flush Count w/o Data Touch Register
+ *
+ * This counter is incremented each time the corresponding response buffer
+ * is flushed without any data element in the buffer being used. A word
+ * write to this address clears the count.
+ */
+	typedef union pic_flush_wo_touch_u {
+		picreg_t	pic_flush_wo_touch_regval;
+		struct {
+			picreg_t             :	32; /* 63:32 */
+			picreg_t             :	16; /* 31:16 */
+			picreg_t notouch_cnt :	16; /* 15:0 */
+		} pic_flush_wo_touch_fld_s;
+	} pic_flush_wo_touch_u_t;
+/*
+ * PCI Buffer (x) Request in Flight Count Register
+ *
+ * This counter is incremented on each bus clock while the request is in-
+ * flight. A word write to this address clears the count. ]
+ */
+	typedef union pic_inflight_u {
+		picreg_t	pic_inflight_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t              :	16; /* 31:16 */
+			picreg_t inflight_cnt :	16; /* 15:0 */
+		} pic_inflight_fld_s;
+	} pic_inflight_u_t;
+/*
+ * PCI Buffer (x) Prefetch Request Count Register
+ *
+ * This counter is incremented each time the request using this buffer was
+ * generated from the prefetcher. A word write to this address clears the
+ * count.
+ */
+	typedef union pic_prefetch_u {
+		picreg_t	pic_prefetch_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t              :	16; /* 31:16 */
+			picreg_t prefetch_cnt :	16; /* 15:0 */
+		} pic_prefetch_fld_s;
+	} pic_prefetch_u_t;
+/*
+ * PCI Buffer (x) Total PCI Retry Count Register
+ *
+ * This counter is incremented each time a PCI bus retry occurs and the ad-
+ * dress matches the tag for the selected buffer. The buffer must also has this
+ * request in-flight. A word write to this address clears the count.
+ */
+	typedef union pic_total_pci_retry_u {
+		picreg_t	pic_total_pci_retry_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	16; /* 31:16 */
+			picreg_t retry_cnt :	16; /* 15:0 */
+		} pic_total_pci_retry_fld_s;
+	} pic_total_pci_retry_u_t;
+/*
+ * PCI Buffer (x) Max PCI Retry Count Register
+ *
+ * This counter is contains the maximum retry count for a single request
+ * which was in-flight for this buffer. A word write to this address clears the
+ * count.
+ */
+	typedef union pic_max_pci_retry_u {
+		picreg_t	pic_max_pci_retry_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	16; /* 31:16 */
+			picreg_t max_retry_cnt :	16; /* 15:0 */
+		} pic_max_pci_retry_fld_s;
+	} pic_max_pci_retry_u_t;
+/*
+ * PCI Buffer (x) Max Latency Count Register
+ *
+ * This counter is contains the maximum count (in bus clocks) for a single
+ * request which was in-flight for this buffer. A word write to this address
+ * clears the count.
+ */
+	typedef union pic_max_latency_u {
+		picreg_t	pic_max_latency_regval;
+		struct {
+			picreg_t                 :	32; /* 63:32 */
+			picreg_t                 :	16; /* 31:16 */
+			picreg_t max_latency_cnt :	16; /* 15:0 */
+		} pic_max_latency_fld_s;
+	} pic_max_latency_u_t;
+/*
+ * PCI Buffer (x) Clear All Register
+ *
+ * Any access to this register clears all the count values for the (x) registers.
+ */
+
+
+/*
+ * PCI-X Registers
+ *
+ * This register contains the address in the read buffer structure. There are
+ * 16 read buffer structures.
+ */
+	typedef union pic_rd_buf_addr_u {
+		picreg_t	pic_rd_buf_addr_regval;
+		struct {
+			picreg_t pcix_err_addr :	64; /* 63:0 */
+		} pic_rd_buf_addr_fld_s;
+	} pic_rd_buf_addr_u_t;
+/*
+ * PCI-X Read Buffer (x) Attribute Register
+ *
+ * This register contains the attribute data in the read buffer structure. There
+ * are  16 read buffer structures.
+ */
+	typedef union pic_px_read_buf_attr_u {
+		picreg_t	pic_px_read_buf_attr_regval;
+		struct {
+			picreg_t                :	16; /* 63:48 */
+			picreg_t bus_cmd        :	4; /* 47:44 */
+			picreg_t byte_cnt       :	12; /* 43:32 */
+			picreg_t entry_valid    :	1; /* 31:31 */
+			picreg_t ns             :	1; /* 30:30 */
+			picreg_t ro             :	1; /* 29:29 */
+			picreg_t tag            :	5; /* 28:24 */
+			picreg_t bus_num        :	8; /* 23:16 */
+			picreg_t dev_num        :	5; /* 15:11 */
+			picreg_t fun_num        :	3; /* 10:8 */
+			picreg_t                :	2; /* 7:6 */
+			picreg_t f_buffer_index :	6; /* 5:0 */
+		} pic_px_read_buf_attr_fld_s;
+	} pic_px_read_buf_attr_u_t;
+/*
+ * PCI-X Write Buffer (x) Address Register
+ *
+ * This register contains the address in the write buffer structure. There are
+ * 8 write buffer structures.
+ */
+	typedef union pic_px_write_buf_addr_u {
+		picreg_t	pic_px_write_buf_addr_regval;
+		struct {
+			picreg_t pcix_err_addr :	64; /* 63:0 */
+		} pic_px_write_buf_addr_fld_s;
+	} pic_px_write_buf_addr_u_t;
+/*
+ * PCI-X Write Buffer (x) Attribute Register
+ *
+ * This register contains the attribute data in the write buffer structure.
+ * There are 8 write buffer structures.
+ */
+	typedef union pic_px_write_buf_attr_u {
+		picreg_t	pic_px_write_buf_attr_regval;
+		struct {
+			picreg_t                :	16; /* 63:48 */
+			picreg_t bus_cmd        :	4; /* 47:44 */
+			picreg_t byte_cnt       :	12; /* 43:32 */
+			picreg_t entry_valid    :	1; /* 31:31 */
+			picreg_t ns             :	1; /* 30:30 */
+			picreg_t ro             :	1; /* 29:29 */
+			picreg_t tag            :	5; /* 28:24 */
+			picreg_t bus_num        :	8; /* 23:16 */
+			picreg_t dev_num        :	5; /* 15:11 */
+			picreg_t fun_num        :	3; /* 10:8 */
+			picreg_t                :	2; /* 7:6 */
+			picreg_t f_buffer_index :	6; /* 5:0 */
+		} pic_px_write_buf_attr_fld_s;
+	} pic_px_write_buf_attr_u_t;
+/*
+ * PCI-X Write Buffer (x) Valid Register
+ *
+ * This register contains the valid or inuse cache lines for this buffer struc-
+ * ture.
+ */
+	typedef union pic_px_write_buf_valid_u {
+		picreg_t	pic_px_write_buf_valid_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t wrt_valid_buff :	32; /* 31:0 */
+		} pic_px_write_buf_valid_fld_s;
+	} pic_px_write_buf_valid_u_t;
+
+#endif				/* __ASSEMBLY__ */
+#endif                          /* _ASM_SN_PCI_PIC_H */
diff -Nru a/include/asm-ia64/sn/rw_mmr.h b/include/asm-ia64/sn/rw_mmr.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/rw_mmr.h	Mon Feb 24 05:16:55 2003
@@ -0,0 +1,73 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+#ifndef _ASM_IA64_SN_RW_MMR_H
+#define _ASM_IA64_SN_RW_MMR_H
+
+
+/*
+ * This file contains macros used to access MMR registers via
+ * uncached physical addresses.
+ * 	pio_phys_read_mmr  - read an MMR
+ * 	pio_phys_write_mmr - write an MMR
+ * 	pio_atomic_phys_write_mmrs - atomically write 2 MMRs with psr.ic=0
+ * 		(interrupt collection)
+ *
+ * Addresses passed to these routines should be uncached physical addresses
+ * ie., 0x80000....
+ */
+
+
+extern inline long
+pio_phys_read_mmr(volatile long *mmr) 
+{
+	long val;
+        asm volatile
+            ("mov r2=psr;;"
+             "rsm psr.i | psr.dt;;"
+             "srlz.i;;"
+             "ld8.acq %0=[%1];;"
+             "mov psr.l=r2;;"
+             "srlz.i;;"
+             : "=r"(val)
+             : "r"(mmr)
+	     : "r2");
+        return val;
+}
+
+
+
+extern inline void
+pio_phys_write_mmr(volatile long *mmr, long val) 
+{
+        asm volatile
+            ("mov r2=psr;;"
+             "rsm psr.i | psr.dt;;"
+             "srlz.i;;"
+             "st8.rel [%0]=%1;;"
+             "mov psr.l=r2;;"
+             "srlz.i;;"
+	     :: "r"(mmr), "r"(val)
+             : "r2", "memory");
+}            
+
+extern inline void
+pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2) 
+{
+        asm volatile
+            ("mov r2=psr;;"
+             "rsm psr.i | psr.dt | psr.ic;;"
+             "srlz.i;;"
+             "st8.rel [%0]=%1;"
+             "st8.rel [%2]=%3;;"
+             "mov psr.l=r2;;"
+             "srlz.i;;"
+	     :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2)
+             : "r2", "memory");
+}            
+
+#endif /* _ASM_IA64_SN_RW_MMR_H */
diff -Nru a/include/asm-ia64/sn/sn2/geo.h b/include/asm-ia64/sn/sn2/geo.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/sn2/geo.h	Mon Feb 24 04:35:40 2003
@@ -0,0 +1,109 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef __SYS_SN_SN2_GEO_H__
+#define __SYS_SN_SN2_GEO_H__
+
+/* Headers required by declarations in this file */
+
+#include <asm/sn/slotnum.h>
+
+
+/* The geoid_t implementation below is based loosely on the pcfg_t
+   implementation in sys/SN/promcfg.h. */
+
+/* Type declaractions */
+
+/* Size of a geoid_t structure (must be before decl. of geoid_u) */
+#define GEOID_SIZE	8	/* Would 16 be better?  The size can
+				   be different on different platforms. */
+
+#define MAX_SLABS	0xe	/* slabs per module */
+
+typedef unsigned char	geo_type_t;
+
+/* Fields common to all substructures */
+typedef struct geo_any_s {
+    moduleid_t	module;		/* The module (box) this h/w lives in */
+    geo_type_t	type;		/* What type of h/w is named by this geoid_t */
+    slabid_t	slab;		/* The logical assembly within the module */
+} geo_any_t;
+
+/* Additional fields for particular types of hardware */
+typedef struct geo_node_s {
+    geo_any_t	any;		/* No additional fields needed */
+} geo_node_t;
+
+typedef struct geo_rtr_s {
+    geo_any_t	any;		/* No additional fields needed */
+} geo_rtr_t;
+
+typedef struct geo_iocntl_s {
+    geo_any_t	any;		/* No additional fields needed */
+} geo_iocntl_t;
+
+typedef struct geo_pcicard_s {
+    geo_iocntl_t	any;
+    char		bus;	/* Bus/widget number */
+    slotid_t		slot;	/* PCI slot number */
+} geo_pcicard_t;
+
+/* Subcomponents of a node */
+typedef struct geo_cpu_s {
+    geo_node_t	node;
+    char	slice;		/* Which CPU on the node */
+} geo_cpu_t;
+
+typedef struct geo_mem_s {
+    geo_node_t	node;
+    char	membus;		/* The memory bus on the node */
+    char	memslot;	/* The memory slot on the bus */
+} geo_mem_t;
+
+
+typedef union geoid_u {
+    geo_any_t	any;
+    geo_node_t	node;
+    geo_iocntl_t	iocntl;
+    geo_pcicard_t	pcicard;
+    geo_rtr_t	rtr;
+    geo_cpu_t	cpu;
+    geo_mem_t	mem;
+    char	padsize[GEOID_SIZE];
+} geoid_t;
+
+
+/* Preprocessor macros */
+
+#define GEO_MAX_LEN	48	/* max. formatted length, plus some pad:
+				   module/001c07/slab/5/node/memory/2/slot/4 */
+
+/* Values for geo_type_t */
+#define GEO_TYPE_INVALID	0
+#define GEO_TYPE_MODULE		1
+#define GEO_TYPE_NODE		2
+#define GEO_TYPE_RTR		3
+#define GEO_TYPE_IOCNTL		4
+#define GEO_TYPE_IOCARD		5
+#define GEO_TYPE_CPU		6
+#define GEO_TYPE_MEM		7
+#define GEO_TYPE_MAX		(GEO_TYPE_MEM+1)
+
+/* Parameter for hwcfg_format_geoid_compt() */
+#define GEO_COMPT_MODULE	1
+#define GEO_COMPT_SLAB		2
+#define GEO_COMPT_IOBUS		3
+#define GEO_COMPT_IOSLOT	4
+#define GEO_COMPT_CPU		5
+#define GEO_COMPT_MEMBUS	6
+#define GEO_COMPT_MEMSLOT	7
+
+#define GEO_INVALID_STR		"<invalid>"
+
+#endif /* __SYS_SN_SN2_GEO_H__ */
diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
--- a/include/asm-ia64/spinlock.h	Tue Jan 14 21:57:29 2003
+++ b/include/asm-ia64/spinlock.h	Tue Mar  4 18:38:46 2003
@@ -183,6 +183,19 @@
 		:: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory");		\
 } while(0)
 
+#define _raw_write_trylock(rw)							\
+({										\
+	register long result;							\
+										\
+	__asm__ __volatile__ (							\
+		"mov ar.ccv = r0\n"						\
+		"dep r29 = -1, r0, 31, 1\n"					\
+		";;\n"								\
+		"cmpxchg4.acq %0 = [%1], r29, ar.ccv\n"				\
+		: "=r"(result) : "r"(rw) : "ar.ccv", "r29", "memory");		\
+	(result == 0);								\
+})
+
 #define _raw_write_unlock(x)								\
 ({											\
 	smp_mb__before_clear_bit();	/* need barrier before releasing lock... */	\
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	Fri Jan 24 11:56:49 2003
+++ b/include/asm-ia64/system.h	Thu Jan 30 06:15:28 2003
@@ -206,7 +206,7 @@
 
 #ifdef CONFIG_PERFMON
   DECLARE_PER_CPU(unsigned long, pfm_syst_info);
-# define PERFMON_IS_SYSWIDE() (get_cpu_var(pfm_syst_info) & 0x1)
+# define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
 #else
 # define PERFMON_IS_SYSWIDE() (0)
 #endif
diff -Nru a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
--- a/include/asm-ia64/thread_info.h	Mon Dec 16 18:06:43 2002
+++ b/include/asm-ia64/thread_info.h	Thu Mar  6 21:11:46 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002 Hewlett-Packard Co
+ * Copyright (C) 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #ifndef _ASM_IA64_THREAD_INFO_H
@@ -15,7 +15,8 @@
 #define TI_ADDR_LIMIT	0x10
 #define TI_PRE_COUNT	0x18
 
-#define PREEMPT_ACTIVE	0x4000000
+#define PREEMPT_ACTIVE_BIT 30
+#define PREEMPT_ACTIVE	(1 << PREEMPT_ACTIVE_BIT)
 
 #ifndef __ASSEMBLY__
 
@@ -50,6 +51,7 @@
 
 /* how to get the thread information struct from C */
 #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
+#define free_thread_info(ti)	/* nothing */
 
 #endif /* !__ASSEMBLY */
 
diff -Nru a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
--- a/include/asm-ia64/topology.h	Mon Feb  3 23:46:59 2003
+++ b/include/asm-ia64/topology.h	Mon Mar  3 16:00:00 2003
@@ -26,7 +26,7 @@
 /*
  * Returns a bitmask of CPUs on Node 'node'.
  */
-#define node_to_cpumask(node) (node_to_cpumask[node])
+#define node_to_cpumask(node) (node_to_cpu_mask[node])
 
 #else
 #define cpu_to_node(cpu) (0)
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Tue Jan 21 18:31:31 2003
+++ b/include/asm-ia64/unistd.h	Thu Mar  6 14:56:33 2003
@@ -223,7 +223,7 @@
 #define __NR_sched_setaffinity		1231
 #define __NR_sched_getaffinity		1232
 #define __NR_set_tid_address		1233
-/* 1234 available for reuse */
+#define __NR_fadvise64			1234
 /* 1235 available for reuse */
 #define __NR_exit_group			1236
 #define __NR_lookup_dcookie		1237
@@ -237,6 +237,15 @@
 #define __NR_epoll_wait			1245
 #define __NR_restart_syscall		1246
 #define __NR_semtimedop			1247
+#define __NR_sys_timer_create		1248
+#define __NR_sys_timer_settime		1249
+#define __NR_sys_timer_gettime		1250
+#define __NR_sys_timer_getoverrun	1251
+#define __NR_sys_timer_delete		1252
+#define __NR_sys_clock_settime		1253
+#define __NR_sys_clock_gettime		1254
+#define __NR_sys_clock_getres		1255
+#define __NR_sys_clock_nanosleep	1256
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
diff -Nru a/include/asm-ia64/unwind.h b/include/asm-ia64/unwind.h
--- a/include/asm-ia64/unwind.h	Mon Feb  4 23:43:07 2002
+++ b/include/asm-ia64/unwind.h	Mon Mar  3 16:00:00 2003
@@ -60,6 +60,7 @@
 	unsigned long ip;		/* instruction pointer value */
 	unsigned long pr;		/* current predicate values */
 	unsigned long *cfm_loc;		/* cfm save location (or NULL) */
+	unsigned long pt;		/* struct pt_regs location */
 
 	struct task_struct *task;
 	struct switch_stack *sw;
diff -Nru a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h
--- a/include/asm-m68k/processor.h	Mon Nov  4 02:28:50 2002
+++ b/include/asm-m68k/processor.h	Mon Mar 10 10:20:31 2003
@@ -112,6 +112,9 @@
 {
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
--- a/include/asm-m68k/sun3_pgtable.h	Mon May 20 06:43:35 2002
+++ b/include/asm-m68k/sun3_pgtable.h	Thu Mar  6 08:19:09 2003
@@ -196,10 +196,10 @@
 }
 
 /* Find an entry in the third-level pagetable. */
-#define __pte_offset(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
-#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + __pte_offset(address))
+#define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
 /* FIXME: should we bother with kmap() here? */
-#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + __pte_offset(address))
+#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address))
 #define pte_offset_map_nested(pmd, address) pte_offset_map(pmd, address)
 #define pte_unmap(pte) kunmap(pte)
 #define pte_unmap_nested(pte) kunmap(pte)
diff -Nru a/include/asm-m68knommu/pci.h b/include/asm-m68knommu/pci.h
--- a/include/asm-m68knommu/pci.h	Fri Nov  1 08:37:46 2002
+++ b/include/asm-m68knommu/pci.h	Mon Mar 10 16:26:47 2003
@@ -1 +1,33 @@
+#ifndef M68KNOMMU_PCI_H
+#define	M68KNOMMU_PCI_H
+
 #include <asm-m68k/pci.h>
+
+#ifdef CONFIG_COMEMPCI
+/*
+ *	These are pretty much arbitary with the CoMEM implementation.
+ *	We have the whole address space to ourselves.
+ */
+#define PCIBIOS_MIN_IO		0x100
+#define PCIBIOS_MIN_MEM		0x00010000
+
+/*
+ * Return whether the given PCI device DMA address mask can
+ * be supported properly.  For example, if your device can
+ * only drive the low 24-bits during PCI bus mastering, then
+ * you would pass 0x00ffffff as the mask to this function.
+ */
+static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
+{
+	return 1;
+}
+
+/*
+ * Not supporting more than 32-bit PCI bus addresses now, but
+ * must satisfy references to this function.  Change if needed.
+ */
+#define pci_dac_dma_supported(pci_dev, mask) (0)
+
+#endif /* CONFIG_COMEMPCI */
+
+#endif /* M68KNOMMU_PCI_H */
diff -Nru a/include/asm-m68knommu/processor.h b/include/asm-m68knommu/processor.h
--- a/include/asm-m68knommu/processor.h	Tue Dec 10 16:41:17 2002
+++ b/include/asm-m68knommu/processor.h	Mon Mar 10 10:20:31 2003
@@ -108,6 +108,9 @@
 {
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-mips/pci.h b/include/asm-mips/pci.h
--- a/include/asm-mips/pci.h	Tue Feb 25 09:18:09 2003
+++ b/include/asm-mips/pci.h	Sun Mar 16 13:55:58 2003
@@ -252,4 +252,7 @@
 
 #endif /* __KERNEL__ */
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
 #endif /* _ASM_PCI_H */
diff -Nru a/include/asm-mips/processor.h b/include/asm-mips/processor.h
--- a/include/asm-mips/processor.h	Mon Feb 24 12:16:15 2003
+++ b/include/asm-mips/processor.h	Mon Mar 10 10:20:31 2003
@@ -208,6 +208,9 @@
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-mips64/pci.h b/include/asm-mips64/pci.h
--- a/include/asm-mips64/pci.h	Tue Feb 25 09:18:07 2003
+++ b/include/asm-mips64/pci.h	Sun Mar 16 13:55:58 2003
@@ -272,4 +272,8 @@
 
 #endif /* __KERNEL__ */
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
 #endif /* _ASM_PCI_H */
+
diff -Nru a/include/asm-mips64/processor.h b/include/asm-mips64/processor.h
--- a/include/asm-mips64/processor.h	Mon Feb 24 12:16:15 2003
+++ b/include/asm-mips64/processor.h	Mon Mar 10 10:20:31 2003
@@ -231,6 +231,9 @@
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h
--- a/include/asm-parisc/bug.h	Sun Jan  6 03:51:59 2002
+++ b/include/asm-parisc/bug.h	Sun Feb 16 15:52:20 2003
@@ -2,10 +2,7 @@
 #define _PARISC_BUG_H
 
 /*
- * Tell the user there is some problem. Beep too, so we can
- * see^H^H^Hhear bugs in early bootup as well!
- *
- * We don't beep yet.  prumpf
+ * Tell the user there is some problem.
  */
 #define BUG() do { \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
diff -Nru a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
--- a/include/asm-parisc/compat.h	Mon Feb  3 21:35:07 2003
+++ b/include/asm-parisc/compat.h	Sun Mar  9 01:34:45 2003
@@ -72,6 +72,14 @@
 	compat_pid_t		l_pid;
 };
 
+struct compat_flock64 {
+	short			l_type;
+	short			l_whence;
+	compat_loff_t		l_start;
+	compat_loff_t		l_len;
+	compat_pid_t		l_pid;
+};
+
 struct compat_statfs {
 	s32		f_type;
 	s32		f_bsize;
@@ -91,5 +99,8 @@
 #define _COMPAT_NSIG_BPW	BITS_PER_LONG
 
 typedef u32		compat_sigset_word;
+
+#define COMPAT_OFF_T_MAX	0x7fffffff
+#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
 #endif /* _ASM_PARISC_COMPAT_H */
diff -Nru a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
--- a/include/asm-parisc/pci.h	Sun Jan  5 03:22:54 2003
+++ b/include/asm-parisc/pci.h	Sun Mar 16 13:55:58 2003
@@ -186,4 +186,8 @@
 /* export the pci_ DMA API in terms of the dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res);
+
 #endif /* __ASM_PARISC_PCI_H */
diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
--- a/include/asm-parisc/pgtable.h	Tue Feb 18 10:12:35 2003
+++ b/include/asm-parisc/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -329,9 +329,9 @@
 #endif
 
 /* Find an entry in the third-level page table.. */ 
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) \
-	((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
diff -Nru a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
--- a/include/asm-parisc/processor.h	Sun Nov 10 05:59:06 2002
+++ b/include/asm-parisc/processor.h	Mon Mar 10 10:20:31 2003
@@ -290,6 +290,9 @@
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
 
 static inline unsigned long get_wchan(struct task_struct *p)
diff -Nru a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
--- a/include/asm-ppc/pci.h	Sun Sep 15 21:52:05 2002
+++ b/include/asm-ppc/pci.h	Sun Mar 16 13:55:58 2003
@@ -273,4 +273,7 @@
 
 #endif	/* __KERNEL__ */
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
 #endif /* __PPC_PCI_H */
diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
--- a/include/asm-ppc/pgtable.h	Mon Oct  7 15:51:14 2002
+++ b/include/asm-ppc/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -494,14 +494,14 @@
 }
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address)		\
+#define pte_index(address)		\
 	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, addr)	\
-	((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(addr))
+	((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir, addr)		\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + __pte_offset(addr))
+	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
 #define pte_offset_map_nested(dir, addr)	\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + __pte_offset(addr))
+	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
 
 #define pte_unmap(pte)		kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte)	kunmap_atomic(pte, KM_PTE1)
diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
--- a/include/asm-ppc/processor.h	Wed Jan 15 20:09:48 2003
+++ b/include/asm-ppc/processor.h	Sat Mar 15 00:27:20 2003
@@ -469,8 +469,8 @@
 #define	ICMP	SPRN_ICMP	/* Instruction TLB Compare Register */
 #define	IMISS	SPRN_IMISS	/* Instruction TLB Miss Register */
 #define	IMMR	SPRN_IMMR      	/* PPC 860/821 Internal Memory Map Register */
-#define	L2CR	SPRN_L2CR    	/* PPC 750 L2 control register */
-#define	L3CR	SPRN_L3CR    	/* PPC 7450 L3 Cache control register */
+#define	L2CR	SPRN_L2CR    	/* Classic PPC L2 cache control register */
+#define	L3CR	SPRN_L3CR	/* PPC 745x L3 cache control register */
 #define	LR	SPRN_LR
 #define	PVR	SPRN_PVR	/* Processor Version */
 #define	RPA	SPRN_RPA	/* Required Physical Address Register */
@@ -607,6 +607,9 @@
 struct task_struct;
 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
 void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+extern void prepare_to_copy(struct task_struct *tsk);
 
 /*
  * Create a new kernel thread.
diff -Nru a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h
--- a/include/asm-ppc64/compat.h	Thu Jan 16 19:02:40 2003
+++ b/include/asm-ppc64/compat.h	Thu Mar 13 21:26:25 2003
@@ -61,7 +61,18 @@
 	compat_off_t	l_start;
 	compat_off_t	l_len;
 	compat_pid_t	l_pid;
-	short		__unused;
+};
+
+#define F_GETLK64	12	/*  using 'struct flock64' */
+#define F_SETLK64	13
+#define F_SETLKW64	14
+
+struct compat_flock64 {
+	short		l_type;
+	short		l_whence;
+	compat_loff_t	l_start;
+	compat_loff_t	l_len;
+	compat_pid_t	l_pid;
 };
 
 struct compat_statfs {
@@ -83,5 +94,8 @@
 #define _COMPAT_NSIG_BPW	32
 
 typedef u32		compat_sigset_word;
+
+#define COMPAT_OFF_T_MAX	0x7fffffff
+#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
 #endif /* _ASM_PPC64_COMPAT_H */
diff -Nru a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h
--- a/include/asm-ppc64/fcntl.h	Mon May  6 23:40:48 2002
+++ b/include/asm-ppc64/fcntl.h	Thu Mar 13 21:26:25 2003
@@ -42,10 +42,6 @@
 #define F_SETSIG	10	/*  for sockets. */
 #define F_GETSIG	11	/*  for sockets. */
 
-#define F_GETLK64	12	/*  using 'struct flock64' */
-#define F_SETLK64	13
-#define F_SETLKW64	14
-
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC	1	/* actually anything with low bit set goes */
 
@@ -87,13 +83,6 @@
 	pid_t l_pid;
 };
 
-struct flock64 {
-	short  l_type;
-	short  l_whence;
-	loff_t l_start;
-	loff_t l_len;
-	pid_t  l_pid;
-};
-
 #define F_LINUX_SPECIFIC_BASE	1024
+
 #endif /* _PPC64_FCNTL_H */
diff -Nru a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
--- a/include/asm-ppc64/pci-bridge.h	Sat Dec  7 20:23:44 2002
+++ b/include/asm-ppc64/pci-bridge.h	Mon Mar  3 22:12:45 2003
@@ -20,7 +20,8 @@
 	phb_type_unknown    = 0x0,
 	phb_type_hypervisor = 0x1,
 	phb_type_python     = 0x10,
-	phb_type_speedwagon = 0x11
+	phb_type_speedwagon = 0x11,
+	phb_type_winnipeg   = 0x12
 };
 
 /*
diff -Nru a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h
--- a/include/asm-ppc64/pci.h	Sat Dec  7 20:23:44 2002
+++ b/include/asm-ppc64/pci.h	Sun Mar 16 13:55:59 2003
@@ -124,4 +124,7 @@
 	
 #endif	/* __KERNEL__ */
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
 #endif /* __PPC64_PCI_H */
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	Wed Feb 19 09:35:28 2003
+++ b/include/asm-ppc64/processor.h	Mon Mar 10 10:20:31 2003
@@ -601,6 +601,9 @@
 void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
 void release_thread(struct task_struct *);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Create a new kernel thread.
  */
diff -Nru a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h
--- a/include/asm-ppc64/topology.h	Mon Feb  3 23:46:59 2003
+++ b/include/asm-ppc64/topology.h	Wed Mar 12 15:19:15 2003
@@ -1,6 +1,7 @@
 #ifndef _ASM_PPC64_TOPOLOGY_H
 #define _ASM_PPC64_TOPOLOGY_H
 
+#include <linux/config.h>
 #include <asm/mmzone.h>
 
 #ifdef CONFIG_NUMA
diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
--- a/include/asm-s390/pgtable.h	Mon Nov 18 12:11:53 2002
+++ b/include/asm-s390/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -467,9 +467,9 @@
 }
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) \
-	((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
diff -Nru a/include/asm-s390/processor.h b/include/asm-s390/processor.h
--- a/include/asm-s390/processor.h	Mon Feb 24 10:19:06 2003
+++ b/include/asm-s390/processor.h	Mon Mar 10 10:20:31 2003
@@ -114,6 +114,9 @@
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Return saved PC of a blocked thread.
  */
diff -Nru a/include/asm-s390x/compat.h b/include/asm-s390x/compat.h
--- a/include/asm-s390x/compat.h	Mon Feb 24 10:25:00 2003
+++ b/include/asm-s390x/compat.h	Sun Mar  9 01:34:45 2003
@@ -64,7 +64,18 @@
 	compat_off_t	l_start;
 	compat_off_t	l_len;
 	compat_pid_t	l_pid;
-	short		__unused;
+};
+
+#define F_GETLK64       12
+#define F_SETLK64       13
+#define F_SETLKW64      14    
+
+struct compat_flock64 {
+	short		l_type;
+	short		l_whence;
+	compat_loff_t	l_start;
+	compat_loff_t	l_len;
+	compat_pid_t	l_pid;
 };
 
 struct compat_statfs {
@@ -86,5 +97,8 @@
 #define _COMPAT_NSIG_BPW	32
 
 typedef u32		compat_sigset_word;
+
+#define COMPAT_OFF_T_MAX	0x7fffffff
+#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
 #endif /* _ASM_S390X_COMPAT_H */
diff -Nru a/include/asm-s390x/fcntl.h b/include/asm-s390x/fcntl.h
--- a/include/asm-s390x/fcntl.h	Mon Feb  4 23:55:11 2002
+++ b/include/asm-s390x/fcntl.h	Sun Mar  9 01:34:45 2003
@@ -80,6 +80,4 @@
 
 #define F_LINUX_SPECIFIC_BASE  1024
 
-#define flock64   flock
-
 #endif
diff -Nru a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h
--- a/include/asm-s390x/pgtable.h	Mon Feb 24 10:25:00 2003
+++ b/include/asm-s390x/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -488,14 +488,14 @@
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 /* Find an entry in the second-level page table.. */
-#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 #define pmd_offset(dir,addr) \
-	((pmd_t *) pgd_page_kernel(*(dir)) + __pmd_offset(addr))
+	((pmd_t *) pgd_page_kernel(*(dir)) + pmd_index(addr))
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) \
-	((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
diff -Nru a/include/asm-s390x/processor.h b/include/asm-s390x/processor.h
--- a/include/asm-s390x/processor.h	Mon Feb 24 10:19:08 2003
+++ b/include/asm-s390x/processor.h	Mon Mar 10 10:20:31 2003
@@ -129,6 +129,9 @@
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Return saved PC of a blocked thread.
  */
diff -Nru a/include/asm-sh/pci.h b/include/asm-sh/pci.h
--- a/include/asm-sh/pci.h	Tue Feb 25 09:18:11 2003
+++ b/include/asm-sh/pci.h	Sun Mar 16 13:55:59 2003
@@ -240,6 +240,8 @@
 
 #endif /* __KERNEL__ */
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
 
 #endif /* __ASM_SH_PCI_H */
 
diff -Nru a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
--- a/include/asm-sh/pgtable.h	Mon Sep  9 14:01:14 2002
+++ b/include/asm-sh/pgtable.h	Thu Mar  6 17:44:46 2003
@@ -98,8 +98,6 @@
 
 #endif /* !__ASSEMBLY__ */
 
-#define __beep() asm("")
-
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
@@ -274,17 +272,16 @@
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-#define __pgd_offset(address) pgd_index(address)
 #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) \
+#define pte_index(address) \
 		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \
-			__pte_offset(address))
+			pte_index(address))
 
 extern void update_mmu_cache(struct vm_area_struct * vma,
 			     unsigned long address, pte_t pte);
diff -Nru a/include/asm-sh/processor.h b/include/asm-sh/processor.h
--- a/include/asm-sh/processor.h	Thu Nov 21 10:04:20 2002
+++ b/include/asm-sh/processor.h	Mon Mar 10 10:20:31 2003
@@ -134,6 +134,10 @@
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * create a kernel thread without removing it from tasklists
  */
diff -Nru a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
--- a/include/asm-sparc/processor.h	Tue Dec  3 15:19:14 2002
+++ b/include/asm-sparc/processor.h	Mon Mar 10 10:20:31 2003
@@ -139,6 +139,9 @@
 #define release_thread(tsk)		do { } while(0)
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern unsigned long get_wchan(struct task_struct *);
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
diff -Nru a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
--- a/include/asm-sparc/termios.h	Mon Feb  4 23:41:04 2002
+++ b/include/asm-sparc/termios.h	Fri Mar  7 15:36:56 2003
@@ -92,7 +92,7 @@
 	reprint=^R	discard=^U	werase=^W	lnext=^V
 	vmin=\1         vtime=\0
 */
-#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001\000"
+#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001"
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
diff -Nru a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
--- a/include/asm-sparc64/compat.h	Fri Jan 17 02:21:48 2003
+++ b/include/asm-sparc64/compat.h	Tue Mar 11 15:41:39 2003
@@ -64,6 +64,19 @@
 	short		__unused;
 };
 
+#define F_GETLK64	12
+#define F_SETLK64	13
+#define F_SETLKW64	14
+
+struct compat_flock64 {
+	short		l_type;
+	short		l_whence;
+	compat_loff_t	l_start;
+	compat_loff_t	l_len;
+	compat_pid_t	l_pid;
+	short		__unused;
+};
+
 struct compat_statfs {
 	int		f_type;
 	int		f_bsize;
@@ -83,5 +96,8 @@
 #define _COMPAT_NSIG_BPW	32
 
 typedef u32		compat_sigset_word;
+
+#define COMPAT_OFF_T_MAX	0x7fffffff
+#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
 #endif /* _ASM_SPARC64_COMPAT_H */
diff -Nru a/include/asm-sparc64/fcntl.h b/include/asm-sparc64/fcntl.h
--- a/include/asm-sparc64/fcntl.h	Fri Jan  3 19:30:06 2003
+++ b/include/asm-sparc64/fcntl.h	Tue Mar 11 15:41:39 2003
@@ -36,12 +36,6 @@
 #define F_SETSIG	10	/*  for sockets. */
 #define F_GETSIG	11	/*  for sockets. */
 
-#ifdef __KERNEL__
-#define F_GETLK64	12
-#define F_SETLK64	13
-#define F_SETLKW64	14
-#endif
-
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC	1	/* actually anything with low bit set goes */
 
@@ -78,9 +72,6 @@
 	short __unused;
 };
 
-#ifdef __KERNEL__
-#define flock64	flock
-#endif
-
 #define F_LINUX_SPECIFIC_BASE	1024
+
 #endif /* !(_SPARC64_FCNTL_H) */
diff -Nru a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
--- a/include/asm-sparc64/pci.h	Tue Feb 25 09:18:16 2003
+++ b/include/asm-sparc64/pci.h	Sun Mar 16 13:55:59 2003
@@ -207,4 +207,7 @@
 
 #endif /* __KERNEL__ */
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
 #endif /* __SPARC64_PCI_H */
diff -Nru a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
--- a/include/asm-sparc64/pgtable.h	Thu Oct  3 11:02:09 2002
+++ b/include/asm-sparc64/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -273,11 +273,11 @@
 					((address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD-1)))
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(dir, address)	((pte_t *) __pmd_page(*(dir)) + \
+#define pte_index(dir, address)	((pte_t *) __pmd_page(*(dir)) + \
 					((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
-#define pte_offset_kernel		__pte_offset
-#define pte_offset_map			__pte_offset
-#define pte_offset_map_nested		__pte_offset
+#define pte_offset_kernel		pte_index
+#define pte_offset_map			pte_index
+#define pte_offset_map_nested		pte_index
 #define pte_unmap(pte)			do { } while (0)
 #define pte_unmap_nested(pte)		do { } while (0)
 
diff -Nru a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
--- a/include/asm-sparc64/processor.h	Fri Dec 20 18:49:02 2002
+++ b/include/asm-sparc64/processor.h	Mon Mar 10 10:20:31 2003
@@ -186,6 +186,9 @@
 /* Free all resources held by a thread. */
 #define release_thread(tsk)		do { } while (0)
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 extern unsigned long get_wchan(struct task_struct *task);
diff -Nru a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
--- a/include/asm-sparc64/termios.h	Mon Feb  4 23:41:04 2002
+++ b/include/asm-sparc64/termios.h	Fri Mar  7 15:36:56 2003
@@ -91,7 +91,7 @@
 	reprint=^R	discard=^U	werase=^W	lnext=^V
 	vmin=\1         vtime=\0
 */
-#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001\000"
+#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001"
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
diff -Nru a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
--- a/include/asm-um/pgtable.h	Tue Feb 25 01:39:17 2003
+++ b/include/asm-um/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -357,7 +357,6 @@
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-#define __pgd_offset(address) pgd_index(address)
 
 /* to find an entry in a page-table-directory */
 #define pgd_offset(mm, address) \
@@ -366,7 +365,7 @@
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-#define __pmd_offset(address) \
+#define pmd_index(address) \
 		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
 /* Find an entry in the second-level page table.. */
@@ -376,13 +375,13 @@
 }
 
 /* Find an entry in the third-level page table.. */ 
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
-	((pte_t *) pmd_page_kernel(*(dir)) +  __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
 #define pte_offset_map(dir, address) \
-        ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address))
+        ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
 #define pte_offset_map_nested(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address))
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
 #define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
 #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
 
diff -Nru a/include/asm-v850/processor.h b/include/asm-v850/processor.h
--- a/include/asm-v850/processor.h	Tue Dec 17 00:23:49 2002
+++ b/include/asm-v850/processor.h	Mon Mar 10 10:20:31 2003
@@ -81,6 +81,9 @@
 {
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread (int (*fn)(void *), void * arg, unsigned long flags);
 
 /* Free current thread data structures etc.  */
diff -Nru a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h
--- a/include/asm-x86_64/compat.h	Thu Feb  6 06:49:36 2003
+++ b/include/asm-x86_64/compat.h	Mon Mar 10 16:30:59 2003
@@ -68,6 +68,22 @@
 	compat_pid_t	l_pid;
 };
 
+#define F_GETLK64	12	/*  using 'struct flock64' */
+#define F_SETLK64	13
+#define F_SETLKW64	14
+
+/*
+ * IA32 uses 4 byte alignment for 64 bit quantities,
+ * so we need to pack this structure.
+ */
+struct compat_flock64 {
+	short		l_type;
+	short		l_whence;
+	compat_loff_t	l_start;
+	compat_loff_t	l_len;
+	compat_pid_t	l_pid;
+} __attribute__((packed));
+
 struct compat_statfs {
 	int		f_type;
 	int		f_bsize;
@@ -87,5 +103,8 @@
 #define _COMPAT_NSIG_BPW	32
 
 typedef u32               compat_sigset_word;
+
+#define COMPAT_OFF_T_MAX	0x7fffffff
+#define COMPAT_LOFF_T_MAX	0x7fffffffffffffff
 
 #endif /* _ASM_X86_64_COMPAT_H */
diff -Nru a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
--- a/include/asm-x86_64/desc.h	Sat Jan 18 05:53:43 2003
+++ b/include/asm-x86_64/desc.h	Sun Mar  9 16:22:43 2003
@@ -138,9 +138,11 @@
 static inline void set_seg_base(unsigned cpu, int entry, void *base)
 { 
 	struct desc_struct *d = &cpu_gdt_table[cpu][entry];
-	d->base0 = PTR_LOW(base);
-	d->base1 = PTR_MIDDLE(base);
-	d->base2 = PTR_HIGH(base);
+	u32 addr = (u32)(u64)base;
+	BUG_ON((u64)base >> 32); 
+	d->base0 = addr & 0xffff;
+	d->base1 = (addr >> 16) & 0xff;
+	d->base2 = (addr >> 24) & 0xff;
 } 
 
 #define LDT_entry_a(info) \
diff -Nru a/include/asm-x86_64/fcntl.h b/include/asm-x86_64/fcntl.h
--- a/include/asm-x86_64/fcntl.h	Thu Feb  7 02:55:27 2002
+++ b/include/asm-x86_64/fcntl.h	Sun Mar  9 01:34:45 2003
@@ -72,8 +72,4 @@
 
 #define F_LINUX_SPECIFIC_BASE	1024
 
-#ifdef __KERNEL__
-#define flock64	flock
-#endif
-
 #endif /* !_X86_64_FCNTL_H */
diff -Nru a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
--- a/include/asm-x86_64/ia32.h	Mon Feb 10 17:21:29 2003
+++ b/include/asm-x86_64/ia32.h	Sun Mar  9 01:34:45 2003
@@ -11,18 +11,6 @@
  * 32 bit structures for IA32 support.
  */
 
-struct ia32_flock64 {
-	short  l_type;
-	short  l_whence;
-	loff_t l_start;  /* unnatural alignment */
-	loff_t l_len;
-	pid_t  l_pid;
-} __attribute__((packed));
-
-#define F_GETLK64	12	/*  using 'struct flock64' */
-#define F_SETLK64	13
-#define F_SETLKW64	14
-
 #include <asm/sigcontext32.h>
 
 /* signal.h */
@@ -153,13 +141,15 @@
 	char			f_fpack[6];
 };
 
-struct iovec32 { 
-	unsigned int iov_base; 
-	int iov_len; 
-};
-
 #define IA32_PAGE_OFFSET 0xffffe000
 #define IA32_STACK_TOP IA32_PAGE_OFFSET
+
+#ifdef __KERNEL__
+struct user_desc;
+int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info);
+int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info);
+int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs);
+#endif
 
 #endif /* !CONFIG_IA32_SUPPORT */
  
diff -Nru a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
--- a/include/asm-x86_64/pci.h	Sun Oct 20 21:27:39 2002
+++ b/include/asm-x86_64/pci.h	Sun Mar 16 13:55:59 2003
@@ -279,4 +279,7 @@
 
 #endif /* __KERNEL__ */
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
 #endif /* __x8664_PCI_H */
diff -Nru a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
--- a/include/asm-x86_64/pgtable.h	Sat Feb 15 03:05:09 2003
+++ b/include/asm-x86_64/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -321,9 +321,9 @@
 #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
 #define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
 
-#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \
-			__pmd_offset(address))
+			pmd_index(address))
 #define pmd_none(x)	(!pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
 #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
@@ -353,10 +353,10 @@
        return pte; 
 }
 
-#define __pte_offset(address) \
+#define pte_index(address) \
 		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
-			__pte_offset(address))
+			pte_index(address))
 
 /* x86-64 always has all page tables mapped. */
 #define pte_offset_map(dir,address) pte_offset_kernel(dir,address)
diff -Nru a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
--- a/include/asm-x86_64/processor.h	Sat Feb 15 03:56:35 2003
+++ b/include/asm-x86_64/processor.h	Mon Mar 10 10:20:31 2003
@@ -267,6 +267,10 @@
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * create a kernel thread without removing it from tasklists
  */
diff -Nru a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
--- a/include/asm-x86_64/proto.h	Tue Feb 11 06:00:14 2003
+++ b/include/asm-x86_64/proto.h	Sun Mar  9 04:31:52 2003
@@ -57,11 +57,11 @@
 extern unsigned long end_pfn; 
 extern unsigned long table_start, table_end;
 
-struct thread_struct;
-struct user_desc;
+extern void syscall_init(void);
 
-int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info);
-int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info);
+struct pt_regs;
+
+long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 
 #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
 #define round_down(x,y) ((x) & ~((y)-1))
diff -Nru a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h
--- a/include/asm-x86_64/ptrace.h	Thu Jan 16 06:08:20 2003
+++ b/include/asm-x86_64/ptrace.h	Sat Mar  8 17:17:13 2003
@@ -78,9 +78,11 @@
 #define PTRACE_GETFPXREGS         18
 #define PTRACE_SETFPXREGS         19
 
+/* only useful for access 32bit programs */
 #define PTRACE_GET_THREAD_AREA    25
 #define PTRACE_SET_THREAD_AREA    26
 
+#define PTRACE_ARCH_PRCTL	  30	/* arch_prctl for child */
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 
 #define user_mode(regs) (!!((regs)->cs & 3))
diff -Nru a/include/asm-x86_64/segment.h b/include/asm-x86_64/segment.h
--- a/include/asm-x86_64/segment.h	Mon Feb 10 13:23:03 2003
+++ b/include/asm-x86_64/segment.h	Sun Mar  9 07:03:05 2003
@@ -6,8 +6,6 @@
 
 #define __KERNEL32_CS   0x38
 
-#define __USER_LONGBASE	((GDT_ENTRY_LONGBASE * 8)  | 3)
-
 /* 
  * we cannot use the same code segment descriptor for user and kernel
  * -- not even in the long flat mode, because of different DPL /kkeil 
@@ -30,6 +28,13 @@
 #define GDT_ENTRY_KERNELCS16 15
 
 #define GDT_ENTRY_TLS_ENTRIES 3
+
+/* TLS indexes for 64bit - hardcoded in arch_prctl */
+#define FS_TLS 0	
+#define GS_TLS 1	
+
+#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)
+#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
 
 #define IDT_ENTRIES 256
 #define GDT_ENTRIES 16
diff -Nru a/include/asm-x86_64/socket32.h b/include/asm-x86_64/socket32.h
--- a/include/asm-x86_64/socket32.h	Fri Dec 20 15:02:21 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,64 +0,0 @@
-#ifndef SOCKET32_H
-#define SOCKET32_H 1
-
-#include <linux/compat.h>
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-struct msghdr32 {
-        u32               msg_name;
-        int               msg_namelen;
-        u32               msg_iov;
-        compat_size_t msg_iovlen;
-        u32               msg_control;
-        compat_size_t msg_controllen;
-        unsigned          msg_flags;
-};
-
-struct cmsghdr32 {
-        compat_size_t cmsg_len;
-        int               cmsg_level;
-        int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-#endif
diff -Nru a/include/asm-x86_64/suspend.h b/include/asm-x86_64/suspend.h
--- a/include/asm-x86_64/suspend.h	Sat Nov 30 06:32:19 2002
+++ b/include/asm-x86_64/suspend.h	Wed Mar  5 01:43:59 2003
@@ -14,7 +14,7 @@
 /* image of the saved processor state */
 struct saved_context {
   	u16 ds, es, fs, gs, ss;
-	unsigned long gs_base, fs_base;
+	unsigned long gs_base, gs_kernel_base, fs_base;
 	unsigned long cr0, cr2, cr3, cr4;
 	u16 gdt_pad;
 	u16 gdt_limit;
diff -Nru a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
--- a/include/asm-x86_64/uaccess.h	Tue Feb 25 10:12:17 2003
+++ b/include/asm-x86_64/uaccess.h	Tue Mar 11 11:48:45 2003
@@ -5,6 +5,7 @@
  * User space memory access functions
  */
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/prefetch.h>
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	Sat Feb 22 02:24:04 2003
+++ b/include/asm-x86_64/unistd.h	Sat Mar  8 15:53:55 2003
@@ -469,7 +469,7 @@
 #define __NR_sched_getaffinity     204
 __SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity)
 #define __NR_set_thread_area	205
-__SYSCALL(__NR_set_thread_area, sys_set_thread_area)
+__SYSCALL(__NR_set_thread_area, sys_ni_syscall)	/* use arch_prctl */
 #define __NR_io_setup	206
 __SYSCALL(__NR_io_setup, sys_io_setup)
 #define __NR_io_destroy	207
@@ -481,7 +481,7 @@
 #define __NR_io_cancel	210
 __SYSCALL(__NR_io_cancel, sys_io_cancel)
 #define __NR_get_thread_area	211
-__SYSCALL(__NR_get_thread_area, sys_get_thread_area)
+__SYSCALL(__NR_get_thread_area, sys_ni_syscall)	/* use arch_prctl */
 #define __NR_lookup_dcookie	212
 __SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie)
 #define __NR_epoll_create	213
diff -Nru a/include/linux/aio.h b/include/linux/aio.h
--- a/include/linux/aio.h	Thu Oct  3 13:19:27 2002
+++ b/include/linux/aio.h	Sun Mar 16 22:33:18 2003
@@ -37,9 +37,9 @@
 #define kiocbSetKicked(iocb)	set_bit(KIF_KICKED, &(iocb)->ki_flags)
 #define kiocbSetCancelled(iocb)	set_bit(KIF_CANCELLED, &(iocb)->ki_flags)
 
-#define kiocbClearLocked(iocb)	set_bit(KIF_LOCKED, &(iocb)->ki_flags)
-#define kiocbClearKicked(iocb)	set_bit(KIF_KICKED, &(iocb)->ki_flags)
-#define kiocbClearCancelled(iocb)	set_bit(KIF_CANCELLED, &(iocb)->ki_flags)
+#define kiocbClearLocked(iocb)	clear_bit(KIF_LOCKED, &(iocb)->ki_flags)
+#define kiocbClearKicked(iocb)	clear_bit(KIF_KICKED, &(iocb)->ki_flags)
+#define kiocbClearCancelled(iocb)	clear_bit(KIF_CANCELLED, &(iocb)->ki_flags)
 
 #define kiocbIsLocked(iocb)	test_bit(0, &(iocb)->ki_flags)
 #define kiocbIsKicked(iocb)	test_bit(1, &(iocb)->ki_flags)
diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h
--- a/include/linux/atmdev.h	Wed Feb 19 23:22:24 2003
+++ b/include/linux/atmdev.h	Sat Mar  8 13:09:15 2003
@@ -277,7 +277,6 @@
 
 struct atm_vcc {
 	unsigned long	flags;		/* VCC flags (ATM_VF_*) */
-	unsigned char	family;		/* address family; 0 if unused */
 	short		vpi;		/* VPI and VCI (types must be equal */
 					/* with sockaddr) */
 	int 		vci;
@@ -286,7 +285,6 @@
 	struct atm_dev	*dev;		/* device back pointer */
 	struct atm_qos	qos;		/* QOS */
 	struct atm_sap	sap;		/* SAP */
-	atomic_t	tx_inuse,rx_inuse; /* buffer space in use */
 	void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
 	void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
 	struct sk_buff *(*alloc_tx)(struct atm_vcc *vcc,unsigned int size);
@@ -297,7 +295,6 @@
 	int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
 	void		*dev_data;	/* per-device data */
 	void		*proto_data;	/* per-protocol data */
-	struct sk_buff_head recvq;	/* receive queue */
 	struct k_atm_aal_stats *stats;	/* pointer to AAL stats group */
 	wait_queue_head_t sleep;	/* if socket is busy */
 	struct sock	*sk;		/* socket backpointer */
@@ -346,7 +343,7 @@
 	struct proc_dir_entry *proc_entry; /* proc entry */
 	char *proc_name;		/* proc entry name */
 #endif
-	struct atm_dev	*prev,*next;	/* linkage */
+	struct list_head dev_list;	/* linkage */
 };
 
 
@@ -425,19 +422,19 @@
 
 static __inline__ void atm_force_charge(struct atm_vcc *vcc,int truesize)
 {
-	atomic_add(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
+	atomic_add(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
 }
 
 
 static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
 {
-	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
+	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
 }
 
 
 static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size)
 {
-	return size+atomic_read(&vcc->tx_inuse)+ATM_PDU_OVHD < vcc->sk->sndbuf;
+	return size+atomic_read(&vcc->sk->wmem_alloc)+ATM_PDU_OVHD < vcc->sk->sndbuf;
 }
 
 
diff -Nru a/include/linux/bio.h b/include/linux/bio.h
--- a/include/linux/bio.h	Tue Jan  7 14:52:28 2003
+++ b/include/linux/bio.h	Thu Mar 13 11:17:53 2003
@@ -239,7 +239,6 @@
 	 * balancing is a lot nicer this way
 	 */
 	local_save_flags(*flags);
-	local_irq_disable();
 	addr = (unsigned long) kmap_atomic(bio_page(bio), KM_BIO_SRC_IRQ);
 
 	if (addr & ~PAGE_MASK)
diff -Nru a/include/linux/compat.h b/include/linux/compat.h
--- a/include/linux/compat.h	Tue Jan 14 21:33:09 2003
+++ b/include/linux/compat.h	Sun Mar  9 01:34:45 2003
@@ -10,7 +10,6 @@
 
 #include <linux/stat.h>
 #include <linux/param.h>	/* for HZ */
-#include <linux/fcntl.h>	/* for struct flock */
 #include <asm/compat.h>
 
 #define compat_jiffies_to_clock_t(x)	\
@@ -40,10 +39,15 @@
 } compat_sigset_t;
 
 extern int cp_compat_stat(struct kstat *, struct compat_stat *);
-extern int get_compat_flock(struct flock *, struct compat_flock *);
-extern int put_compat_flock(struct flock *, struct compat_flock *);
 extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
 extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
+
+struct compat_iovec {
+	u32		iov_base;
+	compat_size_t	iov_len;
+};
+#else /* no CONFIG_COMPAT */
+#define compat_size_t	size_t
 
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	Fri Feb 21 19:50:41 2003
+++ b/include/linux/compiler.h	Mon Mar 10 22:34:24 2003
@@ -1,6 +1,12 @@
 #ifndef __LINUX_COMPILER_H
 #define __LINUX_COMPILER_H
 
+#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#define inline		__inline__ __attribute__((always_inline))
+#define __inline__	__inline__ __attribute__((always_inline))
+#define __inline	__inline__ __attribute__((always_inline))
+#endif
+
 /* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
    a mechanism by which the user can annotate likely branch directions and
    expect the blocks to be reordered appropriately.  Define __builtin_expect
diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h
--- a/include/linux/cpufreq.h	Mon Mar  3 14:38:51 2003
+++ b/include/linux/cpufreq.h	Sat Mar  8 01:39:17 2003
@@ -18,7 +18,8 @@
 #include <linux/notifier.h>
 #include <linux/threads.h>
 #include <linux/device.h>
-
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
 
 #define CPUFREQ_NAME_LEN 16
 
@@ -69,6 +70,8 @@
 	struct cpufreq_cpuinfo  cpuinfo;     /* see above */
 	struct device		* dev;
 	struct kobject		kobj;
+ 	struct semaphore	lock;   /* CPU ->setpolicy or ->target may
+					   only be called once a time */
 };
 
 #define CPUFREQ_ADJUST          (0)
@@ -131,18 +134,13 @@
 };
 
 /* pass a target to the cpufreq driver 
- * _l : (cpufreq_driver_sem is not held)
  */
 inline int cpufreq_driver_target(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation);
 
-inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-				   unsigned int target_freq,
-				   unsigned int relation);
-
 /* pass an event to the cpufreq governor */
-int cpufreq_governor_l(unsigned int cpu, unsigned int event);
+int cpufreq_governor(unsigned int cpu, unsigned int event);
 
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
@@ -154,6 +152,8 @@
 #define CPUFREQ_RELATION_L 0  /* lowest frequency at or above target */
 #define CPUFREQ_RELATION_H 1  /* highest frequency below or at target */
 
+struct freq_attr;
+
 struct cpufreq_driver {
 	/* needed by all drivers */
 	int	(*verify)	(struct cpufreq_policy *policy);
@@ -164,16 +164,15 @@
 	int	(*target)	(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation);
+	struct module           *owner;
 	/* optional, for the moment */
 	int	(*init)		(struct cpufreq_policy *policy);
 	int	(*exit)		(struct cpufreq_policy *policy);
+	struct freq_attr	**attr;
 };
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
-/* deprecated */
-#define cpufreq_register(x)   cpufreq_register_driver(x)
-#define cpufreq_unregister() cpufreq_unregister_driver(NULL)
 
 
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state);
@@ -194,6 +193,13 @@
 	return;
 }
 
+struct freq_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct cpufreq_policy *, char *);
+	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
+};
+
+
 /*********************************************************************
  *                        CPUFREQ 2.6. INTERFACE                     *
  *********************************************************************/
@@ -289,15 +295,20 @@
 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table);
 
-int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
-				      struct cpufreq_frequency_table *table,
-				      unsigned int *index);
-
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table,
 				   unsigned int target_freq,
 				   unsigned int relation,
 				   unsigned int *index);
+
+/* the following are really really optional */
+extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 
+				      unsigned int cpu);
+
+void cpufreq_frequency_table_put_attr(unsigned int cpu);
+
 
 #endif /* CONFIG_CPU_FREQ_TABLE */
 
diff -Nru a/include/linux/crypto.h b/include/linux/crypto.h
--- a/include/linux/crypto.h	Sun Feb  2 23:34:59 2003
+++ b/include/linux/crypto.h	Sat Mar  8 11:46:18 2003
@@ -134,10 +134,18 @@
 			   struct scatterlist *dst,
 			   struct scatterlist *src,
 			   unsigned int nbytes);
+	int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
+	                      struct scatterlist *dst,
+	                      struct scatterlist *src,
+	                      unsigned int nbytes, u8 *iv);
 	int (*cit_decrypt)(struct crypto_tfm *tfm,
 			   struct scatterlist *dst,
 			   struct scatterlist *src,
 			   unsigned int nbytes);
+	int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
+			   struct scatterlist *dst,
+			   struct scatterlist *src,
+			   unsigned int nbytes, u8 *iv);
 	void (*cit_xor_block)(u8 *dst, const u8 *src);
 };
 
@@ -164,7 +172,6 @@
 
 struct crypto_tfm {
 
-	void *crt_ctx;
 	u32 crt_flags;
 	
 	union {
@@ -286,6 +293,16 @@
 	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
 }                                        
 
+static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
+                                           struct scatterlist *dst,
+                                           struct scatterlist *src,
+                                           unsigned int nbytes, u8 *iv)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+	return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
+}                                        
+
 static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
                                         struct scatterlist *dst,
                                         struct scatterlist *src,
@@ -293,6 +310,16 @@
 {
 	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
 	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
+}
+
+static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
+                                           struct scatterlist *dst,
+                                           struct scatterlist *src,
+                                           unsigned int nbytes, u8 *iv)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+	return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
 }
 
 static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
diff -Nru a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
--- a/include/linux/devfs_fs_kernel.h	Wed Jan 15 12:56:40 2003
+++ b/include/linux/devfs_fs_kernel.h	Tue Mar 11 05:58:19 2003
@@ -13,8 +13,6 @@
 
 #define DEVFS_FL_NONE           0x000 /* This helps to make code more readable
 				       */
-#define DEVFS_FL_AUTO_DEVNUM    0x002 /* Automatically generate device number
-				       */
 #define DEVFS_FL_REMOVABLE      0x008 /* This is a removable media device    */
 #define DEVFS_FL_WAIT           0x010 /* Wait for devfsd to finish           */
 #define DEVFS_FL_CURRENT_OWNER  0x020 /* Set initial ownership to current    */
@@ -51,8 +49,6 @@
 extern devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name,
 				    void *info);
 extern int devfs_generate_path (devfs_handle_t de, char *path, int buflen);
-extern int devfs_set_file_size (devfs_handle_t de, unsigned long size);
-extern int devfs_only (void);
 extern int devfs_register_tape (devfs_handle_t de);
 extern void devfs_unregister_tape(int num);
 extern int devfs_alloc_unique_number (struct unique_numspace *space);
@@ -106,14 +102,6 @@
 				       int buflen)
 {
     return -ENOSYS;
-}
-static inline int devfs_set_file_size (devfs_handle_t de, unsigned long size)
-{
-    return -ENOSYS;
-}
-static inline int devfs_only (void)
-{
-    return 0;
 }
 static inline int devfs_register_tape (devfs_handle_t de)
 {
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Mon Mar  3 10:48:36 2003
+++ b/include/linux/device.h	Thu Mar 13 16:37:19 2003
@@ -79,6 +79,8 @@
 extern int bus_register(struct bus_type * bus);
 extern void bus_unregister(struct bus_type * bus);
 
+extern int bus_rescan_devices(struct bus_type * bus);
+
 extern struct bus_type * get_bus(struct bus_type * bus);
 extern void put_bus(struct bus_type * bus);
 
@@ -364,6 +366,7 @@
 extern void platform_device_unregister(struct platform_device *);
 
 extern struct bus_type platform_bus_type;
+extern struct device legacy_bus;
 
 /* drivers/base/power.c */
 extern int device_suspend(u32 state, u32 level);
diff -Nru a/include/linux/efs_fs.h b/include/linux/efs_fs.h
--- a/include/linux/efs_fs.h	Tue Dec 31 17:17:28 2002
+++ b/include/linux/efs_fs.h	Sun Feb 16 16:16:32 2003
@@ -15,14 +15,6 @@
 
 #include <asm/uaccess.h>
 
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#if LINUX_VERSION_CODE < 0x20200
-#error This code is only for linux-2.2 and later.
-#endif
-
 /* 1 block is 512 bytes */
 #define	EFS_BLOCKSIZE_BITS	9
 #define	EFS_BLOCKSIZE		(1 << EFS_BLOCKSIZE_BITS)
@@ -31,13 +23,6 @@
 #include <linux/efs_fs_i.h>
 #include <linux/efs_fs_sb.h>
 #include <linux/efs_dir.h>
-
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#endif
 
 static inline struct efs_inode_info *INODE_INFO(struct inode *inode)
 {
diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h
--- a/include/linux/eisa.h	Sat Feb 15 04:56:07 2003
+++ b/include/linux/eisa.h	Wed Mar  5 07:11:17 2003
@@ -20,7 +20,8 @@
 
 /* The EISA signature, in ASCII form, null terminated */
 struct eisa_device_id {
-	char sig[EISA_SIG_LEN];
+	char          sig[EISA_SIG_LEN];
+	unsigned long driver_data;
 };
 
 /* There is not much we can say about an EISA device, apart from
diff -Nru a/include/linux/elf.h b/include/linux/elf.h
--- a/include/linux/elf.h	Mon Feb 24 10:24:54 2003
+++ b/include/linux/elf.h	Mon Mar  3 13:04:56 2003
@@ -83,6 +83,8 @@
 
 #define EM_V850		87	/* NEC v850 */
 
+#define EM_H8_300H      47      /* Hitachi H8/300H */
+#define EM_H8S          48      /* Hitachi H8S     */
 
 /*
  * This is an interim value that we will use until the committee comes
diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
--- a/include/linux/ext3_fs.h	Mon Jan 13 23:56:29 2003
+++ b/include/linux/ext3_fs.h	Sun Mar 16 22:33:16 2003
@@ -730,6 +730,7 @@
 extern void ext3_dirty_inode(struct inode *);
 extern int ext3_change_inode_journal_flag(struct inode *, int);
 extern void ext3_truncate (struct inode *);
+extern void ext3_set_inode_flags(struct inode *);
 
 /* ioctl.c */
 extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Tue Mar  4 14:30:07 2003
+++ b/include/linux/fs.h	Wed Mar 12 11:10:29 2003
@@ -456,7 +456,10 @@
 #define get_file(x)	atomic_inc(&(x)->f_count)
 #define file_count(x)	atomic_read(&(x)->f_count)
 
-extern int init_private_file(struct file *, struct dentry *, int);
+/* Initialize and open a private file and allocate its security structure. */
+extern int open_private_file(struct file *, struct dentry *, int);
+/* Release a private file and free its security structure. */
+extern void close_private_file(struct file *file);
 
 #define	MAX_NON_LFS	((1UL<<31) - 1)
 
@@ -526,8 +529,10 @@
 extern int fcntl_getlk(struct file *, struct flock *);
 extern int fcntl_setlk(struct file *, unsigned int, struct flock *);
 
+#if BITS_PER_LONG == 32
 extern int fcntl_getlk64(struct file *, struct flock64 *);
 extern int fcntl_setlk64(struct file *, unsigned int, struct flock64 *);
+#endif
 
 /* fs/locks.c */
 extern void locks_init_lock(struct file_lock *);
@@ -1033,7 +1038,7 @@
 #define putname(name)	kmem_cache_free(names_cachep, (void *)(name))
 
 enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW};
-extern int register_blkdev(unsigned int, const char *, struct block_device_operations *);
+extern int register_blkdev(unsigned int, const char *);
 extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern int bd_acquire(struct inode *inode);
diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h
--- a/include/linux/genhd.h	Thu Feb 13 10:14:34 2003
+++ b/include/linux/genhd.h	Sat Mar  8 14:50:30 2003
@@ -13,6 +13,8 @@
 #include <linux/types.h>
 #include <linux/major.h>
 #include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/string.h>
 
 enum {
 /* These three have identical behaviour; use the second one if DOS FDISK gets
@@ -70,6 +72,16 @@
 #define GENHD_FL_CD	8
 #define GENHD_FL_UP	16
 
+struct disk_stats {
+	unsigned read_sectors, write_sectors;
+	unsigned reads, writes;
+	unsigned read_merges, write_merges;
+	unsigned read_ticks, write_ticks;
+	unsigned io_ticks;
+	int in_flight;
+	unsigned time_in_queue;
+};
+	
 struct gendisk {
 	int major;			/* major number of driver */
 	int first_minor;
@@ -94,15 +106,85 @@
 	int policy;
 
 	unsigned sync_io;		/* RAID */
-	unsigned read_sectors, write_sectors;
-	unsigned reads, writes;
-	unsigned read_merges, write_merges;
-	unsigned read_ticks, write_ticks;
-	unsigned io_ticks;
-	int in_flight;
 	unsigned long stamp, stamp_idle;
-	unsigned time_in_queue;
+#ifdef	CONFIG_SMP
+	struct disk_stats *dkstats;
+#else
+	struct disk_stats dkstats;
+#endif
 };
+
+/* 
+ * Macros to operate on percpu disk statistics:
+ * Since writes to disk_stats are serialised through the queue_lock,
+ * smp_processor_id() should be enough to get to the per_cpu versions
+ * of statistics counters
+ */
+#ifdef	CONFIG_SMP
+#define disk_stat_add(gendiskp, field, addnd) 	\
+	(per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd)
+#define disk_stat_read(gendiskp, field)					\
+({									\
+	typeof(gendiskp->dkstats->field) res = 0;			\
+	int i;								\
+	for (i=0; i < NR_CPUS; i++) {					\
+		if (!cpu_possible(i))					\
+			continue;					\
+		res += per_cpu_ptr(gendiskp->dkstats, i)->field;	\
+	}								\
+	res;								\
+})
+
+static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)	{
+	int i;
+	for (i=0; i < NR_CPUS; i++) {
+		if (cpu_possible(i)) {
+			memset(per_cpu_ptr(gendiskp->dkstats, i), value,	
+					sizeof (struct disk_stats));
+		}
+	}
+}		
+				
+#else
+#define disk_stat_add(gendiskp, field, addnd) (gendiskp->dkstats.field += addnd)
+#define disk_stat_read(gendiskp, field)	(gendiskp->dkstats.field)
+
+static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)	{
+	memset(&gendiskp->dkstats, value, sizeof (struct disk_stats));
+}
+#endif
+
+#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1)
+#define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1)
+#define disk_stat_sub(gendiskp, field, subnd) \
+		disk_stat_add(gendiskp, field, -subnd)
+
+
+/* Inlines to alloc and free disk stats in struct gendisk */
+#ifdef  CONFIG_SMP
+static inline int init_disk_stats(struct gendisk *disk)
+{
+	disk->dkstats = kmalloc_percpu(sizeof (struct disk_stats), GFP_KERNEL);
+	if (!disk->dkstats)
+		return 0;
+	disk_stat_set_all(disk, 0);
+	return 1;
+}
+
+static inline void free_disk_stats(struct gendisk *disk)
+{
+	kfree_percpu(disk->dkstats);
+}
+#else	/* CONFIG_SMP */
+static inline int init_disk_stats(struct gendisk *disk)
+{
+	return 1;
+}
+
+static inline void free_disk_stats(struct gendisk *disk)
+{
+}
+#endif	/* CONFIG_SMP */
 
 /* drivers/block/ll_rw_blk.c */
 extern void disk_round_stats(struct gendisk *disk);
diff -Nru a/include/linux/hugetlb.h b/include/linux/hugetlb.h
--- a/include/linux/hugetlb.h	Sun Mar  2 18:14:37 2003
+++ b/include/linux/hugetlb.h	Sat Mar  8 14:50:40 2003
@@ -66,6 +66,7 @@
 
 #ifndef HPAGE_MASK
 #define HPAGE_MASK	0		/* Keep the compiler happy */
+#define HPAGE_SIZE	0
 #endif
 
 #endif /* !CONFIG_HUGETLB_PAGE */
diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h
--- a/include/linux/i2c-id.h	Tue Feb  4 12:58:09 2003
+++ b/include/linux/i2c-id.h	Tue Mar 11 12:21:11 2003
@@ -20,7 +20,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
 /* ------------------------------------------------------------------------- */
 
-/* $Id: i2c-id.h,v 1.63 2003/01/21 08:08:16 kmalkki Exp $ */
+/* $Id: i2c-id.h,v 1.68 2003/02/25 02:55:18 mds Exp $ */
 
 #ifndef LINUX_I2C_ID_H
 #define LINUX_I2C_ID_H
@@ -150,6 +150,7 @@
 #define I2C_DRIVERID_BMCSENSORS 1036
 #define I2C_DRIVERID_FS451 1037
 #define I2C_DRIVERID_W83627HF 1038
+#define I2C_DRIVERID_LM85 1039
 
 /*
  * ---- Adapter types ----------------------------------------------------
@@ -171,6 +172,7 @@
 #define I2C_ALGO_MPC824X 0x0a0000	/* Motorola 8240 / 8245         */
 #define I2C_ALGO_IPMI 	0x0b0000	/* IPMI dummy adapter */
 #define I2C_ALGO_IPMB 	0x0c0000	/* IPMB adapter */
+#define I2C_ALGO_MPC107 0x0d0000
 #define I2C_ALGO_EC     0x100000        /* ACPI embedded controller     */
 
 #define I2C_ALGO_MPC8XX 0x110000	/* MPC8xx PowerPC I2C algorithm */
@@ -209,6 +211,8 @@
 #define I2C_HW_B_IOC	0x11	/* IOC bit-wiggling			*/
 #define I2C_HW_B_TSUNA  0x12	/* DEC Tsunami chipset			*/
 #define I2C_HW_B_FRODO  0x13    /* 2d3D, Inc. SA-1110 Development Board */
+#define I2C_HW_B_OMAHA  0x14    /* Omaha I2C interface (ARM)		*/
+#define I2C_HW_B_GUIDE  0x15    /* Guide bit-basher			*/
 
 /* --- PCF 8584 based algorithms					*/
 #define I2C_HW_P_LP	0x00	/* Parallel port interface		*/
@@ -244,6 +248,7 @@
 #define I2C_HW_SMBUS_SIS645	0x09
 #define I2C_HW_SMBUS_AMD8111	0x0a
 #define I2C_HW_SMBUS_SCX200	0x0b
+#define I2C_HW_SMBUS_NFORCE2	0x0c
 
 /* --- ISA pseudo-adapter						*/
 #define I2C_HW_ISA 0x00
@@ -253,5 +258,8 @@
 
 /* --- IPMB adapter						*/
 #define I2C_HW_IPMB 0x00
+
+/* --- MCP107 adapter */
+#define I2C_HW_MPC107 0x00
 
 #endif /* LINUX_I2C_ID_H */
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	Tue Feb  4 12:58:09 2003
+++ b/include/linux/i2c.h	Thu Mar 13 16:39:32 2003
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/i2c-id.h>
+#include <linux/device.h>	/* for struct device */
 #include <asm/semaphore.h>
 
 /* --- General options ------------------------------------------------	*/
@@ -144,6 +145,8 @@
 	int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
 };
 
+extern struct bus_type i2c_bus_type;
+
 /*
  * i2c_client identifies a single device (i.e. chip) that is connected to an 
  * i2c bus. The behaviour is defined by the routines of the driver. This
@@ -220,20 +223,22 @@
 			/* and can be set via the i2c_ioctl call	*/
 
 			/* data fields that are valid for all devices	*/
-	struct semaphore lock;  
+	struct semaphore bus;
+	struct semaphore list;  
 	unsigned int flags;/* flags specifying div. data		*/
 
 	struct i2c_client *clients[I2C_CLIENT_MAX];
-	int client_count;
 
 	int timeout;
 	int retries;
+	struct device dev;	/* the adapter device */
 
 #ifdef CONFIG_PROC_FS 
 	/* No need to set this when you initialize the adapter          */
 	int inode;
 #endif /* def CONFIG_PROC_FS */
 };
+#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
 /*flags for the driver struct: */
 #define I2C_DF_NOTIFY	0x01		/* notify on bus (de/a)ttaches 	*/
diff -Nru a/include/linux/if_shaper.h b/include/linux/if_shaper.h
--- a/include/linux/if_shaper.h	Tue Feb  5 09:39:42 2002
+++ b/include/linux/if_shaper.h	Tue Mar  4 22:44:07 2003
@@ -21,7 +21,7 @@
 	__u32 bitspersec;
 	__u32 shapelatency;
 	__u32 shapeclock;
-	__u32 recovery;		/* Time we can next clock a packet out on
+	unsigned long recovery;	/* Time we can next clock a packet out on
 				   an empty queue */
         unsigned long locked;
         struct net_device_stats stats;
diff -Nru a/include/linux/if_wanpipe.h b/include/linux/if_wanpipe.h
--- a/include/linux/if_wanpipe.h	Sun Mar 17 20:03:30 2002
+++ b/include/linux/if_wanpipe.h	Sun Feb 16 16:22:42 2003
@@ -100,13 +100,9 @@
 #define WAN_PACKET_MR_ALLMULTI	2
 
 #ifdef __KERNEL__
+
 #ifndef netdevice_t
-#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- #define netdevice_t struct net_device
-#else
- #define netdevice_t struct device
-#endif
+#define netdevice_t struct net_device
 #endif
 
 /* Private wanpipe socket structures. */
diff -Nru a/include/linux/if_wanpipe_common.h b/include/linux/if_wanpipe_common.h
--- a/include/linux/if_wanpipe_common.h	Sun Dec  8 05:42:07 2002
+++ b/include/linux/if_wanpipe_common.h	Sun Feb 16 16:22:42 2003
@@ -19,11 +19,7 @@
 
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- #define netdevice_t struct net_device
-#else
- #define netdevice_t struct device
-#endif
+#define netdevice_t struct net_device
 
 
 typedef struct {
diff -Nru a/include/linux/init.h b/include/linux/init.h
--- a/include/linux/init.h	Tue Feb 18 10:25:13 2003
+++ b/include/linux/init.h	Mon Mar  3 13:05:26 2003
@@ -62,8 +62,10 @@
  */
 typedef int (*initcall_t)(void);
 typedef void (*exitcall_t)(void);
-#endif
 
+extern initcall_t __con_initcall_start, __con_initcall_end;
+#endif
+  
 #ifndef MODULE
 
 #ifndef __ASSEMBLY__
@@ -90,6 +92,9 @@
 
 #define __exitcall(fn)							\
 	static exitcall_t __exitcall_##fn __exit_call = fn
+
+#define console_initcall(fn) \
+	static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".con_initcall.init")))=fn
 
 struct obs_kernel_param {
 	const char *str;
diff -Nru a/include/linux/ipv6.h b/include/linux/ipv6.h
--- a/include/linux/ipv6.h	Thu Oct 24 03:26:49 2002
+++ b/include/linux/ipv6.h	Wed Mar  5 15:45:36 2003
@@ -74,6 +74,21 @@
 #define rt0_type		rt_hdr.type;
 };
 
+struct ipv6_auth_hdr {
+	__u8  nexthdr;
+	__u8  hdrlen;           /* This one is measured in 32 bit units! */
+	__u16 reserved;
+	__u32 spi;
+	__u32 seq_no;           /* Sequence number */
+	__u8  auth_data[4];     /* Length variable but >=4. Mind the 64 bit alignment! */
+};
+
+struct ipv6_esp_hdr {
+	__u32 spi;
+	__u32 seq_no;           /* Sequence number */
+	__u8  enc_data[8];      /* Length variable but >=8. Mind the 64 bit alignment! */
+};
+
 /*
  *	IPv6 fixed header
  *
diff -Nru a/include/linux/jiffies.h b/include/linux/jiffies.h
--- a/include/linux/jiffies.h	Tue Feb 25 02:08:56 2003
+++ b/include/linux/jiffies.h	Wed Mar  5 21:22:52 2003
@@ -1,6 +1,7 @@
 #ifndef _LINUX_JIFFIES_H
 #define _LINUX_JIFFIES_H
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/seqlock.h>
@@ -37,10 +38,16 @@
  * good compiler would generate better code (and a really good compiler
  * wouldn't care). Gcc is currently neither.
  */
-#define time_after(a,b)		((long)(b) - (long)(a) < 0)
+#define time_after(a,b)		\
+	(typecheck(unsigned long, a) && \
+	 typecheck(unsigned long, b) && \
+	 ((long)(b) - (long)(a) < 0))
 #define time_before(a,b)	time_after(b,a)
 
-#define time_after_eq(a,b)	((long)(a) - (long)(b) >= 0)
+#define time_after_eq(a,b)	\
+	(typecheck(unsigned long, a) && \
+	 typecheck(unsigned long, b) && \
+	 ((long)(a) - (long)(b) >= 0))
 #define time_before_eq(a,b)	time_after_eq(b,a)
 
 #endif
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	Mon Nov 18 02:03:05 2002
+++ b/include/linux/kernel.h	Wed Mar  5 21:21:32 2003
@@ -188,6 +188,17 @@
         const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
         (type *)( (char *)__mptr - offsetof(type,member) );})
 
+/*
+ * Check at compile time that something is of a particular type.
+ * Always evaluates to 1 so you may use it easily in conparisons.
+ */
+#define typecheck(type,x) \
+({	type __dummy; \
+	typeof(x) __dummy2; \
+	(void)(&__dummy == &__dummy2); \
+	1; \
+})
+
 #endif /* __KERNEL__ */
 
 #define SI_LOAD_SHIFT	16
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	Tue Mar  4 05:50:39 2003
+++ b/include/linux/list.h	Sat Mar 15 09:52:23 2003
@@ -3,6 +3,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/stddef.h>
 #include <linux/prefetch.h>
 #include <asm/system.h>
 
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Mon Feb 24 23:13:11 2003
+++ b/include/linux/mm.h	Thu Mar  6 03:13:27 2003
@@ -410,8 +410,6 @@
 void clear_page_tables(struct mmu_gather *tlb, unsigned long first, int nr);
 int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
 			struct vm_area_struct *vma);
-int remap_page_range(struct vm_area_struct *vma, unsigned long from,
-			unsigned long to, unsigned long size, pgprot_t prot);
 int zeromap_page_range(struct vm_area_struct *vma, unsigned long from,
 			unsigned long size, pgprot_t prot);
 
@@ -426,7 +424,6 @@
 extern int sys_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long nonblock);
 
 
-extern struct page * follow_page(struct mm_struct *mm, unsigned long address, int write);
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
 		int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
 
@@ -539,10 +536,11 @@
 static inline int
 can_vma_merge(struct vm_area_struct *vma, unsigned long vm_flags)
 {
+#ifdef CONFIG_MMU
 	if (!vma->vm_file && vma->vm_flags == vm_flags)
 		return 1;
-	else
-		return 0;
+#endif
+	return 0;
 }
 
 /* filemap.c */
@@ -558,6 +556,7 @@
 /* readahead.c */
 #define VM_MAX_READAHEAD	128	/* kbytes */
 #define VM_MIN_READAHEAD	16	/* kbytes (includes current page) */
+
 int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
 			unsigned long offset, unsigned long nr_to_read);
 void page_cache_readahead(struct address_space *mapping, 
@@ -569,7 +568,7 @@
 			   struct file *filp,
 			   unsigned long offset);
 void handle_ra_miss(struct address_space *mapping, 
-		    struct file_ra_state *ra);
+		    struct file_ra_state *ra, pgoff_t offset);
 unsigned long max_sane_readahead(unsigned long nr);
 
 /* Do stack extension */
@@ -595,10 +594,31 @@
 
 extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr);
 
-extern struct page * vmalloc_to_page(void *addr);
 extern unsigned long get_page_cache_size(void);
 extern unsigned int nr_used_zone_pages(void);
 
+#ifdef CONFIG_MMU
+extern struct page * vmalloc_to_page(void *addr);
+extern struct page * follow_page(struct mm_struct *mm, unsigned long address,
+		int write);
+extern int remap_page_range(struct vm_area_struct *vma, unsigned long from,
+		unsigned long to, unsigned long size, pgprot_t prot);
+#else
+static inline struct page * vmalloc_to_page(void *addr)
+{
+	return NULL;
+}
+static inline struct page * follow_page(struct mm_struct *mm,
+		unsigned long address, int write)
+{
+	return NULL;
+}
+static inline int remap_page_range(struct vm_area_struct *vma,
+		unsigned long from, unsigned long to,
+		unsigned long size, pgprot_t prot)
+{
+	return -EPERM;
+}
+#endif /* CONFIG_MMU */
 #endif /* __KERNEL__ */
-
-#endif
+#endif /* _LINUX_MM_H */
diff -Nru a/include/linux/net.h b/include/linux/net.h
--- a/include/linux/net.h	Wed Feb 26 12:14:05 2003
+++ b/include/linux/net.h	Thu Mar  6 11:06:44 2003
@@ -78,7 +78,6 @@
 	unsigned char		passcred;
 };
 
-struct scm_cookie;
 struct vm_area_struct;
 struct page;
 struct kiocb;
@@ -106,11 +105,9 @@
   int	(*getsockopt)	(struct socket *sock, int level, int optname,
 			 char *optval, int *optlen);
   int   (*sendmsg)	(struct kiocb *iocb, struct socket *sock,
-			 struct msghdr *m, int total_len,
-			 struct scm_cookie *scm);
+			 struct msghdr *m, int total_len);
   int   (*recvmsg)	(struct kiocb *iocb, struct socket *sock,
-			 struct msghdr *m, int total_len, int flags,
-			 struct scm_cookie *scm);
+			 struct msghdr *m, int total_len, int flags);
   int	(*mmap)		(struct file *file, struct socket *sock, struct vm_area_struct * vma);
   ssize_t (*sendpage)	(struct socket *sock, struct page *page, int offset, size_t size, int flags);
 };
@@ -202,10 +199,10 @@
 			 char *optval, int optlen), (sock, level, optname, optval, optlen)) \
 SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \
 			 char *optval, int *optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, struct scm_cookie *scm), \
-	      (iocb, sock, m, len, scm)) \
-SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags, struct scm_cookie *scm), \
-	      (iocb, sock, m, len, flags, scm)) \
+SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len), \
+	      (iocb, sock, m, len)) \
+SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags), \
+	      (iocb, sock, m, len, flags)) \
 SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \
 	      (file, sock, vma)) \
 	      \
diff -Nru a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h
--- a/include/linux/netfilter_bridge/ebt_ip.h	Mon Oct 28 04:58:32 2002
+++ b/include/linux/netfilter_bridge/ebt_ip.h	Mon Mar  3 04:41:09 2003
@@ -25,7 +25,7 @@
  EBT_IP_SPORT | EBT_IP_DPORT )
 #define EBT_IP_MATCH "ip"
 
-// the same values are used for the invflags
+/* the same values are used for the invflags */
 struct ebt_ip_info
 {
 	uint32_t saddr;
diff -Nru a/include/linux/netfilter_bridge/ebt_log.h b/include/linux/netfilter_bridge/ebt_log.h
--- a/include/linux/netfilter_bridge/ebt_log.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_log.h	Mon Mar  3 04:41:09 2003
@@ -1,7 +1,7 @@
 #ifndef __LINUX_BRIDGE_EBT_LOG_H
 #define __LINUX_BRIDGE_EBT_LOG_H
 
-#define EBT_LOG_IP 0x01 // if the frame is made by ip, log the ip information
+#define EBT_LOG_IP 0x01 /* if the frame is made by ip, log the ip information */
 #define EBT_LOG_ARP 0x02
 #define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP)
 #define EBT_LOG_PREFIX_SIZE 30
diff -Nru a/include/linux/netfilter_bridge/ebt_mark_t.h b/include/linux/netfilter_bridge/ebt_mark_t.h
--- a/include/linux/netfilter_bridge/ebt_mark_t.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_mark_t.h	Mon Mar  3 04:41:09 2003
@@ -4,7 +4,7 @@
 struct ebt_mark_t_info
 {
 	unsigned long mark;
-	// EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN
+	/* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */
 	int target;
 };
 #define EBT_MARK_TARGET "mark"
diff -Nru a/include/linux/netfilter_bridge/ebt_nat.h b/include/linux/netfilter_bridge/ebt_nat.h
--- a/include/linux/netfilter_bridge/ebt_nat.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_nat.h	Mon Mar  3 04:41:09 2003
@@ -4,7 +4,7 @@
 struct ebt_nat_info
 {
 	unsigned char mac[ETH_ALEN];
-	// EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN
+	/* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */
 	int target;
 };
 #define EBT_SNAT_TARGET "snat"
diff -Nru a/include/linux/netfilter_bridge/ebt_redirect.h b/include/linux/netfilter_bridge/ebt_redirect.h
--- a/include/linux/netfilter_bridge/ebt_redirect.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_redirect.h	Mon Mar  3 04:41:09 2003
@@ -3,7 +3,7 @@
 
 struct ebt_redirect_info
 {
-	// EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN
+	/* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */
 	int target;
 };
 #define EBT_REDIRECT_TARGET "redirect"
diff -Nru a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
--- a/include/linux/netfilter_bridge/ebtables.h	Mon Oct 28 05:00:13 2002
+++ b/include/linux/netfilter_bridge/ebtables.h	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtables
  *
  *	Authors:
- *	Bart De Schuymer		<bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer		<bdschuym@pandora.be>
  *
  *  ebtables.c,v 2.0, April, 2002
  *
@@ -20,7 +20,7 @@
 #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
 #define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
 
-// verdicts >0 are "branches"
+/* verdicts >0 are "branches" */
 #define EBT_ACCEPT   -1
 #define EBT_DROP     -2
 #define EBT_CONTINUE -3
@@ -34,33 +34,34 @@
 };
 
 struct ebt_entries {
-	// this field is always set to zero
-	// See EBT_ENTRY_OR_ENTRIES.
-	// Must be same size as ebt_entry.bitmask
+	/* this field is always set to zero
+	 * See EBT_ENTRY_OR_ENTRIES.
+	 * Must be same size as ebt_entry.bitmask */
 	unsigned int distinguisher;
-	// the chain name
+	/* the chain name */
 	char name[EBT_CHAIN_MAXNAMELEN];
-	// counter offset for this chain
+	/* counter offset for this chain */
 	unsigned int counter_offset;
-	// one standard (accept, drop, return) per hook
+	/* one standard (accept, drop, return) per hook */
 	int policy;
-	// nr. of entries
+	/* nr. of entries */
 	unsigned int nentries;
-	// entry list
+	/* entry list */
 	char data[0];
 };
 
-// used for the bitmask of struct ebt_entry
+/* used for the bitmask of struct ebt_entry */
 
-// This is a hack to make a difference between an ebt_entry struct and an
-// ebt_entries struct when traversing the entries from start to end.
-// Using this simplifies the code alot, while still being able to use
-// ebt_entries.
-// Contrary, iptables doesn't use something like ebt_entries and therefore uses
-// different techniques for naming the policy and such. So, iptables doesn't
-// need a hack like this.
+/* This is a hack to make a difference between an ebt_entry struct and an
+ * ebt_entries struct when traversing the entries from start to end.
+ * Using this simplifies the code alot, while still being able to use
+ * ebt_entries.
+ * Contrary, iptables doesn't use something like ebt_entries and therefore uses
+ * different techniques for naming the policy and such. So, iptables doesn't
+ * need a hack like this.
+ */
 #define EBT_ENTRY_OR_ENTRIES 0x01
-// these are the normal masks
+/* these are the normal masks */
 #define EBT_NOPROTO 0x02
 #define EBT_802_3 0x04
 #define EBT_SOURCEMAC 0x08
@@ -84,7 +85,7 @@
 		char name[EBT_FUNCTION_MAXNAMELEN];
 		struct ebt_match *match;
 	} u;
-	// size of data
+	/* size of data */
 	unsigned int match_size;
 	unsigned char data[0];
 };
@@ -95,7 +96,7 @@
 		char name[EBT_FUNCTION_MAXNAMELEN];
 		struct ebt_watcher *watcher;
 	} u;
-	// size of data
+	/* size of data */
 	unsigned int watcher_size;
 	unsigned char data[0];
 };
@@ -106,7 +107,7 @@
 		char name[EBT_FUNCTION_MAXNAMELEN];
 		struct ebt_target *target;
 	} u;
-	// size of data
+	/* size of data */
 	unsigned int target_size;
 	unsigned char data[0];
 };
@@ -118,29 +119,29 @@
 	int verdict;
 };
 
-// one entry
+/* one entry */
 struct ebt_entry {
-	// this needs to be the first field
+	/* this needs to be the first field */
 	unsigned int bitmask;
 	unsigned int invflags;
 	uint16_t ethproto;
-	// the physical in-dev
+	/* the physical in-dev */
 	char in[IFNAMSIZ];
-	// the logical in-dev
+	/* the logical in-dev */
 	char logical_in[IFNAMSIZ];
-	// the physical out-dev
+	/* the physical out-dev */
 	char out[IFNAMSIZ];
-	// the logical out-dev
+	/* the logical out-dev */
 	char logical_out[IFNAMSIZ];
 	unsigned char sourcemac[ETH_ALEN];
 	unsigned char sourcemsk[ETH_ALEN];
 	unsigned char destmac[ETH_ALEN];
 	unsigned char destmsk[ETH_ALEN];
-	// sizeof ebt_entry + matches
+	/* sizeof ebt_entry + matches */
 	unsigned int watchers_offset;
-	// sizeof ebt_entry + matches + watchers
+	/* sizeof ebt_entry + matches + watchers */
 	unsigned int target_offset;
-	// sizeof ebt_entry + matches + watchers + target
+	/* sizeof ebt_entry + matches + watchers + target */
 	unsigned int next_offset;
 	unsigned char elems[0];
 };
@@ -149,20 +150,20 @@
 {
 	char name[EBT_TABLE_MAXNAMELEN];
 	unsigned int valid_hooks;
-	// nr of rules in the table
+	/* nr of rules in the table */
 	unsigned int nentries;
-	// total size of the entries
+	/* total size of the entries */
 	unsigned int entries_size;
-	// start of the chains
+	/* start of the chains */
 	struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
-	// nr of counters userspace expects back
+	/* nr of counters userspace expects back */
 	unsigned int num_counters;
-	// where the kernel will put the old counters
+	/* where the kernel will put the old counters */
 	struct ebt_counter *counters;
 	char *entries;
 };
 
-// [gs]etsockopt numbers
+/* {g,s}etsockopt numbers */
 #define EBT_BASE_CTL            128
 
 #define EBT_SO_SET_ENTRIES      (EBT_BASE_CTL)
@@ -177,7 +178,7 @@
 
 #ifdef __KERNEL__
 
-// return values for match() functions
+/* return values for match() functions */
 #define EBT_MATCH 0
 #define EBT_NOMATCH 1
 
@@ -185,11 +186,11 @@
 {
 	struct list_head list;
 	const char name[EBT_FUNCTION_MAXNAMELEN];
-	// 0 == it matches
+	/* 0 == it matches */
 	int (*match)(const struct sk_buff *skb, const struct net_device *in,
 	   const struct net_device *out, const void *matchdata,
 	   unsigned int datalen);
-	// 0 == let it in
+	/* 0 == let it in */
 	int (*check)(const char *tablename, unsigned int hookmask,
 	   const struct ebt_entry *e, void *matchdata, unsigned int datalen);
 	void (*destroy)(void *matchdata, unsigned int datalen);
@@ -203,7 +204,7 @@
 	void (*watcher)(const struct sk_buff *skb, const struct net_device *in,
 	   const struct net_device *out, const void *watcherdata,
 	   unsigned int datalen);
-	// 0 == let it in
+	/* 0 == let it in */
 	int (*check)(const char *tablename, unsigned int hookmask,
 	   const struct ebt_entry *e, void *watcherdata, unsigned int datalen);
 	void (*destroy)(void *watcherdata, unsigned int datalen);
@@ -214,33 +215,33 @@
 {
 	struct list_head list;
 	const char name[EBT_FUNCTION_MAXNAMELEN];
-	// returns one of the standard verdicts
+	/* returns one of the standard verdicts */
 	int (*target)(struct sk_buff **pskb, unsigned int hooknr,
 	   const struct net_device *in, const struct net_device *out,
 	   const void *targetdata, unsigned int datalen);
-	// 0 == let it in
+	/* 0 == let it in */
 	int (*check)(const char *tablename, unsigned int hookmask,
 	   const struct ebt_entry *e, void *targetdata, unsigned int datalen);
 	void (*destroy)(void *targetdata, unsigned int datalen);
 	struct module *me;
 };
 
-// used for jumping from and into user defined chains (udc)
+/* used for jumping from and into user defined chains (udc) */
 struct ebt_chainstack
 {
-	struct ebt_entries *chaininfo; // pointer to chain data
-	struct ebt_entry *e; // pointer to entry data
-	unsigned int n; // n'th entry
+	struct ebt_entries *chaininfo; /* pointer to chain data */
+	struct ebt_entry *e; /* pointer to entry data */
+	unsigned int n; /* n'th entry */
 };
 
 struct ebt_table_info
 {
-	// total size of the entries
+	/* total size of the entries */
 	unsigned int entries_size;
 	unsigned int nentries;
-	// pointers to the start of the chains
+	/* pointers to the start of the chains */
 	struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
-	// room to maintain the stack used for jumping from and into udc
+	/* room to maintain the stack used for jumping from and into udc */
 	struct ebt_chainstack **chainstack;
 	char *entries;
 	struct ebt_counter counters[0] ____cacheline_aligned;
@@ -253,11 +254,11 @@
 	struct ebt_replace *table;
 	unsigned int valid_hooks;
 	rwlock_t lock;
-	// e.g. could be the table explicitly only allows certain
-	// matches, targets, ... 0 == let it in
+	/* e.g. could be the table explicitly only allows certain
+	 * matches, targets, ... 0 == let it in */
 	int (*check)(const struct ebt_table_info *info,
 	   unsigned int valid_hooks);
-	// the data used by the kernel
+	/* the data used by the kernel */
 	struct ebt_table_info *private;
 };
 
@@ -273,20 +274,20 @@
    const struct net_device *in, const struct net_device *out,
    struct ebt_table *table);
 
-   // Used in the kernel match() functions
+/* Used in the kernel match() functions */
 #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))
-// True if the hook mask denotes that the rule is in a base chain,
-// used in the check() functions
+/* True if the hook mask denotes that the rule is in a base chain,
+ * used in the check() functions */
 #define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS))
-// Clear the bit in the hook mask that tells if the rule is on a base chain
+/* Clear the bit in the hook mask that tells if the rule is on a base chain */
 #define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS))
-// True if the target is not a standard target
+/* True if the target is not a standard target */
 #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
 
 #endif /* __KERNEL__ */
 
-// blatently stolen from ip_tables.h
-// fn returns 0 to continue iteration
+/* blatently stolen from ip_tables.h
+ * fn returns 0 to continue iteration */
 #define EBT_MATCH_ITERATE(e, fn, args...)                   \
 ({                                                          \
 	unsigned int __i;                                   \
diff -Nru a/include/linux/netfilter_ipv4/ipchains_core.h b/include/linux/netfilter_ipv4/ipchains_core.h
--- a/include/linux/netfilter_ipv4/ipchains_core.h	Tue Feb  5 09:39:43 2002
+++ b/include/linux/netfilter_ipv4/ipchains_core.h	Sat Mar  8 11:30:11 2003
@@ -178,12 +178,8 @@
 
 #include <linux/config.h>
 #include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
 #include <linux/init.h>
 extern void ip_fw_init(void) __init;
-#else /* 2.0.x */
-extern void ip_fw_init(void);
-#endif /* 2.1.x */
 extern int ip_fw_ctl(int, void *, int);
 #ifdef CONFIG_IP_MASQUERADE
 extern int ip_masq_uctl(int, char *, int);
diff -Nru a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
--- a/include/linux/nfsd/export.h	Wed Oct 30 14:40:03 2002
+++ b/include/linux/nfsd/export.h	Tue Mar 11 20:07:11 2003
@@ -35,12 +35,13 @@
 #define NFSEXP_UIDMAP		0x0040
 #define NFSEXP_KERBEROS		0x0080		/* not available */
 #define NFSEXP_SUNSECURE	0x0100
-#define NFSEXP_CROSSMNT		0x0200
+#define NFSEXP_NOHIDE		0x0200
 #define NFSEXP_NOSUBTREECHECK	0x0400
 #define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
 #define NFSEXP_MSNFS		0x1000	/* do silly things that MS clients expect */
 #define NFSEXP_FSID		0x2000
-#define NFSEXP_ALLFLAGS		0x3FFF
+#define	NFSEXP_CROSSMNT		0x4000
+#define NFSEXP_ALLFLAGS		0x7FFF
 
 
 #ifdef __KERNEL__
@@ -73,7 +74,7 @@
 #define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
 #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
 #define EX_RDONLY(exp)		((exp)->ex_flags & NFSEXP_READONLY)
-#define EX_CROSSMNT(exp)	((exp)->ex_flags & NFSEXP_CROSSMNT)
+#define EX_NOHIDE(exp)	((exp)->ex_flags & NFSEXP_NOHIDE)
 #define EX_SUNSECURE(exp)	((exp)->ex_flags & NFSEXP_SUNSECURE)
 #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
 
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Mon Feb 24 08:17:50 2003
+++ b/include/linux/pci.h	Sun Mar 16 14:16:33 2003
@@ -413,6 +413,7 @@
 
 	/* These fields are used by common fixups */
 	unsigned int	transparent:1;	/* Transparent PCI bridge */
+	unsigned int	multifunction:1;/* Part of multi-function device */
 };
 
 #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
@@ -484,11 +485,9 @@
 	int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
 };
 
-struct pbus_set_ranges_data
-{
-	unsigned long io_start, io_end;
-	unsigned long mem_start, mem_end;
-	unsigned long prefetch_start, prefetch_end;
+struct pci_bus_region {
+	unsigned long start;
+	unsigned long end;
 };
 
 struct pci_driver {
@@ -530,10 +529,7 @@
 /* Used only when drivers/pci/setup.c is used */
 void pcibios_align_resource(void *, struct resource *,
 			    unsigned long, unsigned long);
-void pcibios_update_resource(struct pci_dev *, struct resource *,
-			     struct resource *, int);
 void pcibios_update_irq(struct pci_dev *, int irq);
-void pcibios_fixup_pbus_ranges(struct pci_bus *, struct pbus_set_ranges_data *);
 
 /* Generic PCI functions used internally */
 
@@ -548,7 +544,8 @@
 {
 	return pci_alloc_primary_bus_parented(NULL, bus);
 }
-struct pci_dev *pci_scan_slot(struct pci_dev *temp);
+int pci_scan_slot(struct pci_bus *bus, int devfn);
+void pci_bus_add_devices(struct pci_bus *bus);
 int pci_proc_attach_device(struct pci_dev *dev);
 int pci_proc_detach_device(struct pci_dev *dev);
 int pci_proc_attach_bus(struct pci_bus *bus);
@@ -641,6 +638,16 @@
 int pci_request_region(struct pci_dev *, int, char *);
 void pci_release_region(struct pci_dev *, int);
 
+/* drivers/pci/bus.c */
+
+int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+			   unsigned long size, unsigned long align,
+			   unsigned long min, unsigned int type_mask,
+			   void (*alignf)(void *, struct resource *,
+					  unsigned long, unsigned long),
+			   void *alignf_data);
+void pci_enable_bridges(struct pci_bus *bus);
+
 /* New-style probing supporting hot-pluggable devices */
 int pci_register_driver(struct pci_driver *);
 void pci_unregister_driver(struct pci_driver *);
@@ -844,7 +851,7 @@
 #define PCIPCI_NATOMA		4
 #define PCIPCI_VIAETBF		8
 #define PCIPCI_VSFX		16
-
+#define PCIPCI_ALIMAGIK		32
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Thu Feb 27 13:23:56 2003
+++ b/include/linux/pci_ids.h	Sat Mar 15 17:15:06 2003
@@ -1235,6 +1235,7 @@
 
 #define PCI_VENDOR_ID_XIRCOM		0x115d
 #define PCI_DEVICE_ID_XIRCOM_X3201_ETH	0x0003
+#define PCI_DEVICE_ID_XIRCOM_RBM56G	0x0101
 #define PCI_DEVICE_ID_XIRCOM_X3201_MDM	0x0103
 
 #define PCI_VENDOR_ID_RENDITION		0x1163
@@ -1854,6 +1855,7 @@
 #define PCI_DEVICE_ID_INTEL_82801DB_7	0x24c7
 #define PCI_DEVICE_ID_INTEL_82801DB_9	0x24cb
 #define PCI_DEVICE_ID_INTEL_82801DB_11	PCI_DEVICE_ID_INTEL_82801DB_9
+#define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
 #define PCI_DEVICE_ID_INTEL_82801DB_13	0x24cd
 #define PCI_DEVICE_ID_INTEL_82820_HB	0x2500
 #define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
diff -Nru a/include/linux/pnp.h b/include/linux/pnp.h
--- a/include/linux/pnp.h	Fri Feb 21 15:46:20 2003
+++ b/include/linux/pnp.h	Mon Mar 10 22:34:19 2003
@@ -138,11 +138,8 @@
 	struct list_head global_list;	/* node in global list of cards */
 	struct list_head protocol_list;	/* node in protocol's list of cards */
 	struct list_head devices;	/* devices attached to the card */
-	struct list_head rdevs;		/* a list of devices requested by the card driver */
-	int status;
 
 	struct pnp_protocol * protocol;
-	struct pnpc_driver * driver;
 	struct pnp_id * id;		/* contains supported EISA IDs*/
 
 	void	      * protocol_data;	/* Used to store protocol specific data */
@@ -161,24 +158,30 @@
 	(card) != global_to_pnp_card(&pnp_cards); \
 	(card) = global_to_pnp_card((card)->global_list.next))
 
-static inline void *pnpc_get_drvdata (struct pnp_card *pcard)
+static inline void *pnp_get_card_protodata (struct pnp_card *pcard)
 {
-	return dev_get_drvdata(&pcard->dev);
+	return pcard->protocol_data;
 }
 
-static inline void pnpc_set_drvdata (struct pnp_card *pcard, void *data)
+static inline void pnp_set_card_protodata (struct pnp_card *pcard, void *data)
 {
-	dev_set_drvdata(&pcard->dev, data);
+	pcard->protocol_data = data;
 }
 
-static inline void *pnpc_get_protodata (struct pnp_card *pcard)
+struct pnp_card_link {
+	struct pnp_card * card;
+	struct pnp_card_driver * driver;
+	void * driver_data;
+};
+
+static inline void *pnp_get_card_drvdata (struct pnp_card_link *pcard)
 {
-	return pcard->protocol_data;
+	return pcard->driver_data;
 }
 
-static inline void pnpc_set_protodata (struct pnp_card *pcard, void *data)
+static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data)
 {
-	pcard->protocol_data = data;
+	pcard->driver_data = data;
 }
 
 struct pnp_dev {
@@ -196,6 +199,7 @@
 	struct pnp_protocol * protocol;
 	struct pnp_card * card;		/* card the device is attached to, none if NULL */
 	struct pnp_driver * driver;
+	struct pnp_card_link * card_link;
 
 	struct pnp_id		      * id;		/* supported EISA IDs*/
 	struct pnp_resource_table	res;		/* contains the currently chosen resources */
@@ -299,11 +303,8 @@
 	} devs[PNP_MAX_DEVICES];	/* logical devices */
 };
 
-#define PNP_DRIVER_DO_NOT_ACTIVATE	(1<<0)
-
 struct pnp_driver {
-	struct list_head node;
-	char *name;
+	char * name;
 	const struct pnp_device_id *id_table;
 	unsigned int flags;
 	int  (*probe)  (struct pnp_dev *dev, const struct pnp_device_id *dev_id);
@@ -311,21 +312,22 @@
 	struct device_driver driver;
 };
 
-#define	to_pnp_driver(drv) container_of(drv,struct pnp_driver, driver)
-
-#define PNPC_DRIVER_DO_NOT_ACTIVATE	(1<<0)
+#define	to_pnp_driver(drv) container_of(drv, struct pnp_driver, driver)
 
-struct pnpc_driver {
-	struct list_head node;
-	char *name;
+struct pnp_card_driver {
+	char * name;
 	const struct pnp_card_id *id_table;
 	unsigned int flags;
-	int  (*probe)  (struct pnp_card *card, const struct pnp_card_id *card_id);
-	void (*remove) (struct pnp_card *card);
-	struct device_driver driver;
+	int  (*probe)  (struct pnp_card_link *card, const struct pnp_card_id *card_id);
+	void (*remove) (struct pnp_card_link *card);
+	struct pnp_driver link;
 };
 
-#define	to_pnpc_driver(drv) container_of(drv,struct pnpc_driver, driver)
+#define	to_pnp_card_driver(drv) container_of(drv, struct pnp_card_driver, link)
+
+/* pnp driver flags */
+#define PNP_DRIVER_RES_DO_NOT_CHANGE	0x0001	/* do not change the state of the device */
+#define PNP_DRIVER_RES_DISABLE		0x0003	/* ensure the device is disabled */
 
 
 /*
@@ -366,9 +368,21 @@
 void pnp_unregister_protocol(struct pnp_protocol *protocol);
 int pnp_add_device(struct pnp_dev *dev);
 void pnp_remove_device(struct pnp_dev *dev);
-extern struct list_head pnp_global;
 int pnp_device_attach(struct pnp_dev *pnp_dev);
 void pnp_device_detach(struct pnp_dev *pnp_dev);
+extern struct list_head pnp_global;
+
+/* card */
+int pnp_add_card(struct pnp_card *card);
+void pnp_remove_card(struct pnp_card *card);
+int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
+void pnp_remove_card_device(struct pnp_dev *dev);
+int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card);
+struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from);
+void pnp_release_card_device(struct pnp_dev * dev);
+int pnp_register_card_driver(struct pnp_card_driver * drv);
+void pnp_unregister_card_driver(struct pnp_card_driver * drv);
+extern struct list_head pnp_cards;
 
 /* resource */
 struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent);
@@ -413,6 +427,17 @@
 static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
 static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
 
+/* card */
+static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; }
+static inline void pnp_remove_card(struct pnp_card *card) { ; }
+static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
+static inline void pnp_remove_card_device(struct pnp_dev *dev) { ; }
+static inline int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
+static inline struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) { return NULL; }
+static inline void pnp_release_card_device(struct pnp_dev * dev) { ; }
+static inline int pnp_register_card_driver(struct pnp_card_driver * drv) { return -ENODEV; }
+static inline void pnp_unregister_card_driver(struct pnp_card_driver * drv) { ; }
+
 /* resource */
 static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; }
 static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; }
@@ -445,37 +470,6 @@
 
 #endif /* CONFIG_PNP */
 
-
-#if defined(CONFIG_PNP_CARD)
-
-/* card */
-int pnpc_add_card(struct pnp_card *card);
-void pnpc_remove_card(struct pnp_card *card);
-int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev);
-void pnpc_remove_device(struct pnp_dev *dev);
-struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from);
-void pnp_release_card_device(struct pnp_dev *dev);
-int pnpc_register_driver(struct pnpc_driver * drv);
-void pnpc_unregister_driver(struct pnpc_driver *drv);
-int pnpc_add_id(struct pnp_id *id, struct pnp_card *card);
-extern struct list_head pnp_cards;
-int pnpc_attach(struct pnp_card *card);
-void pnpc_detach(struct pnp_card *card);
-
-#else
-
-/* card */
-static inline int pnpc_add_card(struct pnp_card *card) { return -ENODEV; }
-static inline void pnpc_remove_card(struct pnp_card *card) { ; }
-static inline int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
-static inline void pnpc_remove_device(struct pnp_dev *dev) { ; }
-static inline struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) { return NULL; }
-static inline void pnp_release_card_device(struct pnp_dev *dev) { ; }
-static inline int pnpc_register_driver(struct pnpc_driver *drv) { return -ENODEV; }
-static inline void pnpc_unregister_driver(struct pnpc_driver *drv) { ; }
-static inline int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
-
-#endif /* CONFIG_PNP_CARD */
 
 #define pnp_err(format, arg...) printk(KERN_ERR "pnp: " format "\n" , ## arg)
 #define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg)
diff -Nru a/include/linux/profile.h b/include/linux/profile.h
--- a/include/linux/profile.h	Tue Feb 18 18:59:01 2003
+++ b/include/linux/profile.h	Wed Feb 26 18:41:10 2003
@@ -2,15 +2,15 @@
 #define _LINUX_PROFILE_H
 
 #ifdef __KERNEL__
- 
+
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/errno.h>
- 
+
 /* parse command line */
 int __init profile_setup(char * str);
- 
+
 /* init basic kernel profiler */
 void __init profile_init(void);
 
@@ -27,14 +27,14 @@
 };
 
 #ifdef CONFIG_PROFILING
- 
+
 struct notifier_block;
 struct task_struct;
 struct mm_struct;
- 
+
 /* task is in do_exit() */
 void profile_exit_task(struct task_struct * task);
- 
+
 /* change of vma mappings */
 void profile_exec_unmap(struct mm_struct * mm);
 
@@ -44,10 +44,10 @@
 int profile_event_register(enum profile_type, struct notifier_block * n);
 
 int profile_event_unregister(enum profile_type, struct notifier_block * n);
- 
+
 int register_profile_notifier(struct notifier_block * nb);
 int unregister_profile_notifier(struct notifier_block * nb);
- 
+
 /* profiling hook activated on each timer interrupt */
 void profile_hook(struct pt_regs * regs);
 
@@ -57,12 +57,12 @@
 {
 	return -ENOSYS;
 }
- 
+
 static inline int profile_event_unregister(enum profile_type t, struct notifier_block * n)
 {
 	return -ENOSYS;
 }
- 
+
 #define profile_exit_task(a) do { } while (0)
 #define profile_exec_unmap(a) do { } while (0)
 #define profile_exit_mmap(a) do { } while (0)
@@ -80,7 +80,7 @@
 #define profile_hook(regs) do { } while (0)
 
 #endif /* CONFIG_PROFILING */
- 
+
 #endif /* __KERNEL__ */
- 
+
 #endif /* _LINUX_PROFILE_H */
diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h
--- a/include/linux/raid/md.h	Mon Feb 17 14:07:44 2003
+++ b/include/linux/raid/md.h	Tue Mar 11 18:15:04 2003
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/hdreg.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <net/checksum.h>
@@ -68,13 +69,14 @@
 }
 extern int register_md_personality (int p_num, mdk_personality_t *p);
 extern int unregister_md_personality (int p_num);
-extern mdk_thread_t * md_register_thread (void (*run) (void *data),
-				void *data, const char *name);
+extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
+				mddev_t *mddev, const char *name);
 extern void md_unregister_thread (mdk_thread_t *thread);
 extern void md_wakeup_thread(mdk_thread_t *thread);
+extern void md_check_recovery(mddev_t *mddev);
 extern void md_interrupt_thread (mdk_thread_t *thread);
 extern void md_write_start(mddev_t *mddev);
-extern void md_write_end(mddev_t *mddev, mdk_thread_t *thread);
+extern void md_write_end(mddev_t *mddev);
 extern void md_handle_safemode(mddev_t *mddev);
 extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
 extern void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors);
diff -Nru a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
--- a/include/linux/raid/md_k.h	Mon Feb 17 14:07:44 2003
+++ b/include/linux/raid/md_k.h	Tue Mar 11 18:46:36 2003
@@ -155,6 +155,7 @@
 
 	struct page	*sb_page;
 	int		sb_loaded;
+	sector_t	data_offset;	/* start of data in array */
 	sector_t	sb_offset;
 	int		preferred_minor;	/* autorun support */
 
@@ -206,22 +207,31 @@
 
 	char				uuid[16];
 
+	struct mdk_thread_s		*thread;	/* management thread */
 	struct mdk_thread_s		*sync_thread;	/* doing resync or reconstruct */
 	unsigned long			curr_resync;	/* blocks scheduled */
 	unsigned long			resync_mark;	/* a recent timestamp */
 	unsigned long			resync_mark_cnt;/* blocks written at resync_mark */
-	/* recovery_running is 0 for no recovery/resync,
-	 * 1 for active recovery
-	 * 2 for active resync
-	 * -error for an error (e.g. -EINTR)
-	 * it can only be set > 0 under reconfig_sem
+
+	/* recovery/resync flags 
+	 * NEEDED:   we might need to start a resync/recover
+	 * RUNNING:  a thread is running, or about to be started
+	 * SYNC:     actually doing a resync, not a recovery
+	 * ERR:      and IO error was detected - abort the resync/recovery
+	 * INTR:     someone requested a (clean) early abort.
+	 * DONE:     thread is done and is waiting to be reaped
 	 */
-	int				recovery_running;
-	int				recovery_error;	/* error from recovery write */
+#define	MD_RECOVERY_RUNNING	0
+#define	MD_RECOVERY_SYNC	1
+#define	MD_RECOVERY_ERR		2
+#define	MD_RECOVERY_INTR	3
+#define	MD_RECOVERY_DONE	4
+#define	MD_RECOVERY_NEEDED	5
+	unsigned long			recovery;
+
 	int				in_sync;	/* know to not need resync */
 	struct semaphore		reconfig_sem;
 	atomic_t			active;
-	int				spares;
 
 	int				degraded;	/* whether md should consider
 							 * adding a spare
@@ -230,9 +240,11 @@
 	atomic_t			recovery_active; /* blocks scheduled, but not written */
 	wait_queue_head_t		recovery_wait;
 	sector_t			recovery_cp;
-	int				safemode;	/* if set, update "clean" superblock
+	unsigned int			safemode;	/* if set, update "clean" superblock
 							 * when no writes pending.
 							 */ 
+	unsigned int			safemode_delay;
+	struct timer_list		safemode_timer;
 	atomic_t			writes_pending; 
 	request_queue_t			queue;	/* for plugging ... */
 
@@ -245,7 +257,7 @@
 	int (*make_request)(request_queue_t *q, struct bio *bio);
 	int (*run)(mddev_t *mddev);
 	int (*stop)(mddev_t *mddev);
-	int (*status)(char *page, mddev_t *mddev);
+	void (*status)(struct seq_file *seq, mddev_t *mddev);
 	/* error_handler must set ->faulty and clear ->in_sync
 	 * if appropriate, and should abort recovery if needed 
 	 */
@@ -292,8 +304,8 @@
 	ITERATE_RDEV_GENERIC(pending_raid_disks,rdev,tmp)
 
 typedef struct mdk_thread_s {
-	void			(*run) (void *data);
-	void			*data;
+	void			(*run) (mddev_t *mddev);
+	mddev_t			*mddev;
 	wait_queue_head_t	wqueue;
 	unsigned long           flags;
 	struct completion	*event;
diff -Nru a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
--- a/include/linux/raid/md_p.h	Sun Jan  5 16:12:35 2003
+++ b/include/linux/raid/md_p.h	Tue Mar 11 18:46:39 2003
@@ -173,5 +173,58 @@
 	return (ev<<32)| sb->events_lo;
 }
 
+/*
+ * The version-1 superblock :
+ * All numeric fields are little-endian.
+ *
+ * total size: 256 bytes plus 2 per device.
+ *  1K allows 384 devices.
+ */
+struct mdp_superblock_1 {
+	/* constant array information - 128 bytes */
+	__u32	magic;		/* MD_SB_MAGIC: 0xa92b4efc - little endian */
+	__u32	major_version;	/* 1 */
+	__u32	feature_map;	/* 0 for now */
+	__u32	pad0;		/* always set to 0 when writing */
+
+	__u8	set_uuid[16];	/* user-space generated. */
+	char	set_name[32];	/* set and interpreted by user-space */
+
+	__u64	ctime;		/* lo 40 bits are seconds, top 24 are microseconds or 0*/
+	__u32	level;		/* -4 (multipath), -1 (linear), 0,1,4,5 */
+	__u32	layout;		/* only for raid5 currently */
+	__u64	size;		/* used size of component devices, in 512byte sectors */
+
+	__u32	chunksize;	/* in 512byte sectors */
+	__u32	raid_disks;
+	__u8	pad1[128-92];	/* set to 0 when written */
+
+	/* constant this-device information - 64 bytes */
+	__u64	data_offset;	/* sector start of data, often 0 */
+	__u64	data_size;	/* sectors in this device that can be used for data */
+	__u64	super_offset;	/* sector start of this superblock */
+	__u64	recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
+	__u32	dev_number;	/* permanent identifier of this  device - not role in raid */
+	__u32	cnt_corrected_read; /* number of read errors that were corrected by re-writing */
+	__u8	device_uuid[16]; /* user-space setable, ignored by kernel */
+	__u8	pad2[64-56];	/* set to 0 when writing */
+
+	/* array state information - 64 bytes */
+	__u64	utime;		/* 40 bits second, 24 btes microseconds */
+	__u64	events;		/* incremented when superblock updated */
+	__u64	resync_offset;	/* data before this offset (from data_offset) known to be in sync */
+	__u32	sb_csum;	/* checksum upto devs[max_dev] */
+	__u32	max_dev;	/* size of devs[] array to consider */
+	__u8	pad3[64-40];	/* set to 0 when writing */
+
+	/* device state information. Indexed by dev_number.
+	 * 2 bytes per device
+	 * Note there are no per-device state flags. State information is rolled
+	 * into the 'roles' value.  If a device is spare or faulty, then it doesn't
+	 * have a meaningful role.
+	 */
+	__u16	dev_roles[0];	/* role in array, or 0xffff for a spare, or 0xfffe for faulty */
+};
+
 #endif 
 
diff -Nru a/include/linux/raid/multipath.h b/include/linux/raid/multipath.h
--- a/include/linux/raid/multipath.h	Wed Aug 21 16:14:39 2002
+++ b/include/linux/raid/multipath.h	Tue Mar 11 18:15:04 2003
@@ -13,7 +13,6 @@
 	struct multipath_info	multipaths[MD_SB_DISKS];
 	int			raid_disks;
 	int			working_disks;
-	mdk_thread_t		*thread;
 	spinlock_t		device_lock;
 
 	mempool_t		*pool;
diff -Nru a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
--- a/include/linux/raid/raid1.h	Mon Feb 17 14:03:30 2003
+++ b/include/linux/raid/raid1.h	Tue Mar 11 18:15:04 2003
@@ -19,7 +19,6 @@
 	int			working_disks;
 	int			last_used;
 	sector_t		next_seq_sect;
-	mdk_thread_t		*thread;
 	spinlock_t		device_lock;
 
 	/* for use when syncing mirrors: */
@@ -34,7 +33,6 @@
 
 	mempool_t *r1bio_pool;
 	mempool_t *r1buf_pool;
-	char thread_name[MD_THREAD_NAME_MAX];
 };
 
 typedef struct r1_private_data_s conf_t;
diff -Nru a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
--- a/include/linux/raid/raid5.h	Mon Feb 17 14:03:30 2003
+++ b/include/linux/raid/raid5.h	Tue Mar 11 18:15:04 2003
@@ -203,7 +203,6 @@
 struct raid5_private_data {
 	struct stripe_head	**stripe_hashtbl;
 	mddev_t			*mddev;
-	mdk_thread_t		*thread;
 	struct disk_info	disks[MD_SB_DISKS];
 	struct disk_info	*spare;
 	int			chunk_size, level, algorithm;
@@ -226,7 +225,6 @@
 							 * waiting for 25% to be free
 							 */        
 	spinlock_t		device_lock;
-	char			thread_name[MD_THREAD_NAME_MAX];
 };
 
 typedef struct raid5_private_data raid5_conf_t;
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Mon Feb 24 09:40:34 2003
+++ b/include/linux/sched.h	Wed Mar  5 16:00:00 2003
@@ -328,7 +328,7 @@
 	prio_array_t *array;
 
 	unsigned long sleep_avg;
-	unsigned long sleep_timestamp;
+	unsigned long last_run;
 
 	unsigned long policy;
 	unsigned long cpus_allowed;
diff -Nru a/include/linux/sdladrv.h b/include/linux/sdladrv.h
--- a/include/linux/sdladrv.h	Mon Feb  4 23:39:17 2002
+++ b/include/linux/sdladrv.h	Sun Feb 16 16:22:42 2003
@@ -19,19 +19,6 @@
 #ifndef	_SDLADRV_H
 #define	_SDLADRV_H
 
-#include <linux/version.h>
-
-#ifndef KERNEL_VERSION
-  #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-#define LINUX_2_4	
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-#define LINUX_2_1
-#else
-#define LINUX_2_0
-#endif
 
 #define	SDLA_MAXIORANGE	4	/* maximum I/O port range */
 #define	SDLA_WINDOWSIZE	0x2000	/* default dual-port memory window size */
@@ -50,12 +37,7 @@
 	char S514_cpu_no[1];		/* PCI CPU Number */
 	unsigned char S514_slot_no;	/* PCI Slot Number */
 	char auto_pci_cfg;		/* Autodetect PCI Slot */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct pci_dev *pci_dev;	/* PCI device */
-#else
-	unsigned char pci_bus;		/* PCI bus number */
-	unsigned char pci_dev_func;	/* PCI device/function number */
-#endif
 	void * dpmbase;			/* dual-port memory base */
 	unsigned dpmsize;		/* dual-port memory size */
 	unsigned pclk;			/* CPU clock rate, kHz */
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Fri Feb  7 01:51:46 2003
+++ b/include/linux/security.h	Mon Mar 10 13:12:23 2003
@@ -48,6 +48,7 @@
 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
 extern void cap_task_kmod_set_label (void);
 extern void cap_task_reparent_to_init (struct task_struct *p);
+extern int cap_syslog (int type);
 
 static inline int cap_netlink_send (struct sk_buff *skb)
 {
@@ -62,7 +63,6 @@
 	return 0;
 }
 
-
 /*
  * Values used in the task_security_ops calls
  */
@@ -351,10 +351,6 @@
  *	@mnt is the vfsmount where the dentry was looked up
  *	@dentry contains the dentry structure for the file.
  *	Return 0 if permission is granted.
- * @inode_post_lookup:
- *	Set the security attributes for a file after it has been looked up.
- *	@inode contains the inode structure for parent directory.
- *	@d contains the dentry structure for the file.
  * @inode_delete:
  *	@inode contains the inode structure for deleted inode.
  *	This hook is called when a deleted inode is released (i.e. an inode
@@ -926,11 +922,23 @@
  *	is NULL.
  *	@file contains the file structure for the accounting file (may be NULL).
  *	Return 0 if permission is granted.
+ * @sysctl:
+ *	Check permission before accessing the @table sysctl variable in the
+ *	manner specified by @op.
+ *	@table contains the ctl_table structure for the sysctl variable.
+ *	@op contains the operation (001 = search, 002 = write, 004 = read).
+ *	Return 0 if permission is granted.
  * @capable:
  *	Check whether the @tsk process has the @cap capability.
  *	@tsk contains the task_struct for the process.
  *	@cap contains the capability <include/linux/capability.h>.
  *	Return 0 if the capability is granted for @tsk.
+ * @syslog:
+ *	Check permission before accessing the kernel message ring or changing
+ *	logging to the console.
+ *	See the syslog(2) manual page for an explanation of the @type values.  
+ *	@type contains the type of action.
+ *	Return 0 if permission is granted.
  *
  * @register_security:
  * 	allow module stacking.
@@ -957,9 +965,11 @@
 			    kernel_cap_t * inheritable,
 			    kernel_cap_t * permitted);
 	int (*acct) (struct file * file);
+	int (*sysctl) (ctl_table * table, int op);
 	int (*capable) (struct task_struct * tsk, int cap);
 	int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
 	int (*quota_on) (struct file * f);
+	int (*syslog) (int type);
 
 	int (*bprm_alloc_security) (struct linux_binprm * bprm);
 	void (*bprm_free_security) (struct linux_binprm * bprm);
@@ -969,6 +979,7 @@
 
 	int (*sb_alloc_security) (struct super_block * sb);
 	void (*sb_free_security) (struct super_block * sb);
+	int (*sb_kern_mount) (struct super_block *sb);
 	int (*sb_statfs) (struct super_block * sb);
 	int (*sb_mount) (char *dev_name, struct nameidata * nd,
 			 char *type, unsigned long flags, void *data);
@@ -1022,7 +1033,6 @@
 	int (*inode_permission_lite) (struct inode *inode, int mask);
 	int (*inode_setattr)	(struct dentry *dentry, struct iattr *attr);
 	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
-	void (*inode_post_lookup) (struct inode *inode, struct dentry *d);
         void (*inode_delete) (struct inode *inode);
 	int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
 			       size_t size, int flags);
@@ -1111,6 +1121,8 @@
 	int (*unregister_security) (const char *name,
 	                            struct security_operations *ops);
 
+	void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
+
 #ifdef CONFIG_SECURITY_NETWORK
 	int (*unix_stream_connect) (struct socket * sock,
 				    struct socket * other, struct sock * newsk);
@@ -1178,6 +1190,11 @@
 	return security_ops->acct (file);
 }
 
+static inline int security_sysctl(ctl_table * table, int op)
+{
+	return security_ops->sysctl(table, op);
+}
+
 static inline int security_quotactl (int cmds, int type, int id,
 				     struct super_block *sb)
 {
@@ -1189,6 +1206,11 @@
 	return security_ops->quota_on (file);
 }
 
+static inline int security_syslog(int type)
+{
+	return security_ops->syslog(type);
+}
+
 static inline int security_bprm_alloc (struct linux_binprm *bprm)
 {
 	return security_ops->bprm_alloc_security (bprm);
@@ -1220,6 +1242,11 @@
 	security_ops->sb_free_security (sb);
 }
 
+static inline int security_sb_kern_mount (struct super_block *sb)
+{
+	return security_ops->sb_kern_mount (sb);
+}
+
 static inline int security_sb_statfs (struct super_block *sb)
 {
 	return security_ops->sb_statfs (sb);
@@ -1426,12 +1453,6 @@
 	return security_ops->inode_getattr (mnt, dentry);
 }
 
-static inline void security_inode_post_lookup (struct inode *inode,
-					       struct dentry *dentry)
-{
-	security_ops->inode_post_lookup (inode, dentry);
-}
-
 static inline void security_inode_delete (struct inode *inode)
 {
 	security_ops->inode_delete (inode);
@@ -1729,6 +1750,11 @@
 	return security_ops->sem_semop(sma, sops, nsops, alter);
 }
 
+static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
+{
+	security_ops->d_instantiate (dentry, inode);
+}
+
 static inline int security_netlink_send(struct sk_buff * skb)
 {
 	return security_ops->netlink_send(skb);
@@ -1793,6 +1819,11 @@
 	return 0;
 }
 
+static inline int security_sysctl(ctl_table * table, int op)
+{
+	return 0;
+}
+
 static inline int security_quotactl (int cmds, int type, int id,
 				     struct super_block * sb)
 {
@@ -1804,6 +1835,11 @@
 	return 0;
 }
 
+static inline int security_syslog(int type)
+{
+	return cap_syslog(type);
+}
+
 static inline int security_bprm_alloc (struct linux_binprm *bprm)
 {
 	return 0;
@@ -1835,6 +1871,11 @@
 static inline void security_sb_free (struct super_block *sb)
 { }
 
+static inline int security_sb_kern_mount (struct super_block *sb)
+{
+	return 0;
+}
+
 static inline int security_sb_statfs (struct super_block *sb)
 {
 	return 0;
@@ -2013,10 +2054,6 @@
 	return 0;
 }
 
-static inline void security_inode_post_lookup (struct inode *inode,
-					       struct dentry *dentry)
-{ }
-
 static inline void security_inode_delete (struct inode *inode)
 { }
 
@@ -2299,6 +2336,9 @@
 {
 	return 0;
 }
+
+static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
+{ }
 
 /*
  * The netlink capability defaults need to be used inline by default
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	Sun Feb 16 11:59:58 2003
+++ b/include/linux/serial_core.h	Tue Mar 11 06:17:45 2003
@@ -208,12 +208,11 @@
 #define USF_CLOSING_WAIT_NONE	(65535)
 
 	int			count;
+	int			pm_state;
 	struct uart_info	*info;
 	struct uart_port	*port;
 
-#ifdef CONFIG_PM
-	struct pm_dev		*pm;
-#endif
+	struct semaphore	sem;
 };
 
 #define UART_XMIT_SIZE 1024
@@ -224,8 +223,6 @@
  * stuff here.
  */
 struct uart_info {
-	struct uart_port	*port;
-	struct uart_state	*state;
 	struct tty_struct	*tty;
 	struct circ_buf		xmit;
 	unsigned int		flags;
@@ -237,7 +234,6 @@
  */
 #define UIF_CHECK_CD		(1 << 25)
 #define UIF_CTS_FLOW		(1 << 26)
-#define UIF_CLOSING		(1 << 27)
 #define UIF_NORMAL_ACTIVE	(1 << 29)
 #define UIF_INITIALIZED		(1 << 31)
 
@@ -306,6 +302,12 @@
 int uart_register_port(struct uart_driver *reg, struct uart_port *port);
 int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
 int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
+
+/*
+ * Power Management
+ */
+int uart_suspend_port(struct uart_driver *reg, struct uart_port *port, u32 level);
+int uart_resume_port(struct uart_driver *reg, struct uart_port *port, u32 level);
 
 #define uart_circ_empty(circ)		((circ)->head == (circ)->tail)
 #define uart_circ_clear(circ)		((circ)->head = (circ)->tail = 0)
diff -Nru a/include/linux/slab.h b/include/linux/slab.h
--- a/include/linux/slab.h	Fri Feb  7 12:25:20 2003
+++ b/include/linux/slab.h	Sat Mar  8 14:50:35 2003
@@ -37,6 +37,7 @@
 #define	SLAB_HWCACHE_ALIGN	0x00002000UL	/* align objs on a h/w cache lines */
 #define SLAB_CACHE_DMA		0x00004000UL	/* use GFP_DMA memory */
 #define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* force alignment */
+#define SLAB_STORE_USER		0x00010000UL	/* store the last owner for bug hunting */
 
 /* flags passed to a constructor func */
 #define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
diff -Nru a/include/linux/socket.h b/include/linux/socket.h
--- a/include/linux/socket.h	Fri Feb 21 23:42:02 2003
+++ b/include/linux/socket.h	Thu Mar  6 11:06:44 2003
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
+#include <linux/linkage.h>
 #include <asm/socket.h>			/* arch-dependent defines	*/
 #include <linux/sockios.h>		/* the SIOCxxx I/O controls	*/
 #include <linux/uio.h>			/* iovec support		*/
@@ -234,6 +235,24 @@
 
 #define MSG_EOF         MSG_FIN
 
+#if defined(CONFIG_COMPAT)
+#define MSG_CMSG_COMPAT	0x80000000	/* This message needs 32 bit fixups */
+#else
+#define MSG_CMSG_COMPAT	0		/* We never have 32 bit fixups */
+#define compat_msghdr	msghdr		/* Needed to avoid compiler hoops */
+#endif
+
+struct compat_msghdr;
+extern int msghdr_from_user_compat_to_kern(struct msghdr *, struct compat_msghdr *);
+extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int);
+extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr *,unsigned);
+extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr *,unsigned);
+extern asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags);
+extern asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned flags);
+extern asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
+				char *optval, int *optlen);
+
+
 
 /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
 #define SOL_IP		0
@@ -276,6 +295,11 @@
 extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
 extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+extern int put_cmsg_compat(struct msghdr*, int level, int type, int len, void *data);
+extern void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr);
+extern int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
+			       unsigned char *stackbuf, int stackbuf_size);
+
 #endif
 #endif /* not kernel and not glibc */
 #endif /* _LINUX_SOCKET_H */
diff -Nru a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
--- a/include/linux/sunrpc/cache.h	Sun Jan  5 15:12:26 2003
+++ b/include/linux/sunrpc/cache.h	Tue Mar 11 20:03:48 2003
@@ -190,6 +190,7 @@
 			else read_unlock(&(DETAIL)->hash_lock);				\
 			if (set)							\
 				cache_fresh(DETAIL, &tmp->MEMBER, item->MEMBER.expiry_time); \
+			if (set==1 && new) cache_fresh(DETAIL, &new->MEMBER, 0);	\
 			if (new) (DETAIL)->cache_put(&new->MEMBER, DETAIL);		\
 			return tmp;							\
 		}									\
diff -Nru a/include/linux/tty.h b/include/linux/tty.h
--- a/include/linux/tty.h	Sun Dec 29 23:18:11 2002
+++ b/include/linux/tty.h	Thu Mar  6 21:27:16 2003
@@ -294,7 +294,7 @@
 	unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
 	unsigned char closing:1;
 	unsigned short minimum_to_wake;
-	unsigned overrun_time;
+	unsigned long overrun_time;
 	int num_overrun;
 	unsigned long process_char_map[256/(8*sizeof(unsigned long))];
 	char *read_buf;
@@ -348,7 +348,6 @@
 
 extern int kmsg_redirect;
 
-extern void con_init(void);
 extern void console_init(void);
 
 extern int lp_init(void);
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Wed Feb 26 08:29:24 2003
+++ b/include/linux/usb.h	Wed Mar  5 07:24:34 2003
@@ -213,7 +213,7 @@
 struct usb_device {
 	int		devnum;		/* Address on USB bus */
 	char		devpath [16];	/* Use in messages: /port/port/... */
-
+	enum usb_device_state	state;	/* configured, not attached, etc */
 	enum usb_device_speed	speed;	/* high/full/low (or error) */
 
 	struct usb_tt	*tt; 		/* low/full speed dev, highspeed hub */
@@ -240,7 +240,6 @@
 
 	int have_langid;		/* whether string_langid is valid yet */
 	int string_langid;		/* language ID for strings */
-	int present;			/* if device is present or not */
 
 	void *hcpriv;			/* Host Controller private data */
 	
diff -Nru a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h
--- a/include/linux/usb_ch9.h	Tue Oct 29 15:14:57 2002
+++ b/include/linux/usb_ch9.h	Wed Mar  5 07:28:25 2003
@@ -291,4 +291,25 @@
 	USB_SPEED_HIGH				/* usb 2.0 */
 };
 
+enum usb_device_state {
+	/* NOTATTACHED isn't in the USB spec, and this state acts
+	 * the same as ATTACHED ... but it's clearer this way.
+	 */
+	USB_STATE_NOTATTACHED = 0,
+
+	/* the chapter 9 device states */
+	USB_STATE_ATTACHED,
+	USB_STATE_POWERED,
+	USB_STATE_DEFAULT,			/* limited function */
+	USB_STATE_ADDRESS,
+	USB_STATE_CONFIGURED,			/* most functions */
+
+	USB_STATE_SUSPENDED
+
+	/* NOTE:  there are actually four different SUSPENDED
+	 * states, returning to POWERED, DEFAULT, ADDRESS, or
+	 * CONFIGURED respectively when SOF tokens flow again.
+	 */
+};
+
 #endif	/* __LINUX_USB_CH9_H */
diff -Nru a/include/linux/wanpipe.h b/include/linux/wanpipe.h
--- a/include/linux/wanpipe.h	Sun Dec  8 05:52:12 2002
+++ b/include/linux/wanpipe.h	Sun Feb 16 16:22:42 2003
@@ -39,59 +39,7 @@
 #ifndef	_WANPIPE_H
 #define	_WANPIPE_H
 
-#include <linux/version.h>
-
-#ifndef KERNEL_VERSION
-  #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- 
- #define LINUX_2_4
- #define netdevice_t struct net_device
-
- #define FREE_READ 1
- #define FREE_WRITE 0
-
- #define stop_net_queue(a) 	netif_stop_queue(a) 
- #define start_net_queue(a) 	netif_start_queue(a)
- #define is_queue_stopped(a)	netif_queue_stopped(a)
- #define wake_net_dev(a)	netif_wake_queue(a)
- #define is_dev_running(a)	netif_running(a)
- #define wan_dev_kfree_skb(a,b)	dev_kfree_skb_any(a)
-
-
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-
- #define LINUX_2_1
- #define netdevice_t struct device
- #define FREE_READ 1
- #define FREE_WRITE 0
-
- #define stop_net_queue(a) 	(set_bit(0, &##a->tbusy)) 
- #define start_net_queue(a) 	(clear_bit(0,&##a->tbusy))
- #define is_queue_stopped(a)	(##a->tbusy)
- #define wake_net_dev(a)	{clear_bit(0,&##a->tbusy);mark_bh(NET_BH);}
- #define is_dev_running(a)	(test_bit(0,&##a->start))
- #define wan_dev_kfree_skb(a,b)	dev_kfree_skb(a)
-
-#else
- #define LINUX_2_0
- #define netdevice_t struct device
-
- #define test_and_set_bit set_bit
- #define net_ratelimit() 1 
-
- #define stop_net_queue(a) 	(set_bit(0, &##a->tbusy)) 
- #define start_net_queue(a) 	(clear_bit(0,&##a->tbusy))
- #define is_queue_stopped(a)	(##a->tbusy)
- #define wake_net_dev(a)	{clear_bit(0,&##a->tbusy);mark_bh(NET_BH);}
- #define is_dev_running(a)	(test_bit(0,(void*)&##a->start))
- #define wan_dev_kfree_skb(a,b) dev_kfree_skb(a,b)  		 
- #define spin_lock_init(a)
- #define spin_lock(a)
- #define spin_unlock(a)
-#endif
+#define netdevice_t struct net_device
 
 #include <linux/wanrouter.h>
 
@@ -121,21 +69,11 @@
 #define MAX_LCN_NUM	4095	/* Maximum lcn number */
 #define MAX_FT1_RETRY 	100
 
-#ifdef LINUX_2_4
-  #ifndef AF_WANPIPE
+#ifndef AF_WANPIPE
 	#define AF_WANPIPE 25
 	#ifndef PF_WANPIPE
 		#define PF_WANPIPE AF_WANPIPE
 	#endif
-  #endif
-
-#else
-  #ifndef AF_WANPIPE
-	#define AF_WANPIPE 24
-	#ifndef PF_WANPIPE
-		#define PF_WANPIPE AF_WANPIPE
-	#endif
-  #endif
 #endif
 
 
@@ -321,12 +259,10 @@
 #include <linux/sdladrv.h>	/* SDLA support module API definitions */
 #include <linux/sdlasfm.h>	/* SDLA firmware module definitions */
 #include <linux/workqueue.h>
-#ifdef LINUX_2_4
-  #include <linux/serial.h>
-  #include <linux/serialP.h>
-  #include <linux/serial_reg.h>
-  #include <asm/serial.h>
-#endif
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
diff -Nru a/include/linux/wanrouter.h b/include/linux/wanrouter.h
--- a/include/linux/wanrouter.h	Wed Apr 24 10:11:41 2002
+++ b/include/linux/wanrouter.h	Sun Feb 16 16:22:42 2003
@@ -43,27 +43,10 @@
 * Jan 16, 1997	Gene Kozin	router_devlist made public
 * Jan 02, 1997	Gene Kozin	Initial version (based on wanpipe.h).
 *****************************************************************************/
-#include <linux/version.h>
 
-#ifndef KERNEL_VERSION
-  #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- #define LINUX_2_4
- #define netdevice_t struct net_device
- #include <linux/spinlock.h>       /* Support for SMP Locking */
-
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
- #define LINUX_2_1
- #define netdevice_t struct device
- #include <asm/spinlock.h>       /* Support for SMP Locking */
-
-#else
- #define LINUX_2_0
- #define netdevice_t struct device
- #define spinlock_t int
-#endif
+#define netdevice_t struct net_device
+
+#include <linux/spinlock.h>       /* Support for SMP Locking */
 
 #ifndef	_ROUTER_H
 #define	_ROUTER_H
@@ -512,11 +495,7 @@
 					/****** status and statistics *******/
 	char state;			/* device state */
 	char api_status;		/* device api status */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct net_device_stats stats; 	/* interface statistics */
-#else
-	struct enet_statistics stats;	/* interface statistics */
-#endif
 	unsigned reserved[16];		/* reserved for future use */
 	unsigned long critical;		/* critical section flag */
 	spinlock_t lock;                /* Support for SMP Locking */
@@ -534,11 +513,7 @@
 	struct wan_device* next;	/* -> next device */
 	netdevice_t* dev;		/* list of network interfaces */
 	unsigned ndev;			/* number of interfaces */
-#ifdef LINUX_2_4
 	struct proc_dir_entry *dent;	/* proc filesystem entry */
-#else
-	struct proc_dir_entry dent;	/* proc filesystem entry */
-#endif
 } wan_device_t;
 
 /* Public functions available for device drivers */
diff -Nru a/include/linux/writeback.h b/include/linux/writeback.h
--- a/include/linux/writeback.h	Sat Dec 14 09:42:09 2002
+++ b/include/linux/writeback.h	Sun Mar 16 22:33:14 2003
@@ -79,6 +79,7 @@
 extern int dirty_expire_centisecs;
 
 
+void page_writeback_init(void);
 void balance_dirty_pages(struct address_space *mapping);
 void balance_dirty_pages_ratelimited(struct address_space *mapping);
 int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
diff -Nru a/include/media/audiochip.h b/include/media/audiochip.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/media/audiochip.h	Wed Mar 12 06:07:06 2003
@@ -0,0 +1,24 @@
+#ifndef AUDIOCHIP_H
+#define AUDIOCHIP_H
+
+/* ---------------------------------------------------------------------- */
+
+/* v4l device was opened in Radio mode */
+#define AUDC_SET_RADIO        _IO('m',2)
+/* select from TV,radio,extern,MUTE */
+#define AUDC_SET_INPUT        _IOW('m',17,int)
+
+/* audio inputs */
+#define AUDIO_TUNER        0x00
+#define AUDIO_RADIO        0x01
+#define AUDIO_EXTERN       0x02
+#define AUDIO_INTERN       0x03
+#define AUDIO_OFF          0x04 
+#define AUDIO_ON           0x05
+#define AUDIO_MUTE         0x80
+#define AUDIO_UNMUTE       0x81
+
+/* misc stuff to pass around config info to i2c chips */
+#define AUDC_CONFIG_PINNACLE  _IOW('m',32,int)
+
+#endif /* AUDIOCHIP_H */
diff -Nru a/include/media/id.h b/include/media/id.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/media/id.h	Wed Mar 12 06:07:06 2003
@@ -0,0 +1,35 @@
+/* FIXME: this temporarely, until these are included in linux/i2c-id.h */
+
+/* drivers */
+#ifndef  I2C_DRIVERID_TVMIXER
+# define I2C_DRIVERID_TVMIXER I2C_DRIVERID_EXP0
+#endif
+#ifndef  I2C_DRIVERID_TVAUDIO
+# define I2C_DRIVERID_TVAUDIO I2C_DRIVERID_EXP1
+#endif
+
+/* chips */
+#ifndef  I2C_DRIVERID_DPL3518
+# define I2C_DRIVERID_DPL3518 I2C_DRIVERID_EXP2
+#endif
+#ifndef  I2C_DRIVERID_TDA9873
+# define I2C_DRIVERID_TDA9873 I2C_DRIVERID_EXP3
+#endif
+#ifndef  I2C_DRIVERID_TDA9875
+# define I2C_DRIVERID_TDA9875 I2C_DRIVERID_EXP0+4
+#endif
+#ifndef  I2C_DRIVERID_PIC16C54_PV951
+# define I2C_DRIVERID_PIC16C54_PV951 I2C_DRIVERID_EXP0+5
+#endif
+#ifndef  I2C_DRIVERID_TDA7432
+# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6
+#endif
+#ifndef  I2C_DRIVERID_TDA9874
+# define I2C_DRIVERID_TDA9874 I2C_DRIVERID_EXP0+7
+#endif
+
+/* algorithms */
+#ifndef I2C_ALGO_SAA7134
+# define I2C_ALGO_SAA7134 0x090000
+#endif
+
diff -Nru a/include/media/tuner.h b/include/media/tuner.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/media/tuner.h	Wed Mar 12 06:07:06 2003
@@ -0,0 +1,94 @@
+/* 
+    tuner.h - definition for different tuners
+
+    Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
+    minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _TUNER_H
+#define _TUNER_H
+
+#include "id.h"
+
+#define TUNER_TEMIC_PAL     0        /* 4002 FH5 (3X 7756, 9483) */
+#define TUNER_PHILIPS_PAL_I 1
+#define TUNER_PHILIPS_NTSC  2
+#define TUNER_PHILIPS_SECAM 3		/* you must actively select B/G, L, L` */
+#define TUNER_ABSENT        4
+#define TUNER_PHILIPS_PAL   5
+#define TUNER_TEMIC_NTSC    6        /* 4032 FY5 (3X 7004, 9498, 9789)  */
+#define TUNER_TEMIC_PAL_I   7        /* 4062 FY5 (3X 8501, 9957)        */
+#define TUNER_TEMIC_4036FY5_NTSC 8   /* 4036 FY5 (3X 1223, 1981, 7686)  */
+#define TUNER_ALPS_TSBH1_NTSC 	 9
+#define TUNER_ALPS_TSBE1_PAL 	10
+#define TUNER_ALPS_TSBB5_PAL_I 	11
+#define TUNER_ALPS_TSBE5_PAL 	12
+#define TUNER_ALPS_TSBC5_PAL 	13
+#define TUNER_TEMIC_4006FH5_PAL	14   /* 4006 FH5 (3X 9500, 9501, 7291)     */
+#define TUNER_ALPS_TSHC6_NTSC 	15
+#define TUNER_TEMIC_PAL_DK	16   /* 4016 FY5 (3X 1392, 1393)     */
+#define TUNER_PHILIPS_NTSC_M	17
+#define TUNER_TEMIC_4066FY5_PAL_I       18  /* 4066 FY5 (3X 7032, 7035) */
+#define TUNER_TEMIC_4006FN5_MULTI_PAL   19  /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
+#define TUNER_TEMIC_4009FR5_PAL         20  /* incl. FM radio (3X 7607, 7488, 7711)*/
+#define TUNER_TEMIC_4039FR5_NTSC        21  /* incl. FM radio (3X 7246, 7578, 7732)*/
+#define TUNER_TEMIC_4046FM5             22  /* you must actively select B/G, D/K, I, L, L` !  (3X 7804, 7806, 8103, 8104)*/
+#define TUNER_PHILIPS_PAL_DK		23
+#define TUNER_PHILIPS_FQ1216ME		24  /* you must actively select B/G/D/K, I, L, L` */
+#define TUNER_LG_PAL_I_FM	25
+#define TUNER_LG_PAL_I		26
+#define TUNER_LG_NTSC_FM	27
+#define TUNER_LG_PAL_FM		28
+#define TUNER_LG_PAL		29
+#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM	30  /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
+#define TUNER_SHARP_2U5JF5540_NTSC  31
+#define TUNER_Samsung_PAL_TCPM9091PD27 32
+#define TUNER_MT2032 33
+#define TUNER_TEMIC_4106FH5 	34	/* 4106 FH5 (3X 7808, 7865)*/
+#define TUNER_TEMIC_4012FY5	35	/* 4012 FY5 (3X 0971, 1099)*/
+#define TUNER_TEMIC_4136FY5	36	/* 4136 FY5 (3X 7708, 7746)*/
+#define TUNER_LG_PAL_NEW_TAPC   37
+#define TUNER_PHILIPS_FM1216ME_MK3  38
+#define TUNER_LG_NTSC_NEW_TAPC   39
+
+
+
+
+#define NOTUNER 0
+#define PAL     1	/* PAL_BG */
+#define PAL_I   2
+#define NTSC    3
+#define SECAM   4
+
+#define NoTuner 0
+#define Philips 1
+#define TEMIC   2
+#define Sony    3
+#define Alps    4
+#define LGINNOTEK 5
+#define SHARP   6
+#define Samsung 7
+#define Microtune 8
+
+#define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
+#define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
+#if 0 /* obsolete */
+# define TUNER_SET_RADIOFREQ         _IOW('t',3,int)    /* set radio freq */
+# define TUNER_SET_MODE              _IOW('t',4,int)    /* set tuner mode */
+#endif
+
+#endif
diff -Nru a/include/media/video-buf.h b/include/media/video-buf.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/media/video-buf.h	Wed Mar 12 06:07:06 2003
@@ -0,0 +1,234 @@
+/*
+ * generic helper functions for video4linux capture buffers, to handle
+ * memory management and PCI DMA.  Right now bttv + saa7134 use it.
+ *
+ * The functions expect the hardware being able to scatter gatter
+ * (i.e. the buffers are not linear in physical memory, but fragmented
+ * into PAGE_SIZE chunks).  They also assume the driver does not need
+ * to touch the video data (thus it is probably not useful for USB as
+ * data often must be uncompressed by the drivers).
+ * 
+ * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/videodev.h>
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Return a scatterlist for some page-aligned vmalloc()'ed memory
+ * block (NULL on errors).  Memory for the scatterlist is allocated
+ * using kmalloc.  The caller must free the memory.
+ */
+struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages);
+
+/*
+ * Return a scatterlist for a an array of userpages (NULL on errors).
+ * Memory for the scatterlist is allocated using kmalloc.  The caller
+ * must free the memory.
+ */
+struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages,
+					 int offset);
+int videobuf_lock(struct page **pages, int nr_pages);
+int videobuf_unlock(struct page **pages, int nr_pages);
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * A small set of helper functions to manage buffers (both userland
+ * and kernel) for DMA.
+ *
+ * videobuf_init_*_dmabuf()
+ *	creates a buffer.  The userland version takes a userspace
+ *	pointer + length.  The kernel version just wants the size and
+ *	does memory allocation too using vmalloc_32().
+ *
+ * videobuf_pci_*_dmabuf()
+ *	see Documentation/DMA-mapping.txt, these functions to
+ *	basically the same.  The map function does also build a
+ *	scatterlist for the buffer (and unmap frees it ...)
+ *
+ * videobuf_free_dmabuf()
+ *	no comment ...
+ *
+ */
+
+struct videobuf_dmabuf {
+	/* for userland buffer */
+	int                 offset;
+	struct page         **pages;
+
+	/* for kernel buffers */
+	void                *vmalloc;
+
+	/* common */
+	struct scatterlist  *sglist;
+	int                 sglen;
+	int                 nr_pages;
+	int                 direction;
+};
+
+int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
+			   unsigned long data, unsigned long size);
+int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
+			     int nr_pages);
+int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma);
+int videobuf_dma_pci_sync(struct pci_dev *dev,
+			  struct videobuf_dmabuf *dma);
+int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma);
+int videobuf_dma_free(struct videobuf_dmabuf *dma);
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * A small set of helper functions to manage video4linux buffers.
+ *
+ * struct videobuf_buffer holds the data structures used by the helper
+ * functions, additionally some commonly used fields for v4l buffers
+ * (width, height, lists, waitqueue) are in there.  That struct should
+ * be used as first element in the drivers buffer struct.
+ * 
+ * about the mmap helpers (videobuf_mmap_*):
+ *
+ * The mmaper function allows to map any subset of contingous buffers.
+ * This includes one mmap() call for all buffers (which the original
+ * video4linux API uses) as well as one mmap() for every single buffer
+ * (which v4l2 uses).
+ *
+ * If there is a valid mapping for a buffer, buffer->baddr/bsize holds
+ * userspace address + size which can be feeded into the
+ * videobuf_dma_init_user function listed above.
+ *
+ */
+
+struct videobuf_buffer;
+struct videobuf_queue;
+
+struct videobuf_mapping {
+	unsigned int count;
+	int highmem_ok;
+	unsigned long start;
+	unsigned long end;
+	struct videobuf_queue *q;
+};
+
+enum videobuf_state {
+	STATE_NEEDS_INIT = 0,
+	STATE_PREPARED   = 1,
+	STATE_QUEUED     = 2,
+	STATE_ACTIVE     = 3,
+	STATE_DONE       = 4,
+	STATE_ERROR      = 5,
+	STATE_IDLE       = 6,
+};
+
+struct videobuf_buffer {
+	unsigned int            i;
+
+	/* info about the buffer */
+	unsigned int            width;
+	unsigned int            height;
+	unsigned long           size;
+	enum v4l2_field         field;
+	enum videobuf_state     state;
+	struct videobuf_dmabuf  dma;
+	struct list_head        stream;  /* QBUF/DQBUF list */
+
+	/* for mmap'ed buffers */
+	size_t                  boff;    /* buffer offset (mmap) */
+	size_t                  bsize;   /* buffer size */
+	unsigned long           baddr;   /* buffer addr (userland ptr!) */
+	struct videobuf_mapping *map;
+
+	/* touched by irq handler */
+	struct list_head        queue;
+	wait_queue_head_t       done;
+	unsigned int            field_count;
+	struct timeval          ts;
+};
+
+struct videobuf_queue_ops {
+	int (*buf_setup)(struct file *file,
+			 unsigned int *count, unsigned int *size);
+	int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb,
+			   enum v4l2_field field);
+	void (*buf_queue)(struct file *file,struct videobuf_buffer *vb);
+	void (*buf_release)(struct file *file,struct videobuf_buffer *vb);
+};
+
+struct videobuf_queue {
+        struct semaphore           lock;
+	spinlock_t                 *irqlock;
+	struct pci_dev             *pci;
+
+	enum v4l2_buf_type         type;
+	unsigned int               msize;
+	enum v4l2_field            field;
+	enum v4l2_field            last; /* for field=V4L2_FIELD_ALTERNATE */
+	struct videobuf_buffer     *bufs[VIDEO_MAX_FRAME];
+	struct videobuf_queue_ops  *ops;
+
+	/* capture via mmap() + ioctl(QBUF/DQBUF) */
+	unsigned int               streaming;
+	struct list_head           stream;
+
+	/* capture via read() */
+	unsigned int               reading;
+	unsigned int               read_off;
+	struct videobuf_buffer     *read_buf;
+};
+
+void* videobuf_alloc(unsigned int size);
+int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
+int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb);
+
+void videobuf_queue_init(struct videobuf_queue *q,
+			 struct videobuf_queue_ops *ops,
+			 struct pci_dev *pci, spinlock_t *irqlock,
+			 enum v4l2_buf_type type,
+			 enum v4l2_field field,
+			 unsigned int msize);
+int  videobuf_queue_is_busy(struct videobuf_queue *q);
+void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q);
+
+void videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,
+		     enum v4l2_buf_type type);
+int videobuf_reqbufs(struct file *file, struct videobuf_queue *q,
+		     struct v4l2_requestbuffers *req);
+int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b);
+int videobuf_qbuf(struct file *file, struct videobuf_queue *q,
+		  struct v4l2_buffer *b);
+int videobuf_dqbuf(struct file *file, struct videobuf_queue *q,
+		   struct v4l2_buffer *b);
+int videobuf_streamon(struct file *file, struct videobuf_queue *q);
+int videobuf_streamoff(struct file *file, struct videobuf_queue *q);
+
+int videobuf_read_start(struct file *file, struct videobuf_queue *q);
+void videobuf_read_stop(struct file *file, struct videobuf_queue *q);
+ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q,
+			     char *data, size_t count, loff_t *ppos,
+			     int vbihack);
+ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q,
+			  char *data, size_t count, loff_t *ppos);
+unsigned int videobuf_poll_stream(struct file *file,
+				  struct videobuf_queue *q,
+				  poll_table *wait);
+
+int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q,
+			unsigned int bcount, unsigned int bsize);
+int videobuf_mmap_free(struct file *file, struct videobuf_queue *q);
+int videobuf_mmap_mapper(struct vm_area_struct *vma,
+			 struct videobuf_queue *q);
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Nru a/include/net/ah.h b/include/net/ah.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/net/ah.h	Thu Mar  6 16:15:33 2003
@@ -0,0 +1,35 @@
+#ifndef _NET_AH_H
+#define _NET_AH_H
+
+#include <net/xfrm.h>
+
+struct ah_data
+{
+	u8			*key;
+	int			key_len;
+	u8			*work_icv;
+	int			icv_full_len;
+	int			icv_trunc_len;
+
+	void			(*icv)(struct ah_data*,
+	                               struct sk_buff *skb, u8 *icv);
+
+	struct crypto_tfm	*tfm;
+};
+
+extern void skb_ah_walk(const struct sk_buff *skb,
+                        struct crypto_tfm *tfm, icv_update_fn_t icv_update);
+
+static inline void
+ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
+{
+	struct crypto_tfm *tfm = ahp->tfm;
+
+	memset(auth_data, 0, ahp->icv_trunc_len);
+	crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
+	skb_ah_walk(skb, tfm, crypto_hmac_update);
+	crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv);
+	memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
+}
+
+#endif
diff -Nru a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
--- a/include/net/bluetooth/bluetooth.h	Thu Oct 31 18:06:05 2002
+++ b/include/net/bluetooth/bluetooth.h	Thu Mar  6 11:06:44 2003
@@ -128,7 +128,7 @@
 struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio);
 void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
-int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm);
+int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags);
 uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
 int  bt_sock_w4_connect(struct sock *sk, int flags);
 
diff -Nru a/include/net/compat_socket.h b/include/net/compat_socket.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/net/compat_socket.h	Thu Mar  6 11:02:18 2003
@@ -0,0 +1,67 @@
+#ifndef NET_COMPAT_SOCKET_H
+#define NET_COMPAT_SOCKET_H 1
+
+#include <linux/compat.h>
+
+#if defined(CONFIG_COMPAT)
+
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
+					   16 for IP, 16 for IPX,
+					   24 for IPv6,
+					   about 80 for AX.25 */
+
+struct compat_msghdr {
+	u32		msg_name;
+	int		msg_namelen;
+	u32		msg_iov;
+	compat_size_t	msg_iovlen;
+	u32		msg_control;
+	compat_size_t	msg_controllen;
+	unsigned	msg_flags;
+};
+
+struct compat_cmsghdr {
+	compat_size_t	cmsg_len;
+	int		cmsg_level;
+	int		cmsg_type;
+};
+
+/* Bleech... */
+#define __CMSG_COMPAT_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg_compat_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG_COMPAT_NXTHDR(mhdr, cmsg, cmsglen) cmsg_compat_nxthdr((mhdr), (cmsg), (cmsglen))
+
+#define CMSG_COMPAT_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+
+#define CMSG_COMPAT_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))))
+#define CMSG_COMPAT_SPACE(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len))
+#define CMSG_COMPAT_LEN(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len))
+
+#define __CMSG_COMPAT_FIRSTHDR(ctl,len) ((len) >= sizeof(struct compat_cmsghdr) ? \
+				    (struct compat_cmsghdr *)(ctl) : \
+				    (struct compat_cmsghdr *)NULL)
+#define CMSG_COMPAT_FIRSTHDR(msg)	__CMSG_COMPAT_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+static __inline__ struct compat_cmsghdr *__cmsg_compat_nxthdr(void *__ctl, __kernel_size_t __size,
+					      struct compat_cmsghdr *__cmsg, int __cmsg_len)
+{
+	struct compat_cmsghdr * __ptr;
+
+	__ptr = (struct compat_cmsghdr *)(((unsigned char *) __cmsg) +
+				     CMSG_COMPAT_ALIGN(__cmsg_len));
+	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+		return NULL;
+
+	return __ptr;
+}
+
+static __inline__ struct compat_cmsghdr *cmsg_compat_nxthdr (struct msghdr *__msg,
+					    struct compat_cmsghdr *__cmsg,
+					    int __cmsg_len)
+{
+	return __cmsg_compat_nxthdr(__msg->msg_control, __msg->msg_controllen,
+			       __cmsg, __cmsg_len);
+}
+
+#endif /* CONFIG_COMPAT */
+#endif
diff -Nru a/include/net/dn_route.h b/include/net/dn_route.h
--- a/include/net/dn_route.h	Wed Feb 19 13:55:33 2003
+++ b/include/net/dn_route.h	Mon Mar  3 04:56:52 2003
@@ -134,7 +134,7 @@
 	}
 
 	sk->err = EHOSTUNREACH;
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 }
 
diff -Nru a/include/net/dst.h b/include/net/dst.h
--- a/include/net/dst.h	Sun Dec 22 23:29:59 2002
+++ b/include/net/dst.h	Wed Mar  5 15:45:36 2003
@@ -247,7 +247,10 @@
 struct flowi;
 extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
 		       struct sock *sk, int flags);
+extern int xfrm6_lookup(struct dst_entry **dst_p, struct flowi *fl,
+		       struct sock *sk, int flags);
 extern void xfrm_init(void);
+extern void xfrm6_init(void);
 
 #endif
 
diff -Nru a/include/net/esp.h b/include/net/esp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/net/esp.h	Thu Mar  6 16:15:34 2003
@@ -0,0 +1,56 @@
+#ifndef _NET_ESP_H
+#define _NET_ESP_H
+
+#include <net/xfrm.h>
+
+struct esp_data
+{
+	/* Confidentiality */
+	struct {
+		u8			*key;		/* Key */
+		int			key_len;	/* Key length */
+		u8			*ivec;		/* ivec buffer */
+		/* ivlen is offset from enc_data, where encrypted data start.
+		 * It is logically different of crypto_tfm_alg_ivsize(tfm).
+		 * We assume that it is either zero (no ivec), or
+		 * >= crypto_tfm_alg_ivsize(tfm). */
+		int			ivlen;
+		int			padlen;		/* 0..255 */
+		struct crypto_tfm	*tfm;		/* crypto handle */
+	} conf;
+
+	/* Integrity. It is active when icv_full_len != 0 */
+	struct {
+		u8			*key;		/* Key */
+		int			key_len;	/* Length of the key */
+		u8			*work_icv;
+		int			icv_full_len;
+		int			icv_trunc_len;
+		void			(*icv)(struct esp_data*,
+		                               struct sk_buff *skb,
+		                               int offset, int len, u8 *icv);
+		struct crypto_tfm	*tfm;
+	} auth;
+};
+
+extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
+			 int offset, int len, icv_update_fn_t icv_update);
+extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len);
+extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
+extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
+
+static inline void
+esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
+                int len, u8 *auth_data)
+{
+	struct crypto_tfm *tfm = esp->auth.tfm;
+	char *icv = esp->auth.work_icv;
+
+	memset(auth_data, 0, esp->auth.icv_trunc_len);
+	crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len);
+	skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update);
+	crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv);
+	memcpy(auth_data, icv, esp->auth.icv_trunc_len);
+}
+
+#endif
diff -Nru a/include/net/inet_common.h b/include/net/inet_common.h
--- a/include/net/inet_common.h	Tue Oct  8 07:02:41 2002
+++ b/include/net/inet_common.h	Thu Mar  6 11:06:44 2003
@@ -23,11 +23,11 @@
 extern int			inet_recvmsg(struct kiocb *iocb,
 					     struct socket *sock, 
 					     struct msghdr *ubuf, 
-					     int size, int flags, struct scm_cookie *scm);
+					     int size, int flags);
 extern int			inet_sendmsg(struct kiocb *iocb,
 					     struct socket *sock, 
 					     struct msghdr *msg, 
-					     int size, struct scm_cookie *scm);
+					     int size);
 extern int			inet_shutdown(struct socket *sock, int how);
 extern unsigned int		inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
 extern int			inet_setsockopt(struct socket *sock, int level,
diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h
--- a/include/net/ip6_route.h	Sun Feb 23 22:41:51 2003
+++ b/include/net/ip6_route.h	Wed Mar  5 15:45:36 2003
@@ -57,6 +57,8 @@
 					    struct in6_addr *saddr,
 					    int oif, int flags);
 
+extern struct rt6_info		*ndisc_get_dummy_rt(void);
+
 /*
  *	support functions for ND
  *
diff -Nru a/include/net/scm.h b/include/net/scm.h
--- a/include/net/scm.h	Fri Feb  8 19:10:55 2002
+++ b/include/net/scm.h	Thu Mar  6 11:06:44 2003
@@ -22,6 +22,7 @@
 };
 
 extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
+extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
 extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
 extern void __scm_destroy(struct scm_cookie *scm);
 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
diff -Nru a/include/net/snmp.h b/include/net/snmp.h
--- a/include/net/snmp.h	Tue Jan  7 02:19:04 2003
+++ b/include/net/snmp.h	Mon Mar 10 11:55:44 2003
@@ -299,8 +299,8 @@
 #define DECLARE_SNMP_STAT(type, name)	\
 	extern __typeof__(type) *name[2]
 
-#define SNMP_STAT_USRPTR(name)	(name[0])
-#define SNMP_STAT_BHPTR(name)	(name[1])
+#define SNMP_STAT_BHPTR(name)	(name[0])
+#define SNMP_STAT_USRPTR(name)	(name[1])
 
 #define SNMP_INC_STATS_BH(mib, field) 	\
 	(per_cpu_ptr(mib[0], smp_processor_id())->field++)
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	Fri Feb  7 01:48:38 2003
+++ b/include/net/sock.h	Sat Mar  8 11:39:01 2003
@@ -29,6 +29,8 @@
  *              			protocol specific parts were moved to
  *              			respective headers and ipv4/v6, etc now
  *              			use private slabcaches for its socks
+ *              Pedro Hortas	:	New flags field for socket options
+ *
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -52,7 +54,6 @@
 
 #include <asm/atomic.h>
 #include <net/dst.h>
-#include <net/scm.h>
 
 /*
  * This structure really needs to be cleaned up.
@@ -60,6 +61,17 @@
  * the other protocols.
  */
 
+/* Sock flags */
+enum {
+	SOCK_DEAD,
+	SOCK_DONE,
+	SOCK_URGINLINE,
+	SOCK_KEEPOPEN,
+	SOCK_LINGER,
+	SOCK_DESTROY,
+	SOCK_BROADCAST,
+};
+
 /* Define this to get the sk->debug debugging facility. */
 #define SOCK_DEBUGGING
 #ifdef SOCK_DEBUGGING
@@ -120,18 +132,8 @@
 	int			sndbuf;		/* Size of send buffer in bytes		*/
 	struct sock		*prev;
 
-	/* Not all are volatile, but some are, so we might as well say they all are.
-	 * XXX Make this a flag word -DaveM
-	 */
-	volatile char		dead,
-				done,
-				urginline,
-				keepopen,
-				linger,
-				destroy,
-				no_check,
-				broadcast,
-				bsdism;
+	unsigned long 		flags;
+	char		 	no_check;
 	unsigned char		debug;
 	unsigned char		rcvtstamp;
 	unsigned char		no_largesend;
@@ -306,9 +308,9 @@
 	int			size;
 	struct socket		*sock;
 	struct sock		*sk;
+	struct scm_cookie	*scm;
 	struct msghdr		*msg, async_msg;
 	struct iovec		async_iov;
-	struct scm_cookie	*scm, async_scm;
 };
 
 static inline struct sock_iocb *kiocb_to_siocb(struct kiocb *iocb)
@@ -434,11 +436,9 @@
 extern int			sock_no_setsockopt(struct socket *, int, int,
 						   char *, int);
 extern int                      sock_no_sendmsg(struct kiocb *, struct socket *,
-						struct msghdr *, int,
-						struct scm_cookie *);
+						struct msghdr *, int);
 extern int                      sock_no_recvmsg(struct kiocb *, struct socket *,
-						struct msghdr *, int, int,
-						struct scm_cookie *);
+						struct msghdr *, int, int);
 extern int			sock_no_mmap(struct file *file,
 					     struct socket *sock,
 					     struct vm_area_struct *vma);
@@ -605,7 +605,7 @@
 static inline void sock_orphan(struct sock *sk)
 {
 	write_lock_bh(&sk->callback_lock);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sk->socket = NULL;
 	sk->sleep = NULL;
 	write_unlock_bh(&sk->callback_lock);
@@ -769,7 +769,7 @@
 	skb->dev = NULL;
 	skb_set_owner_r(skb, sk);
 	skb_queue_tail(&sk->receive_queue, skb);
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk,skb->len);
 out:
 	return err;
@@ -784,7 +784,7 @@
 		return -ENOMEM;
 	skb_set_owner_r(skb, sk);
 	skb_queue_tail(&sk->error_queue,skb);
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk,skb->len);
 	return 0;
 }
@@ -895,6 +895,14 @@
 				remove_wait_queue((sk)->sleep, &wait); \
 				lock_sock(sk); \
 				}
+
+static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
+{
+	if (valbool)
+		__set_bit(bit, &sk->flags);
+	else
+		__clear_bit(bit, &sk->flags);
+}
 
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	Mon Feb 10 14:44:43 2003
+++ b/include/net/tcp.h	Sat Mar  8 11:37:51 2003
@@ -144,6 +144,7 @@
 extern kmem_cache_t *tcp_bucket_cachep;
 extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
 						 unsigned short snum);
+extern void tcp_bucket_destroy(struct tcp_bind_bucket *tb);
 extern void tcp_bucket_unlock(struct sock *sk);
 extern int tcp_port_rover;
 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
@@ -1422,7 +1423,7 @@
 
 	sk->shutdown = SHUTDOWN_MASK;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 	else
 		tcp_destroy_sock(sk);
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	Thu Feb 13 01:26:32 2003
+++ b/include/net/xfrm.h	Thu Mar  6 16:16:15 2003
@@ -12,6 +12,7 @@
 
 #include <net/dst.h>
 #include <net/route.h>
+#include <net/ip6_fib.h>
 
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
 
@@ -223,7 +224,7 @@
 	char			*id;
 	int			(*notify)(struct xfrm_state *x, int event);
 	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
-	struct xfrm_policy	*(*compile_policy)(int opt, u8 *data, int len, int *dir);
+	struct xfrm_policy	*(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -282,6 +283,7 @@
 		struct xfrm_dst		*next;
 		struct dst_entry	dst;
 		struct rtable		rt;
+		struct rt6_info		rt6;
 	} u;
 };
 
@@ -308,26 +310,42 @@
 	if (sp && atomic_dec_and_test(&sp->refcnt))
 		__secpath_destroy(sp);
 }
-
-extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb);
+extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
 
 static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
 {
 	if (sk && sk->policy[XFRM_POLICY_IN])
-		return __xfrm_policy_check(sk, dir, skb);
+		return __xfrm_policy_check(sk, dir, skb, AF_INET);
+		
+	return	!xfrm_policy_list[dir] ||
+		(skb->dst->flags & DST_NOPOLICY) ||
+		__xfrm_policy_check(sk, dir, skb, AF_INET);
+}
+
+static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+{
+	if (sk && sk->policy[XFRM_POLICY_IN])
+		return __xfrm_policy_check(sk, dir, skb, AF_INET6);
 		
 	return	!xfrm_policy_list[dir] ||
 		(skb->dst->flags & DST_NOPOLICY) ||
-		__xfrm_policy_check(sk, dir, skb);
+		__xfrm_policy_check(sk, dir, skb, AF_INET6);
 }
 
-extern int __xfrm_route_forward(struct sk_buff *skb);
+extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
 
 static inline int xfrm_route_forward(struct sk_buff *skb)
 {
 	return	!xfrm_policy_list[XFRM_POLICY_OUT] ||
 		(skb->dst->flags & DST_NOXFRM) ||
-		__xfrm_route_forward(skb);
+		__xfrm_route_forward(skb, AF_INET);
+}
+
+static inline int xfrm6_route_forward(struct sk_buff *skb)
+{
+	return	!xfrm_policy_list[XFRM_POLICY_OUT] ||
+		(skb->dst->flags & DST_NOXFRM) ||
+		__xfrm_route_forward(skb, AF_INET6);
 }
 
 extern int __xfrm_sk_clone_policy(struct sock *sk);
@@ -380,12 +398,16 @@
 extern void xfrm_input_init(void);
 extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
 extern struct xfrm_state *xfrm_state_alloc(void);
-extern struct xfrm_state *xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
-					  struct xfrm_policy *pol, int *err);
+extern struct xfrm_state *xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
+					   struct xfrm_policy *pol, int *err);
+extern struct xfrm_state *xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr,
+					   struct flowi *fl, struct xfrm_tmpl *tmpl,
+					   struct xfrm_policy *pol, int *err);
 extern int xfrm_state_check_expire(struct xfrm_state *x);
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb);
-extern struct xfrm_state *xfrm_state_lookup(u32 daddr, u32 spi, u8 proto);
+extern struct xfrm_state *xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto);
+extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto);
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern void xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
@@ -393,17 +415,21 @@
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
 extern int xfrm4_rcv(struct sk_buff *skb);
+extern int xfrm6_rcv(struct sk_buff *skb);
+extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir);
 extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen);
 
 struct xfrm_policy *xfrm_policy_alloc(int gfp);
 extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
-struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl);
+struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, unsigned short family);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
 struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel);
 struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
 void xfrm_policy_flush(void);
 void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
 struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create);
+struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr,
+				   struct in6_addr *saddr, int create);
 extern void xfrm_policy_flush(void);
 extern void xfrm_policy_kill(struct xfrm_policy *);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
@@ -425,23 +451,52 @@
 extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name);
 
+static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
+{
+	__u32 *a1 = token1;
+	__u32 *a2 = token2;
+	int pdw;
+	int pbi;
+
+	pdw = prefixlen >> 5;	  /* num of whole __u32 in prefix */
+	pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */
+
+	if (pdw)
+		if (memcmp(a1, a2, pdw << 2))
+			return 0;
+
+	if (pbi) {
+		__u32 mask;
+
+		mask = htonl((0xffffffff) << (32 - pbi));
+
+		if ((a1[pdw] ^ a2[pdw]) & mask)
+			return 0;
+	}
+
+	return 1;
+}
+
 static inline int
 xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
-      return  !memcmp(fl->fl6_dst, sel->daddr.a6, sizeof(struct in6_addr)) &&
-              !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
-              !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
-              (fl->proto == sel->proto || !sel->proto) &&
-              (fl->oif == sel->ifindex || !sel->ifindex) &&
-              !memcmp(fl->fl6_src, sel->saddr.a6, sizeof(struct in6_addr));
+	return  addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
+		addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
+		!((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
+		!((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
+		(fl->proto == sel->proto || !sel->proto) &&
+		(fl->oif == sel->ifindex || !sel->ifindex);
 }
 
 extern int xfrm6_register_type(struct xfrm_type *type);
 extern int xfrm6_unregister_type(struct xfrm_type *type);
 extern struct xfrm_type *xfrm6_get_type(u8 proto);
 
-extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto);
-struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create);
-void xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
+struct crypto_tfm;
+typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int);
+
+typedef int (xfrm_dst_lookup_t)(struct xfrm_dst **dst, struct flowi *fl);
+int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, unsigned short family);
+void xfrm_dst_lookup_unregister(unsigned short family);
 
 #endif	/* _NET_XFRM_H */
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	Mon Feb  3 12:19:37 2003
+++ b/init/Kconfig	Mon Mar 10 22:34:13 2003
@@ -37,6 +37,16 @@
 
 menu "General setup"
 
+config SWAP
+	bool "Support for paging of anonymous memory"
+	depends on MMU
+	default y
+	help
+	  This option allows you to choose whether you want to have support
+	  for socalled swap devices or swap files in your kernel that are
+	  used to provide more virtual memory than the actual RAM present
+	  in your computer.  If unsure say Y.
+
 config SYSVIPC
 	bool "System V IPC"
 	---help---
diff -Nru a/init/Makefile b/init/Makefile
--- a/init/Makefile	Sun Mar  2 20:33:40 2003
+++ b/init/Makefile	Fri Mar  7 12:55:30 2003
@@ -21,5 +21,5 @@
 # actual file if its content has changed.
 
 include/linux/compile.h: FORCE
-	@echo -n '  GEN     $@'
+	@echo '  CHK     $@'
 	@sh $(srctree)/scripts/mkcompile_h $@ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
diff -Nru a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c	Sat Mar  1 11:25:53 2003
+++ b/init/do_mounts.c	Thu Mar  6 16:27:25 2003
@@ -17,7 +17,7 @@
 int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */
 
 int root_mountflags = MS_RDONLY | MS_VERBOSE;
-static char * __initdata root_device_name;
+char * __initdata root_device_name;
 static char __initdata saved_root_name[64];
 
 /* this is initialized in init/main.c */
diff -Nru a/init/do_mounts.h b/init/do_mounts.h
--- a/init/do_mounts.h	Fri Feb 21 23:12:30 2003
+++ b/init/do_mounts.h	Thu Mar  6 16:27:25 2003
@@ -27,6 +27,7 @@
 void  mount_block_root(char *name, int flags);
 void  mount_root(void);
 extern int root_mountflags;
+extern char *root_device_name;
 
 #ifdef CONFIG_DEVFS_FS
 
diff -Nru a/init/do_mounts_rd.c b/init/do_mounts_rd.c
--- a/init/do_mounts_rd.c	Fri Feb 21 23:12:30 2003
+++ b/init/do_mounts_rd.c	Thu Mar  6 16:27:25 2003
@@ -242,6 +242,7 @@
 {
 	if (rd_prompt)
 		change_floppy("root floppy disk to be loaded into RAM disk");
+	create_dev("/dev/root", ROOT_DEV, root_device_name);
 	create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL);
 	return rd_load_image("/dev/root");
 }
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Tue Mar  4 08:13:43 2003
+++ b/init/main.c	Sun Mar 16 22:33:14 2003
@@ -35,10 +35,21 @@
 #include <linux/profile.h>
 #include <linux/rcupdate.h>
 #include <linux/moduleparam.h>
+#include <linux/writeback.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
 
+/*
+ * This is one of the first .c files built. Error out early
+ * if we have compiler trouble..
+ */
+#if __GNUC__ == 2 && __GNUC_MINOR__ == 96
+#ifdef CONFIG_FRAME_POINTER
+#error This compiler cannot compile correctly with frame pointers enabled
+#endif
+#endif
+
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/smp.h>
 #endif
@@ -429,6 +440,8 @@
 	vfs_caches_init(num_physpages);
 	radix_tree_init();
 	signals_init();
+	/* rootfs populating might need page-writeback */
+	page_writeback_init();
 	populate_rootfs();
 #ifdef CONFIG_PROC_FS
 	proc_root_init();
diff -Nru a/kernel/cpufreq.c b/kernel/cpufreq.c
--- a/kernel/cpufreq.c	Mon Mar  3 14:38:51 2003
+++ b/kernel/cpufreq.c	Sat Mar  8 01:39:17 2003
@@ -43,12 +43,40 @@
  */
 static struct notifier_block    *cpufreq_policy_notifier_list;
 static struct notifier_block    *cpufreq_transition_notifier_list;
-static DECLARE_MUTEX            (cpufreq_notifier_sem);
+static DECLARE_RWSEM		(cpufreq_notifier_rwsem);
 
 
 LIST_HEAD(cpufreq_governor_list);
+static DECLARE_MUTEX		(cpufreq_governor_sem);
 
-static int cpufreq_governor(unsigned int cpu, unsigned int event);
+static struct device_interface cpufreq_interface;
+
+static int cpufreq_cpu_get(unsigned int cpu) {
+	if (cpu >= NR_CPUS)
+		return 0;
+
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
+
+	if (!try_module_get(cpufreq_driver->owner)) {
+		kset_put(&cpufreq_interface.kset);
+		return 0;
+	}
+
+	if (!kobject_get(&cpufreq_driver->policy[cpu].kobj)) {
+		module_put(cpufreq_driver->owner);
+		kset_put(&cpufreq_interface.kset);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void cpufreq_cpu_put(unsigned int cpu) {
+	kobject_put(&cpufreq_driver->policy[cpu].kobj);
+	module_put(cpufreq_driver->owner);
+	kset_put(&cpufreq_interface.kset);
+}
 
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
@@ -67,19 +95,19 @@
 		return 0;
 	} else 	{
 		struct cpufreq_governor *t;
-		down(&cpufreq_driver_sem);
+		down(&cpufreq_governor_sem);
 		if (!cpufreq_driver || !cpufreq_driver->target)
 			goto out;
 		list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
 			if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
 				*governor = t;
 				*policy = CPUFREQ_POLICY_GOVERNOR;
-				up(&cpufreq_driver_sem);
+				up(&cpufreq_governor_sem);
 				return 0;
 			}
 		}
 	out:
-		up(&cpufreq_driver_sem);
+		up(&cpufreq_governor_sem);
 	}
 	return -EINVAL;
 }
@@ -120,14 +148,7 @@
 static ssize_t show_##file_name 					\
 (struct cpufreq_policy * policy, char *buf)				\
 {									\
-	unsigned int value = 0;						\
-									\
-	down(&cpufreq_driver_sem);					\
-	if (cpufreq_driver)						\
-		value = policy->object;					\
-	up(&cpufreq_driver_sem);					\
-									\
-	return sprintf (buf, "%u\n", value);				\
+	return sprintf (buf, "%u\n", policy->object);			\
 }
 
 show_one(cpuinfo_min_freq, cpuinfo.min_freq);
@@ -143,12 +164,17 @@
 (struct cpufreq_policy * policy, const char *buf, size_t count)		\
 {									\
 	unsigned int ret = -EINVAL;					\
+	struct cpufreq_policy new_policy;				\
 									\
-	ret = sscanf (buf, "%u", &policy->object);			\
+	ret = cpufreq_get_policy(&new_policy, policy->cpu);		\
+	if (ret)							\
+		return -EINVAL;						\
+									\
+	ret = sscanf (buf, "%u", &new_policy.object);			\
 	if (ret != 1)							\
 		return -EINVAL;						\
 									\
-	ret = cpufreq_set_policy(policy);				\
+	ret = cpufreq_set_policy(&new_policy);				\
 									\
 	return ret ? ret : count;					\
 }
@@ -161,26 +187,16 @@
  */
 static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
 {
-	unsigned int value = 0;
-	char value2[CPUFREQ_NAME_LEN];
-
-	down(&cpufreq_driver_sem);
-	if (cpufreq_driver)
-		value = policy->policy;
-	if (value == CPUFREQ_POLICY_GOVERNOR)
-		strncpy(value2, policy->governor->name, CPUFREQ_NAME_LEN);
-	up(&cpufreq_driver_sem);
-
-	switch (value) {
+	switch (policy->policy) {
 	case CPUFREQ_POLICY_POWERSAVE:
 		return sprintf(buf, "powersave\n");
 	case CPUFREQ_POLICY_PERFORMANCE:
 		return sprintf(buf, "performance\n");
 	case CPUFREQ_POLICY_GOVERNOR:
-		return sprintf(buf, "%s\n", value2);
+		return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
+	default:
+		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
 
@@ -192,25 +208,55 @@
 {
 	unsigned int ret = -EINVAL;
 	char	str_governor[16];
+	struct cpufreq_policy new_policy;
+
+	ret = cpufreq_get_policy(&new_policy, policy->cpu);
+	if (ret)
+		return ret;
 
 	ret = sscanf (buf, "%15s", str_governor);
 	if (ret != 1)
 		return -EINVAL;
 
-	if (cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor))
+	if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
 		return -EINVAL;
 
-	ret = cpufreq_set_policy(policy);
+	ret = cpufreq_set_policy(&new_policy);
 
 	return ret ? ret : count;
 }
 
+/**
+ * show_scaling_driver - show the cpufreq driver currently loaded
+ */
+static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
+{
+	return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+}
+
+/**
+ * show_scaling_available_governors - show the available CPUfreq governors
+ */
+static ssize_t show_scaling_available_governors(struct cpufreq_policy * policy, char *buf)
+{
+	ssize_t i = 0;
+	struct cpufreq_governor *t;
+
+	i += sprintf(buf, "performance powersave");
+
+	if (!cpufreq_driver->target)
+		goto out;
+
+	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
+		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
+			goto out;
+		i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
+	}
+ out:
+	i += sprintf(&buf[i], "\n");
+	return i;
+}
 
-struct freq_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct cpufreq_policy *, char *);
-	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
-};
 
 #define define_one_ro(_name) \
 struct freq_attr _name = { \
@@ -227,6 +273,8 @@
 
 define_one_ro(cpuinfo_min_freq);
 define_one_ro(cpuinfo_max_freq);
+define_one_ro(scaling_available_governors);
+define_one_ro(scaling_driver);
 define_one_rw(scaling_min_freq);
 define_one_rw(scaling_max_freq);
 define_one_rw(scaling_governor);
@@ -237,10 +285,11 @@
 	&scaling_min_freq.attr,
 	&scaling_max_freq.attr,
 	&scaling_governor.attr,
+	&scaling_driver.attr,
+	&scaling_available_governors.attr,
 	NULL
 };
 
-
 #define to_policy(k) container_of(k,struct cpufreq_policy,kobj)
 #define to_attr(a) container_of(a,struct freq_attr,attr)
 
@@ -248,7 +297,12 @@
 {
 	struct cpufreq_policy * policy = to_policy(kobj);
 	struct freq_attr * fattr = to_attr(attr);
-	return fattr->show ? fattr->show(policy,buf) : 0;
+	ssize_t ret;
+	if (!cpufreq_cpu_get(policy->cpu))
+		return -EINVAL;
+	ret = fattr->show ? fattr->show(policy,buf) : 0;
+	cpufreq_cpu_put(policy->cpu);
+	return ret;
 }
 
 static ssize_t store(struct kobject * kobj, struct attribute * attr, 
@@ -256,7 +310,12 @@
 {
 	struct cpufreq_policy * policy = to_policy(kobj);
 	struct freq_attr * fattr = to_attr(attr);
-	return fattr->store ? fattr->store(policy,buf,count) : 0;
+	ssize_t ret;
+	if (!cpufreq_cpu_get(policy->cpu))
+		return -EINVAL;
+	ret = fattr->store ? fattr->store(policy,buf,count) : 0;
+	cpufreq_cpu_put(policy->cpu);
+	return ret;
 }
 
 static struct sysfs_ops sysfs_ops = {
@@ -271,56 +330,6 @@
 
 
 /**
- * show_scaling_governor - show the current policy for the specified CPU
- */
-static ssize_t show_scaling_driver (struct device *dev, char *buf)
-{
-	char value[CPUFREQ_NAME_LEN];
-
-	if (!dev)
-		return 0;
-
-	down(&cpufreq_driver_sem);
-	if (cpufreq_driver)
-		strncpy(value, cpufreq_driver->name, CPUFREQ_NAME_LEN);
-	up(&cpufreq_driver_sem);
-
-	return sprintf(buf, "%s\n", value);
-}
-
-/**
- * show_available_govs - show the available CPUfreq governors
- */
-static ssize_t show_available_govs(struct device *dev, char *buf)
-{
-	ssize_t i = 0;
-	struct cpufreq_governor *t;
-
-	if (!dev)
-		return 0;
-
-	i += sprintf(buf, "performance powersave");
-
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver || !cpufreq_driver->target)
-		goto out;
-
-	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
-			goto out;
-		i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
-	}
- out:
-	up(&cpufreq_driver_sem);
-	i += sprintf(&buf[i], "\n");
-	return i;
-}
-
-
-static DEVICE_ATTR(scaling_driver, S_IRUGO, show_scaling_driver, NULL);
-static DEVICE_ATTR(available_scaling_governors, S_IRUGO, show_available_govs, NULL);
-
-/**
  * cpufreq_add_dev - add a CPU device
  *
  * Adds the cpufreq interface for a CPU device. 
@@ -329,50 +338,62 @@
 {
 	unsigned int cpu = to_cpu_nr(dev);
 	int ret = 0;
-	struct cpufreq_policy policy;
+	struct cpufreq_policy new_policy;
+	struct cpufreq_policy *policy;
+	struct freq_attr **drv_attr;
 
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver) {
-		up(&cpufreq_driver_sem);
+	if (!kset_get(&cpufreq_interface.kset))
+		return -EINVAL;
+
+	if (!try_module_get(cpufreq_driver->owner)) {
+		kset_put(&cpufreq_interface.kset);
 		return -EINVAL;
 	}
 
 	/* call driver. From then on the cpufreq must be able
 	 * to accept all calls to ->verify and ->setpolicy for this CPU
 	 */
-	cpufreq_driver->policy[cpu].cpu = cpu;
+	policy = &cpufreq_driver->policy[cpu];
+	policy->cpu = cpu;
 	if (cpufreq_driver->init) {
-		ret = cpufreq_driver->init(&cpufreq_driver->policy[cpu]);
-		if (ret) {
-			up(&cpufreq_driver_sem);
-			return -ENODEV;
-		}
+		ret = cpufreq_driver->init(policy);
+		if (ret)
+			goto out;
 	}
 
 	/* set default policy on this CPU */
-	memcpy(&policy, 
-	       &cpufreq_driver->policy[cpu], 
+	down(&cpufreq_driver_sem);
+	memcpy(&new_policy, 
+	       policy, 
 	       sizeof(struct cpufreq_policy));
-
-	if (cpufreq_driver->target)
-		cpufreq_governor(cpu, CPUFREQ_GOV_START);
-
 	up(&cpufreq_driver_sem);
-	ret = cpufreq_set_policy(&policy);
-	if (ret)
-		return -EINVAL;
-	down(&cpufreq_driver_sem);
 
+	init_MUTEX(&policy->lock);
 	/* prepare interface data */
-	policy.kobj.parent = &dev->kobj;
-	policy.kobj.ktype = &ktype_cpufreq;
-	policy.dev = dev;
-	strncpy(policy.kobj.name, 
+	policy->kobj.parent = &dev->kobj;
+	policy->kobj.ktype = &ktype_cpufreq;
+	policy->dev = dev;
+	strncpy(policy->kobj.name, 
 		cpufreq_interface.name, KOBJ_NAME_LEN);
 
-	ret = kobject_register(&policy.kobj);
+	ret = kobject_register(&policy->kobj);
+	if (ret)
+		goto out;
 
-	up(&cpufreq_driver_sem);
+	drv_attr = cpufreq_driver->attr;
+	while ((drv_attr) && (*drv_attr)) {
+		sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+		drv_attr++;
+	}
+
+	/* set default policy */
+	ret = cpufreq_set_policy(&new_policy);
+	if (ret)
+		kobject_unregister(&policy->kobj);
+
+ out:
+	module_put(cpufreq_driver->owner);
+	kset_put(&cpufreq_interface.kset);
 	return ret;
 }
 
@@ -380,21 +401,39 @@
 /**
  * cpufreq_remove_dev - remove a CPU device
  *
- * Removes the cpufreq interface for a CPU device. Is called with
- * cpufreq_driver_sem locked.
+ * Removes the cpufreq interface for a CPU device.
  */
 static int cpufreq_remove_dev (struct device * dev)
 {
 	unsigned int cpu = to_cpu_nr(dev);
 
-	if (cpufreq_driver->target)
-		cpufreq_governor(cpu, CPUFREQ_GOV_STOP);
+	if (!kset_get(&cpufreq_interface.kset))
+		return -EINVAL;
+
+	if (!kobject_get(&cpufreq_driver->policy[cpu].kobj)) {
+		kset_put(&cpufreq_interface.kset);
+		return -EINVAL;
+	}
 
+	down(&cpufreq_driver_sem);
+	if ((cpufreq_driver->target) && 
+	    (cpufreq_driver->policy[cpu].policy == CPUFREQ_POLICY_GOVERNOR)) {
+		cpufreq_driver->policy[cpu].governor->governor(&cpufreq_driver->policy[cpu], CPUFREQ_GOV_STOP);
+		module_put(cpufreq_driver->policy[cpu].governor->owner);
+	}
+
+	/* we may call driver->exit here without checking for try_module_exit
+	 * as it's either the driver which wants to unload or we have a CPU
+	 * removal AND driver removal at the same time...
+	 */
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(&cpufreq_driver->policy[cpu]);
 
 	kobject_unregister(&cpufreq_driver->policy[cpu].kobj);
 
+	up(&cpufreq_driver_sem);
+	kobject_put(&cpufreq_driver->policy[cpu].kobj);
+	kset_put(&cpufreq_interface.kset);
 	return 0;
 }
 
@@ -420,7 +459,7 @@
 {
 	int ret;
 
-	down(&cpufreq_notifier_sem);
+	down_write(&cpufreq_notifier_rwsem);
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
 		ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
@@ -431,7 +470,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	up(&cpufreq_notifier_sem);
+	up_write(&cpufreq_notifier_rwsem);
 
 	return ret;
 }
@@ -452,7 +491,7 @@
 {
 	int ret;
 
-	down(&cpufreq_notifier_sem);
+	down_write(&cpufreq_notifier_rwsem);
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
 		ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
@@ -463,7 +502,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	up(&cpufreq_notifier_sem);
+	up_write(&cpufreq_notifier_rwsem);
 
 	return ret;
 }
@@ -474,71 +513,72 @@
  *                              GOVERNORS                            *
  *********************************************************************/
 
-inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-				   unsigned int target_freq,
-				   unsigned int relation)
-{
-	unsigned int ret;
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver)
-		ret = -EINVAL;
-	else
-		ret = cpufreq_driver->target(policy, target_freq, relation);
-	up(&cpufreq_driver_sem);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(cpufreq_driver_target_l);
-
-
 inline int cpufreq_driver_target(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation)
 {
-	return cpufreq_driver->target(policy, target_freq, relation);
+	unsigned int ret;
+	unsigned int cpu = policy->cpu;
+
+	if (!cpufreq_cpu_get(cpu))
+		return -EINVAL;
+
+	down(&cpufreq_driver->policy[cpu].lock);
+
+	ret = cpufreq_driver->target(policy, target_freq, relation);
+
+	up(&cpufreq_driver->policy[cpu].lock);
+
+	cpufreq_cpu_put(cpu);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
 
-static int cpufreq_governor(unsigned int cpu, unsigned int event)
+int cpufreq_governor(unsigned int cpu, unsigned int event)
 {
 	int ret = 0;
 	struct cpufreq_policy *policy = &cpufreq_driver->policy[cpu];
 
+	if (!cpufreq_cpu_get(cpu))
+		return -EINVAL;
+
 	switch (policy->policy) {
 	case CPUFREQ_POLICY_POWERSAVE: 
-		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START))
+		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
+			down(&cpufreq_driver->policy[cpu].lock);
 			ret = cpufreq_driver->target(policy, policy->min, CPUFREQ_RELATION_L);
+			up(&cpufreq_driver->policy[cpu].lock);
+		}
 		break;
 	case CPUFREQ_POLICY_PERFORMANCE:
-		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START))
+		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
+			down(&cpufreq_driver->policy[cpu].lock);
 			ret = cpufreq_driver->target(policy, policy->max, CPUFREQ_RELATION_H);
+			up(&cpufreq_driver->policy[cpu].lock);
+		}
 		break;
 	case CPUFREQ_POLICY_GOVERNOR:
 		ret = -EINVAL;
-		if (event == CPUFREQ_GOV_START)
-			if (!try_module_get(cpufreq_driver->policy[cpu].governor->owner))
-				break;
+		if (!try_module_get(cpufreq_driver->policy[cpu].governor->owner))
+			break;
 		ret = cpufreq_driver->policy[cpu].governor->governor(policy, event);
-		if ((event == CPUFREQ_GOV_STOP) ||
-			(ret && (event == CPUFREQ_GOV_START)))
+		/* we keep one module reference alive for each CPU governed by this CPU */
+		if ((event != CPUFREQ_GOV_START) || ret)
+			module_put(cpufreq_driver->policy[cpu].governor->owner);
+		if ((event == CPUFREQ_GOV_STOP) && !ret)
 			module_put(cpufreq_driver->policy[cpu].governor->owner);
 		break;
 	default:
 		ret = -EINVAL;
 	}
-	return ret;
-}
 
+	cpufreq_cpu_put(cpu);
 
-int cpufreq_governor_l(unsigned int cpu, unsigned int event)
-{
-	int ret = 0;
-	down(&cpufreq_driver_sem);
-	ret = cpufreq_governor(cpu, event);
-	up(&cpufreq_driver_sem);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_governor_l);
+EXPORT_SYMBOL_GPL(cpufreq_governor);
 
 
 int cpufreq_register_governor(struct cpufreq_governor *governor)
@@ -553,16 +593,17 @@
 	if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
 		return -EBUSY;
 
-	down(&cpufreq_driver_sem);
+	down(&cpufreq_governor_sem);
 	
 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
 		if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
-			up(&cpufreq_driver_sem);
+			up(&cpufreq_governor_sem);
 			return -EBUSY;
 		}
 	}
 	list_add(&governor->governor_list, &cpufreq_governor_list);
- 	up(&cpufreq_driver_sem);
+
+ 	up(&cpufreq_governor_sem);
 
 	return 0;
 }
@@ -576,7 +617,8 @@
 	if (!governor)
 		return;
 
-	down(&cpufreq_driver_sem);
+	down(&cpufreq_governor_sem);
+
 	/* 
 	 * Unless the user uses rmmod -f, we can be safe. But we never
 	 * know, so check whether if it's currently used. If so,
@@ -584,17 +626,21 @@
 	 */
 	for (i=0; i<NR_CPUS; i++)
 	{
-		if (cpufreq_driver && 
-		    (cpufreq_driver->policy[i].policy == CPUFREQ_POLICY_GOVERNOR) && 
+		if (!cpufreq_cpu_get(i))
+			continue;
+		if ((cpufreq_driver->policy[i].policy == CPUFREQ_POLICY_GOVERNOR) && 
 		    (cpufreq_driver->policy[i].governor == governor)) {
 			cpufreq_governor(i, CPUFREQ_GOV_STOP);
 			cpufreq_driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
 			cpufreq_governor(i, CPUFREQ_GOV_START);
+			cpufreq_governor(i, CPUFREQ_GOV_LIMITS);
 		}
+		cpufreq_cpu_put(i);
 	}
+
 	/* now we can safely remove it from the list */
 	list_del(&governor->governor_list);
-	up(&cpufreq_driver_sem);
+	up(&cpufreq_governor_sem);
 	return;
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
@@ -613,19 +659,17 @@
  */
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
 {
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver  || !policy || 
-	    (cpu >= NR_CPUS) || (!cpu_online(cpu))) {
-		up(&cpufreq_driver_sem);
+	if (!policy || !cpufreq_cpu_get(cpu))
 		return -EINVAL;
-	}
 
+	down(&cpufreq_driver_sem);
 	memcpy(policy, 
 	       &cpufreq_driver->policy[cpu], 
 	       sizeof(struct cpufreq_policy));
-	
 	up(&cpufreq_driver_sem);
 
+	cpufreq_cpu_put(cpu);
+
 	return 0;
 }
 EXPORT_SYMBOL(cpufreq_get_policy);
@@ -639,27 +683,23 @@
  */
 int cpufreq_set_policy(struct cpufreq_policy *policy)
 {
-	int ret;
+	int ret = 0;
 
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver || !policy ||
-	    (policy->cpu >= NR_CPUS) || (!cpu_online(policy->cpu))) {
-		up(&cpufreq_driver_sem);
+	if (!policy || !cpufreq_cpu_get(policy->cpu))
 		return -EINVAL;
-	}
 
+	down(&cpufreq_driver_sem);
 	memcpy(&policy->cpuinfo, 
 	       &cpufreq_driver->policy[policy->cpu].cpuinfo, 
 	       sizeof(struct cpufreq_cpuinfo));
+	up(&cpufreq_driver_sem);
 
 	/* verify the cpu speed can be set within this limit */
 	ret = cpufreq_driver->verify(policy);
-	if (ret) {
-		up(&cpufreq_driver_sem);
-		return ret;
-	}
+	if (ret)
+		goto error_out;
 
-	down(&cpufreq_notifier_sem);
+	down_read(&cpufreq_notifier_rwsem);
 
 	/* adjust if necessary - all reasons */
 	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
@@ -673,17 +713,18 @@
 	   which might be different to the first one */
 	ret = cpufreq_driver->verify(policy);
 	if (ret) {
-		up(&cpufreq_notifier_sem);
-		up(&cpufreq_driver_sem);
-		return ret;
+		up_read(&cpufreq_notifier_rwsem);
+		goto error_out;
 	}
 
 	/* notification of the new policy */
 	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
 			    policy);
 
-	up(&cpufreq_notifier_sem);
+	up_read(&cpufreq_notifier_rwsem);
 
+	/* from here on we limit it to one limit and/or governor change running at the moment */
+	down(&cpufreq_driver_sem);
 	cpufreq_driver->policy[policy->cpu].min    = policy->min;
 	cpufreq_driver->policy[policy->cpu].max    = policy->max;
 
@@ -711,9 +752,11 @@
 			cpufreq_governor(policy->cpu, CPUFREQ_GOV_LIMITS);
 		}
 	}
-	
 	up(&cpufreq_driver_sem);
 
+ error_out:	
+	cpufreq_cpu_put(policy->cpu);
+
 	return ret;
 }
 EXPORT_SYMBOL(cpufreq_set_policy);
@@ -759,7 +802,7 @@
  */
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
 {
-	down(&cpufreq_notifier_sem);
+	down_read(&cpufreq_notifier_rwsem);
 	switch (state) {
 	case CPUFREQ_PRECHANGE:
 		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
@@ -771,7 +814,7 @@
 		cpufreq_driver->policy[freqs->cpu].cur = freqs->new;
 		break;
 	}
-	up(&cpufreq_notifier_sem);
+	up_read(&cpufreq_notifier_rwsem);
 }
 EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
 
@@ -793,38 +836,33 @@
  */
 int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 {
-	int ret = 0;
-
-	if (cpufreq_driver)
-		return -EBUSY;
-	
-	if (!driver_data || !driver_data->verify || 
+	if (!driver_data || !driver_data->verify || !driver_data->init ||
 	    ((!driver_data->setpolicy) && (!driver_data->target)))
 		return -EINVAL;
 
-	down(&cpufreq_driver_sem);
 
+	if (kset_get(&cpufreq_interface.kset)) {
+		kset_put(&cpufreq_interface.kset);
+		return -EBUSY;
+	}
+
+	down(&cpufreq_driver_sem);
+	if (cpufreq_driver) {
+		up(&cpufreq_driver_sem);		
+		return -EBUSY;
+	}
 	cpufreq_driver = driver_data;
+	up(&cpufreq_driver_sem);
 
+	cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
 	if (!cpufreq_driver->policy) {
-		/* then we need per-CPU init */
-		if (!cpufreq_driver->init) {
-			up(&cpufreq_driver_sem);
-			return -EINVAL;
-		}
-		cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-		if (!cpufreq_driver->policy) {
-			up(&cpufreq_driver_sem);
-			return -ENOMEM;
-		}
-		memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy));
+		cpufreq_driver = NULL;
+		return -ENOMEM;
 	}
-	
-	up(&cpufreq_driver_sem);
 
-	ret = interface_register(&cpufreq_interface);
+	memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy));
 
-	return ret;
+	return interface_register(&cpufreq_interface);
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_driver);
 
@@ -839,20 +877,20 @@
  */
 int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 {
-	down(&cpufreq_driver_sem);
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
 
-	if (!cpufreq_driver || 
-	    ((driver != cpufreq_driver) && (driver != NULL))) { /* compat */
-		up(&cpufreq_driver_sem);
+	if (!cpufreq_driver || (driver != cpufreq_driver)) {
+		kset_put(&cpufreq_interface.kset);
 		return -EINVAL;
 	}
 
+	kset_put(&cpufreq_interface.kset);
 	interface_unregister(&cpufreq_interface);
 
-	if (driver)
-		kfree(cpufreq_driver->policy);
+	down(&cpufreq_driver_sem);
+	kfree(cpufreq_driver->policy);
 	cpufreq_driver = NULL;
-
 	up(&cpufreq_driver_sem);
 
 	return 0;
@@ -876,21 +914,27 @@
 	if (in_interrupt())
 		panic("cpufreq_restore() called from interrupt context!");
 
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
+
+	if (!try_module_get(cpufreq_driver->owner))
+		goto error_out;
+
 	for (i=0;i<NR_CPUS;i++) {
-		if (!cpu_online(i))
+		if (!cpu_online(i) || !cpufreq_cpu_get(i))
 			continue;
 
 		down(&cpufreq_driver_sem);
-		if (!cpufreq_driver) {
-			up(&cpufreq_driver_sem);
-			return 0;
-		}
-
 		memcpy(&policy, &cpufreq_driver->policy[i], sizeof(struct cpufreq_policy));
 		up(&cpufreq_driver_sem);
-
 		ret += cpufreq_set_policy(&policy);
+
+		cpufreq_cpu_put(i);
 	}
+
+	module_put(cpufreq_driver->owner);
+ error_out:
+	kset_put(&cpufreq_interface.kset);
 
 	return ret;
 }
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Thu Feb 27 23:02:30 2003
+++ b/kernel/fork.c	Mon Mar 10 22:34:31 2003
@@ -188,7 +188,7 @@
 	task_struct_cachep =
 		kmem_cache_create("task_struct",
 				  sizeof(struct task_struct),0,
-				  SLAB_HWCACHE_ALIGN, NULL, NULL);
+				  SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
 	if (!task_struct_cachep)
 		panic("fork_init(): cannot create task_struct SLAB cache");
 
@@ -214,6 +214,8 @@
 	struct thread_info *ti;
 	int cpu = get_cpu();
 
+	prepare_to_copy(orig);
+
 	tsk = task_cache[cpu];
 	task_cache[cpu] = NULL;
 	put_cpu();
@@ -916,7 +918,7 @@
 	 */
 	p->first_time_slice = 1;
 	current->time_slice >>= 1;
-	p->sleep_timestamp = jiffies;
+	p->last_run = jiffies;
 	if (!current->time_slice) {
 		/*
 	 	 * This case is rare, it happens when the parent has only
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Sun Mar  2 18:13:25 2003
+++ b/kernel/ksyms.c	Wed Mar 12 11:10:29 2003
@@ -57,6 +57,7 @@
 #include <linux/mount.h>
 #include <linux/ptrace.h>
 #include <linux/time.h>
+#include <linux/backing-dev.h>
 #include <asm/checksum.h>
 
 #if defined(CONFIG_PROC_FS)
@@ -176,7 +177,8 @@
 EXPORT_SYMBOL(end_buffer_io_sync);
 EXPORT_SYMBOL(__mark_inode_dirty);
 EXPORT_SYMBOL(get_empty_filp);
-EXPORT_SYMBOL(init_private_file);
+EXPORT_SYMBOL(open_private_file);
+EXPORT_SYMBOL(close_private_file);
 EXPORT_SYMBOL(filp_open);
 EXPORT_SYMBOL(filp_close);
 EXPORT_SYMBOL(put_filp);
@@ -234,15 +236,6 @@
 EXPORT_SYMBOL(generic_file_mmap);
 EXPORT_SYMBOL(generic_file_readonly_mmap);
 EXPORT_SYMBOL(generic_ro_fops);
-EXPORT_SYMBOL(file_lock_list);
-EXPORT_SYMBOL(locks_init_lock);
-EXPORT_SYMBOL(locks_copy_lock);
-EXPORT_SYMBOL(posix_lock_file);
-EXPORT_SYMBOL(posix_test_lock);
-EXPORT_SYMBOL(posix_block_lock);
-EXPORT_SYMBOL(posix_unblock_lock);
-EXPORT_SYMBOL(posix_locks_deadlock);
-EXPORT_SYMBOL(locks_mandatory_area);
 EXPORT_SYMBOL(dput);
 EXPORT_SYMBOL(have_submounts);
 EXPORT_SYMBOL(d_find_alias);
@@ -367,6 +360,7 @@
 EXPORT_SYMBOL(generic_file_readv);
 EXPORT_SYMBOL(generic_file_writev);
 EXPORT_SYMBOL(iov_shorten);
+EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
 /* tty routines */
 EXPORT_SYMBOL(tty_wait_until_sent);
diff -Nru a/kernel/posix-timers.c b/kernel/posix-timers.c
--- a/kernel/posix-timers.c	Wed Feb 26 12:02:09 2003
+++ b/kernel/posix-timers.c	Sun Mar  9 18:48:02 2003
@@ -1273,7 +1273,7 @@
 		spin_unlock_irq(&nanosleep_abs_list_lock);
 	}
 	if (active) {
-		unsigned long jiffies_f = jiffies;
+		long jiffies_left;
 
 		/*
 		 * Always restart abs calls from scratch to pick up any
@@ -1282,7 +1282,12 @@
 		if (abs)
 			return -ERESTARTNOHAND;
 
-		jiffies_to_timespec(new_timer.expires - jiffies_f, tsave);
+		jiffies_left = new_timer.expires - jiffies;
+
+		if (jiffies_left < 0)
+			return 0;
+
+		jiffies_to_timespec(jiffies_left, tsave);
 
 		while (tsave->tv_nsec < 0) {
 			tsave->tv_nsec += NSEC_PER_SEC;
diff -Nru a/kernel/printk.c b/kernel/printk.c
--- a/kernel/printk.c	Mon Feb  3 23:46:51 2003
+++ b/kernel/printk.c	Tue Jan 21 08:56:27 2003
@@ -28,6 +28,7 @@
 #include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/smp.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 
@@ -161,6 +162,10 @@
 	char c;
 	int error = 0;
 
+	error = security_syslog(type);
+	if (error)
+		return error;
+
 	switch (type) {
 	case 0:		/* Close log */
 		break;
@@ -273,8 +278,6 @@
 
 asmlinkage long sys_syslog(int type, char * buf, int len)
 {
-	if ((type != 3) && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
 	return do_syslog(type, buf, len);
 }
 
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Thu Feb 20 20:33:52 2003
+++ b/kernel/sched.c	Sun Mar 16 16:00:00 2003
@@ -33,6 +33,12 @@
 #include <linux/timer.h>
 #include <linux/rcupdate.h>
 
+#ifdef CONFIG_NUMA
+#define cpu_to_node_mask(cpu) node_to_cpumask(cpu_to_node(cpu))
+#else
+#define cpu_to_node_mask(cpu) (cpu_online_map)
+#endif
+
 /*
  * Convert user-nice values [ -20 ... 0 ... 19 ]
  * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -54,20 +60,20 @@
 /*
  * These are the 'tuning knobs' of the scheduler:
  *
- * Minimum timeslice is 10 msecs, default timeslice is 150 msecs,
- * maximum timeslice is 300 msecs. Timeslices get refilled after
+ * Minimum timeslice is 10 msecs, default timeslice is 100 msecs,
+ * maximum timeslice is 200 msecs. Timeslices get refilled after
  * they expire.
  */
 #define MIN_TIMESLICE		( 10 * HZ / 1000)
-#define MAX_TIMESLICE		(300 * HZ / 1000)
-#define CHILD_PENALTY		95
+#define MAX_TIMESLICE		(200 * HZ / 1000)
+#define CHILD_PENALTY		50
 #define PARENT_PENALTY		100
 #define EXIT_WEIGHT		3
 #define PRIO_BONUS_RATIO	25
 #define INTERACTIVE_DELTA	2
-#define MAX_SLEEP_AVG		(2*HZ)
-#define STARVATION_LIMIT	(2*HZ)
-#define NODE_THRESHOLD          125
+#define MAX_SLEEP_AVG		(10*HZ)
+#define STARVATION_LIMIT	(10*HZ)
+#define NODE_THRESHOLD		125
 
 /*
  * If a task is 'interactive' then we reinsert it in the active
@@ -154,10 +160,9 @@
 	task_t *curr, *idle;
 	struct mm_struct *prev_mm;
 	prio_array_t *active, *expired, arrays[2];
-	int prev_nr_running[NR_CPUS];
+	int prev_cpu_load[NR_CPUS];
 #ifdef CONFIG_NUMA
 	atomic_t *node_nr_running;
-	unsigned int nr_balanced;
 	int prev_node_load[MAX_NUMNODES];
 #endif
 	task_t *migration_thread;
@@ -302,10 +307,13 @@
  *
  * Both properties are important to certain workloads.
  */
-static inline int effective_prio(task_t *p)
+static int effective_prio(task_t *p)
 {
 	int bonus, prio;
 
+	if (rt_task(p))
+		return p->prio;
+
 	bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 -
 			MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2;
 
@@ -318,31 +326,65 @@
 }
 
 /*
- * activate_task - move a task to the runqueue.
+ * __activate_task - move a task to the runqueue.
+ */
+static inline void __activate_task(task_t *p, runqueue_t *rq)
+{
+	enqueue_task(p, rq->active);
+	nr_running_inc(rq);
+}
 
- * Also update all the scheduling statistics stuff. (sleep average
+/*
+ * activate_task - move a task to the runqueue and do priority recalculation
+ *
+ * Update all the scheduling statistics stuff. (sleep average
  * calculation, priority modifiers, etc.)
  */
-static inline void activate_task(task_t *p, runqueue_t *rq)
+static inline int activate_task(task_t *p, runqueue_t *rq)
 {
-	unsigned long sleep_time = jiffies - p->sleep_timestamp;
-	prio_array_t *array = rq->active;
+	long sleep_time = jiffies - p->last_run - 1;
+	int requeue_waker = 0;
+
+	if (sleep_time > 0) {
+		int sleep_avg;
 
-	if (!rt_task(p) && sleep_time) {
 		/*
-		 * This code gives a bonus to interactive tasks. We update
-		 * an 'average sleep time' value here, based on
-		 * sleep_timestamp. The more time a task spends sleeping,
-		 * the higher the average gets - and the higher the priority
-		 * boost gets as well.
+		 * This code gives a bonus to interactive tasks.
+		 *
+		 * The boost works by updating the 'average sleep time'
+		 * value here, based on ->last_run. The more time a task
+		 * spends sleeping, the higher the average gets - and the
+		 * higher the priority boost gets as well.
 		 */
-		p->sleep_avg += sleep_time;
-		if (p->sleep_avg > MAX_SLEEP_AVG)
-			p->sleep_avg = MAX_SLEEP_AVG;
-		p->prio = effective_prio(p);
+		sleep_avg = p->sleep_avg + sleep_time;
+
+		/*
+		 * 'Overflow' bonus ticks go to the waker as well, so the
+		 * ticks are not lost. This has the effect of further
+		 * boosting tasks that are related to maximum-interactive
+		 * tasks.
+		 */
+		if (sleep_avg > MAX_SLEEP_AVG) {
+			if (!in_interrupt()) {
+				sleep_avg += current->sleep_avg - MAX_SLEEP_AVG;
+				if (sleep_avg > MAX_SLEEP_AVG)
+					sleep_avg = MAX_SLEEP_AVG;
+
+				if (current->sleep_avg != sleep_avg) {
+					current->sleep_avg = sleep_avg;
+					requeue_waker = 1;
+				}
+			}
+			sleep_avg = MAX_SLEEP_AVG;
+		}
+		if (p->sleep_avg != sleep_avg) {
+			p->sleep_avg = sleep_avg;
+			p->prio = effective_prio(p);
+		}
 	}
-	enqueue_task(p, array);
-	nr_running_inc(rq);
+	__activate_task(p, rq);
+
+	return requeue_waker;
 }
 
 /*
@@ -455,8 +497,8 @@
  */
 static int try_to_wake_up(task_t * p, unsigned int state, int sync)
 {
+	int success = 0, requeue_waker = 0;
 	unsigned long flags;
-	int success = 0;
 	long old_state;
 	runqueue_t *rq;
 
@@ -479,16 +521,34 @@
 			}
 			if (old_state == TASK_UNINTERRUPTIBLE)
 				rq->nr_uninterruptible--;
-			activate_task(p, rq);
-	
-			if (p->prio < rq->curr->prio)
-				resched_task(rq->curr);
+			if (sync)
+				__activate_task(p, rq);
+			else {
+				requeue_waker = activate_task(p, rq);
+				if (p->prio < rq->curr->prio)
+					resched_task(rq->curr);
+			}
 			success = 1;
 		}
 		p->state = TASK_RUNNING;
 	}
 	task_rq_unlock(rq, &flags);
 
+	/*
+	 * We have to do this outside the other spinlock, the two
+	 * runqueues might be different:
+	 */
+	if (requeue_waker) {
+		prio_array_t *array;
+
+		rq = task_rq_lock(current, &flags);
+		array = current->array;
+		dequeue_task(current, array);
+		current->prio = effective_prio(current);
+		enqueue_task(current, array);
+		task_rq_unlock(rq, &flags);
+	}
+
 	return success;
 }
 
@@ -514,19 +574,25 @@
 	runqueue_t *rq = task_rq_lock(current, &flags);
 
 	p->state = TASK_RUNNING;
-	if (!rt_task(p)) {
-		/*
-		 * We decrease the sleep average of forking parents
-		 * and children as well, to keep max-interactive tasks
-		 * from forking tasks that are max-interactive.
-		 */
-		current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100;
-		p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100;
-		p->prio = effective_prio(p);
-	}
+	/*
+	 * We decrease the sleep average of forking parents
+	 * and children as well, to keep max-interactive tasks
+	 * from forking tasks that are max-interactive.
+	 */
+	current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100;
+	p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100;
+	p->prio = effective_prio(p);
 	set_task_cpu(p, smp_processor_id());
-	activate_task(p, rq);
 
+	if (unlikely(!current->array))
+		__activate_task(p, rq);
+	else {
+		p->prio = current->prio;
+		list_add_tail(&p->run_list, &current->run_list);
+		p->array = current->array;
+		p->array->nr_active++;
+		nr_running_inc(rq);
+	}
 	task_rq_unlock(rq, &flags);
 }
 
@@ -780,7 +846,7 @@
 }
 
 /*
- * Find the busiest node. All previous node loads contribute with a 
+ * Find the busiest node. All previous node loads contribute with a
  * geometrically deccaying weight to the load measure:
  *      load_{t} = load_{t-1}/2 + nr_node_running_{t}
  * This way sudden load peaks are flattened out a bit.
@@ -788,7 +854,7 @@
 static int find_busiest_node(int this_node)
 {
 	int i, node = -1, load, this_load, maxload;
-	
+
 	this_load = maxload = (this_rq()->prev_node_load[this_node] >> 1)
 		+ atomic_read(&node_nr_running[this_node]);
 	this_rq()->prev_node_load[this_node] = this_load;
@@ -806,29 +872,6 @@
 	return node;
 }
 
-static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq)
-{
-	int this_node = cpu_to_node(this_cpu);
-	/*
-	 * Avoid rebalancing between nodes too often.
-	 * We rebalance globally once every NODE_BALANCE_RATE load balances.
-	 */
-	if (++(this_rq->nr_balanced) == NODE_BALANCE_RATE) {
-		int node = find_busiest_node(this_node);
-		this_rq->nr_balanced = 0;
-		if (node >= 0)
-			return (node_to_cpumask(node) | (1UL << this_cpu));
-	}
-	return node_to_cpumask(this_node);
-}
-
-#else /* !CONFIG_NUMA */
-
-static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq)
-{
-	return cpu_online_map;
-}
-
 #endif /* CONFIG_NUMA */
 
 #if CONFIG_SMP
@@ -848,10 +891,10 @@
 			spin_lock(&busiest->lock);
 			spin_lock(&this_rq->lock);
 			/* Need to recalculate nr_running */
-			if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+			if (idle || (this_rq->nr_running > this_rq->prev_cpu_load[this_cpu]))
 				nr_running = this_rq->nr_running;
 			else
-				nr_running = this_rq->prev_nr_running[this_cpu];
+				nr_running = this_rq->prev_cpu_load[this_cpu];
 		} else
 			spin_lock(&busiest->lock);
 	}
@@ -888,10 +931,10 @@
 	 * that case we are less picky about moving a task across CPUs and
 	 * take what can be taken.
 	 */
-	if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+	if (idle || (this_rq->nr_running > this_rq->prev_cpu_load[this_cpu]))
 		nr_running = this_rq->nr_running;
 	else
-		nr_running = this_rq->prev_nr_running[this_cpu];
+		nr_running = this_rq->prev_cpu_load[this_cpu];
 
 	busiest = NULL;
 	max_load = 1;
@@ -900,11 +943,11 @@
 			continue;
 
 		rq_src = cpu_rq(i);
-		if (idle || (rq_src->nr_running < this_rq->prev_nr_running[i]))
+		if (idle || (rq_src->nr_running < this_rq->prev_cpu_load[i]))
 			load = rq_src->nr_running;
 		else
-			load = this_rq->prev_nr_running[i];
-		this_rq->prev_nr_running[i] = rq_src->nr_running;
+			load = this_rq->prev_cpu_load[i];
+		this_rq->prev_cpu_load[i] = rq_src->nr_running;
 
 		if ((load > max_load) && (rq_src != this_rq)) {
 			busiest = rq_src;
@@ -953,6 +996,11 @@
 	 */
 	if (p->prio < this_rq->curr->prio)
 		set_need_resched();
+	else {
+		if (p->prio == this_rq->curr->prio &&
+				p->time_slice > this_rq->curr->time_slice)
+			set_need_resched();
+	}
 }
 
 /*
@@ -963,7 +1011,7 @@
  * We call this with the current runqueue locked,
  * irqs disabled.
  */
-static void load_balance(runqueue_t *this_rq, int idle)
+static void load_balance(runqueue_t *this_rq, int idle, unsigned long cpumask)
 {
 	int imbalance, idx, this_cpu = smp_processor_id();
 	runqueue_t *busiest;
@@ -971,8 +1019,7 @@
 	struct list_head *head, *curr;
 	task_t *tmp;
 
-	busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance,
-					cpus_to_balance(this_cpu, this_rq));
+	busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance, cpumask);
 	if (!busiest)
 		goto out;
 
@@ -1016,7 +1063,7 @@
 	 */
 
 #define CAN_MIGRATE_TASK(p,rq,this_cpu)					\
-	((jiffies - (p)->sleep_timestamp > cache_decay_ticks) &&	\
+	((jiffies - (p)->last_run > cache_decay_ticks) &&	\
 		!task_running(rq, p) &&					\
 			((p)->cpus_allowed & (1UL << (this_cpu))))
 
@@ -1047,21 +1094,75 @@
  * frequency and balancing agressivity depends on whether the CPU is
  * idle or not.
  *
- * busy-rebalance every 250 msecs. idle-rebalance every 1 msec. (or on
+ * busy-rebalance every 200 msecs. idle-rebalance every 1 msec. (or on
  * systems with HZ=100, every 10 msecs.)
+ *
+ * On NUMA, do a node-rebalance every 400 msecs.
  */
-#define BUSY_REBALANCE_TICK (HZ/4 ?: 1)
 #define IDLE_REBALANCE_TICK (HZ/1000 ?: 1)
+#define BUSY_REBALANCE_TICK (HZ/5 ?: 1)
+#define IDLE_NODE_REBALANCE_TICK (IDLE_REBALANCE_TICK * 5)
+#define BUSY_NODE_REBALANCE_TICK (BUSY_REBALANCE_TICK * 100)
 
-static inline void idle_tick(runqueue_t *rq)
+#if CONFIG_NUMA
+static void balance_node(runqueue_t *this_rq, int idle, int this_cpu)
 {
-	if (jiffies % IDLE_REBALANCE_TICK)
-		return;
-	spin_lock(&rq->lock);
-	load_balance(rq, 1);
-	spin_unlock(&rq->lock);
+	int node = find_busiest_node(cpu_to_node(this_cpu));
+	unsigned long cpumask, this_cpumask = 1UL << this_cpu;
+
+	if (node >= 0) {
+		cpumask = node_to_cpumask(node) | this_cpumask;
+		spin_lock(&this_rq->lock);
+		load_balance(this_rq, idle, cpumask);
+		spin_unlock(&this_rq->lock);
+	}
 }
+#endif
 
+static void rebalance_tick(runqueue_t *this_rq, int idle)
+{
+#if CONFIG_NUMA
+	int this_cpu = smp_processor_id();
+#endif
+	unsigned long j = jiffies;
+
+	/*
+	 * First do inter-node rebalancing, then intra-node rebalancing,
+	 * if both events happen in the same tick. The inter-node
+	 * rebalancing does not necessarily have to create a perfect
+	 * balance within the node, since we load-balance the most loaded
+	 * node with the current CPU. (ie. other CPUs in the local node
+	 * are not balanced.)
+	 */
+	if (idle) {
+#if CONFIG_NUMA
+		if (!(j % IDLE_NODE_REBALANCE_TICK))
+			balance_node(this_rq, idle, this_cpu);
+#endif
+		if (!(j % IDLE_REBALANCE_TICK)) {
+			spin_lock(&this_rq->lock);
+			load_balance(this_rq, 0, cpu_to_node_mask(this_cpu));
+			spin_unlock(&this_rq->lock);
+		}
+		return;
+	}
+#if CONFIG_NUMA
+	if (!(j % BUSY_NODE_REBALANCE_TICK))
+		balance_node(this_rq, idle, this_cpu);
+#endif
+	if (!(j % BUSY_REBALANCE_TICK)) {
+		spin_lock(&this_rq->lock);
+		load_balance(this_rq, idle, cpu_to_node_mask(this_cpu));
+		spin_unlock(&this_rq->lock);
+	}
+}
+#else
+/*
+ * on UP we do not need to balance between CPUs:
+ */
+static inline void rebalance_tick(runqueue_t *this_rq, int idle)
+{
+}
 #endif
 
 DEFINE_PER_CPU(struct kernel_stat, kstat) = { { 0 } };
@@ -1076,9 +1177,9 @@
  * increasing number of running tasks:
  */
 #define EXPIRED_STARVING(rq) \
-		((rq)->expired_timestamp && \
+		(STARVATION_LIMIT && ((rq)->expired_timestamp && \
 		(jiffies - (rq)->expired_timestamp >= \
-			STARVATION_LIMIT * ((rq)->nr_running) + 1))
+			STARVATION_LIMIT * ((rq)->nr_running) + 1)))
 
 /*
  * This function gets called by the timer code, with HZ frequency.
@@ -1093,8 +1194,8 @@
 	runqueue_t *rq = this_rq();
 	task_t *p = current;
 
- 	if (rcu_pending(cpu))
- 		rcu_check_callbacks(cpu, user_ticks);
+	if (rcu_pending(cpu))
+		rcu_check_callbacks(cpu, user_ticks);
 
 	if (p == rq->idle) {
 		/* note: this timer irq context must be accounted for as well */
@@ -1104,9 +1205,7 @@
 			kstat_cpu(cpu).cpustat.iowait += sys_ticks;
 		else
 			kstat_cpu(cpu).cpustat.idle += sys_ticks;
-#if CONFIG_SMP
-		idle_tick(rq);
-#endif
+		rebalance_tick(rq, 1);
 		return;
 	}
 	if (TASK_NICE(p) > 0)
@@ -1121,6 +1220,16 @@
 		return;
 	}
 	spin_lock(&rq->lock);
+	/*
+	 * The task was running during this tick - update the
+	 * time slice counter and the sleep average. Note: we
+	 * do not update a thread's priority until it either
+	 * goes to sleep or uses up its timeslice. This makes
+	 * it possible for interactive tasks to use up their
+	 * timeslices at their highest priority levels.
+	 */
+	if (p->sleep_avg)
+		p->sleep_avg--;
 	if (unlikely(rt_task(p))) {
 		/*
 		 * RR tasks need a special form of timeslice management.
@@ -1137,16 +1246,6 @@
 		}
 		goto out;
 	}
-	/*
-	 * The task was running during this tick - update the
-	 * time slice counter and the sleep average. Note: we
-	 * do not update a thread's priority until it either
-	 * goes to sleep or uses up its timeslice. This makes
-	 * it possible for interactive tasks to use up their
-	 * timeslices at their highest priority levels.
-	 */
-	if (p->sleep_avg)
-		p->sleep_avg--;
 	if (!--p->time_slice) {
 		dequeue_task(p, rq->active);
 		set_tsk_need_resched(p);
@@ -1162,11 +1261,8 @@
 			enqueue_task(p, rq->active);
 	}
 out:
-#if CONFIG_SMP
-	if (!(jiffies % BUSY_REBALANCE_TICK))
-		load_balance(rq, 0);
-#endif
 	spin_unlock(&rq->lock);
+	rebalance_tick(rq, 0);
 }
 
 void scheduling_functions_start_here(void) { }
@@ -1201,7 +1297,7 @@
 	rq = this_rq();
 
 	release_kernel_lock(prev);
-	prev->sleep_timestamp = jiffies;
+	prev->last_run = jiffies;
 	spin_lock_irq(&rq->lock);
 
 	/*
@@ -1225,7 +1321,7 @@
 pick_next_task:
 	if (unlikely(!rq->nr_running)) {
 #if CONFIG_SMP
-		load_balance(rq, 1);
+		load_balance(rq, 1, cpu_to_node_mask(smp_processor_id()));
 		if (rq->nr_running)
 			goto pick_next_task;
 #endif
@@ -1257,7 +1353,7 @@
 	if (likely(prev != next)) {
 		rq->nr_switches++;
 		rq->curr = next;
-	
+
 		prepare_arch_switch(rq, next);
 		prev = context_switch(rq, prev, next);
 		barrier();
@@ -1387,7 +1483,7 @@
 }
 
 #endif
- 
+
 void complete(struct completion *x)
 {
 	unsigned long flags;
@@ -1471,7 +1567,7 @@
 void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
-	
+
 	current->state = TASK_UNINTERRUPTIBLE;
 
 	SLEEP_ON_HEAD
@@ -1482,7 +1578,7 @@
 long sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
-	
+
 	current->state = TASK_UNINTERRUPTIBLE;
 
 	SLEEP_ON_HEAD
@@ -1701,7 +1797,7 @@
 	else
 		p->prio = p->static_prio;
 	if (array)
-		activate_task(p, task_rq(p));
+		__activate_task(p, task_rq(p));
 
 out_unlock:
 	task_rq_unlock(rq, &flags);
@@ -2315,7 +2411,7 @@
 			set_task_cpu(p, cpu_dest);
 			if (p->array) {
 				deactivate_task(p, rq_src);
-				activate_task(p, rq_dest);
+				__activate_task(p, rq_dest);
 				if (p->prio < rq_dest->curr->prio)
 					resched_task(rq_dest->curr);
 			}
@@ -2376,12 +2472,12 @@
 
 static void kstat_init_cpu(int cpu)
 {
-        /* Add any initialisation to kstat here */
-        /* Useful when cpu offlining logic is added.. */
+	/* Add any initialisation to kstat here */
+	/* Useful when cpu offlining logic is added.. */
 }
 
 static int __devinit kstat_cpu_notify(struct notifier_block *self,
-                                unsigned long action, void *hcpu)
+					unsigned long action, void *hcpu)
 {
 	int cpu = (unsigned long)hcpu;
 	switch(action) {
@@ -2393,7 +2489,7 @@
 	}
 	return NOTIFY_OK;
 }
- 
+
 static struct notifier_block __devinitdata kstat_nb = {
 	.notifier_call  = kstat_cpu_notify,
 	.next           = NULL,
@@ -2402,7 +2498,7 @@
 __init static void init_kstat(void) {
 	kstat_cpu_notify(&kstat_nb, (unsigned long)CPU_UP_PREPARE,
 			(void *)(long)smp_processor_id());
-	register_cpu_notifier(&kstat_nb);  
+	register_cpu_notifier(&kstat_nb);
 }
 
 void __init sched_init(void)
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	Tue Feb 11 14:57:54 2003
+++ b/kernel/softirq.c	Fri Mar  7 02:39:07 2003
@@ -92,10 +92,9 @@
 			mask &= ~pending;
 			goto restart;
 		}
-		__local_bh_enable();
-
 		if (pending)
 			wakeup_softirqd(cpu);
+		__local_bh_enable();
 	}
 
 	local_irq_restore(flags);
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Mon Feb 24 23:13:10 2003
+++ b/kernel/sys.c	Mon Mar 10 10:49:27 2003
@@ -212,18 +212,25 @@
 
 static int set_one_prio(struct task_struct *p, int niceval, int error)
 {
+	int no_nice;
+
 	if (p->uid != current->euid &&
 		p->uid != current->uid && !capable(CAP_SYS_NICE)) {
 		error = -EPERM;
 		goto out;
 	}
-
+	if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) {
+		error = -EACCES;
+		goto out;
+	}
+	no_nice = security_task_setnice(p, niceval);
+	if (no_nice) {
+		error = no_nice;
+		goto out;
+	}
 	if (error == -ESRCH)
 		error = 0;
-	if (niceval < task_nice(p) && !capable(CAP_SYS_NICE))
-		error = -EACCES;
-	else
-		set_user_nice(p, niceval);
+	set_user_nice(p, niceval);
 out:
 	return error;
 }
@@ -941,6 +948,10 @@
 	}
 
 ok_pgid:
+	err = security_task_setpgid(p, pgid);
+	if (err)
+		goto out;
+
 	if (p->pgrp != pgid) {
 		detach_pid(p, PIDTYPE_PGID);
 		p->pgrp = pgid;
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Thu Dec  5 08:06:54 2002
+++ b/kernel/sysctl.c	Fri Jan 17 06:49:15 2003
@@ -33,6 +33,7 @@
 #include <linux/highuid.h>
 #include <linux/writeback.h>
 #include <linux/hugetlb.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_ROOT_NFS
@@ -432,6 +433,10 @@
 
 static inline int ctl_perm(ctl_table *table, int op)
 {
+	int error;
+	error = security_sysctl(table, op);
+	if (error)
+		return error;
 	return test_perm(table->mode, op);
 }
 
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Mon Feb 24 23:13:14 2003
+++ b/mm/filemap.c	Sat Mar  8 14:50:29 2003
@@ -562,7 +562,7 @@
 find_page:
 		page = find_get_page(mapping, index);
 		if (unlikely(page == NULL)) {
-			handle_ra_miss(mapping, ra);
+			handle_ra_miss(mapping, ra, index);
 			goto no_cached_page;
 		}
 		if (!PageUptodate(page))
@@ -978,7 +978,7 @@
 	page = find_get_page(mapping, pgoff);
 	if (!page) {
 		if (did_readahead) {
-			handle_ra_miss(mapping,ra);
+			handle_ra_miss(mapping, ra, pgoff);
 			did_readahead = 0;
 		}
 		goto no_cached_page;
diff -Nru a/mm/fremap.c b/mm/fremap.c
--- a/mm/fremap.c	Wed Feb  5 20:05:09 2003
+++ b/mm/fremap.c	Thu Feb 20 08:38:13 2003
@@ -1,5 +1,5 @@
 /*
- *   linux/mm/mpopulate.c
+ *   linux/mm/fremap.c
  * 
  * Explicit pagetable population and nonlinear (random) mappings support.
  *
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Mon Feb 24 23:13:16 2003
+++ b/mm/memory.c	Sun Mar 16 22:33:14 2003
@@ -286,9 +286,16 @@
 					goto cont_copy_pte_range_noset;
 				}
 				pfn = pte_pfn(pte);
+				/* the pte points outside of valid memory, the
+				 * mapping is assumed to be good, meaningful
+				 * and not mapped via rmap - duplicate the
+				 * mapping as is.
+				 */
+				if (!pfn_valid(pfn)) {
+					set_pte(dst_pte, pte);
+					goto cont_copy_pte_range_noset;
+				}
 				page = pfn_to_page(pfn);
-				if (!pfn_valid(pfn))
-					goto cont_copy_pte_range;
 				if (PageReserved(page))
 					goto cont_copy_pte_range;
 
@@ -537,7 +544,12 @@
 
 		ret++;
 		while (start != end) {
-			unsigned long block = min(zap_bytes, end - start);
+			unsigned long block;
+
+			if (is_vm_hugetlb_page(vma))
+				block = end - start;
+			else
+				block = min(zap_bytes, end - start);
 
 			if (!tlb_start_valid) {
 				tlb_start = start;
@@ -547,7 +559,7 @@
 			unmap_page_range(*tlbp, vma, start, start + block);
 			start += block;
 			zap_bytes -= block;
-			if (zap_bytes != 0)
+			if ((long)zap_bytes > 0)
 				continue;
 			if (need_resched()) {
 				tlb_finish_mmu(*tlbp, tlb_start, start);
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Sun Mar  2 18:14:37 2003
+++ b/mm/mmap.c	Sat Mar  8 14:50:32 2003
@@ -1258,20 +1258,24 @@
  
 	/*
 	 * If we need to split any vma, do it now to save pain later.
+	 *
+	 * Note: mremap's move_vma VM_ACCOUNT handling assumes a partially
+	 * unmapped vm_area_struct will remain in use: so lower split_vma
+	 * places tmp vma above, and higher split_vma places tmp vma below.
 	 */
 	if (start > mpnt->vm_start) {
 		if (split_vma(mm, mpnt, start, 0))
 			return -ENOMEM;
 		prev = mpnt;
-		mpnt = mpnt->vm_next;
 	}
 
 	/* Does it split the last one? */
 	last = find_vma(mm, end);
 	if (last && end > last->vm_start) {
-		if (split_vma(mm, last, end, 0))
+		if (split_vma(mm, last, end, 1))
 			return -ENOMEM;
 	}
+	mpnt = prev? prev->vm_next: mm->mmap;
 
 	/*
 	 * Remove the vma's, and unmap the actual pages
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	Wed Feb  5 20:05:32 2003
+++ b/mm/mremap.c	Thu Feb 20 08:37:02 2003
@@ -1,5 +1,5 @@
 /*
- *	mm/remap.c
+ *	mm/mremap.c
  *
  *	(C) Copyright 1996 Linus Torvalds
  *
diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c
--- a/mm/page-writeback.c	Fri Feb 14 18:24:05 2003
+++ b/mm/page-writeback.c	Sun Mar 16 22:33:14 2003
@@ -139,6 +139,9 @@
 	struct page_state ps;
 	long background_thresh;
 	long dirty_thresh;
+	unsigned long pages_written = 0;
+	unsigned long write_chunk = sync_writeback_pages();
+
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 
 	get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
@@ -147,7 +150,7 @@
 			.bdi		= bdi,
 			.sync_mode	= WB_SYNC_NONE,
 			.older_than_this = NULL,
-			.nr_to_write	= sync_writeback_pages(),
+			.nr_to_write	= write_chunk,
 		};
 
 		dirty_exceeded = 1;
@@ -158,10 +161,14 @@
 		get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
 		if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
 			break;
+		pages_written += write_chunk - wbc.nr_to_write;
+		if (pages_written >= write_chunk)
+			break;		/* We've done our duty */
 		blk_congestion_wait(WRITE, HZ/10);
 	}
 
-	dirty_exceeded = 0;
+	if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
+		dirty_exceeded = 0;
 
 	if (!writeback_in_progress(bdi) && ps.nr_dirty > background_thresh)
 		pdflush_operation(background_writeout, 0);
@@ -362,7 +369,7 @@
  * dirty memory thresholds: allowing too much dirty highmem pins an excessive
  * number of buffer_heads.
  */
-static int __init page_writeback_init(void)
+void __init page_writeback_init(void)
 {
 	long buffer_pages = nr_free_buffer_pages();
 	long correction;
@@ -385,9 +392,7 @@
 	add_timer(&wb_timer);
 	set_ratelimit();
 	register_cpu_notifier(&ratelimit_nb);
-	return 0;
 }
-module_init(page_writeback_init);
 
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
diff -Nru a/mm/pdflush.c b/mm/pdflush.c
--- a/mm/pdflush.c	Fri Feb 21 01:41:33 2003
+++ b/mm/pdflush.c	Mon Mar 10 22:34:08 2003
@@ -106,6 +106,7 @@
 		schedule();
 		if (current->flags & PF_FREEZE) {
 			refrigerator(PF_IOTHREAD);
+			spin_lock_irq(&pdflush_lock);
 			continue;
 		}
 
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	Wed Feb  5 20:04:19 2003
+++ b/mm/readahead.c	Sat Mar  8 14:50:29 2003
@@ -136,6 +136,12 @@
  * ahead_size:  Together, these form the "ahead window".
  * ra_pages:	The externally controlled max readahead for this fd.
  *
+ * When readahead is in the "maximally shrunk" state (next_size == -1UL),
+ * readahead is disabled.  In this state, prev_page and size are used, inside
+ * handle_ra_miss(), to detect the resumption of sequential I/O.  Once there
+ * has been a decent run of sequential I/O (defined by get_min_readahead),
+ * readahead is reenabled.
+ *
  * The readahead code manages two windows - the "current" and the "ahead"
  * windows.  The intent is that while the application is walking the pages
  * in the current window, I/O is underway on the ahead window.  When the
@@ -168,6 +174,8 @@
  * will continue to perform linear reads.  Either at the new file position, or
  * at the old one after another seek.
  *
+ * After enough misses, readahead is fully disabled. (next_size = -1UL).
+ *
  * There is a special-case: if the first page which the application tries to
  * read happens to be the first page of the file, it is assumed that a linear
  * read is about to happen and the window is immediately set to half of the
@@ -253,14 +261,19 @@
 	int ret = 0;
 
 	while (nr_to_read) {
+		int err;
+
 		unsigned long this_chunk = (2 * 1024 * 1024) / PAGE_CACHE_SIZE;
 
 		if (this_chunk > nr_to_read)
 			this_chunk = nr_to_read;
-		ret = __do_page_cache_readahead(mapping, filp,
+		err = __do_page_cache_readahead(mapping, filp,
 						offset, this_chunk);
-		if (ret < 0)
+		if (err < 0) {
+			ret = err;
 			break;
+		}
+		ret += err;
 		offset += this_chunk;
 		nr_to_read -= this_chunk;
 	}
@@ -286,6 +299,7 @@
 				ra->ahead_size = ra->next_size;
 		} else {
 			ra->next_size = -1UL;
+			ra->size = 0;
 		}
 	}
 }
@@ -345,16 +359,19 @@
 		ra->next_size += 2;
 	} else {
 		/*
-		 * A miss - lseek, pread, etc.  Shrink the readahead
+		 * A miss - lseek, pagefault, pread, etc.  Shrink the readahead
 		 * window by 25%.
 		 */
-		ra->next_size -= ra->next_size / 4;
+		ra->next_size -= ra->next_size / 4 + 2;
 	}
 
-	if (ra->next_size > max)
+	if ((long)ra->next_size > (long)max)
 		ra->next_size = max;
-	if (ra->next_size < min)
-		ra->next_size = min;
+	if ((long)ra->next_size <= 0L) {
+		ra->next_size = -1UL;
+		ra->size = 0;
+		goto out;		/* Readahead is off */
+	}
 
 	/*
 	 * Is this request outside the current window?
@@ -374,6 +391,7 @@
 			ra->prev_page = ra->start;
 			ra->ahead_start = 0;
 			ra->ahead_size = 0;
+
 			/*
 			 * Control now returns, probably to sleep until I/O
 			 * completes against the first ahead page.
@@ -394,7 +412,6 @@
 		ra->size = ra->next_size;
 		ra->ahead_start = 0;		/* Invalidate these */
 		ra->ahead_size = 0;
-
 		actual = do_page_cache_readahead(mapping, filp, offset,
 						 ra->size);
 		check_ra_success(ra, ra->size, actual, orig_next_size);
@@ -455,21 +472,37 @@
  * not found.  This will happen if it was evicted by the VM (readahead
  * thrashing) or if the readahead window is maximally shrunk.
  *
- * If the window has been maximally shrunk (next_size == 0) then bump it up
- * again to resume readahead.
+ * If the window has been maximally shrunk (next_size == -1UL) then look to see
+ * if we are getting misses against sequential file offsets.  If so, and this
+ * persists then resume readahead.
  *
  * Otherwise we're thrashing, so shrink the readahead window by three pages.
  * This is because it is grown by two pages on a readahead hit.  Theory being
  * that the readahead window size will stabilise around the maximum level at
  * which there is no thrashing.
  */
-void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra)
+void handle_ra_miss(struct address_space *mapping,
+		struct file_ra_state *ra, pgoff_t offset)
 {
-	const unsigned long min = get_min_readahead(ra);
-
 	if (ra->next_size == -1UL) {
-		ra->next_size = min;
+		const unsigned long max = get_max_readahead(ra);
+
+		if (offset != ra->prev_page + 1) {
+			ra->size = 0;			/* Not sequential */
+		} else {
+			ra->size++;			/* A sequential read */
+			if (ra->size >= max) {		/* Resume readahead */
+				ra->start = offset - max;
+				ra->next_size = max;
+				ra->size = max;
+				ra->ahead_start = 0;
+				ra->ahead_size = 0;
+			}
+		}
+		ra->prev_page = offset;
 	} else {
+		const unsigned long min = get_min_readahead(ra);
+
 		ra->next_size -= 3;
 		if (ra->next_size < min)
 			ra->next_size = min;
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Sun Mar  2 18:13:32 2003
+++ b/mm/slab.c	Tue Mar 11 07:15:44 2003
@@ -82,6 +82,7 @@
 #include	<linux/compiler.h>
 #include	<linux/seq_file.h>
 #include	<linux/notifier.h>
+#include	<linux/kallsyms.h>
 #include	<asm/uaccess.h>
 
 /*
@@ -114,7 +115,7 @@
 # define CREATE_MASK	(SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
 			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
 			 SLAB_NO_REAP | SLAB_CACHE_DMA | \
-			 SLAB_MUST_HWCACHE_ALIGN)
+			 SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER)
 #else
 # define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
 			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN)
@@ -280,9 +281,7 @@
 #endif
 };
 
-/* internal c_flags */
-#define	CFLGS_OFF_SLAB	0x010000UL	/* slab management in own cache */
-
+#define CFLGS_OFF_SLAB		(0x80000000UL)
 #define	OFF_SLAB(x)	((x)->flags & CFLGS_OFF_SLAB)
 
 #define BATCHREFILL_LIMIT	16
@@ -764,10 +763,28 @@
 		addr += BYTES_PER_WORD;
 		size -= 2*BYTES_PER_WORD;
 	}
+	if (cachep->flags & SLAB_STORE_USER) {
+		size -= BYTES_PER_WORD;
+	}
 	memset(addr, val, size);
 	*(unsigned char *)(addr+size-1) = POISON_END;
 }
 
+static void *fprob(unsigned char* addr, unsigned int size)
+{
+	unsigned char *end;
+	
+	end = addr + size - 1;
+
+	for (; addr < end; addr++) {
+		if (*addr != POISON_BEFORE && *addr != POISON_AFTER)
+			return addr;
+	}
+	if (*addr != POISON_END)
+		return addr;
+	return NULL;
+}
+
 static void check_poison_obj(kmem_cache_t *cachep, void *addr)
 {
 	int size = cachep->objsize;
@@ -776,9 +793,47 @@
 		addr += BYTES_PER_WORD;
 		size -= 2*BYTES_PER_WORD;
 	}
-	end = memchr(addr, POISON_END, size);
-	if (end != (addr+size-1))
+	if (cachep->flags & SLAB_STORE_USER) {
+		size -= BYTES_PER_WORD;
+	}
+	end = fprob(addr, size);
+	if (end) {
+		int s;
+		printk(KERN_ERR "Slab corruption: start=%p, expend=%p, "
+				"problemat=%p\n", addr, addr+size-1, end);
+		if (cachep->flags & SLAB_STORE_USER) {
+			void *pc;
+
+			if (cachep->flags & SLAB_RED_ZONE)
+				pc = *(void**)(addr+size+BYTES_PER_WORD);
+			else
+				pc = *(void**)(addr+size);
+			printk(KERN_ERR "Last user: [<%p>]", pc);
+			print_symbol("(%s)", (unsigned long)pc);
+			printk("\n");
+		}
+		printk(KERN_ERR "Data: ");
+		for (s = 0; s < size; s++) {
+			if (((char*)addr)[s] == POISON_BEFORE)
+				printk(".");
+			else if (((char*)addr)[s] == POISON_AFTER)
+				printk("*");
+			else
+				printk("%02X ", ((unsigned char*)addr)[s]);
+		}
+		printk("\n");
+		printk(KERN_ERR "Next: ");
+		for (; s < size + 32; s++) {
+			if (((char*)addr)[s] == POISON_BEFORE)
+				printk(".");
+			else if (((char*)addr)[s] == POISON_AFTER)
+				printk("*");
+			else
+				printk("%02X ", ((unsigned char*)addr)[s]);
+		}
+		printk("\n");
 		slab_error(cachep, "object was modified after freeing");
+	}
 }
 #endif
 
@@ -792,16 +847,19 @@
 	int i;
 	for (i = 0; i < cachep->num; i++) {
 		void *objp = slabp->s_mem + cachep->objsize * i;
+		int objlen = cachep->objsize;
 
 		if (cachep->flags & SLAB_POISON)
 			check_poison_obj(cachep, objp);
+		if (cachep->flags & SLAB_STORE_USER)
+			objlen -= BYTES_PER_WORD;
 
 		if (cachep->flags & SLAB_RED_ZONE) {
 			if (*((unsigned long*)(objp)) != RED_INACTIVE)
 				slab_error(cachep, "start of a freed object "
 							"was overwritten");
-			if (*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) != RED_INACTIVE)
+			if (*((unsigned long*)(objp + objlen - BYTES_PER_WORD))
+				       	!= RED_INACTIVE)
 				slab_error(cachep, "end of a freed object "
 							"was overwritten");
 			objp += BYTES_PER_WORD;
@@ -890,7 +948,7 @@
 		 * do not red zone large object, causes severe
 		 * fragmentation.
 		 */
-		flags |= SLAB_RED_ZONE;
+		flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
 	flags |= SLAB_POISON;
 #endif
 #endif
@@ -927,6 +985,10 @@
 		flags &= ~SLAB_HWCACHE_ALIGN;
 		size += 2*BYTES_PER_WORD;	/* words for redzone */
 	}
+	if (flags & SLAB_STORE_USER) {
+		flags &= ~SLAB_HWCACHE_ALIGN;
+		size += BYTES_PER_WORD;		/* word for kfree caller address */
+	}
 #endif
 	align = BYTES_PER_WORD;
 	if (flags & SLAB_HWCACHE_ALIGN)
@@ -1283,15 +1345,20 @@
 	for (i = 0; i < cachep->num; i++) {
 		void* objp = slabp->s_mem+cachep->objsize*i;
 #if DEBUG
+		int objlen = cachep->objsize;
 		/* need to poison the objs? */
 		if (cachep->flags & SLAB_POISON)
 			poison_obj(cachep, objp, POISON_BEFORE);
+		if (cachep->flags & SLAB_STORE_USER) {
+			objlen -= BYTES_PER_WORD;
+			((unsigned long*)(objp+objlen))[0] = 0;
+		}
 
 		if (cachep->flags & SLAB_RED_ZONE) {
 			*((unsigned long*)(objp)) = RED_INACTIVE;
-			*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) = RED_INACTIVE;
 			objp += BYTES_PER_WORD;
+			objlen -= 2* BYTES_PER_WORD;
+			*((unsigned long*)(objp + objlen)) = RED_INACTIVE;
 		}
 		/*
 		 * Constructors are not allowed to allocate memory from
@@ -1302,14 +1369,13 @@
 			cachep->ctor(objp, cachep, ctor_flags);
 
 		if (cachep->flags & SLAB_RED_ZONE) {
+			if (*((unsigned long*)(objp + objlen)) != RED_INACTIVE)
+				slab_error(cachep, "constructor overwrote the"
+							" end of an object");
 			objp -= BYTES_PER_WORD;
 			if (*((unsigned long*)(objp)) != RED_INACTIVE)
 				slab_error(cachep, "constructor overwrote the"
 							" start of an object");
-			if (*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) != RED_INACTIVE)
-				slab_error(cachep, "constructor overwrote the"
-							" end of an object");
 		}
 #else
 		if (cachep->ctor)
@@ -1451,11 +1517,12 @@
 #endif 
 }
 
-static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp)
+static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, void *caller)
 {
 #if DEBUG
 	struct page *page;
 	unsigned int objnr;
+	int objlen = cachep->objsize;
 	struct slab *slabp;
 
 	kfree_debugcheck(objp);
@@ -1464,16 +1531,21 @@
 	BUG_ON(GET_PAGE_CACHE(page) != cachep);
 	slabp = GET_PAGE_SLAB(page);
 
+	if (cachep->flags & SLAB_STORE_USER) {
+		objlen -= BYTES_PER_WORD;
+	}
 	if (cachep->flags & SLAB_RED_ZONE) {
 		objp -= BYTES_PER_WORD;
 		if (xchg((unsigned long *)objp, RED_INACTIVE) != RED_ACTIVE)
 			slab_error(cachep, "double free, or memory before"
 						" object was overwritten");
-		if (xchg((unsigned long *)(objp+cachep->objsize -
-				BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE)
+		if (xchg((unsigned long *)(objp+objlen-BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE)
 			slab_error(cachep, "double free, or memory after "
 						" object was overwritten");
 	}
+	if (cachep->flags & SLAB_STORE_USER) {
+		*((void**)(objp+objlen)) = caller;
+	}
 
 	objnr = (objp-slabp->s_mem)/cachep->objsize;
 
@@ -1626,22 +1698,31 @@
 
 static inline void *
 cache_alloc_debugcheck_after(kmem_cache_t *cachep,
-			unsigned long flags, void *objp)
+			unsigned long flags, void *objp, void *caller)
 {
 #if DEBUG
+	int objlen = cachep->objsize;
+
 	if (!objp)	
 		return objp;
 	if (cachep->flags & SLAB_POISON)
 		check_poison_obj(cachep, objp);
+	if (cachep->flags & SLAB_STORE_USER) {
+		objlen -= BYTES_PER_WORD;
+		*((void **)(objp+objlen)) = caller;
+	}
+
 	if (cachep->flags & SLAB_RED_ZONE) {
 		/* Set alloc red-zone, and check old one. */
-		if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE)
+		if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE) {
 			slab_error(cachep, "memory before object was "
 						"overwritten");
-		if (xchg((unsigned long *)(objp+cachep->objsize -
-			  BYTES_PER_WORD), RED_ACTIVE) != RED_INACTIVE)
+		}
+		if (xchg((unsigned long *)(objp+objlen - BYTES_PER_WORD),
+				       	RED_ACTIVE) != RED_INACTIVE) {
 			slab_error(cachep, "memory after object was "
 						"overwritten");
+		}
 		objp += BYTES_PER_WORD;
 	}
 	if (cachep->ctor && cachep->flags & SLAB_POISON) {
@@ -1676,7 +1757,7 @@
 		objp = cache_alloc_refill(cachep, flags);
 	}
 	local_irq_restore(save_flags);
-	objp = cache_alloc_debugcheck_after(cachep, flags, objp);
+	objp = cache_alloc_debugcheck_after(cachep, flags, objp, __builtin_return_address(0));
 	return objp;
 }
 
@@ -1783,7 +1864,7 @@
 	struct array_cache *ac = ac_data(cachep);
 
 	check_irq_off();
-	objp = cache_free_debugcheck(cachep, objp);
+	objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
 	if (likely(ac->avail < ac->limit)) {
 		STATS_INC_FREEHIT(cachep);
@@ -1960,11 +2041,16 @@
 
 unsigned int kmem_cache_size(kmem_cache_t *cachep)
 {
+	unsigned int objlen = cachep->objsize;
+
 #if DEBUG
 	if (cachep->flags & SLAB_RED_ZONE)
-		return (cachep->objsize - 2*BYTES_PER_WORD);
+		objlen -= 2*BYTES_PER_WORD;
+	if (cachep->flags & SLAB_STORE_USER)
+		objlen -= BYTES_PER_WORD;
 #endif
-	return cachep->objsize;
+
+	return objlen;
 }
 
 kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
diff -Nru a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
--- a/net/8021q/vlanproc.c	Sat Aug  3 17:18:02 2002
+++ b/net/8021q/vlanproc.c	Sun Mar  9 14:00:21 2003
@@ -251,8 +251,10 @@
 	offs = file->f_pos;
 	if (offs < pos) {
 		len = min_t(int, pos - offs, count);
-		if (copy_to_user(buf, (page + offs), len))
+		if (copy_to_user(buf, (page + offs), len)) {
+			kfree(page);
 			return -EFAULT;
+		}
 
 		file->f_pos += len;
 	} else {
diff -Nru a/net/Makefile b/net/Makefile
--- a/net/Makefile	Mon Feb  3 14:19:38 2003
+++ b/net/Makefile	Thu Mar  6 11:06:44 2003
@@ -7,6 +7,8 @@
 
 obj-y	:= socket.o core/
 
+obj-$(CONFIG_COMPAT)		+= compat.o
+
 # LLC has to be linked before the files in net/802/
 obj-$(CONFIG_LLC)		+= llc/
 obj-$(CONFIG_NET)		+= ethernet/ 802/ sched/ netlink/
diff -Nru a/net/appletalk/ddp.c b/net/appletalk/ddp.c
--- a/net/appletalk/ddp.c	Fri Oct 11 19:45:27 2002
+++ b/net/appletalk/ddp.c	Thu Mar  6 11:06:44 2003
@@ -190,7 +190,7 @@
 	struct sock *sk = (struct sock *)data;
 
 	if (!atomic_read(&sk->wmem_alloc) &&
-	    !atomic_read(&sk->rmem_alloc) && sk->dead) {
+	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) {
 		sock_put(sk);
 		MOD_DEC_USE_COUNT;
 	} else {
@@ -205,7 +205,7 @@
 	skb_queue_purge(&sk->receive_queue);
 
 	if (!atomic_read(&sk->wmem_alloc) &&
-	    !atomic_read(&sk->rmem_alloc) && sk->dead) {
+	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) {
 		sock_put(sk);
 		MOD_DEC_USE_COUNT;
 	} else {
@@ -1016,9 +1016,9 @@
 	struct sock *sk = sock->sk;
 
 	if (sk) {
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
-		sk->dead = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
 		sock->sk = NULL;
 		atalk_destroy_socket(sk);
 	}
@@ -1158,7 +1158,8 @@
 	if (addr->sat_family != AF_APPLETALK)
 		return -EAFNOSUPPORT;
 
-	if (addr->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) {
+	if (addr->sat_addr.s_node == ATADDR_BCAST &&
+			!test_bit(SOCK_BROADCAST, &sk->flags)) {
 #if 1	
 		printk(KERN_WARNING "%s is broken and did not set "
 				    "SO_BROADCAST. It will break when 2.2 is "
@@ -1492,7 +1493,7 @@
 }
 
 static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-			 int len, struct scm_cookie *scm)
+			 int len)
 {
 	struct sock *sk = sock->sk;
 	struct atalk_sock *at = at_sk(sk);
@@ -1523,7 +1524,8 @@
 			return -EINVAL;
 
 		/* netatalk doesn't implement this check */
-		if (usat->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) {
+		if (usat->sat_addr.s_node == ATADDR_BCAST &&
+				!test_bit(SOCK_BROADCAST, &sk->flags)) {
 			printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as "
 					 "it will break before 2.2\n");
 #if 0
@@ -1651,7 +1653,7 @@
 }
 
 static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-			 int size, int flags, struct scm_cookie *scm)
+			 int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
diff -Nru a/net/atm/atm_misc.c b/net/atm/atm_misc.c
--- a/net/atm/atm_misc.c	Tue Feb  5 09:40:00 2002
+++ b/net/atm/atm_misc.c	Sat Mar  8 13:09:15 2003
@@ -16,7 +16,7 @@
 int atm_charge(struct atm_vcc *vcc,int truesize)
 {
 	atm_force_charge(vcc,truesize);
-	if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) return 1;
+	if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) return 1;
 	atm_return(vcc,truesize);
 	atomic_inc(&vcc->stats->rx_drop);
 	return 0;
@@ -29,11 +29,11 @@
 	int guess = atm_guess_pdu2truesize(pdu_size);
 
 	atm_force_charge(vcc,guess);
-	if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) {
+	if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) {
 		struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
 
 		if (skb) {
-			atomic_add(skb->truesize-guess,&vcc->rx_inuse);
+			atomic_add(skb->truesize-guess,&vcc->sk->rmem_alloc);
 			return skb;
 		}
 	}
diff -Nru a/net/atm/clip.c b/net/atm/clip.c
--- a/net/atm/clip.c	Fri Oct 11 16:07:30 2002
+++ b/net/atm/clip.c	Sat Mar  8 13:09:15 2003
@@ -63,7 +63,7 @@
 	ctrl->itf_num = itf;
 	ctrl->ip = ip;
 	atm_force_charge(atmarpd,skb->truesize);
-	skb_queue_tail(&atmarpd->recvq,skb);
+	skb_queue_tail(&atmarpd->sk->receive_queue,skb);
 	wake_up(&atmarpd->sleep);
 	return 0;
 }
@@ -426,7 +426,7 @@
 		memcpy(here,llc_oui,sizeof(llc_oui));
 		((u16 *) here)[3] = skb->protocol;
 	}
-	atomic_add(skb->truesize,&vcc->tx_inuse);
+	atomic_add(skb->truesize,&vcc->sk->wmem_alloc);
 	ATM_SKB(skb)->iovcnt = 0;
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 	entry->vccs->last_use = jiffies;
@@ -485,7 +485,7 @@
 	vcc->push = clip_push;
 	vcc->pop = clip_pop;
 	skb_queue_head_init(&copy);
-	skb_migrate(&vcc->recvq,&copy);
+	skb_migrate(&vcc->sk->receive_queue,&copy);
 	/* re-process everything received between connection setup and MKIP */
 	while ((skb = skb_dequeue(&copy)))
 		if (!clip_devs) {
@@ -691,10 +691,10 @@
 	barrier();
 	unregister_inetaddr_notifier(&clip_inet_notifier);
 	unregister_netdevice_notifier(&clip_dev_notifier);
-	if (skb_peek(&vcc->recvq))
+	if (skb_peek(&vcc->sk->receive_queue))
 		printk(KERN_ERR "atmarpd_close: closing with requests "
 		    "pending\n");
-	skb_queue_purge(&vcc->recvq);
+	skb_queue_purge(&vcc->sk->receive_queue);
 	DPRINTK("(done)\n");
 }
 
diff -Nru a/net/atm/common.c b/net/atm/common.c
--- a/net/atm/common.c	Wed Feb 19 23:22:24 2003
+++ b/net/atm/common.c	Sat Mar  8 13:09:15 2003
@@ -85,14 +85,14 @@
 {
 	struct sk_buff *skb;
 
-	if (atomic_read(&vcc->tx_inuse) && !atm_may_send(vcc,size)) {
-		DPRINTK("Sorry: tx_inuse = %d, size = %d, sndbuf = %d\n",
-		    atomic_read(&vcc->tx_inuse),size,vcc->sk->sndbuf);
+	if (atomic_read(&vcc->sk->wmem_alloc) && !atm_may_send(vcc,size)) {
+		DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
+		    atomic_read(&vcc->sk->wmem_alloc),size,vcc->sk->sndbuf);
 		return NULL;
 	}
 	while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
-	DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->tx_inuse),skb->truesize);
-	atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
+	DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->sk->wmem_alloc),skb->truesize);
+	atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
 	return skb;
 }
 
@@ -108,21 +108,19 @@
 	vcc = atm_sk(sk);
 	memset(&vcc->flags,0,sizeof(vcc->flags));
 	vcc->dev = NULL;
-	vcc->family = sock->ops->family;
 	vcc->alloc_tx = alloc_tx;
 	vcc->callback = NULL;
 	memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
 	memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
 	vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
-	atomic_set(&vcc->tx_inuse,0);
-	atomic_set(&vcc->rx_inuse,0);
+	atomic_set(&vcc->sk->wmem_alloc,0);
+	atomic_set(&vcc->sk->rmem_alloc,0);
 	vcc->push = NULL;
 	vcc->pop = NULL;
 	vcc->push_oam = NULL;
 	vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
 	vcc->atm_options = vcc->aal_options = 0;
 	init_waitqueue_head(&vcc->sleep);
-	skb_queue_head_init(&vcc->recvq);
 	skb_queue_head_init(&vcc->listenq);
 	sk->sleep = &vcc->sleep;
 	sock->sk = sk;
@@ -139,7 +137,7 @@
 	if (vcc->dev) {
 		if (vcc->dev->ops->close) vcc->dev->ops->close(vcc);
 		if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */
-		while ((skb = skb_dequeue(&vcc->recvq))) {
+		while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
 			atm_return(vcc,skb->truesize);
 			if (vcc->dev->ops->free_rx_skb)
 				vcc->dev->ops->free_rx_skb(vcc,skb);
@@ -147,10 +145,10 @@
 		}
 		spin_lock (&atm_dev_lock);	
 		fops_put (vcc->dev->ops);
-		if (atomic_read(&vcc->rx_inuse))
+		if (atomic_read(&vcc->sk->rmem_alloc))
 			printk(KERN_WARNING "atm_release_vcc: strange ... "
-			    "rx_inuse == %d after closing\n",
-			    atomic_read(&vcc->rx_inuse));
+			    "rmem_alloc == %d after closing\n",
+			    atomic_read(&vcc->sk->rmem_alloc));
 		bind_vcc(vcc,NULL);
 	} else
 		spin_lock (&atm_dev_lock);	
@@ -305,11 +303,15 @@
 		if (error) return error;
 	}
 	else {
-		struct atm_dev *dev;
+		struct atm_dev *dev = NULL;
+		struct list_head *p;
 
 		spin_lock (&atm_dev_lock);
-		for (dev = atm_devs; dev; dev = dev->next)
+		list_for_each(p, &atm_devs) {
+			dev = list_entry(p, struct atm_dev, dev_list);
 			if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
+			dev = NULL;
+		}
 		spin_unlock (&atm_dev_lock);
 		if (!dev) return -ENODEV;
 	}
@@ -336,7 +338,7 @@
 
 
 int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, int flags, struct scm_cookie *scm)
+		int total_len, int flags)
 {
 	DECLARE_WAITQUEUE(wait,current);
 	struct atm_vcc *vcc;
@@ -354,7 +356,7 @@
 	add_wait_queue(&vcc->sleep,&wait);
 	set_current_state(TASK_INTERRUPTIBLE);
 	error = 1; /* <= 0 is error */
-	while (!(skb = skb_dequeue(&vcc->recvq))) {
+	while (!(skb = skb_dequeue(&vcc->sk->receive_queue))) {
 		if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
 		    test_bit(ATM_VF_CLOSE,&vcc->flags)) {
 			error = vcc->reply;
@@ -385,7 +387,7 @@
 	if (vcc->dev->ops->feedback)
 		vcc->dev->ops->feedback(vcc,skb,(unsigned long) skb->data,
 		    (unsigned long) buff,eff_len);
-	DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->rx_inuse),skb->truesize);
+	DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->sk->rmem_alloc),skb->truesize);
 	atm_return(vcc,skb->truesize);
 	if (ATM_SKB(skb)->iovcnt) { /* @@@ hack */
 		/* iovcnt set, use scatter-gather for receive */
@@ -417,7 +419,7 @@
 
 
 int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, struct scm_cookie *scm)
+		int total_len)
 {
 	DECLARE_WAITQUEUE(wait,current);
 	struct atm_vcc *vcc;
@@ -488,14 +490,14 @@
 	vcc = ATM_SD(sock);
 	poll_wait(file,&vcc->sleep,wait);
 	mask = 0;
-	if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq))
+	if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq))
 		mask |= POLLIN | POLLRDNORM;
 	if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
 	    test_bit(ATM_VF_CLOSE,&vcc->flags))
 		mask |= POLLHUP;
 	if (sock->state != SS_CONNECTING) {
 		if (vcc->qos.txtp.traffic_class != ATM_NONE &&
-		    vcc->qos.txtp.max_sdu+atomic_read(&vcc->tx_inuse)+
+		    vcc->qos.txtp.max_sdu+atomic_read(&vcc->sk->wmem_alloc)+
 		    ATM_PDU_OVHD <= vcc->sk->sndbuf)
 			mask |= POLLOUT | POLLWRNORM;
 	}
@@ -546,6 +548,7 @@
 int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int *tmp_buf, *tmp_p;
 	void *buf;
@@ -562,7 +565,7 @@
 				goto done;
 			}
 			ret_val =  put_user(vcc->sk->sndbuf-
-			    atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
+			    atomic_read(&vcc->sk->wmem_alloc)-ATM_PDU_OVHD,
 			    (int *) arg) ? -EFAULT : 0;
 			goto done;
 		case SIOCINQ:
@@ -573,7 +576,7 @@
 					ret_val = -EINVAL;
 					goto done;
 				}
-				skb = skb_peek(&vcc->recvq);
+				skb = skb_peek(&vcc->sk->receive_queue);
 				ret_val = put_user(skb ? skb->len : 0,(int *) arg)
 				    ? -EFAULT : 0;
 				goto done;
@@ -590,7 +593,7 @@
 				goto done;
 			}
 			size = 0;
-			for (dev = atm_devs; dev; dev = dev->next)
+			list_for_each(p, &atm_devs)
 				size += sizeof(int);
 			if (size > len) {
 				ret_val = -E2BIG;
@@ -602,8 +605,10 @@
 				goto done;
 			}
 			tmp_p = tmp_buf;
-			for (dev = atm_devs; dev; dev = dev->next)
+			list_for_each(p, &atm_devs) {
+				dev = list_entry(p, struct atm_dev, dev_list);
 				*tmp_p++ = dev->number;
+			}
 		        ret_val = ((copy_to_user(buf, tmp_buf, size)) ||
 			    put_user(size, &((struct atm_iobuf *) arg)->length)
 			    ) ? -EFAULT : 0;
@@ -963,7 +968,7 @@
 	if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
 	if (error) return error;
 	if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
-	if (vcc->family == AF_ATMPVC)
+	if (vcc->sk->family == AF_ATMPVC)
 		return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
 	return svc_change_qos(vcc,qos);
 }
diff -Nru a/net/atm/common.h b/net/atm/common.h
--- a/net/atm/common.h	Tue Oct  8 07:02:41 2002
+++ b/net/atm/common.h	Thu Mar  6 11:06:44 2003
@@ -14,9 +14,9 @@
 int atm_release(struct socket *sock);
 int atm_connect(struct socket *sock,int itf,short vpi,int vci);
 int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, int flags, struct scm_cookie *scm);
+		int total_len, int flags);
 int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, struct scm_cookie *scm);
+		int total_len);
 unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait);
 int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg);
 int atm_setsockopt(struct socket *sock,int level,int optname,char *optval,
diff -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	Mon Mar  3 01:16:42 2003
+++ b/net/atm/lec.c	Sat Mar  8 13:09:15 2003
@@ -125,7 +125,7 @@
 
                 priv = (struct lec_priv *)dev->priv;
                 atm_force_charge(priv->lecd, skb2->truesize);
-                skb_queue_tail(&priv->lecd->recvq, skb2);
+                skb_queue_tail(&priv->lecd->sk->receive_queue, skb2);
                 wake_up(&priv->lecd->sleep);
         }
 
@@ -202,7 +202,7 @@
 lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
 {
 	if (atm_may_send(vcc, skb->len)) {
-		atomic_add(skb->truesize, &vcc->tx_inuse);
+		atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
 	        ATM_SKB(skb)->vcc = vcc;
 	        ATM_SKB(skb)->iovcnt = 0;
 	        ATM_SKB(skb)->atm_options = vcc->atm_options;
@@ -399,7 +399,7 @@
         int i;
         char *tmp; /* FIXME */
 
-	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
         mesg = (struct atmlec_msg *)skb->data;
         tmp = skb->data;
         tmp += sizeof(struct atmlec_msg);
@@ -505,7 +505,7 @@
                         skb2->len = sizeof(struct atmlec_msg);
                         memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
                         atm_force_charge(priv->lecd, skb2->truesize);
-                        skb_queue_tail(&priv->lecd->recvq, skb2);
+                        skb_queue_tail(&priv->lecd->sk->receive_queue, skb2);
                         wake_up(&priv->lecd->sleep);
                 }
                 if (f != NULL) br_fdb_put_hook(f);
@@ -534,10 +534,10 @@
         netif_stop_queue(dev);
         lec_arp_destroy(priv);
 
-        if (skb_peek(&vcc->recvq))
+        if (skb_peek(&vcc->sk->receive_queue))
 		printk("%s lec_atm_close: closing with messages pending\n",
                        dev->name);
-        while ((skb = skb_dequeue(&vcc->recvq))) {
+        while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
                 atm_return(vcc, skb->truesize);
 		dev_kfree_skb(skb);
         }
@@ -595,13 +595,13 @@
 		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
 
         atm_force_charge(priv->lecd, skb->truesize);
-	skb_queue_tail(&priv->lecd->recvq, skb);
+	skb_queue_tail(&priv->lecd->sk->receive_queue, skb);
         wake_up(&priv->lecd->sleep);
 
         if (data != NULL) {
                 DPRINTK("lec: about to send %d bytes of data\n", data->len);
                 atm_force_charge(priv->lecd, data->truesize);
-                skb_queue_tail(&priv->lecd->recvq, data);
+                skb_queue_tail(&priv->lecd->sk->receive_queue, data);
                 wake_up(&priv->lecd->sleep);
         }
 
@@ -683,7 +683,7 @@
 #endif /* DUMP_PACKETS > 0 */
         if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
                 DPRINTK("%s: To daemon\n",dev->name);
-                skb_queue_tail(&vcc->recvq, skb);
+                skb_queue_tail(&vcc->sk->receive_queue, skb);
                 wake_up(&vcc->sleep);
         } else { /* Data frame, queue to protocol handlers */
                 unsigned char *dst;
@@ -784,16 +784,20 @@
                 size = sizeof(struct lec_priv);
 #ifdef CONFIG_TR
                 if (is_trdev)
-                        dev_lec[i] = init_trdev(NULL, size);
+                        dev_lec[i] = alloc_trdev(size);
                 else
 #endif
-                dev_lec[i] = init_etherdev(NULL, size);
+                dev_lec[i] = alloc_etherdev(size);
                 if (!dev_lec[i])
                         return -ENOMEM;
+                snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
+                if (register_netdev(dev_lec[i])) {
+                        kfree(dev_lec[i]);
+                        return -EINVAL;
+                }
 
                 priv = dev_lec[i]->priv;
                 priv->is_trdev = is_trdev;
-                sprintf(dev_lec[i]->name, "lec%d", i);
                 lec_init(dev_lec[i]);
         } else {
                 priv = dev_lec[i]->priv;
diff -Nru a/net/atm/mpc.c b/net/atm/mpc.c
--- a/net/atm/mpc.c	Thu Jan 16 11:15:45 2003
+++ b/net/atm/mpc.c	Sat Mar  8 13:09:15 2003
@@ -520,7 +520,7 @@
 		memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
 	}
 
-	atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
+	atomic_add(skb->truesize, &entry->shortcut->sk->wmem_alloc);
 	ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */
 	ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
 	entry->shortcut->send(entry->shortcut, skb);
@@ -665,7 +665,7 @@
 	skb->dev = dev;
 	if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
 		dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
-		skb_queue_tail(&vcc->recvq, skb);           /* Pass control packets to daemon */
+		skb_queue_tail(&vcc->sk->receive_queue, skb);           /* Pass control packets to daemon */
 		wake_up(&vcc->sleep);
 		return;
 	}
@@ -841,7 +841,7 @@
 	mpc->in_ops->destroy_cache(mpc);
 	mpc->eg_ops->destroy_cache(mpc);
 
-	while ( (skb = skb_dequeue(&vcc->recvq)) ){
+	while ( (skb = skb_dequeue(&vcc->sk->receive_queue)) ){
 		atm_return(vcc, skb->truesize);
 		kfree_skb(skb);
 	}
@@ -861,7 +861,7 @@
 	
 	struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
 	struct k_message *mesg = (struct k_message*)skb->data;
-	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
 	
 	if (mpc == NULL) {
 		printk("mpoa: msg_from_mpoad: no mpc found\n");
@@ -938,7 +938,7 @@
 	skb_put(skb, sizeof(struct k_message));
 	memcpy(skb->data, mesg, sizeof(struct k_message));
 	atm_force_charge(mpc->mpoad_vcc, skb->truesize);
-	skb_queue_tail(&mpc->mpoad_vcc->recvq, skb);
+	skb_queue_tail(&mpc->mpoad_vcc->sk->receive_queue, skb);
 	wake_up(&mpc->mpoad_vcc->sleep);
 
 	return 0;
@@ -1215,7 +1215,7 @@
 		purge_msg->content.eg_info = entry->ctrl_info;
 
 	atm_force_charge(vcc, skb->truesize);
-	skb_queue_tail(&vcc->recvq, skb);
+	skb_queue_tail(&vcc->sk->receive_queue, skb);
 	wake_up(&vcc->sleep);
 	dprintk("mpoa: purge_egress_shortcut: exiting:\n");
 
diff -Nru a/net/atm/proc.c b/net/atm/proc.c
--- a/net/atm/proc.c	Thu Nov 21 10:05:26 2002
+++ b/net/atm/proc.c	Sat Mar  8 13:09:15 2003
@@ -135,7 +135,7 @@
 	unsigned char *ip;
 	int svc,off,ip_len;
 
-	svc = !clip_vcc || clip_vcc->vcc->family == AF_ATMSVC;
+	svc = !clip_vcc || clip_vcc->vcc->sk->family == AF_ATMSVC;
 	off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC",
 	    !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
 	    (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/
@@ -210,7 +210,7 @@
 	if (!vcc->dev) here += sprintf(here,"Unassigned    ");
 	else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,
 		    vcc->vci);
-	switch (vcc->family) {
+	switch (vcc->sk->family) {
 		case AF_ATMPVC:
 			here += sprintf(here,"PVC");
 			break;
@@ -218,12 +218,12 @@
 			here += sprintf(here,"SVC");
 			break;
 		default:
-			here += sprintf(here,"%3d",vcc->family);
+			here += sprintf(here,"%3d",vcc->sk->family);
 	}
 	here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags,
 	    vcc->reply,
-	    atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf,
-	    atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf);
+	    atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf,
+	    atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf);
 }
 
 
@@ -303,6 +303,7 @@
 static int atm_devices_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	int left;
 
 	if (!pos) {
@@ -310,10 +311,14 @@
 		    "AAL(TX,err,RX,err,drop) ...\n");
 	}
 	left = pos-1;
-	for (dev = atm_devs; dev && left; dev = dev->next) left--;
-	if (!dev) return 0;
-	dev_info(dev,buf);
-	return strlen(buf);
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
+		if (left-- == 0) {
+			dev_info(dev,buf);
+			return strlen(buf);
+		}
+	}
+	return 0;
 }
 
 /*
@@ -324,6 +329,7 @@
 static int atm_pvc_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int left;
 
@@ -332,13 +338,15 @@
 		    "TX(PCR,Class)\n");
 	}
 	left = pos-1;
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
-			if (vcc->family == PF_ATMPVC &&
+			if (vcc->sk->family == PF_ATMPVC &&
 			    vcc->dev && !left--) {
 				pvc_info(vcc,buf);
 				return strlen(buf);
 			}
+	}
 	return 0;
 }
 
@@ -346,6 +354,7 @@
 static int atm_vc_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int left;
 
@@ -354,12 +363,14 @@
 		    "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
 		    "     Recv buffer\n");
 	left = pos-1;
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
 			if (!left--) {
 				vc_info(vcc,buf);
 				return strlen(buf);
 			}
+	}
 	for (vcc = nodev_vccs; vcc; vcc = vcc->next)
 		if (!left--) {
 			vc_info(vcc,buf);
@@ -373,20 +384,23 @@
 static int atm_svc_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int left;
 
 	if (!pos)
 		return sprintf(buf,"Itf VPI VCI           State      Remote\n");
 	left = pos-1;
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
-			if (vcc->family == PF_ATMSVC && !left--) {
+			if (vcc->sk->family == PF_ATMSVC && !left--) {
 				svc_info(vcc,buf);
 				return strlen(buf);
 			}
+	}
 	for (vcc = nodev_vccs; vcc; vcc = vcc->next)
-		if (vcc->family == PF_ATMSVC && !left--) {
+		if (vcc->sk->family == PF_ATMSVC && !left--) {
 			svc_info(vcc,buf);
 			return strlen(buf);
 		}
diff -Nru a/net/atm/raw.c b/net/atm/raw.c
--- a/net/atm/raw.c	Tue Feb  5 09:40:00 2002
+++ b/net/atm/raw.c	Sat Mar  8 13:09:15 2003
@@ -28,7 +28,7 @@
 void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb)
 {
 	if (skb) {
-		skb_queue_tail(&vcc->recvq,skb);
+		skb_queue_tail(&vcc->sk->receive_queue,skb);
 		wake_up(&vcc->sleep);
 	}
 }
@@ -36,8 +36,8 @@
 
 static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
 {
-	DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize);
-	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
+	DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->sk->wmem_alloc,skb->truesize);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
 	dev_kfree_skb_any(skb);
 	wake_up(&vcc->sleep);
 }
diff -Nru a/net/atm/resources.c b/net/atm/resources.c
--- a/net/atm/resources.c	Sat Jun  8 16:11:04 2002
+++ b/net/atm/resources.c	Sat Mar  8 13:09:15 2003
@@ -26,8 +26,7 @@
 #endif
 
 
-struct atm_dev *atm_devs = NULL;
-static struct atm_dev *last_dev = NULL;
+LIST_HEAD(atm_devs);
 struct atm_vcc *nodev_vccs = NULL;
 extern spinlock_t atm_dev_lock;
 
@@ -43,15 +42,7 @@
 	dev->type = type;
 	dev->signal = ATM_PHY_SIG_UNKNOWN;
 	dev->link_rate = ATM_OC3_PCR;
-	dev->next = NULL;
-
-	dev->prev = last_dev;
-
-	if (atm_devs)
-		last_dev->next = dev;
-	else
-		atm_devs = dev;
-	last_dev = dev;
+	list_add_tail(&dev->dev_list, &atm_devs);
 
 	return dev;
 }
@@ -59,14 +50,7 @@
 /* Caller must hold atm_dev_lock. */
 static void __free_atm_dev(struct atm_dev *dev)
 {
-	if (dev->prev)
-		dev->prev->next = dev->next;
-	else
-		atm_devs = dev->next;
-	if (dev->next)
-		dev->next->prev = dev->prev;
-	else
-		last_dev = dev->prev;
+	list_del(&dev->dev_list);
 	kfree(dev);
 }
 
@@ -74,10 +58,13 @@
 struct atm_dev *atm_find_dev(int number)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		if (dev->ops && dev->number == number)
 			return dev;
+	}
 	return NULL;
 }
 
diff -Nru a/net/atm/resources.h b/net/atm/resources.h
--- a/net/atm/resources.h	Tue Feb  5 09:40:00 2002
+++ b/net/atm/resources.h	Sat Mar  8 13:09:15 2003
@@ -10,7 +10,7 @@
 #include <linux/atmdev.h>
 
 
-extern struct atm_dev *atm_devs;
+extern struct list_head atm_devs;
 extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */
 
 
diff -Nru a/net/atm/signaling.c b/net/atm/signaling.c
--- a/net/atm/signaling.c	Thu Jul 18 23:16:19 2002
+++ b/net/atm/signaling.c	Sat Mar  8 13:09:15 2003
@@ -61,7 +61,7 @@
 	}
 #endif
 	atm_force_charge(sigd,skb->truesize);
-	skb_queue_tail(&sigd->recvq,skb);
+	skb_queue_tail(&sigd->sk->receive_queue,skb);
 	wake_up(&sigd->sleep);
 }
 
@@ -98,7 +98,7 @@
 	struct atm_vcc *session_vcc;
 
 	msg = (struct atmsvc_msg *) skb->data;
-	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
 	DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
 	  (unsigned long) msg->vcc);
 	vcc = *(struct atm_vcc **) &msg->vcc;
@@ -198,7 +198,7 @@
 static void purge_vccs(struct atm_vcc *vcc)
 {
 	while (vcc) {
-		if (vcc->family == PF_ATMSVC &&
+		if (vcc->sk->family == PF_ATMSVC &&
 		    !test_bit(ATM_VF_META,&vcc->flags)) {
 			set_bit(ATM_VF_RELEASED,&vcc->flags);
 			vcc->reply = -EUNATCH;
@@ -212,16 +212,20 @@
 static void sigd_close(struct atm_vcc *vcc)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 
 	DPRINTK("sigd_close\n");
 	sigd = NULL;
-	if (skb_peek(&vcc->recvq))
+	if (skb_peek(&vcc->sk->receive_queue))
 		printk(KERN_ERR "sigd_close: closing with requests pending\n");
-	skb_queue_purge(&vcc->recvq);
+	skb_queue_purge(&vcc->sk->receive_queue);
 	purge_vccs(nodev_vccs);
 
 	spin_lock (&atm_dev_lock);
-	for (dev = atm_devs; dev; dev = dev->next) purge_vccs(dev->vccs);
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
+		purge_vccs(dev->vccs);
+	}
 	spin_unlock (&atm_dev_lock);
 }
 
diff -Nru a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
--- a/net/ax25/af_ax25.c	Sun Dec 29 02:00:21 2002
+++ b/net/ax25/af_ax25.c	Thu Mar  6 11:06:44 2003
@@ -330,7 +330,7 @@
 				ax25_cb *sax25 = ax25_sk(skb->sk);
 
 				/* Queue the unaccepted socket for death */
-				skb->sk->dead = 1;
+				__set_bit(SOCK_DEAD, &skb->sk->flags);
 
 				ax25_start_heartbeat(sax25);
 				sax25->state = AX25_STATE_0;
@@ -984,8 +984,8 @@
 			sk->state                = TCP_CLOSE;
 			sk->shutdown            |= SEND_SHUTDOWN;
 			sk->state_change(sk);
-			sk->dead                 = 1;
-			sk->destroy              = 1;
+			__set_bit(SOCK_DEAD, &sk->flags);
+			__set_bit(SOCK_DESTROY, &sk->flags);
 			break;
 
 		default:
@@ -995,7 +995,7 @@
 		sk->state     = TCP_CLOSE;
 		sk->shutdown |= SEND_SHUTDOWN;
 		sk->state_change(sk);
-		sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
 		ax25_destroy_socket(ax25);
 	}
 
@@ -1411,8 +1411,7 @@
 }
 
 static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int len,
-	struct scm_cookie *scm)
+			struct msghdr *msg, int len)
 {
 	struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
 	struct sock *sk = sock->sk;
@@ -1590,7 +1589,7 @@
 }
 
 static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
+	struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
diff -Nru a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
--- a/net/ax25/ax25_ds_in.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_ds_in.c	Mon Mar  3 04:56:53 2003
@@ -67,7 +67,7 @@
 		if (ax25->sk != NULL) {
 			ax25->sk->state = TCP_ESTABLISHED;
 			/* For WAIT_SABM connections we will produce an accept ready socket here */
-			if (!ax25->sk->dead)
+			if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 				ax25->sk->state_change(ax25->sk);
 		}
 		ax25_dama_on(ax25);
diff -Nru a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
--- a/net/ax25/ax25_ds_timer.c	Mon Aug  5 09:23:19 2002
+++ b/net/ax25/ax25_ds_timer.c	Mon Mar  3 04:56:53 2003
@@ -103,7 +103,7 @@
 	case AX25_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
+		if (ax25->sk == NULL || test_bit(SOCK_DESTROY, &ax25->sk->flags) || (ax25->sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &ax25->sk->flags))) {
 			ax25_destroy_socket(ax25);
 			return;
 		}
@@ -157,9 +157,9 @@
 		ax25->sk->state     = TCP_CLOSE;
 		ax25->sk->err       = 0;
 		ax25->sk->shutdown |= SEND_SHUTDOWN;
-		if (!ax25->sk->dead)
+		if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 			ax25->sk->state_change(ax25->sk);
-		ax25->sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &ax25->sk->flags);
 	}
 }
 
diff -Nru a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
--- a/net/ax25/ax25_in.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_in.c	Mon Mar  3 04:56:53 2003
@@ -434,7 +434,7 @@
 	ax25_start_idletimer(ax25);
 
 	if (sk != NULL) {
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->data_ready(sk, skb->len);
 	} else {
 		kfree_skb(skb);
diff -Nru a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
--- a/net/ax25/ax25_std_in.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_std_in.c	Mon Mar  3 04:56:53 2003
@@ -75,7 +75,7 @@
 			if (ax25->sk != NULL) {
 				ax25->sk->state = TCP_ESTABLISHED;
 				/* For WAIT_SABM connections we will produce an accept ready socket here */
-				if (!ax25->sk->dead)
+				if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 					ax25->sk->state_change(ax25->sk);
 			}
 		}
diff -Nru a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
--- a/net/ax25/ax25_std_timer.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_std_timer.c	Mon Mar  3 04:56:53 2003
@@ -37,7 +37,7 @@
 	case AX25_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
+		if (ax25->sk == NULL || test_bit(SOCK_DESTROY, &ax25->sk->flags) || (ax25->sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &ax25->sk->flags))) {
 			ax25_destroy_socket(ax25);
 			return;
 		}
@@ -94,9 +94,9 @@
 		ax25->sk->state     = TCP_CLOSE;
 		ax25->sk->err       = 0;
 		ax25->sk->shutdown |= SEND_SHUTDOWN;
-		if (!ax25->sk->dead)
+		if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 			ax25->sk->state_change(ax25->sk);
-		ax25->sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &ax25->sk->flags);
 	}
 }
 
diff -Nru a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
--- a/net/ax25/ax25_subr.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_subr.c	Mon Mar  3 04:56:53 2003
@@ -285,8 +285,8 @@
 		ax25->sk->state     = TCP_CLOSE;
 		ax25->sk->err       = reason;
 		ax25->sk->shutdown |= SEND_SHUTDOWN;
-		if (!ax25->sk->dead)
+		if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 			ax25->sk->state_change(ax25->sk);
-		ax25->sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &ax25->sk->flags);
 	}
 }
diff -Nru a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
--- a/net/bluetooth/af_bluetooth.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/af_bluetooth.c	Thu Mar  6 11:06:44 2003
@@ -212,7 +212,7 @@
 }
 
 int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int len, int flags, struct scm_cookie *scm)
+	struct msghdr *msg, int len, int flags)
 {
 	int noblock = flags & MSG_DONTWAIT;
 	struct sock *sk = sock->sk;
diff -Nru a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
--- a/net/bluetooth/bnep/core.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/bnep/core.c	Thu Mar  6 11:06:44 2003
@@ -97,26 +97,12 @@
 
 static int bnep_send(struct bnep_session *s, void *data, size_t len)
 {
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct socket *sock = s->sock;
 	struct iovec iv = { data, len };
-	int err;
 
 	s->msg.msg_iov    = &iv;
 	s->msg.msg_iovlen = 1;
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = NULL;
-	si->sock = sock;
-	si->msg = &s->msg;
-	si->size = len;
-
-	err = sock->ops->sendmsg(&iocb, sock, &s->msg, len, NULL);
-	if (-EIOCBQUEUED == err)
-		err = wait_on_sync_kiocb(&iocb);
-
-	return err;
+	return sock_sendmsg(sock, &s->msg, len);
 }
 
 static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
@@ -444,20 +430,9 @@
 	
 	/* FIXME: linearize skb */
 	{
-		struct kiocb iocb;
-		struct sock_iocb *si;
-	
 		s->msg.msg_iov    = iv;
 		s->msg.msg_iovlen = il;
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->scm = NULL;
-		si->sock = sock;
-		si->msg = &s->msg;
-		si->size = len;
-		len = sock->ops->sendmsg(&iocb, sock, &s->msg, len, NULL);
-		if (-EIOCBQUEUED == len)
-			len = wait_on_sync_kiocb(&iocb);
+		len = sock_sendmsg(sock, &s->msg, len);
 	}
 	kfree_skb(skb);
 
diff -Nru a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
--- a/net/bluetooth/hci_sock.c	Wed Feb 19 21:13:32 2003
+++ b/net/bluetooth/hci_sock.c	Thu Mar  6 11:06:44 2003
@@ -320,7 +320,7 @@
         	put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(skb->stamp), &skb->stamp);
 }
  
-static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm)
+static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags)
 {
 	int noblock = flags & MSG_DONTWAIT;
 	struct sock *sk = sock->sk;
@@ -356,8 +356,7 @@
 	return err ? : copied;
 }
 
-static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len,
-                            struct scm_cookie *scm)
+static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct hci_dev *hdev;
diff -Nru a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
--- a/net/bluetooth/l2cap.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/l2cap.c	Thu Mar  6 11:06:44 2003
@@ -272,7 +272,7 @@
 
 	/* Kill poor orphan */
 	bt_sock_unlink(&l2cap_sk_list, sk);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock_put(sk);
 }
 
@@ -712,7 +712,7 @@
 	return err;
 }
 
-static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
+static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
diff -Nru a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
--- a/net/bluetooth/rfcomm/core.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/rfcomm/core.c	Thu Mar  6 11:06:44 2003
@@ -605,29 +605,17 @@
 /* ---- RFCOMM frame sending ---- */
 static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len)
 {
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct socket *sock = s->sock;
 	struct iovec iv = { data, len };
 	struct msghdr msg;
-	int err;
 
 	BT_DBG("session %p len %d", s, len);
 
 	memset(&msg, 0, sizeof(msg));
 	msg.msg_iovlen = 1;
 	msg.msg_iov = &iv;
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = NULL;
-	si->sock = sock;
-	si->msg = &msg;
-	si->size = len;
-
-	err = sock->ops->sendmsg(&iocb, sock, &msg, len, NULL);
-	if (-EIOCBQUEUED == err)
-		err = wait_on_sync_kiocb(&iocb);
-	return err;
+
+	return sock_sendmsg(sock, &msg, len);
 }
 
 static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci)
@@ -839,13 +827,10 @@
 
 static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len)
 {
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct socket *sock = s->sock;
 	struct iovec iv[3];
 	struct msghdr msg;
 	unsigned char hdr[5], crc[1];
-	int err;
 
 	if (len > 125)
 		return -EINVAL;
@@ -870,18 +855,8 @@
 	memset(&msg, 0, sizeof(msg));
 	msg.msg_iovlen = 3;
 	msg.msg_iov = iv;
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = NULL;
-	si->sock = sock;
-	si->msg = &msg;
-	si->size = 6 + len;
-
-	err = sock->ops->sendmsg(&iocb, sock, &msg, 6 + len, NULL);
-	if (-EIOCBQUEUED == err)
-		err = wait_on_sync_kiocb(&iocb);
 
-	return err;
+	return sock_sendmsg(sock, &msg, 6 + len);
 }
 
 static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits)
diff -Nru a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
--- a/net/bluetooth/rfcomm/sock.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/rfcomm/sock.c	Thu Mar  6 11:06:44 2003
@@ -212,7 +212,7 @@
 
 	/* Kill poor orphan */
 	bt_sock_unlink(&rfcomm_sk_list, sk);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock_put(sk);
 }
 
@@ -479,7 +479,7 @@
 }
 
 static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int len, struct scm_cookie *scm)
+			       struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
@@ -553,8 +553,7 @@
 }
 
 static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int size, int flags,
-			       struct scm_cookie *scm)
+			       struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	int target, err = 0, copied = 0;
diff -Nru a/net/bluetooth/sco.c b/net/bluetooth/sco.c
--- a/net/bluetooth/sco.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/sco.c	Thu Mar  6 11:06:44 2003
@@ -377,7 +377,7 @@
 
 	/* Kill poor orphan */
 	bt_sock_unlink(&sco_sk_list, sk);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock_put(sk);
 }
 
@@ -632,7 +632,7 @@
 	return 0;
 }
 
-static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
+static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
diff -Nru a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
--- a/net/bridge/netfilter/ebt_arp.c	Mon Sep 16 16:11:26 2002
+++ b/net/bridge/netfilter/ebt_arp.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_arp
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *	Tim Gardner <timg@tpi.com>
  *
  *  April, 2002
@@ -37,10 +37,10 @@
 		uint32_t dst;
 		uint32_t src;
 
-		// Make sure the packet is long enough.
+		/* Make sure the packet is long enough */
 		if ((((*skb).nh.raw) + arp_len) > (*skb).tail)
 			return EBT_NOMATCH;
-		// IPv4 addresses are always 4 bytes.
+		/* IPv4 addresses are always 4 bytes */
 		if (((*skb).nh.arph)->ar_pln != sizeof(uint32_t))
 			return EBT_NOMATCH;
 
@@ -82,8 +82,10 @@
 
 static struct ebt_match filter_arp =
 {
-	{NULL, NULL}, EBT_ARP_MATCH, ebt_filter_arp, ebt_arp_check, NULL,
-	THIS_MODULE
+	.name		= EBT_ARP_MATCH,
+	.match		= ebt_filter_arp,
+	.check		= ebt_arp_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
--- a/net/bridge/netfilter/ebt_dnat.c	Mon Sep 16 16:11:26 2002
+++ b/net/bridge/netfilter/ebt_dnat.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_dnat
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  June, 2002
  *
@@ -45,8 +45,10 @@
 
 static struct ebt_target dnat =
 {
-	{NULL, NULL}, EBT_DNAT_TARGET, ebt_target_dnat, ebt_target_dnat_check,
-	NULL, THIS_MODULE
+	.name		= EBT_DNAT_TARGET,
+	.target		= ebt_target_dnat,
+	.check		= ebt_target_dnat_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
--- a/net/bridge/netfilter/ebt_ip.c	Mon Oct 28 04:58:32 2002
+++ b/net/bridge/netfilter/ebt_ip.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_ip
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -86,7 +86,7 @@
 	if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
 		return -EINVAL;
 	if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
-		if (!info->bitmask & EBT_IPROTO)
+		if (!(info->bitmask & EBT_IPROTO))
 			return -EINVAL;
 		if (info->protocol != IPPROTO_TCP &&
 		    info->protocol != IPPROTO_UDP)
@@ -101,8 +101,10 @@
 
 static struct ebt_match filter_ip =
 {
-	{NULL, NULL}, EBT_IP_MATCH, ebt_filter_ip, ebt_ip_check, NULL,
-	THIS_MODULE
+	.name		= EBT_IP_MATCH,
+	.match		= ebt_filter_ip,
+	.check		= ebt_ip_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
--- a/net/bridge/netfilter/ebt_log.c	Mon Jan 13 17:12:01 2003
+++ b/net/bridge/netfilter/ebt_log.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_log
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -80,8 +80,10 @@
 
 static struct ebt_watcher log =
 {
-	{NULL, NULL}, EBT_LOG_WATCHER, ebt_log, ebt_log_check, NULL,
-	THIS_MODULE
+	.name		= EBT_LOG_WATCHER,
+	.watcher	= ebt_log,
+	.check		= ebt_log_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
--- a/net/bridge/netfilter/ebt_mark.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_mark.c	Mon Mar  3 04:41:09 2003
@@ -2,15 +2,16 @@
  *  ebt_mark
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  July, 2002
  *
  */
 
-// The mark target can be used in any chain
-// I believe adding a mangle table just for marking is total overkill
-// Marking a frame doesn't really change anything in the frame anyway
+/* The mark target can be used in any chain,
+ * I believe adding a mangle table just for marking is total overkill.
+ * Marking a frame doesn't really change anything in the frame anyway.
+ */
 
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_mark_t.h>
@@ -46,8 +47,10 @@
 
 static struct ebt_target mark_target =
 {
-	{NULL, NULL}, EBT_MARK_TARGET, ebt_target_mark,
-	ebt_target_mark_check, NULL, THIS_MODULE
+	.name		= EBT_MARK_TARGET,
+	.target		= ebt_target_mark,
+	.check		= ebt_target_mark_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
--- a/net/bridge/netfilter/ebt_mark_m.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_mark_m.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_mark_m
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  July, 2002
  *
@@ -41,8 +41,10 @@
 
 static struct ebt_match filter_mark =
 {
-	{NULL, NULL}, EBT_MARK_MATCH, ebt_filter_mark, ebt_mark_check, NULL,
-	THIS_MODULE
+	.name		= EBT_MARK_MATCH,
+	.match		= ebt_filter_mark,
+	.check		= ebt_mark_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
--- a/net/bridge/netfilter/ebt_redirect.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_redirect.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_redirect
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -51,8 +51,10 @@
 
 static struct ebt_target redirect_target =
 {
-	{NULL, NULL}, EBT_REDIRECT_TARGET, ebt_target_redirect,
-	ebt_target_redirect_check, NULL, THIS_MODULE
+	.name		= EBT_REDIRECT_TARGET,
+	.target		= ebt_target_redirect,
+	.check		= ebt_target_redirect_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
--- a/net/bridge/netfilter/ebt_snat.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_snat.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_snat
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  June, 2002
  *
@@ -44,8 +44,10 @@
 
 static struct ebt_target snat =
 {
-	{NULL, NULL}, EBT_SNAT_TARGET, ebt_target_snat, ebt_target_snat_check,
-	NULL, THIS_MODULE
+	.name		= EBT_SNAT_TARGET,
+	.target		= ebt_target_snat,
+	.check		= ebt_target_snat_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
--- a/net/bridge/netfilter/ebt_vlan.c	Thu Dec  5 13:15:16 2002
+++ b/net/bridge/netfilter/ebt_vlan.c	Mon Mar  3 04:41:09 2003
@@ -1,7 +1,7 @@
 /*
  * Description: EBTables 802.1Q match extension kernelspace module.
  * Authors: Nick Fedchik <nick@fedchik.org.ua>
- *          Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *          Bart De Schuymer <bdschuym@pandora.be>
  *    
  * 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
@@ -226,12 +226,10 @@
 }
 
 static struct ebt_match filter_vlan = {
-	{NULL, NULL},
-	EBT_VLAN_MATCH,
-	ebt_filter_vlan,
-	ebt_check_vlan,
-	NULL,
-	THIS_MODULE
+	.name		= EBT_VLAN_MATCH,
+	.match		= ebt_filter_vlan,
+	.check		= ebt_check_vlan,
+	.me		= THIS_MODULE,
 };
 
 /*
diff -Nru a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
--- a/net/bridge/netfilter/ebtable_broute.c	Mon Mar  3 01:43:37 2003
+++ b/net/bridge/netfilter/ebtable_broute.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtable_broute
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -16,11 +16,12 @@
 #include <linux/if_bridge.h>
 #include <linux/brlock.h>
 
-// EBT_ACCEPT means the frame will be bridged
-// EBT_DROP means the frame will be routed
+/* EBT_ACCEPT means the frame will be bridged
+ * EBT_DROP means the frame will be routed
+ */
 static struct ebt_entries initial_chain = {
-	.name	= "BROUTING",
-	.policy	= EBT_ACCEPT,
+	.name		= "BROUTING",
+	.policy		= EBT_ACCEPT,
 };
 
 static struct ebt_replace initial_table =
@@ -31,7 +32,7 @@
 	.hook_entry	= {
 		[NF_BR_BROUTING]	= &initial_chain,
 	},
-	.entries	= (char *)&initial_chain
+	.entries	= (char *)&initial_chain,
 };
 
 static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
@@ -57,8 +58,8 @@
 	ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL,
 	   &broute_table);
 	if (ret == NF_DROP)
-		return 1; // route it
-	return 0; // bridge it
+		return 1; /* route it */
+	return 0; /* bridge it */
 }
 
 static int __init init(void)
@@ -69,7 +70,7 @@
 	if (ret < 0)
 		return ret;
 	br_write_lock_bh(BR_NETPROTO_LOCK);
-	// see br_input.c
+	/* see br_input.c */
 	br_should_route_hook = ebt_broute;
 	br_write_unlock_bh(BR_NETPROTO_LOCK);
 	return ret;
diff -Nru a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
--- a/net/bridge/netfilter/ebtable_filter.c	Mon Mar  3 01:43:37 2003
+++ b/net/bridge/netfilter/ebtable_filter.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtable_filter
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -27,7 +27,7 @@
 	{
 		.name	= "OUTPUT",
 		.policy	= EBT_ACCEPT,
-	}
+	},
 };
 
 static struct ebt_replace initial_table =
@@ -35,12 +35,12 @@
 	.name		= "filter",
 	.valid_hooks	= FILTER_VALID_HOOKS,
 	.entries_size	= 3 * sizeof(struct ebt_entries),
-  	.hook_entry	= {
+	.hook_entry	= {
 		[NF_BR_LOCAL_IN]	= &initial_chains[0],
 		[NF_BR_FORWARD]		= &initial_chains[1],
-    		[NF_BR_LOCAL_OUT]	= &initial_chains[2],
+		[NF_BR_LOCAL_OUT]	= &initial_chains[2],
 	},
-	.entries	= (char *)initial_chains
+	.entries	= (char *)initial_chains,
 };
 
 static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
@@ -77,14 +77,14 @@
 		.hook		= ebt_hook,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_FORWARD,
-		.priority	= NF_BR_PRI_FILTER_BRIDGED
+		.priority	= NF_BR_PRI_FILTER_BRIDGED,
 	},
 	{
 		.hook		= ebt_hook,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_LOCAL_OUT,
-		.priority	= NF_BR_PRI_FILTER_OTHER
-	}
+		.priority	= NF_BR_PRI_FILTER_OTHER,
+	},
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
--- a/net/bridge/netfilter/ebtable_nat.c	Mon Mar  3 01:43:37 2003
+++ b/net/bridge/netfilter/ebtable_nat.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtable_nat
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -39,7 +39,7 @@
 		[NF_BR_LOCAL_OUT]	= &initial_chains[1],
 		[NF_BR_POST_ROUTING]	= &initial_chains[2],
 	},
-	.entries	= (char *)initial_chains
+	.entries	= (char *)initial_chains,
 };
 
 static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
@@ -77,19 +77,19 @@
 		.hook		= ebt_nat_dst,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_LOCAL_OUT,
-		.priority	= NF_BR_PRI_NAT_DST_OTHER
+		.priority	= NF_BR_PRI_NAT_DST_OTHER,
 	},
 	{
 		.hook		= ebt_nat_src,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_POST_ROUTING,
-		.priority	= NF_BR_PRI_NAT_SRC
+		.priority	= NF_BR_PRI_NAT_SRC,
 	},
 	{
 		.hook		= ebt_nat_dst,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_PRE_ROUTING,
-		.priority	= NF_BR_PRI_NAT_DST_BRIDGED
+		.priority	= NF_BR_PRI_NAT_DST_BRIDGED,
 	},
 };
 
diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
--- a/net/bridge/netfilter/ebtables.c	Mon Jan 13 00:16:09 2003
+++ b/net/bridge/netfilter/ebtables.c	Mon Mar  3 04:41:09 2003
@@ -365,7 +365,7 @@
 	m->u.match = match;
 	if (!try_module_get(match->me)) {
 		up(&ebt_mutex);
-		return -EINVAL;
+		return -ENOENT;
 	}
 	up(&ebt_mutex);
 	if (match->check &&
@@ -394,7 +394,7 @@
 	w->u.watcher = watcher;
 	if (!try_module_get(watcher->me)) {
 		up(&ebt_mutex);
-		return -EINVAL;
+		return -ENOENT;
 	}
 	up(&ebt_mutex);
 	if (watcher->check &&
@@ -634,6 +634,7 @@
 		goto cleanup_watchers;
 	if (!try_module_get(target->me)) {
 		up(&ebt_mutex);
+		ret = -ENOENT;
 		goto cleanup_watchers;
 	}
 	up(&ebt_mutex);
diff -Nru a/net/compat.c b/net/compat.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/compat.c	Thu Mar  6 11:02:18 2003
@@ -0,0 +1,700 @@
+/* 
+ * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c.
+ *
+ * Copyright (C) 2000		VA Linux Co
+ * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
+ * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com>
+ * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 2000		Hewlett-Packard Co.
+ * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs 
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/file.h>
+#include <linux/icmpv6.h>
+#include <linux/socket.h>
+#include <linux/filter.h>
+#include <linux/compat.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+#include <net/scm.h>
+#include <net/sock.h>
+#include <asm/uaccess.h>
+#include <net/compat_socket.h>
+
+#define A(__x)		((unsigned long)(__x))
+#define AA(__x)		((unsigned long)(__x))
+
+extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
+				       void * optval, int *optlen);
+
+
+static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
+					  struct compat_iovec *uiov32,
+					  int niov)
+{
+	int tot_len = 0;
+
+	while(niov > 0) {
+		u32 len, buf;
+
+		if(get_user(len, &uiov32->iov_len) ||
+		   get_user(buf, &uiov32->iov_base)) {
+			tot_len = -EFAULT;
+			break;
+		}
+		tot_len += len;
+		kiov->iov_base = (void *)A(buf);
+		kiov->iov_len = (__kernel_size_t) len;
+		uiov32++;
+		kiov++;
+		niov--;
+	}
+	return tot_len;
+}
+
+int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *umsg)
+{
+	u32 tmp1, tmp2, tmp3;
+	int err;
+
+	err = get_user(tmp1, &umsg->msg_name);
+	err |= __get_user(tmp2, &umsg->msg_iov);
+	err |= __get_user(tmp3, &umsg->msg_control);
+	if (err)
+		return -EFAULT;
+
+	kmsg->msg_name = (void *)A(tmp1);
+	kmsg->msg_iov = (struct iovec *)A(tmp2);
+	kmsg->msg_control = (void *)A(tmp3);
+
+	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
+	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+	
+	return err;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
+		   char *kern_address, int mode)
+{
+	int tot_len;
+
+	if(kern_msg->msg_namelen) {
+		if(mode==VERIFY_READ) {
+			int err = move_addr_to_kernel(kern_msg->msg_name,
+						      kern_msg->msg_namelen,
+						      kern_address);
+			if(err < 0)
+				return err;
+		}
+		kern_msg->msg_name = kern_address;
+	} else
+		kern_msg->msg_name = NULL;
+
+	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+				   GFP_KERNEL);
+		if(!kern_iov)
+			return -ENOMEM;
+	}
+
+	tot_len = iov_from_user_compat_to_kern(kern_iov,
+					  (struct compat_iovec *)kern_msg->msg_iov,
+					  kern_msg->msg_iovlen);
+	if(tot_len >= 0)
+		kern_msg->msg_iov = kern_iov;
+	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+		kfree(kern_iov);
+
+	return tot_len;
+}
+
+/* There is a lot of hair here because the alignment rules (and
+ * thus placement) of cmsg headers and length are different for
+ * 32-bit apps.  -DaveM
+ */
+int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
+			       unsigned char *stackbuf, int stackbuf_size)
+{
+	struct compat_cmsghdr *ucmsg;
+	struct cmsghdr *kcmsg, *kcmsg_base;
+	compat_size_t ucmlen;
+	__kernel_size_t kcmlen, tmp;
+
+	kcmlen = 0;
+	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+	ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		if(get_user(ucmlen, &ucmsg->cmsg_len))
+			return -EFAULT;
+
+		/* Catch bogons. */
+		if(CMSG_COMPAT_ALIGN(ucmlen) <
+		   CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)))
+			return -EINVAL;
+		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
+				   + ucmlen) > kmsg->msg_controllen)
+			return -EINVAL;
+
+		tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmlen += tmp;
+		ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+	if(kcmlen == 0)
+		return -EINVAL;
+
+	/* The kcmlen holds the 64-bit version of the control length.
+	 * It may not be modified as we do not stick it into the kmsg
+	 * until we have successfully copied over all of the data
+	 * from the user.
+	 */
+	if(kcmlen > stackbuf_size)
+		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
+	if(kcmsg == NULL)
+		return -ENOBUFS;
+
+	/* Now copy them over neatly. */
+	memset(kcmsg, 0, kcmlen);
+	ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		__get_user(ucmlen, &ucmsg->cmsg_len);
+		tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmsg->cmsg_len = tmp;
+		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+		/* Copy over the data. */
+		if(copy_from_user(CMSG_DATA(kcmsg),
+				  CMSG_COMPAT_DATA(ucmsg),
+				  (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
+			goto out_free_efault;
+
+		/* Advance. */
+		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+		ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+
+	/* Ok, looks like we made it.  Hook it up and return success. */
+	kmsg->msg_control = kcmsg_base;
+	kmsg->msg_controllen = kcmlen;
+	return 0;
+
+out_free_efault:
+	if(kcmsg_base != (struct cmsghdr *)stackbuf)
+		kfree(kcmsg_base);
+	return -EFAULT;
+}
+
+int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
+{
+	struct compat_cmsghdr *cm = (struct compat_cmsghdr *) kmsg->msg_control;
+	struct compat_cmsghdr cmhdr;
+	int cmlen = CMSG_COMPAT_LEN(len);
+
+	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		return 0; /* XXX: return error? check spec. */
+	}
+
+	if(kmsg->msg_controllen < cmlen) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		cmlen = kmsg->msg_controllen;
+	}
+	cmhdr.cmsg_level = level;
+	cmhdr.cmsg_type = type;
+	cmhdr.cmsg_len = cmlen;
+
+	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+		return -EFAULT;
+	if(copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr)))
+		return -EFAULT;
+	cmlen = CMSG_COMPAT_SPACE(len);
+	kmsg->msg_control += cmlen;
+	kmsg->msg_controllen -= cmlen;
+	return 0;
+}
+
+void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
+{
+	struct compat_cmsghdr *cm = (struct compat_cmsghdr *) kmsg->msg_control;
+	int fdmax = (kmsg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int);
+	int fdnum = scm->fp->count;
+	struct file **fp = scm->fp->fp;
+	int *cmfptr;
+	int err = 0, i;
+
+	if (fdnum < fdmax)
+		fdmax = fdnum;
+
+	for (i = 0, cmfptr = (int *) CMSG_COMPAT_DATA(cm); i < fdmax; i++, cmfptr++) {
+		int new_fd;
+		err = get_unused_fd();
+		if (err < 0)
+			break;
+		new_fd = err;
+		err = put_user(new_fd, cmfptr);
+		if (err) {
+			put_unused_fd(new_fd);
+			break;
+		}
+		/* Bump the usage count and install the file. */
+		get_file(fp[i]);
+		fd_install(new_fd, fp[i]);
+	}
+
+	if (i > 0) {
+		int cmlen = CMSG_COMPAT_LEN(i * sizeof(int));
+		if (!err)
+			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		if (!err)
+			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+		if (!err)
+			err = put_user(cmlen, &cm->cmsg_len);
+		if (!err) {
+			cmlen = CMSG_COMPAT_SPACE(i * sizeof(int));
+			kmsg->msg_control += cmlen;
+			kmsg->msg_controllen -= cmlen;
+		}
+	}
+	if (i < fdnum)
+		kmsg->msg_flags |= MSG_CTRUNC;
+
+	/*
+	 * All of the files that fit in the message have had their
+	 * usage counts incremented, so we just free the list.
+	 */
+	__scm_destroy(scm);
+}
+
+/* In these cases we (currently) can just copy to data over verbatim
+ * because all CMSGs created by the kernel have well defined types which
+ * have the same layout in both the 32-bit and 64-bit API.  One must add
+ * some special cased conversions here if we start sending control messages
+ * with incompatible types.
+ *
+ * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg_compat right after
+ * we do our work.  The remaining cases are:
+ *
+ * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
+ *		IP_TTL		int			32-bit clean
+ *		IP_TOS		__u8			32-bit clean
+ *		IP_RECVOPTS	variable length		32-bit clean
+ *		IP_RETOPTS	variable length		32-bit clean
+ *		(these last two are clean because the types are defined
+ *		 by the IPv4 protocol)
+ *		IP_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in	32-bit clean
+ * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in6	32-bit clean
+ *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
+ *		IPV6_HOPLIMIT	int			32-bit clean
+ *		IPV6_FLOWINFO	u32			32-bit clean
+ *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
+ *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
+ *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
+ *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
+ */
+void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+{
+	unsigned char *workbuf, *wp;
+	unsigned long bufsz, space_avail;
+	struct cmsghdr *ucmsg;
+
+	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
+	space_avail = kmsg->msg_controllen + bufsz;
+	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
+	if(workbuf == NULL)
+		goto fail;
+
+	/* To make this more sane we assume the kernel sends back properly
+	 * formatted control messages.  Because of how the kernel will truncate
+	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
+	 */
+	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
+	while(((unsigned long)ucmsg) <=
+	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
+		struct compat_cmsghdr *kcmsg_compat = (struct compat_cmsghdr *) wp;
+		int clen64, clen32;
+
+		/* UCMSG is the 64-bit format CMSG entry in user-space.
+		 * KCMSG_COMPAT is within the kernel space temporary buffer
+		 * we use to convert into a 32-bit style CMSG.
+		 */
+		__get_user(kcmsg_compat->cmsg_len, &ucmsg->cmsg_len);
+		__get_user(kcmsg_compat->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg_compat->cmsg_type, &ucmsg->cmsg_type);
+
+		clen64 = kcmsg_compat->cmsg_len;
+		copy_from_user(CMSG_COMPAT_DATA(kcmsg_compat), CMSG_DATA(ucmsg),
+			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+			  CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)));
+		kcmsg_compat->cmsg_len = clen32;
+
+		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
+		wp = (((char *)kcmsg_compat) + CMSG_COMPAT_ALIGN(clen32));
+	}
+
+	/* Copy back fixed up data, and adjust pointers. */
+	bufsz = (wp - workbuf);
+	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
+
+	kmsg->msg_control = (struct cmsghdr *)
+		(((char *)orig_cmsg_uptr) + bufsz);
+	kmsg->msg_controllen = space_avail - bufsz;
+
+	kfree(workbuf);
+	return;
+
+fail:
+	/* If we leave the 64-bit format CMSG chunks in there,
+	 * the application could get confused and crash.  So to
+	 * ensure greater recovery, we report no CMSGs.
+	 */
+	kmsg->msg_controllen += bufsz;
+	kmsg->msg_control = (void *) orig_cmsg_uptr;
+}
+
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+				     char *optval, int optlen);
+
+static int do_netfilter_replace(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct ipt_replace32 {
+		char name[IPT_TABLE_MAXNAMELEN];
+		__u32 valid_hooks;
+		__u32 num_entries;
+		__u32 size;
+		__u32 hook_entry[NF_IP_NUMHOOKS];
+		__u32 underflow[NF_IP_NUMHOOKS];
+		__u32 num_counters;
+		__u32 counters;
+		struct ipt_entry entries[0];
+	} *repl32 = (struct ipt_replace32 *)optval;
+	struct ipt_replace *krepl;
+	struct ipt_counters *counters32;
+	__u32 origsize;
+	unsigned int kreplsize, kcountersize;
+	mm_segment_t old_fs;
+	int ret;
+
+	if (optlen < sizeof(repl32))
+		return -EINVAL;
+
+	if (copy_from_user(&origsize,
+			&repl32->size,
+			sizeof(origsize)))
+		return -EFAULT;
+
+	kreplsize = sizeof(*krepl) + origsize;
+	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+
+	/* Hack: Causes ipchains to give correct error msg --RR */
+	if (optlen != kreplsize)
+		return -ENOPROTOOPT;
+
+	krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
+	if (krepl == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(krepl, optval, kreplsize)) {
+		kfree(krepl);
+		return -EFAULT;
+	}
+
+	counters32 = (struct ipt_counters *)AA(
+		((struct ipt_replace32 *)krepl)->counters);
+
+	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+	krepl->counters = (struct ipt_counters *)kmalloc(
+					kcountersize, GFP_KERNEL);
+	if (krepl->counters == NULL) {
+		kfree(krepl);
+		return -ENOMEM;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *)krepl, kreplsize);
+	set_fs(old_fs);
+
+	if (ret == 0 &&
+		copy_to_user(counters32, krepl->counters, kcountersize))
+			ret = -EFAULT;
+
+	kfree(krepl->counters);
+	kfree(krepl);
+
+	return ret;
+}
+
+static int do_set_attach_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct sock_fprog32 {
+		__u16 len;
+		__u32 filter;
+	} *fprog32 = (struct sock_fprog32 *)optval;
+	struct sock_fprog kfprog;
+	struct sock_filter *kfilter;
+	unsigned int fsize;
+	mm_segment_t old_fs;
+	__u32 uptr;
+	int ret;
+
+	if (get_user(kfprog.len, &fprog32->len) ||
+	    __get_user(uptr, &fprog32->filter))
+		return -EFAULT;
+
+	kfprog.filter = (struct sock_filter *)A(uptr);
+	fsize = kfprog.len * sizeof(struct sock_filter);
+
+	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
+	if (kfilter == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
+		kfree(kfilter);
+		return -EFAULT;
+	}
+
+	kfprog.filter = kfilter;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *)&kfprog, sizeof(kfprog));
+	set_fs(old_fs);
+
+	kfree(kfilter);
+
+	return ret;
+}
+
+static int do_set_icmpv6_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct icmp6_filter kfilter;
+	mm_segment_t old_fs;
+	int ret, i;
+
+	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
+		return -EFAULT;
+
+
+	for (i = 0; i < 8; i += 2) {
+		u32 tmp = kfilter.data[i];
+
+		kfilter.data[i] = kfilter.data[i + 1];
+		kfilter.data[i + 1] = tmp;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *) &kfilter, sizeof(kfilter));
+	set_fs(old_fs);
+
+	return ret;
+}
+
+static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
+{
+	struct compat_timeval *up = (struct compat_timeval *) optval;
+	struct timeval ktime;
+	mm_segment_t old_fs;
+	int err;
+
+	if (optlen < sizeof(*up))
+		return -EINVAL;
+	if (get_user(ktime.tv_sec, &up->tv_sec) ||
+	    __get_user(ktime.tv_usec, &up->tv_usec))
+		return -EFAULT;
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
+	set_fs(old_fs);
+
+	return err;
+}
+
+asmlinkage int compat_sys_setsockopt(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	if (optname == IPT_SO_SET_REPLACE)
+		return do_netfilter_replace(fd, level, optname,
+					    optval, optlen);
+	if (optname == SO_ATTACH_FILTER)
+		return do_set_attach_filter(fd, level, optname,
+					    optval, optlen);
+	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
+		return do_set_sock_timeout(fd, level, optname, optval, optlen);
+	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
+		return do_set_icmpv6_filter(fd, level, optname,
+					    optval, optlen);
+
+	return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
+static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
+{
+	struct compat_timeval *up = (struct compat_timeval *) optval;
+	struct timeval ktime;
+	mm_segment_t old_fs;
+	int len, err;
+
+	if (get_user(len, optlen))
+		return -EFAULT;
+	if (len < sizeof(*up))
+		return -EINVAL;
+	len = sizeof(ktime);
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
+	set_fs(old_fs);
+
+	if (!err) {
+		if (put_user(sizeof(*up), optlen) ||
+		    put_user(ktime.tv_sec, &up->tv_sec) ||
+		    __put_user(ktime.tv_usec, &up->tv_usec))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
+				char *optval, int *optlen)
+{
+	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
+		return do_get_sock_timeout(fd, level, optname, optval, optlen);
+	return sys_getsockopt(fd, level, optname, optval, optlen);
+}
+
+/* Argument list sizes for compat_sys_socketcall */
+#define AL(x) ((x) * sizeof(u32))
+static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+				AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+				AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+#undef AL
+
+extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
+extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
+				  int addrlen);
+extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
+				 int *upeer_addrlen); 
+extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
+				      int *usockaddr_len);
+extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
+				      int *usockaddr_len);
+extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
+extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
+				   unsigned flags, u32 addr, int addr_len);
+extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
+extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
+				     unsigned flags, u32 addr, u32 addr_len);
+extern asmlinkage long sys_socket(int family, int type, int protocol);
+extern asmlinkage long sys_socketpair(int family, int type, int protocol,
+				     int usockvec[2]);
+extern asmlinkage long sys_shutdown(int fd, int how);
+extern asmlinkage long sys_listen(int fd, int backlog);
+
+
+asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr *msg, unsigned flags)
+{
+	return sys_sendmsg(fd, (struct msghdr *)msg, flags | MSG_CMSG_COMPAT);
+}
+
+asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr *msg, unsigned int flags)
+{
+	return sys_recvmsg(fd, (struct msghdr *)msg, flags | MSG_CMSG_COMPAT);
+}
+
+asmlinkage long compat_sys_socketcall(int call, u32 *args)
+{
+	int ret;
+	u32 a[6];
+	u32 a0, a1;
+				 
+	if (call < SYS_SOCKET || call > SYS_RECVMSG)
+		return -EINVAL;
+	if (copy_from_user(a, args, nas[call]))
+		return -EFAULT;
+	a0 = a[0];
+	a1 = a[1];
+	
+	switch(call) {
+	case SYS_SOCKET:
+		ret = sys_socket(a0, a1, a[2]);
+		break;
+	case SYS_BIND:
+		ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
+		break;
+	case SYS_CONNECT:
+		ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
+		break;
+	case SYS_LISTEN:
+		ret = sys_listen(a0, a1);
+		break;
+	case SYS_ACCEPT:
+		ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
+		break;
+	case SYS_GETSOCKNAME:
+		ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
+				       (int *)A(a[2]));
+		break;
+	case SYS_GETPEERNAME:
+		ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
+				       (int *)A(a[2]));
+		break;
+	case SYS_SOCKETPAIR:
+		ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+		break;
+	case SYS_SEND:
+		ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
+		break;
+	case SYS_SENDTO:
+		ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
+		break;
+	case SYS_RECV:
+		ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
+		break;
+	case SYS_RECVFROM:
+		ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
+		break;
+	case SYS_SHUTDOWN:
+		ret = sys_shutdown(a0,a1);
+		break;
+	case SYS_SETSOCKOPT:
+		ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
+				      a[4]);
+		break;
+	case SYS_GETSOCKOPT:
+		ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3],
+					    (int *)(u64)a[4]);
+		break;
+	case SYS_SENDMSG:
+		ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1),
+				         a[2]);
+		break;
+	case SYS_RECVMSG:
+		ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1),
+				         a[2]);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
diff -Nru a/net/core/scm.c b/net/core/scm.c
--- a/net/core/scm.c	Wed Nov 27 15:12:41 2002
+++ b/net/core/scm.c	Thu Mar  6 11:06:44 2003
@@ -172,6 +172,9 @@
 	int cmlen = CMSG_LEN(len);
 	int err;
 
+	if (MSG_CMSG_COMPAT & msg->msg_flags)
+		return put_cmsg_compat(msg, level, type, len, data);
+
 	if (cm==NULL || msg->msg_controllen < sizeof(*cm)) {
 		msg->msg_flags |= MSG_CTRUNC;
 		return 0; /* XXX: return error? check spec. */
@@ -206,6 +209,9 @@
 	struct file **fp = scm->fp->fp;
 	int *cmfptr;
 	int err = 0, i;
+
+	if (MSG_CMSG_COMPAT & msg->msg_flags)
+		return scm_detach_fds_compat(msg, scm);
 
 	if (msg->msg_controllen > sizeof(struct cmsghdr))
 		fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr))
diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c	Fri Jan 10 12:07:06 2003
+++ b/net/core/skbuff.c	Mon Mar  3 08:51:51 2003
@@ -196,40 +196,6 @@
 		goto nodata;
 
 	/* XXX: does not include slab overhead */
-	skb->truesize = size + sizeof(struct sk_buff);
-
-	/* Load the data pointers. */
-	skb->head = skb->data = skb->tail = data;
-	skb->end  = data + size;
-
-	/* Set up other state */
-	skb->len      = 0;
-	skb->cloned   = 0;
-	skb->data_len = 0;
-
-	atomic_set(&skb->users, 1);
-	atomic_set(&(skb_shinfo(skb)->dataref), 1);
-	skb_shinfo(skb)->nr_frags  = 0;
-	skb_shinfo(skb)->tso_size = 0;
-	skb_shinfo(skb)->tso_segs = 0;
-	skb_shinfo(skb)->frag_list = NULL;
-out:
-	return skb;
-nodata:
-	skb_head_to_pool(skb);
-	skb = NULL;
-	goto out;
-}
-
-
-/*
- *	Slab constructor for a skb head.
- */
-static void skb_headerinit(void *p, kmem_cache_t *cache,
-			   unsigned long flags)
-{
-	struct sk_buff *skb = p;
-
 	skb->next	  = skb->prev = NULL;
 	skb->list	  = NULL;
 	skb->sk		  = NULL;
@@ -238,27 +204,50 @@
 	skb->dst	  = NULL;
 	skb->sp		  = NULL;
 	memset(skb->cb, 0, sizeof(skb->cb));
+	/* Set up other state */
+	skb->len	  = 0;
+	skb->data_len	  = 0;
+	skb->csum	  = 0;
+	skb->cloned	  = 0;
 	skb->pkt_type	  = PACKET_HOST;	/* Default type */
 	skb->ip_summed	  = 0;
 	skb->priority	  = 0;
+	atomic_set(&skb->users, 1);
 	skb->security	  = 0;	/* By default packets are insecure */
-	skb->destructor	  = NULL;
+	skb->truesize = size + sizeof(struct sk_buff);
+	
+	/* Load the data pointers. */
+	skb->head = skb->data = skb->tail = data;
+	skb->end  = data + size;
 
+	skb->destructor	  = NULL;
 #ifdef CONFIG_NETFILTER
-	skb->nfmark	  = skb->nfcache = 0;
-	skb->nfct	  = NULL;
+	skb->nfmark	= skb->nfcache = 0;
+	skb->nfct	= NULL;
 #ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug	  = 0;
+	skb->nf_debug	= 0;
 #endif
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-	skb->nf_bridge	  = NULL;
+	skb->nf_bridge	= NULL;
 #endif
 #endif
 #ifdef CONFIG_NET_SCHED
-	skb->tc_index	  = 0;
-#endif
+	skb->tc_index	= 0;
+#endif	
+	atomic_set(&(skb_shinfo(skb)->dataref), 1);
+	skb_shinfo(skb)->nr_frags  = 0;
+	skb_shinfo(skb)->tso_size = 0;
+	skb_shinfo(skb)->tso_segs = 0;
+	skb_shinfo(skb)->frag_list = NULL;
+out:
+	return skb;
+nodata:
+	skb_head_to_pool(skb);
+	skb = NULL;
+	goto out;
 }
 
+
 static void skb_drop_fraglist(struct sk_buff *skb)
 {
 	struct sk_buff *list = skb_shinfo(skb)->frag_list;
@@ -339,7 +328,6 @@
 	nf_bridge_put(skb->nf_bridge);
 #endif
 #endif
-	skb_headerinit(skb, NULL, 0);  /* clean state */
 	kfree_skbmem(skb);
 }
 
@@ -1261,7 +1249,7 @@
 					      sizeof(struct sk_buff),
 					      0,
 					      SLAB_HWCACHE_ALIGN,
-					      skb_headerinit, NULL);
+					      NULL, NULL);
 	if (!skbuff_head_cache)
 		panic("cannot create skbuff cache");
 
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	Fri Oct 18 17:45:16 2002
+++ b/net/core/sock.c	Sat Mar  8 11:39:01 2003
@@ -153,6 +153,12 @@
 	return 0;
 }
 
+static void sock_warn_obsolete_bsdism(const char *name)
+{
+	printk(KERN_WARNING "process `%s' is using obsolete "
+	       "%s SO_BSDCOMPAT\n", current->comm, name);
+}
+
 /*
  *	This is meant for all protocols to use and covers goings on
  *	at the socket level. Everything here is generic.
@@ -178,7 +184,7 @@
 	switch(optname)
 	{
 		case SO_DONTLINGER:
-			sk->linger=0;
+			__clear_bit(SOCK_LINGER, &sk->flags);
 			return 0;
 	}
 #endif	
@@ -214,7 +220,7 @@
 			sk->localroute=valbool;
 			break;
 		case SO_BROADCAST:
-			sk->broadcast=valbool;
+			sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
 			break;
 		case SO_SNDBUF:
 			/* Don't error on this BSD doesn't and if you think
@@ -262,11 +268,11 @@
 				tcp_set_keepalive(sk, valbool);
 			}
 #endif
-			sk->keepopen = valbool;
+			sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
 			break;
 
 	 	case SO_OOBINLINE:
-			sk->urginline = valbool;
+			sock_valbool_flag(sk, SOCK_URGINLINE, valbool);
 			break;
 
 	 	case SO_NO_CHECK:
@@ -290,7 +296,7 @@
 				break;
 			}
 			if(ling.l_onoff==0) {
-				sk->linger=0;
+				__clear_bit(SOCK_LINGER, &sk->flags);
 			} else {
 #if (BITS_PER_LONG == 32)
 				if (ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
@@ -298,12 +304,12 @@
 				else
 #endif
 					sk->lingertime=ling.l_linger*HZ;
-				sk->linger=1;
+				__set_bit(SOCK_LINGER, &sk->flags);
 			}
 			break;
 
 		case SO_BSDCOMPAT:
-			sk->bsdism = valbool;
+			sock_warn_obsolete_bsdism("setsockopt");
 			break;
 
 		case SO_PASSCRED:
@@ -443,7 +449,7 @@
 			break;
 		
 		case SO_BROADCAST:
-			v.val= sk->broadcast;
+			v.val= test_bit(SOCK_BROADCAST, &sk->flags);
 			break;
 
 		case SO_SNDBUF:
@@ -459,7 +465,7 @@
 			break;
 
 		case SO_KEEPALIVE:
-			v.val = sk->keepopen;
+			v.val = test_bit(SOCK_KEEPOPEN, &sk->flags);
 			break;
 
 		case SO_TYPE:
@@ -473,7 +479,7 @@
 			break;
 
 		case SO_OOBINLINE:
-			v.val = sk->urginline;
+			v.val = test_bit(SOCK_URGINLINE, &sk->flags);
 			break;
 	
 		case SO_NO_CHECK:
@@ -486,12 +492,12 @@
 		
 		case SO_LINGER:	
 			lv=sizeof(v.ling);
-			v.ling.l_onoff=sk->linger;
+			v.ling.l_onoff = test_bit(SOCK_LINGER, &sk->flags);
  			v.ling.l_linger=sk->lingertime/HZ;
 			break;
 					
 		case SO_BSDCOMPAT:
-			v.val = sk->bsdism;
+			sock_warn_obsolete_bsdism("getsockopt");
 			break;
 
 		case SO_TIMESTAMP:
@@ -806,6 +812,7 @@
 					page = alloc_pages(sk->allocation, 0);
 					if (!page) {
 						err = -ENOBUFS;
+						skb_shinfo(skb)->nr_frags = i;
 						kfree_skb(skb);
 						goto failure;
 					}
@@ -960,13 +967,13 @@
 }
 
 int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		    int flags, struct scm_cookie *scm)
+		    int flags)
 {
 	return -EOPNOTSUPP;
 }
 
 int sock_no_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		    int len, int flags, struct scm_cookie *scm)
+		    int len, int flags)
 {
 	return -EOPNOTSUPP;
 }
diff -Nru a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
--- a/net/decnet/af_decnet.c	Fri Oct 25 14:52:23 2002
+++ b/net/decnet/af_decnet.c	Thu Mar  6 11:06:44 2003
@@ -1718,7 +1718,7 @@
 
 
 static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
+	struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
@@ -1889,7 +1889,7 @@
 }
 
 static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
-	   struct msghdr *msg, int size, struct scm_cookie *scm)
+	   struct msghdr *msg, int size)
 {
 	struct sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
diff -Nru a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
--- a/net/decnet/dn_nsp_in.c	Fri Feb  7 01:48:38 2003
+++ b/net/decnet/dn_nsp_in.c	Mon Mar  3 04:56:53 2003
@@ -118,7 +118,7 @@
 			break;
 	}
 
-	if (wakeup && !sk->dead)
+	if (wakeup && !test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 }
 
@@ -367,7 +367,7 @@
 			}
 		}
                 dn_nsp_send_link(sk, DN_NOCHANGE, 0);
-                if (!sk->dead)
+                if (!test_bit(SOCK_DEAD, &sk->flags))
                 	sk->state_change(sk);
         }
 
@@ -428,7 +428,7 @@
 			break;
 	}
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		if (sk->socket->state != SS_UNCONNECTED)
 			sk->socket->state = SS_DISCONNECTING;
 		sk->state_change(sk);
@@ -477,7 +477,7 @@
 			scp->state = DN_CN;
 	}
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		if (sk->socket->state != SS_UNCONNECTED)
 			sk->socket->state = SS_DISCONNECTING;
 		sk->state_change(sk);
@@ -549,7 +549,7 @@
 			}
 			break;
                 }
-		if (wake_up && !sk->dead)
+		if (wake_up && !test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
         }
 
@@ -587,7 +587,7 @@
 	 * Therefore the plain read_lock is ok here. -DaveM
 	 */
 	read_lock(&sk->callback_lock);
-        if (!sk->dead) {
+        if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		struct socket *sock = sk->socket;
 		wake_up_interruptible(sk->sleep);
 		if (sock && sock->fasync_list &&
@@ -671,7 +671,7 @@
 	if (scp->state == DN_CI) {
 		scp->state = DN_NC;
 		sk->state = TCP_CLOSE;
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
 	}
 
@@ -861,7 +861,7 @@
 		int other = 1;
 
 		/* both data and ack frames can kick a CC socket into RUN */
-		if ((scp->state == DN_CC) && !sk->dead) {
+		if ((scp->state == DN_CC) && !test_bit(SOCK_DEAD, &sk->flags)) {
 			scp->state = DN_RUN;
 			sk->state = TCP_ESTABLISHED;
 			sk->state_change(sk);
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	Tue Feb 11 03:38:22 2003
+++ b/net/econet/af_econet.c	Thu Mar  6 11:06:44 2003
@@ -126,8 +126,7 @@
  */
 
 static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, int flags,
-			  struct scm_cookie *scm)
+			  struct msghdr *msg, int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
@@ -260,7 +259,7 @@
  */
 
 static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, struct scm_cookie *scm)
+			  struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
@@ -533,7 +532,7 @@
 
 	sock->sk = NULL;
 	sk->socket = NULL;
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 
 	/* Purge queues */
 
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Wed Feb 19 23:27:40 2003
+++ b/net/ipv4/af_inet.c	Thu Mar  6 11:06:44 2003
@@ -146,7 +146,7 @@
 		       sk);
 		return;
 	}
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive inet socket %p\n", sk);
 		return;
 	}
@@ -454,7 +454,8 @@
 		 * linger..
 		 */
 		timeout = 0;
-		if (sk->linger && !(current->flags & PF_EXITING))
+		if (test_bit(SOCK_LINGER, &sk->flags) &&
+				!(current->flags & PF_EXITING))
 			timeout = sk->lingertime;
 		sock->sk = NULL;
 		sk->prot->close(sk, timeout);
@@ -730,7 +731,7 @@
 
 
 int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-		 int size, int flags, struct scm_cookie *scm)
+		 int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	int addr_len = 0;
@@ -745,7 +746,7 @@
 
 
 int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-		 int size, struct scm_cookie *scm)
+		 int size)
 {
 	struct sock *sk = sock->sk;
 
diff -Nru a/net/ipv4/ah.c b/net/ipv4/ah.c
--- a/net/ipv4/ah.c	Sun Feb  2 23:19:14 2003
+++ b/net/ipv4/ah.c	Thu Mar  6 16:16:15 2003
@@ -2,30 +2,14 @@
 #include <linux/module.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
+#include <net/ah.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
 #include <net/icmp.h>
 #include <asm/scatterlist.h>
 
-#define AH_HLEN_NOICV	12
-
-typedef void (icv_update_fn_t)(struct crypto_tfm *,
-                               struct scatterlist *, unsigned int);
-
-struct ah_data
-{
-	u8			*key;
-	int			key_len;
-	u8			*work_icv;
-	int			icv_full_len;
-	int			icv_trunc_len;
-
-	void			(*icv)(struct ah_data*,
-	                               struct sk_buff *skb, u8 *icv);
-
-	struct crypto_tfm	*tfm;
-};
 
+#define AH_HLEN_NOICV	12
 
 /* Clear mutable options and find final destination to substitute
  * into IP header for icv calculation. Options are already checked
@@ -71,92 +55,6 @@
 	return 0;
 }
 
-static void skb_ah_walk(const struct sk_buff *skb,
-                        struct crypto_tfm *tfm, icv_update_fn_t icv_update)
-{
-	int offset = 0;
-	int len = skb->len;
-	int start = skb->len - skb->data_len;
-	int i, copy = start - offset;
-	struct scatterlist sg;
-
-	/* Checksum header. */
-	if (copy > 0) {
-		if (copy > len)
-			copy = len;
-		
-		sg.page = virt_to_page(skb->data + offset);
-		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-		sg.length = copy;
-		
-		icv_update(tfm, &sg, 1);
-		
-		if ((len -= copy) == 0)
-			return;
-		offset += copy;
-	}
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		int end;
-
-		BUG_TRAP(start <= offset + len);
-
-		end = start + skb_shinfo(skb)->frags[i].size;
-		if ((copy = end - offset) > 0) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-			if (copy > len)
-				copy = len;
-			
-			sg.page = frag->page;
-			sg.offset = frag->page_offset + offset-start;
-			sg.length = copy;
-			
-			icv_update(tfm, &sg, 1);
-			
-			if (!(len -= copy))
-				return;
-			offset += copy;
-		}
-		start = end;
-	}
-
-	if (skb_shinfo(skb)->frag_list) {
-		struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-		for (; list; list = list->next) {
-			int end;
-
-			BUG_TRAP(start <= offset + len);
-
-			end = start + list->len;
-			if ((copy = end - offset) > 0) {
-				if (copy > len)
-					copy = len;
-				skb_ah_walk(list, tfm, icv_update);
-				if ((len -= copy) == 0)
-					return;
-				offset += copy;
-			}
-			start = end;
-		}
-	}
-	if (len)
-		BUG();
-}
-
-static void
-ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
-{
-	struct crypto_tfm *tfm = ahp->tfm;
-
-	memset(auth_data, 0, ahp->icv_trunc_len);
- 	crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
-  	skb_ah_walk(skb, tfm, crypto_hmac_update);
-	crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv);
-	memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
-}
-
 static int ah_output(struct sk_buff *skb)
 {
 	int err;
@@ -330,7 +228,7 @@
 	    skb->h.icmph->code != ICMP_FRAG_NEEDED)
 		return;
 
-	x = xfrm_state_lookup(iph->daddr, ah->spi, IPPROTO_AH);
+	x = xfrm4_state_lookup(iph->daddr, ah->spi, IPPROTO_AH);
 	if (!x)
 		return;
 	printk(KERN_DEBUG "pmtu discvovery on SA AH/%08x/%08x\n",
diff -Nru a/net/ipv4/esp.c b/net/ipv4/esp.c
--- a/net/ipv4/esp.c	Mon Mar  3 01:45:23 2003
+++ b/net/ipv4/esp.c	Thu Mar  6 16:16:15 2003
@@ -2,318 +2,15 @@
 #include <linux/module.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
+#include <net/esp.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
 #include <net/icmp.h>
 
-#define MAX_SG_ONSTACK 4
-
-typedef void (icv_update_fn_t)(struct crypto_tfm *,
-                               struct scatterlist *, unsigned int);
-
-/* BUGS:
- * - we assume replay seqno is always present.
- */
-
-struct esp_data
-{
-	/* Confidentiality */
-	struct {
-		u8			*key;		/* Key */
-		int			key_len;	/* Key length */
-		u8			*ivec;		/* ivec buffer */
-		/* ivlen is offset from enc_data, where encrypted data start.
-		 * It is logically different of crypto_tfm_alg_ivsize(tfm).
-		 * We assume that it is either zero (no ivec), or
-		 * >= crypto_tfm_alg_ivsize(tfm). */
-		int			ivlen;
-		int			padlen;		/* 0..255 */
-		struct crypto_tfm	*tfm;		/* crypto handle */
-	} conf;
-
-	/* Integrity. It is active when icv_full_len != 0 */
-	struct {
-		u8			*key;		/* Key */
-		int			key_len;	/* Length of the key */
-		u8			*work_icv;
-		int			icv_full_len;
-		int			icv_trunc_len;
-		void			(*icv)(struct esp_data*,
-		                               struct sk_buff *skb,
-		                               int offset, int len, u8 *icv);
-		struct crypto_tfm	*tfm;
-	} auth;
-};
-
-/* Move to common area: it is shared with AH. */
-
-void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
-		  int offset, int len, icv_update_fn_t icv_update)
-{
-	int start = skb->len - skb->data_len;
-	int i, copy = start - offset;
-	struct scatterlist sg;
-
-	/* Checksum header. */
-	if (copy > 0) {
-		if (copy > len)
-			copy = len;
-		
-		sg.page = virt_to_page(skb->data + offset);
-		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-		sg.length = copy;
-		
-		icv_update(tfm, &sg, 1);
-		
-		if ((len -= copy) == 0)
-			return;
-		offset += copy;
-	}
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		int end;
-
-		BUG_TRAP(start <= offset + len);
-
-		end = start + skb_shinfo(skb)->frags[i].size;
-		if ((copy = end - offset) > 0) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-			if (copy > len)
-				copy = len;
-			
-			sg.page = frag->page;
-			sg.offset = frag->page_offset + offset-start;
-			sg.length = copy;
-			
-			icv_update(tfm, &sg, 1);
-
-			if (!(len -= copy))
-				return;
-			offset += copy;
-		}
-		start = end;
-	}
-
-	if (skb_shinfo(skb)->frag_list) {
-		struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-		for (; list; list = list->next) {
-			int end;
-
-			BUG_TRAP(start <= offset + len);
-
-			end = start + list->len;
-			if ((copy = end - offset) > 0) {
-				if (copy > len)
-					copy = len;
-				skb_icv_walk(list, tfm, offset-start, copy, icv_update);
-				if ((len -= copy) == 0)
-					return;
-				offset += copy;
-			}
-			start = end;
-		}
-	}
-	if (len)
-		BUG();
-}
-
-
-/* Looking generic it is not used in another places. */
-
-int
-skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
-{
-	int start = skb->len - skb->data_len;
-	int i, copy = start - offset;
-	int elt = 0;
-
-	if (copy > 0) {
-		if (copy > len)
-			copy = len;
-		sg[elt].page = virt_to_page(skb->data + offset);
-		sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-		sg[elt].length = copy;
-		elt++;
-		if ((len -= copy) == 0)
-			return elt;
-		offset += copy;
-	}
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		int end;
-
-		BUG_TRAP(start <= offset + len);
-
-		end = start + skb_shinfo(skb)->frags[i].size;
-		if ((copy = end - offset) > 0) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-			if (copy > len)
-				copy = len;
-			sg[elt].page = frag->page;
-			sg[elt].offset = frag->page_offset+offset-start;
-			sg[elt].length = copy;
-			elt++;
-			if (!(len -= copy))
-				return elt;
-			offset += copy;
-		}
-		start = end;
-	}
 
-	if (skb_shinfo(skb)->frag_list) {
-		struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-		for (; list; list = list->next) {
-			int end;
-
-			BUG_TRAP(start <= offset + len);
-
-			end = start + list->len;
-			if ((copy = end - offset) > 0) {
-				if (copy > len)
-					copy = len;
-				elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
-				if ((len -= copy) == 0)
-					return elt;
-				offset += copy;
-			}
-			start = end;
-		}
-	}
-	if (len)
-		BUG();
-	return elt;
-}
-
-/* Common with AH after some work on arguments. */
-
-static void
-esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
-		int len, u8 *auth_data)
-{
-	struct crypto_tfm *tfm = esp->auth.tfm;
-	char *icv = esp->auth.work_icv;
-
-	memset(auth_data, 0, esp->auth.icv_trunc_len);
- 	crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len);
-	skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update);
-	crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv);
-	memcpy(auth_data, icv, esp->auth.icv_trunc_len);
-}
-
-/* Check that skb data bits are writable. If they are not, copy data
- * to newly created private area. If "tailbits" is given, make sure that
- * tailbits bytes beyond current end of skb are writable.
- *
- * Returns amount of elements of scatterlist to load for subsequent
- * transformations and pointer to writable trailer skb.
- */
-
-int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
-{
-	int copyflag;
-	int elt;
-	struct sk_buff *skb1, **skb_p;
-
-	/* If skb is cloned or its head is paged, reallocate
-	 * head pulling out all the pages (pages are considered not writable
-	 * at the moment even if they are anonymous).
-	 */
-	if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
-	    __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL)
-		return -ENOMEM;
-
-	/* Easy case. Most of packets will go this way. */
-	if (!skb_shinfo(skb)->frag_list) {
-		/* A little of trouble, not enough of space for trailer.
-		 * This should not happen, when stack is tuned to generate
-		 * good frames. OK, on miss we reallocate and reserve even more
-		 * space, 128 bytes is fair. */
-
-		if (skb_tailroom(skb) < tailbits &&
-		    pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
-			return -ENOMEM;
-
-		/* Voila! */
-		*trailer = skb;
-		return 1;
-	}
-
-	/* Misery. We are in troubles, going to mincer fragments... */
-
-	elt = 1;
-	skb_p = &skb_shinfo(skb)->frag_list;
-	copyflag = 0;
-
-	while ((skb1 = *skb_p) != NULL) {
-		int ntail = 0;
-
-		/* The fragment is partially pulled by someone,
-		 * this can happen on input. Copy it and everything
-		 * after it. */
-
-		if (skb_shared(skb1))
-			copyflag = 1;
-
-		/* If the skb is the last, worry about trailer. */
-
-		if (skb1->next == NULL && tailbits) {
-			if (skb_shinfo(skb1)->nr_frags ||
-			    skb_shinfo(skb1)->frag_list ||
-			    skb_tailroom(skb1) < tailbits)
-				ntail = tailbits + 128;
-		}
-
-		if (copyflag ||
-		    skb_cloned(skb1) ||
-		    ntail ||
-		    skb_shinfo(skb1)->nr_frags ||
-		    skb_shinfo(skb1)->frag_list) {
-			struct sk_buff *skb2;
-
-			/* Fuck, we are miserable poor guys... */
-			if (ntail == 0)
-				skb2 = skb_copy(skb1, GFP_ATOMIC);
-			else
-				skb2 = skb_copy_expand(skb1,
-						       skb_headroom(skb1),
-						       ntail,
-						       GFP_ATOMIC);
-			if (unlikely(skb2 == NULL))
-				return -ENOMEM;
-
-			if (skb1->sk)
-				skb_set_owner_w(skb, skb1->sk);
-
-			/* Looking around. Are we still alive?
-			 * OK, link new skb, drop old one */
-
-			skb2->next = skb1->next;
-			*skb_p = skb2;
-			kfree_skb(skb1);
-			skb1 = skb2;
-		}
-		elt++;
-		*trailer = skb1;
-		skb_p = &skb1->next;
-	}
-
-	return elt;
-}
-
-void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
-{
-	if (tail != skb) {
-		skb->data_len += len;
-		skb->len += len;
-	}
-	return skb_put(tail, len);
-}
+#define MAX_SG_ONSTACK 4
 
 int esp_output(struct sk_buff *skb)
 {
@@ -575,7 +272,7 @@
 	    skb->h.icmph->code != ICMP_FRAG_NEEDED)
 		return;
 
-	x = xfrm_state_lookup(iph->daddr, esph->spi, IPPROTO_ESP);
+	x = xfrm4_state_lookup(iph->daddr, esph->spi, IPPROTO_ESP);
 	if (!x)
 		return;
 	printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/%08x\n",
diff -Nru a/net/ipv4/icmp.c b/net/ipv4/icmp.c
--- a/net/ipv4/icmp.c	Mon Feb 24 03:18:25 2003
+++ b/net/ipv4/icmp.c	Thu Mar  6 16:30:30 2003
@@ -116,7 +116,7 @@
 DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics);
 
 /* An array of errno for error messages from dest unreach. */
-/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errs'. */
+/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */
 
 struct icmp_err icmp_err_convert[] = {
 	{
diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c	Wed Feb 19 13:55:33 2003
+++ b/net/ipv4/igmp.c	Mon Mar 10 17:08:59 2003
@@ -255,30 +255,22 @@
 {
 	struct ip_mc_list *im=(struct ip_mc_list *)data;
 	struct in_device *in_dev = im->interface;
-	int err;
 
 	spin_lock(&im->lock);
 	im->tm_running=0;
 
-	if (IGMP_V1_SEEN(in_dev))
-		err = igmp_send_report(in_dev->dev, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
-	else
-		err = igmp_send_report(in_dev->dev, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
-
-	/* Failed. Retry later. */
-	if (err) {
-		if (!in_dev->dead)
-			igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
-		goto out;
-	}
-
 	if (im->unsolicit_count) {
 		im->unsolicit_count--;
 		igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
 	}
 	im->reporter = 1;
-out:
 	spin_unlock(&im->lock);
+
+	if (IGMP_V1_SEEN(in_dev))
+		igmp_send_report(in_dev->dev, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
+	else
+		igmp_send_report(in_dev->dev, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
+
 	ip_ma_put(im);
 }
 
@@ -606,7 +598,7 @@
 static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
 {
 	struct flowi fl = { .nl_u = { .ip4_u =
-				      { .daddr = imr->imr_address.s_addr } } };
+				      { .daddr = imr->imr_multiaddr.s_addr } } };
 	struct rtable *rt;
 	struct net_device *dev = NULL;
 	struct in_device *idev = NULL;
diff -Nru a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
--- a/net/ipv4/netfilter/arptable_filter.c	Mon Feb 10 02:35:55 2003
+++ b/net/ipv4/netfilter/arptable_filter.c	Tue Mar 11 16:08:41 2003
@@ -111,9 +111,14 @@
     }
 };
 
-static struct arpt_table packet_filter
-= { { NULL, NULL }, "filter", &initial_table.repl,
-    FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct arpt_table packet_filter = {
+	.name		= "filter",
+	.table		= &initial_table.repl,
+	.valid_hooks	= FILTER_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.private	= NULL,
+	.me		= THIS_MODULE,
+};
 
 /* The work comes in here from netfilter.c */
 static unsigned int arpt_hook(unsigned int hook,
@@ -125,9 +130,17 @@
 	return arpt_do_table(pskb, hook, in, out, &packet_filter, NULL);
 }
 
-static struct nf_hook_ops arpt_ops[]
-= { { { NULL, NULL }, arpt_hook, NF_ARP, NF_ARP_IN, 0 },
-    { { NULL, NULL }, arpt_hook, NF_ARP, NF_ARP_OUT, 0 }
+static struct nf_hook_ops arpt_ops[] = {
+	{
+		.hook		= arpt_hook,
+		.pf		= NF_ARP,
+		.hooknum	= NF_ARP_IN,
+	},
+	{
+		.hook		= arpt_hook,
+		.pf		= NF_ARP,
+		.hooknum	= NF_ARP_OUT,
+	}
 };
 
 static int __init init(void)
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c	Mon Mar  3 01:25:39 2003
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c	Tue Mar 11 16:08:41 2003
@@ -226,17 +226,34 @@
 
 /* Connection tracking may drop packets, but never alters them, so
    make it the first hook. */
-static struct nf_hook_ops ip_conntrack_in_ops
-= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
-	NF_IP_PRI_CONNTRACK };
-static struct nf_hook_ops ip_conntrack_local_out_ops
-= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
-	NF_IP_PRI_CONNTRACK };
+static struct nf_hook_ops ip_conntrack_in_ops = {
+	.hook		= ip_conntrack_in,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_PRE_ROUTING,
+	.priority	= NF_IP_PRI_CONNTRACK,
+};
+
+static struct nf_hook_ops ip_conntrack_local_out_ops = {
+	.hook		= ip_conntrack_local,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_LOCAL_OUT,
+	.priority	= NF_IP_PRI_CONNTRACK,
+};
+
 /* Refragmenter; last chance. */
-static struct nf_hook_ops ip_conntrack_out_ops
-= { { NULL, NULL }, ip_refrag, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_LAST };
-static struct nf_hook_ops ip_conntrack_local_in_ops
-= { { NULL, NULL }, ip_confirm, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LAST-1 };
+static struct nf_hook_ops ip_conntrack_out_ops = {
+	.hook		= ip_refrag,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_POST_ROUTING,
+	.priority	= NF_IP_PRI_LAST,
+};
+
+static struct nf_hook_ops ip_conntrack_local_in_ops = {
+	.hook		= ip_confirm,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_LOCAL_IN,
+	.priority	= NF_IP_PRI_LAST-1,
+};
 
 static int init_or_cleanup(int init)
 {
diff -Nru a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
--- a/net/ipv4/netfilter/ip_fw_compat.c	Wed Feb 19 12:23:25 2003
+++ b/net/ipv4/netfilter/ip_fw_compat.c	Tue Mar 11 16:08:41 2003
@@ -216,21 +216,40 @@
 	return -ip_fw_ctl(optval, &tmp_fw, len);
 }
 
-static struct nf_hook_ops preroute_ops
-= { { NULL, NULL }, fw_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FILTER };
+static struct nf_hook_ops preroute_ops = {
+	.hook		= fw_in,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_PRE_ROUTING,
+	.priority	= NF_IP_PRI_FILTER,
+};
 
-static struct nf_hook_ops postroute_ops
-= { { NULL, NULL }, fw_in, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FILTER };
+static struct nf_hook_ops postroute_ops = {
+	.hook		= fw_in,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_POST_ROUTING,
+	.priority	= NF_IP_PRI_FILTER,
+};
 
-static struct nf_hook_ops forward_ops
-= { { NULL, NULL }, fw_in, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER };
+static struct nf_hook_ops forward_ops = {
+	.hook		= fw_in,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_FORWARD,
+	.priority	= NF_IP_PRI_FILTER,
+};
 
-static struct nf_hook_ops local_in_ops
-= { { NULL, NULL }, fw_confirm, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LAST - 1 };
+static struct nf_hook_ops local_in_ops = {
+	.hook		= fw_confirm,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_LOCAL_IN,
+	.priority	= NF_IP_PRI_LAST - 1,
+};
 
-static struct nf_sockopt_ops sock_ops
-= { { NULL, NULL }, PF_INET, 64, 64 + 1024 + 1, &sock_fn, 0, 0, NULL,
-    0, NULL };
+static struct nf_sockopt_ops sock_ops = {
+	.pf		= PF_INET,
+	.set_optmin	= 64,
+	.set_optmax	= 64 + 1024 + 1,
+	.set		= &sock_fn,
+};
 
 extern int ipfw_init_or_cleanup(int init);
 
diff -Nru a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
--- a/net/ipv4/netfilter/ip_nat_rule.c	Sat Feb 22 16:15:34 2003
+++ b/net/ipv4/netfilter/ip_nat_rule.c	Tue Mar 11 16:08:41 2003
@@ -101,9 +101,13 @@
     }
 };
 
-static struct ipt_table nat_table
-= { { NULL, NULL }, "nat", &nat_initial_table.repl,
-    NAT_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct ipt_table nat_table = {
+	.name		= "nat",
+	.table		= &nat_initial_table.repl,
+	.valid_hooks	= NAT_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.me		= THIS_MODULE,
+};
 
 /* Source NAT */
 static unsigned int ipt_snat_target(struct sk_buff **pskb,
@@ -270,10 +274,17 @@
 	return ret;
 }
 
-static struct ipt_target ipt_snat_reg
-= { { NULL, NULL }, "SNAT", ipt_snat_target, ipt_snat_checkentry, NULL };
-static struct ipt_target ipt_dnat_reg
-= { { NULL, NULL }, "DNAT", ipt_dnat_target, ipt_dnat_checkentry, NULL };
+static struct ipt_target ipt_snat_reg = {
+	.name		= "SNAT",
+	.target		= ipt_snat_target,
+	.checkentry	= ipt_snat_checkentry,
+};
+
+static struct ipt_target ipt_dnat_reg = {
+	.name		= "DNAT",
+	.target		= ipt_dnat_target,
+	.checkentry	= ipt_dnat_checkentry,
+};
 
 int __init ip_nat_rule_init(void)
 {
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c	Mon Mar  3 01:15:36 2003
+++ b/net/ipv4/netfilter/ip_nat_standalone.c	Tue Mar 11 16:08:41 2003
@@ -225,18 +225,36 @@
 /* We must be after connection tracking and before packet filtering. */
 
 /* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_in_ops
-= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST };
+static struct nf_hook_ops ip_nat_in_ops = {
+	.hook		= ip_nat_fn,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_PRE_ROUTING,
+	.priority	= NF_IP_PRI_NAT_DST,
+};
+
 /* After packet filtering, change source */
-static struct nf_hook_ops ip_nat_out_ops
-= { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC};
+static struct nf_hook_ops ip_nat_out_ops = {
+	.hook		= ip_nat_out,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_POST_ROUTING,
+	.priority	= NF_IP_PRI_NAT_SRC,
+};
+
 /* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_local_out_ops
-= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
+static struct nf_hook_ops ip_nat_local_out_ops = {
+	.hook		= ip_nat_local_fn,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_LOCAL_OUT,
+	.priority	= NF_IP_PRI_NAT_DST,
+};
 
 #ifdef CONFIG_IP_NF_NAT_LOCAL
-static struct nf_hook_ops ip_nat_local_in_ops
-= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_NAT_SRC };
+static struct nf_hook_ops ip_nat_local_in_ops = {
+	.hook		= ip_nat_fn,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_LOCAL_IN,
+	.priority	= NF_IP_PRI_NAT_SRC,
+};
 #endif
 
 /* Protocol registration. */
diff -Nru a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
--- a/net/ipv4/netfilter/iptable_filter.c	Mon Feb 10 02:35:55 2003
+++ b/net/ipv4/netfilter/iptable_filter.c	Tue Mar 11 16:08:41 2003
@@ -81,9 +81,13 @@
     }
 };
 
-static struct ipt_table packet_filter
-= { { NULL, NULL }, "filter", &initial_table.repl,
-    FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct ipt_table packet_filter = {
+	.name		= "filter",
+	.table		= &initial_table.repl,
+	.valid_hooks	= FILTER_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.me		= THIS_MODULE
+};
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
@@ -114,11 +118,25 @@
 	return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
 }
 
-static struct nf_hook_ops ipt_ops[]
-= { { { NULL, NULL }, ipt_hook, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_FILTER },
-    { { NULL, NULL }, ipt_hook, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER },
-    { { NULL, NULL }, ipt_local_out_hook, PF_INET, NF_IP_LOCAL_OUT,
-		NF_IP_PRI_FILTER }
+static struct nf_hook_ops ipt_ops[] = {
+	{
+		.hook		= ipt_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_FILTER,
+	},
+	{
+		.hook		= ipt_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_FORWARD,
+		.priority	= NF_IP_PRI_FILTER,
+	},
+	{
+		.hook		= ipt_local_out_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_OUT,
+		.priority	= NF_IP_PRI_FILTER,
+	},
 };
 
 /* Default to forward because I got too much mail already. */
diff -Nru a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
--- a/net/ipv4/netfilter/iptable_mangle.c	Mon Feb 10 02:35:55 2003
+++ b/net/ipv4/netfilter/iptable_mangle.c	Tue Mar 11 16:08:41 2003
@@ -114,9 +114,13 @@
     }
 };
 
-static struct ipt_table packet_mangler
-= { { NULL, NULL }, "mangle", &initial_table.repl,
-    MANGLE_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct ipt_table packet_mangler = {
+	.name		= "mangle",
+	.table		= &initial_table.repl,
+	.valid_hooks	= MANGLE_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.me		= THIS_MODULE,
+};
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
@@ -167,17 +171,37 @@
 	return ret;
 }
 
-static struct nf_hook_ops ipt_ops[]
-= { { { NULL, NULL }, ipt_route_hook, PF_INET, NF_IP_PRE_ROUTING, 
-	NF_IP_PRI_MANGLE },
-    { { NULL, NULL }, ipt_local_hook, PF_INET, NF_IP_LOCAL_IN,
-	NF_IP_PRI_MANGLE },
-    { { NULL, NULL }, ipt_route_hook, PF_INET, NF_IP_FORWARD,
-	NF_IP_PRI_MANGLE },
-    { { NULL, NULL }, ipt_local_hook, PF_INET, NF_IP_LOCAL_OUT,
-	NF_IP_PRI_MANGLE },
-    { { NULL, NULL }, ipt_route_hook, PF_INET, NF_IP_POST_ROUTING,
-	NF_IP_PRI_MANGLE }
+static struct nf_hook_ops ipt_ops[] = {
+	{
+		.hook		= ipt_route_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_PRE_ROUTING, 
+		.priority	= NF_IP_PRI_MANGLE,
+	},
+	{
+		.hook		= ipt_local_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_MANGLE,
+	},
+	{
+		.hook		= ipt_route_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_FORWARD,
+		.priority	= NF_IP_PRI_MANGLE,
+	},
+	{
+		.hook		= ipt_local_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_OUT,
+		.priority	= NF_IP_PRI_MANGLE,
+	},
+	{
+		.hook		= ipt_route_hook,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_POST_ROUTING,
+		.priority	= NF_IP_PRI_MANGLE,
+	},
 };
 
 static int __init init(void)
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	Sun Jan 12 08:52:15 2003
+++ b/net/ipv4/raw.c	Mon Mar  3 04:56:53 2003
@@ -450,7 +450,8 @@
 		goto done;
 
 	err = -EACCES;
-	if (rt->rt_flags & RTCF_BROADCAST && !sk->broadcast)
+	if (rt->rt_flags & RTCF_BROADCAST &&
+			!test_bit(SOCK_BROADCAST, &sk->flags))
 		goto done;
 
 	if (msg->msg_flags & MSG_CONFIRM)
diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c
--- a/net/ipv4/route.c	Wed Feb 19 23:24:57 2003
+++ b/net/ipv4/route.c	Wed Mar  5 15:45:36 2003
@@ -96,6 +96,7 @@
 #include <net/arp.h>
 #include <net/tcp.h>
 #include <net/icmp.h>
+#include <net/xfrm.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -930,7 +931,7 @@
 				    rth->u.dst.dev != dev)
 					break;
 
-				dst_clone(&rth->u.dst);
+				dst_hold(&rth->u.dst);
 				rcu_read_unlock();
 
 				rt = dst_alloc(&ipv4_dst_ops);
@@ -2599,6 +2600,13 @@
 #endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_NET_CLS_ROUTE */
 
+int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+{
+        int err = 0;
+        err = __ip_route_output_key((struct rtable**)dst, fl);
+        return err;
+}
+
 int __init ip_rt_init(void)
 {
 	int i, order, goal, rc = 0;
@@ -2680,6 +2688,7 @@
 					ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
+	xfrm_dst_lookup_register(xfrm_dst_lookup, AF_INET);
 #ifdef CONFIG_PROC_FS
 	if (rt_cache_proc_init())
 		goto out_enomem;
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	Tue Feb 25 11:05:23 2003
+++ b/net/ipv4/tcp.c	Mon Mar  3 04:56:53 2003
@@ -441,7 +441,7 @@
 		if ((tp->rcv_nxt != tp->copied_seq) &&
 		    (tp->urg_seq != tp->copied_seq ||
 		     tp->rcv_nxt != tp->copied_seq + 1 ||
-		     sk->urginline || !tp->urg_data))
+		     test_bit(SOCK_URGINLINE, &sk->flags) || !tp->urg_data))
 			mask |= POLLIN | POLLRDNORM;
 
 		if (!(sk->shutdown & SEND_SHUTDOWN)) {
@@ -497,7 +497,8 @@
 		lock_sock(sk);
 		if ((1 << sk->state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
 			answ = 0;
-		else if (sk->urginline || !tp->urg_data ||
+		else if (test_bit(SOCK_URGINLINE, &sk->flags) ||
+			 !tp->urg_data ||
 			 before(tp->urg_seq, tp->copied_seq) ||
 			 !before(tp->urg_seq, tp->rcv_nxt)) {
 			answ = tp->rcv_nxt - tp->copied_seq;
@@ -1254,10 +1255,11 @@
 	struct tcp_opt *tp = tcp_sk(sk);
 
 	/* No URG data to read. */
-	if (sk->urginline || !tp->urg_data || tp->urg_data == TCP_URG_READ)
+	if (test_bit(SOCK_URGINLINE, &sk->flags) || !tp->urg_data ||
+			tp->urg_data == TCP_URG_READ)
 		return -EINVAL;	/* Yes this is right ! */
 
-	if (sk->state == TCP_CLOSE && !sk->done)
+	if (sk->state == TCP_CLOSE && !test_bit(SOCK_DONE, &sk->flags))
 		return -ENOTCONN;
 
 	if (tp->urg_data & TCP_URG_VALID) {
@@ -1588,7 +1590,7 @@
 			    (flags & MSG_PEEK))
 				break;
 		} else {
-			if (sk->done)
+			if (test_bit(SOCK_DONE, &sk->flags))
 				break;
 
 			if (sk->err) {
@@ -1600,7 +1602,7 @@
 				break;
 
 			if (sk->state == TCP_CLOSE) {
-				if (!sk->done) {
+				if (!test_bit(SOCK_DONE, &sk->flags)) {
 					/* This occurs when user tries to read
 					 * from never connected socket.
 					 */
@@ -1713,7 +1715,8 @@
 			u32 urg_offset = tp->urg_seq - *seq;
 			if (urg_offset < used) {
 				if (!urg_offset) {
-					if (!sk->urginline) {
+					if (!test_bit(SOCK_URGINLINE,
+								&sk->flags)) {
 						++*seq;
 						offset++;
 						used--;
@@ -1837,7 +1840,7 @@
 
 /*
  *	Shutdown the sending side of a connection. Much like close except
- *	that we don't receive shut down or set sk->dead.
+ *	that we don't receive shut down or set SOCK_DEAD in sk->flags.
  */
 
 void tcp_shutdown(struct sock *sk, int how)
@@ -1902,7 +1905,7 @@
 void tcp_destroy_sock(struct sock *sk)
 {
 	BUG_TRAP(sk->state == TCP_CLOSE);
-	BUG_TRAP(sk->dead);
+	BUG_TRAP(test_bit(SOCK_DEAD, &sk->flags));
 
 	/* It cannot be in hash table! */
 	BUG_TRAP(!sk->pprev);
@@ -1979,7 +1982,7 @@
 		NET_INC_STATS_USER(TCPAbortOnClose);
 		tcp_set_state(sk, TCP_CLOSE);
 		tcp_send_active_reset(sk, GFP_KERNEL);
-	} else if (sk->linger && !sk->lingertime) {
+	} else if (test_bit(SOCK_LINGER, &sk->flags) && !sk->lingertime) {
 		/* Check zero linger _after_ checking for unread data. */
 		sk->prot->disconnect(sk, 0);
 		NET_INC_STATS_USER(TCPAbortOnData);
@@ -2157,7 +2160,7 @@
 	}
 
 	sk->shutdown = 0;
-	sk->done = 0;
+	__clear_bit(SOCK_DONE, &sk->flags);
 	tp->srtt = 0;
 	if ((tp->write_seq += tp->max_window + 2) == 0)
 		tp->write_seq = 1;
@@ -2358,7 +2361,7 @@
 			err = -EINVAL;
 		else {
 			tp->keepalive_time = val * HZ;
-			if (sk->keepopen &&
+			if (test_bit(SOCK_KEEPOPEN, &sk->flags) &&
 			    !((1 << sk->state) & (TCPF_CLOSE | TCPF_LISTEN))) {
 				__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp;
 				if (tp->keepalive_time > elapsed)
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	Wed Jan  8 01:03:24 2003
+++ b/net/ipv4/tcp_input.c	Mon Mar  3 04:56:53 2003
@@ -2352,7 +2352,7 @@
 			sk->err = ECONNRESET;
 	}
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->error_report(sk);
 
 	tcp_done(sk);
@@ -2379,7 +2379,7 @@
 	tcp_schedule_ack(tp);
 
 	sk->shutdown |= RCV_SHUTDOWN;
-	sk->done = 1;
+	__clear_bit(SOCK_DONE, &sk->flags);
 
 	switch(sk->state) {
 		case TCP_SYN_RECV:
@@ -2428,7 +2428,7 @@
 		tcp_sack_reset(tp);
 	tcp_mem_reclaim(sk);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		sk->state_change(sk);
 
 		/* Do not send POLL_HUP for half duplex close. */
@@ -2745,7 +2745,7 @@
 
 		if (eaten > 0) {
 			__kfree_skb(skb);
-		} else if (!sk->dead)
+		} else if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->data_ready(sk, 0);
 		return;
 	}
@@ -3247,7 +3247,7 @@
 	 * buggy users.
 	 */
 	if (tp->urg_seq == tp->copied_seq && tp->urg_data &&
-	    !sk->urginline &&
+	    !test_bit(SOCK_URGINLINE, &sk->flags) &&
 	    tp->copied_seq != tp->rcv_nxt) {
 		struct sk_buff *skb = skb_peek(&sk->receive_queue);
 		tp->copied_seq++;
@@ -3284,7 +3284,7 @@
 			if (skb_copy_bits(skb, ptr, &tmp, 1))
 				BUG();
 			tp->urg_data = TCP_URG_VALID | tmp;
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->data_ready(sk,0);
 		}
 	}
@@ -3699,7 +3699,7 @@
 		tcp_init_metrics(sk);
 		tcp_init_buffer_space(sk);
 
-		if (sk->keepopen)
+		if (test_bit(SOCK_KEEPOPEN, &sk->flags))
 			tcp_reset_keepalive_timer(sk, keepalive_time_when(tp));
 
 		if (!tp->snd_wscale)
@@ -3714,7 +3714,7 @@
 		mb();
 		tcp_set_state(sk, TCP_ESTABLISHED);
 
-		if(!sk->dead) {
+		if(!test_bit(SOCK_DEAD, &sk->flags)) {
 			sk->state_change(sk);
 			sk_wake_async(sk, 0, POLL_OUT);
 		}
@@ -3977,7 +3977,7 @@
 				sk->shutdown |= SEND_SHUTDOWN;
 				dst_confirm(sk->dst_cache);
 
-				if (!sk->dead) {
+				if (!test_bit(SOCK_DEAD, &sk->flags)) {
 					/* Wake up lingering close() */
 					sk->state_change(sk);
 				} else {
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	Fri Feb  7 01:48:38 2003
+++ b/net/ipv4/tcp_ipv4.c	Sat Mar  8 11:37:51 2003
@@ -142,6 +142,17 @@
 	return tb;
 }
 
+/* Caller must hold hashbucket lock for this tb with local BH disabled */
+void tcp_bucket_destroy(struct tcp_bind_bucket *tb)
+{
+	if (!tb->owners) {
+		if (tb->next)
+			tb->next->pprev = tb->pprev;
+		*(tb->pprev) = tb->next;
+		kmem_cache_free(tcp_bucket_cachep, tb);
+	}
+}
+
 /* Caller must disable local BH processing. */
 static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
 {
@@ -300,12 +311,7 @@
 	*(sk->bind_pprev) = sk->bind_next;
 	sk->prev  = NULL;
 	inet->num = 0;
-	if (!tb->owners) {
-		if (tb->next)
-			tb->next->pprev = tb->pprev;
-		*(tb->pprev) = tb->next;
-		kmem_cache_free(tcp_bucket_cachep, tb);
-	}
+	tcp_bucket_destroy(tb);
 	spin_unlock(&head->lock);
 }
 
diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c	Thu Jan 30 23:22:09 2003
+++ b/net/ipv4/tcp_minisocks.c	Sat Mar  8 11:37:51 2003
@@ -81,12 +81,7 @@
 		tw->bind_next->bind_pprev = tw->bind_pprev;
 	*(tw->bind_pprev) = tw->bind_next;
 	tw->tb = NULL;
-	if (tb->owners == NULL) {
-		if (tb->next)
-			tb->next->pprev = tb->pprev;
-		*(tb->pprev) = tb->next;
-		kmem_cache_free(tcp_bucket_cachep, tb);
-	}
+	tcp_bucket_destroy(tb);
 	spin_unlock(&bhead->lock);
 
 #ifdef INET_REFCNT_DEBUG
@@ -676,7 +671,7 @@
 		newsk->wmem_queued = 0;
 		newsk->forward_alloc = 0;
 
-		newsk->done = 0;
+		__clear_bit(SOCK_DONE, &newsk->flags);
 		newsk->userlocks = sk->userlocks & ~SOCK_BINDPORT_LOCK;
 		newsk->backlog.head = newsk->backlog.tail = NULL;
 		newsk->callback_lock = RW_LOCK_UNLOCKED;
@@ -761,7 +756,7 @@
 #endif
 		atomic_inc(&tcp_sockets_allocated);
 
-		if (newsk->keepopen)
+		if (test_bit(SOCK_KEEPOPEN, &newsk->flags))
 			tcp_reset_keepalive_timer(newsk, keepalive_time_when(newtp));
 		newsk->socket = NULL;
 		newsk->sleep = NULL;
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	Tue Feb 11 22:36:47 2003
+++ b/net/ipv4/tcp_output.c	Mon Mar  3 04:56:53 2003
@@ -1276,7 +1276,7 @@
 	tp->rcv_ssthresh = tp->rcv_wnd;
 
 	sk->err = 0;
-	sk->done = 0;
+	__clear_bit(SOCK_DONE, &sk->flags);
 	tp->snd_wnd = 0;
 	tcp_init_wl(tp, tp->write_seq, 0);
 	tp->snd_una = tp->write_seq;
diff -Nru a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
--- a/net/ipv4/tcp_timer.c	Tue Jan  7 02:19:05 2003
+++ b/net/ipv4/tcp_timer.c	Mon Mar  3 04:56:53 2003
@@ -189,7 +189,7 @@
 		}
 
 		retry_until = sysctl_tcp_retries2;
-		if (sk->dead) {
+		if (test_bit(SOCK_DEAD, &sk->flags)) {
 			int alive = (tp->rto < TCP_RTO_MAX);
  
 			retry_until = tcp_orphan_retries(sk, alive);
@@ -297,7 +297,7 @@
 	 */
 	max_probes = sysctl_tcp_retries2;
 
-	if (sk->dead) {
+	if (test_bit(SOCK_DEAD, &sk->flags)) {
 		int alive = ((tp->rto<<tp->backoff) < TCP_RTO_MAX);
  
 		max_probes = tcp_orphan_retries(sk, alive);
@@ -327,7 +327,7 @@
 
 	BUG_TRAP(!skb_queue_empty(&sk->write_queue));
 
-	if (tp->snd_wnd == 0 && !sk->dead &&
+	if (tp->snd_wnd == 0 && !test_bit(SOCK_DEAD, &sk->flags) &&
 	    !((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV))) {
 		/* Receiver dastardly shrinks window. Our retransmits
 		 * become zero probes, but we should not timeout this
@@ -571,7 +571,7 @@
 	if ((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN))
 		return;
 
-	if (val && !sk->keepopen)
+	if (val && !test_bit(SOCK_KEEPOPEN, &sk->flags))
 		tcp_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk)));
 	else if (!val)
 		tcp_delete_keepalive_timer(sk);
@@ -597,7 +597,7 @@
 		goto out;
 	}
 
-	if (sk->state == TCP_FIN_WAIT2 && sk->dead) {
+	if (sk->state == TCP_FIN_WAIT2 && test_bit(SOCK_DEAD, &sk->flags)) {
 		if (tp->linger2 >= 0) {
 			int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;
 
@@ -610,7 +610,7 @@
 		goto death;
 	}
 
-	if (!sk->keepopen || sk->state == TCP_CLOSE)
+	if (!test_bit(SOCK_KEEPOPEN, &sk->flags) || sk->state == TCP_CLOSE)
 		goto out;
 
 	elapsed = keepalive_time_when(tp);
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	Tue Jan  7 02:19:05 2003
+++ b/net/ipv4/udp.c	Mon Mar  3 04:56:53 2003
@@ -606,7 +606,8 @@
 			goto out;
 
 		err = -EACCES;
-		if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast) 
+		if (rt->rt_flags&RTCF_BROADCAST &&
+				!test_bit(SOCK_BROADCAST, &sk->flags))
 			goto out;
 		if (connected)
 			sk_dst_set(sk, dst_clone(&rt->u.dst));
@@ -887,7 +888,8 @@
 			       inet->sport, usin->sin_port, sk);
 	if (err)
 		return err;
-	if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
+	if ((rt->rt_flags&RTCF_BROADCAST) &&
+			!test_bit(SOCK_BROADCAST, &sk->flags)) {
 		ip_rt_put(rt);
 		return -EACCES;
 	}
diff -Nru a/net/ipv4/xfrm_algo.c b/net/ipv4/xfrm_algo.c
--- a/net/ipv4/xfrm_algo.c	Thu Jan  9 22:55:54 2003
+++ b/net/ipv4/xfrm_algo.c	Thu Mar  6 16:16:15 2003
@@ -8,9 +8,17 @@
  * Software Foundation; either version 2 of the License, or (at your option) 
  * any later version.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
 #include <net/xfrm.h>
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+#include <net/ah.h>
+#endif
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+#include <net/esp.h>
+#endif
+#include <asm/scatterlist.h>
 
 /*
  * Algorithms supported by IPsec.  These entries contain properties which
@@ -348,3 +356,333 @@
 			n++;
 	return n;
 }
+
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+void skb_ah_walk(const struct sk_buff *skb,
+                        struct crypto_tfm *tfm, icv_update_fn_t icv_update)
+{
+	int offset = 0;
+	int len = skb->len;
+	int start = skb->len - skb->data_len;
+	int i, copy = start - offset;
+	struct scatterlist sg;
+
+	/* Checksum header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		
+		sg.page = virt_to_page(skb->data + offset);
+		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
+		sg.length = copy;
+		
+		icv_update(tfm, &sg, 1);
+		
+		if ((len -= copy) == 0)
+			return;
+		offset += copy;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			if (copy > len)
+				copy = len;
+			
+			sg.page = frag->page;
+			sg.offset = frag->page_offset + offset-start;
+			sg.length = copy;
+			
+			icv_update(tfm, &sg, 1);
+			
+			if (!(len -= copy))
+				return;
+			offset += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				skb_ah_walk(list, tfm, icv_update);
+				if ((len -= copy) == 0)
+					return;
+				offset += copy;
+			}
+			start = end;
+		}
+	}
+	if (len)
+		BUG();
+}
+#endif
+
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+/* Move to common area: it is shared with AH. */
+
+void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
+		  int offset, int len, icv_update_fn_t icv_update)
+{
+	int start = skb->len - skb->data_len;
+	int i, copy = start - offset;
+	struct scatterlist sg;
+
+	/* Checksum header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		
+		sg.page = virt_to_page(skb->data + offset);
+		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
+		sg.length = copy;
+		
+		icv_update(tfm, &sg, 1);
+		
+		if ((len -= copy) == 0)
+			return;
+		offset += copy;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			if (copy > len)
+				copy = len;
+			
+			sg.page = frag->page;
+			sg.offset = frag->page_offset + offset-start;
+			sg.length = copy;
+			
+			icv_update(tfm, &sg, 1);
+
+			if (!(len -= copy))
+				return;
+			offset += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				skb_icv_walk(list, tfm, offset-start, copy, icv_update);
+				if ((len -= copy) == 0)
+					return;
+				offset += copy;
+			}
+			start = end;
+		}
+	}
+	if (len)
+		BUG();
+}
+
+
+/* Looking generic it is not used in another places. */
+
+int
+skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
+{
+	int start = skb->len - skb->data_len;
+	int i, copy = start - offset;
+	int elt = 0;
+
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		sg[elt].page = virt_to_page(skb->data + offset);
+		sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
+		sg[elt].length = copy;
+		elt++;
+		if ((len -= copy) == 0)
+			return elt;
+		offset += copy;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			if (copy > len)
+				copy = len;
+			sg[elt].page = frag->page;
+			sg[elt].offset = frag->page_offset+offset-start;
+			sg[elt].length = copy;
+			elt++;
+			if (!(len -= copy))
+				return elt;
+			offset += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
+				if ((len -= copy) == 0)
+					return elt;
+				offset += copy;
+			}
+			start = end;
+		}
+	}
+	if (len)
+		BUG();
+	return elt;
+}
+
+/* Check that skb data bits are writable. If they are not, copy data
+ * to newly created private area. If "tailbits" is given, make sure that
+ * tailbits bytes beyond current end of skb are writable.
+ *
+ * Returns amount of elements of scatterlist to load for subsequent
+ * transformations and pointer to writable trailer skb.
+ */
+
+int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
+{
+	int copyflag;
+	int elt;
+	struct sk_buff *skb1, **skb_p;
+
+	/* If skb is cloned or its head is paged, reallocate
+	 * head pulling out all the pages (pages are considered not writable
+	 * at the moment even if they are anonymous).
+	 */
+	if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
+	    __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL)
+		return -ENOMEM;
+
+	/* Easy case. Most of packets will go this way. */
+	if (!skb_shinfo(skb)->frag_list) {
+		/* A little of trouble, not enough of space for trailer.
+		 * This should not happen, when stack is tuned to generate
+		 * good frames. OK, on miss we reallocate and reserve even more
+		 * space, 128 bytes is fair. */
+
+		if (skb_tailroom(skb) < tailbits &&
+		    pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
+			return -ENOMEM;
+
+		/* Voila! */
+		*trailer = skb;
+		return 1;
+	}
+
+	/* Misery. We are in troubles, going to mincer fragments... */
+
+	elt = 1;
+	skb_p = &skb_shinfo(skb)->frag_list;
+	copyflag = 0;
+
+	while ((skb1 = *skb_p) != NULL) {
+		int ntail = 0;
+
+		/* The fragment is partially pulled by someone,
+		 * this can happen on input. Copy it and everything
+		 * after it. */
+
+		if (skb_shared(skb1))
+			copyflag = 1;
+
+		/* If the skb is the last, worry about trailer. */
+
+		if (skb1->next == NULL && tailbits) {
+			if (skb_shinfo(skb1)->nr_frags ||
+			    skb_shinfo(skb1)->frag_list ||
+			    skb_tailroom(skb1) < tailbits)
+				ntail = tailbits + 128;
+		}
+
+		if (copyflag ||
+		    skb_cloned(skb1) ||
+		    ntail ||
+		    skb_shinfo(skb1)->nr_frags ||
+		    skb_shinfo(skb1)->frag_list) {
+			struct sk_buff *skb2;
+
+			/* Fuck, we are miserable poor guys... */
+			if (ntail == 0)
+				skb2 = skb_copy(skb1, GFP_ATOMIC);
+			else
+				skb2 = skb_copy_expand(skb1,
+						       skb_headroom(skb1),
+						       ntail,
+						       GFP_ATOMIC);
+			if (unlikely(skb2 == NULL))
+				return -ENOMEM;
+
+			if (skb1->sk)
+				skb_set_owner_w(skb, skb1->sk);
+
+			/* Looking around. Are we still alive?
+			 * OK, link new skb, drop old one */
+
+			skb2->next = skb1->next;
+			*skb_p = skb2;
+			kfree_skb(skb1);
+			skb1 = skb2;
+		}
+		elt++;
+		*trailer = skb1;
+		skb_p = &skb1->next;
+	}
+
+	return elt;
+}
+
+void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
+{
+	if (tail != skb) {
+		skb->data_len += len;
+		skb->len += len;
+	}
+	return skb_put(tail, len);
+}
+#endif
diff -Nru a/net/ipv4/xfrm_input.c b/net/ipv4/xfrm_input.c
--- a/net/ipv4/xfrm_input.c	Tue Nov 12 14:35:26 2002
+++ b/net/ipv4/xfrm_input.c	Wed Mar  5 15:45:36 2003
@@ -1,4 +1,14 @@
+/* Changes
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	YOSHIFUJI Hideaki @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ */
+
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/xfrm.h>
 
 static kmem_cache_t *secpath_cachep;
@@ -64,7 +74,7 @@
 		if (xfrm_nr == XFRM_MAX_DEPTH)
 			goto drop;
 
-		x = xfrm_state_lookup(iph->daddr, spi, iph->protocol);
+		x = xfrm4_state_lookup(iph->daddr, spi, iph->protocol);
 		if (x == NULL)
 			goto drop;
 
@@ -157,3 +167,288 @@
 	if (!secpath_cachep)
 		panic("IP: failed to allocate secpath_cache\n");
 }
+
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+
+/* Fetch spi and seq frpm ipsec header */
+
+static int xfrm6_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+{
+	int offset, offset_seq;
+
+	switch (nexthdr) {
+	case IPPROTO_AH:
+		offset = offsetof(struct ip_auth_hdr, spi);
+		offset_seq = offsetof(struct ip_auth_hdr, seq_no);
+		break;
+	case IPPROTO_ESP:
+		offset = offsetof(struct ip_esp_hdr, spi);
+		offset_seq = offsetof(struct ip_esp_hdr, seq_no);
+		break;
+	case IPPROTO_COMP:
+		if (!pskb_may_pull(skb, 4))
+			return -EINVAL;
+		*spi = *(u16*)(skb->h.raw + 2);
+		*seq = 0;
+		return 0;
+	default:
+		return 1;
+	}
+
+	if (!pskb_may_pull(skb, 16))
+		return -EINVAL;
+
+	*spi = *(u32*)(skb->h.raw + offset);
+	*seq = *(u32*)(skb->h.raw + offset_seq);
+	return 0;
+}
+
+static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
+{
+	u8 *opt = (u8 *)opthdr;
+	int len = ipv6_optlen(opthdr);
+	int off = 0;
+	int optlen = 0;
+
+	off += 2;
+	len -= 2;
+
+	while (len > 0) {
+
+		switch (opt[off]) {
+
+		case IPV6_TLV_PAD0:
+			optlen = 1;
+			break;
+		default:
+			if (len < 2) 
+				goto bad;
+			optlen = opt[off+1]+2;
+			if (len < optlen)
+				goto bad;
+			if (opt[off] & 0x20)
+				memset(&opt[off+2], 0, opt[off+1]);
+			break;
+		}
+
+		off += optlen;
+		len -= optlen;
+	}
+	if (len == 0)
+		return 1;
+
+bad:
+	return 0;
+}
+
+int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+	unsigned int packet_len = skb->tail - skb->nh.raw;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+	u8 nextnexthdr = 0;
+
+	*nh_offset = ((unsigned char *)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
+
+	while (offset + 1 <= packet_len) {
+
+		switch (nexthdr) {
+
+		case NEXTHDR_HOP:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			if (!zero_out_mutable_opts(exthdr)) {
+				if (net_ratelimit())
+					printk(KERN_WARNING "overrun hopopts\n"); 
+				return 0;
+			}
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_ROUTING:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			((struct ipv6_rt_hdr*)exthdr)->segments_left = 0; 
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_DEST:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			if (!zero_out_mutable_opts(exthdr))  {
+				if (net_ratelimit())
+					printk(KERN_WARNING "overrun destopt\n"); 
+				return 0;
+			}
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_AUTH:
+			if (dir == XFRM_POLICY_OUT) {
+				memset(((struct ipv6_auth_hdr*)exthdr)->auth_data, 0, 
+				       (((struct ipv6_auth_hdr*)exthdr)->hdrlen - 1) << 2);
+			}
+			if (exthdr->nexthdr == NEXTHDR_DEST) {
+				offset += (((struct ipv6_auth_hdr*)exthdr)->hdrlen + 2) << 2;
+				exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+				nextnexthdr = exthdr->nexthdr;
+				if (!zero_out_mutable_opts(exthdr)) {
+					if (net_ratelimit())
+						printk(KERN_WARNING "overrun destopt\n");
+					return 0;
+				}
+			}
+			return nexthdr;
+		default :
+			return nexthdr;
+		}
+	}
+
+	return nexthdr;
+}
+
+int xfrm6_rcv(struct sk_buff *skb)
+{
+	int err;
+	u32 spi, seq;
+	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
+	struct xfrm_state *x;
+	int xfrm_nr = 0;
+	int decaps = 0;
+	struct ipv6hdr *hdr = skb->nh.ipv6h;
+	unsigned char *tmp_hdr = NULL;
+	int hdr_len = 0;
+	u16 nh_offset = 0;
+	u8 nexthdr = 0;
+
+	if (hdr->nexthdr == IPPROTO_AH || hdr->nexthdr == IPPROTO_ESP) {
+		nh_offset = ((unsigned char*)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
+		hdr_len = sizeof(struct ipv6hdr);
+	} else {
+		hdr_len = skb->h.raw - skb->nh.raw;
+	}
+
+	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+	if (!tmp_hdr)
+		goto drop;
+	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
+
+	nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN);
+	hdr->priority    = 0;
+	hdr->flow_lbl[0] = 0;
+	hdr->flow_lbl[1] = 0;
+	hdr->flow_lbl[2] = 0;
+	hdr->hop_limit   = 0;
+
+	if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
+		goto drop;
+	
+	do {
+		struct ipv6hdr *iph = skb->nh.ipv6h;
+
+		if (xfrm_nr == XFRM_MAX_DEPTH)
+			goto drop;
+
+		x = xfrm6_state_lookup(&iph->daddr, spi, nexthdr);
+		if (x == NULL)
+			goto drop;
+		spin_lock(&x->lock);
+		if (unlikely(x->km.state != XFRM_STATE_VALID))
+			goto drop_unlock;
+
+		if (x->props.replay_window && xfrm_replay_check(x, seq))
+			goto drop_unlock;
+
+		nexthdr = x->type->input(x, skb);
+		if (nexthdr <= 0)
+			goto drop_unlock;
+
+		if (x->props.replay_window)
+			xfrm_replay_advance(x, seq);
+
+		x->curlft.bytes += skb->len;
+		x->curlft.packets++;
+
+		spin_unlock(&x->lock);
+
+		xfrm_vec[xfrm_nr++] = x;
+
+		iph = skb->nh.ipv6h; /* ??? */ 
+
+		if (nexthdr == NEXTHDR_DEST) {
+			if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
+		    	!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
+				err = -EINVAL;
+				goto drop;
+			}
+			nexthdr = skb->h.raw[0];
+			nh_offset = skb->h.raw - skb->nh.raw;
+			skb_pull(skb, (skb->h.raw[1]+1)<<3);
+			skb->h.raw = skb->data;
+		}
+
+		if (x->props.mode) { /* XXX */
+			if (iph->nexthdr != IPPROTO_IPV6)
+				goto drop;
+			skb->nh.raw = skb->data;
+			iph = skb->nh.ipv6h;
+			decaps = 1;
+			break;
+		}
+
+		if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
+			goto drop;
+	} while (!err);
+
+	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+	skb->nh.raw[nh_offset] = nexthdr;
+	skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr));
+
+	/* Allocate new secpath or COW existing one. */
+	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
+		struct sec_path *sp;
+		sp = kmem_cache_alloc(secpath_cachep, SLAB_ATOMIC);
+		if (!sp)
+			goto drop;
+		if (skb->sp) {
+			memcpy(sp, skb->sp, sizeof(struct sec_path));
+			secpath_put(skb->sp);
+		} else
+			sp->len = 0;
+		atomic_set(&sp->refcnt, 1);
+		skb->sp = sp;
+	}
+
+	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
+		goto drop;
+
+	memcpy(skb->sp->xvec+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(void*));
+	skb->sp->len += xfrm_nr;
+
+	if (decaps) {
+		if (!(skb->dev->flags&IFF_LOOPBACK)) {
+			dst_release(skb->dst);
+			skb->dst = NULL;
+		}
+		netif_rx(skb);
+		return 0;
+	} else {
+		return -nexthdr;
+	}
+
+drop_unlock:
+	spin_unlock(&x->lock);
+	xfrm_state_put(x);
+drop:
+	if (tmp_hdr) kfree(tmp_hdr);
+	while (--xfrm_nr >= 0)
+		xfrm_state_put(xfrm_vec[xfrm_nr]);
+	kfree_skb(skb);
+	return 0;
+}
+
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
diff -Nru a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c
--- a/net/ipv4/xfrm_policy.c	Wed Feb 19 14:32:20 2003
+++ b/net/ipv4/xfrm_policy.c	Wed Mar  5 15:45:36 2003
@@ -1,6 +1,16 @@
+/* Changes
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ */
+
 #include <linux/config.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
 
 DECLARE_MUTEX(xfrm_cfg_sem);
 
@@ -10,6 +20,11 @@
 struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 extern struct dst_ops xfrm4_dst_ops;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+extern struct dst_ops xfrm6_dst_ops;
+#endif
+
+static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
 
 /* Limited flow cache. Its function now is to accelerate search for
  * policy rules.
@@ -48,6 +63,24 @@
 	return hash & (FLOWCACHE_HASH_SIZE-1);
 }
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static inline u32 flow_hash6(struct flowi *fl)
+{
+	u32 hash = fl->fl6_src->s6_addr32[2] ^
+		   fl->fl6_src->s6_addr32[3] ^ 
+		   fl->uli_u.ports.sport;
+
+	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
+
+	hash ^= fl->fl6_dst->s6_addr32[2] ^
+		fl->fl6_dst->s6_addr32[3] ^ 
+		fl->uli_u.ports.dport;
+	hash ^= (hash >> 10);
+	hash ^= (hash >> 20);
+	return hash & (FLOWCACHE_HASH_SIZE-1);
+}
+#endif
+
 static int flow_lwm = 2*FLOWCACHE_HASH_SIZE;
 static int flow_hwm = 4*FLOWCACHE_HASH_SIZE;
 
@@ -77,13 +110,27 @@
 	}
 }
 
-struct xfrm_policy *flow_lookup(int dir, struct flowi *fl)
+struct xfrm_policy *flow_lookup(int dir, struct flowi *fl, 
+				unsigned short family)
 {
-	struct xfrm_policy *pol;
+	struct xfrm_policy *pol = NULL;
 	struct flow_entry *fle;
-	u32 hash = flow_hash(fl);
+	u32 hash;
 	int cpu;
 
+	switch (family) {
+	case AF_INET:
+		hash = flow_hash(fl);
+		break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		hash = flow_hash6(fl);
+		break;
+#endif
+	default:
+		return NULL;
+	}
+
 	local_bh_disable();
 	cpu = smp_processor_id();
 
@@ -101,7 +148,7 @@
 		}
 	}
 
-	pol = xfrm_policy_lookup(dir, fl);
+	pol = xfrm_policy_lookup(dir, fl, family);
 
 	if (fle) {
 		/* Stale flow entry found. Update it. */
@@ -199,6 +246,46 @@
 	return type;
 }
 
+static  xfrm_dst_lookup_t *__xfrm_dst_lookup[AF_MAX];
+rwlock_t xdl_lock = RW_LOCK_UNLOCKED;
+
+int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, 
+			     unsigned short family)
+{
+	int err = 0;
+
+	write_lock(&xdl_lock);
+	if (__xfrm_dst_lookup[family])
+		err = -ENOBUFS;
+	else { 
+		__xfrm_dst_lookup[family] = dst_lookup;
+	}
+	write_unlock(&xdl_lock);
+
+	return err;
+}
+
+void xfrm_dst_lookup_unregister(unsigned short family)
+{
+	write_lock(&xdl_lock);
+	if (__xfrm_dst_lookup[family])
+		__xfrm_dst_lookup[family] = 0;
+	write_unlock(&xdl_lock);
+}
+
+static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
+				  unsigned short family)
+{
+	int err = 0;
+	read_lock(&xdl_lock);
+	if (__xfrm_dst_lookup[family])
+		err = __xfrm_dst_lookup[family](dst, fl);
+	else
+		err = -EINVAL;
+	read_unlock(&xdl_lock);
+	return err;
+}
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static struct xfrm_type *xfrm6_type_map[256];
 static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
@@ -506,15 +593,32 @@
 
 /* Find policy to apply to this flow. */
 
-struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl)
+struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, 
+				       unsigned short family)
 {
 	struct xfrm_policy *pol;
 
 	read_lock_bh(&xfrm_policy_lock);
 	for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) {
 		struct xfrm_selector *sel = &pol->selector;
+		int match;
+
+		if (pol->family != family)
+			continue;
 
-		if (xfrm4_selector_match(sel, fl)) {
+		switch (family) {
+		case AF_INET:
+			match = xfrm4_selector_match(sel, fl);
+			break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			match = xfrm6_selector_match(sel, fl);
+			break;
+#endif
+		default:
+			match = 0;
+		}
+		if (match) {
 			atomic_inc(&pol->refcnt);
 			break;
 		}
@@ -529,7 +633,21 @@
 
 	read_lock_bh(&xfrm_policy_lock);
 	if ((pol = sk->policy[dir]) != NULL) {
-		if (xfrm4_selector_match(&pol->selector, fl))
+		int match;
+
+		switch (sk->family) {
+		case AF_INET:
+			match = xfrm4_selector_match(&pol->selector, fl);
+			break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			match = xfrm6_selector_match(&pol->selector, fl);
+			break;
+#endif
+		default:
+			match = 0;
+		}
+		if (match)
 			atomic_inc(&pol->refcnt);
 		else
 			pol = NULL;
@@ -630,8 +748,8 @@
 /* Resolve list of templates for the flow, given policy. */
 
 static int
-xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
-		  struct xfrm_state **xfrm)
+xfrm4_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
+		   struct xfrm_state **xfrm)
 {
 	int nx;
 	int i, error;
@@ -649,7 +767,7 @@
 			local = tmpl->saddr.xfrm4_addr;
 		}
 
-		x = xfrm_state_find(remote, local, fl, tmpl, policy, &error);
+		x = xfrm4_state_find(remote, local, fl, tmpl, policy, &error);
 
 		if (x && x->km.state == XFRM_STATE_VALID) {
 			xfrm[nx++] = x;
@@ -674,6 +792,53 @@
 	return error;
 }
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static int
+xfrm6_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
+		  struct xfrm_state **xfrm)
+{
+	int nx;
+	int i, error;
+	struct in6_addr *daddr = fl->fl6_dst;
+	struct in6_addr *saddr = fl->fl6_src;
+
+	for (nx=0, i = 0; i < policy->xfrm_nr; i++) {
+		struct xfrm_state *x=NULL;
+		struct in6_addr *remote = daddr;
+		struct in6_addr *local = saddr;
+		struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
+
+		if (tmpl->mode) {
+			remote = (struct in6_addr*)&tmpl->id.daddr;
+			local = (struct in6_addr*)&tmpl->saddr;
+		}
+
+		x = xfrm6_state_find(remote, local, fl, tmpl, policy, &error);
+
+		if (x && x->km.state == XFRM_STATE_VALID) {
+			xfrm[nx++] = x;
+			daddr = remote;
+			saddr = local;
+			continue;
+		}
+		if (x) {
+			error = (x->km.state == XFRM_STATE_ERROR ?
+				 -EINVAL : -EAGAIN);
+			xfrm_state_put(x);
+		}
+
+		if (!tmpl->optional)
+			goto fail;
+	}
+	return nx;
+
+fail:
+	for (nx--; nx>=0; nx--)
+		xfrm_state_put(xfrm[nx]);
+	return error;
+}
+#endif
+
 /* Check that the bundle accepts the flow and its components are
  * still valid.
  */
@@ -694,6 +859,24 @@
 	return 0;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int xfrm6_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
+{
+	do {
+		if (xdst->u.dst.ops != &xfrm6_dst_ops)
+			return 1;
+
+		if (!xfrm6_selector_match(&xdst->u.dst.xfrm->sel, fl))
+			return 0;
+		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
+		    xdst->u.dst.path->obsolete > 0)
+			return 0;
+		xdst = (struct xfrm_dst*)xdst->u.dst.child;
+	} while (xdst);
+	return 0;
+}
+#endif
+
 
 /* Allocate chain of dst_entry's, attach known xfrm's, calculate
  * all the metrics... Shortly, bundle a bundle.
@@ -728,7 +911,7 @@
 		else {
 			dst_prev->child = dst1;
 			dst1->flags |= DST_NOHASH;
-			dst_clone(dst1);
+			dst_hold(dst1);
 		}
 		dst_prev = dst1;
 		if (xfrm[i]->props.mode) {
@@ -744,11 +927,11 @@
 						       .saddr = local }
 					           }
 				         };
-		err = __ip_route_output_key(&rt, &fl_tunnel);
+		err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET);
 		if (err)
 			goto error;
 	} else {
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 	}
 	dst_prev->child = &rt->u.dst;
 	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
@@ -791,6 +974,97 @@
 	return err;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int
+xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
+		   struct flowi *fl, struct dst_entry **dst_p)
+{
+	struct dst_entry *dst, *dst_prev;
+	struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
+	struct rt6_info *rt  = rt0;
+	struct in6_addr *remote = fl->fl6_dst;
+	struct in6_addr *local  = fl->fl6_src;
+	int i;
+	int err = 0;
+	int header_len = 0;
+
+	dst = dst_prev = NULL;
+
+	for (i = 0; i < nx; i++) {
+		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
+
+		if (unlikely(dst1 == NULL)) {
+			err = -ENOBUFS;
+			goto error;
+		}
+
+		dst1->xfrm = xfrm[i];
+		if (!dst)
+			dst = dst1;
+		else {
+			dst_prev->child = dst1;
+			dst1->flags |= DST_NOHASH;
+			dst_clone(dst1);
+		}
+		dst_prev = dst1;
+		if (xfrm[i]->props.mode) {
+			remote = (struct in6_addr*)&xfrm[i]->id.daddr;
+			local  = (struct in6_addr*)&xfrm[i]->props.saddr;
+		}
+		header_len += xfrm[i]->props.header_len;
+	}
+
+	if (ipv6_addr_cmp(remote, fl->fl6_dst)) {
+		struct flowi fl_tunnel = { .nl_u = { .ip6_u =
+						     { .daddr = remote,
+						       .saddr = local }
+					           }
+				         };
+		err = xfrm_dst_lookup((struct xfrm_dst**)&dst, &fl_tunnel, AF_INET6);
+		if (err)
+			goto error;
+	} else {
+		dst_clone(&rt->u.dst);
+	}
+	dst_prev->child = &rt->u.dst;
+	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+		x->u.rt.fl = *fl;
+
+		dst_prev->dev = rt->u.dst.dev;
+		if (rt->u.dst.dev)
+			dev_hold(rt->u.dst.dev);
+		dst_prev->obsolete	= -1;
+		dst_prev->flags	       |= DST_HOST;
+		dst_prev->lastuse	= jiffies;
+		dst_prev->header_len	= header_len;
+		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
+		dst_prev->path		= &rt->u.dst;
+
+		/* Copy neighbout for reachability confirmation */
+		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
+		dst_prev->input		= rt->u.dst.input;
+		dst_prev->output	= dst_prev->xfrm->type->output;
+		/* Sheit... I remember I did this right. Apparently,
+		 * it was magically lost, so this code needs audit */
+		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
+		x->u.rt6.rt6i_metric   = rt0->rt6i_metric;
+		x->u.rt6.rt6i_node     = rt0->rt6i_node;
+		x->u.rt6.rt6i_hoplimit = rt0->rt6i_hoplimit;
+		x->u.rt6.rt6i_gateway  = rt0->rt6i_gateway;
+		memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); 
+		header_len -= x->u.dst.xfrm->props.header_len;
+	}
+	*dst_p = dst;
+	return 0;
+
+error:
+	if (dst)
+		dst_free(dst);
+	return err;
+}
+#endif
+
 /* Main function: finds/creates a bundle for given flow.
  *
  * At the moment we eat a raw IP route. Mostly to speed up lookups
@@ -806,9 +1080,7 @@
 	int nx = 0;
 	int err;
 	u32 genid;
-
-	fl->oif = rt->u.dst.dev->ifindex;
-	fl->fl4_src = rt->rt_src;
+	u16 family = (*dst_p)->ops->family;
 
 restart:
 	genid = xfrm_policy_genid;
@@ -821,11 +1093,12 @@
 		if ((rt->u.dst.flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
 			return 0;
 
-		policy = flow_lookup(XFRM_POLICY_OUT, fl);
-		if (!policy)
-			return 0;
+		policy = flow_lookup(XFRM_POLICY_OUT, fl, family);
 	}
 
+	if (!policy)
+		return 0;
+
 	policy->curlft.use_time = (unsigned long)xtime.tv_sec;
 
 	switch (policy->action) {
@@ -846,23 +1119,48 @@
 		 * LATER: help from flow cache. It is optional, this
 		 * is required only for output policy.
 		 */
-		read_lock_bh(&policy->lock);
-		for (dst = policy->bundles; dst; dst = dst->next) {
-			struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
-			if (xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
-			    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
-			    xdst->u.rt.fl.oif == fl->oif &&
-			    xfrm_bundle_ok(xdst, fl)) {
-				dst_clone(dst);
+		if (family == AF_INET) {
+			fl->oif = rt->u.dst.dev->ifindex;
+			fl->fl4_src = rt->rt_src;
+			read_lock_bh(&policy->lock);
+			for (dst = policy->bundles; dst; dst = dst->next) {
+				struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
+				if (xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
+				    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+				    xdst->u.rt.fl.oif == fl->oif &&
+				    xfrm_bundle_ok(xdst, fl)) {
+					dst_clone(dst);
+					break;
+				}
+			}
+			read_unlock_bh(&policy->lock);
+			if (dst)
 				break;
+			nx = xfrm4_tmpl_resolve(policy, fl, xfrm);
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		} else if (family == AF_INET6) {
+			read_lock_bh(&policy->lock);
+			for (dst = policy->bundles; dst; dst = dst->next) {
+				struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
+				if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, fl->fl6_dst) &&
+				    !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, fl->fl6_src) &&
+				    xfrm6_bundle_ok(xdst, fl)) {
+					dst_clone(dst);
+					break;
+				}
 			}
+			read_unlock_bh(&policy->lock);
+			if (dst)
+				break;
+			nx = xfrm6_tmpl_resolve(policy, fl, xfrm);
+#endif
+		} else {
+			return -EINVAL;
 		}
-		read_unlock_bh(&policy->lock);
 
 		if (dst)
 			break;
 
-		nx = xfrm_tmpl_resolve(policy, fl, xfrm);
 		if (unlikely(nx<0)) {
 			err = nx;
 			if (err == -EAGAIN) {
@@ -873,7 +1171,18 @@
 
 				__set_task_state(tsk, TASK_INTERRUPTIBLE);
 				add_wait_queue(&km_waitq, &wait);
-				err = xfrm_tmpl_resolve(policy, fl, xfrm);
+				switch (family) {
+				case AF_INET:
+					err = xfrm4_tmpl_resolve(policy, fl, xfrm);
+					break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+				case AF_INET6:
+					err = xfrm6_tmpl_resolve(policy, fl, xfrm);
+					break;
+#endif
+				default:
+					err = -EINVAL;
+				}
 				if (err == -EAGAIN)
 					schedule();
 				__set_task_state(tsk, TASK_RUNNING);
@@ -896,7 +1205,19 @@
 		}
 
 		dst = &rt->u.dst;
-		err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst);
+		switch (family) {
+		case AF_INET:
+			err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst);
+			break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			err = xfrm6_bundle_create(policy, xfrm, nx, fl, &dst);
+			break;
+#endif
+		default:
+			err = -EINVAL;
+		}
+			
 		if (unlikely(err)) {
 			int i;
 			for (i=0; i<nx; i++)
@@ -919,7 +1240,7 @@
 		}
 		dst->next = policy->bundles;
 		policy->bundles = dst;
-		dst_clone(dst);
+		dst_hold(dst);
 		write_unlock_bh(&policy->lock);
 	}
 	*dst_p = dst;
@@ -962,7 +1283,7 @@
 }
 
 static void
-_decode_session(struct sk_buff *skb, struct flowi *fl)
+_decode_session4(struct sk_buff *skb, struct flowi *fl)
 {
 	struct iphdr *iph = skb->nh.iph;
 	u8 *xprth = skb->nh.raw + iph->ihl*4;
@@ -1008,18 +1329,109 @@
 	fl->fl4_src = iph->saddr;
 }
 
-int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static inline int
+xfrm6_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
+{
+	return	x->id.proto == tmpl->id.proto &&
+		(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
+		x->props.mode == tmpl->mode &&
+		(tmpl->aalgos & (1<<x->props.aalgo)) &&
+		(!x->props.mode || !ipv6_addr_any((struct in6_addr*)&x->props.saddr) ||
+		 !ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
+}
+
+static inline int
+xfrm6_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx)
+{
+	for (; idx < sp->len; idx++) {
+		if (xfrm6_state_ok(tmpl, sp->xvec[idx]))
+			return ++idx;
+	}
+	return -1;
+}
+
+static inline void
+_decode_session6(struct sk_buff *skb, struct flowi *fl)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6hdr *hdr = skb->nh.ipv6h;
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+
+	fl->fl6_dst = &hdr->daddr;
+	fl->fl6_src = &hdr->saddr;
+
+	while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+		switch (nexthdr) {
+		case NEXTHDR_ROUTING:
+		case NEXTHDR_HOP:
+		case NEXTHDR_DEST:
+			offset += ipv6_optlen(exthdr);
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case IPPROTO_UDP:
+		case IPPROTO_TCP:
+		case IPPROTO_SCTP:
+			if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) {
+				u16 *ports = (u16 *)exthdr;
+
+				fl->uli_u.ports.sport = ports[0];
+				fl->uli_u.ports.dport = ports[1];
+			}
+			return;
+
+		/* XXX Why are there these headers? */
+		case IPPROTO_AH:
+		case IPPROTO_ESP:
+		default:
+			fl->uli_u.spi = 0;
+			return;
+		};
+	}
+}
+#endif
+
+int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, 
+			unsigned short family)
 {
 	struct xfrm_policy *pol;
 	struct flowi fl;
 
-	_decode_session(skb, &fl);
+	switch (family) {
+	case AF_INET:
+		_decode_session4(skb, &fl);
+		break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		_decode_session6(skb, &fl);
+		break;
+#endif
+	default :
+		return 0;
+	}
 
 	/* First, check used SA against their selectors. */
 	if (skb->sp) {
 		int i;
+
 		for (i=skb->sp->len-1; i>=0; i--) {
-			if (!xfrm4_selector_match(&skb->sp->xvec[i]->sel, &fl))
+			int match;
+			switch (family) {
+			case AF_INET:
+				match = xfrm4_selector_match(&skb->sp->xvec[i]->sel, &fl);
+				break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+			case AF_INET6:
+				match = xfrm6_selector_match(&skb->sp->xvec[i]->sel, &fl);
+				break;
+#endif
+			default:
+				match = 0;
+			}
+			if (!match)
 				return 0;
 		}
 	}
@@ -1029,7 +1441,7 @@
 		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 
 	if (!pol)
-		pol = flow_lookup(dir, &fl);
+		pol = flow_lookup(dir, &fl, family);
 
 	if (!pol)
 		return 1;
@@ -1050,7 +1462,18 @@
 			 * are implied between each two transformations.
 			 */
 			for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
-				k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k);
+				switch (family) {
+				case AF_INET:
+					k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k);
+					break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+				case AF_INET6:
+					k = xfrm6_policy_ok(pol->xfrm_vec+i, sp, k);
+					break;
+#endif
+				default:
+					k = -1;
+				}
 				if (k < 0)
 					goto reject;
 			}
@@ -1064,18 +1487,29 @@
 	return 0;
 }
 
-int __xfrm_route_forward(struct sk_buff *skb)
+int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 {
 	struct flowi fl;
 
-	_decode_session(skb, &fl);
+	switch (family) {
+	case AF_INET:
+		_decode_session4(skb, &fl);
+		break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		_decode_session6(skb, &fl);
+		break;
+#endif
+	default:
+		return 0;
+	}
 
 	return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
 }
 
 /* Optimize later using cookies and generation ids. */
 
-static struct dst_entry *xfrm4_dst_check(struct dst_entry *dst, u32 cookie)
+static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
 {
 	struct dst_entry *child = dst;
 
@@ -1091,19 +1525,19 @@
 	return dst;
 }
 
-static void xfrm4_dst_destroy(struct dst_entry *dst)
+static void xfrm_dst_destroy(struct dst_entry *dst)
 {
 	xfrm_state_put(dst->xfrm);
 	dst->xfrm = NULL;
 }
 
-static void xfrm4_link_failure(struct sk_buff *skb)
+static void xfrm_link_failure(struct sk_buff *skb)
 {
 	/* Impossible. Such dst must be popped before reaches point of failure. */
 	return;
 }
 
-static struct dst_entry *xfrm4_negative_advice(struct dst_entry *dst)
+static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst)
 {
 	if (dst) {
 		if (dst->obsolete) {
@@ -1114,8 +1548,7 @@
 	return dst;
 }
 
-
-static int xfrm4_garbage_collect(void)
+static void __xfrm_garbage_collect(void)
 {
 	int i;
 	struct xfrm_policy *pol;
@@ -1145,10 +1578,22 @@
 		gc_list = dst->next;
 		dst_free(dst);
 	}
+}
 
+static inline int xfrm4_garbage_collect(void)
+{
+	__xfrm_garbage_collect();
 	return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static inline int xfrm6_garbage_collect(void)
+{
+	__xfrm_garbage_collect();
+	return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
+}
+#endif
+
 static int bundle_depends_on(struct dst_entry *dst, struct xfrm_state *x)
 {
 	do {
@@ -1192,7 +1637,7 @@
 	return 0;
 }
 
-
+ 
 static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 	struct dst_entry *path = dst->path;
@@ -1203,6 +1648,18 @@
 	path->ops->update_pmtu(path, mtu);
 }
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+	struct dst_entry *path = dst->path;
+
+	if (mtu >= 1280 && mtu < dst_pmtu(dst))
+		return;
+
+	path->ops->update_pmtu(path, mtu);
+}
+#endif
+
 /* Well... that's _TASK_. We need to scan through transformation
  * list and figure out what mss tcp should generate in order to
  * final datagram fit to mtu. Mama mia... :-)
@@ -1212,7 +1669,7 @@
  *
  * Consider this function as something like dark humour. :-)
  */
-static int xfrm4_get_mss(struct dst_entry *dst, u32 mtu)
+static int xfrm_get_mss(struct dst_entry *dst, u32 mtu)
 {
 	int res = mtu - dst->header_len;
 
@@ -1247,16 +1704,32 @@
 	.family =		AF_INET,
 	.protocol =		__constant_htons(ETH_P_IP),
 	.gc =			xfrm4_garbage_collect,
-	.check =		xfrm4_dst_check,
-	.destroy =		xfrm4_dst_destroy,
-	.negative_advice =	xfrm4_negative_advice,
-	.link_failure =		xfrm4_link_failure,
+	.check =		xfrm_dst_check,
+	.destroy =		xfrm_dst_destroy,
+	.negative_advice =	xfrm_negative_advice,
+	.link_failure =		xfrm_link_failure,
 	.update_pmtu =		xfrm4_update_pmtu,
-	.get_mss =		xfrm4_get_mss,
+	.get_mss =		xfrm_get_mss,
 	.gc_thresh =		1024,
 	.entry_size =		sizeof(struct xfrm_dst),
 };
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+struct dst_ops xfrm6_dst_ops = {
+	.family =		AF_INET6,
+	.protocol =		__constant_htons(ETH_P_IPV6),
+	.gc =			xfrm6_garbage_collect,
+	.check =		xfrm_dst_check,
+	.destroy =		xfrm_dst_destroy,
+	.negative_advice =	xfrm_negative_advice,
+	.link_failure =		xfrm_link_failure,
+	.update_pmtu =		xfrm6_update_pmtu,
+	.get_mss =		xfrm_get_mss,
+	.gc_thresh =		1024,
+	.entry_size =		sizeof(struct xfrm_dst),
+};
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
+
 void __init xfrm_init(void)
 {
 	xfrm4_dst_ops.kmem_cachep = kmem_cache_create("xfrm4_dst_cache",
@@ -1267,8 +1740,12 @@
 	if (!xfrm4_dst_ops.kmem_cachep)
 		panic("IP: failed to allocate xfrm4_dst_cache\n");
 
-	flow_cache_init();
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	xfrm6_dst_ops.kmem_cachep = xfrm4_dst_ops.kmem_cachep;
+#endif
 
+	flow_cache_init();
 	xfrm_state_init();
 	xfrm_input_init();
 }
+
diff -Nru a/net/ipv4/xfrm_state.c b/net/ipv4/xfrm_state.c
--- a/net/ipv4/xfrm_state.c	Thu Feb 13 01:26:32 2003
+++ b/net/ipv4/xfrm_state.c	Wed Mar  5 15:45:36 2003
@@ -1,3 +1,11 @@
+/* Changes
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ */
+
 #include <net/xfrm.h>
 #include <linux/pfkeyv2.h>
 #include <linux/ipsec.h>
@@ -207,8 +215,8 @@
 }
 
 struct xfrm_state *
-xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
-		struct xfrm_policy *pol, int *err)
+xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
+		 struct xfrm_policy *pol, int *err)
 {
 	unsigned h = ntohl(daddr);
 	struct xfrm_state *x;
@@ -290,6 +298,7 @@
 			x->props.saddr.xfrm4_addr = saddr;
 		x->props.mode = tmpl->mode;
 		x->props.reqid = tmpl->reqid;
+		x->props.family = AF_INET;
 
 		if (km_query(x, tmpl, pol) == 0) {
 			x->km.state = XFRM_STATE_ACQ;
@@ -318,14 +327,133 @@
 	return x;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct xfrm_state *
+xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
+		struct xfrm_policy *pol, int *err)
+{
+	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
+	struct xfrm_state *x;
+	int acquire_in_progress = 0;
+	int error = 0;
+	struct xfrm_state *best = NULL;
+
+	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+
+	spin_lock_bh(&xfrm_state_lock);
+	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
+		if (x->props.family == AF_INET6&&
+		    !ipv6_addr_cmp(daddr, (struct in6_addr *)&x->id.daddr) &&
+		    x->props.reqid == tmpl->reqid &&
+		    (!ipv6_addr_cmp(saddr, (struct in6_addr *)&x->props.saddr)|| ipv6_addr_any(saddr)) &&
+		    tmpl->mode == x->props.mode &&
+		    tmpl->id.proto == x->id.proto) {
+			/* Resolution logic:
+			   1. There is a valid state with matching selector.
+			      Done.
+			   2. Valid state with inappropriate selector. Skip.
+
+			   Entering area of "sysdeps".
+
+			   3. If state is not valid, selector is temporary,
+			      it selects only session which triggered
+			      previous resolution. Key manager will do
+			      something to install a state with proper
+			      selector.
+			 */
+			if (x->km.state == XFRM_STATE_VALID) {
+				if (!xfrm6_selector_match(&x->sel, fl))
+					continue;
+				if (!best ||
+				    best->km.dying > x->km.dying ||
+				    (best->km.dying == x->km.dying &&
+				     best->curlft.add_time < x->curlft.add_time))
+					best = x;
+			} else if (x->km.state == XFRM_STATE_ACQ) {
+				acquire_in_progress = 1;
+			} else if (x->km.state == XFRM_STATE_ERROR ||
+				   x->km.state == XFRM_STATE_EXPIRED) {
+				if (xfrm6_selector_match(&x->sel, fl))
+					error = 1;
+			}
+		}
+	}
+
+	if (best) {
+		atomic_inc(&best->refcnt);
+		spin_unlock_bh(&xfrm_state_lock);
+		return best;
+	}
+	x = NULL;
+	if (!error && !acquire_in_progress &&
+	    ((x = xfrm_state_alloc()) != NULL)) {
+		/* Initialize temporary selector matching only
+		 * to current session. */
+		memcpy(&x->sel.daddr, fl->fl6_dst, sizeof(struct in6_addr));
+		memcpy(&x->sel.saddr, fl->fl6_src, sizeof(struct in6_addr));
+		x->sel.dport = fl->uli_u.ports.dport;
+		x->sel.dport_mask = ~0;
+		x->sel.sport = fl->uli_u.ports.sport;
+		x->sel.sport_mask = ~0;
+		x->sel.prefixlen_d = 128;
+		x->sel.prefixlen_s = 128;
+		x->sel.proto = fl->proto;
+		x->sel.ifindex = fl->oif;
+		x->id = tmpl->id;
+		if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
+			memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
+		memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
+		if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
+			memcpy(&x->props.saddr, &saddr, sizeof(x->sel.saddr));
+		x->props.mode = tmpl->mode;
+		x->props.reqid = tmpl->reqid;
+		x->props.family = AF_INET6;
+
+		if (km_query(x, tmpl, pol) == 0) {
+			x->km.state = XFRM_STATE_ACQ;
+			list_add_tail(&x->bydst, xfrm_state_bydst+h);
+			atomic_inc(&x->refcnt);
+			if (x->id.spi) {
+				struct in6_addr *addr = (struct in6_addr*)&x->id.daddr;
+				h = ntohl((addr->s6_addr32[2]^addr->s6_addr32[3])^x->id.spi^x->id.proto);
+				h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+				list_add(&x->byspi, xfrm_state_byspi+h);
+				atomic_inc(&x->refcnt);
+			}
+			x->lft.hard_add_expires_seconds = ACQ_EXPIRES;
+			atomic_inc(&x->refcnt);
+			mod_timer(&x->timer, ACQ_EXPIRES*HZ);
+		} else {
+			x->km.state = XFRM_STATE_DEAD;
+			xfrm_state_put(x);
+			x = NULL;
+			error = 1;
+		}
+	}
+	spin_unlock_bh(&xfrm_state_lock);
+	if (!x)
+		*err = acquire_in_progress ? -EAGAIN :
+			(error ? -ESRCH : -ENOMEM);
+	return x;
+}
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
+
 void xfrm_state_insert(struct xfrm_state *x)
 {
 	unsigned h = 0;
 
-	if (x->props.family == AF_INET)
+	switch (x->props.family) {
+	case AF_INET:
 		h = ntohl(x->id.daddr.xfrm4_addr);
-	else if (x->props.family == AF_INET6)
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
 		h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]);
+		break;
+#endif
+	default:
+		return;
+	}
 
 	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
 
@@ -384,7 +512,7 @@
 }
 
 struct xfrm_state *
-xfrm_state_lookup(u32 daddr, u32 spi, u8 proto)
+xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto)
 {
 	unsigned h = ntohl(daddr^spi^proto);
 	struct xfrm_state *x;
@@ -406,6 +534,31 @@
 	return NULL;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct xfrm_state *
+xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto)
+{
+	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto);
+	struct xfrm_state *x;
+
+	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+
+	spin_lock_bh(&xfrm_state_lock);
+	list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
+		if (x->props.family == AF_INET6 &&
+		    spi == x->id.spi &&
+		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
+		    proto == x->id.proto) {
+			atomic_inc(&x->refcnt);
+			spin_unlock_bh(&xfrm_state_lock);
+			return x;
+		}
+	}
+	spin_unlock_bh(&xfrm_state_lock);
+	return NULL;
+}
+#endif
+
 struct xfrm_state *
 xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
 {
@@ -445,7 +598,59 @@
 		x0->km.state = XFRM_STATE_ACQ;
 		x0->id.daddr.xfrm4_addr = daddr;
 		x0->id.proto = proto;
+		x0->props.mode = mode;
+		x0->props.reqid = reqid;
 		x0->props.family = AF_INET;
+		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
+		atomic_inc(&x0->refcnt);
+		mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
+		atomic_inc(&x0->refcnt);
+		list_add_tail(&x0->bydst, xfrm_state_bydst+h);
+		wake_up(&km_waitq);
+	}
+	spin_unlock_bh(&xfrm_state_lock);
+	return x0;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct xfrm_state *
+xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create)
+{
+	struct xfrm_state *x, *x0;
+	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
+
+	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+	x0 = NULL;
+
+	spin_lock_bh(&xfrm_state_lock);
+	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
+		if (x->props.family == AF_INET6 &&
+		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
+		    mode == x->props.mode &&
+		    proto == x->id.proto &&
+		    !ipv6_addr_cmp(saddr, (struct in6_addr *)x->props.saddr.a6) &&
+		    reqid == x->props.reqid &&
+		    x->km.state == XFRM_STATE_ACQ) {
+			    if (!x0)
+				    x0 = x;
+			    if (x->id.spi)
+				    continue;
+			    x0 = x;
+			    break;
+		    }
+	}
+	if (x0) {
+		atomic_inc(&x0->refcnt);
+	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
+		memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr));
+		memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr));
+		x0->sel.prefixlen_d = 128;
+		x0->sel.prefixlen_s = 128;
+		memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr));
+		x0->km.state = XFRM_STATE_ACQ;
+		memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr));
+		x0->id.proto = proto;
+		x0->props.family = AF_INET6;
 		x0->props.mode = mode;
 		x0->props.reqid = reqid;
 		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
@@ -458,6 +663,7 @@
 	spin_unlock_bh(&xfrm_state_lock);
 	return x0;
 }
+#endif
 
 /* Silly enough, but I'm lazy to build resolution list */
 
@@ -491,7 +697,18 @@
 		return;
 
 	if (minspi == maxspi) {
-		x0 = xfrm_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
+		switch(x->props.family) {
+		case AF_INET:
+			x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
+			break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
+			break;
+#endif
+		default:
+			x0 = NULL;
+		}
 		if (x0) {
 			xfrm_state_put(x0);
 			return;
@@ -503,7 +720,18 @@
 		maxspi = ntohl(maxspi);
 		for (h=0; h<maxspi-minspi+1; h++) {
 			spi = minspi + net_random()%(maxspi-minspi+1);
-			x0 = xfrm_state_lookup(x->id.daddr.xfrm4_addr, htonl(spi), x->id.proto);
+			switch(x->props.family) {
+			case AF_INET:
+				x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
+				break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+			case AF_INET6:
+				x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
+				break;
+#endif
+			default:
+				x0 = NULL;
+			}
 			if (x0 == NULL)
 				break;
 			xfrm_state_put(x0);
@@ -512,7 +740,18 @@
 	}
 	if (x->id.spi) {
 		spin_lock_bh(&xfrm_state_lock);
-		h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
+		switch(x->props.family) {
+		case AF_INET:
+			h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
+			break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
+			break;
+#endif
+		default:
+			h = 0;	/* XXX */
+		}
 		h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
 		list_add(&x->byspi, xfrm_state_byspi+h);
 		atomic_inc(&x->refcnt);
@@ -605,14 +844,21 @@
 	int i;
 
 	for (i=0; i<n; i++) {
-		if (x[i]->props.family == AF_INET &&
-		    !xfrm4_selector_match(&x[i]->sel, fl))
-			return -EINVAL;
+		int match;
+		switch(x[i]->props.family) {
+		case AF_INET:
+			match = xfrm4_selector_match(&x[i]->sel, fl);
+			break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		if (x[i]->props.family == AF_INET6 &&
-		    !xfrm6_selector_match(&x[i]->sel, fl))
-			return -EINVAL;
+		case AF_INET6:
+			match = xfrm6_selector_match(&x[i]->sel, fl);
+			break;
 #endif
+		default:
+			match = 0;
+		}
+		if (!match)
+			return -EINVAL;
 	}
 	return 0;
 }
@@ -680,7 +926,7 @@
 	err = -EINVAL;
 	read_lock(&xfrm_km_lock);
 	list_for_each_entry(km, &xfrm_km_list, list) {
-		pol = km->compile_policy(optname, data, optlen, &err);
+		pol = km->compile_policy(sk->family, optname, data, optlen, &err);
 		if (err >= 0)
 			break;
 	}
@@ -722,118 +968,3 @@
 	}
 }
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-struct xfrm_state *
-xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto)
-{
-	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto);
-	struct xfrm_state *x;
-
-	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
-
-	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
-		if (x->props.family == AF_INET6 &&
-		    spi == x->id.spi &&
-		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
-		    proto == x->id.proto) {
-			atomic_inc(&x->refcnt);
-			spin_unlock_bh(&xfrm_state_lock);
-			return x;
-		}
-	}
-	spin_unlock_bh(&xfrm_state_lock);
-	return NULL;
-}
-
-struct xfrm_state *
-xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create)
-{
-	struct xfrm_state *x, *x0;
-	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
-
-	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
-	x0 = NULL;
-
-	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
-		if (x->props.family == AF_INET6 &&
-		    !memcmp(daddr, x->id.daddr.a6, sizeof(struct in6_addr)) &&
-		    mode == x->props.mode &&
-		    proto == x->id.proto &&
-		    !memcmp(saddr, x->props.saddr.a6, sizeof(struct in6_addr)) &&
-		    reqid == x->props.reqid &&
-		    x->km.state == XFRM_STATE_ACQ) {
-			    if (!x0)
-				    x0 = x;
-			    if (x->id.spi)
-				    continue;
-			    x0 = x;
-			    break;
-		    }
-	}
-	if (x0) {
-		atomic_inc(&x0->refcnt);
-	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
-		memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr));
-		memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr));
-		x0->sel.prefixlen_d = 128;
-		x0->sel.prefixlen_s = 128;
-		memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr));
-		x0->km.state = XFRM_STATE_ACQ;
-		memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr));
-		x0->id.proto = proto;
-		x0->props.family = AF_INET6;
-		x0->props.mode = mode;
-		x0->props.reqid = reqid;
-		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
-		atomic_inc(&x0->refcnt);
-		mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
-		atomic_inc(&x0->refcnt);
-		list_add_tail(&x0->bydst, xfrm_state_bydst+h);
-		wake_up(&km_waitq);
-	}
-	spin_unlock_bh(&xfrm_state_lock);
-	return x0;
-}
-
-void
-xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
-{
-	u32 h;
-	struct xfrm_state *x0;
-
-	if (x->id.spi)
-		return;
-
-	if (minspi == maxspi) {
-		x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
-		if (x0) {
-			xfrm_state_put(x0);
-			return;
-		}
-		x->id.spi = minspi;
-	} else {
-		u32 spi = 0;
-		minspi = ntohl(minspi);
-		maxspi = ntohl(maxspi);
-		for (h=0; h<maxspi-minspi+1; h++) {
-			spi = minspi + net_random()%(maxspi-minspi+1);
-			x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, htonl(spi), x->id.proto);
-			if (x0 == NULL)
-				break;
-			xfrm_state_put(x0);
-		}
-		x->id.spi = htonl(spi);
-	}
-	if (x->id.spi) {
-		spin_lock_bh(&xfrm_state_lock);
-		h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
-		h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
-		list_add(&x->byspi, xfrm_state_byspi+h);
-		atomic_inc(&x->refcnt);
-		spin_unlock_bh(&xfrm_state_lock);
-		wake_up(&km_waitq);
-	}
-}
-#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
diff -Nru a/net/ipv4/xfrm_user.c b/net/ipv4/xfrm_user.c
--- a/net/ipv4/xfrm_user.c	Wed Feb 19 14:02:51 2003
+++ b/net/ipv4/xfrm_user.c	Wed Mar  5 15:45:36 2003
@@ -234,8 +234,8 @@
 
 	switch (x->props.family) {
 	case AF_INET:
-		x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr,
-				       x->id.spi, x->id.proto);
+		x1 = xfrm4_state_lookup(x->props.saddr.xfrm4_addr,
+					x->id.spi, x->id.proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -265,7 +265,7 @@
 
 	switch (p->family) {
 	case AF_INET:
-		x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -395,7 +395,7 @@
 
 	switch (p->family) {
 	case AF_INET:
-		x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -538,6 +538,21 @@
 		return -EINVAL;
 	};
 
+	switch (p->family) {
+	case AF_INET:
+		break;
+
+	case AF_INET6:
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		break;
+#else
+		return  -EAFNOSUPPORT;
+#endif
+
+	default:
+		return -EINVAL;
+	};
+
 	return verify_policy_dir(p->dir);
 }
 
@@ -1057,7 +1072,8 @@
 /* User gives us xfrm_user_policy_info followed by an array of 0
  * or more templates.
  */
-struct xfrm_policy *xfrm_compile_policy(int opt, u8 *data, int len, int *dir)
+struct xfrm_policy *xfrm_compile_policy(u16 family, int opt,
+                                        u8 *data, int len, int *dir)
 {
 	struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
 	struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
diff -Nru a/net/ipv6/Kconfig b/net/ipv6/Kconfig
--- a/net/ipv6/Kconfig	Sun Feb 23 22:46:32 2003
+++ b/net/ipv6/Kconfig	Wed Mar  5 15:45:36 2003
@@ -17,5 +17,20 @@
 
 	  See <file:Documentation/networking/ip-sysctl.txt> for details.
 
-source "net/ipv6/netfilter/Kconfig"
+config INET6_AH
+	tristate "IPv6: AH transformation"
+	depends on IPV6
+	---help---
+	  Support for IPsec AH.
+
+	  If unsure, say Y.
+
+config INET6_ESP
+	tristate "IPv6: ESP transformation"
+	depends on IPV6
+	---help---
+	  Support for IPsec ESP.
 
+	  If unsure, say Y.
+
+source "net/ipv6/netfilter/Kconfig"
diff -Nru a/net/ipv6/Makefile b/net/ipv6/Makefile
--- a/net/ipv6/Makefile	Wed Feb 19 14:32:20 2003
+++ b/net/ipv6/Makefile	Wed Mar  5 15:45:36 2003
@@ -10,4 +10,6 @@
 		exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
 		ip6_flowlabel.o ipv6_syms.o
 
+obj-$(CONFIG_INET6_AH) += ah6.o
+obj-$(CONFIG_INET6_ESP) += esp6.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
diff -Nru a/net/ipv6/ah6.c b/net/ipv6/ah6.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/ipv6/ah6.c	Thu Mar  6 16:16:15 2003
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C)2002 USAGI/WIDE Project
+ * 
+ * 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
+ *
+ * Authors
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ * 	This file is derived from net/ipv4/ah.c.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#include <net/ah.h>
+#include <linux/crypto.h>
+#include <linux/pfkeyv2.h>
+#include <net/icmp.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+#include <asm/scatterlist.h>
+
+#define AH_HLEN_NOICV	12
+
+/* XXX no ipv6 ah specific */
+#define NIP6(addr) \
+	ntohs((addr).s6_addr16[0]),\
+	ntohs((addr).s6_addr16[1]),\
+	ntohs((addr).s6_addr16[2]),\
+	ntohs((addr).s6_addr16[3]),\
+	ntohs((addr).s6_addr16[4]),\
+	ntohs((addr).s6_addr16[5]),\
+	ntohs((addr).s6_addr16[6]),\
+	ntohs((addr).s6_addr16[7])
+
+int ah6_output(struct sk_buff *skb)
+{
+	int err;
+	int hdr_len = sizeof(struct ipv6hdr);
+	struct dst_entry *dst = skb->dst;
+	struct xfrm_state *x  = dst->xfrm;
+	struct ipv6hdr *iph = NULL;
+	struct ip_auth_hdr *ah;
+	struct ah_data *ahp;
+	u16 nh_offset = 0;
+	u8 nexthdr;
+printk(KERN_DEBUG "%s\n", __FUNCTION__);
+	if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL)
+		return -EINVAL;
+
+	spin_lock_bh(&x->lock);
+	if ((err = xfrm_state_check_expire(x)) != 0)
+		goto error;
+	if ((err = xfrm_state_check_space(x, skb)) != 0)
+		goto error;
+
+	if (x->props.mode) {
+		iph = skb->nh.ipv6h;
+		skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, x->props.header_len);
+		skb->nh.ipv6h->version = 6;
+		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+		skb->nh.ipv6h->nexthdr = IPPROTO_AH;
+		memcpy(&skb->nh.ipv6h->saddr, &x->props.saddr, sizeof(struct in6_addr));
+		memcpy(&skb->nh.ipv6h->daddr, &x->id.daddr, sizeof(struct in6_addr));
+		ah = (struct ip_auth_hdr*)(skb->nh.ipv6h+1);
+		ah->nexthdr = IPPROTO_IPV6;
+	} else {
+		hdr_len = skb->h.raw - skb->nh.raw;
+		iph = kmalloc(hdr_len, GFP_ATOMIC);
+		if (!iph) {
+			err = -ENOMEM;
+			goto error;
+		}
+		memcpy(iph, skb->data, hdr_len);
+		skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, x->props.header_len);
+		memcpy(skb->nh.ipv6h, iph, hdr_len);
+		nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_OUT);
+		if (nexthdr == 0)
+			goto error;
+
+		skb->nh.raw[nh_offset] = IPPROTO_AH;
+		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+		ah = (struct ip_auth_hdr*)(skb->nh.raw+hdr_len);
+		skb->h.raw = (unsigned char*) ah;
+		ah->nexthdr = nexthdr;
+	}
+
+	skb->nh.ipv6h->priority    = 0;
+	skb->nh.ipv6h->flow_lbl[0] = 0;
+	skb->nh.ipv6h->flow_lbl[1] = 0;
+	skb->nh.ipv6h->flow_lbl[2] = 0;
+	skb->nh.ipv6h->hop_limit    = 0;
+
+	ahp = x->data;
+	ah->hdrlen  = (XFRM_ALIGN8(ahp->icv_trunc_len +
+		AH_HLEN_NOICV) >> 2) - 2;
+
+	ah->reserved = 0;
+	ah->spi = x->id.spi;
+	ah->seq_no = htonl(++x->replay.oseq);
+	ahp->icv(ahp, skb, ah->auth_data);
+
+	if (x->props.mode) {
+		skb->nh.ipv6h->hop_limit   = iph->hop_limit;
+		skb->nh.ipv6h->priority    = iph->priority; 	
+		skb->nh.ipv6h->flow_lbl[0] = iph->flow_lbl[0];
+		skb->nh.ipv6h->flow_lbl[1] = iph->flow_lbl[1];
+		skb->nh.ipv6h->flow_lbl[2] = iph->flow_lbl[2];
+	} else {
+		memcpy(skb->nh.ipv6h, iph, hdr_len);
+		skb->nh.raw[nh_offset] = IPPROTO_AH;
+		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+		kfree (iph);
+	}
+
+	skb->nh.raw = skb->data;
+
+	x->curlft.bytes += skb->len;
+	x->curlft.packets++;
+	spin_unlock_bh(&x->lock);
+	if ((skb->dst = dst_pop(dst)) == NULL)
+		goto error_nolock;
+	return NET_XMIT_BYPASS;
+error:
+	spin_unlock_bh(&x->lock);
+error_nolock:
+	kfree_skb(skb);
+	return err;
+}
+
+int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int ah_hlen;
+	struct ipv6hdr *iph;
+	struct ipv6_auth_hdr *ah;
+	struct ah_data *ahp;
+	unsigned char *tmp_hdr = NULL;
+	int hdr_len = skb->h.raw - skb->nh.raw;
+	u8 nexthdr = 0;
+
+	if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
+		goto out;
+
+	ah = (struct ipv6_auth_hdr*)skb->data;
+	ahp = x->data;
+        ah_hlen = (ah->hdrlen + 2) << 2;
+
+        if (ah_hlen != XFRM_ALIGN8(ahp->icv_full_len + AH_HLEN_NOICV) &&
+            ah_hlen != XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV))
+                goto out;
+
+	if (!pskb_may_pull(skb, ah_hlen))
+		goto out;
+
+	/* We are going to _remove_ AH header to keep sockets happy,
+	 * so... Later this can change. */
+	if (skb_cloned(skb) &&
+	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		goto out;
+
+	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+	if (!tmp_hdr)
+		goto out;
+	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
+	ah = (struct ipv6_auth_hdr*)skb->data;
+	iph = skb->nh.ipv6h;
+
+        {
+		u8 auth_data[ahp->icv_trunc_len];
+
+		memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
+		skb_push(skb, skb->data - skb->nh.raw);
+		ahp->icv(ahp, skb, ah->auth_data);
+		if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ipsec ah authentication error\n");
+			x->stats.integrity_failed++;
+			goto free_out;
+		}
+	}
+
+	nexthdr = ah->nexthdr;
+	skb->nh.raw = skb_pull(skb, (ah->hdrlen+2)<<2);
+	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+	skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+	skb_pull(skb, hdr_len);
+	skb->h.raw = skb->data;
+
+
+	kfree(tmp_hdr);
+
+	return nexthdr;
+
+free_out:
+	kfree(tmp_hdr);
+out:
+	return -EINVAL;
+}
+
+void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 
+	 int type, int code, int offset, __u32 info)
+{
+	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
+	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
+	struct xfrm_state *x;
+
+	if (type != ICMPV6_DEST_UNREACH ||
+	    type != ICMPV6_PKT_TOOBIG)
+		return;
+
+	x = xfrm6_state_lookup(&iph->daddr, ah->spi, IPPROTO_AH);
+	if (!x)
+		return;
+
+	printk(KERN_DEBUG "pmtu discvovery on SA AH/%08x/"
+			"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+	       ntohl(ah->spi), NIP6(iph->daddr));
+
+	xfrm_state_put(x);
+}
+
+static int ah6_init_state(struct xfrm_state *x, void *args)
+{
+	struct ah_data *ahp = NULL;
+	struct xfrm_algo_desc *aalg_desc;
+
+	/* null auth can use a zero length key */
+	if (x->aalg->alg_key_len > 512)
+		goto error;
+
+	ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
+	if (ahp == NULL)
+		return -ENOMEM;
+
+	memset(ahp, 0, sizeof(*ahp));
+
+	ahp->key = x->aalg->alg_key;
+	ahp->key_len = (x->aalg->alg_key_len+7)/8;
+	ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
+	if (!ahp->tfm)
+		goto error;
+	ahp->icv = ah_hmac_digest;
+	
+	/*
+	 * Lookup the algorithm description maintained by xfrm_algo,
+	 * verify crypto transform properties, and store information
+	 * we need for AH processing.  This lookup cannot fail here
+	 * after a successful crypto_alloc_tfm().
+	 */
+	aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
+	BUG_ON(!aalg_desc);
+
+	if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
+	    crypto_tfm_alg_digestsize(ahp->tfm)) {
+		printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
+		       x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm),
+		       aalg_desc->uinfo.auth.icv_fullbits/8);
+		goto error;
+	}
+	
+	ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
+	ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
+	
+	ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
+	if (!ahp->work_icv)
+		goto error;
+	
+	x->props.header_len = XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV);
+	if (x->props.mode)
+		x->props.header_len += 20;
+	x->data = ahp;
+
+	return 0;
+
+error:
+	if (ahp) {
+		if (ahp->work_icv)
+			kfree(ahp->work_icv);
+		if (ahp->tfm)
+			crypto_free_tfm(ahp->tfm);
+		kfree(ahp);
+	}
+	return -EINVAL;
+}
+
+static void ah6_destroy(struct xfrm_state *x)
+{
+	struct ah_data *ahp = x->data;
+
+	if (ahp->work_icv) {
+		kfree(ahp->work_icv);
+		ahp->work_icv = NULL;
+	}
+	if (ahp->tfm) {
+		crypto_free_tfm(ahp->tfm);
+		ahp->tfm = NULL;
+	}
+}
+
+static struct xfrm_type ah6_type =
+{
+	.description	= "AH6",
+	.proto	     	= IPPROTO_AH,
+	.init_state	= ah6_init_state,
+	.destructor	= ah6_destroy,
+	.input		= ah6_input,
+	.output		= ah6_output
+};
+
+static struct inet6_protocol ah6_protocol = {
+	.handler	=	xfrm6_rcv,
+	.err_handler	=	ah6_err,
+};
+
+int __init ah6_init(void)
+{
+	SET_MODULE_OWNER(&ah6_type);
+
+	if (xfrm6_register_type(&ah6_type) < 0) {
+		printk(KERN_INFO "ipv6 ah init: can't add xfrm type\n");
+		return -EAGAIN;
+	}
+
+	if (inet6_add_protocol(&ah6_protocol, IPPROTO_AH) < 0) {
+		printk(KERN_INFO "ipv6 ah init: can't add protocol\n");
+		xfrm6_unregister_type(&ah6_type);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static void __exit ah6_fini(void)
+{
+	if (inet6_del_protocol(&ah6_protocol, IPPROTO_AH) < 0)
+		printk(KERN_INFO "ipv6 ah close: can't remove protocol\n");
+
+	if (xfrm6_unregister_type(&ah6_type) < 0)
+		printk(KERN_INFO "ipv6 ah close: can't remove xfrm type\n");
+
+}
+
+module_init(ah6_init);
+module_exit(ah6_fini);
+
+MODULE_LICENSE("GPL");
diff -Nru a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/ipv6/esp6.c	Thu Mar  6 16:16:15 2003
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C)2002 USAGI/WIDE Project
+ * 
+ * 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
+ *
+ * Authors
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ * 	This file is derived from net/ipv4/esp.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#include <net/esp.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+#include <linux/pfkeyv2.h>
+#include <linux/random.h>
+#include <net/icmp.h>
+#include <net/ipv6.h>
+#include <linux/icmpv6.h>
+
+#define MAX_SG_ONSTACK 4
+
+/* BUGS:
+ * - we assume replay seqno is always present.
+ */
+
+/* Move to common area: it is shared with AH. */
+/* Common with AH after some work on arguments. */
+
+/* XXX no ipv6 esp specific */
+#define NIP6(addr) \
+	ntohs((addr).s6_addr16[0]),\
+	ntohs((addr).s6_addr16[1]),\
+	ntohs((addr).s6_addr16[2]),\
+	ntohs((addr).s6_addr16[3]),\
+	ntohs((addr).s6_addr16[4]),\
+	ntohs((addr).s6_addr16[5]),\
+	ntohs((addr).s6_addr16[6]),\
+	ntohs((addr).s6_addr16[7])
+
+static int get_offset(u8 *packet, u32 packet_len, u8 *nexthdr, struct ipv6_opt_hdr **prevhdr)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(packet + offset);
+	u8 nextnexthdr;
+
+	*nexthdr = ((struct ipv6hdr*)packet)->nexthdr;
+
+	while (offset + 1 < packet_len) {
+
+		switch (*nexthdr) {
+
+		case NEXTHDR_HOP:
+		case NEXTHDR_ROUTING:
+			offset += ipv6_optlen(exthdr);
+			*nexthdr = exthdr->nexthdr;
+			*prevhdr = exthdr;
+			exthdr = (struct ipv6_opt_hdr*)(packet + offset);
+			break;
+
+		case NEXTHDR_DEST:
+			nextnexthdr =
+				((struct ipv6_opt_hdr*)(packet + offset + ipv6_optlen(exthdr)))->nexthdr;
+			/* XXX We know the option is inner dest opt
+			   with next next header check. */
+			if (nextnexthdr != NEXTHDR_HOP &&
+		    	    nextnexthdr != NEXTHDR_ROUTING &&
+			    nextnexthdr != NEXTHDR_DEST) {
+					return offset;
+			}
+			offset += ipv6_optlen(exthdr);
+			*nexthdr = exthdr->nexthdr;
+			*prevhdr = exthdr;
+			exthdr = (struct ipv6_opt_hdr*)(packet + offset);
+			break;
+
+		default :
+			return offset;
+		}
+	}
+
+	return offset;
+}
+
+int esp6_output(struct sk_buff *skb)
+{
+	int err;
+	int hdr_len = 0;
+	struct dst_entry *dst = skb->dst;
+	struct xfrm_state *x  = dst->xfrm;
+	struct ipv6hdr *iph = NULL, *top_iph;
+	struct ip_esp_hdr *esph;
+	struct crypto_tfm *tfm;
+	struct esp_data *esp;
+	struct sk_buff *trailer;
+	struct ipv6_opt_hdr *prevhdr = NULL;
+	int blksize;
+	int clen;
+	int alen;
+	int nfrags;
+	u8 nexthdr;
+printk(KERN_DEBUG "%s\n", __FUNCTION__);
+	/* First, if the skb is not checksummed, complete checksum. */
+	if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL)
+		return -EINVAL;
+
+	spin_lock_bh(&x->lock);
+	if ((err = xfrm_state_check_expire(x)) != 0)
+		goto error;
+	if ((err = xfrm_state_check_space(x, skb)) != 0)
+		goto error;
+
+	err = -ENOMEM;
+
+	/* Strip IP header in transport mode. Save it. */
+
+	if (!x->props.mode) {
+		hdr_len = get_offset(skb->nh.raw, skb->len, &nexthdr, &prevhdr);
+		iph = kmalloc(hdr_len, GFP_ATOMIC);
+		if (!iph) {
+			err = -ENOMEM;
+			goto error;
+		}
+		memcpy(iph, skb->nh.raw, hdr_len);
+		__skb_pull(skb, hdr_len);
+	}
+
+	/* Now skb is pure payload to encrypt */
+
+	/* Round to block size */
+	clen = skb->len;
+
+	esp = x->data;
+	alen = esp->auth.icv_trunc_len;
+	tfm = esp->conf.tfm;
+	blksize = crypto_tfm_alg_blocksize(tfm);
+	clen = (clen + 2 + blksize-1)&~(blksize-1);
+	if (esp->conf.padlen)
+		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+
+	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
+		if (!x->props.mode && iph) kfree(iph);
+		goto error;
+	}
+
+	/* Fill padding... */
+	do {
+		int i;
+		for (i=0; i<clen-skb->len - 2; i++)
+			*(u8*)(trailer->tail + i) = i+1;
+	} while (0);
+	*(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
+	pskb_put(skb, trailer, clen - skb->len);
+
+	if (x->props.mode) {
+		iph = skb->nh.ipv6h;
+		top_iph = (struct ipv6hdr*)skb_push(skb, x->props.header_len);
+		esph = (struct ip_esp_hdr*)(top_iph+1);
+		*(u8*)(trailer->tail - 1) = IPPROTO_IPV6;
+		top_iph->version = 6;
+		top_iph->priority = iph->priority;
+		top_iph->flow_lbl[0] = iph->flow_lbl[0];
+		top_iph->flow_lbl[1] = iph->flow_lbl[1];
+		top_iph->flow_lbl[2] = iph->flow_lbl[2];
+		top_iph->nexthdr = IPPROTO_ESP;
+		top_iph->payload_len = htons(skb->len + alen);
+		top_iph->hop_limit = iph->hop_limit;
+		memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct ipv6hdr));
+		memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct ipv6hdr));
+	} else { 
+		/* XXX exthdr */
+		esph = (struct ip_esp_hdr*)skb_push(skb, x->props.header_len);
+		skb->h.raw = (unsigned char*)esph;
+		top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len);
+		memcpy(top_iph, iph, hdr_len);
+		kfree(iph);
+		top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr));
+		if (prevhdr) {
+			prevhdr->nexthdr = IPPROTO_ESP;
+		} else {
+			top_iph->nexthdr = IPPROTO_ESP;
+		}
+		*(u8*)(trailer->tail - 1) = nexthdr;
+	}
+
+	esph->spi = x->id.spi;
+	esph->seq_no = htonl(++x->replay.oseq);
+
+	if (esp->conf.ivlen)
+		crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+
+	do {
+		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
+		struct scatterlist *sg = sgbuf;
+
+		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
+			if (!sg)
+				goto error;
+		}
+		skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
+		crypto_cipher_encrypt(tfm, sg, sg, clen);
+		if (unlikely(sg != sgbuf))
+			kfree(sg);
+	} while (0);
+
+	if (esp->conf.ivlen) {
+		memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+		crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+	}
+
+	if (esp->auth.icv_full_len) {
+		esp->auth.icv(esp, skb, (u8*)esph-skb->data,
+			8+esp->conf.ivlen+clen, trailer->tail);
+		pskb_put(skb, trailer, alen);
+	}
+
+	skb->nh.raw = skb->data;
+
+	x->curlft.bytes += skb->len;
+	x->curlft.packets++;
+	spin_unlock_bh(&x->lock);
+	if ((skb->dst = dst_pop(dst)) == NULL)
+		goto error_nolock;
+	return NET_XMIT_BYPASS;
+
+error:
+	spin_unlock_bh(&x->lock);
+error_nolock:
+	kfree_skb(skb);
+	return err;
+}
+
+int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct ipv6hdr *iph;
+	struct ip_esp_hdr *esph;
+	struct esp_data *esp = x->data;
+	struct sk_buff *trailer;
+	int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+	int alen = esp->auth.icv_trunc_len;
+	int elen = skb->len - 8 - esp->conf.ivlen - alen;
+
+	int hdr_len = skb->h.raw - skb->nh.raw;
+	int nfrags;
+	u8 ret_nexthdr = 0;
+	unsigned char *tmp_hdr = NULL;
+
+	if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
+		goto out;
+
+	if (elen <= 0 || (elen & (blksize-1)))
+		goto out;
+
+	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+	if (!tmp_hdr)
+		goto out;
+	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
+
+	/* If integrity check is required, do this. */
+        if (esp->auth.icv_full_len) {
+		u8 sum[esp->auth.icv_full_len];
+		u8 sum1[alen];
+
+		esp->auth.icv(esp, skb, 0, skb->len-alen, sum);
+
+		if (skb_copy_bits(skb, skb->len-alen, sum1, alen))
+			BUG();
+
+		if (unlikely(memcmp(sum, sum1, alen))) {
+			x->stats.integrity_failed++;
+			goto out;
+		}
+	}
+
+	if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0)
+		goto out;
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	esph = (struct ip_esp_hdr*)skb->data;
+	iph = skb->nh.ipv6h;
+
+	/* Get ivec. This can be wrong, check against another impls. */
+	if (esp->conf.ivlen)
+		crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm));
+
+        {
+		u8 nexthdr[2];
+		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
+		struct scatterlist *sg = sgbuf;
+		u8 padlen;
+
+		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
+			if (!sg)
+				goto out;
+		}
+		skb_to_sgvec(skb, sg, 8+esp->conf.ivlen, elen);
+		crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
+		if (unlikely(sg != sgbuf))
+			kfree(sg);
+
+		if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
+			BUG();
+
+		padlen = nexthdr[0];
+		if (padlen+2 >= elen) {
+			if (net_ratelimit()) {
+				printk(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen);
+			}
+			goto out;
+		}
+		/* ... check padding bits here. Silly. :-) */ 
+
+		ret_nexthdr = nexthdr[1];
+		pskb_trim(skb, skb->len - alen - padlen - 2);
+		skb->h.raw = skb_pull(skb, 8 + esp->conf.ivlen);
+		skb->nh.raw += 8 + esp->conf.ivlen;
+		memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+	}
+	kfree(tmp_hdr);
+	return ret_nexthdr;
+
+out:
+	return -EINVAL;
+}
+
+static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
+{
+	struct esp_data *esp = x->data;
+	u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+
+	if (x->props.mode) {
+		mtu = (mtu + 2 + blksize-1)&~(blksize-1);
+	} else {
+		/* The worst case. */
+		mtu += 2 + blksize;
+	}
+	if (esp->conf.padlen)
+		mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+
+	return mtu + x->props.header_len + esp->auth.icv_full_len;
+}
+
+void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+		int type, int code, int offset, __u32 info)
+{
+	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
+	struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+offset);
+	struct xfrm_state *x;
+
+	if (type != ICMPV6_DEST_UNREACH ||
+	    type != ICMPV6_PKT_TOOBIG)
+		return;
+
+	x = xfrm6_state_lookup(&iph->daddr, esph->spi, IPPROTO_ESP);
+	if (!x)
+		return;
+	printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/"
+			"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 
+			ntohl(esph->spi), NIP6(iph->daddr));
+	xfrm_state_put(x);
+}
+
+void esp6_destroy(struct xfrm_state *x)
+{
+	struct esp_data *esp = x->data;
+
+	if (esp->conf.tfm) {
+		crypto_free_tfm(esp->conf.tfm);
+		esp->conf.tfm = NULL;
+	}
+	if (esp->conf.ivec) {
+		kfree(esp->conf.ivec);
+		esp->conf.ivec = NULL;
+	}
+	if (esp->auth.tfm) {
+		crypto_free_tfm(esp->auth.tfm);
+		esp->auth.tfm = NULL;
+	}
+	if (esp->auth.work_icv) {
+		kfree(esp->auth.work_icv);
+		esp->auth.work_icv = NULL;
+	}
+}
+
+int esp6_init_state(struct xfrm_state *x, void *args)
+{
+	struct esp_data *esp = NULL;
+
+	if (x->aalg) {
+		if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512)
+			goto error;
+	}
+	if (x->ealg == NULL || x->ealg->alg_key_len == 0)
+		goto error;
+
+	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
+	if (esp == NULL)
+		return -ENOMEM;
+
+	memset(esp, 0, sizeof(*esp));
+
+	if (x->aalg) {
+		struct xfrm_algo_desc *aalg_desc;
+
+		esp->auth.key = x->aalg->alg_key;
+		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
+		esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
+		if (esp->auth.tfm == NULL)
+			goto error;
+		esp->auth.icv = esp_hmac_digest;
+ 
+		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
+		BUG_ON(!aalg_desc);
+ 
+		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
+			crypto_tfm_alg_digestsize(esp->auth.tfm)) {
+				printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
+					x->aalg->alg_name,
+					crypto_tfm_alg_digestsize(esp->auth.tfm),
+					aalg_desc->uinfo.auth.icv_fullbits/8);
+				goto error;
+		}
+ 
+		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
+		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
+ 
+		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
+		if (!esp->auth.work_icv)
+			goto error;
+	}
+	esp->conf.key = x->ealg->alg_key;
+	esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
+	esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
+	if (esp->conf.tfm == NULL)
+		goto error;
+	esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
+	esp->conf.padlen = 0;
+	if (esp->conf.ivlen) {
+		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
+		get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
+	}
+	crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len);
+	x->props.header_len = 8 + esp->conf.ivlen;
+	if (x->props.mode)
+		x->props.header_len += 40;  /* XXX ext hdr */
+	x->data = esp;
+	return 0;
+
+error:
+	if (esp) {
+		if (esp->auth.tfm)
+			crypto_free_tfm(esp->auth.tfm);
+		if (esp->auth.work_icv)
+			kfree(esp->auth.work_icv);
+		if (esp->conf.tfm)
+			crypto_free_tfm(esp->conf.tfm);
+		kfree(esp);
+	}
+	return -EINVAL;
+}
+
+static struct xfrm_type esp6_type =
+{
+	.description	= "ESP6",
+	.proto	     	= IPPROTO_ESP,
+	.init_state	= esp6_init_state,
+	.destructor	= esp6_destroy,
+	.get_max_size	= esp6_get_max_size,
+	.input		= esp6_input,
+	.output		= esp6_output
+};
+
+static struct inet6_protocol esp6_protocol = {
+	.handler 	=	xfrm6_rcv,
+	.err_handler	=	esp6_err,
+};
+
+int __init esp6_init(void)
+{
+	SET_MODULE_OWNER(&esp6_type);
+	if (xfrm6_register_type(&esp6_type) < 0) {
+		printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n");
+		return -EAGAIN;
+	}
+	if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) {
+		printk(KERN_INFO "ipv6 esp init: can't add protocol\n");
+		xfrm6_unregister_type(&esp6_type);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static void __exit esp6_fini(void)
+{
+	if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0)
+		printk(KERN_INFO "ipv6 esp close: can't remove protocol\n");
+	if (xfrm6_unregister_type(&esp6_type) < 0)
+		printk(KERN_INFO "ipv6 esp close: can't remove xfrm type\n");
+}
+
+module_init(esp6_init);
+module_exit(esp6_fini);
+
+MODULE_LICENSE("GPL");
diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c	Mon Feb 24 03:18:25 2003
+++ b/net/ipv6/icmp.c	Thu Mar  6 16:30:30 2003
@@ -353,7 +353,7 @@
 	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
 		       MSG_DONTWAIT);
 	if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
-		ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-1]++;
+		ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-ICMPV6_DEST_UNREACH]++;
 	ICMP6_INC_STATS_BH(Icmp6OutMsgs);
 out:
 	icmpv6_xmit_unlock();
@@ -524,7 +524,7 @@
 		break;
 
 	case ICMPV6_ECHO_REPLY:
-		/* we coulnd't care less */
+		/* we couldn't care less */
 		break;
 
 	case ICMPV6_PKT_TOOBIG:
@@ -577,7 +577,7 @@
 
 	default:
 		if (net_ratelimit())
-			printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
+			printk(KERN_DEBUG "icmpv6: msg of unknown type\n");
 
 		/* informational */
 		if (type & ICMPV6_INFOMSG_MASK)
diff -Nru a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
--- a/net/ipv6/ip6_input.c	Wed Feb 19 13:55:33 2003
+++ b/net/ipv6/ip6_input.c	Wed Mar  5 15:45:36 2003
@@ -150,7 +150,8 @@
 	   It would be stupid to detect for optional headers,
 	   which are missing with probability of 200%
 	 */
-	if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP) {
+	if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP &&
+	    nexthdr != NEXTHDR_AUTH && nexthdr != NEXTHDR_ESP) {
 		nhoff = ipv6_parse_exthdrs(&skb, nhoff);
 		if (nhoff < 0)
 			return 0;
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	Sun Feb 23 22:41:51 2003
+++ b/net/ipv6/ip6_output.c	Wed Mar  5 15:45:36 2003
@@ -192,6 +192,11 @@
 	int seg_len = skb->len;
 	int hlimit;
 	u32 mtu;
+	int err = 0;
+
+	if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) {
+		return err;
+	}
 
 	if (opt) {
 		int head_room;
@@ -550,7 +555,7 @@
 		    || (fl->oif && fl->oif != dst->dev->ifindex)) {
 			dst = NULL;
 		} else
-			dst_clone(dst);
+			dst_hold(dst);
 	}
 
 	if (dst == NULL)
@@ -576,6 +581,13 @@
 	}
 	pktlength = length;
 
+        if (dst) {
+		if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+			dst_release(dst);	
+			return -ENETUNREACH;
+		}
+        }
+
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(fl->fl6_dst))
 			hlimit = np->mcast_hops;
@@ -630,10 +642,8 @@
 		err = 0;
 		if (flags&MSG_PROBE)
 			goto out;
-
-		skb = sock_alloc_send_skb(sk, pktlength + 15 +
-					  dev->hard_header_len,
-					  flags & MSG_DONTWAIT, &err);
+		/* alloc skb with mtu as we do in the IPv4 stack for IPsec */
+		skb = sock_alloc_send_skb(sk, mtu, flags & MSG_DONTWAIT, &err);
 
 		if (skb == NULL) {
 			IP6_INC_STATS(Ip6OutDiscards);
@@ -663,6 +673,8 @@
 		err = getfrag(data, &hdr->saddr,
 			      ((char *) hdr) + (pktlength - length),
 			      0, length);
+		if (!opt || !opt->dst1opt)
+			skb->h.raw = ((char *) hdr) + (pktlength - length);
 
 		if (!err) {
 			IP6_INC_STATS(Ip6OutRequests);
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	Tue Feb 25 09:45:41 2003
+++ b/net/ipv6/ndisc.c	Wed Mar  5 15:45:36 2003
@@ -71,6 +71,7 @@
 #include <net/addrconf.h>
 #include <net/icmp.h>
 
+#include <net/flow.h>
 #include <net/checksum.h>
 #include <linux/proc_fs.h>
 
@@ -335,8 +336,6 @@
 	unsigned char ha[MAX_ADDR_LEN];
 	unsigned char *h_dest = NULL;
 
-	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
-
 	if (dev->hard_header) {
 		if (ipv6_addr_type(daddr) & IPV6_ADDR_MULTICAST) {
 			ndisc_mc_map(daddr, ha, dev, 1);
@@ -373,10 +372,50 @@
  *	Send a Neighbour Advertisement
  */
 
+int ndisc_output(struct sk_buff *skb)
+{
+	if (skb) {
+		struct neighbour *neigh = (skb->dst ? skb->dst->neighbour : NULL);
+		if (ndisc_build_ll_hdr(skb, skb->dev, &skb->nh.ipv6h->daddr, neigh, skb->len) == 0) {
+			kfree_skb(skb);
+			return -EINVAL;
+		}
+		dev_queue_xmit(skb);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static inline void ndisc_rt_init(struct rt6_info *rt, struct net_device *dev,
+			    struct neighbour *neigh)
+{
+	rt->rt6i_dev	  = dev;
+	rt->rt6i_nexthop  = neigh;
+	rt->rt6i_expires  = 0;
+	rt->rt6i_flags    = RTF_LOCAL;
+	rt->rt6i_metric   = 0;
+	rt->rt6i_hoplimit = 255;
+	rt->u.dst.output  = ndisc_output;
+}
+
+static inline void ndisc_flow_init(struct flowi *fl, u8 type,
+			    struct in6_addr *saddr, struct in6_addr *daddr)
+{
+	memset(fl, 0, sizeof(*fl));
+	fl->fl6_src		= saddr;
+	fl->fl6_dst	 	= daddr;
+	fl->proto	 	= IPPROTO_ICMPV6;
+	fl->uli_u.icmpt.type	= type;
+	fl->uli_u.icmpt.code	= 0;
+}
+
 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 		   struct in6_addr *daddr, struct in6_addr *solicited_addr,
-		   int router, int solicited, int override, int inc_opt) 
+	 	   int router, int solicited, int override, int inc_opt) 
 {
+	struct flowi fl;
+	struct rt6_info *rt = NULL;
+	struct dst_entry* dst;
         struct sock *sk = ndisc_socket->sk;
         struct nd_msg *msg;
         int len;
@@ -385,6 +424,22 @@
 
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 
+	rt = ndisc_get_dummy_rt();
+	if (!rt) 
+		return;
+
+	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, solicited_addr, daddr);
+	ndisc_rt_init(rt, dev, neigh);	
+
+	dst = (struct dst_entry*)rt;
+	dst_clone(dst);
+
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err < 0) {
+		dst_release(dst);
+		return;
+	}
+
 	if (inc_opt) {
 		if (dev->addr_len)
 			len += NDISC_OPT_SPACE(dev->addr_len);
@@ -400,14 +455,10 @@
 		return;
 	}
 
-	if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
-		kfree_skb(skb);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, skb, dev, solicited_addr, daddr, IPPROTO_ICMPV6, len);
 
-	msg = (struct nd_msg *) skb_put(skb, len);
+	skb->h.raw = (unsigned char*) msg = (struct nd_msg *) skb_put(skb, len);
 
         msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
         msg->icmph.icmp6_code = 0;
@@ -430,7 +481,9 @@
 						 csum_partial((__u8 *) msg, 
 							      len, 0));
 
-	dev_queue_xmit(skb);
+	dst_clone(dst);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutNeighborAdvertisements);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
@@ -440,6 +493,9 @@
 		   struct in6_addr *solicit,
 		   struct in6_addr *daddr, struct in6_addr *saddr) 
 {
+	struct flowi fl;
+	struct rt6_info *rt = NULL;
+	struct dst_entry* dst;
         struct sock *sk = ndisc_socket->sk;
         struct sk_buff *skb;
         struct nd_msg *msg;
@@ -454,6 +510,22 @@
 		saddr = &addr_buf;
 	}
 
+	rt = ndisc_get_dummy_rt();
+	if (!rt) 
+		return;
+
+	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
+	ndisc_rt_init(rt, dev, neigh);	
+
+	dst = (struct dst_entry*)rt;
+	dst_clone(dst);
+
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err < 0) {
+		dst_release(dst);
+		return;
+	}
+
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 	send_llinfo = dev->addr_len && ipv6_addr_type(saddr) != IPV6_ADDR_ANY;
 	if (send_llinfo)
@@ -466,14 +538,10 @@
 		return;
 	}
 
-	if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
-		kfree_skb(skb);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
 
-	msg = (struct nd_msg *)skb_put(skb, len);
+	skb->h.raw = (unsigned char*) msg = (struct nd_msg *)skb_put(skb, len);
 	msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
 	msg->icmph.icmp6_code = 0;
 	msg->icmph.icmp6_cksum = 0;
@@ -492,7 +560,9 @@
 						 csum_partial((__u8 *) msg, 
 							      len, 0));
 	/* send it! */
-	dev_queue_xmit(skb);
+	dst_clone(dst);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutNeighborSolicits);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
@@ -501,6 +571,9 @@
 void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
 		   struct in6_addr *daddr)
 {
+	struct flowi fl;
+	struct rt6_info *rt = NULL;
+	struct dst_entry* dst;
 	struct sock *sk = ndisc_socket->sk;
         struct sk_buff *skb;
         struct icmp6hdr *hdr;
@@ -508,6 +581,22 @@
         int len;
 	int err;
 
+	rt = ndisc_get_dummy_rt();
+	if (!rt) 
+		return;
+
+	ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
+	ndisc_rt_init(rt, dev, NULL);
+
+	dst = (struct dst_entry*)rt;
+	dst_clone(dst);
+
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err < 0) {
+		dst_release(dst);
+		return;
+	}
+
 	len = sizeof(struct icmp6hdr);
 	if (dev->addr_len)
 		len += NDISC_OPT_SPACE(dev->addr_len);
@@ -519,14 +608,10 @@
 		return;
 	}
 
-	if (ndisc_build_ll_hdr(skb, dev, daddr, NULL, len) == 0) {
-		kfree_skb(skb);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
 
-        hdr = (struct icmp6hdr *) skb_put(skb, len);
+        skb->h.raw = (unsigned char*) hdr = (struct icmp6hdr *) skb_put(skb, len);
         hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
         hdr->icmp6_code = 0;
         hdr->icmp6_cksum = 0;
@@ -543,7 +628,9 @@
 					   csum_partial((__u8 *) hdr, len, 0));
 
 	/* send it! */
-	dev_queue_xmit(skb);
+	dst_clone(dst);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutRouterSolicits);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
@@ -1125,6 +1212,8 @@
 	struct in6_addr *addrp;
 	struct net_device *dev;
 	struct rt6_info *rt;
+	struct dst_entry *dst;
+	struct flowi fl;
 	u8 *opt;
 	int rd_len;
 	int err;
@@ -1136,6 +1225,22 @@
 	if (rt == NULL)
 		return;
 
+	dst = (struct dst_entry*)rt;
+
+	if (ipv6_get_lladdr(dev, &saddr_buf)) {
+ 		ND_PRINTK1("redirect: no link_local addr for dev\n");
+ 		return;
+ 	}
+
+	ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
+
+	dst_clone(dst);
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err) {
+		dst_release(dst);
+		return;
+	}
+
 	if (rt->rt6i_flags & RTF_GATEWAY) {
 		ND_PRINTK1("ndisc_send_redirect: not a neighbour\n");
 		dst_release(&rt->u.dst);
@@ -1164,11 +1269,6 @@
 	rd_len &= ~0x7;
 	len += rd_len;
 
-	if (ipv6_get_lladdr(dev, &saddr_buf)) {
- 		ND_PRINTK1("redirect: no link_local addr for dev\n");
- 		return;
- 	}
-
 	buff = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15,
 				   0, &err);
 	if (buff == NULL) {
@@ -1178,15 +1278,11 @@
 
 	hlen = 0;
 
-	if (ndisc_build_ll_hdr(buff, dev, &skb->nh.ipv6h->saddr, NULL, len) == 0) {
-		kfree_skb(buff);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
 		   IPPROTO_ICMPV6, len);
 
-	icmph = (struct icmp6hdr *) skb_put(buff, len);
+	skb->h.raw = (unsigned char*) icmph = (struct icmp6hdr *) skb_put(buff, len);
 
 	memset(icmph, 0, sizeof(struct icmp6hdr));
 	icmph->icmp6_type = NDISC_REDIRECT;
@@ -1224,7 +1320,8 @@
 					     len, IPPROTO_ICMPV6,
 					     csum_partial((u8 *) icmph, len, 0));
 
-	dev_queue_xmit(buff);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutRedirects);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
diff -Nru a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
--- a/net/ipv6/netfilter/ip6t_ah.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_ah.c	Thu Mar  6 09:11:12 2003
@@ -9,7 +9,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_ah.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 AH match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
--- a/net/ipv6/netfilter/ip6t_dst.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_dst.c	Thu Mar  6 09:11:12 2003
@@ -15,7 +15,6 @@
 
 #define HOPBYHOP	0
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 #if HOPBYHOP
 MODULE_DESCRIPTION("IPv6 HbH match");
diff -Nru a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
--- a/net/ipv6/netfilter/ip6t_esp.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_esp.c	Thu Mar  6 09:11:12 2003
@@ -9,7 +9,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_esp.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 ESP match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
--- a/net/ipv6/netfilter/ip6t_frag.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_frag.c	Thu Mar  6 09:11:12 2003
@@ -11,7 +11,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_frag.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 FRAG match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
--- a/net/ipv6/netfilter/ip6t_hbh.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_hbh.c	Thu Mar  6 09:11:12 2003
@@ -15,7 +15,6 @@
 
 #define HOPBYHOP	1
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 #if HOPBYHOP
 MODULE_DESCRIPTION("IPv6 HbH match");
diff -Nru a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
--- a/net/ipv6/netfilter/ip6t_ipv6header.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c	Thu Mar  6 09:11:12 2003
@@ -14,7 +14,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_ipv6header.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 headers match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
--- a/net/ipv6/netfilter/ip6t_rt.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_rt.c	Thu Mar  6 09:11:12 2003
@@ -11,7 +11,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_rt.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 RT match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
--- a/net/ipv6/netfilter/ip6table_filter.c	Mon Feb 10 04:36:12 2003
+++ b/net/ipv6/netfilter/ip6table_filter.c	Sat Mar  8 11:40:17 2003
@@ -81,9 +81,13 @@
     }
 };
 
-static struct ip6t_table packet_filter
-= { { NULL, NULL }, "filter", &initial_table.repl,
-    FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct ip6t_table packet_filter = {
+	.name		= "filter",
+	.table		= &initial_table.repl,
+	.valid_hooks	= FILTER_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.me		= THIS_MODULE,
+};
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
@@ -116,11 +120,25 @@
 	return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL);
 }
 
-static struct nf_hook_ops ip6t_ops[]
-= { { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_LOCAL_IN, NF_IP6_PRI_FILTER },
-    { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_FORWARD, NF_IP6_PRI_FILTER },
-    { { NULL, NULL }, ip6t_local_out_hook, PF_INET6, NF_IP6_LOCAL_OUT,
-		NF_IP6_PRI_FILTER }
+static struct nf_hook_ops ip6t_ops[] = {
+	{
+		.hook		= ip6t_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_IN,
+		.priority	= NF_IP6_PRI_FILTER,
+	},
+	{
+		.hook		= ip6t_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_FORWARD,
+		.priority	= NF_IP6_PRI_FILTER,
+	},
+	{
+		.hook		= ip6t_local_out_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_FILTER,
+	},
 };
 
 /* Default to forward because I got too much mail already. */
diff -Nru a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
--- a/net/ipv6/netfilter/ip6table_mangle.c	Mon Feb 10 04:36:12 2003
+++ b/net/ipv6/netfilter/ip6table_mangle.c	Sat Mar  8 11:40:17 2003
@@ -111,9 +111,13 @@
     }
 };
 
-static struct ip6t_table packet_mangler
-= { { NULL, NULL }, "mangle", &initial_table.repl,
-    MANGLE_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct ip6t_table packet_mangler = {
+	.name		= "mangle",
+	.table		= &initial_table.repl,
+	.valid_hooks	= MANGLE_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.me		= THIS_MODULE,
+};
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
@@ -175,12 +179,37 @@
 	return ret;
 }
 
-static struct nf_hook_ops ip6t_ops[]
-= { { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_PRE_ROUTING,  NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_IN,     NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_FORWARD,      NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_OUT,    NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_POST_ROUTING, NF_IP6_PRI_MANGLE }
+static struct nf_hook_ops ip6t_ops[] = {
+	{
+		.hook		= ip6t_route_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_PRE_ROUTING,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_local_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_IN,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_route_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_FORWARD,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_local_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_route_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_POST_ROUTING,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
 };
 
 static int __init init(void)
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	Mon Oct 28 04:53:45 2002
+++ b/net/ipv6/raw.c	Wed Mar  5 15:45:36 2003
@@ -45,6 +45,7 @@
 #include <net/inet_common.h>
 
 #include <net/rawv6.h>
+#include <net/xfrm.h>
 
 struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE];
 rwlock_t raw_v6_lock = RW_LOCK_UNLOCKED;
@@ -303,6 +304,11 @@
 {
 	struct inet_opt *inet = inet_sk(sk);
 	struct raw6_opt *raw_opt = raw6_sk(sk);
+
+        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
+                kfree_skb(skb);
+                return NET_RX_DROP;
+        }
 
 	if (!raw_opt->checksum)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c
--- a/net/ipv6/route.c	Mon Mar  3 01:47:43 2003
+++ b/net/ipv6/route.c	Wed Mar  5 15:45:36 2003
@@ -49,6 +49,8 @@
 #include <net/addrconf.h>
 #include <net/tcp.h>
 #include <linux/rtnetlink.h>
+#include <net/dst.h>
+#include <net/xfrm.h>
 
 #include <asm/uaccess.h>
 
@@ -128,6 +130,12 @@
 rwlock_t rt6_lock = RW_LOCK_UNLOCKED;
 
 
+/*	Dummy rt for ndisc */
+struct rt6_info *ndisc_get_dummy_rt()
+{
+	return dst_alloc(&ip6_dst_ops);
+}
+
 /*
  *	Route lookup. Any rt6_lock is implied.
  */
@@ -356,7 +364,7 @@
 
 		rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
 
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 
 		err = rt6_ins(rt);
 		if (err == 0)
@@ -366,7 +374,7 @@
 
 		return rt;
 	}
-	dst_clone(&ip6_null_entry.u.dst);
+	dst_hold(&ip6_null_entry.u.dst);
 	return &ip6_null_entry;
 }
 
@@ -374,7 +382,7 @@
 if (rt == &ip6_null_entry && strict) { \
        while ((fn = fn->parent) != NULL) { \
 		if (fn->fn_flags & RTN_ROOT) { \
-			dst_clone(&rt->u.dst); \
+			dst_hold(&rt->u.dst); \
 			goto out; \
 		} \
 		if (fn->fn_flags & RTN_RTINFO) \
@@ -404,7 +412,7 @@
 	if ((rt->rt6i_flags & RTF_CACHE)) {
 		rt = rt6_device_match(rt, skb->dev->ifindex, strict);
 		BACKTRACK();
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 		goto out;
 	}
 
@@ -424,7 +432,7 @@
 		*/
 		goto relookup;
 	}
-	dst_clone(&rt->u.dst);
+	dst_hold(&rt->u.dst);
 
 out:
 	read_unlock_bh(&rt6_lock);
@@ -455,7 +463,7 @@
 	if ((rt->rt6i_flags & RTF_CACHE)) {
 		rt = rt6_device_match(rt, fl->oif, strict);
 		BACKTRACK();
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 		goto out;
 	}
 	if (rt->rt6i_flags & RTF_DEFAULT) {
@@ -480,7 +488,7 @@
 		*/
 		goto relookup;
 	}
-	dst_clone(&rt->u.dst);
+	dst_hold(&rt->u.dst);
 
 out:
 	read_unlock_bh(&rt6_lock);
@@ -815,7 +823,7 @@
 			if (rtmsg->rtmsg_metric &&
 			    rtmsg->rtmsg_metric != rt->rt6i_metric)
 				continue;
-			dst_clone(&rt->u.dst);
+			dst_hold(&rt->u.dst);
 			read_unlock_bh(&rt6_lock);
 
 			return ip6_del_rt(rt);
@@ -878,7 +886,7 @@
 			read_lock(&rt6_lock);
 			for (rt1 = ip6_routing_table.leaf; rt1; rt1 = rt1->u.next) {
 				if (!ipv6_addr_cmp(saddr, &rt1->rt6i_gateway)) {
-					dst_clone(&rt1->u.dst);
+					dst_hold(&rt1->u.dst);
 					dst_release(&rt->u.dst);
 					read_unlock(&rt6_lock);
 					rt = rt1;
@@ -1065,7 +1073,7 @@
 			break;
 	}
 	if (rt)
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 	write_unlock_bh(&rt6_lock);
 	return rt;
 }
@@ -1859,6 +1867,14 @@
 
 #endif
 
+int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+{
+	int err = 0;
+	*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
+	if (!*dst)
+		err = -ENETUNREACH;
+	return err;
+}
 
 void __init ip6_route_init(void)
 {
@@ -1867,6 +1883,7 @@
 						     0, SLAB_HWCACHE_ALIGN,
 						     NULL, NULL);
 	fib6_init();
+	xfrm_dst_lookup_register(xfrm6_dst_lookup, AF_INET6);
 #ifdef 	CONFIG_PROC_FS
 	proc_net_create("ipv6_route", 0, rt6_proc_info);
 	proc_net_create("rt6_stats", 0, rt6_proc_stats);
@@ -1880,7 +1897,7 @@
 	proc_net_remove("ipv6_route");
 	proc_net_remove("rt6_stats");
 #endif
-
+	xfrm_dst_lookup_unregister(AF_INET6);
 	rt6_ifdown(NULL);
 	fib6_gc_cleanup();
 }
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	Sat Feb 22 16:15:34 2003
+++ b/net/ipv6/tcp_ipv6.c	Wed Mar  5 15:45:36 2003
@@ -50,6 +50,7 @@
 #include <net/ip6_route.h>
 #include <net/inet_ecn.h>
 #include <net/protocol.h>
+#include <net/xfrm.h>
 
 #include <asm/uaccess.h>
 
@@ -677,6 +678,9 @@
 		fl.nl_u.ip6_u.daddr = rt0->addr;
 	}
 
+	if (!fl.fl6_src)
+		fl.fl6_src = &np->saddr;
+
 	dst = ip6_route_output(sk, &fl);
 
 	if ((err = dst->error) != 0) {
@@ -800,7 +804,7 @@
 
 			dst = ip6_route_output(sk, &fl);
 		} else
-			dst_clone(dst);
+			dst_hold(dst);
 
 		if (dst->error) {
 			sk->err_soft = -dst->error;
@@ -1637,6 +1641,9 @@
 	if (sk_filter(sk, skb, 0))
 		goto discard_and_relse;
 
+	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
+		goto discard_it;
+
 	skb->dev = NULL;
 
 	bh_lock_sock(sk);
@@ -1652,6 +1659,9 @@
 	return ret;
 
 no_tcp_socket:
+	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
+		goto discard_and_relse;
+
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 bad_packet:
 		TCP_INC_STATS_BH(TcpInErrs);
@@ -1671,8 +1681,11 @@
 discard_and_relse:
 	sock_put(sk);
 	goto discard_it;
-                
+
 do_time_wait:
+	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
+		goto discard_and_relse;
+
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TcpInErrs);
 		sock_put(sk);
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	Tue Jan  7 02:19:42 2003
+++ b/net/ipv6/udp.c	Wed Mar  5 15:45:36 2003
@@ -50,6 +50,7 @@
 #include <net/inet_common.h>
 
 #include <net/checksum.h>
+#include <net/xfrm.h>
 
 DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
 
@@ -541,6 +542,11 @@
 
 static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 {
+	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
+		kfree_skb(skb);
+		return -1;
+	}
+
 #if defined(CONFIG_FILTER)
 	if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
 		if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
@@ -645,6 +651,9 @@
 
 	if (!pskb_may_pull(skb, sizeof(struct udphdr)))
 		goto short_packet;
+
+	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
+                goto discard;
 
 	saddr = &skb->nh.ipv6h->saddr;
 	daddr = &skb->nh.ipv6h->daddr;
diff -Nru a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
--- a/net/ipx/af_ipx.c	Tue Feb 25 11:05:23 2003
+++ b/net/ipx/af_ipx.c	Thu Mar  6 11:06:44 2003
@@ -1719,10 +1719,10 @@
 	if (!sk)
 		goto out;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock->sk = NULL;
 	ipx_destroy_socket(sk);
 
@@ -2010,7 +2010,7 @@
 }
 
 static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int len, struct scm_cookie *scm)
+	struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct ipx_opt *ipxs = ipx_sk(sk);
@@ -2070,7 +2070,7 @@
 
 
 static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
-		struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
+		struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct ipx_opt *ipxs = ipx_sk(sk);
diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c
--- a/net/irda/af_irda.c	Thu Nov 14 09:20:05 2002
+++ b/net/irda/af_irda.c	Thu Mar  6 11:06:45 2003
@@ -133,13 +133,13 @@
 	}
 
 	/* Prevent race conditions with irda_release() and irda_shutdown() */
-	if ((!sk->dead) && (sk->state != TCP_CLOSE)) {
+	if ((!test_bit(SOCK_DEAD, &sk->flags)) && (sk->state != TCP_CLOSE)) {
 		sk->state     = TCP_CLOSE;
 		sk->err       = ECONNRESET;
 		sk->shutdown |= SEND_SHUTDOWN;
 
 		sk->state_change(sk);
-                sk->dead = 1;	/* Uh-oh... Should use sock_orphan ? */
+                __set_bit(SOCK_DEAD, &sk->flags);	/* Uh-oh... Should use sock_orphan ? */
 
 		/* Close our TSAP.
 		 * If we leave it open, IrLMP put it back into the list of
@@ -163,7 +163,7 @@
 	/* Note : once we are there, there is not much you want to do
 	 * with the socket anymore, apart from closing it.
 	 * For example, bind() and connect() won't reset sk->err,
-	 * sk->shutdown and sk->dead to valid values...
+	 * sk->shutdown and sk->flags to valid values...
 	 * Jean II
 	 */
 }
@@ -1253,14 +1253,14 @@
 }
 
 /*
- * Function irda_sendmsg (iocb, sock, msg, len, scm)
+ * Function irda_sendmsg (iocb, sock, msg, len)
  *
  *    Send message down to TinyTP. This function is used for both STREAM and
  *    SEQPACK services. This is possible since it forces the client to
  *    fragment the message if necessary
  */
 static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int len, struct scm_cookie *scm)
+			struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self;
@@ -1326,14 +1326,13 @@
 }
 
 /*
- * Function irda_recvmsg_dgram (iocb, sock, msg, size, flags, scm)
+ * Function irda_recvmsg_dgram (iocb, sock, msg, size, flags)
  *
  *    Try to receive message and copy it to user. The frame is discarded
  *    after being read, regardless of how much the user actually read
  */
 static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int size, int flags,
-			      struct scm_cookie *scm)
+			      struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self = irda_sk(sk);
@@ -1380,11 +1379,10 @@
 }
 
 /*
- * Function irda_recvmsg_stream (iocb, sock, msg, size, flags, scm)
+ * Function irda_recvmsg_stream (iocb, sock, msg, size, flags)
  */
 static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int size, int flags,
-			       struct scm_cookie *scm)
+			       struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self = irda_sk(sk);
@@ -1504,14 +1502,14 @@
 }
 
 /*
- * Function irda_sendmsg_dgram (iocb, sock, msg, len, scm)
+ * Function irda_sendmsg_dgram (iocb, sock, msg, len)
  *
  *    Send message down to TinyTP for the unreliable sequenced
  *    packet service...
  *
  */
 static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int len, struct scm_cookie *scm)
+			      struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self;
@@ -1570,14 +1568,14 @@
 }
 
 /*
- * Function irda_sendmsg_ultra (iocb, sock, msg, len, scm)
+ * Function irda_sendmsg_ultra (iocb, sock, msg, len)
  *
  *    Send message down to IrLMP for the unreliable Ultra
  *    packet service...
  */
 #ifdef CONFIG_IRDA_ULTRA
 static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int len, struct scm_cookie *scm)
+			      struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self;
diff -Nru a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
--- a/net/irda/ircomm/ircomm_core.c	Mon Sep 23 16:34:19 2002
+++ b/net/irda/ircomm/ircomm_core.c	Mon Mar 10 22:34:30 2003
@@ -119,8 +119,10 @@
 	} else
 		ret = ircomm_open_tsap(self);
 
-	if (ret < 0)
+	if (ret < 0) {
+		kfree(self);
 		return NULL;
+	}
 
 	self->service_type = service_type;
 	self->line = line;
diff -Nru a/net/key/af_key.c b/net/key/af_key.c
--- a/net/key/af_key.c	Wed Feb 19 13:45:59 2003
+++ b/net/key/af_key.c	Thu Mar  6 11:06:45 2003
@@ -51,7 +51,7 @@
 {
 	skb_queue_purge(&sk->receive_queue);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive pfkey socket: %p\n", sk);
 		return;
 	}
@@ -550,8 +550,8 @@
 
 	switch (((struct sockaddr *)(addr + 1))->sa_family) {
 	case AF_INET:
-		x = xfrm_state_lookup(((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr,
-				      sa->sadb_sa_spi, proto);
+		x = xfrm4_state_lookup(((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr,
+				       sa->sadb_sa_spi, proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -1097,18 +1097,7 @@
 			min_spi = htonl(0x100);
 			max_spi = htonl(0x0fffffff);
 		}
-		switch (x->props.family) {
-		case AF_INET:
-			xfrm_alloc_spi(x, min_spi, max_spi);
-			break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			xfrm6_alloc_spi(x, min_spi, max_spi);
-			break;
-#endif
-		default:
-			break;
-		}
+		xfrm_alloc_spi(x, min_spi, max_spi);
 		if (x->id.spi)
 			resp_skb = pfkey_xfrm_state2msg(x, 0, 3);
 	}
@@ -2420,7 +2409,8 @@
 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
 }
 
-static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int *dir)
+static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
+                                                u8 *data, int len, int *dir)
 {
 	struct xfrm_policy *xp;
 	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
@@ -2451,6 +2441,7 @@
 	xp->lft.hard_byte_limit = XFRM_INF;
 	xp->lft.soft_packet_limit = XFRM_INF;
 	xp->lft.hard_packet_limit = XFRM_INF;
+	xp->family = family;
 
 	xp->xfrm_nr = 0;
 	if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
@@ -2466,8 +2457,7 @@
 }
 
 static int pfkey_sendmsg(struct kiocb *kiocb,
-			 struct socket *sock, struct msghdr *msg, int len,
-			 struct scm_cookie *scm)
+			 struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb = NULL;
@@ -2510,7 +2500,7 @@
 
 static int pfkey_recvmsg(struct kiocb *kiocb,
 			 struct socket *sock, struct msghdr *msg, int len,
-			 int flags, struct scm_cookie *scm)
+			 int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
diff -Nru a/net/llc/af_llc.c b/net/llc/af_llc.c
--- a/net/llc/af_llc.c	Tue Feb 25 10:47:07 2003
+++ b/net/llc/af_llc.c	Thu Mar  6 11:06:45 2003
@@ -672,14 +672,12 @@
  *	@msg: Various user space related information.
  *	@size: Size of user buffer.
  *	@flags: User specified flags.
- *	@scm: Unknown.
  *
  *	Copy received data to the socket user.
  *	Returns non-negative upon success, negative otherwise.
  */
 static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int size, int flags,
-			  struct scm_cookie *scm)
+			  struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
@@ -727,13 +725,12 @@
  *	@sock: Socket to transmit data from.
  *	@msg: Various user related information.
  *	@len: Length of data to transmit.
- *	@scm: Unknown.
  *
  *	Transmit data provided by the socket user.
  *	Returns non-negative upon success, negative otherwise.
  */
 static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, struct scm_cookie *scm)
+			  struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct llc_opt *llc = llc_sk(sk);
diff -Nru a/net/llc/llc_conn.c b/net/llc/llc_conn.c
--- a/net/llc/llc_conn.c	Mon Sep 30 12:17:03 2002
+++ b/net/llc/llc_conn.c	Mon Mar  3 04:56:53 2003
@@ -119,9 +119,9 @@
 			sk->shutdown       = SHUTDOWN_MASK;
 			sk->socket->state  = SS_UNCONNECTED;
 			sk->state          = TCP_CLOSE;
-			if (!sk->dead) {
+			if (!test_bit(SOCK_DEAD, &sk->flags)) {
 				sk->state_change(sk);
-				sk->dead = 1;
+				__set_bit(SOCK_DEAD, &sk->flags);
 			}
 		}
 		kfree_skb(skb);
diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c	Sun Feb 23 22:14:05 2003
+++ b/net/netlink/af_netlink.c	Thu Mar  6 11:06:45 2003
@@ -90,7 +90,7 @@
 {
 	skb_queue_purge(&sk->receive_queue);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Freeing alive netlink socket %p\n", sk);
 		return;
 	}
@@ -457,7 +457,7 @@
 
 		if ((atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
 		    test_bit(0, &nlk->state)) &&
-		    !sk->dead)
+		    !test_bit(SOCK_DEAD, &sk->flags))
 			timeo = schedule_timeout(timeo);
 
 		__set_current_state(TASK_RUNNING);
@@ -595,10 +595,10 @@
 		wake_up_interruptible(&nlk->wait);
 }
 
-static int netlink_sendmsg(struct kiocb *iocb, struct socket *sock,
-			   struct msghdr *msg, int len,
-			   struct scm_cookie *scm)
+static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
+			   struct msghdr *msg, int len)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	struct netlink_opt *nlk = nlk_sk(sk);
 	struct sockaddr_nl *addr=msg->msg_name;
@@ -606,10 +606,17 @@
 	u32 dst_groups;
 	struct sk_buff *skb;
 	int err;
+	struct scm_cookie scm;
 
 	if (msg->msg_flags&MSG_OOB)
 		return -EOPNOTSUPP;
 
+	if (NULL == siocb->scm)
+		siocb->scm = &scm;
+	err = scm_send(sock, msg, siocb->scm);
+	if (err < 0)
+		return err;
+
 	if (msg->msg_namelen) {
 		if (addr->nl_family != AF_NETLINK)
 			return -EINVAL;
@@ -640,7 +647,7 @@
 	NETLINK_CB(skb).groups	= nlk->groups;
 	NETLINK_CB(skb).dst_pid = dst_pid;
 	NETLINK_CB(skb).dst_groups = dst_groups;
-	memcpy(NETLINK_CREDS(skb), &scm->creds, sizeof(struct ucred));
+	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
 	/* What can I do? Netlink is asynchronous, so that
 	   we will have to save current capabilities to
@@ -670,10 +677,12 @@
 	return err;
 }
 
-static int netlink_recvmsg(struct kiocb *iocb, struct socket *sock,
+static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
 			   struct msghdr *msg, int len,
-			   int flags, struct scm_cookie *scm)
+			   int flags)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
+	struct scm_cookie scm;
 	struct sock *sk = sock->sk;
 	struct netlink_opt *nlk = nlk_sk(sk);
 	int noblock = flags&MSG_DONTWAIT;
@@ -709,11 +718,17 @@
 		msg->msg_namelen = sizeof(*addr);
 	}
 
-	scm->creds = *NETLINK_CREDS(skb);
+	if (NULL == siocb->scm) {
+		memset(&scm, 0, sizeof(scm));
+		siocb->scm = &scm;
+	}
+	siocb->scm->creds = *NETLINK_CREDS(skb);
 	skb_free_datagram(sk, skb);
 
 	if (nlk->cb && atomic_read(&sk->rmem_alloc) <= sk->rcvbuf / 2)
 		netlink_dump(sk);
+
+	scm_recv(sock, msg, siocb->scm, flags);
 
 out:
 	netlink_rcv_wake(sk);
diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
--- a/net/netrom/af_netrom.c	Tue Oct  8 07:02:41 2002
+++ b/net/netrom/af_netrom.c	Thu Mar  6 11:06:45 2003
@@ -285,7 +285,7 @@
 
 	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
 		if (skb->sk != sk) {			/* A pending connection */
-			skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
+			__set_bit(SOCK_DEAD, &skb->sk->flags);	/* Queue the unaccepted socket for death */
 			nr_start_heartbeat(skb->sk);
 			nr_sk(skb->sk)->state = NR_STATE_0;
 		}
@@ -545,8 +545,8 @@
 		sk->state    = TCP_CLOSE;
 		sk->shutdown |= SEND_SHUTDOWN;
 		sk->state_change(sk);
-		sk->dead     = 1;
-		sk->destroy  = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
+		__set_bit(SOCK_DESTROY, &sk->flags);
 		sk->socket   = NULL;
 		break;
 
@@ -960,14 +960,14 @@
 	nr_start_heartbeat(make);
 	nr_start_idletimer(make);
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skb->len);
 
 	return 1;
 }
 
 static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,
-		      struct msghdr *msg, int len, struct scm_cookie *scm)
+		      struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	nr_cb *nr = nr_sk(sk);
@@ -1058,8 +1058,7 @@
 }
 
 static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
-		      struct msghdr *msg, int size, int flags,
-		      struct scm_cookie *scm)
+		      struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
diff -Nru a/net/netrom/nr_in.c b/net/netrom/nr_in.c
--- a/net/netrom/nr_in.c	Mon Aug  5 08:44:44 2002
+++ b/net/netrom/nr_in.c	Mon Mar  3 04:56:53 2003
@@ -90,7 +90,7 @@
 		nr->n2count    = 0;
 		nr->window     = skb->data[20];
 		sk->state      = TCP_ESTABLISHED;
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
 		break;
 	}
diff -Nru a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
--- a/net/netrom/nr_subr.c	Mon Aug  5 08:44:44 2002
+++ b/net/netrom/nr_subr.c	Mon Mar  3 04:56:53 2003
@@ -276,8 +276,8 @@
 	sk->err       = reason;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 }
diff -Nru a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
--- a/net/netrom/nr_timer.c	Mon Aug  5 09:14:03 2002
+++ b/net/netrom/nr_timer.c	Mon Mar  3 04:56:53 2003
@@ -141,7 +141,9 @@
 	case NR_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
+		if (test_bit(SOCK_DESTROY, &sk->flags) ||
+				(sk->state == TCP_LISTEN &&
+					test_bit(SOCK_DEAD, &sk->flags))) {
 			nr_destroy_socket(sk);
 			return;
 		}
@@ -209,10 +211,10 @@
 	sk->err       = 0;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	bh_unlock_sock(sk);
 }
 
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Tue Feb 25 18:56:15 2003
+++ b/net/netsyms.c	Thu Mar  6 16:16:15 2003
@@ -54,6 +54,12 @@
 #include <linux/mroute.h>
 #include <linux/igmp.h>
 #include <net/xfrm.h>
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+#include <net/ah.h>
+#endif
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+#include <net/esp.h>
+#endif
 
 extern struct net_proto_family inet_family_ops;
 
@@ -296,11 +302,11 @@
 EXPORT_SYMBOL(__xfrm_route_forward);
 EXPORT_SYMBOL(xfrm_state_alloc);
 EXPORT_SYMBOL(__xfrm_state_destroy);
-EXPORT_SYMBOL(xfrm_state_find);
+EXPORT_SYMBOL(xfrm4_state_find);
 EXPORT_SYMBOL(xfrm_state_insert);
 EXPORT_SYMBOL(xfrm_state_check_expire);
 EXPORT_SYMBOL(xfrm_state_check_space);
-EXPORT_SYMBOL(xfrm_state_lookup);
+EXPORT_SYMBOL(xfrm4_state_lookup);
 EXPORT_SYMBOL(xfrm_replay_check);
 EXPORT_SYMBOL(xfrm_replay_advance);
 EXPORT_SYMBOL(xfrm_check_selectors);
@@ -324,13 +330,17 @@
 EXPORT_SYMBOL(xfrm_policy_flush);
 EXPORT_SYMBOL(xfrm_policy_byid);
 EXPORT_SYMBOL(xfrm_policy_list);
+EXPORT_SYMBOL(xfrm_dst_lookup_register);
+EXPORT_SYMBOL(xfrm_dst_lookup_unregister);
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+EXPORT_SYMBOL(xfrm6_state_find);
+EXPORT_SYMBOL(xfrm6_rcv);
 EXPORT_SYMBOL(xfrm6_state_lookup);
 EXPORT_SYMBOL(xfrm6_find_acq);
-EXPORT_SYMBOL(xfrm6_alloc_spi);
 EXPORT_SYMBOL(xfrm6_register_type);
 EXPORT_SYMBOL(xfrm6_unregister_type);
 EXPORT_SYMBOL(xfrm6_get_type);
+EXPORT_SYMBOL(xfrm6_clear_mutable_options);
 #endif
 
 EXPORT_SYMBOL_GPL(xfrm_probe_algs);
@@ -342,6 +352,15 @@
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+EXPORT_SYMBOL_GPL(skb_ah_walk);
+#endif
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+EXPORT_SYMBOL_GPL(skb_cow_data);
+EXPORT_SYMBOL_GPL(pskb_put);
+EXPORT_SYMBOL_GPL(skb_icv_walk);
+EXPORT_SYMBOL_GPL(skb_to_sgvec);
+#endif
 
 #if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE)
 /* inet functions common to v4 and v6 */
diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c
--- a/net/packet/af_packet.c	Sat Nov  2 02:29:53 2002
+++ b/net/packet/af_packet.c	Thu Mar  6 11:06:45 2003
@@ -198,7 +198,7 @@
 	BUG_TRAP(atomic_read(&sk->rmem_alloc)==0);
 	BUG_TRAP(atomic_read(&sk->wmem_alloc)==0);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive packet socket: %p\n", sk);
 		return;
 	}
@@ -280,8 +280,7 @@
  */
  
 static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int len,
-			       struct scm_cookie *scm)
+			       struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
@@ -658,7 +657,7 @@
 
 
 static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, struct scm_cookie *scm)
+			  struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
@@ -852,7 +851,7 @@
 			po->running = 1;
 		} else {
 			sk->err = ENETDOWN;
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->error_report(sk);
 		}
 	} else {
@@ -1013,8 +1012,7 @@
  */
 
 static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len,
-			  int flags, struct scm_cookie *scm)
+			  struct msghdr *msg, int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
@@ -1392,7 +1390,7 @@
 					__sock_put(sk);
 					po->running = 0;
 					sk->err = ENETDOWN;
-					if (!sk->dead)
+					if (!test_bit(SOCK_DEAD, &sk->flags))
 						sk->error_report(sk);
 				}
 				if (msg == NETDEV_UNREGISTER) {
diff -Nru a/net/rose/af_rose.c b/net/rose/af_rose.c
--- a/net/rose/af_rose.c	Tue Oct  8 07:02:41 2002
+++ b/net/rose/af_rose.c	Thu Mar  6 11:06:45 2003
@@ -365,7 +365,7 @@
 
 	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
 		if (skb->sk != sk) {			/* A pending connection */
-			skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
+			__set_bit(SOCK_DEAD, &skb->sk->flags);	/* Queue the unaccepted socket for death */
 			rose_start_heartbeat(skb->sk);
 			rose_sk(skb->sk)->state = ROSE_STATE_0;
 		}
@@ -646,8 +646,8 @@
 		sk->state    = TCP_CLOSE;
 		sk->shutdown |= SEND_SHUTDOWN;
 		sk->state_change(sk);
-		sk->dead     = 1;
-		sk->destroy  = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
+		__set_bit(SOCK_DESTROY, &sk->flags);
 		break;
 
 	default:
@@ -1019,14 +1019,14 @@
 
 	rose_start_heartbeat(make);
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skb->len);
 
 	return 1;
 }
 
 static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int len, struct scm_cookie *scm)
+			struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	rose_cb *rose = rose_sk(sk);
@@ -1190,8 +1190,7 @@
 
 
 static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int size, int flags,
-			struct scm_cookie *scm)
+			struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	rose_cb *rose = rose_sk(sk);
diff -Nru a/net/rose/rose_in.c b/net/rose/rose_in.c
--- a/net/rose/rose_in.c	Mon Aug  5 08:44:44 2002
+++ b/net/rose/rose_in.c	Mon Mar  3 04:56:53 2003
@@ -54,7 +54,7 @@
 		rose->vl        = 0;
 		rose->state     = ROSE_STATE_3;
 		sk->state                    = TCP_ESTABLISHED;
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
 		break;
 
diff -Nru a/net/rose/rose_route.c b/net/rose/rose_route.c
--- a/net/rose/rose_route.c	Mon Aug  5 09:23:19 2002
+++ b/net/rose/rose_route.c	Mon Mar  3 04:56:53 2003
@@ -910,9 +910,9 @@
 			sk->state	 = TCP_CLOSE;
 			sk->err		 = 0;
 			sk->shutdown	 |= SEND_SHUTDOWN;
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->state_change(sk);
-			sk->dead         = 1;
+			__set_bit(SOCK_DEAD, &sk->flags);
 		}
 		else {
 			skb->h.raw = skb->data;
diff -Nru a/net/rose/rose_subr.c b/net/rose/rose_subr.c
--- a/net/rose/rose_subr.c	Mon Aug  5 08:44:45 2002
+++ b/net/rose/rose_subr.c	Mon Mar  3 04:56:53 2003
@@ -510,8 +510,8 @@
 	sk->err       = reason;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead  = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 }
diff -Nru a/net/rose/rose_timer.c b/net/rose/rose_timer.c
--- a/net/rose/rose_timer.c	Mon Aug  5 09:14:03 2002
+++ b/net/rose/rose_timer.c	Mon Mar  3 04:56:53 2003
@@ -136,7 +136,9 @@
 	case ROSE_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
+		if (test_bit(SOCK_DESTROY, &sk->flags) ||
+				(sk->state == TCP_LISTEN &&
+					test_bit(SOCK_DEAD, &sk->flags))) {
 			rose_destroy_socket(sk);
 			return;
 		}
@@ -207,9 +209,9 @@
 	sk->err       = 0;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	bh_unlock_sock(sk);
 }
diff -Nru a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
--- a/net/sctp/ulpqueue.c	Mon Mar  3 01:00:55 2003
+++ b/net/sctp/ulpqueue.c	Mon Mar  3 04:56:53 2003
@@ -189,7 +189,7 @@
 	/* If the socket is just going to throw this away, do not
 	 * even try to deliver it.
 	 */
-	if (sk->dead || (sk->shutdown & RCV_SHUTDOWN))
+	if (test_bit(SOCK_DEAD, &sk->flags) || (sk->shutdown & RCV_SHUTDOWN))
 		goto out_free;
 
 	/* Check if the user wishes to receive this event.  */
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	Tue Feb 25 18:56:15 2003
+++ b/net/socket.c	Thu Mar  6 11:06:45 2003
@@ -78,6 +78,7 @@
 #include <linux/divert.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/compat.h>
 
 #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
 #include <linux/kmod.h>
@@ -88,9 +89,9 @@
 #endif	/* CONFIG_NET_RADIO */
 
 #include <asm/uaccess.h>
+#include <net/compat_socket.h>
 
 #include <net/sock.h>
-#include <net/scm.h>
 #include <linux/netfilter.h>
 
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
@@ -518,13 +519,13 @@
 	sock->file=NULL;
 }
 
-static int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size)
+static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size)
 {
 	struct sock_iocb *si = kiocb_to_siocb(iocb);
 	int err;
 
-	si->scm = &si->async_scm;
 	si->sock = sock;
+	si->scm = NULL;
 	si->msg = msg;
 	si->size = size;
 
@@ -532,13 +533,7 @@
 	if (err)
 		return err;
 
-	err = scm_send(sock, msg, si->scm);
-	if (err >= 0) {
-		err = sock->ops->sendmsg(iocb, sock, msg, size, si->scm);
-		if (-EIOCBQUEUED != err)
-			scm_destroy(si->scm);
-	}
-	return err;
+	return sock->ops->sendmsg(iocb, sock, msg, size);
 }
 
 int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size)
@@ -554,14 +549,13 @@
 }
 
 
-int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags)
+static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags)
 {
 	int err;
 	struct sock_iocb *si = kiocb_to_siocb(iocb);
 
 	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->sock = sock;
+	si->scm = NULL;
 	si->msg = msg;
 	si->size = size;
 	si->flags = flags;
@@ -570,13 +564,7 @@
 	if (err)
 		return err;
 
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	size = sock->ops->recvmsg(iocb, sock, msg, size, flags, si->scm);
-	if (size >= 0)
-		scm_recv(sock, msg, si->scm, flags);
-
-	return size;
+	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
 }
 
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags)
@@ -1545,12 +1533,21 @@
 	return err;
 }
 
+/* A couple of helpful macros for getting the address of the 32/64 bit 
+ * fields which are the same type (int / unsigned) on our platforms.
+ */
+#define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
+#define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
+#define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
+
+
 /*
  *	BSD sendmsg interface
  */
 
 asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
 {
+	struct compat_msghdr *msg_compat = (struct compat_msghdr *)msg;
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
@@ -1560,8 +1557,11 @@
 	int err, ctl_len, iov_size, total_len;
 	
 	err = -EFAULT;
-	if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
-		goto out; 
+	if (MSG_CMSG_COMPAT & flags) {
+		if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat))
+			return -EFAULT;
+	} else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
+		return -EFAULT;
 
 	sock = sockfd_lookup(fd, &err);
 	if (!sock) 
@@ -1582,7 +1582,10 @@
 	}
 
 	/* This will also move the address data into kernel space */
-	err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
+	if (MSG_CMSG_COMPAT & flags) {
+		err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+	} else
+		err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
 	if (err < 0) 
 		goto out_freeiov;
 	total_len = err;
@@ -1592,8 +1595,12 @@
 	if (msg_sys.msg_controllen > INT_MAX)
 		goto out_freeiov;
 	ctl_len = msg_sys.msg_controllen; 
-	if (ctl_len) 
-	{
+	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
+		err = cmsghdr_from_user_compat_to_kern(&msg_sys, ctl, sizeof(ctl));
+		if (err)
+			goto out_freeiov;
+		ctl_buf = msg_sys.msg_control;
+	} else if (ctl_len) {
 		if (ctl_len > sizeof(ctl))
 		{
 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
@@ -1629,6 +1636,7 @@
 
 asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
 {
+	struct compat_msghdr *msg_compat = (struct compat_msghdr *)msg;
 	struct socket *sock;
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov=iovstack;
@@ -1643,9 +1651,12 @@
 	struct sockaddr *uaddr;
 	int *uaddr_len;
 	
-	err=-EFAULT;
-	if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
-		goto out;
+	if (MSG_CMSG_COMPAT & flags) {
+		if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat))
+			return -EFAULT;
+	} else
+		if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
+			return -EFAULT;
 
 	sock = sockfd_lookup(fd, &err);
 	if (!sock)
@@ -1670,8 +1681,11 @@
 	 */
 	 
 	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+	uaddr_len = COMPAT_NAMELEN(msg);
+	if (MSG_CMSG_COMPAT & flags) {
+		err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+	} else
+		err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
 	if (err < 0)
 		goto out_freeiov;
 	total_len=err;
@@ -1691,11 +1705,20 @@
 		if (err < 0)
 			goto out_freeiov;
 	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
+	err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg));
 	if (err)
 		goto out_freeiov;
-	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
-							 &msg->msg_controllen);
+	if (MSG_CMSG_COMPAT & flags) {
+		unsigned long ucmsg_ptr;
+		compat_size_t uclen;
+		if((unsigned long) msg_sys.msg_control != cmsg_ptr)
+			cmsg_compat_recvmsg_fixup(&msg_sys, cmsg_ptr);
+		ucmsg_ptr = ((unsigned long)msg_sys.msg_control);
+		uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
+		err = __put_user(uclen, &msg_compat->msg_controllen);
+	} else
+		err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
+				 &msg->msg_controllen);
 	if (err)
 		goto out_freeiov;
 	err = len;
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	Sat Feb 15 12:05:02 2003
+++ b/net/sunrpc/clnt.c	Thu Mar  6 08:17:17 2003
@@ -208,7 +208,8 @@
 		rpcauth_destroy(clnt->cl_auth);
 		clnt->cl_auth = NULL;
 	}
-	rpc_rmdir(clnt->cl_pathname);
+	if (clnt->cl_pathname[0])
+		rpc_rmdir(clnt->cl_pathname);
 	if (clnt->cl_xprt) {
 		xprt_destroy(clnt->cl_xprt);
 		clnt->cl_xprt = NULL;
diff -Nru a/net/sunrpc/sched.c b/net/sunrpc/sched.c
--- a/net/sunrpc/sched.c	Tue Feb 11 14:57:54 2003
+++ b/net/sunrpc/sched.c	Sat Mar  8 15:47:51 2003
@@ -158,10 +158,8 @@
 static inline void
 rpc_delete_timer(struct rpc_task *task)
 {
-	if (timer_pending(&task->tk_timer)) {
+	if (del_timer_sync(&task->tk_timer))
 		dprintk("RPC: %4d deleting timer\n", task->tk_pid);
-		del_timer_sync(&task->tk_timer);
-	}
 }
 
 /*
diff -Nru a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
--- a/net/sunrpc/svcauth_unix.c	Mon Jan 13 17:12:02 2003
+++ b/net/sunrpc/svcauth_unix.c	Tue Mar 11 20:03:48 2003
@@ -441,9 +441,6 @@
 		return SVC_DENIED;
 	}
 
-	/* Put NULL verifier */
-	svc_putu32(resv, RPC_AUTH_NULL);
-	svc_putu32(resv, 0);
 
 	key.m_class = rqstp->rq_server->sv_program->pg_class;
 	key.m_addr = rqstp->rq_addr.sin_addr;
@@ -470,8 +467,13 @@
 		}
 	else rv = SVC_DROP;
 
-	if (rqstp->rq_client == NULL && rqstp->rq_proc != 0)
+	if (rv  == SVC_OK && rqstp->rq_client == NULL && rqstp->rq_proc != 0)
 		goto badcred;
+
+	/* Put NULL verifier */
+	svc_putu32(resv, RPC_AUTH_NULL);
+	svc_putu32(resv, 0);
+
 	return rv;
 
 badcred:
diff -Nru a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
--- a/net/sunrpc/svcsock.c	Mon Feb 17 13:46:20 2003
+++ b/net/sunrpc/svcsock.c	Tue Mar 11 20:03:48 2003
@@ -577,12 +577,15 @@
 
 	if (skb_is_nonlinear(skb)) {
 		/* we have to copy */
+		local_bh_disable();
 		if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) {
+			local_bh_enable();
 			/* checksum error */
 			skb_free_datagram(svsk->sk_sk, skb);
 			svc_sock_received(svsk);
 			return 0;
 		}
+		local_bh_enable();
 		skb_free_datagram(svsk->sk_sk, skb); 
 	} else {
 		/* we can use it in-place */
@@ -1435,7 +1438,7 @@
 svc_defer(struct cache_req *req)
 {
 	struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle);
-	int size = sizeof(struct svc_deferred_req) + (rqstp->rq_arg.head[0].iov_len);
+	int size = sizeof(struct svc_deferred_req) + (rqstp->rq_arg.len);
 	struct svc_deferred_req *dr;
 
 	if (rqstp->rq_arg.page_len)
@@ -1444,6 +1447,7 @@
 		dr = rqstp->rq_deferred;
 		rqstp->rq_deferred = NULL;
 	} else {
+		int skip  = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
 		/* FIXME maybe discard if size too large */
 		dr = kmalloc(size, GFP_KERNEL);
 		if (dr == NULL)
@@ -1452,8 +1456,8 @@
 		dr->serv = rqstp->rq_server;
 		dr->prot = rqstp->rq_prot;
 		dr->addr = rqstp->rq_addr;
-		dr->argslen = rqstp->rq_arg.head[0].iov_len >> 2;
-		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base, dr->argslen<<2);
+		dr->argslen = rqstp->rq_arg.len >> 2;
+		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
 	}
 	spin_lock(&rqstp->rq_server->sv_lock);
 	rqstp->rq_sock->sk_inuse++;
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	Thu Feb 13 05:17:10 2003
+++ b/net/sunrpc/xprt.c	Mon Mar  3 04:56:53 2003
@@ -967,7 +967,7 @@
 	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
 	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
 				sk->state, xprt_connected(xprt),
-				sk->dead, sk->zapped);
+				test_bit(SOCK_DEAD, &sk->flags), sk->zapped);
 
 	switch (sk->state) {
 	case TCP_ESTABLISHED:
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	Fri Feb  7 01:50:37 2003
+++ b/net/unix/af_unix.c	Thu Mar  6 11:06:45 2003
@@ -331,7 +331,8 @@
 		 * we signal error. Messages are lost. Do not make this,
 		 * when peer was not connected to us.
 		 */
-		if (!other->dead && unix_peer(other) == sk) {
+		if (!test_bit(SOCK_DEAD, &other->flags) &&
+				unix_peer(other) == sk) {
 			other->err = ECONNRESET;
 			other->error_report(other);
 		}
@@ -347,7 +348,7 @@
 	BUG_TRAP(atomic_read(&sk->wmem_alloc) == 0);
 	BUG_TRAP(!u->list);
 	BUG_TRAP(sk->socket==NULL);
-	if (sk->dead==0) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive unix socket: %p\n", sk);
 		return;
 	}
@@ -863,7 +864,7 @@
 	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue_exclusive(&u->peer_wait, &wait);
 
-	sched = (!other->dead &&
+	sched = (!test_bit(SOCK_DEAD, &other->flags) &&
 		 !(other->shutdown&RCV_SHUTDOWN) &&
 		 skb_queue_len(&other->receive_queue) > other->max_ack_backlog);
 
@@ -928,7 +929,7 @@
 	unix_state_rlock(other);
 
 	/* Apparently VFS overslept socket death. Retry. */
-	if (other->dead) {
+	if (test_bit(SOCK_DEAD, &other->flags)) {
 		unix_state_runlock(other);
 		sock_put(other);
 		goto restart;
@@ -1192,10 +1193,10 @@
  *	Send AF_UNIX data.
  */
 
-static int unix_dgram_sendmsg(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int len,
-			      struct scm_cookie *scm)
+static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
+			      struct msghdr *msg, int len)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	struct unix_sock *u = unix_sk(sk);
 	struct sockaddr_un *sunaddr=msg->msg_name;
@@ -1205,6 +1206,13 @@
 	unsigned hash;
 	struct sk_buff *skb;
 	long timeo;
+	struct scm_cookie tmp_scm;
+
+	if (NULL == siocb->scm)
+		siocb->scm = &tmp_scm;
+	err = scm_send(sock, msg, siocb->scm);
+	if (err < 0)
+		return err;
 
 	err = -EOPNOTSUPP;
 	if (msg->msg_flags&MSG_OOB)
@@ -1234,9 +1242,9 @@
 	if (skb==NULL)
 		goto out;
 
-	memcpy(UNIXCREDS(skb), &scm->creds, sizeof(struct ucred));
-	if (scm->fp)
-		unix_attach_fds(scm, skb);
+	memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+	if (siocb->scm->fp)
+		unix_attach_fds(siocb->scm, skb);
 
 	skb->h.raw = skb->data;
 	err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
@@ -1261,7 +1269,7 @@
 	if (!unix_may_send(sk, other))
 		goto out_unlock;
 
-	if (other->dead) {
+	if (test_bit(SOCK_DEAD, &other->flags)) {
 		/*
 		 *	Check with 1003.1g - what should
 		 *	datagram error
@@ -1316,6 +1324,7 @@
 	unix_state_runlock(other);
 	other->data_ready(other, len);
 	sock_put(other);
+	scm_destroy(siocb->scm);
 	return len;
 
 out_unlock:
@@ -1325,20 +1334,28 @@
 out:
 	if (other)
 		sock_put(other);
+	scm_destroy(siocb->scm);
 	return err;
 }
 
 		
-static int unix_stream_sendmsg(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int len,
-			       struct scm_cookie *scm)
+static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
+			       struct msghdr *msg, int len)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	unix_socket *other = NULL;
 	struct sockaddr_un *sunaddr=msg->msg_name;
 	int err,size;
 	struct sk_buff *skb;
 	int sent=0;
+	struct scm_cookie tmp_scm;
+
+	if (NULL == siocb->scm)
+		siocb->scm = &tmp_scm;
+	err = scm_send(sock, msg, siocb->scm);
+	if (err < 0)
+		return err;
 
 	err = -EOPNOTSUPP;
 	if (msg->msg_flags&MSG_OOB)
@@ -1392,9 +1409,9 @@
 		 */
 		size = min_t(int, size, skb_tailroom(skb));
 
-		memcpy(UNIXCREDS(skb), &scm->creds, sizeof(struct ucred));
-		if (scm->fp)
-			unix_attach_fds(scm, skb);
+		memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+		if (siocb->scm->fp)
+			unix_attach_fds(siocb->scm, skb);
 
 		if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) {
 			kfree_skb(skb);
@@ -1403,7 +1420,8 @@
 
 		unix_state_rlock(other);
 
-		if (other->dead || (other->shutdown & RCV_SHUTDOWN))
+		if (test_bit(SOCK_DEAD, &other->flags) ||
+				(other->shutdown & RCV_SHUTDOWN))
 			goto pipe_err_free;
 
 		skb_queue_tail(&other->receive_queue, skb);
@@ -1412,6 +1430,10 @@
 		sent+=size;
 	}
 	sock_put(other);
+
+	scm_destroy(siocb->scm);
+	siocb->scm = NULL;
+
 	return sent;
 
 pipe_err_free:
@@ -1424,6 +1446,8 @@
 out_err:
         if (other)
 		sock_put(other);
+	scm_destroy(siocb->scm);
+	siocb->scm = NULL;
 	return sent ? : err;
 }
 
@@ -1440,8 +1464,10 @@
 
 static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 			      struct msghdr *msg, int size,
-			      int flags, struct scm_cookie *scm)
+			      int flags)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(iocb);
+	struct scm_cookie tmp_scm;
 	struct sock *sk = sock->sk;
 	struct unix_sock *u = unix_sk(sk);
 	int noblock = flags & MSG_DONTWAIT;
@@ -1472,12 +1498,16 @@
 	if (err)
 		goto out_free;
 
-	scm->creds = *UNIXCREDS(skb);
+	if (!siocb->scm) {
+		siocb->scm = &tmp_scm;
+		memset(&tmp_scm, 0, sizeof(tmp_scm));
+	}
+	siocb->scm->creds = *UNIXCREDS(skb);
 
 	if (!(flags & MSG_PEEK))
 	{
 		if (UNIXCB(skb).fp)
-			unix_detach_fds(scm, skb);
+			unix_detach_fds(siocb->scm, skb);
 	}
 	else 
 	{
@@ -1494,10 +1524,12 @@
 		   
 		*/
 		if (UNIXCB(skb).fp)
-			scm->fp = scm_fp_dup(UNIXCB(skb).fp);
+			siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
 	}
 	err = size;
 
+	scm_recv(sock, msg, siocb->scm, flags);
+
 out_free:
 	skb_free_datagram(sk,skb);
 out:
@@ -1543,8 +1575,10 @@
 
 static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 			       struct msghdr *msg, int size,
-			       int flags, struct scm_cookie *scm)
+			       int flags)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(iocb);
+	struct scm_cookie tmp_scm;
 	struct sock *sk = sock->sk;
 	struct unix_sock *u = unix_sk(sk);
 	struct sockaddr_un *sunaddr=msg->msg_name;
@@ -1571,6 +1605,11 @@
 	 * while sleeps in memcpy_tomsg
 	 */
 
+	if (!siocb->scm) {
+		siocb->scm = &tmp_scm;
+		memset(&tmp_scm, 0, sizeof(tmp_scm));
+	}
+
 	down(&u->readsem);
 
 	do
@@ -1609,13 +1648,13 @@
 
 		if (check_creds) {
 			/* Never glue messages from different writers */
-			if (memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) {
+			if (memcmp(UNIXCREDS(skb), &siocb->scm->creds, sizeof(siocb->scm->creds)) != 0) {
 				skb_queue_head(&sk->receive_queue, skb);
 				break;
 			}
 		} else {
 			/* Copy credentials */
-			scm->creds = *UNIXCREDS(skb);
+			siocb->scm->creds = *UNIXCREDS(skb);
 			check_creds = 1;
 		}
 
@@ -1642,7 +1681,7 @@
 			skb_pull(skb, chunk);
 
 			if (UNIXCB(skb).fp)
-				unix_detach_fds(scm, skb);
+				unix_detach_fds(siocb->scm, skb);
 
 			/* put the skb back if we didn't use it up.. */
 			if (skb->len)
@@ -1653,7 +1692,7 @@
 
 			kfree_skb(skb);
 
-			if (scm->fp)
+			if (siocb->scm->fp)
 				break;
 		}
 		else
@@ -1661,7 +1700,7 @@
 			/* It is questionable, see note in unix_dgram_recvmsg.
 			 */
 			if (UNIXCB(skb).fp)
-				scm->fp = scm_fp_dup(UNIXCB(skb).fp);
+				siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
 
 			/* put message back and return */
 			skb_queue_head(&sk->receive_queue, skb);
@@ -1670,6 +1709,7 @@
 	} while (size);
 
 	up(&u->readsem);
+	scm_recv(sock, msg, siocb->scm, flags);
 out:
 	return copied ? : err;
 }
diff -Nru a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
--- a/net/wanrouter/af_wanpipe.c	Mon Feb 24 12:51:23 2003
+++ b/net/wanrouter/af_wanpipe.c	Sat Mar  8 11:30:11 2003
@@ -76,14 +76,7 @@
 	#define DBG_PRINTK(format, a...)
 #endif      
 
-#if defined(LINUX_2_1)
- #define dev_put(a)
- #define __sock_put(a)
- #define sock_hold(a)
- #define DECLARE_WAITQUEUE(a,b) \
-		struct wait_queue a = { b, NULL }
-#endif
-		
+
 /* SECURE SOCKET IMPLEMENTATION 
  * 
  *   TRANSMIT:
@@ -542,7 +535,7 @@
  *===========================================================*/
 
 static int wanpipe_sendmsg(struct kiocb *iocb, struct socket *sock,
-			   struct msghdr *msg, int len, struct scm_cookie *scm)
+			   struct msghdr *msg, int len)
 {
 	wanpipe_opt *wp;
 	struct sock *sk = sock->sk;
@@ -599,17 +592,8 @@
   		return -EMSGSIZE;
 	}
 
-      #ifndef LINUX_2_4
-	dev_lock_list();
-      #endif
-      
-      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
 	skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 
 				msg->msg_flags & MSG_DONTWAIT, &err);
-      #else
-	skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, 
-				msg->msg_flags & MSG_DONTWAIT, &err);
-      #endif
 
 	if (skb==NULL){
 		goto out_unlock;
@@ -642,10 +626,6 @@
 	if (!(dev->flags & IFF_UP))
 		goto out_free;
 
-      #ifndef LINUX_2_4
-	dev_unlock_list();
-      #endif
-	
 	if (atomic_read(&sk->wmem_alloc) + skb->truesize > (unsigned int)sk->sndbuf){
 		kfree_skb(skb);
 		return -ENOBUFS;
@@ -665,9 +645,6 @@
 out_free:
 	kfree_skb(skb);
 out_unlock:
-#ifndef LINUX_2_4
-	dev_unlock_list();
-#endif
 	return err;
 }
 
@@ -862,16 +839,12 @@
 		kfree(wp);
 		wp_sk(sk) = NULL;
 		
-              #ifdef LINUX_2_4
 		if (atomic_read(&sk->refcnt) != 1){
 			atomic_set(&sk->refcnt,1);
 			DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :delay.\n",
 					atomic_read(&sk->refcnt));
 		}
 		sock_put(sk);
-              #else
-		sk_free(sk);
-              #endif
 		atomic_dec(&wanpipe_socks_nr);
 		MOD_DEC_USE_COUNT;
 		return;
@@ -970,16 +943,8 @@
  *      protocol entry in the device list.
  *===========================================================*/
 
-#ifdef LINUX_2_4
 static int wanpipe_release(struct socket *sock)
-#else
-static int wanpipe_release(struct socket *sock, struct socket *peersock)
-#endif
 {
-	
-#ifndef LINUX_2_4
-	struct sk_buff	*skb;
-#endif
 	wanpipe_opt *wp;
 	struct sock *sk = sock->sk;
 	struct sock **skp;
@@ -1039,25 +1004,13 @@
 
 	sock->sk = NULL;
 	sk->socket = NULL;
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 
 	/* Purge queues */
-#ifdef LINUX_2_4
 	skb_queue_purge(&sk->receive_queue);
 	skb_queue_purge(&sk->write_queue);
 	skb_queue_purge(&sk->error_queue);
-#else	
 
-	while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->error_queue))!=NULL){
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->write_queue))!=NULL){
-		kfree_skb(skb);
-	}
-#endif	
 	if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {
 		del_timer(&sk->timer);
 		printk(KERN_INFO "wansock: Killing in Timer R %i , W %i\n",
@@ -1072,16 +1025,12 @@
 	kfree(wp);
 	wp_sk(sk) = NULL;
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:release.\n",
 					atomic_read(&sk->refcnt));
 		atomic_set(&sk->refcnt,1);
 	}
 	sock_put(sk);
-      #else	
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -1128,7 +1077,7 @@
 		while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){
 			if ((deadsk = get_newsk_from_skb(skb))){
 				DBG_PRINTK (KERN_INFO "wansock: RELEASE: FOUND DEAD SOCK\n");
-				deadsk->dead=1;
+				__set_bit(SOCK_DEAD, &deadsk->flags);
 				start_cleanup_timer(deadsk);
 			}
 			kfree_skb(skb);
@@ -1181,10 +1130,6 @@
 {
 
 	struct sock *sk = (struct sock *)data;
-#ifndef LINUX_2_4
-	struct sk_buff *skb;
-#endif
-
 	struct sock **skp;
 
 	if (!sk)
@@ -1226,21 +1171,9 @@
 	sk->socket = NULL;
 
 	/* Purge queues */
-#ifdef LINUX_2_4
 	skb_queue_purge(&sk->receive_queue);
 	skb_queue_purge(&sk->write_queue);
 	skb_queue_purge(&sk->error_queue);
-#else	
-	while ((skb=skb_dequeue(&sk->receive_queue)) != NULL){
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->write_queue)) != NULL) {
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->error_queue)) != NULL){
-		kfree_skb(skb);
-	}
-#endif
 	
 	if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {
 		del_timer(&sk->timer);
@@ -1257,16 +1190,12 @@
 		wp_sk(sk) = NULL;
 	}
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		atomic_set(&sk->refcnt,1);
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",
 					atomic_read(&sk->refcnt));
 	}
 	sock_put(sk);
-      #else
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return;
@@ -1301,16 +1230,12 @@
 		wp_sk(sk) = NULL;
 	}
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		atomic_set(&sk->refcnt,1);
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",
 					atomic_read(&sk->refcnt));
 	}
 	sock_put(sk);
-      #else
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return;
@@ -1330,16 +1255,12 @@
 		wp_sk(sk) = NULL;
 	}
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		atomic_set(&sk->refcnt,1);
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:listen.\n",
 					atomic_read(&sk->refcnt));
 	}
 	sock_put(sk);
-      #else
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return;
@@ -1494,11 +1415,7 @@
                  */
 		strncpy(name,sll->sll_device,14);
 		name[14]=0;
-#ifdef LINUX_2_4
 		dev = dev_get_by_name(name);
-#else
-		dev = dev_get(name);
-#endif
 		if (dev == NULL){
 			printk(KERN_INFO "wansock: Failed to get Dev from name: %s,\n",
 					name);
@@ -1649,8 +1566,7 @@
  *===========================================================*/
 
 static int wanpipe_recvmsg(struct kiocb *iocb, struct socket *sock,
-			   struct msghdr *msg, int len, int flags,
-			   struct scm_cookie *scm)
+			   struct msghdr *msg, int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
@@ -1706,11 +1622,7 @@
 	if (err)
 		goto out_free;
 	
-#ifdef LINUX_2_1
-	sk->stamp=skb->stamp;
-#else
 	sock_recv_timestamp(msg, sk, skb);
-#endif
 	
 	if (msg->msg_name)
 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
@@ -2212,11 +2124,7 @@
 	if (sock_writeable(sk)){
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 	}else{
-	      #ifdef LINUX_2_4
 		set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
-	      #else
- 		sk->socket->flags |= SO_NOSPACE;
-	      #endif
 	}
 		
 	return mask;
@@ -2649,7 +2557,6 @@
 	return 0;
 }
 
-#ifdef LINUX_2_4
 struct proto_ops wanpipe_ops = {
 	.family = 	PF_WANPIPE,
 
@@ -2668,29 +2575,6 @@
 	.sendmsg = 	wanpipe_sendmsg,
 	.recvmsg = 	wanpipe_recvmsg
 };
-#else
-struct proto_ops wanpipe_ops = {
-	PF_WANPIPE,
-
-	sock_no_dup,
-	wanpipe_release,
-	wanpipe_bind,
-	wanpipe_connect,
-	sock_no_socketpair,
-	wanpipe_accept,
-	wanpipe_getname, 
-	wanpipe_poll,
-	wanpipe_ioctl,
-	wanpipe_listen, 
-	sock_no_shutdown,
-	sock_no_setsockopt,
-	sock_no_getsockopt,
-	sock_no_fcntl,
-	wanpipe_sendmsg,
-	wanpipe_recvmsg
-};
-#endif
-
 
 static struct net_proto_family wanpipe_family_ops = {
 	.family =PF_WANPIPE,
diff -Nru a/net/x25/af_x25.c b/net/x25/af_x25.c
--- a/net/x25/af_x25.c	Tue Oct  8 07:03:35 2002
+++ b/net/x25/af_x25.c	Thu Mar  6 11:06:45 2003
@@ -344,7 +344,7 @@
 			/*
 			 * Queue the unaccepted socket for death
 			 */
-			skb->sk->dead = 1;
+			__set_bit(SOCK_DEAD, &skb->sk->flags);
 			x25_start_heartbeat(skb->sk);
 			x25_sk(skb->sk)->state = X25_STATE_0;
 		}
@@ -580,8 +580,8 @@
 			sk->state               = TCP_CLOSE;
 			sk->shutdown           |= SEND_SHUTDOWN;
 			sk->state_change(sk);
-			sk->dead                = 1;
-			sk->destroy             = 1;
+			__set_bit(SOCK_DEAD, &sk->flags);
+			__set_bit(SOCK_DESTROY, &sk->flags);
 			break;
 	}
 
@@ -902,7 +902,7 @@
 
 	x25_start_heartbeat(make);
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skb->len);
 	rc = 1;
 	sock_put(sk);
@@ -917,7 +917,7 @@
 }
 
 static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
-		       struct msghdr *msg, int len, struct scm_cookie *scm)
+		       struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct x25_opt *x25 = x25_sk(sk);
@@ -1093,7 +1093,7 @@
 
 static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *msg, int size,
-		       int flags, struct scm_cookie *scm)
+		       int flags)
 {
 	struct sock *sk = sock->sk;
 	struct x25_opt *x25 = x25_sk(sk);
@@ -1112,7 +1112,8 @@
 
 	if (flags & MSG_OOB) {
 		rc = -EINVAL;
-		if (sk->urginline || !skb_peek(&x25->interrupt_in_queue))
+		if (test_bit(SOCK_URGINLINE, &sk->flags) ||
+				!skb_peek(&x25->interrupt_in_queue))
 			goto out;
 
 		skb = skb_dequeue(&x25->interrupt_in_queue);
diff -Nru a/net/x25/x25_in.c b/net/x25/x25_in.c
--- a/net/x25/x25_in.c	Sat Sep 28 02:28:53 2002
+++ b/net/x25/x25_in.c	Mon Mar  3 04:56:53 2003
@@ -86,7 +86,7 @@
 
 	skb_set_owner_r(skbn, sk);
 	skb_queue_tail(&sk->receive_queue, skbn);
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skbn->len);
 
 	return 0;
@@ -129,7 +129,7 @@
 				       skb->len);
 				x25->calluserdata.cudlength = skb->len;
 			}
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->state_change(sk);
 			break;
 		}
@@ -277,7 +277,7 @@
 			break;
 
 		case X25_INTERRUPT:
-			if (sk->urginline) {
+			if (test_bit(SOCK_URGINLINE, &sk->flags)) {
 				queued = (sock_queue_rcv_skb(sk, skb) == 0);
 			} else {
 				skb_set_owner_r(skb, sk);
diff -Nru a/net/x25/x25_subr.c b/net/x25/x25_subr.c
--- a/net/x25/x25_subr.c	Sat Sep 28 02:28:53 2002
+++ b/net/x25/x25_subr.c	Mon Mar  3 04:56:53 2003
@@ -344,10 +344,10 @@
 	sk->err       = reason;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 }
 
 /*
diff -Nru a/net/x25/x25_timer.c b/net/x25/x25_timer.c
--- a/net/x25/x25_timer.c	Tue Oct  8 17:45:17 2002
+++ b/net/x25/x25_timer.c	Mon Mar  3 04:56:53 2003
@@ -139,7 +139,7 @@
 		case X25_STATE_0:
 			/* Magic here: If we listen() and a new link dies before it
 			   is accepted() it isn't 'dead' so doesn't get removed. */
-			if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
+			if (test_bit(SOCK_DESTROY, &sk->flags) || (sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &sk->flags))) {
 				x25_destroy_socket(sk);
 				goto unlock;
 			}
diff -Nru a/scripts/Makefile b/scripts/Makefile
--- a/scripts/Makefile	Fri Feb 21 19:54:51 2003
+++ b/scripts/Makefile	Mon Mar 10 13:03:33 2003
@@ -8,11 +8,11 @@
 # docproc: 	 Preprocess .tmpl file in order to generate .sgml docs
 # conmakehash:	 Create arrays for initializing the kernel console tables
 
-host-progs    := fixdep split-include conmakehash docproc kallsyms modpost \
-		 mk_elfconfig
-build-targets := $(host-progs) empty.o
+host-progs	:= fixdep split-include conmakehash docproc kallsyms modpost \
+		   mk_elfconfig
+always		:= $(host-progs) empty.o
 
-modpost-objs  := modpost.o file2alias.o
+modpost-objs	:= modpost.o file2alias.o
 
 subdir-$(CONFIG_MODVERSIONS)	+= genksyms
 
@@ -20,7 +20,7 @@
 subdir-	+= lxdialog kconfig
 
 # fixdep is needed to compile other host programs
-$(addprefix $(obj)/,$(filter-out fixdep,$(build-targets)) $(subdir-y)): $(obj)/fixdep
+$(addprefix $(obj)/,$(filter-out fixdep,$(always)) $(subdir-y)): $(obj)/fixdep
 
 # dependencies on generated files need to be listed explicitly
 
@@ -32,4 +32,4 @@
 $(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE
 	$(call if_changed,elfconfig)
 
-targets += $(obj)/elfconfig.h
+targets += elfconfig.h
diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build
--- a/scripts/Makefile.build	Wed Feb 19 14:42:13 2003
+++ b/scripts/Makefile.build	Mon Mar 10 13:03:33 2003
@@ -15,6 +15,14 @@
 
 include scripts/Makefile.lib
 
+ifdef EXTRA_TARGETS
+$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.5. Please fix!)
+endif
+
+ifdef build-targets
+$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.5. Please fix!)
+endif
+
 ifdef export-objs
 $(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.5. Please fix!)
 endif
@@ -53,9 +61,9 @@
 
 touch-module = @echo $(@:.o=.ko) > $(MODVERDIR)/$(@F:.o=.mod)
 
-__build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \
+__build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(extra-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m)) \
-	 $(subdir-ym) $(build-targets)
+	 $(subdir-ym) $(always)
 	@:
 
 # Module versioning
@@ -163,12 +171,12 @@
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
 
 $(single-used-m): %.o: %.c FORCE
-	$(touch-module)
 ifdef CONFIG_MODVERSIONS
 	$(call if_changed_rule,vcc_o_c)
 else
 	$(call if_changed_dep,cc_o_c)
 endif
+	$(touch-module)
 
 quiet_cmd_cc_lst_c = MKLST   $@
       cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
@@ -198,8 +206,7 @@
 %.o: %.S FORCE
 	$(call if_changed_dep,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) \
-	   $(build-targets)
+targets += $(real-objs-y) $(real-objs-m) $(extra-y) $(MAKECMDGOALS) $(always)
 
 # Build the compiled-in targets
 # ---------------------------------------------------------------------------
@@ -262,8 +269,8 @@
 	$(call if_changed,link_multi-y)
 
 $(multi-used-m) : %.o: $(multi-objs-m) FORCE
-	$(touch-module)
 	$(call if_changed,link_multi-m)
+	$(touch-module)
 
 targets += $(multi-used-y) $(multi-used-m)
 
diff -Nru a/scripts/Makefile.clean b/scripts/Makefile.clean
--- a/scripts/Makefile.clean	Wed Feb 19 09:02:47 2003
+++ b/scripts/Makefile.clean	Mon Mar 10 13:03:33 2003
@@ -28,14 +28,12 @@
 
 # Add subdir path
 
-EXTRA_TARGETS	:= $(addprefix $(obj)/,$(EXTRA_TARGETS))
-clean-files	:= $(addprefix $(obj)/,$(clean-files))
-host-progs	:= $(addprefix $(obj)/,$(host-progs))
 subdir-ymn	:= $(addprefix $(obj)/,$(subdir-ymn))
+__clean-files	:= $(wildcard $(addprefix $(obj)/, \
+		   $(extra-y) $(EXTRA_TARGETS) $(always) $(host-progs) \
+		   $(targets) $(clean-files)))
 
 # ==========================================================================
-
-__clean-files := $(wildcard $(EXTRA_TARGETS) $(host-progs) $(clean-files) $(targets))
 
 quiet_cmd_clean = CLEAN   $(obj)
       cmd_clean = rm -f $(__clean-files); $(clean-rule)
diff -Nru a/scripts/Makefile.lib b/scripts/Makefile.lib
--- a/scripts/Makefile.lib	Mon Feb 10 19:27:35 2003
+++ b/scripts/Makefile.lib	Mon Mar 10 13:03:33 2003
@@ -8,6 +8,8 @@
 empty   :=
 space   := $(empty) $(empty)
 
+# Backward compatibility - to be removed...
+extra-y	+= $(EXTRA_TARGETS)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
@@ -51,7 +53,7 @@
 subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)))
 
 # Replace multi-part objects by their individual parts, look at local dir only
-real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(EXTRA_TARGETS)
+real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
 real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
 
 # C code
@@ -84,8 +86,9 @@
 
 # Add subdir path
 
-EXTRA_TARGETS	:= $(addprefix $(obj)/,$(EXTRA_TARGETS))
-build-targets	:= $(addprefix $(obj)/,$(build-targets))
+extra-y		:= $(addprefix $(obj)/,$(extra-y))
+always		:= $(addprefix $(obj)/,$(always))
+targets		:= $(addprefix $(obj)/,$(targets))
 obj-y		:= $(addprefix $(obj)/,$(obj-y))
 obj-m		:= $(addprefix $(obj)/,$(obj-m))
 subdir-obj-y	:= $(addprefix $(obj)/,$(subdir-obj-y))
diff -Nru a/scripts/Makefile.modpost b/scripts/Makefile.modpost
--- a/scripts/Makefile.modpost	Sun Mar  2 20:55:31 2003
+++ b/scripts/Makefile.modpost	Wed Mar  5 17:51:30 2003
@@ -37,7 +37,7 @@
 quiet_cmd_cc_o_c = CC      $@
       cmd_cc_o_c = $(CC) $(CFLAGS) $(CFLAGS_MODULE) -c -o $@ $<
 
-$(modules:.ko=.mod.o): %.mod.o: %.mod.c
+$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
 	$(call if_changed,cc_o_c)
 
 targets += $(modules:.ko=.mod.o)
@@ -51,9 +51,9 @@
 # Extract all checksums for all exported symbols
 
 quiet_cmd_modpost = MODPOST
-      cmd_modpost = scripts/modpost $^
+      cmd_modpost = scripts/modpost $(filter-out FORCE,$^)
 
-__modpost: $(wildcard vmlinux) $(modules:.ko=.o)
+__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
 	$(call if_changed,modpost)
 
 targets += __modpost
diff -Nru a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
--- a/scripts/genksyms/Makefile	Wed Feb 19 14:17:21 2003
+++ b/scripts/genksyms/Makefile	Mon Mar 10 13:03:33 2003
@@ -1,6 +1,6 @@
 
 host-progs	:= genksyms
-build-targets	:= $(host-progs)
+always		:= $(host-progs)
 
 genksyms-objs	:= genksyms.o parse.o lex.o
 
diff -Nru a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
--- a/scripts/kconfig/Makefile	Tue Dec 31 11:22:40 2002
+++ b/scripts/kconfig/Makefile	Sat Mar 15 09:25:56 2003
@@ -6,20 +6,29 @@
 #         Utilizes the lxdialog package
 # qconf:  Used for the xconfig target
 #         Based on QT which needs to be installed to compile it
+# gconf:  Used for the gconfig target
+#         Based on GTK which needs to be installed to compile it
 #
+#################
 
 # object files used by all lkc flavours
 libkconfig-objs := zconf.tab.o
 
-host-progs	:= conf mconf qconf
+host-progs	:= conf mconf qconf gconf
 conf-objs	:= conf.o  libkconfig.so
 mconf-objs	:= mconf.o libkconfig.so
 
-qconf-objs	:= kconfig_load.o
+ifeq ($(MAKECMDGOALS),$(obj)/qconf)
 qconf-cxxobjs	:= qconf.o
+qconf-objs	:= kconfig_load.o
+endif
+
+ifeq ($(MAKECMDGOALS),$(obj)/gconf)
+gconf-objs	:= gconf.o kconfig_load.o
+endif
 
 clean-files	:= libkconfig.so lkc_defs.h qconf.moc .tmp_qtcheck \
-		   zconf.tab.c zconf.tab.h lex.zconf.c
+		   .tmp_gtkcheck zconf.tab.c zconf.tab.h lex.zconf.c
 
 # generated files seem to need this to find local include files
 HOSTCFLAGS_lex.zconf.o	:= -I$(src)
@@ -28,7 +37,10 @@
 HOSTLOADLIBES_qconf	= -L$(QTDIR)/lib -Wl,-rpath,$(QTDIR)/lib -l$(QTLIB) -ldl
 HOSTCXXFLAGS_qconf.o	= -I$(QTDIR)/include 
 
-$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o: $(obj)/zconf.tab.h
+HOSTLOADLIBES_gconf	= `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs`
+HOSTCFLAGS_gconf.o	= `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags`
+
+$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o $(obj)/gconf.o: $(obj)/zconf.tab.h
 
 $(obj)/qconf.o: $(obj)/.tmp_qtcheck
 
@@ -38,7 +50,7 @@
 
 # QT needs some extra effort...
 $(obj)/.tmp_qtcheck:
-	@set -e; for d in $$QTDIR /usr/share/qt /usr/lib/qt*3*; do \
+	@set -e; for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
 	  if [ -f $$d/include/qconfig.h ]; then DIR=$$d; break; fi; \
 	done; \
 	if [ -z "$$DIR" ]; then \
@@ -60,11 +72,39 @@
 	fi
 endif
 
+$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
+
+ifeq ($(MAKECMDGOALS),$(obj)/gconf)
+-include $(obj)/.tmp_gtkcheck
+
+# GTK needs some extra effort, too...
+$(obj)/.tmp_gtkcheck:
+	@if `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --exists`; then		\
+		if `pkg-config gtk+-2.0 --atleast-version=2.0.0`; then			\
+			touch $@;								\
+		else									\
+			echo "*"; 							\
+			echo "* GTK+ is present but version >= 2.0.0 is required.";	\
+			echo "*";							\
+			false;								\
+		fi									\
+	else										\
+		echo "*"; 								\
+		echo "* Unable to find the GTK+ installation. Please make sure that"; 	\
+		echo "* the GTK+ 2.0 development package is correctly installed..."; 	\
+		echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; 		\
+		echo "*"; 								\
+		false;									\
+	fi
+endif
+
 $(obj)/zconf.tab.o: $(obj)/lex.zconf.c
 
 $(obj)/kconfig_load.o: $(obj)/lkc_defs.h
 
 $(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h
+
+$(obj)/gconf.o: $(obj)/lkc_defs.h
 
 $(obj)/%.moc: $(src)/%.h
 	$(MOC) -i $< -o $@
diff -Nru a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
--- a/scripts/kconfig/expr.h	Sat Dec  7 20:14:02 2002
+++ b/scripts/kconfig/expr.h	Sat Mar 15 09:25:55 2003
@@ -155,9 +155,11 @@
 #define for_all_properties(sym, st, tok) \
 	for (st = sym->prop; st; st = st->next) \
 		if (st->type == (tok))
-#define for_all_prompts(sym, st) for_all_properties(sym, st, P_PROMPT)
 #define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
 #define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
+#define for_all_prompts(sym, st) \
+	for (st = sym->prop; st; st = st->next) \
+		if (st->text)
 
 struct menu {
 	struct menu *next;
diff -Nru a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/kconfig/gconf.c	Sat Mar 15 09:25:55 2003
@@ -0,0 +1,1580 @@
+/* Hey EMACS -*- linux-c -*- */
+/*
+ *
+ * Copyright (C) 2002-2003 Romain Lievin <roms@lpg.ticalc.org>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "lkc.h"
+#include "images.c"
+
+#include <glade/glade.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdlib.h>
+
+//#define DEBUG
+
+enum {
+	SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
+};
+
+static gint view_mode = SPLIT_VIEW;
+static gboolean show_name = TRUE;
+static gboolean show_range = TRUE;
+static gboolean show_value = TRUE;
+static gboolean show_all = FALSE;
+static gboolean show_debug = FALSE;
+static gboolean resizeable = FALSE;
+
+static gboolean config_changed = FALSE;
+
+static char nohelp_text[] =
+    "Sorry, no help available for this option yet.\n";
+
+GtkWidget *main_wnd = NULL;
+GtkWidget *tree1_w = NULL;	// left  frame
+GtkWidget *tree2_w = NULL;	// right frame
+GtkWidget *text_w = NULL;
+GtkWidget *hpaned = NULL;
+GtkWidget *vpaned = NULL;
+GtkWidget *back_btn = NULL;
+
+GtkTextTag *tag1, *tag2;
+GdkColor color;
+
+GtkTreeStore *tree1, *tree2, *tree;
+GtkTreeModel *model1, *model2;
+static GtkTreeIter *parents[256] = { 0 };
+static gint indent;
+
+static struct menu *current;
+
+enum {
+	COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
+	COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
+	COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC,
+	COL_NUMBER
+};
+
+static void display_list(void);
+static void display_tree(struct menu *menu);
+static void display_tree_part(void);
+static void update_tree(struct menu *src, GtkTreeIter * dst);
+static void set_node2(GtkTreeIter * node, struct menu *menu, gchar ** row);
+static gchar **fill_row(struct menu *menu);
+
+
+/* Helping/Debugging Functions */
+
+
+const char *dbg_print_stype(int val)
+{
+	static char buf[256];
+
+	bzero(buf, 256);
+
+	if (val == S_UNKNOWN)
+		strcpy(buf, "unknown");
+	if (val == S_BOOLEAN)
+		strcpy(buf, "boolean");
+	if (val == S_TRISTATE)
+		strcpy(buf, "tristate");
+	if (val == S_INT)
+		strcpy(buf, "int");
+	if (val == S_HEX)
+		strcpy(buf, "hex");
+	if (val == S_STRING)
+		strcpy(buf, "string");
+	if (val == S_OTHER)
+		strcpy(buf, "other");
+
+#ifdef DEBUG
+	printf("%s", buf);
+#endif
+
+	return buf;
+}
+
+const char *dbg_print_flags(int val)
+{
+	static char buf[256] = { 0 };
+
+	bzero(buf, 256);
+
+	if (val & SYMBOL_YES)
+		strcat(buf, "yes/");
+	if (val & SYMBOL_MOD)
+		strcat(buf, "mod/");
+	if (val & SYMBOL_NO)
+		strcat(buf, "no/");
+	if (val & SYMBOL_CONST)
+		strcat(buf, "const/");
+	if (val & SYMBOL_CHECK)
+		strcat(buf, "check/");
+	if (val & SYMBOL_CHOICE)
+		strcat(buf, "choice/");
+	if (val & SYMBOL_CHOICEVAL)
+		strcat(buf, "choiceval/");
+	if (val & SYMBOL_PRINTED)
+		strcat(buf, "printed/");
+	if (val & SYMBOL_VALID)
+		strcat(buf, "valid/");
+	if (val & SYMBOL_OPTIONAL)
+		strcat(buf, "optional/");
+	if (val & SYMBOL_WRITE)
+		strcat(buf, "write/");
+	if (val & SYMBOL_CHANGED)
+		strcat(buf, "changed/");
+	if (val & SYMBOL_NEW)
+		strcat(buf, "new/");
+	if (val & SYMBOL_AUTO)
+		strcat(buf, "auto/");
+
+	buf[strlen(buf) - 1] = '\0';
+#ifdef DEBUG
+	printf("%s", buf);
+#endif
+
+	return buf;
+}
+
+const char *dbg_print_ptype(int val)
+{
+	static char buf[256];
+
+	bzero(buf, 256);
+
+	if (val == P_UNKNOWN)
+		strcpy(buf, "unknown");
+	if (val == P_PROMPT)
+		strcpy(buf, "prompt");
+	if (val == P_COMMENT)
+		strcpy(buf, "comment");
+	if (val == P_MENU)
+		strcpy(buf, "menu");
+	if (val == P_ROOTMENU)
+		strcpy(buf, "rootmenu");
+	if (val == P_DEFAULT)
+		strcpy(buf, "default");
+	if (val == P_CHOICE)
+		strcpy(buf, "choice");
+
+#ifdef DEBUG
+	printf("%s", buf);
+#endif
+
+	return buf;
+}
+
+
+/* Main Window Initialization */
+
+
+void init_main_window(const gchar * glade_file)
+{
+	GladeXML *xml;
+	GtkWidget *widget;
+	GtkTextBuffer *txtbuf;
+	char title[256];
+	GdkPixmap *pixmap;
+	GdkBitmap *mask;
+	GtkStyle *style;
+
+	xml = glade_xml_new(glade_file, "window1", NULL);
+	if (!xml)
+		g_error("GUI loading failed !\n");
+	glade_xml_signal_autoconnect(xml);
+
+	main_wnd = glade_xml_get_widget(xml, "window1");
+	hpaned = glade_xml_get_widget(xml, "hpaned1");
+	vpaned = glade_xml_get_widget(xml, "vpaned1");
+	tree1_w = glade_xml_get_widget(xml, "treeview1");
+	tree2_w = glade_xml_get_widget(xml, "treeview2");
+	text_w = glade_xml_get_widget(xml, "textview3");
+
+	back_btn = glade_xml_get_widget(xml, "button1");
+	gtk_widget_set_sensitive(back_btn, FALSE);
+
+	widget = glade_xml_get_widget(xml, "show_name1");
+	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+				       show_name);
+
+	widget = glade_xml_get_widget(xml, "show_range1");
+	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+				       show_range);
+
+	widget = glade_xml_get_widget(xml, "show_data1");
+	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+				       show_value);
+
+	style = gtk_widget_get_style(main_wnd);
+	widget = glade_xml_get_widget(xml, "toolbar1");
+
+	pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
+					      &style->bg[GTK_STATE_NORMAL],
+					      (gchar **) xpm_single_view);
+	gtk_image_set_from_pixmap(GTK_IMAGE
+				  (((GtkToolbarChild
+				     *) (g_list_nth(GTK_TOOLBAR(widget)->
+						    children,
+						    5)->data))->icon),
+				  pixmap, mask);
+	pixmap =
+	    gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
+					 &style->bg[GTK_STATE_NORMAL],
+					 (gchar **) xpm_split_view);
+	gtk_image_set_from_pixmap(GTK_IMAGE
+				  (((GtkToolbarChild
+				     *) (g_list_nth(GTK_TOOLBAR(widget)->
+						    children,
+						    6)->data))->icon),
+				  pixmap, mask);
+	pixmap =
+	    gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
+					 &style->bg[GTK_STATE_NORMAL],
+					 (gchar **) xpm_tree_view);
+	gtk_image_set_from_pixmap(GTK_IMAGE
+				  (((GtkToolbarChild
+				     *) (g_list_nth(GTK_TOOLBAR(widget)->
+						    children,
+						    7)->data))->icon),
+				  pixmap, mask);
+
+	switch (view_mode) {
+	case SINGLE_VIEW:
+		widget = glade_xml_get_widget(xml, "button4");
+		gtk_button_clicked(GTK_BUTTON(widget));
+		break;
+	case SPLIT_VIEW:
+		widget = glade_xml_get_widget(xml, "button5");
+		gtk_button_clicked(GTK_BUTTON(widget));
+		break;
+	case FULL_VIEW:
+		widget = glade_xml_get_widget(xml, "button6");
+		gtk_button_clicked(GTK_BUTTON(widget));
+		break;
+	}
+
+	txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+	tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
+					  "foreground", "red",
+					  "weight", PANGO_WEIGHT_BOLD,
+					  NULL);
+	tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
+					  /*"style", PANGO_STYLE_OBLIQUE, */
+					  NULL);
+
+	sprintf(title, "Linux Kernel v%s.%s.%s%s Configuration",
+		getenv("VERSION"), getenv("PATCHLEVEL"),
+		getenv("SUBLEVEL"), getenv("EXTRAVERSION"));
+	gtk_window_set_title(GTK_WINDOW(main_wnd), title);
+
+	gtk_widget_show(main_wnd);
+}
+
+void init_tree_model(void)
+{
+	gint i;
+
+	tree = tree2 = gtk_tree_store_new(COL_NUMBER,
+					  G_TYPE_STRING, G_TYPE_STRING,
+					  G_TYPE_STRING, G_TYPE_STRING,
+					  G_TYPE_STRING, G_TYPE_STRING,
+					  G_TYPE_POINTER, GDK_TYPE_COLOR,
+					  G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+					  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+					  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
+	model2 = GTK_TREE_MODEL(tree2);
+
+	for (parents[0] = NULL, i = 1; i < 256; i++)
+		parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
+
+	tree1 = gtk_tree_store_new(COL_NUMBER,
+				   G_TYPE_STRING, G_TYPE_STRING,
+				   G_TYPE_STRING, G_TYPE_STRING,
+				   G_TYPE_STRING, G_TYPE_STRING,
+				   G_TYPE_POINTER, GDK_TYPE_COLOR,
+				   G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+				   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+				   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
+	model1 = GTK_TREE_MODEL(tree1);
+}
+
+void init_left_tree(void)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
+	GtkCellRenderer *renderer;
+	GtkTreeSelection *sel;
+
+	gtk_tree_view_set_model(view, model1);
+	gtk_tree_view_set_headers_visible(view, TRUE);
+	gtk_tree_view_set_rules_hint(view, FALSE);
+
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "Options", renderer,
+						    "text", COL_OPTION,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+
+	sel = gtk_tree_view_get_selection(view);
+	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+	gtk_widget_realize(tree1_w);
+}
+
+static void renderer_edited(GtkCellRendererText * cell,
+			    const gchar * path_string,
+			    const gchar * new_text, gpointer user_data);
+static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
+			     gchar * arg1, gpointer user_data);
+
+void init_right_tree(void)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
+	GtkCellRenderer *renderer;
+	GtkTreeSelection *sel;
+	GtkTreeViewColumn *column;
+	gint i;
+
+	gtk_tree_view_set_model(view, model2);
+	gtk_tree_view_set_headers_visible(view, TRUE);
+	gtk_tree_view_set_rules_hint(view, FALSE);
+
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_append_column(view, column);
+	gtk_tree_view_column_set_title(column, "Options");
+
+	renderer = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "pixbuf", COL_PIXBUF,
+					    "visible", COL_PIXVIS, NULL);
+	renderer = gtk_cell_renderer_toggle_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "active", COL_BTNACT,
+					    "inconsistent", COL_BTNINC,
+					    "visible", COL_BTNVIS, NULL);
+	g_signal_connect(G_OBJECT(renderer), "toggled",
+			 G_CALLBACK(renderer_toggled), NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "text", COL_OPTION,
+					    "foreground-gdk",
+					    COL_COLOR, NULL);
+
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "Name", renderer,
+						    "text", COL_NAME,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "N", renderer,
+						    "text", COL_NO,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "M", renderer,
+						    "text", COL_MOD,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "Y", renderer,
+						    "text", COL_YES,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "Value", renderer,
+						    "text", COL_VALUE,
+						    "editable",
+						    COL_EDIT,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	g_signal_connect(G_OBJECT(renderer), "edited",
+			 G_CALLBACK(renderer_edited), NULL);
+
+	column = gtk_tree_view_get_column(view, COL_NAME);
+	gtk_tree_view_column_set_visible(column, show_name);
+	column = gtk_tree_view_get_column(view, COL_NO);
+	gtk_tree_view_column_set_visible(column, show_range);
+	column = gtk_tree_view_get_column(view, COL_MOD);
+	gtk_tree_view_column_set_visible(column, show_range);
+	column = gtk_tree_view_get_column(view, COL_YES);
+	gtk_tree_view_column_set_visible(column, show_range);
+	column = gtk_tree_view_get_column(view, COL_VALUE);
+	gtk_tree_view_column_set_visible(column, show_value);
+
+	if (resizeable) {
+		for (i = 0; i < COL_VALUE; i++) {
+			column = gtk_tree_view_get_column(view, i);
+			gtk_tree_view_column_set_resizable(column, TRUE);
+		}
+	}
+
+	sel = gtk_tree_view_get_selection(view);
+	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+}
+
+
+/* Utility Functions */
+
+
+static void text_insert_help(struct menu *menu)
+{
+	GtkTextBuffer *buffer;
+	GtkTextIter start, end;
+	const char *prompt = menu_get_prompt(menu);
+	gchar *name;
+	const char *help = nohelp_text;
+
+	if (!menu->sym)
+		help = "";
+	else if (menu->sym->help)
+		help = menu->sym->help;
+
+	if (menu->sym && menu->sym->name)
+		name = g_strdup_printf(menu->sym->name);
+	else
+		name = g_strdup("");
+
+	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+	gtk_text_buffer_get_bounds(buffer, &start, &end);
+	gtk_text_buffer_delete(buffer, &start, &end);
+	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
+					 NULL);
+	gtk_text_buffer_insert_at_cursor(buffer, " ", 1);
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1,
+					 NULL);
+	gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2,
+					 NULL);
+}
+
+
+static void text_insert_msg(const char *title, const char *message)
+{
+	GtkTextBuffer *buffer;
+	GtkTextIter start, end;
+	const char *msg = message;
+
+	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+	gtk_text_buffer_get_bounds(buffer, &start, &end);
+	gtk_text_buffer_delete(buffer, &start, &end);
+	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
+					 NULL);
+	gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
+					 NULL);
+}
+
+
+/* Main Windows Callbacks */
+
+void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
+gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
+				 gpointer user_data)
+{
+	GtkWidget *dialog, *label;
+	gint result;
+
+	if (config_changed == FALSE)
+		return FALSE;
+
+	dialog = gtk_dialog_new_with_buttons("Warning !",
+					     GTK_WINDOW(main_wnd),
+					     (GtkDialogFlags)
+					     (GTK_DIALOG_MODAL |
+					      GTK_DIALOG_DESTROY_WITH_PARENT),
+					     GTK_STOCK_OK,
+					     GTK_RESPONSE_YES,
+					     GTK_STOCK_NO,
+					     GTK_RESPONSE_NO,
+					     GTK_STOCK_CANCEL,
+					     GTK_RESPONSE_CANCEL, NULL);
+	gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+					GTK_RESPONSE_CANCEL);
+
+	label = gtk_label_new("\nSave configuration ?\n");
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+	gtk_widget_show(label);
+
+	result = gtk_dialog_run(GTK_DIALOG(dialog));
+	switch (result) {
+	case GTK_RESPONSE_YES:
+		on_save1_activate(NULL, NULL);
+		return FALSE;
+	case GTK_RESPONSE_NO:
+		return FALSE;
+	case GTK_RESPONSE_CANCEL:
+	case GTK_RESPONSE_DELETE_EVENT:
+	default:
+		gtk_widget_destroy(dialog);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+void on_window1_destroy(GtkObject * object, gpointer user_data)
+{
+	gtk_main_quit();
+}
+
+
+void
+on_window1_size_request(GtkWidget * widget,
+			GtkRequisition * requisition, gpointer user_data)
+{
+	static gint old_h = 0;
+	gint w, h;
+
+	if (widget->window == NULL)
+		gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+	else
+		gdk_window_get_size(widget->window, &w, &h);
+
+	if (h == old_h)
+		return;
+	old_h = h;
+
+	gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
+}
+
+
+/* Menu & Toolbar Callbacks */
+
+
+static void
+load_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+	const gchar *fn;
+
+	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+					     (user_data));
+
+	if (conf_read(fn))
+		text_insert_msg("Error", "Unable to load configuration !");
+	else
+		display_tree(&rootmenu);
+}
+
+void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *fs;
+
+	fs = gtk_file_selection_new("Load file...");
+	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+			 "clicked",
+			 G_CALLBACK(load_filename), (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->ok_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->cancel_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	gtk_widget_show(fs);
+}
+
+
+void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	if (conf_write(NULL))
+		text_insert_msg("Error", "Unable to save configuration !");
+
+	config_changed = FALSE;
+}
+
+
+static void
+store_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+	const gchar *fn;
+
+	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+					     (user_data));
+
+	if (conf_write(fn))
+		text_insert_msg("Error", "Unable to save configuration !");
+
+	gtk_widget_destroy(GTK_WIDGET(user_data));
+}
+
+void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *fs;
+
+	fs = gtk_file_selection_new("Save file as...");
+	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+			 "clicked",
+			 G_CALLBACK(store_filename), (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->ok_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->cancel_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	gtk_widget_show(fs);
+}
+
+
+void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	if (!on_window1_delete_event(NULL, NULL, NULL))
+		gtk_widget_destroy(GTK_WIDGET(main_wnd));
+}
+
+
+void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkTreeViewColumn *col;
+
+	show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_name);
+}
+
+
+void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkTreeViewColumn *col;
+
+	show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_range);
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_range);
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_range);
+
+}
+
+
+void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkTreeViewColumn *col;
+
+	show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_value);
+}
+
+
+void
+on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
+
+	gtk_tree_store_clear(tree2);
+	display_tree(&rootmenu);	// instead of update_tree for speed reasons
+}
+
+
+void
+on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	update_tree(&rootmenu, NULL);
+}
+
+
+void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *dialog;
+	const gchar *intro_text =
+	    "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
+	    "for Linux.\n"
+	    "For each option, a blank box indicates the feature is disabled, a\n"
+	    "check indicates it is enabled, and a dot indicates that it is to\n"
+	    "be compiled as a module.  Clicking on the box will cycle through the three states.\n"
+	    "\n"
+	    "If you do not see an option (e.g., a device driver) that you\n"
+	    "believe should be present, try turning on Show All Options\n"
+	    "under the Options menu.\n"
+	    "Although there is no cross reference yet to help you figure out\n"
+	    "what other options must be enabled to support the option you\n"
+	    "are interested in, you can still view the help of a grayed-out\n"
+	    "option.\n"
+	    "\n"
+	    "Toggling Show Debug Info under the Options menu will show \n"
+	    "the dependencies, which you can then match by examining other options.";
+
+	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					GTK_MESSAGE_INFO,
+					GTK_BUTTONS_CLOSE, intro_text);
+	g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+				 G_CALLBACK(gtk_widget_destroy),
+				 GTK_OBJECT(dialog));
+	gtk_widget_show_all(dialog);
+}
+
+
+void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *dialog;
+	const gchar *about_text =
+	    "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
+	    "Based on the source code from Roman Zippel.\n";
+
+	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					GTK_MESSAGE_INFO,
+					GTK_BUTTONS_CLOSE, about_text);
+	g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+				 G_CALLBACK(gtk_widget_destroy),
+				 GTK_OBJECT(dialog));
+	gtk_widget_show_all(dialog);
+}
+
+
+void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *dialog;
+	const gchar *license_text =
+	    "gkc is released under the terms of the GNU GPL v2.\n"
+	    "For more information, please see the source code or\n"
+	    "visit http://www.fsf.org/licenses/licenses.html\n";
+
+	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					GTK_MESSAGE_INFO,
+					GTK_BUTTONS_CLOSE, license_text);
+	g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+				 G_CALLBACK(gtk_widget_destroy),
+				 GTK_OBJECT(dialog));
+	gtk_widget_show_all(dialog);
+}
+
+
+void on_back_pressed(GtkButton * button, gpointer user_data)
+{
+	enum prop_type type;
+
+	current = current->parent;
+	type = current->prompt ? current->prompt->type : P_UNKNOWN;
+	if ((type != P_ROOTMENU) && (type != P_MENU))
+		current = current->parent;
+	display_tree_part();
+
+	if (current == &rootmenu)
+		gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_load_pressed(GtkButton * button, gpointer user_data)
+{
+	on_load1_activate(NULL, user_data);
+}
+
+
+void on_save_pressed(GtkButton * button, gpointer user_data)
+{
+	on_save1_activate(NULL, user_data);
+}
+
+
+void on_single_clicked(GtkButton * button, gpointer user_data)
+{
+	view_mode = SINGLE_VIEW;
+	gtk_paned_set_position(GTK_PANED(hpaned), 0);
+	gtk_widget_hide(tree1_w);
+	if (tree2)
+		gtk_tree_store_clear(tree2);
+	current = &rootmenu;
+	display_tree_part();
+}
+
+
+void on_split_clicked(GtkButton * button, gpointer user_data)
+{
+	gint w, h;
+	view_mode = SPLIT_VIEW;
+	gtk_widget_show(tree1_w);
+	gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+	gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
+	if (tree2)
+		gtk_tree_store_clear(tree2);
+	display_list();
+}
+
+
+void on_full_clicked(GtkButton * button, gpointer user_data)
+{
+	view_mode = FULL_VIEW;
+	gtk_paned_set_position(GTK_PANED(hpaned), 0);
+	gtk_widget_hide(tree1_w);
+	if (tree2)
+		gtk_tree_store_clear(tree2);
+	display_tree(&rootmenu);
+	gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_collapse_pressed(GtkButton * button, gpointer user_data)
+{
+	gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+void on_expand_pressed(GtkButton * button, gpointer user_data)
+{
+	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+/* CTree Callbacks */
+
+/* Change hex/int/string value in the cell */
+static void renderer_edited(GtkCellRendererText * cell,
+			    const gchar * path_string,
+			    const gchar * new_text, gpointer user_data)
+{
+	GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
+	GtkTreeIter iter;
+	const char *old_def, *new_def;
+	struct menu *menu;
+	struct symbol *sym;
+
+	if (!gtk_tree_model_get_iter(model2, &iter, path))
+		return;
+
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+	sym = menu->sym;
+
+	gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
+	new_def = new_text;
+
+	sym_set_string_value(sym, new_def);
+
+	config_changed = TRUE;
+	update_tree(&rootmenu, NULL);
+
+	gtk_tree_path_free(path);
+}
+
+/* Change the value of a symbol and update the tree */
+static void change_sym_value(struct menu *menu, gint col)
+{
+	struct symbol *sym = menu->sym;
+	int stype;
+	tristate oldval, newval;
+
+	newval = no;
+	switch (col) {
+	case COL_OPTION:
+		return;
+	case COL_NAME:
+		return;
+	case COL_NO:
+		newval = no;
+		break;
+	case COL_MOD:
+		newval = mod;
+		break;
+	case COL_YES:
+		newval = yes;
+		break;
+	default:
+		break;
+	}
+
+	if (!sym)
+		return;
+
+	stype = sym_get_type(sym);
+	switch (stype) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		if (col == COL_VALUE)
+			return;
+		else {
+			oldval = sym_get_tristate_value(sym);
+			if (!sym_tristate_within_range(sym, newval))
+				newval = yes;
+			sym_set_tristate_value(sym, newval);
+			config_changed = TRUE;
+			if (view_mode == FULL_VIEW)
+				update_tree(&rootmenu, NULL);
+			else
+				//display_tree_part();  //fixme: keep exp/coll
+				update_tree(current, NULL);
+		}
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		break;
+	}
+}
+
+static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
+			     gchar * path_string, gpointer user_data)
+{
+	GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
+	GtkTreeIter iter;
+	gint col;
+	struct menu *menu;
+	const int next_col[3] = { COL_NO, COL_MOD, COL_YES };
+
+	if (!gtk_tree_model_get_iter(model2, &iter, path))
+		return;
+
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+	gtk_tree_model_get(model2, &iter, COL_BTNINC, &col, -1);
+	if (col)
+		col = COL_MOD;
+	else {
+		gtk_tree_model_get(model2, &iter, COL_BTNACT, &col, -1);
+		col = col ? COL_YES : COL_NO;
+	}
+
+	change_sym_value(menu, next_col[((col - COL_NO) + 1) % 3]);
+
+	gtk_tree_path_free(path);
+}
+
+static gint column2index(GtkTreeViewColumn * column)
+{
+	gint i;
+
+	for (i = 0; i < COL_NUMBER; i++) {
+		GtkTreeViewColumn *col;
+
+		col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
+		if (col == column)
+			return i;
+	}
+
+	return -1;
+}
+
+
+//#define GTK_BUG_FIXED // GTK+ 2.1.4 mini
+
+/* User click: update choice (full) or goes down (single) */
+gboolean
+on_treeview2_button_press_event(GtkWidget * widget,
+				GdkEventButton * event, gpointer user_data)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(widget);
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	struct menu *menu;
+	gint col;
+
+#ifdef GTK_BUG_FIXED
+	gint tx = (gint) event->x;
+	gint ty = (gint) event->y;
+	gint cx, cy;
+
+	gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+				      &cy);
+#else
+	gtk_tree_view_get_cursor(view, &path, &column);
+#endif
+	if (path == NULL)
+		return FALSE;
+
+	gtk_tree_model_get_iter(model2, &iter, path);
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+	col = column2index(column);
+	if ((col == COL_OPTION) && (event->type == GDK_2BUTTON_PRESS) &&
+	    (view_mode != FULL_VIEW) && menu->list) {
+		enum prop_type type;
+		type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+		if ((type != P_MENU) && (type != P_ROOTMENU))
+			return FALSE;
+		current = menu;
+		display_tree_part();
+		gtk_widget_set_sensitive(back_btn, TRUE);
+	} else
+		change_sym_value(menu, col);
+
+	return FALSE;
+}
+
+/* Key pressed: update choice */
+gboolean
+on_treeview2_key_press_event(GtkWidget * widget,
+			     GdkEventKey * event, gpointer user_data)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(widget);
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	struct menu *menu;
+	gint col;
+
+	gtk_tree_view_get_cursor(view, &path, &column);
+	if (path == NULL) {
+		//g_warning("key_press_event: path is NULL !\n");
+		return FALSE;
+	}
+
+	if (event->keyval == GDK_space) {
+		if (gtk_tree_view_row_expanded(view, path))
+			gtk_tree_view_collapse_row(view, path);
+		else
+			gtk_tree_view_expand_row(view, path, FALSE);
+		return FALSE;
+	}
+	if (widget == tree1_w)
+		return FALSE;
+
+	gtk_tree_model_get_iter(model2, &iter, path);
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+	if (!strcasecmp(event->string, "n"))
+		col = COL_NO;
+	else if (!strcasecmp(event->string, "m"))
+		col = COL_MOD;
+	else if (!strcasecmp(event->string, "y"))
+		col = COL_YES;
+	else if (!strcasecmp(event->string, "e"))
+		col = COL_VALUE;
+	else
+		col = 0;
+
+	change_sym_value(menu, col);
+
+	return FALSE;
+}
+
+
+/* Row selection changed: update help */
+void
+on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
+{
+	GtkTreeSelection *selection;
+	GtkTreeIter iter;
+	struct menu *menu;
+
+	selection = gtk_tree_view_get_selection(treeview);
+	if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
+		gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+		text_insert_help(menu);
+	}
+}
+
+
+/* User click: display sub-tree in the right frame. */
+gboolean
+on_treeview1_button_press_event(GtkWidget * widget,
+				GdkEventButton * event, gpointer user_data)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(widget);
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	struct menu *menu;
+
+	gint tx = (gint) event->x;
+	gint ty = (gint) event->y;
+	gint cx, cy;
+
+	gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+				      &cy);
+	if (path == NULL)
+		return FALSE;
+
+	gtk_tree_model_get_iter(model1, &iter, path);
+	gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
+
+	current = menu;
+	display_tree_part();
+
+	return FALSE;
+}
+
+
+/* Conf management */
+
+
+/* Fill a row of strings */
+static gchar **fill_row(struct menu *menu)
+{
+	static gchar **row;
+	struct symbol *sym = menu->sym;
+	const char *def;
+	int stype;
+	tristate val;
+	enum prop_type type;
+
+	//g_strfreev(row); //to fix...
+	row = (gchar **) g_malloc0(COL_NUMBER * sizeof(gchar *));
+	row[COL_OPTION] =
+	    g_strdup_printf("%s %s", menu_get_prompt(menu),
+			    sym ? (sym->
+				   flags & SYMBOL_NEW ? "(NEW)" : "") :
+			    "");
+
+	if (show_all && !menu_is_visible(menu))
+		row[COL_COLOR] = g_strdup("DarkGray");
+	else
+		row[COL_COLOR] = g_strdup("Black");
+
+	type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	switch (type) {
+	case P_MENU:
+	case P_ROOTMENU:
+		row[COL_PIXBUF] =
+		    (gchar *) (view_mode !=
+			       FULL_VIEW ? xpm_menu : xpm_void);
+		row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+		break;
+	case P_COMMENT:
+		row[COL_PIXBUF] = (gchar *) xpm_void;
+		row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+		break;
+	default:
+		row[COL_PIXBUF] = (gchar *) xpm_void;
+		row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
+		break;
+	}
+
+	if (!sym)
+		return row;
+	row[COL_NAME] = g_strdup(sym->name);
+
+	sym_calc_value(sym);
+	sym->flags &= ~SYMBOL_CHANGED;
+
+	if (sym_is_choice(sym)) {	// parse childs for getting final value
+		struct menu *child;
+		struct symbol *def_sym = sym_get_choice_value(sym);
+		struct menu *def_menu = NULL;
+
+		for (child = menu->list; child; child = child->next) {
+			if (menu_is_visible(child)
+			    && child->sym == def_sym)
+				def_menu = child;
+		}
+
+		if (def_menu)
+			row[COL_VALUE] =
+			    g_strdup(menu_get_prompt(def_menu));
+	}
+
+	stype = sym_get_type(sym);
+	switch (stype) {
+	case S_BOOLEAN:
+		if (sym_is_choice(sym))
+			break;
+	case S_TRISTATE:
+		val = sym_get_tristate_value(sym);
+		switch (val) {
+		case no:
+			row[COL_NO] = g_strdup("N");
+			row[COL_VALUE] = g_strdup("N");
+			row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
+			row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+			break;
+		case mod:
+			row[COL_MOD] = g_strdup("M");
+			row[COL_VALUE] = g_strdup("M");
+			row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
+			break;
+		case yes:
+			row[COL_YES] = g_strdup("Y");
+			row[COL_VALUE] = g_strdup("Y");
+			row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
+			row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+			break;
+		}
+
+		if (val != no && sym_tristate_within_range(sym, no))
+			row[COL_NO] = g_strdup("_");
+		if (val != mod && sym_tristate_within_range(sym, mod))
+			row[COL_MOD] = g_strdup("_");
+		if (val != yes && sym_tristate_within_range(sym, yes))
+			row[COL_YES] = g_strdup("_");
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		def = sym_get_string_value(sym);
+		row[COL_VALUE] = g_strdup(def);
+		row[COL_EDIT] = GINT_TO_POINTER(TRUE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+		break;
+	}
+
+	return row;
+}
+
+
+/* Set the node content with a row of strings */
+static void set_node2(GtkTreeIter * node, struct menu *menu, gchar ** row)
+{
+	GdkColor color;
+	gboolean success;
+	GdkPixbuf *pix;
+
+	pix = gdk_pixbuf_new_from_xpm_data((const char **)
+					   row[COL_PIXBUF]);
+
+	gdk_color_parse(row[COL_COLOR], &color);
+	gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
+				  FALSE, FALSE, &success);
+
+	gtk_tree_store_set(tree, node,
+			   COL_OPTION, row[COL_OPTION],
+			   COL_NAME, row[COL_NAME],
+			   COL_NO, row[COL_NO],
+			   COL_MOD, row[COL_MOD],
+			   COL_YES, row[COL_YES],
+			   COL_VALUE, row[COL_VALUE],
+			   COL_MENU, (gpointer) menu,
+			   COL_COLOR, &color,
+			   COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
+			   COL_PIXBUF, pix,
+			   COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
+			   COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
+			   COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
+			   COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
+			   -1);
+
+	g_object_unref(pix);
+	g_strfreev(row);
+}
+
+
+/* Add a node to the tree */
+static void place_node2(struct menu *menu, char **row)
+{
+	GtkTreeIter *parent = parents[indent - 1];
+	GtkTreeIter *node = parents[indent];
+
+	gtk_tree_store_append(tree, node, parent);
+	set_node2(node, menu, row);
+}
+
+
+/* Find a node in the GTK+ tree */
+static GtkTreeIter found;
+
+/*
+ * Find a menu in the GtkTree starting at parent.
+ */
+GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
+				    struct menu *tofind)
+{
+	GtkTreeIter iter;
+	GtkTreeIter *child = &iter;
+	gboolean valid;
+	GtkTreeIter *ret;
+
+	valid = gtk_tree_model_iter_children(model2, child, parent);
+	while (valid) {
+		struct menu *menu;
+
+		gtk_tree_model_get(model2, child, 6, &menu, -1);
+
+		if (menu == tofind) {
+			memcpy(&found, child, sizeof(GtkTreeIter));
+			return &found;
+		}
+
+		ret = gtktree_iter_find_node(child, tofind);
+		if (ret)
+			return ret;
+
+		valid = gtk_tree_model_iter_next(model2, child);
+	}
+
+	return NULL;
+}
+
+
+/*
+ * Update the tree by adding/removing entries
+ * Does not change other nodes
+ */
+static void update_tree(struct menu *src, GtkTreeIter * dst)
+{
+	struct menu *child1;
+	GtkTreeIter iter, tmp;
+	GtkTreeIter *child2 = &iter;
+	gboolean valid;
+	GtkTreeIter *sibling;
+	struct symbol *sym;
+	struct property *prop;
+	struct menu *menu1, *menu2;
+
+	if (src == &rootmenu)
+		indent = 1;
+
+	valid = gtk_tree_model_iter_children(model2, child2, dst);
+	for (child1 = src->list; child1; child1 = child1->next) {
+
+		prop = child1->prompt;
+		sym = child1->sym;
+
+	      reparse:
+		menu1 = child1;
+		if (valid)
+			gtk_tree_model_get(model2, child2, COL_MENU,
+					   &menu2, -1);
+		else
+			menu2 = NULL;	// force adding of a first child
+
+#ifdef DEBUG
+		printf("%*c%s | %s\n", indent, ' ',
+		       menu1 ? menu_get_prompt(menu1) : "nil",
+		       menu2 ? menu_get_prompt(menu2) : "nil");
+#endif
+
+		if (!menu_is_visible(child1) && !show_all) {	// remove node
+			if (gtktree_iter_find_node(dst, menu1) != NULL) {
+				memcpy(&tmp, child2, sizeof(GtkTreeIter));
+				valid = gtk_tree_model_iter_next(model2,
+								 child2);
+				gtk_tree_store_remove(tree2, &tmp);
+				if (!valid)
+					return;	// next parent 
+				else
+					goto reparse;	// next child
+			} else
+				continue;
+		}
+
+		if (menu1 != menu2) {
+			if (gtktree_iter_find_node(dst, menu1) == NULL) {	// add node
+				if (!valid && !menu2)
+					sibling = NULL;
+				else
+					sibling = child2;
+				gtk_tree_store_insert_before(tree2,
+							     child2,
+							     dst, sibling);
+				set_node2(child2, menu1, fill_row(menu1));
+				if (menu2 == NULL)
+					valid = TRUE;
+			} else {	// remove node
+				memcpy(&tmp, child2, sizeof(GtkTreeIter));
+				valid = gtk_tree_model_iter_next(model2,
+								 child2);
+				gtk_tree_store_remove(tree2, &tmp);
+				if (!valid)
+					return;	// next parent 
+				else
+					goto reparse;	// next child
+			}
+		} else if (sym && (sym->flags & SYMBOL_CHANGED)) {
+			set_node2(child2, menu1, fill_row(menu1));
+		}
+
+		indent++;
+		update_tree(child1, child2);
+		indent--;
+
+		valid = gtk_tree_model_iter_next(model2, child2);
+	}
+}
+
+
+/* Display the whole tree (single/split/full view) */
+static void display_tree(struct menu *menu)
+{
+	struct symbol *sym;
+	struct property *prop;
+	struct menu *child;
+	enum prop_type ptype;
+
+	if (menu == &rootmenu) {
+		indent = 1;
+		current = &rootmenu;
+	}
+
+	for (child = menu->list; child; child = child->next) {
+		prop = child->prompt;
+		sym = child->sym;
+		ptype = prop ? prop->type : P_UNKNOWN;
+
+		if (sym)
+			sym->flags &= ~SYMBOL_CHANGED;
+
+		if ((view_mode == SPLIT_VIEW) && (ptype != P_ROOTMENU) &&
+		    (tree == tree1))
+			continue;
+
+		if ((view_mode == SPLIT_VIEW) && (ptype == P_ROOTMENU) &&
+		    (tree == tree2))
+			continue;
+
+		if (menu_is_visible(child) || show_all)
+			place_node2(child, fill_row(child));
+#ifdef DEBUG
+		printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
+		dbg_print_ptype(ptype);
+		printf(" | ");
+		if (sym) {
+			dbg_print_stype(sym->type);
+			printf(" | ");
+			dbg_print_flags(sym->flags);
+			printf("\n");
+		} else
+			printf("\n");
+#endif
+		if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
+		    && (tree == tree2))
+			continue;
+
+		if (((menu != &rootmenu) && (ptype != P_ROOTMENU)) ||
+		    (view_mode == FULL_VIEW)
+		    || (view_mode == SPLIT_VIEW)) {
+			indent++;
+			display_tree(child);
+			indent--;
+		}
+	}
+}
+
+/* Display a part of the tree starting at current node (single/split view) */
+static void display_tree_part(void)
+{
+	if (tree2)
+		gtk_tree_store_clear(tree2);
+	display_tree(current);
+	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+/* Display the list in the left frame (split view) */
+static void display_list(void)
+{
+	tree = tree1;
+	display_tree(&rootmenu);
+	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
+	tree = tree2;
+}
+
+static void fixup_rootmenu(struct menu *menu)
+{
+	struct menu *child;
+
+	if (!menu->prompt || menu->prompt->type != P_MENU)
+		return;
+	menu->prompt->type = P_ROOTMENU;
+	for (child = menu->list; child; child = child->next)
+		fixup_rootmenu(child);
+}
+
+
+/* Main */
+
+
+int main(int ac, char *av[])
+{
+	const char *name;
+	gchar *cur_dir, *exe_path;
+	gchar *glade_file;
+
+#ifndef LKC_DIRECT_LINK
+	kconfig_load();
+#endif
+
+	/* GTK stuffs */
+	gtk_set_locale();
+	gtk_init(&ac, &av);
+	glade_init();
+
+	//add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
+	//add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
+
+	/* Determine GUI path */
+	cur_dir = g_get_current_dir();
+	exe_path = g_strdup(av[0]);
+	exe_path[0] = '/';
+	glade_file = g_strconcat(cur_dir, exe_path, ".glade", NULL);
+	g_free(cur_dir);
+	g_free(exe_path);
+
+	/* Load the interface and connect signals */
+	init_main_window(glade_file);
+	init_tree_model();
+	init_left_tree();
+	init_right_tree();
+
+	/* Conf stuffs */
+	if (ac > 1 && av[1][0] == '-') {
+		switch (av[1][1]) {
+		case 'a':
+			//showAll = 1;
+			break;
+		case 'h':
+		case '?':
+			printf("%s <config>\n", av[0]);
+			exit(0);
+		}
+		name = av[2];
+	} else
+		name = av[1];
+
+	conf_parse(name);
+	fixup_rootmenu(&rootmenu);
+	conf_read(NULL);
+
+	switch (view_mode) {
+	case SINGLE_VIEW:
+		display_tree_part();
+		break;
+	case SPLIT_VIEW:
+		display_list();
+		break;
+	case FULL_VIEW:
+		display_tree(&rootmenu);
+		break;
+	}
+
+	gtk_main();
+
+	return 0;
+}
diff -Nru a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/kconfig/gconf.glade	Sat Mar 15 09:25:55 2003
@@ -0,0 +1,543 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="window1">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Gtk Kernel Configurator</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="default_width">640</property>
+  <property name="default_height">480</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <signal name="destroy" handler="on_window1_destroy" object="window1"/>
+  <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
+  <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
+
+  <child>
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child>
+	<widget class="GtkMenuBar" id="menubar1">
+	  <property name="visible">True</property>
+
+	  <child>
+	    <widget class="GtkMenuItem" id="file1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">_File</property>
+	      <property name="use_underline">True</property>
+
+	      <child>
+		<widget class="GtkMenu" id="file1_menu">
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="load1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Load a config file</property>
+		      <property name="label" translatable="yes">_Load</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_load1_activate"/>
+		      <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image27">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-open</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="save1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Save the config in .config</property>
+		      <property name="label" translatable="yes">_Save</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_save1_activate"/>
+		      <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image28">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-save</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="save_as1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Save the config in a file</property>
+		      <property name="label" translatable="yes">Save _as</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_save_as1_activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image29">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-save-as</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkMenuItem" id="separator1">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="quit1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_Quit</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_quit1_activate"/>
+		      <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image30">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-quit</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkMenuItem" id="options1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">_Options</property>
+	      <property name="use_underline">True</property>
+
+	      <child>
+		<widget class="GtkMenu" id="options1_menu">
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_name1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show name</property>
+		      <property name="label" translatable="yes">Show _name</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_name1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_range1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
+		      <property name="label" translatable="yes">Show _range</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_range1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_data1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show value of the option</property>
+		      <property name="label" translatable="yes">Show _data</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_data1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkMenuItem" id="separator2">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_all_options1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show all options</property>
+		      <property name="label" translatable="yes">Show all _options</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_all_options1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_debug_info1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show masked options</property>
+		      <property name="label" translatable="yes">Show _debug info</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_debug_info1_activate"/>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkMenuItem" id="help1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">_Help</property>
+	      <property name="use_underline">True</property>
+
+	      <child>
+		<widget class="GtkMenu" id="help1_menu">
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="introduction1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_Introduction</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+		      <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image31">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-dialog-question</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="about1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_About</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+		      <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image32">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-properties</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="license1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_License</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image33">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-justify-fill</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHandleBox" id="handlebox1">
+	  <property name="visible">True</property>
+	  <property name="shadow_type">GTK_SHADOW_OUT</property>
+	  <property name="handle_position">GTK_POS_LEFT</property>
+	  <property name="snap_edge">GTK_POS_TOP</property>
+
+	  <child>
+	    <widget class="GtkToolbar" id="toolbar1">
+	      <property name="visible">True</property>
+	      <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+	      <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
+	      <property name="tooltips">True</property>
+
+	      <child>
+		<widget class="button" id="button1">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
+		  <property name="label" translatable="yes">Back</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_pixmap">gtk-undo</property>
+		  <signal name="pressed" handler="on_back_pressed"/>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="GtkVSeparator" id="vseparator1">
+		  <property name="visible">True</property>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="button" id="button2">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Load a config file</property>
+		  <property name="label" translatable="yes">Load</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_pixmap">gtk-open</property>
+		  <signal name="pressed" handler="on_load_pressed"/>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="button" id="button3">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Save a config file</property>
+		  <property name="label" translatable="yes">Save</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_pixmap">gtk-save</property>
+		  <signal name="pressed" handler="on_save_pressed"/>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="GtkVSeparator" id="vseparator2">
+		  <property name="visible">True</property>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="button" id="button4">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Single view</property>
+		  <property name="label" translatable="yes">Single</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_pixmap">gtk-missing-image</property>
+		  <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="button" id="button5">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Split view</property>
+		  <property name="label" translatable="yes">Split</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_pixmap">gtk-missing-image</property>
+		  <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="button" id="button6">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Full view</property>
+		  <property name="label" translatable="yes">Full</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_pixmap">gtk-missing-image</property>
+		  <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="GtkVSeparator" id="vseparator3">
+		  <property name="visible">True</property>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="button" id="button7">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
+		  <property name="label" translatable="yes">Collapse</property>
+		  <property name="use_underline">True</property>
+		  <signal name="pressed" handler="on_collapse_pressed"/>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="button" id="button8">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
+		  <property name="label" translatable="yes">Expand</property>
+		  <property name="use_underline">True</property>
+		  <signal name="pressed" handler="on_expand_pressed"/>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHPaned" id="hpaned1">
+	  <property name="width_request">1</property>
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="position">0</property>
+
+	  <child>
+	    <widget class="GtkScrolledWindow" id="scrolledwindow1">
+	      <property name="visible">True</property>
+	      <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+	      <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+	      <property name="shadow_type">GTK_SHADOW_IN</property>
+	      <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+	      <child>
+		<widget class="GtkTreeView" id="treeview1">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="headers_visible">True</property>
+		  <property name="rules_hint">False</property>
+		  <property name="reorderable">False</property>
+		  <property name="enable_search">True</property>
+		  <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
+		  <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
+		  <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
+		</widget>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="shrink">True</property>
+	      <property name="resize">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkVPaned" id="vpaned1">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="position">0</property>
+
+	      <child>
+		<widget class="GtkScrolledWindow" id="scrolledwindow2">
+		  <property name="visible">True</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="shadow_type">GTK_SHADOW_IN</property>
+		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+		  <child>
+		    <widget class="GtkTreeView" id="treeview2">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="has_focus">True</property>
+		      <property name="headers_visible">True</property>
+		      <property name="rules_hint">False</property>
+		      <property name="reorderable">False</property>
+		      <property name="enable_search">True</property>
+		      <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
+		      <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
+		      <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="shrink">True</property>
+		  <property name="resize">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkScrolledWindow" id="scrolledwindow3">
+		  <property name="visible">True</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="shadow_type">GTK_SHADOW_IN</property>
+		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+		  <child>
+		    <widget class="GtkTextView" id="textview3">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="editable">False</property>
+		      <property name="justification">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap_mode">GTK_WRAP_WORD</property>
+		      <property name="cursor_visible">True</property>
+		      <property name="pixels_above_lines">0</property>
+		      <property name="pixels_below_lines">0</property>
+		      <property name="pixels_inside_wrap">0</property>
+		      <property name="left_margin">0</property>
+		      <property name="right_margin">0</property>
+		      <property name="indent">0</property>
+		      <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="shrink">True</property>
+		  <property name="resize">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="shrink">True</property>
+	      <property name="resize">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff -Nru a/scripts/kconfig/images.c b/scripts/kconfig/images.c
--- a/scripts/kconfig/images.c	Tue Oct 29 17:16:44 2002
+++ b/scripts/kconfig/images.c	Sat Mar 15 09:25:55 2003
@@ -290,3 +290,37 @@
 " .......... ",
 " .......... ",
 "            "};
+
+static const char *xpm_menuback[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+" .......... ",
+" .        . ",
+" .     .. . ",
+" .   .... . ",
+" . ...... . ",
+" . ...... . ",
+" .   .... . ",
+" .     .. . ",
+" .        . ",
+" .......... ",
+"            "};
+
+static const char *xpm_void[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            "};
diff -Nru a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped
--- a/scripts/kconfig/lex.zconf.c_shipped	Mon Dec  9 12:30:46 2002
+++ b/scripts/kconfig/lex.zconf.c_shipped	Sat Mar 15 09:25:55 2003
@@ -357,18 +357,18 @@
     },
 
     {
-       11,   38,   38,   39,   40,   41,   38,   42,   41,   43,
-       44,   45,   46,   46,   47,   48,   46,   46,   46,   46,
-       46,   46,   46,   46,   49,   46,   46,   46,   50,   46,
-       46,   46,   46,   46,   46,   46,   51
+       11,   38,   38,   39,   40,   41,   42,   43,   41,   44,
+       45,   46,   47,   47,   48,   49,   47,   47,   47,   47,
+       47,   47,   47,   47,   50,   47,   47,   47,   51,   47,
+       47,   47,   47,   47,   47,   47,   52
 
     },
 
     {
-       11,   38,   38,   39,   40,   41,   38,   42,   41,   43,
-       44,   45,   46,   46,   47,   48,   46,   46,   46,   46,
-       46,   46,   46,   46,   49,   46,   46,   46,   50,   46,
-       46,   46,   46,   46,   46,   46,   51
+       11,   38,   38,   39,   40,   41,   42,   43,   41,   44,
+       45,   46,   47,   47,   48,   49,   47,   47,   47,   47,
+       47,   47,   47,   47,   50,   47,   47,   47,   51,   47,
+       47,   47,   47,   47,   47,   47,   52
     },
 
     {
@@ -387,7 +387,7 @@
     },
 
     {
-       11,  -13,   52,   53,  -13,  -13,   54,  -13,  -13,  -13,
+       11,  -13,   53,   54,  -13,  -13,   55,  -13,  -13,  -13,
       -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
       -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
       -13,  -13,  -13,  -13,  -13,  -13,  -13
@@ -402,10 +402,10 @@
     },
 
     {
-       11,   55,   55,   56,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55
+       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56
     },
 
     {
@@ -425,109 +425,109 @@
 
     {
        11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,   57,  -18,  -18,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -18
+      -18,  -18,  -18,   58,  -18,  -18,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -18
     },
 
     {
        11,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,   57,  -19,  -19,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   58,   57,
-       57,   57,   57,   57,   57,   57,  -19
+      -19,  -19,  -19,   58,  -19,  -19,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   59,   58,
+       58,   58,   58,   58,   58,   58,  -19
 
     },
 
     {
        11,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,   57,  -20,  -20,   57,   57,   57,   57,
-       57,   57,   57,   59,   57,   57,   57,   57,   60,   57,
-       57,   57,   57,   57,   57,   57,  -20
+      -20,  -20,  -20,   58,  -20,  -20,   58,   58,   58,   58,
+       58,   58,   58,   60,   58,   58,   58,   58,   61,   58,
+       58,   58,   58,   58,   58,   58,  -20
     },
 
     {
        11,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,   57,  -21,  -21,   57,   57,   57,   57,
-       61,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -21
+      -21,  -21,  -21,   58,  -21,  -21,   58,   58,   58,   58,
+       62,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -21
     },
 
     {
        11,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,   57,  -22,  -22,   57,   57,   57,   57,
+      -22,  -22,  -22,   58,  -22,  -22,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   62,   57,   57,
-       57,   57,   57,   57,   57,   57,  -22
+       58,   58,   58,   58,   58,   58,   58,   63,   58,   58,
+       58,   58,   58,   58,   58,   58,  -22
     },
 
     {
        11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,   57,  -23,  -23,   57,   57,   57,   57,
-       63,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -23
+      -23,  -23,  -23,   58,  -23,  -23,   58,   58,   58,   58,
+       64,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -23
     },
 
     {
        11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,   57,  -24,  -24,   57,   57,   57,   57,
-       57,   64,   57,   57,   57,   57,   57,   65,   57,   57,
-       57,   57,   57,   57,   57,   57,  -24
+      -24,  -24,  -24,   58,  -24,  -24,   58,   58,   58,   58,
+       58,   65,   58,   58,   58,   58,   58,   66,   58,   58,
+       58,   58,   58,   58,   58,   58,  -24
 
     },
 
     {
        11,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,   57,  -25,  -25,   66,   57,   57,   57,
-       67,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -25
+      -25,  -25,  -25,   58,  -25,  -25,   67,   58,   58,   58,
+       68,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -25
     },
 
     {
        11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,   57,  -26,  -26,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   68,
-       57,   57,   57,   57,   57,   57,  -26
+      -26,  -26,  -26,   58,  -26,  -26,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   69,
+       58,   58,   58,   58,   58,   58,  -26
     },
 
     {
        11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,   57,  -27,  -27,   57,   57,   57,   57,
+      -27,  -27,  -27,   58,  -27,  -27,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   69,   57,   57,   57,   57,  -27
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   70,   58,   58,   58,   58,  -27
     },
 
     {
        11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,   57,  -28,  -28,   57,   57,   57,   57,
-       70,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -28
+      -28,  -28,  -28,   58,  -28,  -28,   58,   58,   58,   58,
+       71,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -28
     },
 
     {
        11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,   57,  -29,  -29,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   71,   57,
-       57,   57,   57,   72,   57,   57,  -29
+      -29,  -29,  -29,   58,  -29,  -29,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   72,   58,
+       58,   58,   58,   73,   58,   58,  -29
 
     },
 
     {
        11,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,   57,  -30,  -30,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   73,   57,   57,   57,   57,  -30
+      -30,  -30,  -30,   58,  -30,  -30,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   74,   58,   58,   58,   58,  -30
     },
 
     {
-       11,   74,   74,  -31,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74
+       11,   75,   75,  -31,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75
     },
 
     {
-       11,  -32,   75,   76,  -32,  -32,  -32,  -32,  -32,  -32,
+       11,  -32,   76,   77,  -32,  -32,  -32,  -32,  -32,  -32,
       -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
 
       -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
@@ -535,17 +535,17 @@
     },
 
     {
-       11,   77,  -33,  -33,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77
+       11,   78,  -33,  -33,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78
     },
 
     {
-       11,   78,   78,   79,   78,  -34,   78,   78,  -34,   78,
-       78,   78,   78,   78,   78,  -34,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78
+       11,   79,   79,   80,   79,  -34,   79,   79,  -34,   79,
+       79,   79,   79,   79,   79,  -34,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79
 
     },
 
@@ -564,11 +564,11 @@
     },
 
     {
-       11,   80,   80,   81,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       11,   81,   81,   82,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
 
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81
     },
 
     {
@@ -588,7 +588,7 @@
 
     {
        11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,   82,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,   83,  -40,  -40,  -40,  -40,  -40,
       -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
       -40,  -40,  -40,  -40,  -40,  -40,  -40
     },
@@ -601,15 +601,15 @@
     },
 
     {
-       11,  -42,  -42,  -42,  -42,  -42,  -42,   83,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+       11,   84,   84,  -42,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
 
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84
     },
 
     {
-       11,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+       11,  -43,  -43,  -43,  -43,  -43,  -43,   85,  -43,  -43,
       -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
       -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
       -43,  -43,  -43,  -43,  -43,  -43,  -43
@@ -625,272 +625,272 @@
 
     {
        11,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,   84,   85,   85,  -45,  -45,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,  -45
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45
     },
 
     {
        11,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,   85,   85,   85,  -46,  -46,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,  -46
+      -46,   86,   87,   87,  -46,  -46,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,  -46
     },
 
     {
        11,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,   87,   87,   87,  -47,  -47,   87,   87,   87,   87,
 
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,  -47
     },
 
     {
-       11,  -48,  -48,   86,  -48,  -48,  -48,  -48,  -48,  -48,
+       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
       -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
       -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
       -48,  -48,  -48,  -48,  -48,  -48,  -48
     },
 
     {
-       11,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,   85,   85,   85,  -49,  -49,   85,   85,   85,   85,
-       85,   87,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,  -49
+       11,  -49,  -49,   88,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49
 
     },
 
     {
        11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,   85,   85,   85,  -50,  -50,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   88,   85,   85,
-       85,   85,   85,   85,   85,   85,  -50
+      -50,   87,   87,   87,  -50,  -50,   87,   87,   87,   87,
+       87,   89,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,  -50
     },
 
     {
        11,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,   89
+      -51,   87,   87,   87,  -51,  -51,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   90,   87,   87,
+       87,   87,   87,   87,   87,   87,  -51
     },
 
     {
-       11,  -52,   52,   53,  -52,  -52,   54,  -52,  -52,  -52,
+       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
       -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
 
       -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52
+      -52,  -52,  -52,  -52,  -52,  -52,   91
     },
 
     {
-       11,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+       11,  -53,   53,   54,  -53,  -53,   55,  -53,  -53,  -53,
       -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
       -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
       -53,  -53,  -53,  -53,  -53,  -53,  -53
     },
 
     {
-       11,   55,   55,   56,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55
+       11,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54
 
     },
 
     {
-       11,   55,   55,   56,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55
+       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56
     },
 
     {
-       11,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56
+       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56
     },
 
     {
        11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,   57,  -57,  -57,   57,   57,   57,   57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -57
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57
     },
 
     {
        11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,   57,  -58,  -58,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   90,   57,
-       57,   57,   57,   57,   57,   57,  -58
+      -58,  -58,  -58,   58,  -58,  -58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -58
     },
 
     {
        11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,   57,  -59,  -59,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   91,   57,
-       57,   57,   57,   57,   57,   57,  -59
+      -59,  -59,  -59,   58,  -59,  -59,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   92,   58,
+       58,   58,   58,   58,   58,   58,  -59
 
     },
 
     {
        11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,   57,  -60,  -60,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   92,   93,   57,   57,
-       57,   57,   57,   57,   57,   57,  -60
+      -60,  -60,  -60,   58,  -60,  -60,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   93,   58,
+       58,   58,   58,   58,   58,   58,  -60
     },
 
     {
        11,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,   57,  -61,  -61,   57,   57,   57,   57,
-       57,   94,   57,   57,   57,   57,   57,   57,   57,   95,
-       57,   57,   57,   57,   57,   57,  -61
+      -61,  -61,  -61,   58,  -61,  -61,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   94,   95,   58,   58,
+       58,   58,   58,   58,   58,   58,  -61
     },
 
     {
        11,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,   57,  -62,  -62,   57,   57,   57,   96,
+      -62,  -62,  -62,   58,  -62,  -62,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -62
+       58,   96,   58,   58,   58,   58,   58,   58,   58,   97,
+       58,   58,   58,   58,   58,   58,  -62
     },
 
     {
        11,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,   57,  -63,  -63,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   97,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   98,  -63
+      -63,  -63,  -63,   58,  -63,  -63,   58,   58,   58,   98,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -63
     },
 
     {
        11,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,   57,  -64,  -64,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -64
+      -64,  -64,  -64,   58,  -64,  -64,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   99,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  100,  -64
 
     },
 
     {
        11,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,   57,  -65,  -65,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   99,   57,   57,  -65
+      -65,  -65,  -65,   58,  -65,  -65,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -65
     },
 
     {
        11,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,   57,  -66,  -66,   57,   57,   57,   57,
-       57,   57,   57,   57,  100,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -66
+      -66,  -66,  -66,   58,  -66,  -66,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  101,   58,   58,  -66
     },
 
     {
        11,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,   57,  -67,  -67,   57,   57,   57,   57,
+      -67,  -67,  -67,   58,  -67,  -67,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,  101,   57,   57,
-       57,   57,   57,   57,   57,   57,  -67
+       58,   58,   58,   58,  102,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -67
     },
 
     {
        11,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,   57,  -68,  -68,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,  102,   57,   57,  -68
+      -68,  -68,  -68,   58,  -68,  -68,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  103,   58,   58,
+       58,   58,   58,   58,   58,   58,  -68
     },
 
     {
        11,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,   57,  -69,  -69,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  103,   57,
-       57,   57,   57,   57,   57,   57,  -69
+      -69,  -69,  -69,   58,  -69,  -69,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  104,   58,   58,  -69
 
     },
 
     {
        11,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,   57,  -70,  -70,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-      104,   57,   57,   57,   57,   57,  -70
+      -70,  -70,  -70,   58,  -70,  -70,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  105,   58,
+       58,   58,   58,   58,   58,   58,  -70
     },
 
     {
        11,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,   57,  -71,  -71,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,  105,   57,  -71
+      -71,  -71,  -71,   58,  -71,  -71,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+      106,   58,   58,   58,   58,   58,  -71
     },
 
     {
        11,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,   57,  -72,  -72,   57,   57,   57,   57,
+      -72,  -72,  -72,   58,  -72,  -72,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,  106,   57,   57,   57,   57,  -72
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  107,   58,  -72
     },
 
     {
        11,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,   57,  -73,  -73,   57,   57,   57,   57,
-       57,   57,   57,   57,  107,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -73
+      -73,  -73,  -73,   58,  -73,  -73,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,  108,   58,   58,   58,   58,  -73
     },
 
     {
-       11,   74,   74,  -74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74
+       11,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,   58,  -74,  -74,   58,   58,   58,   58,
+       58,   58,   58,   58,  109,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -74
 
     },
 
     {
-       11,  -75,   75,   76,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75
+       11,   75,   75,  -75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75
     },
 
     {
-       11,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+       11,  -76,   76,   77,  -76,  -76,  -76,  -76,  -76,  -76,
       -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
       -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
       -76,  -76,  -76,  -76,  -76,  -76,  -76
     },
 
     {
-       11,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+       11,   78,  -77,  -77,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
 
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78
     },
 
     {
-       11,   78,   78,   79,   78,  -78,   78,   78,  -78,   78,
-       78,   78,   78,   78,   78,  -78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78
+       11,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78
     },
 
     {
-       11,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79
+       11,   79,   79,   80,   79,  -79,   79,   79,  -79,   79,
+       79,   79,   79,   79,   79,  -79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79
 
     },
 
     {
-       11,  -80,  -80,   81,  -80,  -80,  -80,  -80,  -80,  -80,
+       11,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
       -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
       -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
       -80,  -80,  -80,  -80,  -80,  -80,  -80
     },
 
     {
-       11,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+       11,  -81,  -81,   82,  -81,  -81,  -81,  -81,  -81,  -81,
       -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
       -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
       -81,  -81,  -81,  -81,  -81,  -81,  -81
@@ -912,669 +912,728 @@
     },
 
     {
-       11,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  108,   85,   85,  -84,  -84,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,  -84
+       11,   84,   84,  -84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84
 
     },
 
     {
        11,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,   85,   85,   85,  -85,  -85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,  -85
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85
     },
 
     {
        11,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86
+      -86,  110,   87,   87,  -86,  -86,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,  -86
     },
 
     {
        11,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,   85,   85,   85,  -87,  -87,   85,   85,   85,   85,
+      -87,   87,   87,   87,  -87,  -87,   87,   87,   87,   87,
 
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,  -87
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,  -87
     },
 
     {
        11,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,   85,   85,   85,  -88,  -88,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,  -88
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88
     },
 
     {
        11,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89
+      -89,   87,   87,   87,  -89,  -89,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,  -89
 
     },
 
     {
        11,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,   57,  -90,  -90,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,  109,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -90
+      -90,   87,   87,   87,  -90,  -90,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,  -90
     },
 
     {
        11,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,   57,  -91,  -91,   57,   57,   57,   57,
-       57,   57,   57,   57,  110,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -91
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91
     },
 
     {
        11,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,   57,  -92,  -92,   57,   57,   57,   57,
+      -92,  -92,  -92,   58,  -92,  -92,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,  111,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -92
+       58,   58,   58,   58,   58,  111,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -92
     },
 
     {
        11,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,   57,  -93,  -93,   57,   57,   57,   57,
-       57,  112,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -93
+      -93,  -93,  -93,   58,  -93,  -93,   58,   58,   58,   58,
+       58,   58,   58,   58,  112,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -93
     },
 
     {
        11,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,   57,  -94,  -94,  113,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -94
+      -94,  -94,  -94,   58,  -94,  -94,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  113,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -94
 
     },
 
     {
        11,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,   57,  -95,  -95,   57,   57,   57,   57,
-      114,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -95
+      -95,  -95,  -95,   58,  -95,  -95,   58,   58,   58,   58,
+       58,  114,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -95
     },
 
     {
        11,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,   57,  -96,  -96,   57,   57,  115,   57,
-       57,   57,   57,   57,  116,   57,  117,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -96
+      -96,  -96,  -96,   58,  -96,  -96,  115,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -96
     },
 
     {
        11,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,   57,  -97,  -97,   57,   57,   57,   57,
+      -97,  -97,  -97,   58,  -97,  -97,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,  118,
-       57,   57,   57,   57,   57,   57,  -97
+      116,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -97
     },
 
     {
        11,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,   57,  -98,  -98,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -98
+      -98,  -98,  -98,   58,  -98,  -98,   58,   58,  117,   58,
+       58,   58,   58,   58,  118,   58,  119,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  -98
     },
 
     {
        11,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,   57,  -99,  -99,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  -99
+      -99,  -99,  -99,   58,  -99,  -99,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  120,
+       58,   58,   58,   58,   58,   58,  -99
 
     },
 
     {
        11, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100,   57, -100, -100,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,  119,   57,   57,
-       57,   57,   57,   57,   57,   57, -100
+     -100, -100, -100,   58, -100, -100,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -100
     },
 
     {
        11, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101,   57, -101, -101,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,  120,   57, -101
+     -101, -101, -101,   58, -101, -101,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -101
     },
 
     {
        11, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102,   57, -102, -102,   57,   57,   57,   57,
+     -102, -102, -102,   58, -102, -102,   58,   58,   58,   58,
 
-       57,   57,   57,   57,  121,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -102
+       58,   58,   58,   58,   58,   58,   58,  121,   58,   58,
+       58,   58,   58,   58,   58,   58, -102
     },
 
     {
        11, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103,   57, -103, -103,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  122,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -103
+     -103, -103, -103,   58, -103, -103,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  122,   58, -103
     },
 
     {
        11, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104,   57, -104, -104,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,  123,   57, -104
+     -104, -104, -104,   58, -104, -104,   58,   58,   58,   58,
+       58,   58,   58,   58,  123,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -104
 
     },
 
     {
        11, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105,   57, -105, -105,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,  124,   57,   57,   57,   57, -105
+     -105, -105, -105,   58, -105, -105,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  124,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -105
     },
 
     {
        11, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106,   57, -106, -106,   57,   57,   57,   57,
-       57,   57,   57,   57,  125,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -106
+     -106, -106, -106,   58, -106, -106,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  125,   58, -106
     },
 
     {
        11, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107,   57, -107, -107,   57,   57,   57,   57,
+     -107, -107, -107,   58, -107, -107,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,  126,   57,   57,   57, -107
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,  126,   58,   58,   58,   58, -107
     },
 
     {
        11, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108,   85,   85,   85, -108, -108,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85, -108
+     -108, -108, -108,   58, -108, -108,   58,   58,   58,   58,
+       58,   58,   58,   58,  127,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -108
     },
 
     {
        11, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109,   57, -109, -109,   57,   57,   57,   57,
-      127,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -109
+     -109, -109, -109,   58, -109, -109,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,  128,   58,   58,   58, -109
 
     },
 
     {
        11, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110,   57, -110, -110,   57,   57,  128,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -110
+     -110,   87,   87,   87, -110, -110,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87, -110
     },
 
     {
        11, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111,   57, -111, -111,   57,   57,   57,   57,
-      129,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -111
+     -111, -111, -111,   58, -111, -111,   58,   58,   58,   58,
+      129,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -111
     },
 
     {
        11, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112,   57, -112, -112,   57,   57,   57,   57,
+     -112, -112, -112,   58, -112, -112,   58,   58,  130,   58,
 
-       57,   57,   57,   57,  130,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -112
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -112
     },
 
     {
        11, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113,   57, -113, -113,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,  131,   57, -113
+     -113, -113, -113,   58, -113, -113,   58,   58,   58,   58,
+      131,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -113
     },
 
     {
        11, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114,   57, -114, -114,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,  132,   57,   57,
-       57,   57,   57,   57,   57,   57, -114
+     -114, -114, -114,   58, -114, -114,   58,   58,   58,   58,
+       58,   58,   58,   58,  132,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -114
 
     },
 
     {
        11, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115,   57, -115, -115,   57,   57,   57,   57,
-       57,   57,   57,  133,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -115
+     -115, -115, -115,   58, -115, -115,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  133,   58, -115
     },
 
     {
        11, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116,   57, -116, -116,   57,   57,   57,   57,
-       57,  134,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -116
+     -116, -116, -116,   58, -116, -116,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  134,   58,   58,
+       58,   58,   58,   58,   58,   58, -116
     },
 
     {
        11, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117,   57, -117, -117,   57,   57,   57,   57,
+     -117, -117, -117,   58, -117, -117,   58,   58,   58,   58,
 
-      135,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -117
+       58,   58,   58,  135,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -117
     },
 
     {
        11, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118,   57, -118, -118,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -118
+     -118, -118, -118,   58, -118, -118,   58,   58,   58,   58,
+       58,  136,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -118
     },
 
     {
        11, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119,   57, -119, -119,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,  136,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -119
+     -119, -119, -119,   58, -119, -119,   58,   58,   58,   58,
+      137,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -119
 
     },
 
     {
        11, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120,   57, -120, -120,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -120
+     -120, -120, -120,   58, -120, -120,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -120
     },
 
     {
        11, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121,   57, -121, -121,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  137,   57,
-       57,   57,   57,   57,   57,   57, -121
+     -121, -121, -121,   58, -121, -121,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  138,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -121
     },
 
     {
        11, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122,   57, -122, -122,   57,   57,   57,   57,
+     -122, -122, -122,   58, -122, -122,   58,   58,  139,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,  138,
-       57,   57,   57,   57,   57,   57, -122
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -122
     },
 
     {
        11, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123,   57, -123, -123,   57,   57,   57,   57,
-       57,   57,   57,   57,  139,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -123
+     -123, -123, -123,   58, -123, -123,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  140,   58,
+       58,   58,   58,   58,   58,   58, -123
     },
 
     {
        11, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124,   57, -124, -124,   57,   57,  140,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -124
+     -124, -124, -124,   58, -124, -124,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  141,
+       58,   58,   58,   58,   58,   58, -124
 
     },
 
     {
        11, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125,   57, -125, -125,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,  141,   57,   57,
-       57,   57,   57,   57,   57,   57, -125
+     -125, -125, -125,   58, -125, -125,   58,   58,   58,   58,
+       58,   58,   58,   58,  142,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -125
     },
 
     {
        11, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126,   57, -126, -126,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,  142,   57,   57, -126
+     -126, -126, -126,   58, -126, -126,   58,   58,  143,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -126
     },
 
     {
        11, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127,   57, -127, -127,  143,   57,   57,   57,
+     -127, -127, -127,   58, -127, -127,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -127
+       58,   58,   58,   58,   58,   58,   58,  144,   58,   58,
+       58,   58,   58,   58,   58,   58, -127
     },
 
     {
        11, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128,   57, -128, -128,   57,   57,   57,   57,
-      144,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -128
+     -128, -128, -128,   58, -128, -128,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  145,   58,   58, -128
     },
 
     {
        11, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129,   57, -129, -129,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,  145,   57,   57,
-       57,   57,   57,   57,   57,   57, -129
+     -129, -129, -129,   58, -129, -129,  146,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -129
 
     },
 
     {
        11, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130,   57, -130, -130,   57,   57,   57,   57,
-       57,   57,  146,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -130
+     -130, -130, -130,   58, -130, -130,   58,   58,   58,   58,
+      147,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -130
     },
 
     {
        11, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131,   57, -131, -131,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,  147,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -131
+     -131, -131, -131,   58, -131, -131,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  148,   58,   58,
+       58,   58,   58,   58,   58,   58, -131
     },
 
     {
        11, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132,   57, -132, -132,   57,   57,   57,  148,
+     -132, -132, -132,   58, -132, -132,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -132
+       58,   58,  149,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -132
     },
 
     {
        11, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133,   57, -133, -133,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  149,   57,
-       57,   57,   57,   57,   57,   57, -133
+     -133, -133, -133,   58, -133, -133,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  150,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -133
     },
 
     {
        11, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134,   57, -134, -134,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -134
+     -134, -134, -134,   58, -134, -134,   58,   58,   58,  151,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -134
 
     },
 
     {
        11, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135,   57, -135, -135,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,  150,   57,   57,
-       57,   57,   57,   57,   57,   57, -135
+     -135, -135, -135,   58, -135, -135,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  152,   58,
+       58,   58,   58,   58,   58,   58, -135
     },
 
     {
        11, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136,   57, -136, -136,   57,   57,   57,   57,
-      151,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -136
+     -136, -136, -136,   58, -136, -136,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -136
     },
 
     {
        11, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137,   57, -137, -137,   57,   57,   57,   57,
+     -137, -137, -137,   58, -137, -137,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,  152,   57,   57,
-       57,   57,   57,   57,   57,   57, -137
+       58,   58,   58,   58,   58,   58,   58,  153,   58,   58,
+       58,   58,   58,   58,   58,   58, -137
     },
 
     {
        11, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138,   57, -138, -138,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,  153,   57,   57, -138
+     -138, -138, -138,   58, -138, -138,   58,   58,   58,   58,
+      154,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -138
     },
 
     {
        11, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139,   57, -139, -139,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,  154,   57,   57,   57,   57, -139
+     -139, -139, -139,   58, -139, -139,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  155,   58,
+       58,   58,   58,   58,   58,   58, -139
 
     },
 
     {
        11, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140,   57, -140, -140,   57,   57,   57,   57,
-      155,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -140
+     -140, -140, -140,   58, -140, -140,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  156,   58,   58,
+       58,   58,   58,   58,   58,   58, -140
     },
 
     {
        11, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141,   57, -141, -141,   57,   57,   57,   57,
-       57,   57,  156,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -141
+     -141, -141, -141,   58, -141, -141,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  157,   58,   58, -141
     },
 
     {
        11, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142,   57, -142, -142,  157,   57,   57,   57,
+     -142, -142, -142,   58, -142, -142,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -142
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,  158,   58,   58,   58,   58, -142
     },
 
     {
        11, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143,   57, -143, -143,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,  158,   57,   57,
-       57,   57,   57,   57,   57,   57, -143
+     -143, -143, -143,   58, -143, -143,   58,   58,   58,   58,
+      159,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -143
     },
 
     {
        11, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144,   57, -144, -144,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -144
+     -144, -144, -144,   58, -144, -144,   58,   58,   58,   58,
+       58,   58,  160,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -144
 
     },
 
     {
        11, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145,   57, -145, -145,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,  159,   57,   57, -145
+     -145, -145, -145,   58, -145, -145,  161,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -145
     },
 
     {
        11, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146,   57, -146, -146,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -146
+     -146, -146, -146,   58, -146, -146,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  162,   58,   58,
+       58,   58,   58,   58,   58,   58, -146
     },
 
     {
        11, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147,   57, -147, -147,   57,   57,   57,   57,
+     -147, -147, -147,   58, -147, -147,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,  160,   57,   57, -147
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -147
     },
 
     {
        11, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148,   57, -148, -148,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,  161,   57,   57,   57, -148
+     -148, -148, -148,   58, -148, -148,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  163,   58,   58, -148
     },
 
     {
        11, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149,   57, -149, -149,   57,   57,   57,   57,
-       57,   57,   57,   57,  162,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -149
+     -149, -149, -149,   58, -149, -149,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -149
 
     },
 
     {
        11, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150,   57, -150, -150,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,  163,   57, -150
+     -150, -150, -150,   58, -150, -150,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  164,   58,   58, -150
     },
 
     {
        11, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151,   57, -151, -151,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,  164,   57,   57,
-       57,   57,   57,   57,   57,   57, -151
+     -151, -151, -151,   58, -151, -151,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,  165,   58,   58,   58, -151
     },
 
     {
        11, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152,   57, -152, -152,  165,   57,   57,   57,
+     -152, -152, -152,   58, -152, -152,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -152
+       58,   58,   58,   58,  166,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -152
     },
 
     {
        11, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153,   57, -153, -153,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -153
+     -153, -153, -153,   58, -153, -153,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  167,   58, -153
     },
 
     {
        11, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154,   57, -154, -154,   57,   57,   57,   57,
-      166,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -154
+     -154, -154, -154,   58, -154, -154,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  168,   58,   58,
+       58,   58,   58,   58,   58,   58, -154
 
     },
 
     {
        11, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155,   57, -155, -155,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -155
+     -155, -155, -155,   58, -155, -155,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  169,   58,   58,
+       58,   58,   58,   58,   58,   58, -155
     },
 
     {
        11, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156,   57, -156, -156,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -156
+     -156, -156, -156,   58, -156, -156,  170,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -156
     },
 
     {
        11, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157,   57, -157, -157,   57,   57,   57,   57,
+     -157, -157, -157,   58, -157, -157,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,  167,   57,   57, -157
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -157
     },
 
     {
        11, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158,   57, -158, -158,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -158
+     -158, -158, -158,   58, -158, -158,   58,   58,   58,   58,
+      171,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -158
     },
 
     {
        11, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159,   57, -159, -159,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -159
+     -159, -159, -159,   58, -159, -159,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -159
 
     },
 
     {
        11, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160,   57, -160, -160,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -160
+     -160, -160, -160,   58, -160, -160,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -160
     },
 
     {
        11, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161,   57, -161, -161,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -161
+     -161, -161, -161,   58, -161, -161,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  172,   58,   58, -161
     },
 
     {
        11, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162,   57, -162, -162,   57,   57,  168,   57,
+     -162, -162, -162,   58, -162, -162,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -162
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -162
     },
 
     {
        11, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163,   57, -163, -163,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -163
+     -163, -163, -163,   58, -163, -163,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -163
     },
 
     {
        11, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164,   57, -164, -164,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,  169,   57, -164
+     -164, -164, -164,   58, -164, -164,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -164
 
     },
 
     {
        11, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165,   57, -165, -165,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,  170,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -165
+     -165, -165, -165,   58, -165, -165,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -165
     },
 
     {
        11, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166,   57, -166, -166,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,  171,   57,   57,   57, -166
+     -166, -166, -166,   58, -166, -166,   58,   58,  173,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -166
     },
 
     {
        11, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167,   57, -167, -167,   57,   57,   57,   57,
+     -167, -167, -167,   58, -167, -167,   58,   58,   58,   58,
 
-      172,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -167
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -167
     },
 
     {
        11, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168,   57, -168, -168,   57,   57,   57,   57,
-      173,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -168
+     -168, -168, -168,   58, -168, -168,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  174,   58, -168
     },
 
     {
        11, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169,   57, -169, -169,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -169
+     -169, -169, -169,   58, -169, -169,   58,   58,   58,   58,
+       58,  175,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -169
 
     },
 
     {
        11, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170,   57, -170, -170,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -170
+     -170, -170, -170,   58, -170, -170,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  176,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -170
     },
 
     {
        11, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171,   57, -171, -171,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -171
+     -171, -171, -171,   58, -171, -171,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,  177,   58,   58,   58, -171
     },
 
     {
        11, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172,   57, -172, -172,   57,   57,   57,   57,
+     -172, -172, -172,   58, -172, -172,   58,   58,   58,   58,
 
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -172
+      178,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -172
     },
 
     {
        11, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173,   57, -173, -173,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57, -173
+     -173, -173, -173,   58, -173, -173,   58,   58,   58,   58,
+      179,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -173
+    },
+
+    {
+       11, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174,   58, -174, -174,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -174
+
+    },
+
+    {
+       11, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175,   58, -175, -175,   58,   58,   58,   58,
+       58,   58,   58,   58,  180,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -175
+    },
+
+    {
+       11, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176,   58, -176, -176,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -176
+    },
+
+    {
+       11, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177,   58, -177, -177,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -177
+    },
+
+    {
+       11, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178,   58, -178, -178,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -178
+    },
+
+    {
+       11, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179,   58, -179, -179,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -179
+
+    },
+
+    {
+       11, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180,   58, -180, -180,   58,   58,   58,   58,
+       58,   58,  181,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -180
+    },
+
+    {
+       11, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181,   58, -181, -181,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58, -181
     },
 
     } ;
@@ -1595,29 +1654,30 @@
 	*yy_cp = '\0'; \
 	yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 56
-#define YY_END_OF_BUFFER 57
-static yyconst short int yy_accept[174] =
+#define YY_NUM_RULES 58
+#define YY_END_OF_BUFFER 59
+static yyconst short int yy_accept[182] =
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       57,    5,    4,    3,    2,   29,   30,   28,   28,   28,
-       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
-       55,   52,   54,   47,   51,   50,   49,   45,   41,   35,
-       40,   45,   33,   34,   43,   43,   36,   45,   43,   43,
-       45,    4,    3,    2,    2,    1,   28,   28,   28,   28,
-       28,   28,   28,   15,   28,   28,   28,   28,   28,   28,
-       28,   28,   28,   55,   52,   54,   53,   47,   46,   49,
-       48,   37,   31,   43,   43,   44,   38,   39,   32,   28,
-       28,   28,   28,   28,   28,   28,   28,   26,   25,   28,
-
-       28,   28,   28,   28,   28,   28,   28,   42,   23,   28,
-       28,   28,   28,   28,   28,   28,   28,   14,   28,    7,
-       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
-       28,   28,   28,   16,   28,   28,   28,   28,   28,   28,
-       28,   28,   28,   10,   28,   13,   28,   28,   28,   28,
-       28,   28,   21,   28,    9,   27,   28,   24,   12,   20,
-       17,   28,    8,   28,   28,   28,   28,   28,    6,   19,
-       18,   22,   11
+       59,    5,    4,    3,    2,   30,   31,   29,   29,   29,
+       29,   29,   29,   29,   29,   29,   29,   29,   29,   29,
+       57,   54,   56,   49,   53,   52,   51,   47,   42,   36,
+       41,   45,   47,   34,   35,   44,   44,   37,   47,   44,
+       44,   47,    4,    3,    2,    2,    1,   29,   29,   29,
+       29,   29,   29,   29,   16,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   57,   54,   56,   55,   49,   48,
+       51,   50,   38,   45,   32,   44,   44,   46,   39,   40,
+       33,   29,   29,   29,   29,   29,   29,   29,   29,   27,
+
+       26,   29,   29,   29,   29,   29,   29,   29,   29,   43,
+       24,   29,   29,   29,   29,   29,   29,   29,   29,   15,
+       29,    7,   29,   29,   29,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   29,   17,   29,   29,   29,   29,
+       29,   29,   29,   29,   29,   29,   10,   29,   13,   29,
+       29,   29,   29,   29,   29,   29,   22,   29,    9,   28,
+       29,   25,   12,   21,   18,   29,    8,   29,   29,   29,
+       29,   29,   29,    6,   29,   20,   19,   23,   11,   29,
+       14
     } ;
 
 static yyconst int yy_ec[256] =
@@ -1993,43 +2053,43 @@
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_HELP;
+BEGIN(PARAM); return T_MENUCONFIG;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_IF;
+BEGIN(PARAM); return T_HELP;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_ENDIF;
+BEGIN(PARAM); return T_IF;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_DEPENDS;
+BEGIN(PARAM); return T_ENDIF;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_REQUIRES;
+BEGIN(PARAM); return T_DEPENDS;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_OPTIONAL;
+BEGIN(PARAM); return T_REQUIRES;
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_DEFAULT;
+BEGIN(PARAM); return T_OPTIONAL;
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_PROMPT;
+BEGIN(PARAM); return T_DEFAULT;
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_TRISTATE;
+BEGIN(PARAM); return T_PROMPT;
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_BOOLEAN;
+BEGIN(PARAM); return T_TRISTATE;
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
@@ -2037,71 +2097,75 @@
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_INT;
+BEGIN(PARAM); return T_BOOLEAN;
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_HEX;
+BEGIN(PARAM); return T_INT;
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-BEGIN(PARAM); return T_STRING;
+BEGIN(PARAM); return T_HEX;
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
+BEGIN(PARAM); return T_STRING;
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
 {
 		alloc_string(yytext, yyleng);
 		zconflval.string = text;
 		return T_WORD;
 	}
 	YY_BREAK
-case 29:
+case 30:
 YY_RULE_SETUP
 
 	YY_BREAK
-case 30:
+case 31:
 YY_RULE_SETUP
 current_file->lineno++; BEGIN(INITIAL);
 	YY_BREAK
 
 
-case 31:
+case 32:
 YY_RULE_SETUP
 return T_AND;
 	YY_BREAK
-case 32:
+case 33:
 YY_RULE_SETUP
 return T_OR;
 	YY_BREAK
-case 33:
+case 34:
 YY_RULE_SETUP
 return T_OPEN_PAREN;
 	YY_BREAK
-case 34:
+case 35:
 YY_RULE_SETUP
 return T_CLOSE_PAREN;
 	YY_BREAK
-case 35:
+case 36:
 YY_RULE_SETUP
 return T_NOT;
 	YY_BREAK
-case 36:
+case 37:
 YY_RULE_SETUP
 return T_EQUAL;
 	YY_BREAK
-case 37:
+case 38:
 YY_RULE_SETUP
 return T_UNEQUAL;
 	YY_BREAK
-case 38:
+case 39:
 YY_RULE_SETUP
 return T_IF;
 	YY_BREAK
-case 39:
+case 40:
 YY_RULE_SETUP
 return T_ON;
 	YY_BREAK
-case 40:
+case 41:
 YY_RULE_SETUP
 {
 		str = yytext[0];
@@ -2109,15 +2173,15 @@
 		BEGIN(STRING);
 	}
 	YY_BREAK
-case 41:
+case 42:
 YY_RULE_SETUP
 BEGIN(INITIAL); current_file->lineno++; return T_EOL;
 	YY_BREAK
-case 42:
+case 43:
 YY_RULE_SETUP
 /* ignore */
 	YY_BREAK
-case 43:
+case 44:
 YY_RULE_SETUP
 {
 		alloc_string(yytext, yyleng);
@@ -2125,11 +2189,15 @@
 		return T_WORD;
 	}
 	YY_BREAK
-case 44:
+case 45:
+YY_RULE_SETUP
+/* comment */
+	YY_BREAK
+case 46:
 YY_RULE_SETUP
 current_file->lineno++;
 	YY_BREAK
-case 45:
+case 47:
 YY_RULE_SETUP
 
 	YY_BREAK
@@ -2140,7 +2208,7 @@
 	YY_BREAK
 
 
-case 46:
+case 48:
 *yy_cp = yy_hold_char; /* undo effects of setting up yytext */
 yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
@@ -2151,13 +2219,13 @@
 		return T_WORD_QUOTE;
 	}
 	YY_BREAK
-case 47:
+case 49:
 YY_RULE_SETUP
 {
 		append_string(yytext, yyleng);
 	}
 	YY_BREAK
-case 48:
+case 50:
 *yy_cp = yy_hold_char; /* undo effects of setting up yytext */
 yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
@@ -2168,13 +2236,13 @@
 		return T_WORD_QUOTE;
 	}
 	YY_BREAK
-case 49:
+case 51:
 YY_RULE_SETUP
 {
 		append_string(yytext + 1, yyleng - 1);
 	}
 	YY_BREAK
-case 50:
+case 52:
 YY_RULE_SETUP
 {
 		if (str == yytext[0]) {
@@ -2185,7 +2253,7 @@
 			append_string(yytext, 1);
 	}
 	YY_BREAK
-case 51:
+case 53:
 YY_RULE_SETUP
 {
 		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
@@ -2201,7 +2269,7 @@
 	YY_BREAK
 
 
-case 52:
+case 54:
 YY_RULE_SETUP
 {
 		ts = 0;
@@ -2227,9 +2295,9 @@
 		
 	}
 	YY_BREAK
-case 53:
+case 55:
 *yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 1;
+yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
 {
@@ -2238,14 +2306,14 @@
 		return T_HELPTEXT;
 	}
 	YY_BREAK
-case 54:
+case 56:
 YY_RULE_SETUP
 {
 		current_file->lineno++;
 		append_string("\n", 1);
 	}
 	YY_BREAK
-case 55:
+case 57:
 YY_RULE_SETUP
 {
 		append_string(yytext, yyleng);
@@ -2271,7 +2339,7 @@
 	yyterminate();
 }
 	YY_BREAK
-case 56:
+case 58:
 YY_RULE_SETUP
 YY_FATAL_ERROR( "flex scanner jammed" );
 	YY_BREAK
diff -Nru a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
--- a/scripts/kconfig/mconf.c	Sat Dec  7 20:54:55 2002
+++ b/scripts/kconfig/mconf.c	Sat Mar 15 09:25:55 2003
@@ -302,11 +302,8 @@
 					cprint1("%s%*c%s",
 						menu->data ? "-->" : "++>",
 						indent + 1, ' ', prompt);
-				} else {
-					if (menu->parent != &rootmenu)
-						cprint1("   %*c", indent + 1, ' ');
-					cprint1("%s  --->", prompt);
-				}
+				} else
+					cprint1("   %*c%s  --->", indent + 1, ' ', prompt);
 
 				cprint_done();
 				if (single_menu_mode && menu->data)
@@ -373,6 +370,11 @@
 		}
 		cprint_done();
 	} else {
+		if (menu == current_menu) {
+			cprint(":%p", menu);
+			cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+			goto conf_childs;
+		}
 		child_count++;
 		val = sym_get_tristate_value(sym);
 		if (sym_is_choice_value(sym) && val == yes) {
@@ -407,6 +409,11 @@
 		}
 		cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
 			sym_has_value(sym) ? "" : " (NEW)");
+		if (menu->prompt->type == P_MENU) {
+			cprint1("  --->");
+			cprint_done();
+			return;
+		}
 		cprint_done();
 	}
 
@@ -445,9 +452,9 @@
 			cprint(":");
 			cprint("--- ");
 			cprint("L");
-			cprint("Load an Alternate Configuration File");
+			cprint("    Load an Alternate Configuration File");
 			cprint("S");
-			cprint("Save Configuration to an Alternate File");
+			cprint("    Save Configuration to an Alternate File");
 		}
 		stat = exec_conf();
 		if (stat < 0)
@@ -484,6 +491,8 @@
 			case 't':
 				if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
 					conf_choice(submenu);
+				else if (submenu->prompt->type == P_MENU)
+					conf(submenu);
 				break;
 			case 's':
 				conf_string(submenu);
diff -Nru a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
--- a/scripts/kconfig/menu.c	Thu Nov  7 04:44:54 2002
+++ b/scripts/kconfig/menu.c	Sat Mar 15 09:25:55 2003
@@ -54,9 +54,34 @@
 	current_menu = current_menu->parent;
 }
 
+struct expr *menu_check_dep(struct expr *e)
+{
+	if (!e)
+		return e;
+
+	switch (e->type) {
+	case E_NOT:
+		e->left.expr = menu_check_dep(e->left.expr);
+		break;
+	case E_OR:
+	case E_AND:
+		e->left.expr = menu_check_dep(e->left.expr);
+		e->right.expr = menu_check_dep(e->right.expr);
+		break;
+	case E_SYMBOL:
+		/* change 'm' into 'm' && MODULES */
+		if (e->left.sym == &symbol_mod)
+			return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
+		break;
+	default:
+		break;
+	}
+	return e;
+}
+
 void menu_add_dep(struct expr *dep)
 {
-	current_entry->dep = expr_alloc_and(current_entry->dep, dep);
+	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
 }
 
 void menu_set_type(int type)
@@ -96,7 +121,7 @@
 	prop->menu = current_entry;
 	prop->text = prompt;
 	prop->def = def;
-	E_EXPR(prop->visible) = dep;
+	E_EXPR(prop->visible) = menu_check_dep(dep);
 
 	if (prompt)
 		current_entry->prompt = prop;
@@ -169,8 +194,8 @@
 		}
 		for (menu = parent->list; menu; menu = menu->next)
 			menu_finalize(menu);
-	} else if (sym && parent->prompt) {
-		basedep = E_EXPR(parent->prompt->visible);
+	} else if (sym) {
+		basedep = parent->prompt ? E_EXPR(parent->prompt->visible) : NULL;
 		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
 		basedep = expr_eliminate_dups(expr_transform(basedep));
 		last_menu = NULL;
diff -Nru a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
--- a/scripts/kconfig/qconf.cc	Sat Dec  7 20:14:02 2002
+++ b/scripts/kconfig/qconf.cc	Sat Mar 15 09:25:55 2003
@@ -42,15 +42,12 @@
  * menu: entry to be updated
  */
 template <class P>
-static void updateMenuList(P* parent, struct menu* menu)
+void ConfigList::updateMenuList(P* parent, struct menu* menu)
 {
 	struct menu* child;
-	ConfigList* list = parent->listView();
 	ConfigItem* item;
 	ConfigItem* last;
 	bool visible;
-	bool showAll = list->showAll;
-	enum listMode mode = list->mode;
 	enum prop_type type;
 
 	if (!menu) {
@@ -59,7 +56,9 @@
 		return;
 	}
 
-	last = 0;
+	last = parent->firstChild();
+	if (last && !last->goParent)
+		last = 0;
 	for (child = menu->list; child; child = child->next) {
 		item = last ? last->nextSibling() : parent->firstChild();
 		type = child->prompt ? child->prompt->type : P_UNKNOWN;
@@ -81,16 +80,8 @@
 		if (showAll || visible) {
 			if (!item || item->menu != child)
 				item = new ConfigItem(parent, last, child, visible);
-			else {
-				item->visible = visible;
-				if (item->updateNeeded()) {
-					ConfigItem* i = (ConfigItem*)child->data;
-					for (; i; i = i->nextItem) {
-						i->updateMenu();
-					}
-				} else if (list->updateAll)
-					item->updateMenu();
-			}
+			else
+				item->testUpdateMenu(visible);
 
 			if (mode == fullMode || mode == menuMode ||
 			    (type != P_MENU && type != P_ROOTMENU))
@@ -100,7 +91,7 @@
 			last = item;
 			continue;
 		}
-	hide:	
+	hide:
 		if (item && item->menu == child) {
 			last = parent->firstChild();
 			if (last == item)
@@ -131,24 +122,46 @@
 {
 	ConfigList* list;
 	struct symbol* sym;
+	struct property *prop;
 	QString prompt;
 	int type;
-	enum prop_type ptype;
 	tristate expr;
 
 	list = listView();
+	if (goParent) {
+		setPixmap(promptColIdx, list->menuBackPix);
+		prompt = "..";
+		goto set_prompt;
+	}
 
 	sym = menu->sym;
-	if (!sym) {
-		setText(promptColIdx, menu_get_prompt(menu));
-		ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
-		if ((ptype == P_ROOTMENU || ptype == P_MENU) &&
-		    (list->mode == singleMode || list->mode == symbolMode))
+	prop = menu->prompt;
+	prompt = menu_get_prompt(menu);
+
+	if (prop) switch (prop->type) {
+	case P_MENU:
+	case P_ROOTMENU:
+		if (list->mode == singleMode || list->mode == symbolMode) {
+			/* a menuconfig entry is displayed differently
+			 * depending whether it's at the view root or a child.
+			 */
+			if (sym && list->rootEntry == menu)
+				break;
 			setPixmap(promptColIdx, list->menuPix);
-		else
+		} else {
+			if (sym)
+				break;
 			setPixmap(promptColIdx, 0);
-		return;
+		}
+		goto set_prompt;
+	case P_COMMENT:
+		setPixmap(promptColIdx, 0);
+		goto set_prompt;
+	default:
+		;
 	}
+	if (!sym)
+		goto set_prompt;
 
 	setText(nameColIdx, sym->name);
 
@@ -158,7 +171,6 @@
 	case S_TRISTATE:
 		char ch;
 
-		prompt = menu_get_prompt(menu);
 		if (!sym_is_changable(sym) && !list->showAll) {
 			setText(noColIdx, 0);
 			setText(modColIdx, 0);
@@ -211,26 +223,33 @@
 #endif
 		setText(dataColIdx, data);
 		if (type == S_STRING)
-			prompt.sprintf("%s: %s", menu_get_prompt(menu), data);
+			prompt.sprintf("%s: %s", prompt.latin1(), data);
 		else
-			prompt.sprintf("(%s) %s", data, menu_get_prompt(menu));
+			prompt.sprintf("(%s) %s", data, prompt.latin1());
 		break;
 	}
 	if (!sym_has_value(sym) && visible)
 		prompt += " (NEW)";
+set_prompt:
 	setText(promptColIdx, prompt);
 }
 
-bool ConfigItem::updateNeeded(void)
+void ConfigItem::testUpdateMenu(bool v)
 {
-	struct symbol* sym = menu->sym;
-	if (sym)
-		sym_calc_value(sym);
+	ConfigItem* i;
+
+	visible = v;
+	if (!menu)
+		return;
+
+	sym_calc_value(menu->sym);
 	if (menu->flags & MENU_CHANGED) {
+		/* the menu entry changed, so update all list items */
 		menu->flags &= ~MENU_CHANGED;
-		return true;
-	}
-	return false;
+		for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
+			i->updateMenu();
+	} else if (listView()->updateAll)
+		updateMenu();
 }
 
 void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
@@ -251,14 +270,15 @@
  */
 void ConfigItem::init(void)
 {
-	ConfigList* list = listView();
-	nextItem = (ConfigItem*)menu->data;
-	menu->data = this;
+	if (menu) {
+		ConfigList* list = listView();
+		nextItem = (ConfigItem*)menu->data;
+		menu->data = this;
 
-	if (list->mode != fullMode)
-		setOpen(TRUE);
-	if (menu->sym)
+		if (list->mode != fullMode)
+			setOpen(TRUE);
 		sym_calc_value(menu->sym);
+	}
 	updateMenu();
 }
 
@@ -267,11 +287,13 @@
  */
 ConfigItem::~ConfigItem(void)
 {
-	ConfigItem** ip = &(ConfigItem*)menu->data;
-	for (; *ip; ip = &(*ip)->nextItem) {
-		if (*ip == this) {
-			*ip = nextItem;
-			break;
+	if (menu) {
+		ConfigItem** ip = &(ConfigItem*)menu->data;
+		for (; *ip; ip = &(*ip)->nextItem) {
+			if (*ip == this) {
+				*ip = nextItem;
+				break;
+			}
 		}
 	}
 }
@@ -310,7 +332,8 @@
 	: Parent(p), cview(cv),
 	  updateAll(false),
 	  symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
-	  choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), menuPix(xpm_menu), menuInvPix(xpm_menu_inv),
+	  choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
+	  menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback),
 	  showAll(false), showName(false), showRange(false), showData(false),
 	  rootEntry(0)
 {
@@ -366,6 +389,8 @@
 	cview->setHelp(item);
 
 	menu = item->menu;
+	if (!menu)
+		return;
 	type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
 	if (mode == menuMode && (type == P_MENU || type == P_ROOTMENU))
 		emit menuSelected(menu);
@@ -373,7 +398,27 @@
 
 void ConfigList::updateList(ConfigItem* item)
 {
-	(void)item;	// unused so far
+	ConfigItem* last = 0;
+
+	if (!rootEntry)
+		goto update;
+
+	if ((mode == singleMode || mode == symbolMode) && rootEntry != &rootmenu) {
+		item = firstChild();
+		if (!item)
+			item = new ConfigItem(this, 0, true);
+		last = item;
+	}
+	if (mode == singleMode && rootEntry->sym && rootEntry->prompt) {
+		item = last ? last->nextSibling() : firstChild();
+		if (!item)
+			item = new ConfigItem(this, last, rootEntry, true);
+
+		updateMenuList(item, rootEntry);
+		triggerUpdate();
+		return;
+	}
+update:
 	updateMenuList(this, rootEntry);
 	triggerUpdate();
 }
@@ -392,7 +437,7 @@
 	int type;
 	tristate oldval;
 
-	sym = item->menu->sym;
+	sym = item->menu ? item->menu->sym : 0;
 	if (!sym)
 		return;
 
@@ -418,6 +463,8 @@
 	int type, oldexpr, newexpr;
 
 	menu = item->menu;
+	if (!menu)
+		return;
 	sym = menu->sym;
 	if (!sym) {
 		if (item->menu->list)
@@ -511,7 +558,13 @@
 	switch (ev->key()) {
 	case Key_Return:
 	case Key_Enter:
+		if (item->goParent) {
+			emit parentSelected();
+			break;
+		}
 		menu = item->menu;
+		if (!menu)
+			break;
 		type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
 		if ((type == P_MENU || type == P_ROOTMENU) && mode != fullMode) {
 			emit menuSelected(menu);
@@ -564,7 +617,11 @@
 			int off = header()->sectionPos(0) + itemMargin() +
 				treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
 			if (x >= off && x < off + pm->width()) {
-				if (menu->sym)
+				if (item->goParent)
+					emit parentSelected();
+				else if (!menu)
+					break;
+				else if (menu->sym)
 					changeValue(item);
 				else
 					emit menuSelected(menu);
@@ -606,7 +663,13 @@
 
 	if (!item)
 		goto skip;
+	if (item->goParent) {
+		emit parentSelected();
+		goto skip;
+	}
 	menu = item->menu;
+	if (!menu)
+		goto skip;
 	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
 	if ((ptype == P_ROOTMENU || ptype == P_MENU) &&
 	    (mode == singleMode || mode == symbolMode))
@@ -677,7 +740,6 @@
  */
 ConfigMainWindow::ConfigMainWindow(void)
 {
-	ConfigView* view;
 	QMenuBar* menu;
 	QSplitter* split1;
 	QSplitter* split2;
@@ -707,15 +769,15 @@
 	split1->setOrientation(QSplitter::Horizontal);
 	setCentralWidget(split1);
 
-	view = new ConfigView(split1, this);
-	menuList = view->list;
+	menuView = new ConfigView(split1, this);
+	menuList = menuView->list;
 
 	split2 = new QSplitter(split1);
 	split2->setOrientation(QSplitter::Vertical);
 
 	// create config tree
-	view = new ConfigView(split2, this);
-	configList = view->list;
+	configView = new ConfigView(split2, this);
+	configList = configView->list;
 
 	helpText = new QTextView(split2);
 	helpText->setTextFormat(Qt::RichText);
@@ -864,89 +926,87 @@
 void ConfigMainWindow::setHelp(QListViewItem* item)
 {
 	struct symbol* sym;
-	struct menu* menu;
+	struct menu* menu = 0;
 
 	configList->parent()->lineEdit->hide();
-	if (item) {
-		QString head, debug, help;
+	if (item)
 		menu = ((ConfigItem*)item)->menu;
-		sym = menu->sym;
-		if (sym) {
-			if (menu->prompt) {
-				head += "<big><b>";
-				head += print_filter(menu->prompt->text);
-				head += "</b></big>";
-				if (sym->name) {
-					head += " (";
-					head += print_filter(sym->name);
-					head += ")";
-				}
-			} else if (sym->name) {
-				head += "<big><b>";
+	if (!menu) {
+		helpText->setText(NULL);
+		return;
+	}
+
+	QString head, debug, help;
+	menu = ((ConfigItem*)item)->menu;
+	sym = menu->sym;
+	if (sym) {
+		if (menu->prompt) {
+			head += "<big><b>";
+			head += print_filter(menu->prompt->text);
+			head += "</b></big>";
+			if (sym->name) {
+				head += " (";
 				head += print_filter(sym->name);
-				head += "</b></big>";
+				head += ")";
 			}
-			head += "<br><br>";
+		} else if (sym->name) {
+			head += "<big><b>";
+			head += print_filter(sym->name);
+			head += "</b></big>";
+		}
+		head += "<br><br>";
 
-			if (showDebug) {
-				debug += "type: ";
-				debug += print_filter(sym_type_name(sym->type));
-				debug += "<br>";
-				for (struct property *prop = sym->prop; prop; prop = prop->next) {
-					switch (prop->type) {
-					case P_PROMPT:
-						debug += "prompt: ";
-						debug += print_filter(prop->text);
-						debug += "<br>";
-						if (prop->visible.expr) {
-							debug += "&nbsp;&nbsp;dep: ";
-							expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
-							debug += "<br>";
-						}
-						break;
-					case P_DEFAULT:
-						debug += "default: ";
-						if (sym_is_choice(sym))
-							debug += print_filter(prop->def->name);
-						else {
-							sym_calc_value(prop->def);
-							debug += print_filter(sym_get_string_value(prop->def));
-						}
+		if (showDebug) {
+			debug += "type: ";
+			debug += print_filter(sym_type_name(sym->type));
+			debug += "<br>";
+			for (struct property *prop = sym->prop; prop; prop = prop->next) {
+				switch (prop->type) {
+				case P_PROMPT:
+					debug += "prompt: ";
+					debug += print_filter(prop->text);
+					debug += "<br>";
+					if (prop->visible.expr) {
+						debug += "&nbsp;&nbsp;dep: ";
+						expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
 						debug += "<br>";
-						if (prop->visible.expr) {
-							debug += "&nbsp;&nbsp;dep: ";
-							expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
-							debug += "<br>";
-						}
-						break;
-					case P_CHOICE:
-						break;
-					default:
-						debug += "unknown property: ";
-						debug += prop_get_type_name(prop->type);
+					}
+					break;
+				case P_DEFAULT:
+					debug += "default: ";
+					debug += print_filter(prop->def->name);
+					debug += "<br>";
+					if (prop->visible.expr) {
+						debug += "&nbsp;&nbsp;dep: ";
+						expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
 						debug += "<br>";
 					}
+					break;
+				case P_CHOICE:
+					break;
+				default:
+					debug += "unknown property: ";
+					debug += prop_get_type_name(prop->type);
+					debug += "<br>";
 				}
-				debug += "<br>";
 			}
+			debug += "<br>";
+		}
 
-			help = print_filter(sym->help);
-		} else if (menu->prompt) {
-			head += "<big><b>";
-			head += print_filter(menu->prompt->text);
-			head += "</b></big><br><br>";
-			if (showDebug) {
-				if (menu->prompt->visible.expr) {
-					debug += "&nbsp;&nbsp;dep: ";
-					expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
-					debug += "<br>";
-				}
+		help = print_filter(sym->help);
+	} else if (menu->prompt) {
+		head += "<big><b>";
+		head += print_filter(menu->prompt->text);
+		head += "</b></big><br><br>";
+		if (showDebug) {
+			if (menu->prompt->visible.expr) {
+				debug += "&nbsp;&nbsp;dep: ";
+				expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
+				debug += "<br>";
 			}
 		}
-		helpText->setText(head + debug + help);
-		return;
 	}
-	helpText->setText(NULL);
+	helpText->setText(head + debug + help);
 }
 
 void ConfigMainWindow::loadConfig(void)
@@ -1010,7 +1070,7 @@
 
 void ConfigMainWindow::showSingleView(void)
 {
-	menuList->hide();
+	menuView->hide();
 	menuList->setRootMenu(0);
 	configList->mode = singleMode;
 	if (configList->rootEntry == &rootmenu)
@@ -1032,14 +1092,14 @@
 	configApp->processEvents();
 	menuList->mode = menuMode;
 	menuList->setRootMenu(&rootmenu);
-	menuList->show();
 	menuList->setAllOpen(TRUE);
+	menuView->show();
 	menuList->setFocus();
 }
 
 void ConfigMainWindow::showFullView(void)
 {
-	menuList->hide();
+	menuView->hide();
 	menuList->setRootMenu(0);
 	configList->mode = fullMode;
 	if (configList->rootEntry == &rootmenu)
diff -Nru a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
--- a/scripts/kconfig/qconf.h	Sat Dec  7 20:14:02 2002
+++ b/scripts/kconfig/qconf.h	Sat Mar 15 09:25:55 2003
@@ -101,10 +101,14 @@
 	void setAllOpen(bool open);
 	void setParentMenu(void);
 
+	template <class P>
+	void ConfigList::updateMenuList(P*, struct menu*);
+
 	bool updateAll;
 
 	QPixmap symbolYesPix, symbolModPix, symbolNoPix;
-	QPixmap choiceYesPix, choiceNoPix, menuPix, menuInvPix;
+	QPixmap choiceYesPix, choiceNoPix;
+	QPixmap menuPix, menuInvPix, menuBackPix;
 
 	bool showAll, showName, showRange, showData;
 	enum listMode mode;
@@ -121,12 +125,17 @@
 	typedef class QListViewItem Parent;
 public:
 	ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
-	: Parent(parent, after), menu(m), visible(v)
+	: Parent(parent, after), menu(m), visible(v), goParent(false)
 	{
 		init();
 	}
 	ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
-	: Parent(parent, after), menu(m), visible(v)
+	: Parent(parent, after), menu(m), visible(v), goParent(false)
+	{
+		init();
+	}
+	ConfigItem(QListView *parent, ConfigItem *after, bool v)
+	: Parent(parent, after), menu(0), visible(v), goParent(true)
 	{
 		init();
 	}
@@ -136,7 +145,7 @@
 	void okRename(int col);
 #endif
 	void updateMenu(void);
-	bool updateNeeded(void);
+	void testUpdateMenu(bool v);
 	ConfigList* listView() const
 	{
 		return (ConfigList*)Parent::listView();
@@ -170,6 +179,7 @@
 	ConfigItem* nextItem;
 	struct menu *menu;
 	bool visible;
+	bool goParent;
 };
 
 class ConfigLineEdit : public QLineEdit {
@@ -216,7 +226,9 @@
 protected:
 	void closeEvent(QCloseEvent *e);
 
+	ConfigView *menuView;
 	ConfigList *menuList;
+	ConfigView *configView;
 	ConfigList *configList;
 	QTextView *helpText;
 	QToolBar *toolBar;
diff -Nru a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
--- a/scripts/kconfig/symbol.c	Sat Dec  7 20:14:02 2002
+++ b/scripts/kconfig/symbol.c	Sat Mar 15 09:25:55 2003
@@ -160,6 +160,9 @@
 	struct symbol *def_sym;
 	struct expr *e;
 
+	if (!sym)
+		return;
+
 	if (sym->flags & SYMBOL_VALID)
 		return;
 
diff -Nru a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
--- a/scripts/kconfig/zconf.l	Mon Dec  9 12:30:46 2002
+++ b/scripts/kconfig/zconf.l	Sat Mar 15 09:25:55 2003
@@ -96,6 +96,7 @@
 	"endchoice"		BEGIN(PARAM); return T_ENDCHOICE;
 	"comment"		BEGIN(PARAM); return T_COMMENT;
 	"config"		BEGIN(PARAM); return T_CONFIG;
+	"menuconfig"		BEGIN(PARAM); return T_MENUCONFIG;
 	"help"			BEGIN(PARAM); return T_HELP;
 	"if"			BEGIN(PARAM); return T_IF;
 	"endif"			BEGIN(PARAM); return T_ENDIF;
@@ -141,6 +142,7 @@
 		zconflval.string = text;
 		return T_WORD;
 	}
+	#.*	/* comment */
 	\\\n	current_file->lineno++;
 	.
 	<<EOF>> {
@@ -208,7 +210,7 @@
 		}
 		
 	}
-	\n/[^ \t\n] {
+	[ \t]*\n/[^ \t\n] {
 		current_file->lineno++;
 		zconf_endhelp();
 		return T_HELPTEXT;
diff -Nru a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
--- a/scripts/kconfig/zconf.tab.c_shipped	Mon Dec  9 12:30:46 2002
+++ b/scripts/kconfig/zconf.tab.c_shipped	Sat Mar 15 09:25:56 2003
@@ -1,7 +1,7 @@
-/* A Bison parser, made from zconf.y, by GNU bison 1.75.  */
+/* A Bison parser, made by GNU Bison 1.875a.  */
 
 /* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
    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
@@ -34,10 +34,13 @@
    USER NAME SPACE" below.  */
 
 /* Identify Bison output.  */
-#define YYBISON	1
+#define YYBISON 1
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
 
 /* Pure parsers.  */
-#define YYPURE	0
+#define YYPURE 0
 
 /* Using locations.  */
 #define YYLSP_NEEDED 0
@@ -67,32 +70,33 @@
      T_ENDCHOICE = 263,
      T_COMMENT = 264,
      T_CONFIG = 265,
-     T_HELP = 266,
-     T_HELPTEXT = 267,
-     T_IF = 268,
-     T_ENDIF = 269,
-     T_DEPENDS = 270,
-     T_REQUIRES = 271,
-     T_OPTIONAL = 272,
-     T_PROMPT = 273,
-     T_DEFAULT = 274,
-     T_TRISTATE = 275,
-     T_BOOLEAN = 276,
-     T_STRING = 277,
-     T_INT = 278,
-     T_HEX = 279,
-     T_WORD = 280,
-     T_WORD_QUOTE = 281,
-     T_UNEQUAL = 282,
-     T_EOF = 283,
-     T_EOL = 284,
-     T_CLOSE_PAREN = 285,
-     T_OPEN_PAREN = 286,
-     T_ON = 287,
-     T_OR = 288,
-     T_AND = 289,
-     T_EQUAL = 290,
-     T_NOT = 291
+     T_MENUCONFIG = 266,
+     T_HELP = 267,
+     T_HELPTEXT = 268,
+     T_IF = 269,
+     T_ENDIF = 270,
+     T_DEPENDS = 271,
+     T_REQUIRES = 272,
+     T_OPTIONAL = 273,
+     T_PROMPT = 274,
+     T_DEFAULT = 275,
+     T_TRISTATE = 276,
+     T_BOOLEAN = 277,
+     T_STRING = 278,
+     T_INT = 279,
+     T_HEX = 280,
+     T_WORD = 281,
+     T_WORD_QUOTE = 282,
+     T_UNEQUAL = 283,
+     T_EOF = 284,
+     T_EOL = 285,
+     T_CLOSE_PAREN = 286,
+     T_OPEN_PAREN = 287,
+     T_ON = 288,
+     T_OR = 289,
+     T_AND = 290,
+     T_EQUAL = 291,
+     T_NOT = 292
    };
 #endif
 #define T_MAINMENU 258
@@ -103,38 +107,40 @@
 #define T_ENDCHOICE 263
 #define T_COMMENT 264
 #define T_CONFIG 265
-#define T_HELP 266
-#define T_HELPTEXT 267
-#define T_IF 268
-#define T_ENDIF 269
-#define T_DEPENDS 270
-#define T_REQUIRES 271
-#define T_OPTIONAL 272
-#define T_PROMPT 273
-#define T_DEFAULT 274
-#define T_TRISTATE 275
-#define T_BOOLEAN 276
-#define T_STRING 277
-#define T_INT 278
-#define T_HEX 279
-#define T_WORD 280
-#define T_WORD_QUOTE 281
-#define T_UNEQUAL 282
-#define T_EOF 283
-#define T_EOL 284
-#define T_CLOSE_PAREN 285
-#define T_OPEN_PAREN 286
-#define T_ON 287
-#define T_OR 288
-#define T_AND 289
-#define T_EQUAL 290
-#define T_NOT 291
+#define T_MENUCONFIG 266
+#define T_HELP 267
+#define T_HELPTEXT 268
+#define T_IF 269
+#define T_ENDIF 270
+#define T_DEPENDS 271
+#define T_REQUIRES 272
+#define T_OPTIONAL 273
+#define T_PROMPT 274
+#define T_DEFAULT 275
+#define T_TRISTATE 276
+#define T_BOOLEAN 277
+#define T_STRING 278
+#define T_INT 279
+#define T_HEX 280
+#define T_WORD 281
+#define T_WORD_QUOTE 282
+#define T_UNEQUAL 283
+#define T_EOF 284
+#define T_EOL 285
+#define T_CLOSE_PAREN 286
+#define T_OPEN_PAREN 287
+#define T_ON 288
+#define T_OR 289
+#define T_AND 290
+#define T_EQUAL 291
+#define T_NOT 292
 
 
 
 
 /* Copy the first part of user declarations.  */
 
+
 /*
  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  * Released under the terms of the GNU GPL v2.0.
@@ -166,7 +172,7 @@
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG 0
+# define YYDEBUG 1
 #endif
 
 /* Enabling verbose error messages.  */
@@ -177,41 +183,33 @@
 # define YYERROR_VERBOSE 0
 #endif
 
-#ifndef YYSTYPE
-#line 33 "zconf.y"
-typedef union {
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+
+typedef union YYSTYPE {
 	int token;
 	char *string;
 	struct symbol *symbol;
 	struct expr *expr;
 	struct menu *menu;
-} yystype;
-/* Line 193 of /usr/share/bison/yacc.c.  */
-#line 191 "zconf.tab.c"
-# define YYSTYPE yystype
+} YYSTYPE;
+/* Line 191 of yacc.c.  */
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
 # define YYSTYPE_IS_TRIVIAL 1
 #endif
 
-#ifndef YYLTYPE
-typedef struct yyltype
-{
-  int first_line;
-  int first_column;
-  int last_line;
-  int last_column;
-} yyltype;
-# define YYLTYPE yyltype
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
+
 
 /* Copy the second part of user declarations.  */
 
+
 #define LKC_DIRECT_LINK
 #include "lkc.h"
 
 
-/* Line 213 of /usr/share/bison/yacc.c.  */
-#line 215 "zconf.tab.c"
+/* Line 214 of yacc.c.  */
+
 
 #if ! defined (yyoverflow) || YYERROR_VERBOSE
 
@@ -247,7 +245,7 @@
 
 #if (! defined (yyoverflow) \
      && (! defined (__cplusplus) \
-	 || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+	 || (YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
@@ -257,13 +255,13 @@
   };
 
 /* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
 
 /* The size of an array large to enough to hold all stacks, each with
    N elements.  */
 # define YYSTACK_BYTES(N) \
      ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
-      + YYSTACK_GAP_MAX)
+      + YYSTACK_GAP_MAXIMUM)
 
 /* Copy COUNT objects from FROM to TO.  The source and destination do
    not overlap.  */
@@ -277,7 +275,7 @@
 	{					\
 	  register YYSIZE_T yyi;		\
 	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];	\
+	    (To)[yyi] = (From)[yyi];		\
 	}					\
       while (0)
 #  endif
@@ -294,7 +292,7 @@
 	YYSIZE_T yynewbytes;						\
 	YYCOPY (&yyptr->Stack, Stack, yysize);				\
 	Stack = &yyptr->Stack;						\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;	\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
 	yyptr += yynewbytes / sizeof (*yyptr);				\
       }									\
     while (0)
@@ -309,23 +307,24 @@
 
 /* YYFINAL -- State number of the termination state. */
 #define YYFINAL  2
-#define YYLAST   154
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   160
 
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  37
+#define YYNTOKENS  38
 /* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  39
+#define YYNNTS  41
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  96
+#define YYNRULES  99
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  146
+#define YYNSTATES  152
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   291
+#define YYMAXUTOK   292
 
-#define YYTRANSLATE(X) \
-  ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK)
+#define YYTRANSLATE(YYX) 						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
 static const unsigned char yytranslate[] =
@@ -359,7 +358,7 @@
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36
+      35,    36,    37
 };
 
 #if YYDEBUG
@@ -368,63 +367,64 @@
 static const unsigned short yyprhs[] =
 {
        0,     0,     3,     4,     7,     9,    11,    13,    17,    19,
-      21,    23,    26,    28,    30,    32,    34,    36,    39,    43,
-      44,    48,    52,    55,    58,    61,    64,    67,    70,    73,
-      77,    81,    83,    87,    89,    94,    97,    98,   102,   106,
-     109,   112,   116,   118,   122,   123,   126,   129,   131,   137,
-     141,   142,   145,   148,   151,   154,   158,   160,   165,   168,
-     169,   172,   175,   178,   182,   185,   188,   191,   195,   198,
-     201,   202,   206,   209,   213,   216,   219,   220,   222,   226,
-     228,   230,   232,   234,   236,   238,   240,   241,   244,   246,
-     250,   254,   258,   261,   265,   269,   271
+      21,    23,    26,    28,    30,    32,    34,    36,    38,    41,
+      45,    48,    52,    53,    57,    61,    64,    67,    70,    73,
+      76,    79,    82,    86,    90,    92,    96,    98,   103,   106,
+     107,   111,   115,   118,   121,   125,   127,   131,   132,   135,
+     138,   140,   146,   150,   151,   154,   157,   160,   163,   167,
+     169,   174,   177,   178,   181,   184,   187,   191,   194,   197,
+     200,   204,   207,   210,   211,   215,   218,   222,   225,   228,
+     229,   231,   235,   237,   239,   241,   243,   245,   247,   249,
+     250,   253,   255,   259,   263,   267,   270,   274,   278,   280
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
 static const yysigned_char yyrhs[] =
 {
-      38,     0,    -1,    -1,    38,    39,    -1,    40,    -1,    48,
-      -1,    59,    -1,     3,    70,    72,    -1,     5,    -1,    14,
-      -1,     8,    -1,     1,    72,    -1,    54,    -1,    64,    -1,
-      42,    -1,    62,    -1,    72,    -1,    10,    25,    -1,    41,
-      29,    43,    -1,    -1,    43,    44,    29,    -1,    43,    68,
-      29,    -1,    43,    66,    -1,    43,    29,    -1,    20,    69,
-      -1,    21,    69,    -1,    23,    69,    -1,    24,    69,    -1,
-      22,    69,    -1,    18,    70,    73,    -1,    19,    75,    73,
-      -1,     7,    -1,    45,    29,    49,    -1,    71,    -1,    46,
-      51,    47,    29,    -1,    46,    51,    -1,    -1,    49,    50,
-      29,    -1,    49,    68,    29,    -1,    49,    66,    -1,    49,
-      29,    -1,    18,    70,    73,    -1,    17,    -1,    19,    75,
-      73,    -1,    -1,    51,    40,    -1,    13,    74,    -1,    71,
-      -1,    52,    29,    55,    53,    29,    -1,    52,    29,    55,
-      -1,    -1,    55,    40,    -1,    55,    59,    -1,    55,    48,
-      -1,     4,    70,    -1,    56,    29,    67,    -1,    71,    -1,
-      57,    60,    58,    29,    -1,    57,    60,    -1,    -1,    60,
-      40,    -1,    60,    59,    -1,    60,    48,    -1,    60,     1,
-      29,    -1,     6,    70,    -1,    61,    29,    -1,     9,    70,
-      -1,    63,    29,    67,    -1,    11,    29,    -1,    65,    12,
-      -1,    -1,    67,    68,    29,    -1,    67,    29,    -1,    15,
-      32,    74,    -1,    15,    74,    -1,    16,    74,    -1,    -1,
-      70,    -1,    70,    13,    74,    -1,    25,    -1,    26,    -1,
-       5,    -1,     8,    -1,    14,    -1,    29,    -1,    28,    -1,
-      -1,    13,    74,    -1,    75,    -1,    75,    35,    75,    -1,
-      75,    27,    75,    -1,    31,    74,    30,    -1,    36,    74,
-      -1,    74,    33,    74,    -1,    74,    34,    74,    -1,    25,
-      -1,    26,    -1
+      39,     0,    -1,    -1,    39,    40,    -1,    41,    -1,    51,
+      -1,    62,    -1,     3,    73,    75,    -1,     5,    -1,    15,
+      -1,     8,    -1,     1,    75,    -1,    57,    -1,    67,    -1,
+      43,    -1,    45,    -1,    65,    -1,    75,    -1,    10,    26,
+      -1,    42,    30,    46,    -1,    11,    26,    -1,    44,    30,
+      46,    -1,    -1,    46,    47,    30,    -1,    46,    71,    30,
+      -1,    46,    69,    -1,    46,    30,    -1,    21,    72,    -1,
+      22,    72,    -1,    24,    72,    -1,    25,    72,    -1,    23,
+      72,    -1,    19,    73,    76,    -1,    20,    78,    76,    -1,
+       7,    -1,    48,    30,    52,    -1,    74,    -1,    49,    54,
+      50,    30,    -1,    49,    54,    -1,    -1,    52,    53,    30,
+      -1,    52,    71,    30,    -1,    52,    69,    -1,    52,    30,
+      -1,    19,    73,    76,    -1,    18,    -1,    20,    78,    76,
+      -1,    -1,    54,    41,    -1,    14,    77,    -1,    74,    -1,
+      55,    30,    58,    56,    30,    -1,    55,    30,    58,    -1,
+      -1,    58,    41,    -1,    58,    62,    -1,    58,    51,    -1,
+       4,    73,    -1,    59,    30,    70,    -1,    74,    -1,    60,
+      63,    61,    30,    -1,    60,    63,    -1,    -1,    63,    41,
+      -1,    63,    62,    -1,    63,    51,    -1,    63,     1,    30,
+      -1,     6,    73,    -1,    64,    30,    -1,     9,    73,    -1,
+      66,    30,    70,    -1,    12,    30,    -1,    68,    13,    -1,
+      -1,    70,    71,    30,    -1,    70,    30,    -1,    16,    33,
+      77,    -1,    16,    77,    -1,    17,    77,    -1,    -1,    73,
+      -1,    73,    14,    77,    -1,    26,    -1,    27,    -1,     5,
+      -1,     8,    -1,    15,    -1,    30,    -1,    29,    -1,    -1,
+      14,    77,    -1,    78,    -1,    78,    36,    78,    -1,    78,
+      28,    78,    -1,    32,    77,    31,    -1,    37,    77,    -1,
+      77,    34,    77,    -1,    77,    35,    77,    -1,    26,    -1,
+      27,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const unsigned short yyrline[] =
 {
-       0,    89,    89,    90,    93,    94,    95,    96,    97,    98,
-      99,   100,   103,   105,   106,   107,   108,   114,   122,   128,
-     130,   131,   132,   133,   136,   142,   148,   154,   160,   166,
-     172,   180,   189,   195,   203,   205,   211,   213,   214,   215,
-     216,   219,   225,   231,   237,   239,   244,   253,   261,   263,
-     269,   271,   272,   273,   278,   285,   291,   299,   301,   307,
-     309,   310,   311,   312,   315,   321,   328,   335,   342,   348,
-     355,   356,   357,   360,   365,   370,   378,   380,   384,   389,
-     390,   393,   394,   395,   398,   399,   401,   402,   405,   406,
-     407,   408,   409,   410,   411,   414,   415
+       0,    90,    90,    91,    94,    95,    96,    97,    98,    99,
+     100,   101,   105,   106,   107,   108,   109,   110,   116,   124,
+     130,   138,   148,   150,   151,   152,   153,   156,   162,   168,
+     174,   180,   186,   192,   200,   209,   215,   224,   225,   231,
+     233,   234,   235,   236,   239,   245,   251,   257,   259,   264,
+     273,   282,   283,   289,   291,   292,   293,   298,   305,   311,
+     320,   321,   327,   329,   330,   331,   332,   335,   341,   348,
+     355,   362,   368,   375,   376,   377,   380,   385,   390,   398,
+     400,   404,   409,   410,   413,   414,   415,   419,   419,   421,
+     422,   425,   426,   427,   428,   429,   430,   431,   434,   435
 };
 #endif
 
@@ -435,19 +435,19 @@
 {
   "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", 
   "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", 
-  "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", "T_REQUIRES", 
-  "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", "T_BOOLEAN", 
-  "T_STRING", "T_INT", "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", 
-  "T_EOF", "T_EOL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_OR", 
-  "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", 
+  "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", 
+  "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", 
+  "T_BOOLEAN", "T_STRING", "T_INT", "T_HEX", "T_WORD", "T_WORD_QUOTE", 
+  "T_UNEQUAL", "T_EOF", "T_EOL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", 
+  "T_OR", "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", 
   "common_block", "config_entry_start", "config_stmt", 
-  "config_option_list", "config_option", "choice", "choice_entry", 
-  "choice_end", "choice_stmt", "choice_option_list", "choice_option", 
-  "choice_block", "if", "if_end", "if_stmt", "if_block", "menu", 
-  "menu_entry", "menu_end", "menu_stmt", "menu_block", "source", 
-  "source_stmt", "comment", "comment_stmt", "help_start", "help", 
-  "depends_list", "depends", "prompt_stmt_opt", "prompt", "end", 
-  "nl_or_eof", "if_expr", "expr", "symbol", 0
+  "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", 
+  "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", 
+  "choice_option_list", "choice_option", "choice_block", "if", "if_end", 
+  "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt", 
+  "menu_block", "source", "source_stmt", "comment", "comment_stmt", 
+  "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", 
+  "prompt", "end", "nl_or_eof", "if_expr", "expr", "symbol", 0
 };
 #endif
 
@@ -459,38 +459,38 @@
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291
+     285,   286,   287,   288,   289,   290,   291,   292
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const unsigned char yyr1[] =
 {
-       0,    37,    38,    38,    39,    39,    39,    39,    39,    39,
-      39,    39,    40,    40,    40,    40,    40,    41,    42,    43,
-      43,    43,    43,    43,    44,    44,    44,    44,    44,    44,
-      44,    45,    46,    47,    48,    48,    49,    49,    49,    49,
-      49,    50,    50,    50,    51,    51,    52,    53,    54,    54,
-      55,    55,    55,    55,    56,    57,    58,    59,    59,    60,
-      60,    60,    60,    60,    61,    62,    63,    64,    65,    66,
-      67,    67,    67,    68,    68,    68,    69,    69,    69,    70,
-      70,    71,    71,    71,    72,    72,    73,    73,    74,    74,
-      74,    74,    74,    74,    74,    75,    75
+       0,    38,    39,    39,    40,    40,    40,    40,    40,    40,
+      40,    40,    41,    41,    41,    41,    41,    41,    42,    43,
+      44,    45,    46,    46,    46,    46,    46,    47,    47,    47,
+      47,    47,    47,    47,    48,    49,    50,    51,    51,    52,
+      52,    52,    52,    52,    53,    53,    53,    54,    54,    55,
+      56,    57,    57,    58,    58,    58,    58,    59,    60,    61,
+      62,    62,    63,    63,    63,    63,    63,    64,    65,    66,
+      67,    68,    69,    70,    70,    70,    71,    71,    71,    72,
+      72,    72,    73,    73,    74,    74,    74,    75,    75,    76,
+      76,    77,    77,    77,    77,    77,    77,    77,    78,    78
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const unsigned char yyr2[] =
 {
        0,     2,     0,     2,     1,     1,     1,     3,     1,     1,
-       1,     2,     1,     1,     1,     1,     1,     2,     3,     0,
-       3,     3,     2,     2,     2,     2,     2,     2,     2,     3,
-       3,     1,     3,     1,     4,     2,     0,     3,     3,     2,
-       2,     3,     1,     3,     0,     2,     2,     1,     5,     3,
-       0,     2,     2,     2,     2,     3,     1,     4,     2,     0,
-       2,     2,     2,     3,     2,     2,     2,     3,     2,     2,
-       0,     3,     2,     3,     2,     2,     0,     1,     3,     1,
-       1,     1,     1,     1,     1,     1,     0,     2,     1,     3,
-       3,     3,     2,     3,     3,     1,     1
+       1,     2,     1,     1,     1,     1,     1,     1,     2,     3,
+       2,     3,     0,     3,     3,     2,     2,     2,     2,     2,
+       2,     2,     3,     3,     1,     3,     1,     4,     2,     0,
+       3,     3,     2,     2,     3,     1,     3,     0,     2,     2,
+       1,     5,     3,     0,     2,     2,     2,     2,     3,     1,
+       4,     2,     0,     2,     2,     2,     3,     2,     2,     2,
+       3,     2,     2,     0,     3,     2,     3,     2,     2,     0,
+       1,     3,     1,     1,     1,     1,     1,     1,     1,     0,
+       2,     1,     3,     3,     3,     2,     3,     3,     1,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -498,127 +498,134 @@
    means the default is an error.  */
 static const unsigned char yydefact[] =
 {
-       2,     0,     1,     0,     0,     0,     8,     0,    31,    10,
-       0,     0,     0,     9,    85,    84,     3,     4,     0,    14,
-       0,    44,     5,     0,    12,     0,    59,     6,     0,    15,
-       0,    13,    16,    11,    79,    80,     0,    54,    64,    66,
-      17,    95,    96,     0,     0,    46,    88,    19,    36,    35,
-      50,    70,     0,    65,    70,     7,     0,    92,     0,     0,
-       0,     0,    18,    32,    81,    82,    83,    45,     0,    33,
-      49,    55,     0,    60,    62,     0,    61,    56,    67,    91,
-      93,    94,    90,    89,     0,     0,     0,     0,     0,    76,
-      76,    76,    76,    76,    23,     0,     0,    22,     0,    42,
-       0,     0,    40,     0,    39,     0,    34,    51,    53,     0,
-      52,    47,    72,     0,    63,    57,    68,     0,    74,    75,
-      86,    86,    24,    77,    25,    28,    26,    27,    20,    69,
-      21,    86,    86,    37,    38,    48,    71,    73,     0,    29,
-      30,     0,    41,    43,    87,    78
+       2,     0,     1,     0,     0,     0,     8,     0,    34,    10,
+       0,     0,     0,     0,     9,    88,    87,     3,     4,     0,
+      14,     0,    15,     0,    47,     5,     0,    12,     0,    62,
+       6,     0,    16,     0,    13,    17,    11,    82,    83,     0,
+      57,    67,    69,    18,    20,    98,    99,     0,     0,    49,
+      91,    22,    22,    39,    38,    53,    73,     0,    68,    73,
+       7,     0,    95,     0,     0,     0,     0,    19,    21,    35,
+      84,    85,    86,    48,     0,    36,    52,    58,     0,    63,
+      65,     0,    64,    59,    70,    94,    96,    97,    93,    92,
+       0,     0,     0,     0,     0,    79,    79,    79,    79,    79,
+      26,     0,     0,    25,     0,    45,     0,     0,    43,     0,
+      42,     0,    37,    54,    56,     0,    55,    50,    75,     0,
+      66,    60,    71,     0,    77,    78,    89,    89,    27,    80,
+      28,    31,    29,    30,    23,    72,    24,    89,    89,    40,
+      41,    51,    74,    76,     0,    32,    33,     0,    44,    46,
+      90,    81
 };
 
 /* YYDEFGOTO[NTERM-NUM]. */
 static const short yydefgoto[] =
 {
-      -1,     1,    16,    17,    18,    19,    62,    95,    20,    21,
-      68,    22,    63,   103,    49,    23,   109,    24,    70,    25,
-      26,    75,    27,    52,    28,    29,    30,    31,    96,    97,
-      71,   113,   122,   123,    69,    32,   139,    45,    46
+      -1,     1,    17,    18,    19,    20,    21,    22,    67,   101,
+      23,    24,    74,    25,    69,   109,    54,    26,   115,    27,
+      76,    28,    29,    81,    30,    57,    31,    32,    33,    34,
+     102,   103,    77,   104,   128,   129,    75,    35,   145,    49,
+      50
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -120
+#define YYPACT_NINF -121
 static const short yypact[] =
 {
-    -120,    17,  -120,    32,    71,    71,  -120,    71,  -120,  -120,
-      71,    11,    99,  -120,  -120,  -120,  -120,  -120,    12,  -120,
-      22,  -120,  -120,    35,  -120,    52,  -120,  -120,    56,  -120,
-      60,  -120,  -120,  -120,  -120,  -120,    32,  -120,  -120,  -120,
-    -120,  -120,  -120,    99,    99,    83,    38,  -120,  -120,    74,
-    -120,  -120,    49,  -120,  -120,  -120,    98,  -120,    99,    99,
-     101,   101,    89,   104,  -120,  -120,  -120,  -120,    65,  -120,
-      62,    77,    72,  -120,  -120,    85,  -120,  -120,    77,  -120,
-      95,  -120,  -120,  -120,   105,     8,    99,    71,   101,    71,
-      71,    71,    71,    71,  -120,   113,   131,  -120,   115,  -120,
-      71,   101,  -120,   116,  -120,   117,  -120,  -120,  -120,   118,
-    -120,  -120,  -120,   119,  -120,  -120,  -120,    99,    83,    83,
-     136,   136,  -120,   137,  -120,  -120,  -120,  -120,  -120,  -120,
-    -120,   136,   136,  -120,  -120,  -120,  -120,    83,    99,  -120,
-    -120,    99,  -120,  -120,    83,    83
+    -121,    25,  -121,   -18,   -11,   -11,  -121,   -11,  -121,  -121,
+     -11,    21,    27,   112,  -121,  -121,  -121,  -121,  -121,    51,
+    -121,    54,  -121,    57,  -121,  -121,    58,  -121,    62,  -121,
+    -121,    80,  -121,    96,  -121,  -121,  -121,  -121,  -121,   -18,
+    -121,  -121,  -121,  -121,  -121,  -121,  -121,   112,   112,    17,
+      77,  -121,  -121,  -121,    85,  -121,  -121,    56,  -121,  -121,
+    -121,   -21,  -121,   112,   112,    42,    42,   100,   100,   115,
+    -121,  -121,  -121,  -121,    98,  -121,    68,    28,    99,  -121,
+    -121,   111,  -121,  -121,    28,  -121,   105,  -121,  -121,  -121,
+     116,   110,   112,   -11,    42,   -11,   -11,   -11,   -11,   -11,
+    -121,   118,   137,  -121,   121,  -121,   -11,    42,  -121,   122,
+    -121,   123,  -121,  -121,  -121,   124,  -121,  -121,  -121,   125,
+    -121,  -121,  -121,   112,    17,    17,   142,   142,  -121,   143,
+    -121,  -121,  -121,  -121,  -121,  -121,  -121,   142,   142,  -121,
+    -121,  -121,  -121,    17,   112,  -121,  -121,   112,  -121,  -121,
+      17,    17
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yysigned_char yypgoto[] =
 {
-    -120,  -120,  -120,   -38,  -120,  -120,  -120,  -120,  -120,  -120,
-    -120,   -42,  -120,  -120,  -120,  -120,  -120,  -120,  -120,  -120,
-    -120,  -120,   -33,  -120,  -120,  -120,  -120,  -120,  -120,    88,
-     100,    78,    46,    -1,   -23,     2,  -119,   -43,   -53
+    -121,  -121,  -121,   -35,  -121,  -121,  -121,  -121,   106,  -121,
+    -121,  -121,  -121,   -34,  -121,  -121,  -121,  -121,  -121,  -121,
+    -121,  -121,  -121,  -121,   -33,  -121,  -121,  -121,  -121,  -121,
+    -121,    90,   101,    34,    10,    -4,   -30,    -1,  -120,   -43,
+     -57
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, parse error.  */
-#define YYTABLE_NINF -59
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -62
 static const short yytable[] =
 {
-      56,    57,   140,    36,    37,    33,    38,    82,    83,    39,
-      74,    67,   142,   143,    73,    80,    81,     2,     3,    76,
-       4,     5,     6,     7,     8,     9,    10,    11,   108,    77,
-      12,    13,   107,    41,    42,   121,    40,   110,    55,    43,
-     117,    47,   118,   119,    44,    14,    15,   111,   132,   -58,
-      72,    48,   -58,     5,    64,     7,     8,    65,    10,    11,
-      14,    15,    12,    66,    50,    60,     5,    64,     7,     8,
-      65,    10,    11,    61,   137,    12,    66,    14,    15,    64,
-       7,    51,    65,    10,    11,    53,   120,    12,    66,    54,
-      14,    15,    85,    86,   106,   144,    34,    35,   145,   131,
-      84,   114,    14,    15,    85,    86,   112,    87,    88,    89,
-      90,    91,    92,    93,   115,    84,    58,    59,    94,    85,
-      86,    99,   100,   101,    41,    42,    41,    42,    79,    59,
-      43,    58,    59,   102,   116,    44,   124,   125,   126,   127,
-      98,   105,   128,   129,   130,   133,   134,   135,   136,   138,
-     141,   104,     0,     0,    78
+      39,    40,    36,    41,    61,    62,    42,   146,    88,    89,
+      85,    15,    16,    63,    64,    37,    38,   148,   149,    73,
+      86,    87,    79,    80,    82,     2,     3,    83,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,   127,    60,    13,
+      14,   113,   114,   116,    91,    92,   117,    43,   124,   125,
+     138,    63,    64,    44,    15,    16,   -61,    78,   118,   -61,
+       5,    70,     7,     8,    71,    10,    11,    12,    45,    46,
+      13,    72,     5,    70,     7,     8,    71,    10,    11,    12,
+     143,    51,    13,    72,    52,    15,    16,    53,    55,   126,
+      70,     7,    56,    71,    10,    11,    12,    15,    16,    13,
+      72,   150,   137,   111,   151,    65,   130,   131,   132,   133,
+      58,   119,    90,    66,    15,    16,    91,    92,   119,    93,
+      94,    95,    96,    97,    98,    99,    59,    90,   112,   120,
+     100,    91,    92,   105,   106,   107,    45,    46,    45,    46,
+      64,   121,    47,   123,    47,   108,   122,    48,   134,    48,
+     135,   136,   139,   140,   141,   142,   144,   147,    68,   110,
+      84
 };
 
-static const short yycheck[] =
+static const unsigned char yycheck[] =
 {
-      43,    44,   121,     4,     5,     3,     7,    60,    61,    10,
-      52,    49,   131,   132,    52,    58,    59,     0,     1,    52,
-       3,     4,     5,     6,     7,     8,     9,    10,    70,    52,
-      13,    14,    70,    25,    26,    88,    25,    70,    36,    31,
-      32,    29,    85,    86,    36,    28,    29,    70,   101,     0,
-       1,    29,     3,     4,     5,     6,     7,     8,     9,    10,
-      28,    29,    13,    14,    29,    27,     4,     5,     6,     7,
-       8,     9,    10,    35,   117,    13,    14,    28,    29,     5,
-       6,    29,     8,     9,    10,    29,    87,    13,    14,    29,
-      28,    29,    15,    16,    29,   138,    25,    26,   141,   100,
-      11,    29,    28,    29,    15,    16,    29,    18,    19,    20,
-      21,    22,    23,    24,    29,    11,    33,    34,    29,    15,
-      16,    17,    18,    19,    25,    26,    25,    26,    30,    34,
-      31,    33,    34,    29,    29,    36,    90,    91,    92,    93,
-      62,    63,    29,    12,    29,    29,    29,    29,    29,    13,
-      13,    63,    -1,    -1,    54
+       4,     5,     3,     7,    47,    48,    10,   127,    65,    66,
+      31,    29,    30,    34,    35,    26,    27,   137,   138,    54,
+      63,    64,    57,    57,    57,     0,     1,    57,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    94,    39,    14,
+      15,    76,    76,    76,    16,    17,    76,    26,    91,    92,
+     107,    34,    35,    26,    29,    30,     0,     1,    30,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    26,    27,
+      14,    15,     4,     5,     6,     7,     8,     9,    10,    11,
+     123,    30,    14,    15,    30,    29,    30,    30,    30,    93,
+       5,     6,    30,     8,     9,    10,    11,    29,    30,    14,
+      15,   144,   106,    69,   147,    28,    96,    97,    98,    99,
+      30,    77,    12,    36,    29,    30,    16,    17,    84,    19,
+      20,    21,    22,    23,    24,    25,    30,    12,    30,    30,
+      30,    16,    17,    18,    19,    20,    26,    27,    26,    27,
+      35,    30,    32,    33,    32,    30,    30,    37,    30,    37,
+      13,    30,    30,    30,    30,    30,    14,    14,    52,    69,
+      59
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const unsigned char yystos[] =
 {
-       0,    38,     0,     1,     3,     4,     5,     6,     7,     8,
-       9,    10,    13,    14,    28,    29,    39,    40,    41,    42,
-      45,    46,    48,    52,    54,    56,    57,    59,    61,    62,
-      63,    64,    72,    72,    25,    26,    70,    70,    70,    70,
-      25,    25,    26,    31,    36,    74,    75,    29,    29,    51,
-      29,    29,    60,    29,    29,    72,    74,    74,    33,    34,
-      27,    35,    43,    49,     5,     8,    14,    40,    47,    71,
-      55,    67,     1,    40,    48,    58,    59,    71,    67,    30,
-      74,    74,    75,    75,    11,    15,    16,    18,    19,    20,
-      21,    22,    23,    24,    29,    44,    65,    66,    68,    17,
-      18,    19,    29,    50,    66,    68,    29,    40,    48,    53,
-      59,    71,    29,    68,    29,    29,    29,    32,    74,    74,
-      70,    75,    69,    70,    69,    69,    69,    69,    29,    12,
-      29,    70,    75,    29,    29,    29,    29,    74,    13,    73,
-      73,    13,    73,    73,    74,    74
+       0,    39,     0,     1,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    14,    15,    29,    30,    40,    41,    42,
+      43,    44,    45,    48,    49,    51,    55,    57,    59,    60,
+      62,    64,    65,    66,    67,    75,    75,    26,    27,    73,
+      73,    73,    73,    26,    26,    26,    27,    32,    37,    77,
+      78,    30,    30,    30,    54,    30,    30,    63,    30,    30,
+      75,    77,    77,    34,    35,    28,    36,    46,    46,    52,
+       5,     8,    15,    41,    50,    74,    58,    70,     1,    41,
+      51,    61,    62,    74,    70,    31,    77,    77,    78,    78,
+      12,    16,    17,    19,    20,    21,    22,    23,    24,    25,
+      30,    47,    68,    69,    71,    18,    19,    20,    30,    53,
+      69,    71,    30,    41,    51,    56,    62,    74,    30,    71,
+      30,    30,    30,    33,    77,    77,    73,    78,    72,    73,
+      72,    72,    72,    72,    30,    13,    30,    73,    78,    30,
+      30,    30,    30,    77,    14,    76,    76,    14,    76,    76,
+      77,    77
 };
 
 #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
@@ -639,13 +646,14 @@
 
 #define yyerrok		(yyerrstatus = 0)
 #define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		-2
+#define YYEMPTY		(-2)
 #define YYEOF		0
 
 #define YYACCEPT	goto yyacceptlab
 #define YYABORT		goto yyabortlab
 #define YYERROR		goto yyerrlab1
 
+
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
    Once GCC version 2 has supplanted version 1, this can go.  */
@@ -660,13 +668,13 @@
     {								\
       yychar = (Token);						\
       yylval = (Value);						\
-      yychar1 = YYTRANSLATE (yychar);				\
+      yytoken = YYTRANSLATE (yychar);				\
       YYPOPSTACK;						\
       goto yybackup;						\
     }								\
   else								\
     { 								\
-      yyerror ("syntax error: cannot back up");			\
+      yyerror ("syntax error: cannot back up");\
       YYERROR;							\
     }								\
 while (0)
@@ -678,7 +686,7 @@
    are run).  */
 
 #ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)           \
+# define YYLLOC_DEFAULT(Current, Rhs, N)         \
   Current.first_line   = Rhs[1].first_line;      \
   Current.first_column = Rhs[1].first_column;    \
   Current.last_line    = Rhs[N].last_line;       \
@@ -687,7 +695,11 @@
 
 /* YYLEX -- calling `yylex' with the right arguments.  */
 
-#define YYLEX	yylex ()
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
 
 /* Enable debugging if requested.  */
 #if YYDEBUG
@@ -702,19 +714,93 @@
   if (yydebug)					\
     YYFPRINTF Args;				\
 } while (0)
+
 # define YYDSYMPRINT(Args)			\
 do {						\
   if (yydebug)					\
     yysymprint Args;				\
 } while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location)		\
+do {								\
+  if (yydebug)							\
+    {								\
+      YYFPRINTF (stderr, "%s ", Title);				\
+      yysymprint (stderr, 					\
+                  Token, Value);	\
+      YYFPRINTF (stderr, "\n");					\
+    }								\
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (cinluded).                                                   |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short *bottom, short *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    short *bottom;
+    short *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (/* Nothing. */; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+    int yyrule;
+#endif
+{
+  int yyi;
+  unsigned int yylineno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+             yyrule - 1, yylineno);
+  /* Print the symbols being reduced, and their result.  */
+  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (Rule);		\
+} while (0)
+
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
 int yydebug;
 #else /* !YYDEBUG */
 # define YYDPRINTF(Args)
 # define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
 #endif /* !YYDEBUG */
 
+
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
 #ifndef	YYINITDEPTH
 # define YYINITDEPTH 200
@@ -793,95 +879,85 @@
 
 
 #if YYDEBUG
-/*-----------------------------.
-| Print this symbol on YYOUT.  |
-`-----------------------------*/
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
 
-static void
 #if defined (__STDC__) || defined (__cplusplus)
-yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
 #else
-yysymprint (yyout, yytype, yyvalue)
-    FILE* yyout;
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
     int yytype;
-    YYSTYPE yyvalue;
+    YYSTYPE *yyvaluep;
 #endif
 {
   /* Pacify ``unused variable'' warnings.  */
-  (void) yyvalue;
+  (void) yyvaluep;
 
   if (yytype < YYNTOKENS)
     {
-      YYFPRINTF (yyout, "token %s (", yytname[yytype]);
+      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
 # ifdef YYPRINT
-      YYPRINT (yyout, yytoknum[yytype], yyvalue);
+      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
 # endif
     }
   else
-    YYFPRINTF (yyout, "nterm %s (", yytname[yytype]);
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
   switch (yytype)
     {
       default:
         break;
     }
-  YYFPRINTF (yyout, ")");
+  YYFPRINTF (yyoutput, ")");
 }
-#endif /* YYDEBUG. */
-
 
+#endif /* ! YYDEBUG */
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-static void
 #if defined (__STDC__) || defined (__cplusplus)
-yydestruct (int yytype, YYSTYPE yyvalue)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
 #else
-yydestruct (yytype, yyvalue)
+static void
+yydestruct (yytype, yyvaluep)
     int yytype;
-    YYSTYPE yyvalue;
+    YYSTYPE *yyvaluep;
 #endif
 {
   /* Pacify ``unused variable'' warnings.  */
-  (void) yyvalue;
+  (void) yyvaluep;
 
   switch (yytype)
     {
+
       default:
         break;
     }
 }
-
 
 
-/* The user can define YYPARSE_PARAM as the name of an argument to be passed
-   into yyparse.  The argument should have type void *.
-   It should actually point to an object.
-   Grammar actions can access the variable by casting it
-   to the proper pointer type.  */
+/* Prevent warnings from -Wmissing-prototypes.  */
 
 #ifdef YYPARSE_PARAM
 # if defined (__STDC__) || defined (__cplusplus)
-#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
-#  define YYPARSE_PARAM_DECL
+int yyparse (void *YYPARSE_PARAM);
 # else
-#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
-#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+int yyparse ();
 # endif
-#else /* !YYPARSE_PARAM */
-# define YYPARSE_PARAM_ARG
-# define YYPARSE_PARAM_DECL
-#endif /* !YYPARSE_PARAM */
-
-/* Prevent warning if -Wstrict-prototypes.  */
-#ifdef __GNUC__
-# ifdef YYPARSE_PARAM
-int yyparse (void *);
-# else
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
 int yyparse (void);
-# endif
+#else
+int yyparse ();
 #endif
+#endif /* ! YYPARSE_PARAM */
+
 
 
 /* The lookahead symbol.  */
@@ -890,13 +966,32 @@
 /* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
 
-/* Number of parse errors so far.  */
+/* Number of syntax errors so far.  */
 int yynerrs;
 
 
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+  void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
 int
-yyparse (YYPARSE_PARAM_ARG)
-     YYPARSE_PARAM_DECL
+yyparse ()
+
+#endif
+#endif
 {
   
   register int yystate;
@@ -905,7 +1000,7 @@
   /* Number of tokens to shift before error messages enabled.  */
   int yyerrstatus;
   /* Lookahead token as an internal (translated) token number.  */
-  int yychar1 = 0;
+  int yytoken = 0;
 
   /* Three stacks and their tools:
      `yyss': related to states,
@@ -969,7 +1064,7 @@
  yysetstate:
   *yyssp = yystate;
 
-  if (yyssp >= yyss + yystacksize - 1)
+  if (yyss + yystacksize - 1 <= yyssp)
     {
       /* Get the current used size of the three stacks, in elements.  */
       YYSIZE_T yysize = yyssp - yyss + 1;
@@ -1001,10 +1096,10 @@
       goto yyoverflowlab;
 # else
       /* Extend the stack our own way.  */
-      if (yystacksize >= YYMAXDEPTH)
+      if (YYMAXDEPTH <= yystacksize)
 	goto yyoverflowlab;
       yystacksize *= 2;
-      if (yystacksize > YYMAXDEPTH)
+      if (YYMAXDEPTH < yystacksize)
 	yystacksize = YYMAXDEPTH;
 
       {
@@ -1030,7 +1125,7 @@
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
 		  (unsigned long int) yystacksize));
 
-      if (yyssp >= yyss + yystacksize - 1)
+      if (yyss + yystacksize - 1 <= yyssp)
 	YYABORT;
     }
 
@@ -1055,39 +1150,28 @@
 
   /* Not known => get a lookahead token if don't already have one.  */
 
-  /* yychar is either YYEMPTY or YYEOF
-     or a valid token in external form.  */
-
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
       yychar = YYLEX;
     }
 
-  /* Convert token to internal form (in yychar1) for indexing tables with.  */
-
-  if (yychar <= 0)		/* This means end of input.  */
+  if (yychar <= YYEOF)
     {
-      yychar1 = 0;
-      yychar = YYEOF;		/* Don't call YYLEX any more.  */
-
+      yychar = yytoken = YYEOF;
       YYDPRINTF ((stderr, "Now at end of input.\n"));
     }
   else
     {
-      yychar1 = YYTRANSLATE (yychar);
-
-      /* We have to keep this `#if YYDEBUG', since we use variables
-	 which are defined only if `YYDEBUG' is set.  */
-      YYDPRINTF ((stderr, "Next token is "));
-      YYDSYMPRINT ((stderr, yychar1, yylval));
-      YYDPRINTF ((stderr, "\n"));
+      yytoken = YYTRANSLATE (yychar);
+      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
     }
 
-  /* If the proper action on seeing token YYCHAR1 is to reduce or to
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
      detect an error, take that action.  */
-  yyn += yychar1;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1)
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
     goto yydefault;
   yyn = yytable[yyn];
   if (yyn <= 0)
@@ -1102,8 +1186,7 @@
     YYACCEPT;
 
   /* Shift the lookahead token.  */
-  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
-	      yychar, yytname[yychar1]));
+  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
 
   /* Discard the token being shifted unless it is eof.  */
   if (yychar != YYEOF)
@@ -1149,378 +1232,430 @@
   yyval = yyvsp[1-yylen];
 
 
-
-#if YYDEBUG
-  /* We have to keep this `#if YYDEBUG', since we use variables which
-     are defined only if `YYDEBUG' is set.  */
-  if (yydebug)
-    {
-      int yyi;
-
-      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
-		 yyn - 1, yyrline[yyn]);
-
-      /* Print the symbols being reduced, and their result.  */
-      for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++)
-	YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
-      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
-    }
-#endif
+  YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
         case 8:
-    { zconfprint("unexpected 'endmenu' statement"); }
+
+    { zconfprint("unexpected 'endmenu' statement"); ;}
     break;
 
   case 9:
-    { zconfprint("unexpected 'endif' statement"); }
+
+    { zconfprint("unexpected 'endif' statement"); ;}
     break;
 
   case 10:
-    { zconfprint("unexpected 'endchoice' statement"); }
+
+    { zconfprint("unexpected 'endchoice' statement"); ;}
     break;
 
   case 11:
-    { zconfprint("syntax error"); yyerrok; }
+
+    { zconfprint("syntax error"); yyerrok; ;}
     break;
 
-  case 17:
+  case 18:
+
     {
 	struct symbol *sym = sym_lookup(yyvsp[0].string, 0);
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
 	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[0].string);
-}
+;}
     break;
 
-  case 18:
+  case 19:
+
     {
 	menu_end_entry();
 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
-}
+;}
+    break;
+
+  case 20:
+
+    {
+	struct symbol *sym = sym_lookup(yyvsp[0].string, 0);
+	sym->flags |= SYMBOL_OPTIONAL;
+	menu_add_entry(sym);
+	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[0].string);
+;}
+    break;
+
+  case 21:
+
+    {
+	if (current_entry->prompt)
+		current_entry->prompt->type = P_MENU;
+	else
+		zconfprint("warning: menuconfig statement without prompt");
+	menu_end_entry();
+	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+;}
     break;
 
-  case 23:
-    { }
+  case 26:
+
+    { ;}
     break;
 
-  case 24:
+  case 27:
+
     {
 	menu_set_type(S_TRISTATE);
 	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 25:
+  case 28:
+
     {
 	menu_set_type(S_BOOLEAN);
 	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 26:
+  case 29:
+
     {
 	menu_set_type(S_INT);
 	printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 27:
+  case 30:
+
     {
 	menu_set_type(S_HEX);
 	printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 28:
+  case 31:
+
     {
 	menu_set_type(S_STRING);
 	printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 29:
+  case 32:
+
     {
 	menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr);
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 30:
+  case 33:
+
     {
 	menu_add_prop(P_DEFAULT, NULL, yyvsp[-1].symbol, yyvsp[0].expr);
 	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 31:
+  case 34:
+
     {
 	struct symbol *sym = sym_lookup(NULL, 0);
 	sym->flags |= SYMBOL_CHOICE;
 	menu_add_entry(sym);
 	menu_add_prop(P_CHOICE, NULL, NULL, NULL);
 	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 32:
+  case 35:
+
     {
 	menu_end_entry();
 	menu_add_menu();
-}
+;}
     break;
 
-  case 33:
+  case 36:
+
     {
 	if (zconf_endtoken(yyvsp[0].token, T_CHOICE, T_ENDCHOICE)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
 	}
-}
+;}
     break;
 
-  case 35:
+  case 38:
+
     {
 	printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
 	zconfnerrs++;
-}
+;}
     break;
 
-  case 41:
+  case 44:
+
     {
 	menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr);
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 42:
+  case 45:
+
     {
 	current_entry->sym->flags |= SYMBOL_OPTIONAL;
 	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 43:
+  case 46:
+
     {
 	menu_add_prop(P_DEFAULT, NULL, yyvsp[-1].symbol, yyvsp[0].expr);
 	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 46:
+  case 49:
+
     {
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 	menu_add_entry(NULL);
 	menu_add_dep(yyvsp[0].expr);
 	menu_end_entry();
 	menu_add_menu();
-}
+;}
     break;
 
-  case 47:
+  case 50:
+
     {
 	if (zconf_endtoken(yyvsp[0].token, T_IF, T_ENDIF)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
 	}
-}
+;}
     break;
 
-  case 49:
+  case 52:
+
     {
 	printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
 	zconfnerrs++;
-}
+;}
     break;
 
-  case 54:
+  case 57:
+
     {
 	menu_add_entry(NULL);
 	menu_add_prop(P_MENU, yyvsp[0].string, NULL, NULL);
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 55:
+  case 58:
+
     {
 	menu_end_entry();
 	menu_add_menu();
-}
+;}
     break;
 
-  case 56:
+  case 59:
+
     {
 	if (zconf_endtoken(yyvsp[0].token, T_MENU, T_ENDMENU)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
 	}
-}
+;}
     break;
 
-  case 58:
+  case 61:
+
     {
 	printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
 	zconfnerrs++;
-}
+;}
     break;
 
-  case 63:
-    { zconfprint("invalid menu option"); yyerrok; }
+  case 66:
+
+    { zconfprint("invalid menu option"); yyerrok; ;}
     break;
 
-  case 64:
+  case 67:
+
     {
 	yyval.string = yyvsp[0].string;
 	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[0].string);
-}
+;}
     break;
 
-  case 65:
+  case 68:
+
     {
 	zconf_nextfile(yyvsp[-1].string);
-}
+;}
     break;
 
-  case 66:
+  case 69:
+
     {
 	menu_add_entry(NULL);
 	menu_add_prop(P_COMMENT, yyvsp[0].string, NULL, NULL);
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 67:
+  case 70:
+
     {
 	menu_end_entry();
-}
+;}
     break;
 
-  case 68:
+  case 71:
+
     {
 	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
 	zconf_starthelp();
-}
+;}
     break;
 
-  case 69:
+  case 72:
+
     {
 	current_entry->sym->help = yyvsp[0].string;
-}
+;}
     break;
 
-  case 72:
-    { }
+  case 75:
+
+    { ;}
     break;
 
-  case 73:
+  case 76:
+
     {
 	menu_add_dep(yyvsp[0].expr);
 	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 74:
+  case 77:
+
     {
 	menu_add_dep(yyvsp[0].expr);
 	printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 75:
+  case 78:
+
     {
 	menu_add_dep(yyvsp[0].expr);
 	printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
-}
+;}
     break;
 
-  case 77:
+  case 80:
+
     {
 	menu_add_prop(P_PROMPT, yyvsp[0].string, NULL, NULL);
-}
+;}
     break;
 
-  case 78:
+  case 81:
+
     {
 	menu_add_prop(P_PROMPT, yyvsp[-2].string, NULL, yyvsp[0].expr);
-}
+;}
     break;
 
-  case 81:
-    { yyval.token = T_ENDMENU; }
-    break;
+  case 84:
 
-  case 82:
-    { yyval.token = T_ENDCHOICE; }
+    { yyval.token = T_ENDMENU; ;}
     break;
 
-  case 83:
-    { yyval.token = T_ENDIF; }
-    break;
+  case 85:
 
-  case 86:
-    { yyval.expr = NULL; }
+    { yyval.token = T_ENDCHOICE; ;}
     break;
 
-  case 87:
-    { yyval.expr = yyvsp[0].expr; }
-    break;
+  case 86:
 
-  case 88:
-    { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); }
+    { yyval.token = T_ENDIF; ;}
     break;
 
   case 89:
-    { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); }
+
+    { yyval.expr = NULL; ;}
     break;
 
   case 90:
-    { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); }
+
+    { yyval.expr = yyvsp[0].expr; ;}
     break;
 
   case 91:
-    { yyval.expr = yyvsp[-1].expr; }
+
+    { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;}
     break;
 
   case 92:
-    { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); }
+
+    { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
     break;
 
   case 93:
-    { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); }
+
+    { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
     break;
 
   case 94:
-    { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); }
+
+    { yyval.expr = yyvsp[-1].expr; ;}
     break;
 
   case 95:
-    { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); }
+
+    { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;}
     break;
 
   case 96:
-    { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); }
+
+    { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;}
+    break;
+
+  case 97:
+
+    { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;}
+    break;
+
+  case 98:
+
+    { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;}
+    break;
+
+  case 99:
+
+    { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;}
     break;
 
 
     }
 
-/* Line 1016 of /usr/share/bison/yacc.c.  */
-#line 1509 "zconf.tab.c"
+/* Line 999 of yacc.c.  */
+
 
   yyvsp -= yylen;
   yyssp -= yylen;
 
 
-#if YYDEBUG
-  if (yydebug)
-    {
-      short *yyssp1 = yyss - 1;
-      YYFPRINTF (stderr, "state stack now");
-      while (yyssp1 != yyssp)
-	YYFPRINTF (stderr, " %d", *++yyssp1);
-      YYFPRINTF (stderr, "\n");
-    }
-#endif
+  YY_STACK_PRINT (yyss, yyssp);
 
   *++yyvsp = yyval;
 
@@ -1565,12 +1700,12 @@
 	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
 	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
 	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
-	  yysize += yystrlen ("parse error, unexpected ") + 1;
+	  yysize += yystrlen ("syntax error, unexpected ") + 1;
 	  yysize += yystrlen (yytname[yytype]);
 	  yymsg = (char *) YYSTACK_ALLOC (yysize);
 	  if (yymsg != 0)
 	    {
-	      char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
 	      yyp = yystpcpy (yyp, yytname[yytype]);
 
 	      if (yycount < 5)
@@ -1591,19 +1726,15 @@
 	      YYSTACK_FREE (yymsg);
 	    }
 	  else
-	    yyerror ("parse error; also virtual memory exhausted");
+	    yyerror ("syntax error; also virtual memory exhausted");
 	}
       else
 #endif /* YYERROR_VERBOSE */
-	yyerror ("parse error");
+	yyerror ("syntax error");
     }
-  goto yyerrlab1;
 
 
-/*----------------------------------------------------.
-| yyerrlab1 -- error raised explicitly by an action.  |
-`----------------------------------------------------*/
-yyerrlab1:
+
   if (yyerrstatus == 3)
     {
       /* If just tried and failed to reuse lookahead token after an
@@ -1615,28 +1746,30 @@
 	  /* Pop the error token.  */
           YYPOPSTACK;
 	  /* Pop the rest of the stack.  */
-	  while (yyssp > yyss)
+	  while (yyss < yyssp)
 	    {
-	      YYDPRINTF ((stderr, "Error: popping "));
-	      YYDSYMPRINT ((stderr,
-			    yystos[*yyssp],
-			    *yyvsp));
-	      YYDPRINTF ((stderr, "\n"));
-	      yydestruct (yystos[*yyssp], *yyvsp);
+	      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+	      yydestruct (yystos[*yyssp], yyvsp);
 	      YYPOPSTACK;
 	    }
 	  YYABORT;
         }
 
-      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
-		  yychar, yytname[yychar1]));
-      yydestruct (yychar1, yylval);
+      YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+      yydestruct (yytoken, &yylval);
       yychar = YYEMPTY;
+
     }
 
   /* Else will try to reuse lookahead token after shifting the error
      token.  */
+  goto yyerrlab1;
+
 
+/*----------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action.  |
+`----------------------------------------------------*/
+yyerrlab1:
   yyerrstatus = 3;	/* Each real token shifted decrements this.  */
 
   for (;;)
@@ -1657,26 +1790,12 @@
       if (yyssp == yyss)
 	YYABORT;
 
-      YYDPRINTF ((stderr, "Error: popping "));
-      YYDSYMPRINT ((stderr,
-		    yystos[*yyssp], *yyvsp));
-      YYDPRINTF ((stderr, "\n"));
-
-      yydestruct (yystos[yystate], *yyvsp);
+      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+      yydestruct (yystos[yystate], yyvsp);
       yyvsp--;
       yystate = *--yyssp;
 
-
-#if YYDEBUG
-      if (yydebug)
-	{
-	  short *yyssp1 = yyss - 1;
-	  YYFPRINTF (stderr, "Error: state stack now");
-	  while (yyssp1 != yyssp)
-	    YYFPRINTF (stderr, " %d", *++yyssp1);
-	  YYFPRINTF (stderr, "\n");
-	}
-#endif
+      YY_STACK_PRINT (yyss, yyssp);
     }
 
   if (yyn == YYFINAL)
@@ -1726,12 +1845,14 @@
 
 
 
+
 void conf_parse(const char *name)
 {
 	zconf_initscan(name);
 
 	sym_init();
 	menu_init();
+	modules_sym = sym_lookup("MODULES", 0);
 	rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
 
 	//zconfdebug = 1;
@@ -1739,8 +1860,6 @@
 	if (zconfnerrs)
 		exit(1);
 	menu_finalize(&rootmenu);
-
-	modules_sym = sym_lookup("MODULES", 0);
 
 	sym_change_count = 1;
 }
diff -Nru a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
--- a/scripts/kconfig/zconf.y	Mon Dec  9 12:30:46 2002
+++ b/scripts/kconfig/zconf.y	Sat Mar 15 09:25:55 2003
@@ -27,7 +27,7 @@
 
 #define YYERROR_VERBOSE
 %}
-%expect 36
+%expect 40
 
 %union
 {
@@ -46,6 +46,7 @@
 %token T_ENDCHOICE
 %token T_COMMENT
 %token T_CONFIG
+%token T_MENUCONFIG
 %token T_HELP
 %token <string> T_HELPTEXT
 %token T_IF
@@ -104,12 +105,13 @@
 	  if_stmt
 	| comment_stmt
 	| config_stmt
+	| menuconfig_stmt
 	| source_stmt
 	| nl_or_eof
 ;
 
 
-/* config entry */
+/* config/menuconfig entry */
 
 config_entry_start: T_CONFIG T_WORD
 {
@@ -125,6 +127,24 @@
 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 };
 
+menuconfig_entry_start: T_MENUCONFIG T_WORD
+{
+	struct symbol *sym = sym_lookup($2, 0);
+	sym->flags |= SYMBOL_OPTIONAL;
+	menu_add_entry(sym);
+	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+menuconfig_stmt: menuconfig_entry_start T_EOL config_option_list
+{
+	if (current_entry->prompt)
+		current_entry->prompt->type = P_MENU;
+	else
+		zconfprint("warning: menuconfig statement without prompt");
+	menu_end_entry();
+	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
 config_option_list:
 	  /* empty */
 	| config_option_list config_option T_EOL
@@ -423,6 +443,7 @@
 
 	sym_init();
 	menu_init();
+	modules_sym = sym_lookup("MODULES", 0);
 	rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
 
 	//zconfdebug = 1;
@@ -430,8 +451,6 @@
 	if (zconfnerrs)
 		exit(1);
 	menu_finalize(&rootmenu);
-
-	modules_sym = sym_lookup("MODULES", 0);
 
 	sym_change_count = 1;
 }
diff -Nru a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
--- a/scripts/lxdialog/Makefile	Fri Nov 22 12:15:37 2002
+++ b/scripts/lxdialog/Makefile	Mon Mar 10 13:03:33 2003
@@ -15,8 +15,8 @@
 endif
 endif
 
-host-progs    := lxdialog
-build-targets := $(host-progs)
+host-progs	:= lxdialog
+always		:= $(host-progs)
 
 lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
 		 util.o lxdialog.o msgbox.o
diff -Nru a/scripts/mkcompile_h b/scripts/mkcompile_h
--- a/scripts/mkcompile_h	Sun Oct  6 09:21:00 2002
+++ b/scripts/mkcompile_h	Fri Mar  7 12:55:30 2003
@@ -10,7 +10,7 @@
 # do "compiled by root"
 
 if [ -r $TARGET -a ! -O include/linux/autoconf.h ]; then
-  echo ' (not modified)'
+  echo "  SKIPPED $TARGET"
   exit 0
 fi
 
@@ -70,10 +70,9 @@
       grep -v 'UTS_VERSION\|LINUX_COMPILE_TIME' $TARGET > .tmpver.1 && \
       grep -v 'UTS_VERSION\|LINUX_COMPILE_TIME' .tmpcompile > .tmpver.2 && \
       cmp -s .tmpver.1 .tmpver.2; then
-   echo ' (unchanged)'
    rm -f .tmpcompile
 else
-   echo ' (updated)'
+   echo "  UPD     $TARGET"
    mv -f .tmpcompile $TARGET
 fi
-#rm -f .tmpver.1 .tmpver.2
+rm -f .tmpver.1 .tmpver.2
diff -Nru a/scripts/modpost.c b/scripts/modpost.c
--- a/scripts/modpost.c	Fri Feb 21 19:50:41 2003
+++ b/scripts/modpost.c	Wed Mar  5 18:07:11 2003
@@ -293,6 +293,9 @@
 		/* undefined symbol */
 		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
 			break;
+		/* ignore global offset table */
+		if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
+			break;
 		
 		if (memcmp(symname, MODULE_SYMBOL_PREFIX,
 			   strlen(MODULE_SYMBOL_PREFIX)) == 0) {
diff -Nru a/scripts/per-cpu-check.awk b/scripts/per-cpu-check.awk
--- a/scripts/per-cpu-check.awk	Fri Jan 24 12:27:01 2003
+++ b/scripts/per-cpu-check.awk	Wed Mar  5 17:53:22 2003
@@ -6,7 +6,7 @@
 	IN_PER_CPU=0
 }
 
-/__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ || / __kcrctab_/ ) {
+/__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ || / __kcrctab_/ || / __crc_/ ) {
 	if (!IN_PER_CPU) {
 		print $$3 " not in per-cpu section" > "/dev/stderr";
 		FOUND=1;
diff -Nru a/security/capability.c b/security/capability.c
--- a/security/capability.c	Sat Feb 15 19:30:18 2003
+++ b/security/capability.c	Mon Feb 17 12:08:10 2003
@@ -263,6 +263,13 @@
 	return;
 }
 
+int cap_syslog (int type)
+{
+	if ((type != 3) && !capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	return 0;
+}
+
 EXPORT_SYMBOL(cap_capable);
 EXPORT_SYMBOL(cap_ptrace);
 EXPORT_SYMBOL(cap_capget);
@@ -273,6 +280,7 @@
 EXPORT_SYMBOL(cap_task_post_setuid);
 EXPORT_SYMBOL(cap_task_kmod_set_label);
 EXPORT_SYMBOL(cap_task_reparent_to_init);
+EXPORT_SYMBOL(cap_syslog);
 
 #ifdef CONFIG_SECURITY
 
@@ -292,6 +300,8 @@
 	.task_post_setuid =		cap_task_post_setuid,
 	.task_kmod_set_label =		cap_task_kmod_set_label,
 	.task_reparent_to_init =	cap_task_reparent_to_init,
+
+	.syslog =                       cap_syslog,
 };
 
 #if defined(CONFIG_SECURITY_CAPABILITIES_MODULE)
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Fri Feb  7 01:51:46 2003
+++ b/security/dummy.c	Sun Feb 16 08:54:39 2003
@@ -75,6 +75,11 @@
 	return -EPERM;
 }
 
+static int dummy_sysctl (ctl_table * table, int op)
+{
+	return 0;
+}
+
 static int dummy_quotactl (int cmds, int type, int id, struct super_block *sb)
 {
 	return 0;
@@ -85,6 +90,13 @@
 	return 0;
 }
 
+static int dummy_syslog (int type)
+{
+	if ((type != 3) && current->euid)
+		return -EPERM;
+	return 0;
+}
+
 static int dummy_bprm_alloc_security (struct linux_binprm *bprm)
 {
 	return 0;
@@ -120,6 +132,11 @@
 	return;
 }
 
+static int dummy_sb_kern_mount (struct super_block *sb)
+{
+	return 0;
+}
+
 static int dummy_sb_statfs (struct super_block *sb)
 {
 	return 0;
@@ -306,11 +323,6 @@
 	return 0;
 }
 
-static void dummy_inode_post_lookup (struct inode *ino, struct dentry *d)
-{
-	return;
-}
-
 static void dummy_inode_delete (struct inode *ino)
 {
 	return;
@@ -719,6 +731,12 @@
 	return -EINVAL;
 }
 
+static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
+{
+	return;
+}
+
+
 struct security_operations dummy_security_ops;
 
 #define set_to_dummy_if_null(ops, function)				\
@@ -740,6 +758,8 @@
 	set_to_dummy_if_null(ops, capable);
 	set_to_dummy_if_null(ops, quotactl);
 	set_to_dummy_if_null(ops, quota_on);
+	set_to_dummy_if_null(ops, sysctl);
+	set_to_dummy_if_null(ops, syslog);
 	set_to_dummy_if_null(ops, bprm_alloc_security);
 	set_to_dummy_if_null(ops, bprm_free_security);
 	set_to_dummy_if_null(ops, bprm_compute_creds);
@@ -747,6 +767,7 @@
 	set_to_dummy_if_null(ops, bprm_check_security);
 	set_to_dummy_if_null(ops, sb_alloc_security);
 	set_to_dummy_if_null(ops, sb_free_security);
+	set_to_dummy_if_null(ops, sb_kern_mount);
 	set_to_dummy_if_null(ops, sb_statfs);
 	set_to_dummy_if_null(ops, sb_mount);
 	set_to_dummy_if_null(ops, sb_check_sb);
@@ -780,7 +801,6 @@
 	set_to_dummy_if_null(ops, inode_permission_lite);
 	set_to_dummy_if_null(ops, inode_setattr);
 	set_to_dummy_if_null(ops, inode_getattr);
-	set_to_dummy_if_null(ops, inode_post_lookup);
 	set_to_dummy_if_null(ops, inode_delete);
 	set_to_dummy_if_null(ops, inode_setxattr);
 	set_to_dummy_if_null(ops, inode_getxattr);
@@ -839,6 +859,7 @@
 	set_to_dummy_if_null(ops, netlink_recv);
 	set_to_dummy_if_null(ops, register_security);
 	set_to_dummy_if_null(ops, unregister_security);
+	set_to_dummy_if_null(ops, d_instantiate);
 #ifdef CONFIG_SECURITY_NETWORK
 	set_to_dummy_if_null(ops, unix_stream_connect);
 	set_to_dummy_if_null(ops, unix_may_send);
diff -Nru a/sound/isa/als100.c b/sound/isa/als100.c
--- a/sound/isa/als100.c	Tue Oct 22 06:04:00 2002
+++ b/sound/isa/als100.c	Sun Mar  9 15:44:14 2003
@@ -24,11 +24,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/time.h>
-#ifndef LINUX_ISAPNP_H
-#include <linux/isapnp.h>
-#define isapnp_card pci_bus
-#define isapnp_dev pci_dev
-#endif
+#include <linux/pnp.h>
 #include <sound/core.h>
 #define SNDRV_GET_ID
 #include <sound/initval.h>
@@ -96,167 +92,124 @@
 MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC);
 
 struct snd_card_als100 {
-#ifdef __ISAPNP__
-	struct isapnp_dev *dev;
-	struct isapnp_dev *devmpu;
-	struct isapnp_dev *devopl;
-#endif	/* __ISAPNP__ */
+	int dev_no;
+	struct pnp_dev *dev;
+	struct pnp_dev *devmpu;
+	struct pnp_dev *devopl;
 };
 
-static snd_card_t *snd_als100_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
-#ifdef __ISAPNP__
-static struct isapnp_card *snd_als100_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
-static const struct isapnp_card_id *snd_als100_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
-
-#define ISAPNP_ALS100(_va, _vb, _vc, _device, _audio, _mpu401, _opl) \
-        { \
-                ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
-                devs : { ISAPNP_DEVICE_ID('@', '@', '@', _audio), \
-                         ISAPNP_DEVICE_ID('@', 'X', '@', _mpu401), \
-			 ISAPNP_DEVICE_ID('@', 'H', '@', _opl) } \
-        }
-
-static struct isapnp_card_id snd_als100_pnpids[] __devinitdata = {
+static struct pnp_card_id snd_als100_pnpids[] __devinitdata = {
 	/* ALS100 - PRO16PNP */
-	ISAPNP_ALS100('A','L','S',0x0001,0x0001,0x0001,0x0001),
+	{ .id = "ALS0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" }, } },
 	/* ALS110 - MF1000 - Digimate 3D Sound */
-	ISAPNP_ALS100('A','L','S',0x0110,0x1001,0x1001,0x1001),
+	{ .id = "ALS0110", .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" }, } },
 	/* ALS120 */
-	ISAPNP_ALS100('A','L','S',0x0120,0x2001,0x2001,0x2001),
+	{ .id = "ALS0120", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } },
 	/* ALS200 */
-	ISAPNP_ALS100('A','L','S',0x0200,0x0020,0x0020,0x0001),
+	{ .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" }, } },
 	/* RTL3000 */
-	ISAPNP_ALS100('R','T','L',0x3000,0x2001,0x2001,0x2001),
-	{ ISAPNP_CARD_END, }
+	{ .id = "RTL3000", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } },
+	{ .id = "", } /* end */
 };
 
-ISAPNP_CARD_TABLE(snd_als100_pnpids);
-
-#endif	/* __ISAPNP__ */
+MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
 
 #define DRIVER_NAME	"snd-card-als100"
 
-
-#ifdef __ISAPNP__
-static int __init snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard)
+static int __devinit snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard,
+					    struct pnp_card_link *card,
+					    const struct pnp_card_id *id)
 {
-	const struct isapnp_card_id *id = snd_als100_isapnp_id[dev];
-	struct isapnp_card *card = snd_als100_isapnp_cards[dev];
-	struct isapnp_dev *pdev;
-
-	acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
-	if (acard->dev->active) {
-		acard->dev = NULL;
-		return -EBUSY;
-	}
-	acard->devmpu = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
-	if (acard->devmpu->active) {
-		acard->dev = acard->devmpu = NULL;
-		return -EBUSY;
-	}
-	acard->devopl = isapnp_find_dev(card, id->devs[2].vendor, id->devs[2].function, NULL);
-	if (acard->devopl->active) {
-		acard->dev = acard->devmpu = acard->devopl = NULL;
-		return -EBUSY;
+	struct pnp_dev *pdev;
+	struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table));
+	int err;
+	if (!cfg)
+		return -ENOMEM;
+	acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
+	if (acard->dev == NULL) {
+		kfree(cfg);
+		return -ENODEV;
 	}
+	acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
+	acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu);
 
 	pdev = acard->dev;
-	if (pdev->prepare(pdev)<0)
-		return -EAGAIN;
 
+	pnp_init_resource_table(cfg);
+
+	/* override resources */
 	if (port[dev] != SNDRV_AUTO_PORT)
-		isapnp_resource_change(&pdev->resource[0], port[dev], 16);
+		pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
 	if (dma8[dev] != SNDRV_AUTO_DMA)
-		isapnp_resource_change(&pdev->dma_resource[0], dma8[dev],
-			1);
+		pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
 	if (dma16[dev] != SNDRV_AUTO_DMA)
-		isapnp_resource_change(&pdev->dma_resource[1], dma16[dev],
-			1);
+		pnp_resource_change(&cfg->dma_resource[1], dma16[dev], 1);
 	if (irq[dev] != SNDRV_AUTO_IRQ)
-		isapnp_resource_change(&pdev->irq_resource[0], irq[dev], 1);
-
-	if (pdev->activate(pdev)<0) {
-		printk(KERN_ERR PFX "AUDIO isapnp configure failure\n");
-		return -EBUSY;
-	}
-
-	port[dev] = pdev->resource[0].start;
-	dma8[dev] = pdev->dma_resource[1].start;
-	dma16[dev] = pdev->dma_resource[0].start;
-	irq[dev] = pdev->irq_resource[0].start;
+		pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
+	if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
+		printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
+	err = pnp_activate_dev(pdev);
+	if (err < 0) {
+		printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
+		return err;
+	}
+	port[dev] = pnp_port_start(pdev, 0);
+	dma8[dev] = pnp_dma(pdev, 1);
+	dma16[dev] = pnp_dma(pdev, 0);
+	irq[dev] = pnp_irq(pdev, 0);
 
 	pdev = acard->devmpu;
-	if (pdev == NULL || pdev->prepare(pdev)<0) {
-		mpu_port[dev] = -1;
-		return 0;
-	}
-
-	if (mpu_port[dev] != SNDRV_AUTO_PORT)
-		isapnp_resource_change(&pdev->resource[0], mpu_port[dev],
-			2);
-	if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
-		isapnp_resource_change(&pdev->irq_resource[0], mpu_irq[dev],
-			1);
-
-	if (pdev->activate(pdev)<0) {
-		printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
-		mpu_port[dev] = -1;
-		acard->devmpu = NULL;
+	if (pdev != NULL) {
+		pnp_init_resource_table(cfg);
+		if (mpu_port[dev] != SNDRV_AUTO_PORT)
+			pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
+		if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
+			pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
+		if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
+			printk(KERN_ERR PFX "MPU401 the requested resources are invalid, using auto config\n");
+		err = pnp_activate_dev(pdev);
+		if (err < 0)
+			goto __mpu_error;
+		mpu_port[dev] = pnp_port_start(pdev, 0);
+		mpu_irq[dev] = pnp_irq(pdev, 0);
 	} else {
-		mpu_port[dev] = pdev->resource[0].start;
-		mpu_irq[dev] = pdev->irq_resource[0].start;
+	     __mpu_error:
+	     	if (pdev) {
+		     	pnp_release_card_device(pdev);
+	     		printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
+	     	}
+	     	acard->devmpu = NULL;
+	     	mpu_port[dev] = -1;
 	}
 
 	pdev = acard->devopl;
-	if (pdev == NULL || pdev->prepare(pdev)<0) {
-		fm_port[dev] = -1;
-		return 0;
-	}
-
-	if (fm_port[dev] != SNDRV_AUTO_PORT)
-		isapnp_resource_change(&pdev->resource[0], fm_port[dev], 4);
-
-	if (pdev->activate(pdev)<0) {
-		printk(KERN_ERR PFX "OPL isapnp configure failure\n");
-		fm_port[dev] = -1;
-		acard->devopl = NULL;
+	if (pdev != NULL) {
+		pnp_init_resource_table(cfg);
+		if (fm_port[dev] != SNDRV_AUTO_PORT)
+			pnp_resource_change(&cfg->port_resource[0], fm_port[dev], 4);
+		if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
+			printk(KERN_ERR PFX "OPL3 the requested resources are invalid, using auto config\n");
+		err = pnp_activate_dev(pdev);
+		if (err < 0)
+			goto __fm_error;
+		fm_port[dev] = pnp_port_start(pdev, 0);
 	} else {
-		fm_port[dev] = pdev->resource[0].start;
+	      __fm_error:
+	     	if (pdev) {
+		     	pnp_release_card_device(pdev);
+	     		printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n");
+	     	}
+	     	acard->devopl = NULL;
+	     	fm_port[dev] = -1;
 	}
 
+	kfree(cfg);
 	return 0;
 }
 
-static void snd_card_als100_deactivate(struct snd_card_als100 *acard)
-{
-	if (acard->dev) {
-		acard->dev->deactivate(acard->dev);
-		acard->dev = NULL;
-	}
-	if (acard->devmpu) {
-		acard->devmpu->deactivate(acard->devmpu);
-		acard->devmpu = NULL;
-	}
-	if (acard->devopl) {
-		acard->devopl->deactivate(acard->devopl);
-		acard->devopl = NULL;
-	}
-}
-#endif	/* __ISAPNP__ */
-
-static void snd_card_als100_free(snd_card_t *card)
-{
-	struct snd_card_als100 *acard = (struct snd_card_als100 *)card->private_data;
-
-	if (acard) {
-#ifdef __ISAPNP__
-		snd_card_als100_deactivate(acard);
-#endif	/* __ISAPNP__ */
-	}
-}
-
-static int __init snd_card_als100_probe(int dev)
+static int __init snd_card_als100_probe(int dev,
+					struct pnp_card_link *pcard,
+					const struct pnp_card_id *pid)
 {
 	int error;
 	sb_t *chip;
@@ -268,18 +221,11 @@
 				 sizeof(struct snd_card_als100))) == NULL)
 		return -ENOMEM;
 	acard = (struct snd_card_als100 *)card->private_data;
-	card->private_free = snd_card_als100_free;
 
-#ifdef __ISAPNP__
-	if ((error = snd_card_als100_isapnp(dev, acard))) {
+	if ((error = snd_card_als100_isapnp(dev, acard, pcard, pid))) {
 		snd_card_free(card);
 		return error;
 	}
-#else
-	printk(KERN_ERR PFX "you have to enable PnP support ...\n");
-	snd_card_free(card);
-	return -ENOSYS;
-#endif	/* __ISAPNP__ */
 
 	if ((error = snd_sbdsp_create(card, port[dev],
 				      irq[dev],
@@ -336,13 +282,12 @@
 		snd_card_free(card);
 		return error;
 	}
-	snd_als100_cards[dev] = card;
+	pnp_set_card_drvdata(pcard, card);
 	return 0;
 }
 
-#ifdef __ISAPNP__
-static int __init snd_als100_isapnp_detect(struct isapnp_card *card,
-					   const struct isapnp_card_id *id)
+static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
+					   const struct pnp_card_id *id)
 {
 	static int dev;
 	int res;
@@ -350,9 +295,7 @@
 	for ( ; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev])
 			continue;
-		snd_als100_isapnp_cards[dev] = card;
-		snd_als100_isapnp_id[dev] = id;
-		res = snd_card_als100_probe(dev);
+		res = snd_card_als100_probe(dev, card, id);
 		if (res < 0)
 			return res;
 		dev++;
@@ -360,17 +303,28 @@
 	}
 	return -ENODEV;
 }
-#endif
+
+static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
+{
+	snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+
+	snd_card_disconnect(card);
+	snd_card_free_in_thread(card);
+}
+
+static struct pnp_card_driver als100_pnpc_driver = {
+	.flags          = PNP_DRIVER_RES_DISABLE,
+        .name           = "als100",
+        .id_table       = snd_als100_pnpids,
+        .probe          = snd_als100_pnp_detect,
+        .remove         = __devexit_p(snd_als100_pnp_remove),
+};
 
 static int __init alsa_card_als100_init(void)
 {
 	int cards = 0;
 
-#ifdef __ISAPNP__
-	cards += isapnp_probe_cards(snd_als100_pnpids, snd_als100_isapnp_detect);
-#else
-	printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
-#endif
+	cards += pnp_register_card_driver(&als100_pnpc_driver);
 #ifdef MODULE
 	if (!cards)
 		printk(KERN_ERR "no ALS100 based soundcards found\n");
@@ -380,10 +334,7 @@
 
 static void __exit alsa_card_als100_exit(void)
 {
-	int dev;
-
-	for (dev = 0; dev < SNDRV_CARDS; dev++)
-		snd_card_free(snd_als100_cards[dev]);
+	pnp_unregister_card_driver(&als100_pnpc_driver);
 }
 
 module_init(alsa_card_als100_init)
diff -Nru a/sound/oss/sb_card.c b/sound/oss/sb_card.c
--- a/sound/oss/sb_card.c	Wed Feb 19 09:56:36 2003
+++ b/sound/oss/sb_card.c	Sun Mar  9 15:44:14 2003
@@ -32,9 +32,9 @@
 #include "sound_config.h"
 #include "sb_mixer.h"
 #include "sb.h"
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 #include <linux/pnp.h>
-#endif
+#endif /* CONFIG_PNP */
 #include "sb_card.h"
 
 MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver");
@@ -54,7 +54,7 @@
 
 struct sb_card_config *legacy = NULL;
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 static int __initdata pnp       = 1;
 /*
 static int __initdata uart401	= 0;
@@ -85,7 +85,7 @@
 MODULE_PARM_DESC(acer,	   "Set this to detect cards in some ACER notebooks "\
 		 "(doesn't work with pnp)");
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 module_param(pnp, int, 000);
 MODULE_PARM_DESC(pnp,     "Went set to 0 will disable detection using PnP. "\
 		  "Default is 1.\n");
@@ -95,7 +95,7 @@
 MODULE_PARM_DESC(uart401,  "When set to 1, will attempt to detect and enable"\
 		 "the mpu on some clones");
 */
-#endif /* CONFIG_PNP_CARD */
+#endif /* CONFIG_PNP */
 
 /* OSS subsystem card registration shared by PnP and legacy routines */
 static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo)
@@ -157,7 +157,7 @@
 	return sb_register_oss(legacy, &sbmo);
 }
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 
 /* Populate the OSS subsystem structures with information from PnP */
 static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
@@ -224,7 +224,7 @@
 }
 
 /* Probe callback function for the PnP API */
-static int sb_pnp_probe(struct pnp_card *card, const struct pnp_card_id *card_id)
+static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_id *card_id)
 {
 	struct sb_card_config *scc;
 	struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */
@@ -252,14 +252,14 @@
 	       "dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq,
 	       scc->conf.dma, scc->conf.dma2);
 
-	pnpc_set_drvdata(card, scc);
+	pnp_set_card_drvdata(card, scc);
 
 	return sb_register_oss(scc, &sbmo);
 }
 
-static void sb_pnp_remove(struct pnp_card *card)
+static void sb_pnp_remove(struct pnp_card_link *card)
 {
-	struct sb_card_config *scc = pnpc_get_drvdata(card);
+	struct sb_card_config *scc = pnp_get_card_drvdata(card);
 
 	if(!scc)
 		return;
@@ -269,13 +269,13 @@
 	sb_unload(scc);
 }
 
-static struct pnpc_driver sb_pnp_driver = {
+static struct pnp_card_driver sb_pnp_driver = {
 	.name          = "OSS SndBlstr", /* 16 character limit */
 	.id_table      = sb_pnp_card_table,
 	.probe         = sb_pnp_probe,
 	.remove        = sb_pnp_remove,
 };
-#endif /* CONFIG_PNP_CARD */
+#endif /* CONFIG_PNP */
 
 static int __init sb_init(void)
 {
@@ -293,9 +293,9 @@
 		printk(KERN_ERR "sb: Error: At least io, irq, and dma "\
 		       "must be set for legacy cards.\n");
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 	if(pnp) {
-		pres = pnpc_register_driver(&sb_pnp_driver);
+		pres = pnp_register_card_driver(&sb_pnp_driver);
 	}
 #endif
 	printk(KERN_INFO "sb: Init: Done\n");
@@ -315,8 +315,8 @@
 		sb_unload(legacy);
 	}
 
-#ifdef CONFIG_PNP_CARD
-	pnpc_unregister_driver(&sb_pnp_driver);
+#ifdef CONFIG_PNP
+	pnp_unregister_card_driver(&sb_pnp_driver);
 #endif
 
 	if (smw_free) {
diff -Nru a/sound/oss/sb_card.h b/sound/oss/sb_card.h
--- a/sound/oss/sb_card.h	Wed Feb 19 09:56:37 2003
+++ b/sound/oss/sb_card.h	Sun Mar  9 15:44:14 2003
@@ -16,7 +16,7 @@
 	int                 mpu;
 };
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 
 /*
  * SoundBlaster PnP tables and structures.
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	Fri Feb 28 17:14:13 2003
+++ b/sound/oss/trident.c	Thu Mar  6 09:38:03 2003
@@ -221,7 +221,7 @@
 #define TRIDENT_STATE_MAGIC	0x63657373 /* "cess" */
 
 #define TRIDENT_DMA_MASK	0x3fffffff /* DMA buffer mask for pci_alloc_consist */
-#define ALI_DMA_MASK		0xffffffff /* ALI Tridents lack the 30-bit limitation */
+#define ALI_DMA_MASK		0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */
 
 #define NR_HW_CH		32
 
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	Fri Feb 21 18:52:09 2003
+++ b/sound/pci/ac97/ac97_codec.c	Wed Mar  5 21:39:37 2003
@@ -1808,7 +1808,7 @@
  */
 static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
 {
-	signed long end_time;
+	unsigned long end_time;
 	end_time = jiffies + timeout;
 	do {
 		unsigned short ext_mid;
@@ -1866,7 +1866,7 @@
 	int err;
 	ac97_t *ac97;
 	char name[64];
-	signed long end_time;
+	unsigned long end_time;
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_ac97_dev_free,
 	};
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	Sun Feb 16 05:47:43 2003
+++ b/sound/pci/intel8x0.c	Wed Mar  5 21:39:37 2003
@@ -1741,7 +1741,7 @@
 
 static int snd_intel8x0_ich_chip_init(intel8x0_t *chip)
 {
-	signed long end_time;
+	unsigned long end_time;
 	unsigned int cnt, status, nstatus;
 	
 	/* put logic to right state */
diff -Nru a/usr/Makefile b/usr/Makefile
--- a/usr/Makefile	Tue Nov  5 08:08:10 2002
+++ b/usr/Makefile	Sun Mar  9 13:47:41 2003
@@ -1,16 +1,34 @@
 
 obj-y := initramfs_data.o
 
-host-progs := gen_init_cpio
+host-progs  := gen_init_cpio
 
 clean-files := initramfs_data.cpio.gz
 
 LDFLAGS_initramfs_data.o := $(LDFLAGS_BLOB) -r -T
 
-$(obj)/initramfs_data.o: $(src)/initramfs_data.scr $(obj)/initramfs_data.cpio.gz FORCE
+$(obj)/initramfs_data.o: $(src)/initramfs_data.scr \
+			 $(obj)/initramfs_data.cpio.gz FORCE
 	$(call if_changed,ld)
 
-$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio
-	./$< | gzip -9c > $@
+# initramfs-y are the programs which will be copied into the CPIO
+# archive. Currently, the filenames are hardcoded in gen_init_cpio,
+# but we need the information for the build as well, so it's duplicated
+# here.
 
+# Commented out for now
+# initramfs-y := $(obj)/root/hello
+
+quiet_cmd_cpio = CPIO    $@
+      cmd_cpio = ./$< > $@
+
+$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio $(initramfs-y) FORCE
+	$(call if_changed,cpio)
+
+targets += initramfs_data.cpio
+
+$(obj)/initramfs_data.cpio.gz: $(obj)/initramfs_data.cpio FORCE
+	$(call if_changed,gzip)
+
+targets += initramfs_data.cpio.gz
 
diff -Nru a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
--- a/usr/gen_init_cpio.c	Fri Nov  1 09:00:19 2002
+++ b/usr/gen_init_cpio.c	Fri Mar  7 16:36:36 2003
@@ -5,10 +5,28 @@
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
+#include <fcntl.h>
 
 static unsigned int offset;
 static unsigned int ino = 721;
 
+static void push_string(const char *name)
+{
+	unsigned int name_len = strlen(name) + 1;
+
+	fputs(name, stdout);
+	putchar(0);
+	offset += name_len;
+}
+
+static void push_pad (void)
+{
+	while (offset & 3) {
+		putchar(0);
+		offset++;
+	}
+}
+
 static void push_rest(const char *name)
 {
 	unsigned int name_len = strlen(name) + 1;
@@ -118,6 +136,78 @@
 		0);			/* chksum */
 	push_hdr(s);
 	push_rest(name);
+}
+
+/* Not marked static to keep the compiler quiet, as no one uses this yet... */
+void cpio_mkfile(const char *filename, const char *location,
+			unsigned int mode, uid_t uid, gid_t gid)
+{
+	char s[256];
+	char *filebuf;
+	struct stat buf;
+	int file;
+	int retval;
+	int i;
+
+	mode |= S_IFREG;
+
+	retval = stat (filename, &buf);
+	if (retval) {
+		fprintf (stderr, "Filename %s could not be located\n", filename);
+		goto error;
+	}
+
+	file = open (filename, O_RDONLY);
+	if (file < 0) {
+		fprintf (stderr, "Filename %s could not be opened for reading\n", filename);
+		goto error;
+	}
+
+	filebuf = malloc(buf.st_size);
+	if (!filebuf) {
+		fprintf (stderr, "out of memory\n");
+		goto error_close;
+	}
+
+	retval = read (file, filebuf, buf.st_size);
+	if (retval < 0) {
+		fprintf (stderr, "Can not read %s file\n", filename);
+		goto error_free;
+	}
+
+	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
+	       "%08X%08X%08X%08X%08X%08X%08X",
+		"070701",		/* magic */
+		ino++,			/* ino */
+		mode,			/* mode */
+		(long) uid,		/* uid */
+		(long) gid,		/* gid */
+		1,			/* nlink */
+		(long) buf.st_mtime,	/* mtime */
+		(int) buf.st_size,	/* filesize */
+		3,			/* major */
+		1,			/* minor */
+		0,			/* rmajor */
+		0,			/* rminor */
+		strlen(location) + 1,	/* namesize */
+		0);			/* chksum */
+	push_hdr(s);
+	push_string(location);
+	push_pad();
+
+	for (i = 0; i < buf.st_size; ++i)
+		fputc(filebuf[i], stdout);
+	close(file);
+	free(filebuf);
+	push_pad();
+	return;
+	
+error_free:
+	free(filebuf);
+error_close:
+	close(file);
+error:
+	exit(-1);
 }
 
 int main (int argc, char *argv[])
