diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Fri Oct 18 21:03:07 2002
+++ b/CREDITS	Fri Oct 18 21:03:07 2002
@@ -1750,6 +1750,11 @@
 S: 370 01  Ceske Budejovice
 S: Czech Republic
 
+N: Adam Belay
+E: ambx1@neo.rr.com
+D: Linux Plug and Play Support
+S: USA
+
 N: Bas Laarhoven
 E: sjml@xs4all.nl
 D: Loadable modules and ftape driver
diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
--- a/Documentation/DocBook/Makefile	Fri Oct 18 21:03:04 2002
+++ b/Documentation/DocBook/Makefile	Fri Oct 18 21:03:04 2002
@@ -13,14 +13,6 @@
 	    writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \
 	    kernel-api.sgml journal-api.sgml lsm.sgml
 
-JBDSOURCES :=  $(TOPDIR)/include/linux/jbd.h \
-	$(TOPDIR)/fs/jbd/journal.c \
-	$(TOPDIR)/fs/jbd/recovery.c \
-	$(TOPDIR)/fs/jbd/transaction.c
-
-journal-api.sgml: journal-api.tmpl $(JBDSOURCES)
-	$(TOPDIR)/scripts/docgen   $(JBDSOURCES) \
-	<journal-api.tmpl >journal-api.sgml
 ###
 # The build process is as follows (targets):
 #              (sgmldocs)
@@ -32,7 +24,7 @@
 # The targets that may be used.
 .PHONY:	sgmldocs psdocs pdfdocs htmldocs clean mrproper
 
-BOOKS := $(addprefix Documentation/DocBook/,$(DOCBOOKS))
+BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
 sgmldocs: $(BOOKS)
 
 PS := $(patsubst %.sgml, %.ps, $(BOOKS))
@@ -86,19 +78,19 @@
 ###
 # procfs guide uses a .c file as example code.
 # This requires an explicit dependency
-C-procfs-example = Documentation/DocBook/procfs_example.sgml
-Documentation/DocBook/procfs-guide.sgml: $(C-procfs-example)
+C-procfs-example = procfs_example.sgml
+C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
+$(obj)/procfs-guide.sgml: $(C-procfs-example2)
 
 ###
 # The parportbook includes a few images.
 # Force them to be build before the books 
 IMG-parportbook := parport-share.fig parport-multi.fig parport-structure.fig
-IMG-parportbook2 := $(addprefix Documentation/DocBook/,$(IMG-parportbook))
+IMG-parportbook2 := $(addprefix $(obj)/,$(IMG-parportbook))
 EPS-parportbook := $(patsubst %.fig,%.eps, $(IMG-parportbook2))
 PNG-parportbook := $(patsubst %.fig,%.png, $(IMG-parportbook2))
-Documentation/DocBook/parportbook.html:	$(PNG-parportbook)
-Documentation/DocBook/parportbook.ps Documentation/DocBook/parportbook.pdf:\
-	$(EPS-parportbook)
+$(obj)/parportbook.html: $(PNG-parportbook)
+$(obj)/parportbook.ps $(obj)/parportbook.pdf: $(EPS-parportbook)
 
 ###
 # Rules to generate postscript, PDF and HTML
@@ -155,21 +147,21 @@
 ###
 # clean and mrproper as used by the top-level makefile 
 # Temporary files left by various tools
-DVI     :=      $(patsubst %.sgml, %.dvi, $(BOOKS))
-AUX     :=      $(patsubst %.sgml, %.aux, $(BOOKS))
-TEX     :=      $(patsubst %.sgml, %.tex, $(BOOKS))
-LOG     :=      $(patsubst %.sgml, %.log, $(BOOKS))
-OUT     :=      $(patsubst %.sgml, %.out, $(BOOKS))
-
-clean:
-	@rm -f $(BOOKS)
-	@rm -f $(DVI) $(AUX) $(TEX) $(LOG) $(OUT)
-	@rm -f $(PNG-parportbook) $(EPS-parportbook)
-	@rm -f $(C-procfs-example)
-
-mrproper:
-	@rm -f $(PS) $(PDF)
-	@rm -f -r $(HTML) $(patsubst %.html,%,$(HTML))
+clean-files := $(DOCBOOKS) \
+	$(patsubst %.sgml, %.dvi,  $(DOCBOOKS)) \
+	$(patsubst %.sgml, %.aux,  $(DOCBOOKS)) \
+	$(patsubst %.sgml, %.tex,  $(DOCBOOKS)) \
+	$(patsubst %.sgml, %.log,  $(DOCBOOKS)) \
+	$(patsubst %.sgml, %.out,  $(DOCBOOKS)) \
+	$(patsubst %.sgml, %.ps,   $(DOCBOOKS)) \
+	$(patsubst %.sgml, %.pdf,  $(DOCBOOKS)) \
+	$(patsubst %.sgml, %.html, $(DOCBOOKS)) \
+	$(patsubst %.fig,%.eps, $(IMG-parportbook)) \
+	$(patsubst %.fig,%.png, $(IMG-parportbook)) \
+	$(C-procfs-example)
 
-include $(TOPDIR)/Rules.make
+ifneq ($(wildcard $(BOOKS)),)
+clean-rule := rm -rf $(wildcard $(BOOKS))
+endif
 
+include $(TOPDIR)/Rules.make
diff -Nru a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/filesystems/sysfs.txt	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,342 @@
+
+sysfs - _The_ filesystem for exporting kernel objects. 
+
+Patrick Mochel	<mochel@osdl.org>
+
+17 October 2002
+
+
+Note (17 Oct 2002): the name has just been changed from driverfs to
+sysfs. Updates to the documentation will come soon; after the
+conversion to use it is completely finished.
+
+
+
+What it is:
+~~~~~~~~~~~
+driverfs is a ram-based filesystem. It was created by copying
+ramfs/inode.c to driverfs/inode.c and doing a little search-and-replace. 
+
+driverfs is a means to export kernel data structures, their
+attributes, and the linkages between them to userspace. 
+
+driverfs provides a unified interface for exporting attributes to
+userspace. Currently, this interface is available only to device and
+bus drivers. 
+
+
+Using driverfs
+~~~~~~~~~~~~~~
+driverfs is always compiled in. You can access it by doing something like:
+
+    mount -t driverfs driverfs /devices 
+
+
+Top Level Directory Layout
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driverfs directory arrangement exposes the relationship of kernel
+data structures. 
+
+The top level driverfs diretory looks like:
+
+bus/
+root/
+
+root/ contains a filesystem representation of the device tree. It maps
+directly to the internal kernel device tree, which is a hierarchy of
+struct device. 
+
+bus/ contains flat directory layout of the various bus types in the
+kernel. Each bus's directory contains two subdirectories:
+
+	devices/
+	drivers/
+
+devices/ contains symlinks for each device discovered in the system
+that point to the device's directory under root/.
+
+drivers/ contains a directory for each device driver that is loaded
+for devices on that particular bus (this assmumes that drivers do not
+span multiple bus types).
+
+
+More information can device-model specific features can be found in
+Documentation/device-model/. 
+
+
+Directory Contents
+~~~~~~~~~~~~~~~~~~
+Each object that is represented in driverfs gets a directory, rather
+than a file, to make it simple to export attributes of that object. 
+Attributes are exported via ASCII text files. The programming
+interface is discussed below. 
+
+Instead of having monolithic files that are difficult to parse, all
+files are intended to export one attribute. The name of the attribute
+is the name of the file. The value of the attribute are the contents
+of the file. 
+
+There should be few, if any, exceptions to this rule. You should not
+violate it, for fear of public humilation.
+
+
+The Two-Tier Model
+~~~~~~~~~~~~~~~~~~
+
+driverfs is a very simple, low-level interface. In order for kernel
+objects to use it, there must be an intermediate layer in place for
+each object type. 
+
+All calls in driverfs are intended to be as type-safe as possible. 
+In order to extend driverfs to support multiple data types, a layer of
+abstraction was required. This intermediate layer converts between the
+generic calls and data structures of the driverfs core to the
+subsystem-specific objects and calls. 
+
+
+The Subsystem Interface
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The subsystems bear the responsibility of implementing driverfs
+extensions for the objects they control. Fortunately, it's intended to
+be really easy to do so. 
+
+It's divided into three sections: directories, files, and operations.
+
+
+Directories
+~~~~~~~~~~~
+
+struct driver_dir_entry {
+        char                    * name;
+        struct dentry           * dentry;
+        mode_t                  mode;
+        struct driverfs_ops     * ops;
+};
+
+
+int
+driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
+
+void
+driverfs_remove_dir(struct driver_dir_entry * entry);
+
+The directory structure should be statically allocated, and reside in
+a subsystem-specific data structure:
+
+struct device {
+       ...
+       struct driver_dir_entry	dir;
+};
+
+The subsystem is responsible for initializing the name, mode, and ops
+fields of the directory entry. (More on struct driverfs_ops later)
+
+
+Files
+~~~~~
+
+struct attribute {
+        char                    * name;
+        mode_t                  mode;
+};
+
+
+int
+driverfs_create_file(struct attribute * attr, struct driver_dir_entry * parent);
+
+void
+driverfs_remove_file(struct driver_dir_entry *, const char * name);
+
+
+The attribute structure is a simple, common token that the driverfs
+core handles. It has little use on its own outside of the
+core. Objects cannot use a plain struct attribute to export
+attributes, since there are no callbacks for reading and writing data.
+
+Therefore, the subsystem is required to define a data structure that
+encapsulates the attribute structure, and provides type-safe callbacks
+for reading and writing data.
+
+An example looks like this:
+
+struct device_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+        ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+
+Note that there is a struct attribute embedded in the structure. In
+order to relieve pain in declaring attributes, the subsystem should
+also define a macro, like:
+
+#define DEVICE_ATTR(_name,_mode,_show,_store)      \
+struct device_attribute dev_attr_##_name = {            \
+        .attr = {.name  = __stringify(_name) , .mode   = _mode },      \
+        .show   = _show,                                \
+        .store  = _store,                               \
+};
+
+This hides the initialization of the embedded struct, and in general,
+the internals of each structure. It yields a structure by the name of
+dev_attr_<name>.
+
+In order for objects to create files, the subsystem should create
+wrapper functions, like this:
+
+int device_create_file(struct device *device, struct device_attribute * entry);
+void device_remove_file(struct device * dev, struct device_attribute * attr);
+
+..and forward the call on to the driverfs functions.
+
+Note that there is no unique information in the attribute structures,
+so the same structure can be used to describe files of several
+different object instances. 
+
+
+Operations
+~~~~~~~~~~
+
+struct driverfs_ops {
+        int     (*open)(struct driver_dir_entry *);
+        int     (*close)(struct driver_dir_entry *);
+        ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
+        ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
+};
+
+
+Subsystems are required to implement this set of callbacks. Their
+purpose is to translate the generic data structures into the specific
+objects, and operate on them. This can be done by defining macros like
+this:
+
+#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+
+#define to_device(d) container_of(d, struct device, dir)
+
+
+Since the directories are statically allocated in the object, you can
+derive the pointer to the object that owns the file. Ditto for the
+attribute structures. 
+
+Current Interfaces
+~~~~~~~~~~~~~~~~~~
+
+The following interface layers currently exist in driverfs:
+
+
+- devices (include/linux/device.h)
+----------------------------------
+Structure:
+
+struct device_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+        ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+Declaring:
+
+DEVICE_ATTR(_name,_str,_mode,_show,_store);
+
+Creation/Removal:
+
+int device_create_file(struct device *device, struct device_attribute * entry);
+void device_remove_file(struct device * dev, struct device_attribute * attr);
+
+
+- bus drivers (include/linux/device.h)
+--------------------------------------
+Structure:
+
+struct bus_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off);
+        ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
+};
+
+Declaring:
+
+BUS_ATTR(_name,_mode,_show,_store)
+
+Creation/Removal:
+
+int bus_create_file(struct bus_type *, struct bus_attribute *);
+void bus_remove_file(struct bus_type *, struct bus_attribute *);
+
+
+- device drivers (include/linux/device.h)
+-----------------------------------------
+
+Structure:
+
+struct driver_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
+        ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
+};
+
+Declaring:
+
+DRIVER_ATTR(_name,_mode,_show,_store)
+
+Creation/Removal:
+
+int driver_create_file(struct device_driver *, struct driver_attribute *);
+void driver_remove_file(struct device_driver *, struct driver_attribute *);
+
+
+Reading/Writing Data
+~~~~~~~~~~~~~~~~~~~~
+The callback functionality is similar to the way procfs works. When a
+user performs a read(2) or write(2) on the file, it first calls a
+driverfs function. This calls to the subsystem, which then calls to
+the object's show() or store() function.
+
+The buffer pointer, offset, and length should be passed to each
+function. The downstream callback should fill the buffer and return
+the number of bytes read/written.
+
+
+What driverfs is not:
+~~~~~~~~~~~~~~~~~~~~~
+It is not a replacement for either devfs or procfs.
+
+It does not handle device nodes, like devfs is intended to do. I think
+this functionality is possible, but indeed think that integration of
+the device nodes and control files should be done. Whether driverfs or
+devfs, or something else, is the place to do it, I don't know.
+
+It is not intended to be a replacement for all of the procfs
+functionality. I think that many of the driver files should be moved
+out of /proc (and maybe a few other things as well ;).
+
+
+
+Limitations:
+~~~~~~~~~~~~
+The driverfs functions assume that at most a page is being either read
+or written each time.
+
+There is a race condition that is really, really hard to fix; if not 
+impossible. There exists a race between a driverfs file being opened
+and the object that owns the file going away. During the driverfs
+open() callback, the reference count for the owning object needs to be
+incremented. 
+
+For drivers, we can put a struct module * owner in struct driver_dir_entry 
+and do try_inc_mod_count() when we open a file. However, this won't
+work for devices, that aren't tied to a module. And, it is still not
+guaranteed to solve the race. 
+
+I'm looking into fixing this, but it may not be doable without making
+a separate filesystem instance for each object. It's fun stuff. Please
+mail me with creative ideas that you know will work. 
+
+
+Possible bugs:
+~~~~~~~~~~~~~~
+It may not deal with offsets and/or seeks very well, especially if
+they cross a page boundary.
+
diff -Nru a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt
--- a/Documentation/i386/zero-page.txt	Fri Oct 18 21:03:04 2002
+++ b/Documentation/i386/zero-page.txt	Fri Oct 18 21:03:04 2002
@@ -31,6 +31,7 @@
 
 0x1e0	unsigned long	ALT_MEM_K, alternative mem check, in Kb
 0x1e8	char		number of entries in E820MAP (below)
+0x1e9	unsigned char	number of entries in EDDBUF (below)
 0x1f1	char		size of setup.S, number of sectors
 0x1f2	unsigned short	MOUNT_ROOT_RDONLY (if !=0)
 0x1f4	unsigned short	size of compressed kernel-part in the
@@ -66,6 +67,7 @@
 0x220	4 bytes		(setup.S)
 0x224	unsigned short	setup.S heap end pointer
 0x2d0 - 0x600		E820MAP
+0x600 - 0x7D4		EDDBUF (setup.S)
 
 0x800	string, 2K max	COMMAND_LINE, the kernel commandline as
 			copied using CL_OFFSET.
diff -Nru a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt
--- a/Documentation/networking/e100.txt	Fri Oct 18 21:03:08 2002
+++ b/Documentation/networking/e100.txt	Fri Oct 18 21:03:08 2002
@@ -1,7 +1,7 @@
 Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
 ==============================================================
 
-April 9, 2002
+September 16, 2002
 
 
 Contents
@@ -19,26 +19,9 @@
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
-Adapters, version 2.0.x.  This driver includes support for Itanium(TM)-based 
+Adapters, version 2.1.x.  This driver includes support for Itanium(TM)-based 
 systems.
 
-New for this release:
-
-   - Additional ethtool functionality, including link status test and EEPROM 
-     read/write. A third-party application can use the ethtool interface to 
-     get and set driver parameters.
-
-   - Support for Zero copy on 82550-based adapters. This feature provides 
-     faster data throughput and significant CPU usage improvement in systems 
-     that use the relevant system call (sendfile(2)).
-
-   - Support for large MTU-enabling interface (1504 bytes) with kernel's 
-     VLAN module
-
-   - Support for polling on RX
-
-   - Support for Wake On LAN* on 82550 and 82559-based adapters
-
 
 Supported Adapters
 ==================
@@ -96,8 +79,7 @@
 
 To verify that your adapter is supported, find the board ID number on the 
 adapter. Look for a label that has a barcode and a number in the format 
-123456-001 (six digits hyphen three digits). Match this to the list of 
-numbers above.
+A12345-001. Match this to the list of numbers above.
 
 For more information on how to identify your adapter, go to the Adapter & 
 Driver ID Guide at:
@@ -106,15 +88,20 @@
 
 For the latest Intel PRO/100 network driver for Linux, see:
 
-  http://appsr.intel.com/scripts-df/support_intel.asp
+  http://downloadfinder.intel.com/scripts-df/support_intel.asp
 
 
 Command Line Parameters
 =======================
 
-The following parameters are used by entering them on the command line with 
-the modprobe or insmod command. For example, with two Intel PRO/100 PCI 
-adapters, entering:
+The following optional parameters are used by entering them on the command 
+line with the modprobe or insmod command using this syntax:
+
+     modprobe e100 [<option>=<VAL1>,<VAL2>,...]
+
+     insmod e100 [<option>=<VAL1>,<VAL2>,...] 
+
+For example, with two Intel PRO/100 PCI adapters, entering:
 	
      modprobe e100 TxDescriptors=32,128
 
@@ -122,16 +109,20 @@
 resources for the second adapter. This configuration favors the second 
 adapter. The driver supports up to 16 network adapters concurrently.
 
+The default value for each parameter is generally the recommended setting,
+unless otherwise noted.
+
 NOTE: Giving any command line option the value "-1" causes the driver to use 
       the appropriate default value for that option, as if no value was 
       specified.
 
 
 BundleMax
-Valid Range: 0x1-0xFFFF
+Valid Range: 1-65535
 Default Value: 6
-   This parameter holds the maximum number of packets in a bundle. Suggested 
-   values range from 2 to 10. See "CPU Cycle Saver."
+   This parameter holds the maximum number of small packets (less than 128
+   bytes) in a bundle. Suggested values range from 2 to 10. See "CPU Cycle 
+   Saver."
 
 BundleSmallFr
 Valid Range: 0-1 (0=off, 1=on)
@@ -142,48 +133,33 @@
 e100_speed_duplex
 Valid Range: 0-4 (1=10half;2=10full;3=100half;4=100full)
 Default Value: 0
-   The default value of 0 is set to auto-negotiate if the link partner is set
-   to auto-negotiate. If the link partner is forced, e100_speed_duplex 
-   defaults to half-duplex. 
+   The default value of 0 sets the adapter to auto-negotiate. Other values
+   set the adapter to forced speed and duplex. 
    Example usage: insmod e100.o e100_speed_duplex=4,4 (for two adapters)
 
 flow_control
 Valid Range: 0-1 (0=off, 1=on)
 Default Value: 0
    This parameter controls the automatic generation(Tx) and response(Rx) to 
-   Ethernet PAUSE frames. flow_control should NOT be set to 1 when the e100 
+   Ethernet PAUSE frames. flow_control should NOT be set to 1 when the 
    adapter is connected to an interface that does not support Ethernet PAUSE 
    frames and when the e100_speed_duplex parameter is NOT set to zero. 
 
 IntDelay
-Valid Range: 0-0xFFFF (0=off)
+Valid Range: 0-65535 (0=off)
 Default Value: 1536
    This parameter holds the number of time units (in adapter terminology)
    until the adapter generates an interrupt. The recommended value for 
-   IntDelay is 0x600 (upon initialization). Suggested values range from 
-   0x200h to 0x800. See "CPU Cycle Saver."
+   IntDelay is 1536 (upon initialization). Suggested values range from 
+   512 to 2048. See "CPU Cycle Saver."
 
 IFS
 Valid Range: 0-1 (0=off, 1=on)
 Default Value: 1
   Inter Frame Spacing (IFS) aims to reduce the number of Ethernet frame
   collisions by altering the time between frame transmissions. When IFS is 
-  enabled the driver tries to find an optimal IFS value. However, some 
-  switches function better when IFS is disabled.
-
-PollingMaxWork
-Valid Range: 1-1024 (max number of RxDescriptors)
-Default Value: Specified number of RxDescriptors
-  This value specifies the maximum number of receive packets that are 
-  processed on a single polling call. This parameter is invalid if 
-  RxCongestionControl is set to 0.
-
-RxCongestionControl
-Valid Range: 0-1 (0=off, 1=on)
-Default Value: 1
-  1 enables polling mode. When the link is congested, the driver can decide 
-  to handle received packets by polling them, instead of waiting until 
-  interrupts occur.
+  enabled the driver tries to find an optimal IFS value. It is used only at 
+  half duplex.
 
 RxDescriptors
 Valid Range: 8-1024
@@ -200,13 +176,15 @@
    Increasing this value allows the protocol stack to queue more transmits at
    the driver level. The maximum value for Itanium-based systems is 64.
 
-ucode (not available for 82557-based adapters)
+ucode
 Valid Range: 0-1 (0=off, 1=on)
 Default Value: 0 for 82558-based adapters
-               1 for 82559(and higher)-based adapters
+               1 for 82559, 82550, and 82551-based adapters
    On uploads the micro code to the adapter, which enables CPU Cycle Saver. 
    See the section "CPU Cycle Saver" below.
-   Example usage: insmod e100.o ucode=0  (does not reduce CPU usage)
+   Example usage: insmod e100.o ucode=1
+
+   Not available on 82557-based adapters.
 
 XsumRX
 Valid Range: 0-1 (0=off, 1=on)
@@ -214,6 +192,8 @@
    On allows Rx checksum offloading for TCP/UDP packets. Requires that the 
    hardware support this feature.
 
+   Not available on 82557 and 82558-based adapters.
+
 
 CPU Cycle Saver
 ================
@@ -234,10 +214,11 @@
 CPU Cycle Saver consists of these arguments: IntDelay, BundleMax and 
 BundleSmallFr. When IntDelay is increased, the adapter waits longer for 
 frames to arrive before generating the interrupt. By increasing BundleMax, 
-the network adapter waits for the number of frames specified to arrive before 
-generating the interrupt. When BundleSmallFr is disabled, the adapter does 
-not bundle packets that are smaller than 128 bytes. Such small packets are 
-often, but not always, control packets that are better served immediately.
+the network adapter waits for the number of small frames (less than 128 bytes)
+specified to arrive before generating the interrupt. When BundleSmallFr is 
+disabled, the adapter does not bundle small packets. Such small packets are 
+often, but not always, control packets that are better served immediately;
+therefore, BundleSmallFr is disabled by default.
 
 For most users, it is recommended that CPU Cycle Saver be used with the 
 default values specified in the Command Line Parameters section. However, in 
@@ -249,7 +230,7 @@
 Support
 =======
 
-For general information and support, go to the Intel support website at:
+For general information, go to the Intel support website at:
 
     http://support.intel.com
 
diff -Nru a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
--- a/Documentation/networking/e1000.txt	Fri Oct 18 21:03:08 2002
+++ b/Documentation/networking/e1000.txt	Fri Oct 18 21:03:08 2002
@@ -1,7 +1,7 @@
 Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
 ===============================================================
 
-August 6, 2002
+October 12, 2002
 
 
 Contents
@@ -20,7 +20,7 @@
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
-of Adapters, version 4.3.x.  This driver includes support for 
+of Adapters, version 4.4.x.  This driver includes support for 
 Itanium(TM)-based systems.
 
 This release version includes the following:
@@ -32,7 +32,7 @@
      default in supporting kernels. It is not supported on the Intel(R)
      PRO/1000 Gigabit Server Adapter.
 
-New features include:
+Features include:
 
    - Support for the 82545 and 82546-based adapters listed below
 
@@ -144,8 +144,7 @@
 
 RxIntDelay
 Valid Range: 0-65535 (0=off)
-Default Value: 0 (82542, 82543, and 82544-based adapters)
-               128 (82540, 82545, and 82546-based adapters)
+Default Value: 0
     This value delays the generation of receive interrupts in units of 1.024 
     microseconds.  Receive interrupt reduction can improve CPU efficiency if 
     properly tuned for specific network traffic. Increasing this value adds 
@@ -154,13 +153,12 @@
     may be set too high, causing the driver to run out of available receive 
     descriptors.
 
-    CAUTION: When setting RxIntDelay to a value other than 0, adapters based 
-             on the Intel 82543 and 82544 LAN controllers may hang (stop 
-             transmitting) under certain network conditions. If this occurs a
-             message is logged in the system event log. In addition, the 
-             controller is automatically reset, restoring the network 
-             connection. To eliminate the potential for the hang ensure that 
-             RxIntDelay is set to 0.
+    CAUTION: When setting RxIntDelay to a value other than 0, adapters may 
+             hang (stop transmitting) under certain network conditions. If
+             this occurs a NETDEV WATCHDOG message is logged in the system
+             event log. In addition, the controller is automatically reset,
+             restoring the network connection. To eliminate the potential for
+             the hang ensure that RxIntDelay is set to 0.
 
 RxAbsIntDelay (82540, 82545, and 82546-based adapters only)
 Valid Range: 0-65535 (0=off)
diff -Nru a/Documentation/pnp.txt b/Documentation/pnp.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/pnp.txt	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,250 @@
+Linux Plug and Play Documentation
+by Adam Belay <ambx1@neo.rr.com>
+last updated: Oct. 16, 2002
+---------------------------------------------------------------------------------------
+
+
+
+Overview
+--------
+	Plug and Play provides a means of detecting and setting resources for legacy or
+otherwise unconfigurable devices.  The Linux Plug and Play Layer provides these 
+services to compatible drivers.
+
+
+
+The User Interface
+------------------
+	The Linux Plug and Play user interface provides a means to activate PnP devices
+for legacy and user level drivers that do not support Linux Plug and Play.  The 
+user interface is integrated into driverfs.
+
+In addition to the standard driverfs file the following are created in each 
+device's directory:
+id - displays a list of support EISA IDs
+possible - displays possible resource configurations
+resources - displays currently allocated resources and allows resource changes
+
+-activating a device
+
+#echo "auto" > resources
+
+this will invoke the automatic resource config system to activate the device
+
+-manually activating a device
+
+#echo "manual <depnum> <mode>" > resources
+<depnum> - the configuration number
+<mode> - static or dynamic
+		static = for next boot
+		dynamic = now
+
+-disabling a device
+
+#echo "disable" > resources
+
+
+EXAMPLE:
+
+Suppose you need to activate the floppy disk controller.
+1.) change to the proper directory, in my case it is 
+/driver/bus/pnp/devices/00:0f
+# cd /driver/bus/pnp/devices/00:0f
+# cat name
+PC standard floppy disk controller
+
+2.) check if the device is already active
+# cat resources
+DISABLED
+
+- Notice the string "DISABLED".  THis means the device is not active.
+
+3.) check the device's possible configurations (optional)
+# cat possible
+Dependent: 01 - Priority acceptable
+    port 0x3f0-0x3f0, align 0x7, size 0x6, 16-bit address decoding
+    port 0x3f7-0x3f7, align 0x0, size 0x1, 16-bit address decoding
+    irq 6
+    dma 2 8-bit compatible
+Dependent: 02 - Priority acceptable
+    port 0x370-0x370, align 0x7, size 0x6, 16-bit address decoding
+    port 0x377-0x377, align 0x0, size 0x1, 16-bit address decoding
+    irq 6
+    dma 2 8-bit compatible
+
+4.) now activate the device
+# echo "auto" > resources
+
+5.) finally check if the device is active
+# cat resources
+io 0x3f0-0x3f5
+io 0x3f7-0x3f7
+irq 6
+dma 2
+
+also there are a series of kernel parameters:
+allowdma0
+pnp_reserve_irq=irq1[,irq2] ....
+pnp_reserve_dma=dma1[,dma2] ....
+pnp_reserve_io=io1,size1[,io2,size2] ....
+pnp_reserve_mem=mem1,size1[,mem2,size2] ....
+
+
+
+The Unified Plug and Play Layer
+-------------------------------
+	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 
+significantly easier.
+
+The following functions are available from the Plug and Play Layer:
+
+pnp_get_protocol
+- increments the number of uses by one
+
+pnp_put_protocol
+- deincrements the number of uses by one
+
+pnp_register_protocol
+- use this to register a new PnP protocol
+
+pnp_unregister_protocol
+- use this function to remove a PnP protocol from the Plug and Play Layer
+
+pnp_register_driver
+- adds a PnP driver to the Plug and Play Layer
+- this includes driver model integration
+
+pnp_unregister_driver
+- removes a PnP driver from the Plug and Play Layer
+
+
+
+Plug and Play Protocols
+-----------------------
+	This section contains information for PnP protocol developers.
+
+The following Protocols are currently available in the computing world:
+- PNPBIOS: used for system devices such as serial and parallel ports.
+- ISAPNP: provides PnP support for the ISA bus
+- ACPI: among its many uses, ACPI provides information about system level 
+devices.
+It is meant to replace the PNPBIOS.  It is not currently supported by Linux
+Plug and Play but it is planned to be in the near future.
+
+
+Requirements for a Linux PnP protocol:
+1.) the protocol must use EISA IDs
+2.) the protocol must inform the PnP Layer of a devices current configuration
+- the ability to set resources is optional but prefered.
+
+The following are PnP protocol related functions:
+
+pnp_add_device
+- use this function to add a PnP device to the PnP layer
+- only call this function when all wanted values are set in the pnp_dev 
+structure
+
+pnp_init_device
+- call this to initialize the PnP structure
+
+pnp_remove_device
+- call this to remove a device from the Plug and Play Layer.
+- it will fail if the device is still in use.
+- automatically will free mem used by the device and related structures
+
+pnp_add_id
+- adds a EISA ID to the list of supported IDs for the specified device
+
+For more information consult the source of a protocol such as
+/drivers/pnp/pnpbios/core.c.
+
+
+
+Linux Plug and Play Drivers
+---------------------------
+	This section contains information for linux PnP driver developers.
+
+The New Way
+...........
+1.) first make a list of supported EISA IDS
+ex:
+static const struct pnp_id pnp_dev_table[] = {
+	/* Standard LPT Printer Port */
+	{.id = "PNP0400", .driver_data = 0},
+	/* ECP Printer Port */
+	{.id = "PNP0401", .driver_data = 0},
+	{.id = ""}
+};
+
+Please note that the character 'X' can be used as a wild card in the function
+portion (last four characters).
+ex:
+	/* Unkown PnP modems */
+	{	"PNPCXXX",		UNKNOWN_DEV	},
+
+Supported PnP card IDs can optionally be defined.
+ex:
+static const struct pnp_id pnp_card_table[] = {
+	{	"ANYDEVS",		0	},
+	{	"",			0	}
+};
+
+2.) Optionally define probe and remove functions.  It may make sense not to 
+define these functions if the driver already has a reliable method of detecting
+the resources, such as the parport_pc driver.
+ex:
+static int
+serial_pnp_probe(struct pnp_dev * dev, const struct pnp_id *card_id, const 
+                 struct pnp_id *dev_id)
+{
+. . .
+
+ex:
+static void serial_pnp_remove(struct pnp_dev * dev)
+{
+. . .
+
+consult /drivers/serial/8250_pnp.c for more information.
+
+3.) create a driver structure
+ex:
+
+static struct pnp_driver serial_pnp_driver = {
+	.name		= "serial",
+	.card_id_table	= pnp_card_table,
+	.id_table	= pnp_dev_table,
+	.probe		= serial_pnp_probe,
+	.remove		= serial_pnp_remove,
+};
+
+* name and id_table can not be NULL.
+
+4.) register the driver
+ex:
+
+static int __init serial8250_pnp_init(void)
+{
+	return pnp_register_driver(&serial_pnp_driver);
+}
+
+The Old Way
+...........
+
+a series of compatability functions have been created to make it easy to convert 
+
+ISAPNP drivers.  They should serve as a temporary solution only.
+
+they are as follows:
+
+struct pnp_card *pnp_find_card(unsigned short vendor,
+				 unsigned short device,
+				 struct pnp_card *from)
+
+struct pnp_dev *pnp_find_dev(struct pnp_card *card,
+				unsigned short vendor,
+				unsigned short function,
+				struct pnp_dev *from)
+
diff -Nru a/Documentation/tipar.txt b/Documentation/tipar.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/tipar.txt	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,93 @@
+
+		Parallel link cable for Texas Instruments handhelds
+		===================================================
+
+
+Author: Romain Lievin
+Homepage: http://lpg.ticalc.org/prj_dev
+
+
+INTRODUCTION:
+
+This is a driver for the very common home-made parallel link cable, a cable 
+designed for connecting TI8x/9x graphing calculators (handhelds) to a computer
+or workstation (Alpha, Sparc). Given that driver is built on parport, the 
+parallel port abstraction layer, this driver is independant of the platform.
+
+It can also be used with another device plugged on the same port (such as a
+ZIP drive). I have a 100MB ZIP and both of them work fine !
+
+If you need more information, please visit the 'TI drivers' homepage at the URL
+above.
+
+WHAT YOU NEED:
+
+A TI calculator of course and a program capable to communicate with your 
+calculator.
+TiLP will work for sure (since I am his developer !). yal92 may be able to use
+it by changing tidev for tipar (may require some hacking...).
+
+HOW TO USE IT:
+
+You must have first compiled parport support (CONFIG_PARPORT_DEV): either 
+compiled in your kernel, either as a module. 
+This driver supports the new device hierarchy (devfs).
+
+Next, (as root) from your appropriate modules directory (lib/modules/2.5.XX):
+
+       modprobe parport
+       insmod tipar.o
+
+If it is not already there (it usually is), create the device:
+
+       mknod /dev/tipar0 c 115 0
+       mknod /dev/tipar1 c 115 1
+       mknod /dev/tipar2 c 115 2
+
+You will have to set permissions on this device to allow you to read/write
+from it:
+
+       chmod 666 /dev/tipar?
+       
+Now you are ready to run a linking program such as TiLP. Be sure to configure 
+it properly (RTFM).
+       
+MODULE PARAMETERS:
+
+  You can set these with:  insmod tipar NAME=VALUE
+  There is currently no way to set these on a per-cable basis.
+
+  NAME: timeout
+  TYPE: integer
+  DEFAULT: 15
+  DESC: Timeout value in tenth of seconds. If no data is available once this 
+	time has expired then the driver will return with a timeout error.
+
+  NAME: delay
+  TYPE: integer
+  DEFAULT: 10
+  DESC: Inter-bit delay in micro-seconds. An lower value gives an higher data 
+	rate but makes transmission less reliable.
+
+These parameters can be changed at run time by any program via ioctl(2) calls 
+as listed in ./include/linux/ticable.h
+Rather than write 50 pages describing the ioctl() and so on, it is
+perhaps more useful you look at ticables library (dev_link.c) that demonstrates
+how to use them, and demonstrates the features of the driver. This is
+probably a lot more useful to people interested in writing applications
+that will be using this driver.
+
+QUIRKS/BUGS:
+
+None.
+
+HOW TO CONTACT US:
+
+You can email me at roms@lpg.ticalc.org. Please prefix the subject line
+with "TIPAR: " so that I am certain to notice your message.
+You can also mail JB at jb@jblache.org. He packaged these drivers for Debian.
+
+CREDITS:
+
+The code is based on tidev.c & parport.c.
+The driver has been developed independantly of Texas Instruments.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Fri Oct 18 21:03:05 2002
+++ b/MAINTAINERS	Fri Oct 18 21:03:05 2002
@@ -1,3 +1,4 @@
+
 	List of maintainers and how to submit kernel changes
 
 Please try to follow the guidelines below.  This will make things
@@ -261,7 +262,6 @@
 P:	Tigran A. Aivazian
 M:	tigran@veritas.com
 L:	linux-kernel@vger.kernel.org
-W:	http://www.ocston.org/~tigran/patches/bfs
 S:	Maintained
 
 BLOCK LAYER
@@ -654,8 +654,8 @@
 S:	Maintained
 
 HFS FILESYSTEM
-P:	Adrian Sun
-M:	asun@cobaltnet.com
+P:	Oliver Neukum
+M:	oliver@neukum.org
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
@@ -1293,11 +1293,8 @@
 S:	Maintained
 
 PNP SUPPORT
-P:	Tom Lees
-M:	tom@lpsg.demon.co.uk
-L:	pnp-users@ferret.lmh.ox.ac.uk
-L:	pnp-devel@ferret.lmh.ox.ac.uk
-W:	http://www-jcr.lmh.ox.ac.uk/~pnp/
+P:	Adam Belay
+M:	ambx1@neo.rr.com
 S:	Maintained
 
 PPP PROTOCOL DRIVERS AND COMPRESSORS
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Fri Oct 18 21:03:03 2002
+++ b/Makefile	Fri Oct 18 21:03:03 2002
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 43
+SUBLEVEL = 44
 EXTRAVERSION =
 
 # *DOCUMENTATION*
@@ -239,7 +239,7 @@
 
 #	If .config doesn't exist - tough luck
 
-.config: arch/$(ARCH)/config.in $(shell find . -name Config.in)
+.config: arch/$(ARCH)/config.in # FIXME $(shell find . -name Config.in)
 	@echo '***'
 	@if [ -f $@ ]; then \
 	  echo '*** The tree was updated, so your .config may be'; \
@@ -456,18 +456,23 @@
 
 depend dep: .hdepend
 
-#	.hdepend is our (misnomed) marker for whether we've run
+#	.hdepend is our (misnomed) marker for whether we've
 #	generated module versions
 
-.hdepend: $(if $(filter dep depend,$(MAKECMDGOALS)),FORCE)
+make-versions := $(strip $(if $(filter dep depend,$(MAKECMDGOALS)),1) \
+			 $(if $(wildcard .hdepend),,1))
+
+.hdepend: prepare FORCE
+ifneq ($(make-versions),)
 	@$(MAKE) include/linux/modversions.h
 	@touch $@
+endif
 
 ifdef CONFIG_MODVERSIONS
 
 # 	Update modversions.h, but only if it would change.
 
-include/linux/modversions.h: scripts/fixdep prepare FORCE
+include/linux/modversions.h: FORCE
 	@rm -rf .tmp_export-objs
 	@$(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS))
 	@echo -n '  Generating $@'
@@ -661,90 +666,61 @@
 defconfig:
 	yes '' | $(CONFIG_SHELL) $(src)/scripts/Configure -d arch/$(ARCH)/config.in
 
-# Cleaning up
-# ---------------------------------------------------------------------------
+###
+# Cleaning is done on three levels.
+# make clean     Delete all automatically generated files, including
+#                tools and firmware.
+# make mrproper  Delete the current configuration, and related files
+#                Any core files spread around is deleted as well
+# make distclean Remove editor backup files, patch leftover files and the like
 
-#	files removed with 'make clean'
-CLEAN_FILES += \
-	include/linux/compile.h \
-	vmlinux System.map \
-	drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
-	drivers/char/conmakehash \
-	drivers/char/drm/*-mod.c \
-	drivers/char/defkeymap.c drivers/char/qtronixmap.c \
-	drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist \
-	drivers/zorro/devlist.h drivers/zorro/gen-devlist \
-	sound/oss/bin2hex sound/oss/hex2hex \
-	drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} \
-	drivers/scsi/aic7xxx/aic7xxx_seq.h \
-	drivers/scsi/aic7xxx/aic7xxx_reg.h \
-	drivers/scsi/aic7xxx/aicasm/aicasm_gram.c \
-	drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \
-	drivers/scsi/aic7xxx/aicasm/y.tab.h \
-	drivers/scsi/aic7xxx/aicasm/aicasm \
-	drivers/scsi/53c700_d.h drivers/scsi/sim710_d.h \
-	drivers/scsi/53c7xx_d.h drivers/scsi/53c7xx_u.h \
-	drivers/scsi/53c8xx_d.h drivers/scsi/53c8xx_u.h \
-	net/802/cl2llc.c net/802/transit/pdutr.h net/802/transit/timertr.h \
-	net/802/pseudo/pseudocode.h \
-	net/khttpd/make_times_h net/khttpd/times.h \
-	submenu*
+# Files removed with 'make clean'
+CLEAN_FILES += vmlinux System.map MC*
 
-# 	files removed with 'make mrproper'
+# Files removed with 'make mrproper'
 MRPROPER_FILES += \
 	include/linux/autoconf.h include/linux/version.h \
-	drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h \
-	drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h \
-	drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h \
-	drivers/net/hamradio/soundmodem/gentbl \
-	sound/oss/*_boot.h sound/oss/.*.boot \
-	sound/oss/msndinit.c \
-	sound/oss/msndperm.c \
-	sound/oss/pndsperm.c \
-	sound/oss/pndspini.c \
-	drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw \
-	.version .config* config.in config.old \
-	scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp \
-	scripts/lxdialog/*.o scripts/lxdialog/lxdialog \
+	.version .config .config.old config.in config.old \
 	.menuconfig.log \
 	include/asm \
 	.hdepend include/linux/modversions.h \
 	tags TAGS kernel.spec \
 	.tmp*
 
-# 	directories removed with 'make mrproper'
+# Directories removed with 'make mrproper'
 MRPROPER_DIRS += \
 	.tmp_export-objs \
 	include/config \
 	include/linux/modules
 
-clean:	archclean
-	@echo 'Cleaning up'
-	@find . $(RCS_FIND_IGNORE) \
-		\( -name \*.[oas] -o -name core -o -name .\*.cmd -o \
-		-name .\*.tmp -o -name .\*.d \) -type f -print \
-		| grep -v lxdialog/ | xargs rm -f
-	@rm -f $(CLEAN_FILES)
-	+@$(call descend,Documentation/DocBook,clean)
+# clean - Delete all intermediate files
+#
+clean-dirs += $(ALL_SUBDIRS) Documentation/DocBook scripts
 
-mrproper: clean archmrproper
-	@echo 'Making mrproper'
+$(addprefix _clean_,$(clean-dirs)):
+	$(MAKE) MAKEFILES= -rR -f scripts/Makefile.clean obj=$(patsubst _clean_%,%,$@)
+
+quiet_cmd_rmclean = RM  $$(CLEAN_FILES)
+cmd_rmclean	  = rm -f $(CLEAN_FILES)
+clean: archclean $(addprefix _clean_,$(clean-dirs))
+	$(call cmd,rmclean)
 	@find . $(RCS_FIND_IGNORE) \
-		\( -name .depend -o -name .\*.cmd \) \
-		-type f -print | xargs rm -f
-	@rm -rf $(MRPROPER_DIRS)
-	@rm -f $(MRPROPER_FILES)
-	+@$(call descend,scripts,mrproper)
-	+@$(call descend,Documentation/DocBook,mrproper)
+	 	\( -name '*.[oas]' -o -name '.*.cmd' -o -name '.*.d' \
+		-o -name '.*.tmp' \) -type f -print | xargs rm -f
 
-distclean: mrproper
-	@echo 'Making distclean'
+# mrproper - delete configuration + modules + core files
+#
+quiet_cmd_mrproper = RM  $$(MRPROPER_DIRS) + $$(MRPROPER_FILES)
+cmd_mrproper = rm -rf $(MRPROPER_DIRS) && rm -f $(MRPROPER_FILES)
+mrproper distclean: clean archmrproper
+	@echo '  Making $@ in the srctree'
 	@find . $(RCS_FIND_IGNORE) \
-		\( -not -type d \) -and \
 	 	\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
 		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-	 	-o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f \
-		-print | xargs rm -f
+	 	-o -name '.*.rej' -o -size 0 \
+		-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
+		-type f -print | xargs rm -f
+	$(call cmd,mrproper)
 
 # Generate tags for editors
 # ---------------------------------------------------------------------------
diff -Nru a/Rules.make b/Rules.make
--- a/Rules.make	Fri Oct 18 21:03:04 2002
+++ b/Rules.make	Fri Oct 18 21:03:04 2002
@@ -1,3 +1,6 @@
+
+ifndef no-rules.make
+
 #
 # This file contains rules which are shared between multiple Makefiles.
 #
@@ -87,6 +90,7 @@
 # Subdirectories we need to descend into
 
 subdir-ym	:= $(sort $(subdir-y) $(subdir-m))
+subdir-ymn      := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
 
 # export.o is never a composite object, since $(export-objs) has a
 # fixed meaning (== objects which EXPORT_SYMBOL())
@@ -113,6 +117,10 @@
 # Only build module versions for files which are selected to be built
 export-objs := $(filter $(export-objs),$(real-objs-y) $(real-objs-m))
 
+host-progs-single     := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
+host-progs-multi      := $(foreach m,$(host-progs),$(if $($(m)-objs),$(m)))
+host-progs-multi-objs := $(foreach m,$(host-progs-multi),$($(m)-objs))
+
 # Add subdir path
 
 EXTRA_TARGETS	:= $(addprefix $(obj)/,$(EXTRA_TARGETS))
@@ -127,12 +135,19 @@
 multi-objs-y	:= $(addprefix $(obj)/,$(multi-objs-y))
 multi-objs-m	:= $(addprefix $(obj)/,$(multi-objs-m))
 subdir-ym	:= $(addprefix $(obj)/,$(subdir-ym))
+subdir-ymn	:= $(addprefix $(obj)/,$(subdir-ymn))
+clean-files	:= $(addprefix $(obj)/,$(clean-files))
+host-progs	:= $(addprefix $(obj)/,$(host-progs))
+host-progs-single     := $(addprefix $(obj)/,$(host-progs-single))
+host-progs-multi      := $(addprefix $(obj)/,$(host-progs-multi))
+host-progs-multi-objs := $(addprefix $(obj)/,$(host-progs-multi-objs))
 
 # The temporary file to save gcc -MD generated dependencies must not
 # contain a comma
 depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
 
-# We're called for one of three purposes:
+# We're called for one of four purposes:
+# o subdirclean: Delete intermidiate files in the current directory
 # o fastdep: build module version files (.ver) for $(export-objs) in
 #   the current directory
 # o modules_install: install the modules in the current directory
@@ -142,6 +157,19 @@
 #   When targets are given directly (like foo.o), we just build these
 #   targets (That happens when someone does make some/dir/foo.[ois])
 
+ifeq ($(MAKECMDGOALS),subdirclean)
+
+__clean-files := $(wildcard $(EXTRA_TARGETS) $(host-progs) $(clean-files))
+
+subdirclean: $(subdir-ymn)
+ifneq ($(strip $(__clean-files) $(clean-rule)),)
+	rm -f $(__clean-files)
+	$(clean-rule)
+else
+	@:
+endif
+
+else
 ifeq ($(MAKECMDGOALS),fastdep)
 
 # ===========================================================================
@@ -154,14 +182,14 @@
 # ---------------------------------------------------------------------------
 
 fastdep: $(subdir-ym)
-	@/bin/true
+	@:
 
 else
 
 # This sets version suffixes on exported symbols
 # ---------------------------------------------------------------------------
 
-MODVERDIR := include/linux/modules/
+MODVERDIR := include/linux/modules
 
 #
 # Added the SMP separator to stop module accidents between uniprocessor
@@ -246,7 +274,7 @@
 ifneq ($(obj-m),)
 	$(call cmd,modules_install)
 else
-	@/bin/true
+	@:
 endif
 
 else # ! modules_install
@@ -255,23 +283,18 @@
 # Building
 # ==========================================================================
 
-# If a Makefile does define neither O_TARGET nor L_TARGET,
-# use a standard O_TARGET named "built-in.o"
-
-ifndef O_TARGET
-ifndef L_TARGET
-O_TARGET := $(obj)/built-in.o
-endif
-endif
+# If a Makefile does not define a L_TARGET, link an object called "built-in.o"
 
 ifdef L_TARGET
 L_TARGET := $(obj)/$(L_TARGET)
+else
+O_TARGET := $(obj)/built-in.o
 endif
 
 first_rule: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \
 	    $(if $(KBUILD_MODULES),$(obj-m)) \
 	    $(subdir-ym)
-	@/bin/true
+	@:
 
 # Compile C sources (.c)
 # ---------------------------------------------------------------------------
@@ -399,14 +422,6 @@
 # Compile programs on the host
 # ===========================================================================
 
-host-progs-single     := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
-host-progs-multi      := $(foreach m,$(host-progs),$(if $($(m)-objs),$(m)))
-host-progs-multi-objs := $(foreach m,$(host-progs-multi),$($(m)-objs))
-host-progs	      := $(addprefix $(obj)/,$(host-progs))
-host-progs-single     := $(addprefix $(obj)/,$(host-progs-single))
-host-progs-multi      := $(addprefix $(obj)/,$(host-progs-multi))
-host-progs-multi-objs := $(addprefix $(obj)/,$(host-progs-multi-objs))
-
 quiet_cmd_host_cc__c  = HOSTCC  $(echo_target)
 cmd_host_cc__c        = $(HOSTCC) -Wp,-MD,$(depfile) \
 			$(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
@@ -431,6 +446,7 @@
 
 targets += $(host-progs-single) $(host-progs-multi-objs) $(host-progs-multi) 
 
+endif # ! subdirclean
 endif # ! modules_install
 endif # ! fastdep
 
@@ -480,9 +496,9 @@
 # Descending
 # ---------------------------------------------------------------------------
 
-.PHONY: $(subdir-ym)
+.PHONY: $(subdir-ymn)
 
-$(subdir-ym):
+$(subdir-ymn):
 	+@$(call descend,$@,$(MAKECMDGOALS))
 
 # Add FORCE to the prequisites of a target to force it to be always rebuilt.
@@ -605,3 +621,5 @@
 descend = echo '$(MAKE) -f $(1)/Makefile $(2)';
 endif
 descend += $(MAKE) -f $(1)/Makefile obj=$(1) $(2)
+
+endif
diff -Nru a/arch/alpha/defconfig b/arch/alpha/defconfig
--- a/arch/alpha/defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/alpha/defconfig	Fri Oct 18 21:03:04 2002
@@ -808,7 +808,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
--- a/arch/alpha/kernel/alpha_ksyms.c	Fri Oct 18 21:03:03 2002
+++ b/arch/alpha/kernel/alpha_ksyms.c	Fri Oct 18 21:03:03 2002
@@ -167,7 +167,6 @@
 EXPORT_SYMBOL(csum_tcpudp_magic);
 EXPORT_SYMBOL(ip_compute_csum);
 EXPORT_SYMBOL(ip_fast_csum);
-EXPORT_SYMBOL(csum_partial_copy);
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(csum_partial_copy_from_user);
 EXPORT_SYMBOL(csum_ipv6_magic);
diff -Nru a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
--- a/arch/alpha/lib/csum_partial_copy.c	Fri Oct 18 21:03:04 2002
+++ b/arch/alpha/lib/csum_partial_copy.c	Fri Oct 18 21:03:04 2002
@@ -385,16 +385,3 @@
 {
 	return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
 }
-
-unsigned int
-csum_partial_copy (const char *src, char *dst, int len, unsigned int sum)
-{
-	unsigned int ret;
-	int error = 0;
-
-	ret = do_csum_partial_copy_from_user(src, dst, len, sum, &error);
-	if (error)
-		printk("csum_partial_copy_old(): tell mingo to convert me!\n");
-
-	return ret;
-}
diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile
--- a/arch/arm/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/Makefile	Fri Oct 18 21:03:04 2002
@@ -63,10 +63,8 @@
   ifeq ($(CONFIG_ROM_KERNEL),y)
     DATAADDR	 = 0x02080000
     TEXTADDR	 = 0x03800000
-    LDSCRIPT	 = arch/arm/vmlinux-armo-rom.lds.in
   else
     TEXTADDR	 = 0x02080000
-    LDSCRIPT	 = arch/arm/vmlinux-armo.lds.in
   endif
 endif
 
@@ -191,8 +189,7 @@
 
 libs-y				+= arch/arm/lib/
 
-MAKEBOOT	 =$(MAKE) -C arch/$(ARCH)/boot
-MAKETOOLS	 =$(MAKE) -C arch/$(ARCH)/tools
+makeboot = $(call descend,arch/arm/boot,$(1))
 
 #	Update machine arch and proc symlinks if something which affects
 #	them changed.  We use .arch and .proc to indicate when they were
@@ -212,13 +209,16 @@
 
 prepare: maketools
 
-.PHONY: maketools
+.PHONY: maketools FORCE
 maketools: include/asm-arm/.arch include/asm-arm/.proc \
-	 include/asm-arm/constants.h include/linux/version.h FORCE
-	@$(MAKETOOLS)
+	   include/asm-arm/constants.h include/linux/version.h FORCE
+	+@$(call descend,arch/arm/tools, include/asm-arm/mach-types.h)
 
-bzImage zImage zinstall Image bootpImage install: vmlinux
-	@$(MAKEBOOT) $@
+zImage Image bootpImage: vmlinux
+	+@$(call makeboot,arch/arm/boot/$@)
+
+bzImage zinstall install: vmlinux
+	+@$(call makeboot,$@)
 
 MRPROPER_FILES	+= \
 	include/asm-arm/arch include/asm-arm/.arch \
@@ -227,18 +227,16 @@
 	include/asm-arm/mach-types.h
 
 # We use MRPROPER_FILES and CLEAN_FILES now
-archmrproper: FORCE
-	@/bin/true
-
+archmrproper:
 archclean: FORCE
-	@$(MAKEBOOT) clean
+	+@$(call makeboot,clean)
 
 # My testing targets (that short circuit a few dependencies)
-zImg:;	@$(MAKEBOOT) zImage
-Img:;	@$(MAKEBOOT) Image
-i:;	@$(MAKEBOOT) install
-zi:;	@$(MAKEBOOT) zinstall
-bp:;	@$(MAKEBOOT) bootpImage
+zImg:;	+@$(call makeboot, zImage)
+Img:;	+@$(call makeboot, Image)
+i:;	+@$(call makeboot, install)
+zi:;	+@$(call makeboot, zinstall)
+bp:;	+@$(call makeboot, bootpImage)
 
 #
 # Configuration targets.  Use these to select a
diff -Nru a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
--- a/arch/arm/boot/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/boot/Makefile	Fri Oct 18 21:03:03 2002
@@ -8,8 +8,6 @@
 # Copyright (C) 1995-2002 Russell King
 #
 
-SYSTEM	=$(TOPDIR)/vmlinux
-
 # Note: the following conditions must always be true:
 #   ZRELADDR == virt_to_phys(TEXTADDR)
 #   PARAMS_PHYS must be with 4MB of ZRELADDR
@@ -121,38 +119,57 @@
 ZBSSADDR	=ALIGN(4)
 endif
 
-export	SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS
-
-Image:	$(SYSTEM)
-	$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
+export	ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS
 
-bzImage: zImage
+include $(TOPDIR)/Rules.make
 
-zImage:	compressed/vmlinux
-	$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
+$(obj)/Image: vmlinux FORCE
+	$(call if_changed,objcopy)
 
-bootpImage: bootp/bootp
-	$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
+bzImage: $(obj)/zImage
 
-compressed/vmlinux: $(TOPDIR)/vmlinux FORCE
-	@$(MAKE) -C compressed vmlinux
+$(obj)/zImage:	$(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
 
-bootp/bootp: zImage initrd FORCE
-	@$(MAKE) -C bootp bootp
+$(obj)/bootpImage: $(obj)/bootp/bootp FORCE
+	$(call if_changed,objcopy)
 
-initrd:
-	@test "$(INITRD_PHYS)" != "" || (echo This machine does not support INITRD; exit -1)
-	@test "$(INITRD)" != "" || (echo You must specify INITRD; exit -1)
+$(obj)/compressed/vmlinux: vmlinux FORCE
+	+@$(call descend,arch/arm/boot/compressed, $(obj)/compressed/vmlinux)
 
-install: Image
-	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
+$(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
+	+@$(call descend,arch/arm/boot/bootp, $(obj)/bootp/bootp)
 
-zinstall: zImage
-	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
+.PHONY: initrd
+initrd:
+	@test "$(INITRD_PHYS)" != "" || \
+	(echo This machine does not support INITRD; exit -1)
+	@test "$(INITRD)" != "" || \
+	(echo You must specify INITRD; exit -1)
+
+install: $(obj)/Image
+	$(CONFIG_SHELL) $(obj)/install.sh \
+	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+	$(obj)/Image System.map "$(INSTALL_PATH)"
+
+zinstall: $(obj)/zImage
+	$(CONFIG_SHELL) $(obj)/install.sh \
+	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
 clean:
-	$(RM) Image zImage bootpImage
-	@$(MAKE) -C compressed clean
-	@$(MAKE) -C bootp clean
+	$(RM) $(addprefix $(obj)/,Image zImage bootpImage)
+	+@$(call descend,arch/arm/boot/bootp, clean)
+	+@$(call descend,arch/arm/boot/compressed, clean)
+
+archhelp:
+	@echo  '* bzImage/zImage- Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+	@echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+	@echo  '  bootpImage    - Combined zImage and initial RAM disk' 
+	@echo  '  install       - Install uncompressed kernel'
+	@echo  '  zinstall      - Install compressed kernel'
+	@echo  '                  Install using (your) ~/bin/installkernel or'
+	@echo  '                  (distribution) /sbin/installkernel or'
+	@echo  '                  install to $$(INSTALL_PATH) and run lilo'
+
 
-FORCE:
diff -Nru a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile
--- a/arch/arm/boot/bootp/Makefile	Fri Oct 18 21:03:07 2002
+++ b/arch/arm/boot/bootp/Makefile	Fri Oct 18 21:03:07 2002
@@ -2,23 +2,25 @@
 # linux/arch/arm/boot/bootp/Makefile
 #
 
-ZSYSTEM		=$(TOPDIR)/arch/arm/boot/zImage
-ZLDFLAGS	=-p -X -T bootp.lds \
+ZSYSTEM		= arch/arm/boot/zImage
+ZLDFLAGS	=-p -X -T $(obj)/bootp.lds \
 		 --defsym initrd_addr=$(INITRD_PHYS) \
 		 --defsym params=$(PARAMS_PHYS)
 
-all:		bootp
+EXTRA_TARGETS := bootp
+
+include $(TOPDIR)/Rules.make
 
 # Note that bootp.lds picks up kernel.o and initrd.o
-bootp:		init.o kernel.o initrd.o bootp.lds
-		$(LD) $(ZLDFLAGS) -o $@ init.o
+$(obj)/bootp:	$(addprefix $(obj)/,init.o kernel.o initrd.o bootp.lds)
+		$(LD) $(ZLDFLAGS) -o $@ $(obj)/init.o
 
-kernel.o:	$(ZSYSTEM)
+$(obj)/kernel.o: $(ZSYSTEM)
 		$(LD) -r -s -o $@ -b binary $(ZSYSTEM)
 
-initrd.o:	$(INITRD)
+$(obj)/initrd.o: $(INITRD)
 		$(LD) -r -s -o $@ -b binary $(INITRD)
 
 .PHONY:		$(INITRD) $(ZSYSTEM)
 
-clean:;		$(RM) bootp
+clean:;		$(RM) $(obj)/bootp
diff -Nru a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
--- a/arch/arm/boot/compressed/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/boot/compressed/Makefile	Fri Oct 18 21:03:03 2002
@@ -3,22 +3,20 @@
 #
 # create a compressed vmlinuz image from the original vmlinux
 #
-# Note! SYSTEM, ZTEXTADDR, ZBSSADDR and ZRELADDR are now exported
+# Note! ZTEXTADDR, ZBSSADDR and ZRELADDR are now exported
 # from arch/arm/boot/Makefile
 #
 
-HEAD		 = head.o
-OBJS		 = misc.o
-CFLAGS		 = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_BOOT) -fpic
-FONTC		 = $(TOPDIR)/drivers/video/font_acorn_8x8.c
-ZLDFLAGS	 = -p -X -T vmlinux.lds
+HEAD	= head.o
+OBJS	= misc.o
+FONTC	= drivers/video/font_acorn_8x8.c
 
 #
 # Architecture dependencies
 #
 ifeq ($(CONFIG_ARCH_ACORN),y)
 OBJS		+= ll_char_wr.o font.o
-CFLAGS		+= -DPARAMS_PHYS=$(PARAMS_PHYS)
+CFLAGS_misc.o	:= -DPARAMS_PHYS=$(PARAMS_PHYS)
 endif
 
 ifeq ($(CONFIG_ARCH_NETWINDER),y)
@@ -65,35 +63,39 @@
 OBJS		+= head-xscale.o
 endif
 
-SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
+SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;\
+s/BSS_START/$(ZBSSADDR)/;s#OBJ#$(obj)#
 
-LIBGCC		:= $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
+EXTRA_TARGETS := vmlinux piggy.o font.o head.o $(OBJS)
+EXTRA_CFLAGS  := $(CFLAGS_BOOT) -fpic
+EXTRA_AFLAGS  := -traditional
 
-all:		vmlinux
+include $(TOPDIR)/Rules.make
 
-vmlinux:	$(HEAD) $(OBJS) piggy.o vmlinux.lds
-		$(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(LIBGCC) -o vmlinux
+LDFLAGS_vmlinux := -p -X \
+	$(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -T
 
-$(HEAD): 	$(HEAD:.o=.S)
-		$(CC) $(AFLAGS) -traditional -c $(HEAD:.o=.S)
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
+	 	$(addprefix $(obj)/, $(OBJS))
+	$(call if_changed,ld)
 
-piggy.o:	$(SYSTEM)
-		$(OBJCOPY) $(OBJCOPYFLAGS) $(SYSTEM) piggy
-		gzip $(GZFLAGS) < piggy > piggy.gz
-		$(LD) -r -o $@ -b binary piggy.gz
-		rm -f piggy piggy.gz
 
-font.o:		$(FONTC)
-		$(CC) $(CFLAGS) -Dstatic= -c -o $@ $(FONTC)
+$(obj)/piggy:    vmlinux;	$(call if_changed,objcopy)
+$(obj)/piggy.gz: $(obj)/piggy;	$(call if_changed,gzip)
 
-vmlinux.lds:	vmlinux.lds.in Makefile $(TOPDIR)/arch/$(ARCH)/boot/Makefile $(TOPDIR)/.config
-		@sed "$(SEDFLAGS)" < vmlinux.lds.in > $@
+LDFLAGS_piggy.o := -r -b binary
+$(obj)/piggy.o:  $(obj)/piggy.gz
+	$(call if_changed,ld)
 
-clean:;		rm -f vmlinux core piggy* vmlinux.lds
+CFLAGS_font.o := -Dstatic=
+$(obj)/font.o: $(FONTC)
+
+$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in Makefile arch/arm/boot/Makefile .config
+	@sed "$(SEDFLAGS)" < $< > $@
 
 .PHONY:	clean
+clean:
+	rm -f $(addprefix $(obj)/,vmlinux core piggy* vmlinux.lds)
 
-misc.o: misc.c $(TOPDIR)/include/asm/arch/uncompress.h $(TOPDIR)/lib/inflate.c
+$(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c
 
-%.o: %.S
-	$(CC) $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) -c -o $@ $<
diff -Nru a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
--- a/arch/arm/boot/compressed/misc.c	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/boot/compressed/misc.c	Fri Oct 18 21:03:03 2002
@@ -270,8 +270,6 @@
 
 static void error(char *x)
 {
-	int ptr;
-
 	puts("\n\n");
 	puts(x);
 	puts("\n\n -- System halted");
diff -Nru a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
--- a/arch/arm/boot/compressed/vmlinux.lds.in	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/boot/compressed/vmlinux.lds.in	Fri Oct 18 21:03:04 2002
@@ -28,7 +28,7 @@
     *(.glue_7)
     *(.glue_7t)
     input_data = .;
-    piggy.o
+    arch/arm/boot/compressed/piggy.o
     input_data_end = .;
     . = ALIGN(4);
   }
diff -Nru a/arch/arm/def-configs/adi_evb b/arch/arm/def-configs/adi_evb
--- a/arch/arm/def-configs/adi_evb	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/adi_evb	Fri Oct 18 21:03:04 2002
@@ -664,7 +664,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/adsbitsy b/arch/arm/def-configs/adsbitsy
--- a/arch/arm/def-configs/adsbitsy	Fri Oct 18 21:03:07 2002
+++ b/arch/arm/def-configs/adsbitsy	Fri Oct 18 21:03:07 2002
@@ -649,7 +649,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/anakin b/arch/arm/def-configs/anakin
--- a/arch/arm/def-configs/anakin	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/anakin	Fri Oct 18 21:03:03 2002
@@ -605,7 +605,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/assabet b/arch/arm/def-configs/assabet
--- a/arch/arm/def-configs/assabet	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/assabet	Fri Oct 18 21:03:04 2002
@@ -949,7 +949,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/badge4 b/arch/arm/def-configs/badge4
--- a/arch/arm/def-configs/badge4	Fri Oct 18 21:03:07 2002
+++ b/arch/arm/def-configs/badge4	Fri Oct 18 21:03:07 2002
@@ -1128,15 +1128,15 @@
 #
 # Bluetooth support
 #
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
 
 #
 # Bluetooth device drivers
 #
-CONFIG_BLUEZ_HCIUSB=m
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIVHCI=m
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIVHCI=m
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/cerfcube b/arch/arm/def-configs/cerfcube
--- a/arch/arm/def-configs/cerfcube	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/cerfcube	Fri Oct 18 21:03:03 2002
@@ -858,7 +858,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/cerfpda b/arch/arm/def-configs/cerfpda
--- a/arch/arm/def-configs/cerfpda	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/cerfpda	Fri Oct 18 21:03:03 2002
@@ -944,15 +944,15 @@
 #
 # Bluetooth support
 #
-CONFIG_BLUEZ=y
-CONFIG_BLUEZ_L2CAP=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
 
 #
 # Bluetooth device drivers
 #
-# CONFIG_BLUEZ_HCIUSB is not set
-CONFIG_BLUEZ_HCIUART=y
-# CONFIG_BLUEZ_HCIVHCI is not set
+# CONFIG_BT_HCIUSB is not set
+CONFIG_BT_HCIUART=y
+# CONFIG_BT_HCIVHCI is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/cerfpod b/arch/arm/def-configs/cerfpod
--- a/arch/arm/def-configs/cerfpod	Fri Oct 18 21:03:08 2002
+++ b/arch/arm/def-configs/cerfpod	Fri Oct 18 21:03:08 2002
@@ -879,7 +879,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/epxa10db b/arch/arm/def-configs/epxa10db
--- a/arch/arm/def-configs/epxa10db	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/epxa10db	Fri Oct 18 21:03:04 2002
@@ -673,7 +673,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/flexanet b/arch/arm/def-configs/flexanet
--- a/arch/arm/def-configs/flexanet	Fri Oct 18 21:03:08 2002
+++ b/arch/arm/def-configs/flexanet	Fri Oct 18 21:03:08 2002
@@ -881,7 +881,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/fortunet b/arch/arm/def-configs/fortunet
--- a/arch/arm/def-configs/fortunet	Fri Oct 18 21:03:08 2002
+++ b/arch/arm/def-configs/fortunet	Fri Oct 18 21:03:08 2002
@@ -572,7 +572,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/graphicsclient b/arch/arm/def-configs/graphicsclient
--- a/arch/arm/def-configs/graphicsclient	Fri Oct 18 21:03:08 2002
+++ b/arch/arm/def-configs/graphicsclient	Fri Oct 18 21:03:08 2002
@@ -717,7 +717,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/graphicsmaster b/arch/arm/def-configs/graphicsmaster
--- a/arch/arm/def-configs/graphicsmaster	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/graphicsmaster	Fri Oct 18 21:03:03 2002
@@ -730,7 +730,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/h3600 b/arch/arm/def-configs/h3600
--- a/arch/arm/def-configs/h3600	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/h3600	Fri Oct 18 21:03:04 2002
@@ -934,7 +934,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/iq80310 b/arch/arm/def-configs/iq80310
--- a/arch/arm/def-configs/iq80310	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/iq80310	Fri Oct 18 21:03:03 2002
@@ -781,7 +781,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/jornada720 b/arch/arm/def-configs/jornada720
--- a/arch/arm/def-configs/jornada720	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/jornada720	Fri Oct 18 21:03:03 2002
@@ -876,7 +876,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/lart b/arch/arm/def-configs/lart
--- a/arch/arm/def-configs/lart	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/lart	Fri Oct 18 21:03:04 2002
@@ -878,7 +878,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/lubbock b/arch/arm/def-configs/lubbock
--- a/arch/arm/def-configs/lubbock	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/lubbock	Fri Oct 18 21:03:03 2002
@@ -855,7 +855,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/neponset b/arch/arm/def-configs/neponset
--- a/arch/arm/def-configs/neponset	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/neponset	Fri Oct 18 21:03:04 2002
@@ -1099,7 +1099,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/pangolin b/arch/arm/def-configs/pangolin
--- a/arch/arm/def-configs/pangolin	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/pangolin	Fri Oct 18 21:03:04 2002
@@ -727,7 +727,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/pleb b/arch/arm/def-configs/pleb
--- a/arch/arm/def-configs/pleb	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/pleb	Fri Oct 18 21:03:03 2002
@@ -520,7 +520,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/shannon b/arch/arm/def-configs/shannon
--- a/arch/arm/def-configs/shannon	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/shannon	Fri Oct 18 21:03:03 2002
@@ -721,7 +721,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/shark b/arch/arm/def-configs/shark
--- a/arch/arm/def-configs/shark	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/def-configs/shark	Fri Oct 18 21:03:03 2002
@@ -912,7 +912,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/stork b/arch/arm/def-configs/stork
--- a/arch/arm/def-configs/stork	Fri Oct 18 21:03:08 2002
+++ b/arch/arm/def-configs/stork	Fri Oct 18 21:03:08 2002
@@ -941,7 +941,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/def-configs/system3 b/arch/arm/def-configs/system3
--- a/arch/arm/def-configs/system3	Fri Oct 18 21:03:04 2002
+++ b/arch/arm/def-configs/system3	Fri Oct 18 21:03:04 2002
@@ -947,7 +947,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
--- a/arch/arm/kernel/Makefile	Fri Oct 18 21:03:08 2002
+++ b/arch/arm/kernel/Makefile	Fri Oct 18 21:03:08 2002
@@ -43,6 +43,7 @@
 include $(TOPDIR)/Rules.make
 
 # Spell out some dependencies that `make dep' doesn't spot
-entry-armv.o: entry-header.S $(TOPDIR)/include/asm-arm/constants.h
-entry-armo.o: entry-header.S $(TOPDIR)/include/asm-arm/constants.h
-entry-common.o: entry-header.S calls.S $(TOPDIR)/include/asm-arm/constants.h
+$(obj)/entry-armv.o: 	$(obj)/entry-header.S include/asm-arm/constants.h
+$(obj)/entry-armo.o: 	$(obj)/entry-header.S include/asm-arm/constants.h
+$(obj)/entry-common.o: 	$(obj)/entry-header.S include/asm-arm/constants.h \
+			$(obj)/calls.S
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	Fri Oct 18 21:03:07 2002
+++ b/arch/arm/kernel/ecard.c	Fri Oct 18 21:03:07 2002
@@ -1114,7 +1114,7 @@
 
 void ecard_remove_driver(struct ecard_driver *drv)
 {
-	remove_driver(&drv->drv);
+	driver_unregister(&drv->drv);
 }
 
 static int ecard_match(struct device *_dev, struct device_driver *_drv)
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c	Fri Oct 18 21:03:07 2002
+++ b/arch/arm/kernel/time.c	Fri Oct 18 21:03:07 2002
@@ -26,6 +26,7 @@
 #include <linux/smp.h>
 #include <linux/timex.h>
 #include <linux/errno.h>
+#include <linux/profile.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
diff -Nru a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
--- a/arch/arm/lib/Makefile	Fri Oct 18 21:03:06 2002
+++ b/arch/arm/lib/Makefile	Fri Oct 18 21:03:06 2002
@@ -43,6 +43,6 @@
 
 include $(TOPDIR)/Rules.make
 
-csumpartialcopy.o: csumpartialcopygeneric.S
-csumpartialcopyuser.o: csumpartialcopygeneric.S
+$(obj)/csumpartialcopy.o:	$(obj)/csumpartialcopygeneric.S
+$(obj)/csumpartialcopyuser.o:	$(obj)/csumpartialcopygeneric.S
 
diff -Nru a/arch/arm/mach-sa1100/pcipool.c b/arch/arm/mach-sa1100/pcipool.c
--- a/arch/arm/mach-sa1100/pcipool.c	Fri Oct 18 21:03:07 2002
+++ b/arch/arm/mach-sa1100/pcipool.c	Fri Oct 18 21:03:07 2002
@@ -70,7 +70,7 @@
  * @size: size of the blocks in this pool.
  * @align: alignment requirement for blocks; must be a power of two
  * @allocation: returned blocks won't cross this boundary (or zero)
- * @mem_flags: SLAB_* flags.
+ * Context: !in_interrupt()
  *
  * Returns a pci allocation pool with the requested characteristics, or
  * null if one can't be created.  Given one of these pools, pci_pool_alloc()
@@ -86,7 +86,7 @@
  */
 struct pci_pool *
 pci_pool_create (const char *name, struct pci_dev *pdev,
-	size_t size, size_t align, size_t allocation, int mem_flags)
+	size_t size, size_t align, size_t allocation)
 {
 	struct pci_pool		*retval;
 
@@ -110,7 +110,7 @@
 	} else if (allocation < size)
 		return 0;
 
-	if (!(retval = kmalloc (sizeof *retval, mem_flags)))
+	if (!(retval = kmalloc (sizeof *retval, SLAB_KERNEL)))
 		return retval;
 
 	strncpy (retval->name, name, sizeof retval->name);
diff -Nru a/arch/arm/mach-sa1100/sa1111-pcibuf.c b/arch/arm/mach-sa1100/sa1111-pcibuf.c
--- a/arch/arm/mach-sa1100/sa1111-pcibuf.c	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/mach-sa1100/sa1111-pcibuf.c	Fri Oct 18 21:03:03 2002
@@ -61,8 +61,7 @@
 					    SA1111_FAKE_PCIDEV,
 					    SIZE_SMALL,
 					    0 /* byte alignment */,
-					    0 /* no page-crossing issues */,
-					    SLAB_KERNEL);
+					    0 /* no page-crossing issues */);
 	if (0 == small_buffer_pool) {
 		printk(KERN_ERR
 		       "sa1111_pcibuf: could not allocate small pci pool\n");
@@ -73,8 +72,7 @@
 					    SA1111_FAKE_PCIDEV,
 					    SIZE_LARGE,
 					    0 /* byte alignment */,
-					    0 /* no page-crossing issues */,
-					    SLAB_KERNEL);
+					    0 /* no page-crossing issues */);
 	if (0 == large_buffer_pool) {
 		printk(KERN_ERR
 		       "sa1111_pcibuf: could not allocate large pci pool\n");
diff -Nru a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
--- a/arch/arm/mm/Makefile	Fri Oct 18 21:03:08 2002
+++ b/arch/arm/mm/Makefile	Fri Oct 18 21:03:08 2002
@@ -42,4 +42,4 @@
 include $(TOPDIR)/Rules.make
 
 # Special dependencies
-$(p-y):	$(TOPDIR)/include/asm-arm/constants.h
+$(obj)/$(p-y):	include/asm-arm/constants.h
diff -Nru a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile
--- a/arch/arm/tools/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/arm/tools/Makefile	Fri Oct 18 21:03:03 2002
@@ -4,9 +4,9 @@
 # Copyright (C) 2001 Russell King
 #
 
-all:	$(TOPDIR)/include/asm-arm/mach-types.h
+include $(TOPDIR)/Rules.make
 
-$(TOPDIR)/include/asm-arm/mach-types.h: mach-types gen-mach-types
-	awk -f gen-mach-types mach-types > $@
+include/asm-arm/mach-types.h: $(obj)/mach-types $(obj)/gen-mach-types
+	@echo '  Generating $@'
+	@awk -f $(obj)/gen-mach-types $(obj)/mach-types > $@
 
-.PHONY:	all
diff -Nru a/arch/cris/lib/old_checksum.c b/arch/cris/lib/old_checksum.c
--- a/arch/cris/lib/old_checksum.c	Fri Oct 18 21:03:08 2002
+++ b/arch/cris/lib/old_checksum.c	Fri Oct 18 21:03:08 2002
@@ -80,48 +80,3 @@
   BITOFF;
   return(sum);
 }
-
-#if 0
-
-/*
- * copy while checksumming, otherwise like csum_partial
- */
-
-unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst, 
-				  int len, unsigned int sum)
-{
-  const unsigned char *endMarker;
-  const unsigned char *marker;
-  printk("csum_partial_copy len %d.\n", len);
-#if 0
-  if((int)src & 0x3)
-    printk("unaligned src %p\n", src);
-  if((int)dst & 0x3)
-    printk("unaligned dst %p\n", dst);
-  __delay(1800); /* extra delay of 90 us to test performance hit */
-#endif
-  endMarker = src + len;
-  marker = endMarker - (len % 16);
-  CBITON;
-  while(src < marker) {
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-  }
-  marker = endMarker - (len % 2);
-  while(src < marker) {
-    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
-  }
-  if(endMarker - src > 0) {
-    sum += (*dst = *src);                 /* add extra byte seperately */
-  }
-  CBITOFF;
-  return(sum);
-}
-
-#endif
diff -Nru a/arch/i386/Config.help b/arch/i386/Config.help
--- a/arch/i386/Config.help	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/Config.help	Fri Oct 18 21:03:03 2002
@@ -1094,3 +1094,11 @@
 
   This support is also available as a module.  If compiled as a
   module, it will be called scx200.o.
+
+CONFIG_EDD
+  Say Y or M here if you want to enable BIOS Enhanced Disk Drive
+  Services real mode BIOS calls to determine which disk
+  BIOS tries boot from.  This information is then exported via driverfs.
+
+  This option is experimental, but believed to be safe,
+  and most disk controller BIOS vendors do not yet implement this feature.
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/i386/Makefile	Fri Oct 18 21:03:04 2002
@@ -88,6 +88,6 @@
 	+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install)
 
 archclean:
-	+@$(call makeboot,clean)
+	$(MAKE) -rR -f scripts/Makefile.clean obj=arch/i386/boot
 
 archmrproper:
diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
--- a/arch/i386/boot/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/i386/boot/Makefile	Fri Oct 18 21:03:04 2002
@@ -28,6 +28,8 @@
 EXTRA_TARGETS	:= vmlinux.bin bootsect bootsect.o \
 		   setup setup.o zImage bzImage
 
+subdir- 	:= compressed
+
 host-progs	:= tools/build
 
 # 	Default
@@ -78,11 +80,6 @@
 
 install: $(BOOTIMAGE)
 	sh $(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
-
-clean:
-	@echo 'Cleaning up (boot)'
-	@rm -f $(host-progs) $(EXTRA_TARGETS)
-	+@$(call descend,$(obj)/compressed) clean
 
 archhelp:
 	@echo  '* bzImage	- Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
diff -Nru a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
--- a/arch/i386/boot/compressed/Makefile	Fri Oct 18 21:03:07 2002
+++ b/arch/i386/boot/compressed/Makefile	Fri Oct 18 21:03:07 2002
@@ -24,7 +24,3 @@
 
 $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
 	$(call if_changed,ld)
-
-clean:
-	@echo 'Cleaning up (boot/compressed)'
-	@rm -f $(EXTRA_TARGETS)
diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
--- a/arch/i386/boot/setup.S	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/boot/setup.S	Fri Oct 18 21:03:03 2002
@@ -44,6 +44,9 @@
  *
  * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
  * by Robert Schwebel, December 2001 <robert@schwebel.de>
+ *    
+ * BIOS Enhanced Disk Drive support
+ * by Matt Domsch <Matt_Domsch@dell.com> September 2002 
  *
  */
 
@@ -53,6 +56,7 @@
 #include <linux/compile.h>
 #include <asm/boot.h>
 #include <asm/e820.h>
+#include <asm/edd.h>    
 #include <asm/page.h>
 	
 /* Signature words to ensure LILO loaded us right */
@@ -541,6 +545,49 @@
 no_32_apm_bios:
 	andw	$0xfffd, (76)			# remove 32 bit support bit
 done_apm_bios:
+#endif
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+# Do the BIOS Enhanced Disk Drive calls
+# This code is sensitive to the size of the structs in edd.h
+edd_start:  
+						# %ds points to the bootsector
+       						# result buffer for fn48
+    	movw	$EDDBUF+EDDEXTSIZE, %si		# in ds:si, fn41 results
+						# kept just before that    
+	movb	$0, (EDDNR)			# zero value at EDDNR
+    	movb	$0x80, %dl			# BIOS device 0x80
+
+edd_check_ext:
+	movb	$0x41, %ah			# Function 41
+	movw	$0x55aa, %bx			# magic
+	int	$0x13				# make the call
+	jc	edd_done			# no more BIOS devices
+
+    	cmpw	$0xAA55, %bx			# is magic right?
+	jne	edd_next			# nope, next...
+
+    	movb	%dl, %ds:-4(%si)		# store device number
+    	movb	%ah, %ds:-3(%si)		# store version
+	movw	%cx, %ds:-2(%si)		# store extensions
+	incb	(EDDNR)				# note that we stored something
+        
+edd_get_device_params:  
+	movw	$EDDPARMSIZE, %ds:(%si)		# put size
+    	movb	$0x48, %ah			# Function 48
+	int	$0x13				# make the call
+						# Don't check for fail return
+						# it doesn't matter.
+	movw	%si, %ax			# increment si
+	addw	$EDDPARMSIZE+EDDEXTSIZE, %ax
+	movw	%ax, %si
+
+edd_next:
+        incb	%dl				# increment to next device
+       	cmpb	$EDDMAXNR, (EDDNR) 		# Out of space?
+	jb	edd_check_ext			# keep looping
+    
+edd_done:   
 #endif
 
 # Now we want to move to protected mode ...
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	Fri Oct 18 21:03:04 2002
+++ b/arch/i386/config.in	Fri Oct 18 21:03:04 2002
@@ -216,6 +216,10 @@
 tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR
 tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID
 
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   tristate 'BIOS Enhanced Disk Drive calls determine boot disk (EXPERIMENTAL)' CONFIG_EDD
+fi
+
 choice 'High Memory Support' \
 	"off           CONFIG_NOHIGHMEM \
 	 4GB           CONFIG_HIGHMEM4G \
@@ -453,6 +457,7 @@
 
 bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
 if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+   bool '  Check for stack overflows' CONFIG_DEBUG_STACKOVERFLOW
    bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
    bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig
--- a/arch/i386/defconfig	Fri Oct 18 21:03:06 2002
+++ b/arch/i386/defconfig	Fri Oct 18 21:03:06 2002
@@ -70,6 +70,7 @@
 # CONFIG_MICROCODE is not set
 # CONFIG_X86_MSR is not set
 # CONFIG_X86_CPUID is not set
+# CONFIG_EDD is not set
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
 # CONFIG_HIGHMEM64G is not set
@@ -1138,7 +1139,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/kernel/Makefile	Fri Oct 18 21:03:03 2002
@@ -28,6 +28,7 @@
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_PROFILING)		+= profile.o
+obj-$(CONFIG_EDD)             	+= edd.o
 
 EXTRA_AFLAGS   := -traditional
 
diff -Nru a/arch/i386/kernel/bluesmoke.c b/arch/i386/kernel/bluesmoke.c
--- a/arch/i386/kernel/bluesmoke.c	Fri Oct 18 21:03:04 2002
+++ b/arch/i386/kernel/bluesmoke.c	Fri Oct 18 21:03:04 2002
@@ -300,7 +300,6 @@
 
 static void do_mce_timer(void *data)
 { 
-	mce_checkregs(NULL);
 	smp_call_function (mce_checkregs, NULL, 1, 1);
 } 
 
diff -Nru a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
--- a/arch/i386/kernel/cpu/amd.c	Fri Oct 18 21:03:08 2002
+++ b/arch/i386/kernel/cpu/amd.c	Fri Oct 18 21:03:08 2002
@@ -42,6 +42,21 @@
 
 	switch(c->x86)
 	{
+		case 4:
+		/*
+		 * General Systems BIOSen alias the cpu frequency registers
+		 * of the Elan at 0x000df000. Unfortuantly, one of the Linux
+		 * drivers subsequently pokes it, and changes the CPU speed.
+		 * Workaround : Remove the unneeded alias.
+		 */
+#define CBAR		(0xfffc) /* Configuration Base Address  (32-bit) */
+#define CBAR_ENB	(0x80000000)
+#define CBAR_KEY	(0X000000CB)
+			if (c->x86_model==9 || c->x86_model == 10) {
+				if (inl (CBAR) & CBAR_ENB)
+					outl (0 | CBAR_KEY, CBAR);
+			}
+
 		case 5:
 			if( c->x86_model < 6 )
 			{
diff -Nru a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/kernel/edd.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,984 @@
+/*
+ * linux/arch/i386/kernel/edd.c
+ *  Copyright (C) 2002 Dell Computer Corporation
+ *  by Matt Domsch <Matt_Domsch@dell.com>
+ *
+ * BIOS Enhanced Disk Drive Services (EDD)
+ * conformant to T13 Committee www.t13.org
+ *   projects 1572D, 1484D, 1386D, 1226DT
+ *
+ * This code takes information provided by BIOS EDD calls
+ * fn41 - Check Extensions Present and
+ * fn48 - Get Device Parametes with EDD extensions
+ * made in setup.S, copied to safe structures in setup.c,
+ * and presents it in driverfs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Known issues:
+ * - module unload leaves a directory around.  Seems related to
+ *   creating symlinks in that directory.  Seen on kernel 2.5.41.
+ * - refcounting of struct device objects could be improved.
+ *
+ * TODO:
+ * - Add IDE and USB disk device support
+ * - when driverfs model of discs and partitions changes,
+ *   update symlink accordingly.
+ * - Get symlink creator helper functions exported from
+ *   drivers/base instead of duplicating them here.
+ * - move edd.[ch] to better locations if/when one is decided
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/limits.h>
+#include <linux/driverfs_fs.h>
+#include <linux/pci.h>
+#include <asm/edd.h>
+#include <linux/device.h>
+#include <linux/blkdev.h>
+/* FIXME - this really belongs in include/scsi/scsi.h */
+#include <../drivers/scsi/scsi.h>
+#include <../drivers/scsi/hosts.h>
+
+MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
+MODULE_DESCRIPTION("driverfs interface to BIOS EDD information");
+MODULE_LICENSE("GPL");
+
+#define EDD_VERSION "0.06 2002-Oct-09"
+#define EDD_DEVICE_NAME_SIZE 16
+#define REPORT_URL "http://domsch.com/linux/edd30/results.html"
+
+/*
+ * bios_dir may go away completely,
+ * and it definitely won't be at the root
+ * of driverfs forever.
+ */
+static struct driver_dir_entry bios_dir = {
+	.name = "bios",
+	.mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO),
+};
+
+struct edd_device {
+	char name[EDD_DEVICE_NAME_SIZE];
+	struct edd_info *info;
+	struct list_head node;
+	struct driver_dir_entry dir;
+};
+
+struct edd_attribute {
+	struct attribute attr;
+	ssize_t(*show) (struct edd_device * edev, char *buf, size_t count,
+			loff_t off);
+};
+
+/* forward declarations */
+static int edd_dev_is_type(struct edd_device *edev, const char *type);
+static struct pci_dev *edd_get_pci_dev(struct edd_device *edev);
+static struct scsi_device *edd_find_matching_scsi_device(struct edd_device *edev);
+
+static struct edd_device *edd_devices[EDDMAXNR];
+
+#define EDD_DEVICE_ATTR(_name,_mode,_show) \
+struct edd_attribute edd_attr_##_name = { 	\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.show	= _show,				\
+};
+
+static inline struct edd_info *
+edd_dev_get_info(struct edd_device *edev)
+{
+	return edev->info;
+}
+static inline void
+edd_dev_set_info(struct edd_device *edev, struct edd_info *info)
+{
+	edev->info = info;
+}
+
+#define to_edd_attr(_attr) container_of(_attr,struct edd_attribute,attr)
+#define to_edd_device(_dir) container_of(_dir,struct edd_device,dir)
+
+static ssize_t
+edd_attr_show(struct driver_dir_entry *dir, struct attribute *attr,
+	      char *buf, size_t count, loff_t off)
+{
+	struct edd_device *dev = to_edd_device(dir);
+	struct edd_attribute *edd_attr = to_edd_attr(attr);
+	ssize_t ret = 0;
+
+	if (edd_attr->show)
+		ret = edd_attr->show(dev, buf, count, off);
+	return ret;
+}
+
+static struct driverfs_ops edd_attr_ops = {
+	.show = edd_attr_show,
+};
+
+static int
+edd_dump_raw_data(char *b, void *data, int length)
+{
+	char *orig_b = b;
+	char buffer1[80], buffer2[80], *b1, *b2, c;
+	unsigned char *p = data;
+	unsigned long column = 0;
+	int length_printed = 0;
+	const char maxcolumn = 16;
+	while (length_printed < length) {
+		b1 = buffer1;
+		b2 = buffer2;
+		for (column = 0;
+		     column < maxcolumn && length_printed < length; column++) {
+			b1 += sprintf(b1, "%02x ", (unsigned char) *p);
+			if (*p < 32 || *p > 126)
+				c = '.';
+			else
+				c = *p;
+			b2 += sprintf(b2, "%c", c);
+			p++;
+			length_printed++;
+		}
+		/* pad out the line */
+		for (; column < maxcolumn; column++) {
+			b1 += sprintf(b1, "   ");
+			b2 += sprintf(b2, " ");
+		}
+
+		b += sprintf(b, "%s\t%s\n", buffer1, buffer2);
+	}
+	return (b - orig_b);
+}
+
+static ssize_t
+edd_show_host_bus(struct edd_device *edev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	int i;
+
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (isprint(info->params.host_bus_type[i])) {
+			p += sprintf(p, "%c", info->params.host_bus_type[i]);
+		} else {
+			p += sprintf(p, " ");
+		}
+	}
+
+	if (!strncmp(info->params.host_bus_type, "ISA", 3)) {
+		p += sprintf(p, "\tbase_address: %x\n",
+			     info->params.interface_path.isa.base_address);
+	} else if (!strncmp(info->params.host_bus_type, "PCIX", 4) ||
+		   !strncmp(info->params.host_bus_type, "PCI", 3)) {
+		p += sprintf(p,
+			     "\t%02x:%02x.%01x  channel: %u\n",
+			     info->params.interface_path.pci.bus,
+			     info->params.interface_path.pci.slot,
+			     info->params.interface_path.pci.function,
+			     info->params.interface_path.pci.channel);
+	} else if (!strncmp(info->params.host_bus_type, "IBND", 4) ||
+		   !strncmp(info->params.host_bus_type, "XPRS", 4) ||
+		   !strncmp(info->params.host_bus_type, "HTPT", 4)) {
+		p += sprintf(p,
+			     "\tTBD: %llx\n",
+			     info->params.interface_path.ibnd.reserved);
+
+	} else {
+		p += sprintf(p, "\tunknown: %llx\n",
+			     info->params.interface_path.unknown.reserved);
+	}
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_interface(struct edd_device *edev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	int i;
+
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	for (i = 0; i < 8; i++) {
+		if (isprint(info->params.interface_type[i])) {
+			p += sprintf(p, "%c", info->params.interface_type[i]);
+		} else {
+			p += sprintf(p, " ");
+		}
+	}
+	if (!strncmp(info->params.interface_type, "ATAPI", 5)) {
+		p += sprintf(p, "\tdevice: %u  lun: %u\n",
+			     info->params.device_path.atapi.device,
+			     info->params.device_path.atapi.lun);
+	} else if (!strncmp(info->params.interface_type, "ATA", 3)) {
+		p += sprintf(p, "\tdevice: %u\n",
+			     info->params.device_path.ata.device);
+	} else if (!strncmp(info->params.interface_type, "SCSI", 4)) {
+		p += sprintf(p, "\tid: %u  lun: %llu\n",
+			     info->params.device_path.scsi.id,
+			     info->params.device_path.scsi.lun);
+	} else if (!strncmp(info->params.interface_type, "USB", 3)) {
+		p += sprintf(p, "\tserial_number: %llx\n",
+			     info->params.device_path.usb.serial_number);
+	} else if (!strncmp(info->params.interface_type, "1394", 4)) {
+		p += sprintf(p, "\teui: %llx\n",
+			     info->params.device_path.i1394.eui);
+	} else if (!strncmp(info->params.interface_type, "FIBRE", 5)) {
+		p += sprintf(p, "\twwid: %llx lun: %llx\n",
+			     info->params.device_path.fibre.wwid,
+			     info->params.device_path.fibre.lun);
+	} else if (!strncmp(info->params.interface_type, "I2O", 3)) {
+		p += sprintf(p, "\tidentity_tag: %llx\n",
+			     info->params.device_path.i2o.identity_tag);
+	} else if (!strncmp(info->params.interface_type, "RAID", 4)) {
+		p += sprintf(p, "\tidentity_tag: %x\n",
+			     info->params.device_path.raid.array_number);
+	} else if (!strncmp(info->params.interface_type, "SATA", 4)) {
+		p += sprintf(p, "\tdevice: %u\n",
+			     info->params.device_path.sata.device);
+	} else {
+		p += sprintf(p, "\tunknown: %llx %llx\n",
+			     info->params.device_path.unknown.reserved1,
+			     info->params.device_path.unknown.reserved2);
+	}
+
+	return (p - buf);
+}
+
+/**
+ * edd_show_raw_data() - unparses EDD information, returned to user-space
+ *
+ * Returns: number of bytes written, or 0 on failure
+ */
+static ssize_t
+edd_show_raw_data(struct edd_device *edev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	int i, rc, warn_padding = 0, email = 0, nonzero_path = 0,
+		len = sizeof (*edd) - 4, found_pci=0;
+	uint8_t checksum = 0, c = 0;
+	char *p = buf;
+	struct pci_dev *pci_dev=NULL;
+	struct scsi_device *sd;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE))
+		len = info->params.length;
+
+	p += sprintf(p, "int13 fn48 returned data:\n\n");
+	p += edd_dump_raw_data(p, ((char *) edd) + 4, len);
+
+	/* Spec violation.  Adaptec AIC7899 returns 0xDDBE
+	   here, when it should be 0xBEDD.
+	 */
+	p += sprintf(p, "\n");
+	if (info->params.key == 0xDDBE) {
+		p += sprintf(p,
+			     "Warning: Spec violation.  Key should be 0xBEDD, is 0xDDBE\n");
+		email++;
+	}
+
+	if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) {
+		goto out;
+	}
+
+	for (i = 30; i <= 73; i++) {
+		c = *(((uint8_t *) edd) + i + 4);
+		if (c)
+			nonzero_path++;
+		checksum += c;
+	}
+
+	if (checksum) {
+		p += sprintf(p,
+			     "Warning: Spec violation.  Device Path checksum invalid.\n");
+		email++;
+	}
+
+	if (!nonzero_path) {
+		p += sprintf(p, "Error: Spec violation.  Empty device path.\n");
+		email++;
+		goto out;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (!isprint(info->params.host_bus_type[i])) {
+			warn_padding++;
+		}
+	}
+	for (i = 0; i < 8; i++) {
+		if (!isprint(info->params.interface_type[i])) {
+			warn_padding++;
+		}
+	}
+
+	if (warn_padding) {
+		p += sprintf(p,
+			     "Warning: Spec violation.  Padding should be 0x20.\n");
+		email++;
+	}
+
+	rc = edd_dev_is_type(edev, "PCI");
+	if (!rc) {
+		pci_dev = pci_find_slot(info->params.interface_path.pci.bus,
+					PCI_DEVFN(info->params.interface_path.
+						  pci.slot,
+						  info->params.interface_path.
+						  pci.function));
+		if (!pci_dev) {
+			p += sprintf(p, "Error: BIOS says this is a PCI device, but the OS doesn't know\n");
+			p += sprintf(p, "  about a PCI device at %02x:%02x.%01x\n",
+				     info->params.interface_path.pci.bus,
+				     info->params.interface_path.pci.slot,
+				     info->params.interface_path.pci.function);
+			email++;
+		}
+		else {
+			found_pci++;
+		}
+	}
+
+	if (found_pci) {
+		sd = edd_find_matching_scsi_device(edev);
+		if (!sd) {
+			p += sprintf(p, "Error: BIOS says this is a SCSI device, but\n");
+			p += sprintf(p, "  the OS doesn't know about this SCSI device.\n");
+			p += sprintf(p, "  Do you have it's driver module loaded?\n");
+			email++;
+		}
+	}
+
+out:
+	if (email) {
+		p += sprintf(p, "\nPlease check %s\n", REPORT_URL);
+		p += sprintf(p, "to see if this has been reported.  If not,\n");
+		p += sprintf(p, "please send the information requested there.\n");
+	}
+
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_version(struct edd_device *edev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	p += sprintf(p, "0x%02x\n", info->version);
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_extensions(struct edd_device *edev, char *buf, size_t count,
+		    loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) {
+		p += sprintf(p, "Fixed disk access\n");
+	}
+	if (info->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) {
+		p += sprintf(p, "Device locking and ejecting\n");
+	}
+	if (info->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) {
+		p += sprintf(p, "Enhanced Disk Drive support\n");
+	}
+	if (info->interface_support & EDD_EXT_64BIT_EXTENSIONS) {
+		p += sprintf(p, "64-bit extensions\n");
+	}
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_info_flags(struct edd_device *edev, char *buf, size_t count,
+		    loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	if (info->params.info_flags & EDD_INFO_DMA_BOUNDRY_ERROR_TRANSPARENT)
+		p += sprintf(p, "DMA boundry error transparent\n");
+	if (info->params.info_flags & EDD_INFO_GEOMETRY_VALID)
+		p += sprintf(p, "geometry valid\n");
+	if (info->params.info_flags & EDD_INFO_REMOVABLE)
+		p += sprintf(p, "removable\n");
+	if (info->params.info_flags & EDD_INFO_WRITE_VERIFY)
+		p += sprintf(p, "write verify\n");
+	if (info->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION)
+		p += sprintf(p, "media change notification\n");
+	if (info->params.info_flags & EDD_INFO_LOCKABLE)
+		p += sprintf(p, "lockable\n");
+	if (info->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT)
+		p += sprintf(p, "no media present\n");
+	if (info->params.info_flags & EDD_INFO_USE_INT13_FN50)
+		p += sprintf(p, "use int13 fn50\n");
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_default_cylinders(struct edd_device *edev, char *buf, size_t count,
+			   loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	p += sprintf(p, "0x%x\n", info->params.num_default_cylinders);
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_default_heads(struct edd_device *edev, char *buf, size_t count,
+		       loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	p += sprintf(p, "0x%x\n", info->params.num_default_heads);
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_default_sectors_per_track(struct edd_device *edev, char *buf,
+				   size_t count, loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	p += sprintf(p, "0x%x\n", info->params.sectors_per_track);
+	return (p - buf);
+}
+
+static ssize_t
+edd_show_sectors(struct edd_device *edev, char *buf, size_t count, loff_t off)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	char *p = buf;
+	if (!edev || !info || !buf || off) {
+		return 0;
+	}
+
+	p += sprintf(p, "0x%llx\n", info->params.number_of_sectors);
+	return (p - buf);
+}
+
+static EDD_DEVICE_ATTR(raw_data, 0444, edd_show_raw_data);
+static EDD_DEVICE_ATTR(version, 0444, edd_show_version);
+static EDD_DEVICE_ATTR(extensions, 0444, edd_show_extensions);
+static EDD_DEVICE_ATTR(info_flags, 0444, edd_show_info_flags);
+static EDD_DEVICE_ATTR(default_cylinders, 0444, edd_show_default_cylinders);
+static EDD_DEVICE_ATTR(default_heads, 0444, edd_show_default_heads);
+static EDD_DEVICE_ATTR(default_sectors_per_track, 0444,
+		       edd_show_default_sectors_per_track);
+static EDD_DEVICE_ATTR(sectors, 0444, edd_show_sectors);
+static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface);
+static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus);
+
+/*
+ * Some device instances may not have all the above attributes,
+ * or the attribute values may be meaningless (i.e. if
+ * the device is < EDD 3.0, it won't have host_bus and interface
+ * information), so don't bother making files for them.  Likewise
+ * if the default_{cylinders,heads,sectors_per_track} values
+ * are zero, the BIOS doesn't provide sane values, don't bother
+ * creating files for them either.
+ *
+ * struct attr_test pairs an attribute and a test,
+ * (the default NULL test being true - the attribute exists)
+ * and individual existence tests may be written for each
+ * attribute.
+ */
+struct attr_test {
+	struct edd_attribute *attr;
+	int (*test) (struct edd_device * edev);
+};
+
+static int
+edd_has_default_cylinders(struct edd_device *edev)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	if (!edev || !info)
+		return 1;
+	return !info->params.num_default_cylinders;
+}
+
+static int
+edd_has_default_heads(struct edd_device *edev)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	if (!edev || !info)
+		return 1;
+	return !info->params.num_default_heads;
+}
+
+static int
+edd_has_default_sectors_per_track(struct edd_device *edev)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	if (!edev || !info)
+		return 1;
+	return !info->params.sectors_per_track;
+}
+
+static int
+edd_has_edd30(struct edd_device *edev)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	int i, nonzero_path = 0;
+	char c;
+
+	if (!edev || !info)
+		return 1;
+
+	if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) {
+		return 1;
+	}
+
+	for (i = 30; i <= 73; i++) {
+		c = *(((uint8_t *) edd) + i + 4);
+		if (c) {
+			nonzero_path++;
+			break;
+		}
+	}
+	if (!nonzero_path) {
+		return 1;
+	}
+
+	return 0;
+}
+
+static struct attr_test def_attrs[] = {
+	{.attr = &edd_attr_raw_data},
+	{.attr = &edd_attr_version},
+	{.attr = &edd_attr_extensions},
+	{.attr = &edd_attr_info_flags},
+	{.attr = &edd_attr_sectors},
+	{.attr = &edd_attr_default_cylinders,
+	 .test = &edd_has_default_cylinders},
+	{.attr = &edd_attr_default_heads,
+	 .test = &edd_has_default_heads},
+	{.attr = &edd_attr_default_sectors_per_track,
+	 .test = &edd_has_default_sectors_per_track},
+	{.attr = &edd_attr_interface,
+	 .test = &edd_has_edd30},
+	{.attr = &edd_attr_host_bus,
+	 .test = &edd_has_edd30},
+	{.attr = NULL,.test = NULL},
+};
+
+/* edd_get_devpath_length(), edd_fill_devpath(), and edd_device_link()
+   were taken from linux/drivers/base/fs/device.c.  When these
+   or similar are exported to generic code, remove these.
+*/
+
+static int
+edd_get_devpath_length(struct device *dev)
+{
+	int length = 1;
+	struct device *parent = dev;
+
+	/* walk up the ancestors until we hit the root.
+	 * Add 1 to strlen for leading '/' of each level.
+	 */
+	do {
+		length += strlen(parent->bus_id) + 1;
+		parent = parent->parent;
+	} while (parent);
+	return length;
+}
+
+static void
+edd_fill_devpath(struct device *dev, char *path, int length)
+{
+	struct device *parent;
+	--length;
+	for (parent = dev; parent; parent = parent->parent) {
+		int cur = strlen(parent->bus_id);
+
+		/* back up enough to print this bus id with '/' */
+		length -= cur;
+		strncpy(path + length, parent->bus_id, cur);
+		*(path + --length) = '/';
+	}
+}
+
+static int
+edd_device_symlink(struct edd_device *edev, struct device *dev, char *name)
+{
+	char *path;
+	int length;
+	int error = 0;
+
+	if (!dev->bus || !name)
+		return 0;
+
+	length = edd_get_devpath_length(dev);
+
+	/* now add the path from the edd_device directory
+	 * It should be '../..' (one to get to the 'bios' directory,
+	 * and one to get to the root of the fs.)
+	 */
+	length += strlen("../../root");
+
+	if (length > PATH_MAX)
+		return -ENAMETOOLONG;
+
+	if (!(path = kmalloc(length, GFP_KERNEL)))
+		return -ENOMEM;
+	memset(path, 0, length);
+
+	/* our relative position */
+	strcpy(path, "../../root");
+
+	edd_fill_devpath(dev, path, length);
+	error = driverfs_create_symlink(&edev->dir, name, path);
+	kfree(path);
+	return error;
+}
+
+/**
+ * edd_dev_is_type() - is this EDD device a 'type' device?
+ * @edev
+ * @type - a host bus or interface identifier string per the EDD spec
+ *
+ * Returns 0 if it is a 'type' device, nonzero otherwise.
+ */
+static int
+edd_dev_is_type(struct edd_device *edev, const char *type)
+{
+	int rc;
+	struct edd_info *info = edd_dev_get_info(edev);
+	if (!edev || !info)
+		return 1;
+
+	rc = strncmp(info->params.host_bus_type, type, strlen(type));
+	if (!rc)
+		return 0;
+
+	return strncmp(info->params.interface_type, type, strlen(type));
+}
+
+/**
+ * edd_get_pci_dev() - finds pci_dev that matches edev
+ * @edev - edd_device
+ *
+ * Returns pci_dev if found, or NULL
+ */
+static struct pci_dev *
+edd_get_pci_dev(struct edd_device *edev)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+	int rc;
+
+	rc = edd_dev_is_type(edev, "PCI");
+	if (rc)
+		return NULL;
+
+	return pci_find_slot(info->params.interface_path.pci.bus,
+			     PCI_DEVFN(info->params.interface_path.pci.slot,
+				       info->params.interface_path.pci.
+				       function));
+}
+
+static int
+edd_create_symlink_to_pcidev(struct edd_device *edev)
+{
+
+	struct pci_dev *pci_dev = edd_get_pci_dev(edev);
+	if (!pci_dev)
+		return 1;
+	return edd_device_symlink(edev, &pci_dev->dev, "pci_dev");
+}
+
+/**
+ * edd_match_scsidev()
+ * @edev - EDD device is a known SCSI device
+ * @sd - scsi_device with host who's parent is a PCI controller
+ * 
+ * returns 0 on success, 1 on failure
+ */
+static int
+edd_match_scsidev(struct edd_device *edev, struct scsi_device *sd)
+{
+	struct edd_info *info = edd_dev_get_info(edev);
+
+	if (!edev || !sd || !info)
+		return 1;
+
+	if ((sd->channel == info->params.interface_path.pci.channel) &&
+	    (sd->id == info->params.device_path.scsi.id) &&
+	    (sd->lun == info->params.device_path.scsi.lun)) {
+		return 0;
+	}
+
+	return 1;
+}
+
+/**
+ * edd_find_matching_device()
+ * @edev - edd_device to match
+ *
+ * Returns struct scsi_device * on success,
+ * or NULL on failure.
+ * This assumes that all children of the PCI controller
+ * are scsi_hosts, and that all children of scsi_hosts
+ * are scsi_devices.
+ * The reference counting probably isn't the best it could be.
+ */
+
+#define	to_scsi_host(d)	\
+	container_of(d, struct Scsi_Host, host_driverfs_dev)
+#define children_to_dev(n) container_of(n,struct device,node)
+static struct scsi_device *
+edd_find_matching_scsi_device(struct edd_device *edev)
+{
+	struct list_head *shost_node, *sdev_node;
+	int rc = 1;
+	struct scsi_device *sd = NULL;
+	struct device *shost_dev, *sdev_dev;
+	struct pci_dev *pci_dev;
+	struct Scsi_Host *sh;
+
+	rc = edd_dev_is_type(edev, "SCSI");
+	if (rc)
+		return NULL;
+
+	pci_dev = edd_get_pci_dev(edev);
+	if (!pci_dev)
+		return NULL;
+
+	get_device(&pci_dev->dev);
+
+	list_for_each(shost_node, &pci_dev->dev.children) {
+		shost_dev = children_to_dev(shost_node);
+		get_device(shost_dev);
+		sh = to_scsi_host(shost_dev);
+
+		list_for_each(sdev_node, &shost_dev->children) {
+			sdev_dev = children_to_dev(sdev_node);
+			get_device(sdev_dev);
+			sd = to_scsi_device(sdev_dev);
+			rc = edd_match_scsidev(edev, sd);
+			put_device(sdev_dev);
+			if (!rc)
+				break;
+		}
+		put_device(shost_dev);
+		if (!rc)
+			break;
+	}
+
+	put_device(&pci_dev->dev);
+	if (!rc)
+		return sd;
+	return NULL;
+}
+
+static int
+edd_create_symlink_to_scsidev(struct edd_device *edev)
+{
+
+	struct scsi_device *sdev;
+	struct pci_dev *pci_dev;
+	struct edd_info *info = edd_dev_get_info(edev);
+	int rc;
+
+	rc = edd_dev_is_type(edev, "PCI");
+	if (rc)
+		return rc;
+
+	pci_dev = pci_find_slot(info->params.interface_path.pci.bus,
+				PCI_DEVFN(info->params.interface_path.pci.slot,
+					  info->params.interface_path.pci.
+					  function));
+	if (!pci_dev)
+		return 1;
+
+	sdev = edd_find_matching_scsi_device(edev);
+	if (!sdev)
+		return 1;
+
+	get_device(&sdev->sdev_driverfs_dev);
+	rc = edd_device_symlink(edev, &sdev->sdev_driverfs_dev, "disc");
+	put_device(&sdev->sdev_driverfs_dev);
+
+	return rc;
+}
+
+static inline int
+edd_create_file(struct edd_device *edev, struct edd_attribute *attr)
+{
+	return driverfs_create_file(&attr->attr, &edev->dir);
+}
+
+static inline void
+edd_device_unregister(struct edd_device *edev)
+{
+	driverfs_remove_file(&edev->dir, "pci_dev");
+	driverfs_remove_file(&edev->dir, "disc");
+	driverfs_remove_dir(&edev->dir);
+	list_del_init(&edev->node);
+}
+
+static int
+edd_populate_dir(struct edd_device *edev)
+{
+	struct attr_test *s;
+	int i;
+	int error = 0;
+
+	for (i = 0; def_attrs[i].attr; i++) {
+		s = &def_attrs[i];
+		if (!s->test || (s->test && !s->test(edev))) {
+			if ((error = edd_create_file(edev, s->attr))) {
+				break;
+			}
+		}
+	}
+
+	if (error)
+		return error;
+
+	edd_create_symlink_to_pcidev(edev);
+	edd_create_symlink_to_scsidev(edev);
+
+	return 0;
+}
+
+static int
+edd_make_dir(struct edd_device *edev)
+{
+	int error;
+
+	edev->dir.name = edev->name;
+	edev->dir.mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
+	edev->dir.ops = &edd_attr_ops;
+
+	error = driverfs_create_dir(&edev->dir, &bios_dir);
+	if (!error)
+		error = edd_populate_dir(edev);
+	return error;
+}
+
+static int
+edd_device_register(struct edd_device *edev, int i)
+{
+	int error;
+
+	if (!edev)
+		return 1;
+	memset(edev, 0, sizeof (*edev));
+	edd_dev_set_info(edev, &edd[i]);
+	snprintf(edev->name, EDD_DEVICE_NAME_SIZE, "int13_dev%02x",
+		 edd[i].device);
+	error = edd_make_dir(edev);
+	return error;
+}
+
+/**
+ * edd_init() - creates driverfs tree of EDD data
+ *
+ * This assumes that eddnr and edd were
+ * assigned in setup.c already.
+ */
+static int __init
+edd_init(void)
+{
+	unsigned int i;
+	int rc;
+	struct edd_device *edev;
+
+	printk(KERN_INFO "BIOS EDD facility v%s, %d devices found\n",
+	       EDD_VERSION, eddnr);
+
+	if (!eddnr) {
+		printk(KERN_INFO "EDD information not available.\n");
+		return 1;
+	}
+
+	rc = driverfs_create_dir(&bios_dir, NULL);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < eddnr && i < EDDMAXNR && !rc; i++) {
+		edev = kmalloc(sizeof (*edev), GFP_KERNEL);
+		if (!edev)
+			return -ENOMEM;
+
+		rc = edd_device_register(edev, i);
+		if (rc) {
+			kfree(edev);
+			break;
+		}
+		edd_devices[i] = edev;
+	}
+
+	if (rc) {
+		driverfs_remove_dir(&bios_dir);
+		return rc;
+	}
+
+	return 0;
+}
+
+static void __exit
+edd_exit(void)
+{
+	int i;
+	struct edd_device *edev;
+
+	for (i = 0; i < eddnr && i < EDDMAXNR; i++) {
+		if ((edev = edd_devices[i])) {
+			edd_device_unregister(edev);
+			kfree(edev);
+		}
+	}
+
+	driverfs_remove_dir(&bios_dir);
+}
+
+late_initcall(edd_init);
+module_exit(edd_exit);
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	Fri Oct 18 21:03:08 2002
+++ b/arch/i386/kernel/i386_ksyms.c	Fri Oct 18 21:03:08 2002
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/tty.h>
+#include <linux/highmem.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -30,6 +31,7 @@
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/nmi.h>
+#include <asm/edd.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern spinlock_t rtc_lock;
@@ -192,3 +194,16 @@
 EXPORT_SYMBOL(is_sony_vaio_laptop);
 
 EXPORT_SYMBOL(__PAGE_KERNEL);
+
+#ifdef CONFIG_HIGHMEM
+EXPORT_SYMBOL(kmap);
+EXPORT_SYMBOL(kunmap);
+EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_to_page);
+#endif
+
+#ifdef CONFIG_EDD_MODULE
+EXPORT_SYMBOL(edd);
+EXPORT_SYMBOL(eddnr);
+#endif
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Fri Oct 18 21:03:04 2002
+++ b/arch/i386/kernel/io_apic.c	Fri Oct 18 21:03:04 2002
@@ -856,7 +856,9 @@
 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
 	printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)&reg_00);
 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.ID);
-	if (reg_00.__reserved_1 || reg_00.__reserved_2)
+	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.delivery_type);
+	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.LTS);
+	if (reg_00.__reserved_0 || reg_00.__reserved_1 || reg_00.__reserved_2)
 		UNEXPECTED_IO_APIC();
 
 	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/kernel/irq.c	Fri Oct 18 21:03:03 2002
@@ -328,8 +328,22 @@
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
 	unsigned int status;
+	long esp;
 
 	irq_enter();
+
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	/* Debugging check for stack overflow: is there less than 1KB free? */
+	__asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191));
+	if (unlikely(esp < (sizeof(struct task_struct) + 1024))) {
+		extern void show_stack(unsigned long *);
+
+		printk("do_IRQ: stack overflow: %ld\n",
+		esp - sizeof(struct task_struct));
+		__asm__ __volatile__("movl %%esp,%0" : "=r" (esp));
+		show_stack((void *)esp);
+	}
+#endif
 	kstat.irqs[cpu][irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
--- a/arch/i386/kernel/microcode.c	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/kernel/microcode.c	Fri Oct 18 21:03:03 2002
@@ -260,7 +260,7 @@
 			
 			if (microcode[i].rev < rev) {
 				spin_unlock_irqrestore(&microcode_update_lock, flags);
-				printk(KERN_ERR 
+				printk(KERN_INFO
 				       "microcode: CPU%d not 'upgrading' to earlier revision"
 				       " %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
 				return;
@@ -268,7 +268,7 @@
 				/* notify the caller of success on this cpu */
 				req->err = 0;
 				spin_unlock_irqrestore(&microcode_update_lock, flags);
-				printk(KERN_ERR 
+				printk(KERN_INFO
 					"microcode: CPU%d already at revision"
 					" %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
 				return;
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Fri Oct 18 21:03:04 2002
+++ b/arch/i386/kernel/setup.c	Fri Oct 18 21:03:04 2002
@@ -36,6 +36,7 @@
 #include <linux/highmem.h>
 #include <asm/e820.h>
 #include <asm/mpspec.h>
+#include <asm/edd.h>
 #include <asm/setup.h>
 #include <asm/arch_hooks.h>
 #include "setup_arch_pre.h"
@@ -466,6 +467,22 @@
 	return 0;
 }
 
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+unsigned char eddnr;
+struct edd_info edd[EDDNR];
+/**
+ * copy_edd() - Copy the BIOS EDD information into a safe place.
+ *
+ */
+static inline void copy_edd(void)
+{
+     eddnr = EDD_NR;
+     memcpy(edd, EDD_BUF, sizeof(edd));
+}
+#else
+#define copy_edd() do {} while (0)
+#endif
+
 /*
  * Do NOT EVER look at the BIOS memory size location.
  * It does not work on many machines.
@@ -843,6 +860,7 @@
 #endif
 	ARCH_SETUP
 	setup_memory_region();
+	copy_edd();
 
 	if (!MOUNT_ROOT_RDONLY)
 		root_mountflags &= ~MS_RDONLY;
diff -Nru a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
--- a/arch/i386/lib/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/lib/Makefile	Fri Oct 18 21:03:03 2002
@@ -4,7 +4,7 @@
 
 L_TARGET = lib.a
 
-obj-y = checksum.o old-checksum.o delay.o \
+obj-y = checksum.o delay.o \
 	usercopy.o getuser.o \
 	memcpy.o strstr.o
 
diff -Nru a/arch/i386/lib/old-checksum.c b/arch/i386/lib/old-checksum.c
--- a/arch/i386/lib/old-checksum.c	Fri Oct 18 21:03:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,19 +0,0 @@
-/*
- * FIXME: old compatibility stuff, will be removed soon.
- */
-
-#include <net/checksum.h>
-
-unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum)
-{
-	int src_err=0, dst_err=0;
-
-	sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err);
-
-	if (src_err || dst_err)
-		printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n");
-
-	return sum;
-}
-
-
diff -Nru a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
--- a/arch/i386/mm/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/i386/mm/Makefile	Fri Oct 18 21:03:04 2002
@@ -4,8 +4,10 @@
 
 export-objs := pageattr.o
 
-obj-y	:= init.o pgtable.o fault.o ioremap.o extable.o pageattr.o 
+obj-y	:= init.o pgtable.o fault.o ioremap.o extable.o pageattr.o
+
 obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_HIGHMEM) += highmem.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/mm/highmem.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,85 @@
+#include <linux/highmem.h>
+
+void *kmap(struct page *page)
+{
+	if (in_interrupt())
+		BUG();
+	if (page < highmem_start_page)
+		return page_address(page);
+	return kmap_high(page);
+}
+
+void kunmap(struct page *page)
+{
+	if (in_interrupt())
+		BUG();
+	if (page < highmem_start_page)
+		return;
+	kunmap_high(page);
+}
+
+/*
+ * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
+ * gives a more generic (and caching) interface. But kmap_atomic can
+ * be used in IRQ contexts, so in some (very limited) cases we need
+ * it.
+ */
+void *kmap_atomic(struct page *page, enum km_type type)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	inc_preempt_count();
+	if (page < highmem_start_page)
+		return page_address(page);
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#if CONFIG_DEBUG_HIGHMEM
+	if (!pte_none(*(kmap_pte-idx)))
+		BUG();
+#endif
+	set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
+	__flush_tlb_one(vaddr);
+
+	return (void*) vaddr;
+}
+
+void kunmap_atomic(void *kvaddr, enum km_type type)
+{
+#if CONFIG_DEBUG_HIGHMEM
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+	if (vaddr < FIXADDR_START) { // FIXME
+		dec_preempt_count();
+		return;
+	}
+
+	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
+		BUG();
+
+	/*
+	 * force other mappings to Oops if they'll try to access
+	 * this pte without first remap it
+	 */
+	pte_clear(kmap_pte-idx);
+	__flush_tlb_one(vaddr);
+#endif
+
+	dec_preempt_count();
+}
+
+struct page *kmap_atomic_to_page(void *ptr)
+{
+	unsigned long idx, vaddr = (unsigned long)ptr;
+	pte_t *pte;
+
+	if (vaddr < FIXADDR_START)
+		return virt_to_page(ptr);
+
+	idx = virt_to_fix(vaddr);
+	pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
+	return pte_page(*pte);
+}
+
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Fri Oct 18 21:03:07 2002
+++ b/arch/i386/mm/init.c	Fri Oct 18 21:03:07 2002
@@ -482,7 +482,7 @@
 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
+	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
 		num_physpages << (PAGE_SHIFT-10),
 		codesize >> 10,
@@ -584,14 +584,14 @@
 		free_page(addr);
 		totalram_pages++;
 	}
-	printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+	printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
 	if (start < end)
-		printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+		printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 	for (; start < end; start += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(start));
 		set_page_count(virt_to_page(start), 1);
diff -Nru a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
--- a/arch/i386/pci/i386.c	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/pci/i386.c	Fri Oct 18 21:03:03 2002
@@ -291,7 +291,7 @@
 		lat = pcibios_max_latency;
 	else
 		return;
-	printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
+	printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
--- a/arch/i386/vmlinux.lds.S	Fri Oct 18 21:03:03 2002
+++ b/arch/i386/vmlinux.lds.S	Fri Oct 18 21:03:03 2002
@@ -8,6 +8,7 @@
 SECTIONS
 {
   . = 0xC0000000 + 0x100000;
+  /* read-only */
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
@@ -29,23 +30,41 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___kallsyms = .;       /* All kernel symbols */
+  __kallsyms : { *(__kallsyms) }
+  __stop___kallsyms = .;
+
+  /* writeable */
   .data : {			/* Data */
 	*(.data)
 	CONSTRUCTORS
 	}
 
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
   _edata = .;			/* End of data section */
 
   . = ALIGN(8192);		/* init_task */
   .data.init_task : { *(.data.init_task) }
 
+  /* will be freed after init */
   . = ALIGN(4096);		/* Init code and data */
   __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
+  .init.text : { *(.init.text) }
+  .init.data : { *(.init.data) }
   . = ALIGN(16);
   __setup_start = .;
-  .setup.init : { *(.setup.init) }
+  .init.setup : { *(.init.setup) }
   __setup_end = .;
   __initcall_start = .;
   .initcall.init : {
@@ -64,23 +83,8 @@
   __per_cpu_end = .;
   . = ALIGN(4096);
   __init_end = .;
-
-  . = ALIGN(4096);
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
-  __nosave_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  __start___kallsyms = .;     /* All kernel symbols */
-  __kallsyms : { *(__kallsyms) }
-  __stop___kallsyms = .;
-
+  /* freed after init ends here */
+	
   __bss_start = .;		/* BSS */
   .bss : { *(.bss) }
   __bss_stop = .; 
@@ -89,8 +93,8 @@
 
   /* Sections to be discarded */
   /DISCARD/ : {
-	*(.text.exit)
-	*(.data.exit)
+	*(.exit.text)
+	*(.exit.data)
 	*(.exitcall.exit)
 	}
 
diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig
--- a/arch/ia64/defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ia64/defconfig	Fri Oct 18 21:03:03 2002
@@ -919,7 +919,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	Fri Oct 18 21:03:05 2002
+++ b/arch/ia64/ia32/sys_ia32.c	Fri Oct 18 21:03:05 2002
@@ -1664,20 +1664,11 @@
 	kmsg->msg_control = (void *) orig_cmsg_uptr;
 }
 
-static inline void
-sockfd_put (struct socket *sock)
-{
-	fput(sock->file);
-}
-
 /* 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);
-
 /*
  *	BSD sendmsg interface
  */
@@ -3772,12 +3763,15 @@
 	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
 	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 
+	if (s32->version != SMB_MOUNT_OLDVERSION)
+		goto out;
 	s->version = s32->version;
 	s->mounted_uid = s32->mounted_uid;
 	s->uid = s32->uid;
 	s->gid = s32->gid;
 	s->file_mode = s32->file_mode;
 	s->dir_mode = s32->dir_mode;
+out:
 	return raw_data;
 }
 
diff -Nru a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c
--- a/arch/ia64/lib/csum_partial_copy.c	Fri Oct 18 21:03:05 2002
+++ b/arch/ia64/lib/csum_partial_copy.c	Fri Oct 18 21:03:05 2002
@@ -146,16 +146,3 @@
 	return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
 }
 
-unsigned int
-csum_partial_copy (const char *src, char *dst, int len, unsigned int sum)
-{
-	unsigned int ret;
-	int error = 0;
-
-	ret = do_csum_partial_copy_from_user(src, dst, len, sum, &error);
-	if (error)
-		printk("csum_partial_copy_old(): tell mingo to convert me!\n");
-
-	return ret;
-}
-
diff -Nru a/arch/ia64/sn/configs/sn1/defconfig-bigsur-mp b/arch/ia64/sn/configs/sn1/defconfig-bigsur-mp
--- a/arch/ia64/sn/configs/sn1/defconfig-bigsur-mp	Fri Oct 18 21:03:04 2002
+++ b/arch/ia64/sn/configs/sn1/defconfig-bigsur-mp	Fri Oct 18 21:03:04 2002
@@ -741,7 +741,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn1/defconfig-bigsur-sp b/arch/ia64/sn/configs/sn1/defconfig-bigsur-sp
--- a/arch/ia64/sn/configs/sn1/defconfig-bigsur-sp	Fri Oct 18 21:03:04 2002
+++ b/arch/ia64/sn/configs/sn1/defconfig-bigsur-sp	Fri Oct 18 21:03:04 2002
@@ -741,7 +741,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn1/defconfig-sn1-mp b/arch/ia64/sn/configs/sn1/defconfig-sn1-mp
--- a/arch/ia64/sn/configs/sn1/defconfig-sn1-mp	Fri Oct 18 21:03:08 2002
+++ b/arch/ia64/sn/configs/sn1/defconfig-sn1-mp	Fri Oct 18 21:03:08 2002
@@ -702,7 +702,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-modules b/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-modules
--- a/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-modules	Fri Oct 18 21:03:06 2002
+++ b/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-modules	Fri Oct 18 21:03:06 2002
@@ -704,7 +704,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-syn1-0 b/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-syn1-0
--- a/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-syn1-0	Fri Oct 18 21:03:04 2002
+++ b/arch/ia64/sn/configs/sn1/defconfig-sn1-mp-syn1-0	Fri Oct 18 21:03:04 2002
@@ -702,7 +702,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn1/defconfig-sn1-sp b/arch/ia64/sn/configs/sn1/defconfig-sn1-sp
--- a/arch/ia64/sn/configs/sn1/defconfig-sn1-sp	Fri Oct 18 21:03:03 2002
+++ b/arch/ia64/sn/configs/sn1/defconfig-sn1-sp	Fri Oct 18 21:03:03 2002
@@ -702,7 +702,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn2/defconfig-sn2-mp b/arch/ia64/sn/configs/sn2/defconfig-sn2-mp
--- a/arch/ia64/sn/configs/sn2/defconfig-sn2-mp	Fri Oct 18 21:03:03 2002
+++ b/arch/ia64/sn/configs/sn2/defconfig-sn2-mp	Fri Oct 18 21:03:03 2002
@@ -701,7 +701,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn2/defconfig-sn2-mp-modules b/arch/ia64/sn/configs/sn2/defconfig-sn2-mp-modules
--- a/arch/ia64/sn/configs/sn2/defconfig-sn2-mp-modules	Fri Oct 18 21:03:06 2002
+++ b/arch/ia64/sn/configs/sn2/defconfig-sn2-mp-modules	Fri Oct 18 21:03:06 2002
@@ -703,7 +703,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ia64/sn/configs/sn2/defconfig-sn2-sp b/arch/ia64/sn/configs/sn2/defconfig-sn2-sp
--- a/arch/ia64/sn/configs/sn2/defconfig-sn2-sp	Fri Oct 18 21:03:03 2002
+++ b/arch/ia64/sn/configs/sn2/defconfig-sn2-sp	Fri Oct 18 21:03:03 2002
@@ -701,7 +701,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
--- a/arch/m68k/atari/stram.c	Fri Oct 18 21:03:07 2002
+++ b/arch/m68k/atari/stram.c	Fri Oct 18 21:03:07 2002
@@ -978,17 +978,10 @@
 
 static void do_stram_request(request_queue_t *q)
 {
-	void *start;
-	unsigned long len;
-
-	while (1) {
-		struct request *req;
-		if (blk_queue_empty(QUEUE))
-			return;
-
-		req = CURRENT;
-		start = swap_start + (req->sector << 9);
-		len   = req->current_nr_sectors << 9;
+	while (!blk_queue_empty(q)) {
+		struct request *req = elv_next_request(q);
+		void *start = swap_start + (req->sector << 9);
+		unsigned long len = req->current_nr_sectors << 9;
 		if ((start + len) > swap_end) {
 			printk( KERN_ERR "stram: bad access beyond end of device: "
 					"block=%ld, count=%ld\n",
@@ -1045,6 +1038,8 @@
 };
 
 static struct gendisk *stram_disk;
+static struct request_queue stram_queue;
+static spinlock_t stram_lock = SPIN_LOCK_UNLOCKED;
 
 int __init stram_device_init(void)
 {
@@ -1065,10 +1060,11 @@
 		return -ENXIO;
 	}
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request);
+	blk_init_queue(&stram_queue, do_stram_request, &stram_lock);
 	stram_disk->major = STRAM_MAJOR;
 	stram_disk->first_minor = STRAM_MINOR;
 	stram_disk->fops = &stram_fops;
+	stram_disk->queue = &stram_queue;
 	sprintf(stram_disk->disk_name, "stram");
 	set_capacity(stram_disk, (swap_end - swap_start)/512);
 	add_disk(stram_disk);
diff -Nru a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
--- a/arch/m68k/kernel/m68k_ksyms.c	Fri Oct 18 21:03:08 2002
+++ b/arch/m68k/kernel/m68k_ksyms.c	Fri Oct 18 21:03:08 2002
@@ -61,9 +61,6 @@
 EXPORT_SYMBOL(vme_brdtype);
 #endif
 
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
-
 /* The following are special because they're not called
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
diff -Nru a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
--- a/arch/m68k/lib/checksum.c	Fri Oct 18 21:03:08 2002
+++ b/arch/m68k/lib/checksum.c	Fri Oct 18 21:03:08 2002
@@ -318,103 +318,3 @@
 
 	return(sum);
 }
-
-/*
- * copy from kernel space while checksumming, otherwise like csum_partial
- */
-
-unsigned int
-csum_partial_copy(const char *src, char *dst, int len, int sum)
-{
-	unsigned long tmp1, tmp2;
-	__asm__("movel %2,%4\n\t"
-		"btst #1,%4\n\t"	/* Check alignment */
-		"jeq 2f\n\t"
-		"subql #2,%1\n\t"	/* buff%4==2: treat first word */
-		"jgt 1f\n\t"
-		"addql #2,%1\n\t"	/* len was == 2, treat only rest */
-		"jra 4f\n"
-	     "1:\t"
-		"movew %2@+,%4\n\t"	/* add first word to sum */
-		"addw %4,%0\n\t"
-		"movew %4,%3@+\n\t"
-		"clrl %4\n\t"
-		"addxl %4,%0\n"		/* add X bit */
-	     "2:\t"
-		/* unrolled loop for the main part: do 8 longs at once */
-		"movel %1,%4\n\t"	/* save len in tmp1 */
-		"lsrl #5,%1\n\t"	/* len/32 */
-		"jeq 2f\n\t"		/* not enough... */
-		"subql #1,%1\n"
-	     "1:\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"dbra %1,1b\n\t"
-		"clrl %5\n\t"
-		"addxl %5,%0\n\t"	/* add X bit */
-		"clrw %1\n\t"
-		"subql #1,%1\n\t"
-		"jcc 1b\n"
-	     "2:\t"
-		"movel %4,%1\n\t"	/* restore len from tmp1 */
-		"andw #0x1c,%4\n\t"	/* number of rest longs */
-		"jeq 4f\n\t"
-		"lsrw #2,%4\n\t"
-		"subqw #1,%4\n"
-	     "3:\t"
-		/* loop for rest longs */
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"dbra %4,3b\n\t"
-		"clrl %5\n\t"
-		"addxl %5,%0\n"		/* add X bit */
-	     "4:\t"
-		/* now check for rest bytes that do not fit into longs */
-		"andw #3,%1\n\t"
-		"jeq 7f\n\t"
-		"clrl %5\n\t"		/* clear tmp2 for rest bytes */
-		"subqw #2,%1\n\t"
-		"jlt 5f\n\t"
-		"movew %2@+,%5\n\t"	/* have rest >= 2: get word */
-		"movew %5,%3@+\n\t"
-		"swap %5\n\t"		/* into bits 16..31 */
-		"tstw %1\n\t"		/* another byte? */
-		"jeq 6f\n"
-	     "5:\t"
-		"moveb %2@,%5\n\t"	/* have odd rest: get byte */
-		"moveb %5,%3@+\n\t"
-		"lslw #8,%5\n"		/* into bits 8..15; 16..31 untouched */
-	     "6:\t"
-		"addl %5,%0\n\t"	/* now add rest long to sum */
-		"clrl %5\n\t"
-		"addxl %5,%0\n"		/* add X bit */
-	     "7:\t"
-		: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
-		  "=&d" (tmp1), "=&d" (tmp2)
-		: "0" (sum), "1" (len), "2" (src), "3" (dst)
-	    );
-    return(sum);
-}
diff -Nru a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
--- a/arch/mips/kernel/mips_ksyms.c	Fri Oct 18 21:03:03 2002
+++ b/arch/mips/kernel/mips_ksyms.c	Fri Oct 18 21:03:03 2002
@@ -79,9 +79,6 @@
 EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
 
 
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
-
 /*
  * Functions to control caches.
  */
diff -Nru a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
--- a/arch/mips/lib/csum_partial_copy.c	Fri Oct 18 21:03:04 2002
+++ b/arch/mips/lib/csum_partial_copy.c	Fri Oct 18 21:03:04 2002
@@ -25,8 +25,8 @@
 /*
  * copy while checksumming, otherwise like csum_partial
  */
-unsigned int csum_partial_copy(const char *src, char *dst, 
-                               int len, unsigned int sum)
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, 
+				       int len, unsigned int sum)
 {
 	/*
 	 * It's 2:30 am and I don't feel like doing it real ...
diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c
--- a/arch/mips64/kernel/linux32.c	Fri Oct 18 21:03:05 2002
+++ b/arch/mips64/kernel/linux32.c	Fri Oct 18 21:03:05 2002
@@ -2084,19 +2084,11 @@
 	return err;
 }
 
-extern __inline__ void
-sockfd_put(struct socket *sock)
-{
-	fput(sock->file);
-}
-
 /* 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);
 
 /*
  *	BSD sendmsg interface
diff -Nru a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c
--- a/arch/mips64/kernel/mips64_ksyms.c	Fri Oct 18 21:03:04 2002
+++ b/arch/mips64/kernel/mips64_ksyms.c	Fri Oct 18 21:03:04 2002
@@ -75,9 +75,6 @@
 EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
 
 
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
-
 /*
  * Functions to control caches.
  */
diff -Nru a/arch/mips64/lib/csum_partial_copy.c b/arch/mips64/lib/csum_partial_copy.c
--- a/arch/mips64/lib/csum_partial_copy.c	Fri Oct 18 21:03:08 2002
+++ b/arch/mips64/lib/csum_partial_copy.c	Fri Oct 18 21:03:08 2002
@@ -16,8 +16,8 @@
 /*
  * copy while checksumming, otherwise like csum_partial
  */
-unsigned int csum_partial_copy(const char *src, char *dst, 
-                               int len, unsigned int sum)
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, 
+				       int len, unsigned int sum)
 {
 	/*
 	 * It's 2:30 am and I don't feel like doing it real ...
diff -Nru a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
--- a/arch/parisc/lib/checksum.c	Fri Oct 18 21:03:06 2002
+++ b/arch/parisc/lib/checksum.c	Fri Oct 18 21:03:06 2002
@@ -97,8 +97,8 @@
 /*
  * copy while checksumming, otherwise like csum_partial
  */
-unsigned int csum_partial_copy(const char *src, char *dst, 
-                               int len, unsigned int sum)
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, 
+				       int len, unsigned int sum)
 {
 	/*
 	 * It's 2:30 am and I don't feel like doing it real ...
diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile
--- a/arch/ppc/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/Makefile	Fri Oct 18 21:03:03 2002
@@ -64,7 +64,7 @@
 drivers-$(CONFIG_4xx)		+= arch/ppc/4xx_io/
 drivers-$(CONFIG_8260)		+= arch/ppc/8260_io/
 
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+makeboot = $(call descend,arch/ppc/boot,$(1))
 
 BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd pImage vmlinux.sm
 
@@ -74,14 +74,14 @@
 bzImage: zImage
 
 $(BOOT_TARGETS): vmlinux
-	@$(MAKEBOOT) $@
+	+@$(call makeboot,$@)
 
 %_config: arch/ppc/configs/%_defconfig
 	rm -f .config arch/ppc/defconfig
 	cp -f arch/ppc/configs/$(@:config=defconfig) .config
 
 archclean:
-	@$(MAKEBOOT) clean
+	+@$(call makeboot,clean)
 
 archmrproper:
 
diff -Nru a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
--- a/arch/ppc/boot/Makefile	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc/boot/Makefile	Fri Oct 18 21:03:05 2002
@@ -10,25 +10,16 @@
 # modified by Cort (cort@cs.nmt.edu)
 #
 
-GZIP_FLAGS = -v9f
-
 CFLAGS	+= -fno-builtin -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/boot/include
 
 AFLAGS	+= -D__BOOTER__
 OBJCOPY_ARGS = -O elf32-powerpc
 
-MKIMAGE				:= ./utils/mkimage.wrapper
-
-lib/lib.a: lib/zlib.c
-	$(MAKE) -C lib
+subdir-y			:= simple
+subdir-$(CONFIG_ALL_PPC)	:= openfirmware prep
 
-images/vmlinux.gz: $(TOPDIR)/vmlinux
-	$(MAKE) -C images vmlinux.gz
+HOSTCFLAGS += -Iarch/$(ARCH)/boot/include
 
-# Subdirs and tools needed for each.  Assume we always need to go into
-# 'simple' unless told otherwise.
-subdir-y			:= lib common simple
-subdir-$(CONFIG_ALL_PPC)	:= openfirmware prep
 tools-$(CONFIG_ALL_PPC)		:= addnote mknote hack-coff mkprep
 tools-$(CONFIG_PPLUS)		:= mkbugboot mkprep
 tools-$(CONFIG_4xx)		:= mktree
@@ -40,49 +31,24 @@
 tools-$(CONFIG_PRPMC800)	:= mkbugboot mkprep
 tools-$(CONFIG_SPRUCE)		:= mktree
 
-# These are dirs we don't want to go into on BOOT_TARGETS.  We have them for
-# the 'depend' stage.
-NONBOOT				:= lib common
-
-# These are the subdirs we want to use
-BOOTDIRS			= $(filter-out $(NONBOOT), $(subdir-y))
-
-makeof1275:
-	$(MAKE) -C of1275
-
-# This will make the tools we need.  We do it like this to ensure that we use
-# HOSTCC. -- Tom
-maketools:
-	$(MAKE) -C utils $(tools-y)
-
-# The targets all boards support for boot images.
-BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
-
-$(BOOT_TARGETS): vmapus lib/lib.a images/vmlinux.gz makeof1275 maketools
-ifneq ($(BOOTDIRS),)
-	for d in $(BOOTDIRS); do $(MAKE) -C $$d $@; done
-endif
-
-vmapus: $(TOPDIR)/vmlinux
-ifdef CONFIG_APUS
-	$(STRIP) $(TOPDIR)/vmlinux -o images/vmapus
-	gzip $(GZIP_FLAGS) images/vmapus
-endif
-
-# Make an image for PPCBoot
-pImage: images/vmlinux.gz
-	$(MKIMAGE) -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
-	-n 'Linux-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)' \
-	-d $< images/vmlinux.PPCBoot
-	ln -sf vmlinux.PPCBoot images/pImage
-
-vmlinux.sm: $(TOPDIR)/vmlinux utils/addSystemMap
-	./utils/addSystemMap $(TOPDIR)/System.map $(TOPDIR)/vmlinux images/vmlinux.sm
-
-# These are subdirs with files not normally rm'ed. -- Tom
-clean:
-	$(MAKE) -C images clean
-	$(MAKE) -C utils clean
-	$(MAKE) -C openfirmware clean
+all-tools := addnote mknote hack-coff mkprep mkbugboot mktree
+
+host-progs			:= $(addprefix utils/,$(tools-y))
 
 include $(TOPDIR)/Rules.make
+
+zImage zImage.initrd znetboot znetboot.initrd: $(subdir-y)
+
+simple openfirmware prep: lib common images
+openfirmware prep: of1275
+
+lib common of1275 images: FORCE
+	+@$(call descend,$(obj)/$@,)
+
+openfirmware prep simple: FORCE
+	+@$(call descend,$(obj)/$@,$(MAKECMDGOALS))
+
+CLEAN_FILES += $(addprefix $(obj)/utils,$(all-tools))
+
+clean: FORCE
+	+@$(call descend,$(obj)/images,clean)
diff -Nru a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile
--- a/arch/ppc/boot/common/Makefile	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc/boot/common/Makefile	Fri Oct 18 21:03:05 2002
@@ -8,7 +8,12 @@
 # Tom Rini	January 2001
 #
 
-coffcrt0.o:
-	$(CC) $(AFLAGS) -DXCOFF -traditional -c -o coffcrt0.o crt0.S
+L_TARGET				:= lib.a
+
+obj-y					:= string.o util.o misc-common.o
+obj-$(CONFIG_ALL_PPC)			+= mpc10x_memory.o
+obj-$(CONFIG_LOPEC)			+= mpc10x_memory.o
+obj-$(CONFIG_PAL4)			+= cpc700_memory.o
+obj-$(CONFIG_SERIAL_8250_CONSOLE)	+= ns16550.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/ppc/boot/common/misc-simple.c b/arch/ppc/boot/common/misc-simple.c
--- a/arch/ppc/boot/common/misc-simple.c	Fri Oct 18 21:03:08 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,236 +0,0 @@
-/*
- * arch/ppc/common/misc-simple.c
- *
- * Misc. bootloader code for many machines.  This assumes you have are using
- * a 6xx/7xx/74xx CPU in your machine.  This assumes the chunk of memory
- * below 8MB is free.  Finally, it assumes you have a NS16550-style uart for
- * your serial console.  If a machine meets these requirements, it can quite
- * likely use this code during boot.
- *
- * Author: Matt Porter <mporter@mvista.com>
- * Derived from arch/ppc/boot/prep/misc.c
- *
- * Copyright 2001 MontaVista Software 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 the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/types.h>
-#include <linux/elf.h>
-#include <linux/config.h>
-
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/mmu.h>
-#include <asm/bootinfo.h>
-
-#include "nonstdio.h"
-#include "zlib.h"
-
-/* Default cmdline */
-#ifdef CONFIG_CMDLINE
-#define CMDLINE CONFIG_CMDLINE
-#else
-#define CMDLINE ""
-#endif
-
-/* Keyboard (and VGA console)? */
-#ifdef CONFIG_VGA_CONSOLE
-#define HAS_KEYB 1
-#else
-#define HAS_KEYB 0
-#endif
-
-char *avail_ram;
-char *end_avail;
-char *zimage_start;
-char cmd_preset[] = CMDLINE;
-char cmd_buf[256];
-char *cmd_line = cmd_buf;
-int keyb_present = HAS_KEYB;
-int zimage_size;
-
-unsigned long com_port;
-unsigned long initrd_size = 0;
-
-/* The linker tells us various locations in the image */
-extern char __image_begin, __image_end;
-extern char __ramdisk_begin, __ramdisk_end;
-extern char _end[];
-/* Original location */
-extern unsigned long start;
-
-extern int CRT_tstc(void);
-extern unsigned long get_mem_size(void);
-extern unsigned long serial_init(int chan, void *ignored);
-extern void serial_close(unsigned long com_port);
-extern void gunzip(void *, int, unsigned char *, int *);
-extern void serial_fixups(void);
-
-struct bi_record *
-decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
-{
-	int timer = 0;
-	char *cp, ch;
-	struct bi_record *rec, *birecs;
-	unsigned long TotalMemory = 0;
-
-	serial_fixups();
-	com_port = serial_init(0, NULL);
-
-#if defined(CONFIG_LOPEC) || defined(CONFIG_PAL4)
-	/*
-	 * Call get_mem_size(), which is memory controller dependant,
-	 * and we must have the correct file linked in here.
-	 */
-	TotalMemory = get_mem_size();
-#endif
-
-	/* assume the chunk below 8M is free */
-	end_avail = (char *)0x00800000;
-
-	/*
-	 * Reveal where we were loaded at and where we
-	 * were relocated to.
-	 */
-	puts("loaded at:     "); puthex(load_addr);
-	puts(" "); puthex((unsigned long)(load_addr + (4*num_words)));
-	puts("\n");
-	if ( (unsigned long)load_addr != (unsigned long)&start )
-	{
-		puts("relocated to:  "); puthex((unsigned long)&start);
-		puts(" ");
-		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
-		puts("\n");
-	}
-
-	/*
-	 * We link ourself to 0x00800000.  When we run, we relocate
-	 * ourselves there.  So we just need __image_begin for the
-	 * start. -- Tom
-	 */
-	zimage_start = (char *)(unsigned long)(&__image_begin);
-	zimage_size = (unsigned long)(&__image_end) -
-			(unsigned long)(&__image_begin);
-
-	initrd_size = (unsigned long)(&__ramdisk_end) -
-		(unsigned long)(&__ramdisk_begin);
-
-	/*
-	 * The zImage and initrd will be between start and _end, so they've
-	 * already been moved once.  We're good to go now. -- Tom
-	 */
-	avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
-	puts("zimage at:     "); puthex((unsigned long)zimage_start);
-	puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
-	puts("\n");
-
-	if ( initrd_size ) {
-		puts("initrd at:     ");
-		puthex((unsigned long)(&__ramdisk_begin));
-		puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
-	}
-
-	avail_ram = (char *)0x00400000;
-	end_avail = (char *)0x00800000;
-	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
-	puthex((unsigned long)end_avail); puts("\n");
-
-	if (keyb_present)
-		CRT_tstc();  /* Forces keyboard to be initialized */
-#ifdef CONFIG_GEMINI
-	/*
-	 * If cmd_line is empty and cmd_preset is not, copy cmd_preset
-	 * to cmd_line.  This way we can override cmd_preset with the
-	 * command line from Smon.
-	 */
-
-	if ( (cmd_line[0] == '\0') && (cmd_preset[0] != '\0'))
-		memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
-#endif
-
-	/* Display standard Linux/PPC boot prompt for kernel args */
-	puts("\nLinux/PPC load: ");
-	cp = cmd_line;
-	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
-	while ( *cp ) putc(*cp++);
-
-#ifndef CONFIG_GEMINI
-	/* Val Henson has requested that Gemini doesn't wait for the
-	 * user to edit the cmdline or not. */
-	while (timer++ < 5*1000) {
-		if (tstc()) {
-			while ((ch = getc()) != '\n' && ch != '\r') {
-				/* Test for backspace/delete */
-				if (ch == '\b' || ch == '\177') {
-					if (cp != cmd_line) {
-						cp--;
-						puts("\b \b");
-					}
-				/* Test for ^x/^u (and wipe the line) */
-				} else if (ch == '\030' || ch == '\025') {
-					while (cp != cmd_line) {
-						cp--;
-						puts("\b \b");
-					}
-				} else {
-					*cp++ = ch;
-					putc(ch);
-				}
-			}
-			break;  /* Exit 'timer' loop */
-		}
-		udelay(1000);  /* 1 msec */
-	}
-	*cp = 0;
-#endif
-	puts("\n");
-
-	puts("Uncompressing Linux...");
-	gunzip(0, 0x400000, zimage_start, &zimage_size);
-	puts("done.\n");
-
-	/*
-	 * Create bi_recs for cmd_line and initrds
-	 */
-	rec = (struct bi_record *)_ALIGN((unsigned long)(zimage_size) +
-			(1 << 20) - 1, (1 << 20));
-	birecs = rec;
-
-	rec->tag = BI_FIRST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	if ( TotalMemory ) {
-		rec->tag = BI_MEMSIZE;
-		rec->data[0] = TotalMemory;
-		rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-		rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	}
-
-	rec->tag = BI_CMD_LINE;
-	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
-	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	if ( initrd_size ) {
-		rec->tag = BI_INITRD;
-		rec->data[0] = (unsigned long)(&__ramdisk_begin);
-		rec->data[1] = initrd_size;
-		rec->size = sizeof(struct bi_record) + 2 *
-			sizeof(unsigned long);
-		rec = (struct bi_record *)((unsigned long)rec +
-				rec->size);
-	}
-
-	rec->tag = BI_LAST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	puts("Now booting the kernel\n");
-	serial_close(com_port);
-
-	return birecs;
-}
diff -Nru a/arch/ppc/boot/common/relocate.S b/arch/ppc/boot/common/relocate.S
--- a/arch/ppc/boot/common/relocate.S	Fri Oct 18 21:03:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,205 +0,0 @@
-/*
- * arch/ppc/boot/simple/relocate.S
- *
- * This is the common part of the loader relocation and initialization
- * process.  All of the board/processor specific initialization is
- * done before we get here.
- *
- * Author: Tom Rini
- *	   trini@mvista.com
- * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
- *
- * Copyright 2001-2002 MontaVista Software 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 the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/cache.h>
-#include <asm/ppc_asm.h>
-
-#define GETSYM(reg, sym)	\
-	lis	reg, sym@h; ori	reg, reg, sym@l	
-	
-	.text
-	/* We get called from the early initialization code.
-	 * Register 3 has the address where we were loaded,
-	 * Register 4 contains any residual data passed from the
-	 * boot rom.
-	 */
-	.globl	relocate
-relocate:
-	/* Save r3, r4 for later.
-	 * The r8/r11 are legacy registers so I don't have to
-	 * rewrite the code below :-).
-	 */
-	mr	r8, r3
-	mr	r11, r4
-
-	/* compute the size of the whole image in words. */
-	GETSYM(r4,start)
-	GETSYM(r5,end)
-
-	addi	r5,r5,3		/* round up */
-	sub	r5,r5,r4	/* end - start */
-	srwi	r5,r5,2
-	mr	r7,r5		/* Save for later use. */
-
-	/*
-	 * Check if we need to relocate ourselves to the link addr or were
-	 * we loaded there to begin with.
-	 */
-	cmp	cr0,r3,r4
-	beq	start_ldr	/* If 0, we don't need to relocate */
-
-	/* Move this code somewhere safe.  This is max(load + size, end) 
-	 * r8 == load address
-	 */
-	GETSYM(r4, start)
-	GETSYM(r5, end)
-
-	sub	r6,r5,r4
-	add	r6,r8,r6	/* r6 == phys(load + size) */
-
-	cmpw	r5,r6
-	bgt	1f
-	b	2f
-1:	
-	mr	r6, r5	
-2: 
-	/* dest is in r6 */	
-	/* Ensure alignment --- this code is precautionary */
-	addi	r6,r6,4
-	li	r5,0x0003
-	andc	r6,r6,r5
-
-	/* Find physical address and size of do_relocate */
-	GETSYM(r5, __relocate_start)
-	GETSYM(r4, __relocate_end)
-	GETSYM(r3, start)
-
-	/* Size to copy */
-	sub	r4,r4,r5	
-	srwi	r4,r4,2
-	
-	/* Src addr to copy (= __relocate_start - start + where_loaded) */
-	sub	r3,r5,r3
-	add	r5,r8,r3	
-
-	/* Save dest */
-	mr	r3, r6
-
-	/* Do the copy */	
-	mtctr	r4	
-3:	lwz	r4,0(r5)
-	stw	r4,0(r3)	
-	addi	r3,r3,4
-	addi	r5,r5,4
-	bdnz	3b
-
-	GETSYM(r4, __relocate_start)
-	GETSYM(r5, do_relocate)
-
-	sub	r4,r5,r4	/* Get entry point for do_relocate in
-	add	r6,r6,r4       * relocated section */
-
-	/* This will return to the relocated do_relocate */
-	mtlr	r6
-	b	flush_instruction_cache
-
-	.section ".relocate_code","xa"
-			
-do_relocate:		
-	/* We have 2 cases --- start < load, or start > load  
-	 * This determines whether we copy from the end, or the start.
-	 * Its easier to have 2 loops than to have paramaterised
-	 * loops.  Sigh.
-	 */
-	li	r6,0		/* Clear checksum */
-	mtctr	r7		/* Setup for a loop */
-			
-	GETSYM(r4, start)
-	mr	r3,r8		/* Get the load addr */
-
-	cmp	cr0,r4,r3	/* If we need to copy from the end, do so */
-	bgt	do_relocate_from_end
-	
-do_relocate_from_start:		
-1:	lwz	r5,0(r3)	/* Load and decrement */
-	stw	r5,0(r4)	/* Store and decrement */
-	addi	r3,r3,4
-	addi	r4,r4,4
-	xor	r6,r6,r5	/* Update checksum */
-	bdnz	1b		/* Are we done? */
-	b	do_relocate_out	/* Finished */
-
-do_relocate_from_end:	
-	GETSYM(r3, end)
-	slwi	r4,r7,2
-	add	r4,r8,r4	/* Get the physical end */
-1:	lwzu	r5,-4(r4)
-	stwu	r5, -4(r3)
-	xor	r6,r6,r5
-	bdnz	1b
-
-do_relocate_out:	
-	GETSYM(r3,start_ldr)
-	mtlr	r3		/* Easiest way to do an absolute jump */
-/* Some boards don't boot up with the I-cache enabled.  Do that
- * now because the decompress runs much faster that way.
- * As a side effect, we have to ensure the data cache is not enabled
- * so we can access the serial I/O without trouble.
- */
-	b	flush_instruction_cache
-
-	.previous
-		
-start_ldr:
-/* Clear all of BSS and set up stack for C calls */
-	lis	r3,edata@h
-	ori	r3,r3,edata@l
-	lis	r4,end@h
-	ori	r4,r4,end@l
-	subi	r3,r3,4
-	subi	r4,r4,4
-	li	r0,0
-50:	stwu	r0,4(r3)
-	cmp	cr0,r3,r4
-	bne	50b
-90:	mr	r9,r1		/* Save old stack pointer (in case it matters) */
-	lis	r1,.stack@h
-	ori	r1,r1,.stack@l
-	addi	r1,r1,4096*2
-	subi	r1,r1,256
-	li	r2,0x000F	/* Mask pointer to 16-byte boundary */
-	andc	r1,r1,r2
-
-	/*
-	 * Exec kernel loader
-	 */
-	mr	r3,r8		/* Load point */
-	mr	r4,r7		/* Program length */
-	mr	r5,r6		/* Checksum */
-	mr	r6,r11		/* Residual data */
-	bl	decompress_kernel
-
-	/*
-	 * Make sure the kernel knows we don't have things set in
-	 * registers.  -- Tom
-	 */
-	li	r4,0
-	li	r5,0
-	li	r6,0
-
-	/*
-	 * Start at the begining.
-	 */
-	li	r9,0x0000
-	mtlr	r9
-	blr
-
-	.comm	.stack,4096*2,4
diff -Nru a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
--- a/arch/ppc/boot/images/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/boot/images/Makefile	Fri Oct 18 21:03:03 2002
@@ -2,11 +2,16 @@
 # This dir holds all of the images for PPC machines.
 # Tom Rini	January 2001
 
+all:	$(obj)/vmlinux.gz
+
 include $(TOPDIR)/Rules.make
 
-vmlinux.gz: $(TOPDIR)/vmlinux
-	$(OBJCOPY) --strip-all -S -O binary $(TOPDIR)/vmlinux vmlinux
-	gzip -vf9 vmlinux
+GZIP_FLAGS = -v9f
+
+$(obj)/vmlinux.gz: vmlinux
+	$(OBJCOPY) -S -O binary vmlinux $(obj)/vmlinux
+	gzip $(GZIP_FLAGS) $(obj)/vmlinux
 
 clean:
-	rm -f sImage vmapus vmlinux* miboot* zImage* zvmlinux*
+	rm -f $(obj)/sImage $(obj)/vmapus $(obj)/vmlinux* $(obj)/miboot* 
+	rm -f $(obj)/zImage* z$(obj)/vmlinux*
diff -Nru a/arch/ppc/boot/include/mpc10x.h b/arch/ppc/boot/include/mpc10x.h
--- a/arch/ppc/boot/include/mpc10x.h	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/boot/include/mpc10x.h	Fri Oct 18 21:03:04 2002
@@ -58,7 +58,7 @@
 #define MPC10X_MCTLR_EXT_MEM_START_2	0x8c	/* Banks 4-7 */
 
 #define MPC10X_MCTLR_MEM_END_1		0x90	/* Banks 0-3 */
-#define MPC10X_MCTLR_MEM_END_2i		0x94	/* Banks 4-7 */
+#define MPC10X_MCTLR_MEM_END_2		0x94	/* Banks 4-7 */
 #define MPC10X_MCTLR_EXT_MEM_END_1	0x98	/* Banks 0-3 */
 #define MPC10X_MCTLR_EXT_MEM_END_2	0x9c	/* Banks 4-7 */
 
diff -Nru a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
--- a/arch/ppc/boot/lib/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/boot/lib/Makefile	Fri Oct 18 21:03:04 2002
@@ -4,6 +4,6 @@
 
 L_TARGET := lib.a
 
-obj-y := zlib.o
+obj-y := zlib.o div64.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/ppc/boot/lib/div64.S b/arch/ppc/boot/lib/div64.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/boot/lib/div64.S	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,58 @@
+/*
+ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
+ * This routine assumes that the top 32 bits of the dividend are
+ * non-zero to start with.
+ * On entry, r3 points to the dividend, which get overwritten with
+ * the 64-bit quotient, and r4 contains the divisor.
+ * On exit, r3 contains the remainder.
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+_GLOBAL(__div64_32)
+	lwz	r5,0(r3)	# get the dividend into r5/r6
+	lwz	r6,4(r3)
+	cmplw	r5,r4
+	li	r7,0
+	li	r8,0
+	blt	1f
+	divwu	r7,r5,r4	# if dividend.hi >= divisor,
+	mullw	r0,r7,r4	# quotient.hi = dividend.hi / divisor
+	subf.	r5,r0,r5	# dividend.hi %= divisor
+	beq	3f
+1:	mr	r11,r5		# here dividend.hi != 0
+	andis.	r0,r5,0xc000
+	bne	2f
+	cntlzw	r0,r5		# we are shifting the dividend right
+	li	r10,-1		# to make it < 2^32, and shifting
+	srw	r10,r10,r0	# the divisor right the same amount,
+	add	r9,r4,r10	# rounding up (so the estimate cannot
+	andc	r11,r6,r10	# ever be too large, only too small)
+	andc	r9,r9,r10
+	or	r11,r5,r11
+	rotlw	r9,r9,r0
+	rotlw	r11,r11,r0
+	divwu	r11,r11,r9	# then we divide the shifted quantities
+2:	mullw	r10,r11,r4	# to get an estimate of the quotient,
+	mulhwu	r9,r11,r4	# multiply the estimate by the divisor,
+	subfc	r6,r10,r6	# take the product from the divisor,
+	add	r8,r8,r11	# and add the estimate to the accumulated
+	subfe.	r5,r9,r5	# quotient
+	bne	1b
+3:	cmplw	r6,r4
+	blt	4f
+	divwu	r0,r6,r4	# perform the remaining 32-bit division
+	mullw	r10,r0,r4	# and get the remainder
+	add	r8,r8,r0
+	subf	r6,r10,r6
+4:	stw	r7,0(r3)	# return the quotient in *r3
+	stw	r8,4(r3)
+	mr	r3,r6		# return the remainder in r3
+	blr
diff -Nru a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile
--- a/arch/ppc/boot/of1275/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/boot/of1275/Makefile	Fri Oct 18 21:03:04 2002
@@ -2,7 +2,7 @@
 # Makefile of1275 stuff
 #
 
-L_TARGET := of1275.a
+L_TARGET := lib.a
 
 obj-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o	\
 	 ofstdio.o read.o release.o write.o
diff -Nru a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
--- a/arch/ppc/boot/openfirmware/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/boot/openfirmware/Makefile	Fri Oct 18 21:03:04 2002
@@ -10,24 +10,37 @@
 #	Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the
 #	rules.
 
+EXTRA_TARGETS := start.o misc.o crt0.o coffcrt0.o coffmain.o chrpmain.o \
+		newworldmain.o common.o
+
+boot: zImage
+
+include $(TOPDIR)/Rules.make
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+of1275 := $(boot)/of1275
+images := $(boot)/images
+
 OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
-COFF_LD_ARGS = -T ../ld.script -e _start -Ttext 0x00500000 -Bstatic
-CHRP_LD_ARGS = -T ../ld.script -e _start -Ttext 0x00400000
-NEWWORLD_LD_ARGS = -T ../ld.script -e _start -Ttext 0x01000000
-
-COMMONOBJS = start.o misc.o ../common/string.o common.o
-COFFOBJS = ../common/coffcrt0.o $(COMMONOBJS) coffmain.o
-CHRPOBJS = ../common/crt0.o $(COMMONOBJS) chrpmain.o
-NEWWORLDOBJS = ../common/crt0.o $(COMMONOBJS) newworldmain.o
-
-EXTRA_TARGETS	:= $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS)
-LIBS = $(TOPDIR)/lib/lib.a ../lib/lib.a ../of1275/of1275.a
-
-ADDNOTE := ../utils/addnote
-MKNOTE := ../utils/mknote
-SIZE := ../utils/size
-OFFSET := ../utils/offset
-HACKCOFF := ../utils/hack-coff
+COFF_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x00700000 -Bstatic
+CHRP_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x00800000
+NEWWORLD_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x01000000
+
+COMMONOBJS = $(obj)/start.o $(obj)/misc.o $(obj)/common.o
+COFFOBJS = $(obj)/coffcrt0.o $(COMMONOBJS) $(obj)/coffmain.o
+CHRPOBJS = $(obj)/crt0.o $(COMMONOBJS) $(obj)/chrpmain.o
+NEWWORLDOBJS = $(obj)/crt0.o $(COMMONOBJS) $(obj)/newworldmain.o
+
+LIBS = lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
+
+ADDNOTE := $(utils)/addnote
+MKNOTE := $(utils)/mknote
+SIZE := $(utils)/size
+OFFSET := $(utils)/offset
+HACKCOFF := $(utils)/hack-coff
 
 ifdef CONFIG_SMP
 END := .smp
@@ -38,12 +51,12 @@
 
 TFTPIMAGE=/tftpboot/zImage.
 
-../common/coffcrt0.o:
-	$(MAKE) -C ../common coffcrt0.o
+$(obj)/dummy.o: $(common)/dummy.c
+	$(CC) -c -o $@ $(common)/dummy.c
 
-image.o: ../images/vmlinux.gz ../common/dummy.o
-	$(OBJCOPY) ../common/dummy.o $@ -R .comment \
-		--add-section=.image=../images/vmlinux.gz \
+$(obj)/image.o: $(images)/vmlinux.gz $(obj)/dummy.o
+	$(OBJCOPY) $(obj)/dummy.o $@ -R .comment \
+		--add-section=.image=$(images)/vmlinux.gz \
 		--set-section-flags=.image=contents,alloc,load,readonly,data
 ifdef CONFIG_XMON
 	$(OBJCOPY) $@ $@ \
@@ -52,86 +65,93 @@
 endif
 
 # Place the ramdisk in the initrd image.
-image-initrd.o: image.o ../images/ramdisk.image.gz
-	$(OBJCOPY) image.o $@ \
-		--add-section=.ramdisk=../images/ramdisk.image.gz \
+$(obj)/image-initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz
+	$(OBJCOPY) $(obj)/image.o $@ \
+		--add-section=.ramdisk=$(images)/ramdisk.image.gz \
 		--set-section-flags=.ramdisk=contents,alloc,load,readonly,data
 
 # Create the note section for New-World PowerMacs.
-note: $(MKNOTE)
-	$(MKNOTE) > note
+$(obj)/note: $(MKNOTE)
+	$(MKNOTE) > $(obj)/note
 
-znetboot: vmlinux.coff vmlinux.elf-pmac zImage
-	cp ../images/vmlinux.coff $(TFTPIMAGE).pmac$(END)
-	cp ../images/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END)elf
-	cp ../images/zImage.chrp $(TFTPIMAGE).chrp$(END)
-
-znetboot.initrd: vmlinux.initrd.coff vmlinux.initrd.elf-pmac
-	cp ../images/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END)
-	cp ../images/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf
-	cp ../images/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
-
-miboot.image: ../common/dummy.o ../images/vmlinux.gz
-	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=../images/vmlinux.gz \
-		../common/dummy.o ../images/$@
+znetboot: $(images)/vmlinux.coff $(images)/vmlinux.elf-pmac $(images)/zImage.chrp
+	cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END)
+	cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END)elf
+	cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END)
+
+znetboot.initrd: $(images)/vmlinux.initrd.coff \
+		$(images)/vmlinux.initrd.elf-pmac \
+		$(images)/zImage.initrd.chrp
+	cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END)
+	cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+	cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
+
+$(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz
+	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=$(images)/vmlinux.gz \
+		$(obj)/dummy.o $@
 
-miboot.initrd.image: miboot.image ../images/ramdisk.image.gz
+$(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz
 	$(OBJCOPY) $(OBJCOPY_ARGS) \
-		--add-section=initrd=../images/ramdisk.image.gz \
-		../images/miboot.image ../images/$@
+		--add-section=initrd=$(images)/ramdisk.image.gz \
+		$(images)/miboot.image $@
 
-coffboot: $(COFFOBJS) image.o $(LIBS)
+$(obj)/coffcrt0.o: $(common)/crt0.S
+	$(CC) $(AFLAGS) -DXCOFF -traditional -c -o $@ $(common)/crt0.S
+
+$(obj)/crt0.o: $(common)/crt0.S
+	$(CC) $(AFLAGS) -traditional -c -o $@ $(common)/crt0.S
+
+$(obj)/coffboot: $(COFFOBJS) $(obj)/image.o $(LIBS)
 	$(LD) -o $@ $(COFF_LD_ARGS) $^
 	$(OBJCOPY) $@ $@ -R .comment -R .ramdisk
 
-coffboot.initrd: $(COFFOBJS) image-initrd.o $(LIBS)
+$(obj)/coffboot.initrd: $(COFFOBJS) $(obj)/image-initrd.o $(LIBS)
 	$(LD) -o $@ $(COFF_LD_ARGS) $^
 	$(OBJCOPY) $@ $@ -R .comment
 
-vmlinux.coff: coffboot $(HACKCOFF)
-	$(OBJCOPY) $(OBJCOPY_ARGS) coffboot ../images/$@
-	$(HACKCOFF) ../images/$@
-	rm -f coffboot
-	ln -sf vmlinux.coff ../images/zImage.pmac
-
-vmlinux.initrd.coff: coffboot.initrd $(HACKCOFF)
-	$(OBJCOPY) $(OBJCOPY_ARGS) coffboot.initrd ../images/$@
-	$(HACKCOFF) ../images/$@
-	rm -f coffboot.initrd
-	ln -sf vmlinux.initrd.coff ../images/zImage.initrd.pmac
-
-vmlinux.elf-pmac: $(NEWWORLDOBJS) $(LIBS) image.o
-	$(LD) $(NEWWORLD_LD_ARGS) -o ../images/$@ $^
-
-vmlinux.initrd.elf-pmac: $(NEWWORLDOBJS) $(LIBS) image-initrd.o
-	$(LD) $(NEWWORLD_LD_ARGS) -o ../images/$@ $^
-
-zImage.chrp: $(CHRPOBJS) image.o $(LIBS)
-	$(LD) $(CHRP_LD_ARGS) -o ../images/$@ $^
-
-zImage.initrd.chrp: $(CHRPOBJS) image-initrd.o $(LIBS)
-	$(LD) $(CHRP_LD_ARGS) -o ../images/$@ $^
-
-zImage: vmlinux.coff vmlinux.elf-pmac zImage.chrp miboot.image $(ADDNOTE) \
-	note
-	$(OBJCOPY) ../images/vmlinux.elf-pmac ../images/vmlinux.elf-pmac \
-		--add-section=.note=note -R .comment -R .ramdisk
-	$(OBJCOPY) ../images/zImage.chrp ../images/zImage.chrp \
-		-R .comment -R .ramdisk
-	cp ../images/zImage.chrp ../images/zImage.chrp-rs6k
-	$(ADDNOTE) ../images/zImage.chrp-rs6k
-
-zImage.initrd: vmlinux.initrd.coff vmlinux.initrd.elf-pmac zImage.initrd.chrp \
-	miboot.initrd.image $(ADDNOTE) note
-	$(OBJCOPY) ../images/vmlinux.initrd.elf-pmac \
-		../images/vmlinux.initrd.elf-pmac --add-section=.note=note \
-		-R .comment
-	$(OBJCOPY) ../images/zImage.initrd.chrp ../images/zImage.initrd.chrp \
-		-R .comment
-	cp ../images/zImage.initrd.chrp ../images/zImage.initrd.chrp-rs6k
-	$(ADDNOTE) ../images/zImage.initrd.chrp-rs6k
+$(images)/vmlinux.coff: $(obj)/coffboot
+	$(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot $@
+	$(HACKCOFF) $@
+	ln -sf vmlinux.coff $(images)/zImage.pmac
+
+$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd
+	$(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot.initrd $@
+	$(HACKCOFF) $@
+	ln -sf vmlinux.initrd.coff $(images)/zImage.initrd.pmac
 
-clean:
-	rm -f note
+$(images)/vmlinux.elf-pmac: $(NEWWORLDOBJS) $(LIBS) $(obj)/image.o $(obj)/note
+	$(LD) $(NEWWORLD_LD_ARGS) -o $@ $(NEWWORLDOBJS) $(LIBS) $(obj)/image.o
+	$(OBJCOPY) $@ $@ \
+		--add-section=.note=$(obj)/note -R .comment -R .ramdisk
 
-include $(TOPDIR)/Rules.make
+$(images)/vmlinux.initrd.elf-pmac: $(NEWWORLDOBJS) $(LIBS) \
+		$(obj)/image-initrd.o $(obj)/note
+	$(LD) $(NEWWORLD_LD_ARGS) -o $@ $(NEWWORLDOBJS) $(LIBS) \
+		$(obj)/image-initrd.o
+	$(OBJCOPY) $@ $@ \
+		--add-section=.note=$(obj)/note -R .comment
+
+$(images)/zImage.chrp: $(CHRPOBJS) $(obj)/image.o $(LIBS)
+	$(LD) $(CHRP_LD_ARGS) -o $@ $^
+	$(OBJCOPY) $@ $@ -R .comment -R .ramdisk
+
+$(images)/zImage.initrd.chrp: $(CHRPOBJS) $(obj)/image-initrd.o $(LIBS)
+	$(LD) $(CHRP_LD_ARGS) -o $@ $^
+	$(OBJCOPY) $@ $@ -R .comment
+
+$(images)/zImage.chrp-rs6k: $(images)/zImage.chrp
+	cp $(images)/zImage.chrp $@
+	$(ADDNOTE) $@
+
+$(images)/zImage.initrd.chrp-rs6k: $(images)/zImage.initrd.chrp
+	cp $(images)/zImage.initrd.chrp $@
+	$(ADDNOTE) $@
+
+zImage: $(images)/vmlinux.coff $(images)/vmlinux.elf-pmac \
+		$(images)/zImage.chrp $(images)/miboot.image
+
+zImage.initrd: $(images)/vmlinux.initrd.coff $(images)/vmlinux.initrd.elf-pmac\
+		$(images)/zImage.initrd.chrp $(images)/miboot.initrd.image
+
+clean:
+	rm -f $(obj)/note $(obj)/image.o $(obj)/coffboot $(obj)/coffboot.initrd
diff -Nru a/arch/ppc/boot/prep/Makefile b/arch/ppc/boot/prep/Makefile
--- a/arch/ppc/boot/prep/Makefile	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/boot/prep/Makefile	Fri Oct 18 21:03:08 2002
@@ -13,65 +13,79 @@
 # modified by Cort (cort@cs.nmt.edu)
 #
 
+boot: zImage
+
 TFTPIMAGE			= /tftpboot/zImage.prep
 ifeq ($(CONFIG_SMP),y)
 TFTPIMAGE			= $(TFTPBOOT).smp
 endif
 
-LD_ARGS				= -T ../ld.script -Ttext 0x00800000 -Bstatic
-boot-y				:= head.o ../simple/legacy.o misc.o \
-					../common/util.o ../common/string.o \
-					../common/misc-common.o \
-					../common/mpc10x_memory.o
+LD_ARGS				= -T $(boot)/ld.script -Ttext 0x00800000 -Bstatic
 OBJCOPY_ARGS			= -O elf32-powerpc
-LIBS 				= ../lib/lib.a
+LIBS 				= $(common)/lib.a $(bootlib)/lib.a
 
-boot-$(CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o
+boot-y				:= head.o misc.o
 boot-$(CONFIG_VGA_CONSOLE)	+= vreset.o kbd.o
 
-EXTRA_TARGETS			:= $(boot-y)
+EXTRA_TARGETS			:= $(boot-y) ../simple/legacy.o
+
+include $(TOPDIR)/Rules.make
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+of1275 := $(boot)/of1275
+images := $(boot)/images
+simple := $(boot)/simple
+
+OBJS	:= $(addprefix $(obj)/,$(boot-y)) $(simple)/legacy.o 
 
 # Tools
-MKPREP				:= ../utils/mkprep
-SIZE				:= ../utils/size
-OFFSET				:= ../utils/offset
+MKPREP				:= $(utils)/mkprep
+SIZE				:= $(utils)/size
+OFFSET				:= $(utils)/offset
 
 # Extra include search dirs
-CFLAGS_kbd.o			+= -I$(TOPDIR)/drivers/char
+CFLAGS_kbd.o			+= -Idrivers/char
+
+zImage: $(images)/zImage.prep
+zImage.initrd: $(images)/zImage.initrd.prep
 
-all: zImage
+$(obj)/dummy.o: $(common)/dummy.c
+	$(CC) -c -o $@ $(common)/dummy.c
 
-zImage: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o \
-		$(MKPREP)
+$(images)/zImage.prep: $(OBJS) $(LIBS) $(boot)/ld.script \
+		$(images)/vmlinux.gz $(obj)/dummy.o
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=.image=../images/vmlinux.gz \
+		--add-section=.image=$(images)/vmlinux.gz \
 		--set-section-flags=.image=contents,alloc,load,readonly,data \
-		../common/dummy.o image.o
-	$(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr
-	$(MKPREP) -pbp $@ ../images/$@.prep
-	rm -f $@
+		$(obj)/dummy.o $(obj)/image.o
+	$(LD) $(LD_ARGS) -o $(obj)/zImage $(OBJS) $(obj)/image.o $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/zImage $(obj)/zImage \
+		-R .comment -R .stab -R .stabstr
+	$(MKPREP) -pbp $(obj)/zImage $@
+	rm -f $(obj)/zImage
 
-zImage.initrd: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz $(MKPREP) \
-		../common/dummy.o
+$(images)/zImage.initrd.prep: $(OBJS) $(LIBS) $(boot)/ld.script \
+		$(images)/vmlinux.gz $(obj)/dummy.o
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=.ramdisk=../images/ramdisk.image.gz \
+		--add-section=.ramdisk=$(images)/ramdisk.image.gz \
 		--set-section-flags=.ramdisk=contents,alloc,load,readonly,data \
-		--add-section=.image=../images/vmlinux.gz \
+		--add-section=.image=$(images)/vmlinux.gz \
 		--set-section-flags=.image=contents,alloc,load,readonly,data \
-		../common/dummy.o image.o
-	$(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr
-	$(MKPREP) -pbp $@ ../images/$@.prep
-	rm -f $@
+		$(obj)/dummy.o $(obj)/image.o
+	$(LD) $(LD_ARGS) -o $(obj)/zImage.initrd $(OBJS) $(obj)/image.o $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/zImage.initrd $(obj)/zImage.initrd \
+		-R .comment -R .stab -R .stabstr
+	$(MKPREP) -pbp $(obj)/zImage.initrd $@
+	rm -f  $(obj)/zImage.initrd
 
 floppy: zImage
-	dd if=../images/zImage.prep of=/dev/fd0H1440 bs=64b
+	dd if=$(images)/zImage.prep of=/dev/fd0H1440 bs=64b
 
 znetboot : zImage
-	cp ../images/zImage.prep $(TFTPIMAGE)
+	cp $(images)/zImage.prep $(TFTPIMAGE)
 
 znetboot.initrd : zImage.initrd
-	cp ../images/zImage.initrd.prep $(TFTPIMAGE)
-
-include $(TOPDIR)/Rules.make
+	cp $(images)/zImage.initrd.prep $(TFTPIMAGE)
diff -Nru a/arch/ppc/boot/prep/misc.c b/arch/ppc/boot/prep/misc.c
--- a/arch/ppc/boot/prep/misc.c	Fri Oct 18 21:03:06 2002
+++ b/arch/ppc/boot/prep/misc.c	Fri Oct 18 21:03:06 2002
@@ -132,11 +132,6 @@
 	vga_init((unsigned char *)0xC0000000);
 #endif /* CONFIG_VGA_CONSOLE */
 
-	/* 
-	 * Find out how much memory we have.
-	 */
-	TotalMemory = get_mem_size();
-
 	/*
 	 * Tell the user where we were loaded at and where we were relocated
 	 * to for debugging this process.
@@ -214,6 +209,29 @@
 		/* Tell the user we didn't find anything. */
 		puts("No residual data found.\n");
         }
+
+	/* First, figure out what kind of host bridge we are on.  If it's
+	 * an MPC10x, we can ask it directly how much memory it has.
+	 * Otherwise, see if the residual data has anything.  This isn't
+	 * the best way, but it can be the only way.  If there's nothing,
+	 * assume 32MB. -- Tom.
+	 */
+	/* See what our host bridge is. */
+	pci_read_config_32(0x00, 0x00, &pci_viddid);
+	pci_did = (pci_viddid & 0xffff0000) >> 16;
+	/* See if we are on an MPC10x. */
+	if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA)
+			&& ((pci_did == PCI_DEVICE_ID_MOTOROLA_MPC105)
+				|| (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC106)
+				|| (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC107)))
+		TotalMemory = get_mem_size();
+	/* If it's not, see if we have anything in the residual data. */
+	else if (residual && residual->TotalMemory)
+		TotalMemory = residual->TotalMemory;
+	/* Fall back to hard-coding 32MB. */
+	else
+		TotalMemory = 32*1024*1024;
+
 
 	/* assume the chunk below 8M is free */
 	end_avail = (char *)0x00800000;
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/boot/simple/Makefile	Fri Oct 18 21:03:03 2002
@@ -24,9 +24,11 @@
 # Free Software Foundation;  either version 2 of the  License, or (at your
 # option) any later version.
 
-# Normally, we use the 'misc-simple.c' file for decompress_kernel and
+boot: zImage
+
+# Normally, we use the 'misc.c' file for decompress_kernel and
 # whatnot.  Sometimes we need to override this however.
-MISC				:= ../common/misc-simple.o
+MISC				:= misc.o
 ifeq ($(CONFIG_IBM_OPENBIOS),y)
 ZIMAGE				:= zImage-TREE
 ZIMAGEINITRD			:= zImage.initrd-TREE
@@ -38,6 +40,14 @@
 TFTPIMAGE			:= /tftpboot/zImage.embedded
 MISC				:= misc-embedded.o
 endif
+ifeq ($(CONFIG_EBONY),y)
+ZIMAGE				:= zImage-TREE
+ZIMAGEINITRD			:= zImage.initrd-TREE
+EXTRA				:= direct.o
+END				:= ebony
+ENTRYPOINT			:= 0x01000000
+TFTPIMAGE			:= /tftpboot/zImage.$(END)
+endif
 ifeq ($(CONFIG_EV64260),y)
 EXTRA				:= direct.o misc-ev64260.o
 TFTPIMAGE			:= /tftpboot/zImage.ev64260
@@ -72,11 +82,8 @@
 ifeq ($(CONFIG_PPLUS),y)
 EXTRA				:= legacy.o
 endif
-ifeq ($(CONFIG_LOPEC),y)
-EXTRA				+= ../common/mpc10x_memory.o
-endif
 ifeq ($(CONFIG_PAL4),y)
-EXTRA				:= direct.o ../common/cpc700_memory.o
+EXTRA				:= direct.o
 endif
 ifeq ($(CONFIG_PCORE)$(CONFIG_POWERPMC250),y)
 ZIMAGE				:= zImage-STRIPELF
@@ -122,21 +129,25 @@
 # Default linker args.  Link at 0x00800000 or 0x00400000 by default, but
 # allow it to be overridden.
 ifeq ($(CONFIG_BOOT_LOAD_BOOL),y)
-LD_ARGS				:= -T ../ld.script -Ttext $(CONFIG_BOOT_LOAD) \
-					-Bstatic
+LD_ARGS				:= -T $(boot)/ld.script \
+					-Ttext $(CONFIG_BOOT_LOAD) -Bstatic
 else
-LD_ARGS				= -T ../ld.script -Ttext 0x00800000 -Bstatic
-ifeq ($(CONFIG_8260)$(CONFIG_4xx)$(CONFIG_8xx),y)
-LD_ARGS				:= -T ../ld.script -Ttext 0x00400000 -Bstatic
+LD_ARGS				= -T $(boot)/ld.script \
+					-Ttext 0x00800000 -Bstatic
+ifeq ($(CONFIG_8260)$(CONFIG_40x)$(CONFIG_8xx),y)
+LD_ARGS				:= -T $(boot)/ld.script -Ttext 0x00400000 \
+					-Bstatic
+endif
+ifeq ($(CONFIG_440),y)
+LD_ARGS				:= -T $(boot)/ld.script -Ttext 0x01000000 \
+					-Bstatic
 endif
 endif
 OBJCOPY_ARGS			:= -O elf32-powerpc
 
-# head.o and ../common/relocate.o must be at the start.
-boot-y				:= head.o ../common/relocate.o $(EXTRA) \
-				$(MISC) ../common/misc-common.o \
-				../common/string.o ../common/util.o
-boot-$(CONFIG_4xx)		+= embed_config.o
+# head.o and relocate.o must be at the start.
+boot-y				:= head.o relocate.o $(EXTRA) $(MISC) 
+boot-$(CONFIG_40x)		+= embed_config.o
 boot-$(CONFIG_8xx)		+= embed_config.o
 boot-$(CONFIG_8260)		+= embed_config.o
 boot-$(CONFIG_BSEIP)		+= iic.o
@@ -149,84 +160,97 @@
 boot-$(CONFIG_8260)		+= m8260_tty.o
 boot-$(CONFIG_GT64260_CONSOLE)	+= gt64260_tty.o
 endif
-boot-$(CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o
+
+boot				:= arch/ppc/boot
+common				:= $(boot)/common
+utils				:= $(boot)/utils
+bootlib				:= $(boot)/lib
+images				:= $(boot)/images
 
 EXTRA_TARGETS			:= $(boot-y)
-LIBS				:= ../lib/lib.a
+LIBS				:=  $(common)/lib.a $(bootlib)/lib.a
+
+include $(TOPDIR)/Rules.make
+
+OBJS				:= $(addprefix $(obj)/,$(boot-y))
 
 # Tools
-MKBUGBOOT			:= ../utils/mkbugboot
-MKPREP				:= ../utils/mkprep
-MKTREE				:= ../utils/mktree
+MKBUGBOOT			:= $(utils)/mkbugboot
+MKPREP				:= $(utils)/mkprep
+MKTREE				:= $(utils)/mktree
+
+$(obj)/dummy.o: $(common)/dummy.c
+	$(CC) -c -o $@ $(common)/dummy.c
 
-zvmlinux: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o
+$(obj)/zvmlinux: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \
+	$(obj)/dummy.o
 	$(OBJCOPY) $(OBJCOPY_ARGS) \
-		--add-section=.image=../images/vmlinux.gz \
+		--add-section=.image=$(images)/vmlinux.gz \
 		--set-section-flags=.image=contents,alloc,load,readonly,data \
-		../common/dummy.o image.o
-	$(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \
-		-R .ramdisk -R .sysmap
+		$(obj)/dummy.o $(obj)/image.o
+	$(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
+		-R .stabstr -R .ramdisk -R .sysmap
 
-zvmlinux.initrd: $(boot-y) $(LIBS) ../ld.script ../images/vmlinux.gz \
-		../common/dummy.o
+$(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(boot)/ld.script \
+		$(images)/vmlinux.gz $(obj)/dummy.o
 	$(OBJCOPY) $(OBJCOPY_ARGS) \
-		--add-section=.ramdisk=../images/ramdisk.image.gz \
+		--add-section=.ramdisk=$(images)/ramdisk.image.gz \
 		--set-section-flags=.ramdisk=contents,alloc,load,readonly,data \
-		--add-section=.image=../images/vmlinux.gz \
+		--add-section=.image=$(images)/vmlinux.gz \
 		--set-section-flags=.image=contents,alloc,load,readonly,data \
-		../common/dummy.o image.o
-	$(LD) $(LD_ARGS) -o $@ $(boot-y) image.o $(LIBS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \
-		-R .sysmap
+		$(obj)/dummy.o $(obj)/image.o
+	$(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
+		-R .stabstr -R .sysmap
 
 # Sort-of dummy rules, that let us format the image we want.
-zImage: $(ZIMAGE) zvmlinux
-	cp -f zvmlinux ../images/zImage.elf
-	rm -f zvmlinux
-
-zImage.initrd: $(ZIMAGEINITRD) zvmlinux.initrd
-	cp -f zvmlinux.initrd ../images/zImage.initrd.elf
-	rm -f zvmlinux.initrd
+zImage: $(images)/$(ZIMAGE) $(obj)/zvmlinux
+	cp -f $(obj)/zvmlinux $(images)/zImage.elf
+	rm -f $(obj)/zvmlinux
+
+zImage.initrd: $(images)/$(ZIMAGEINITRD) $(obj)/zvmlinux.initrd
+	cp -f $(obj)/zvmlinux.initrd $(images)/zImage.initrd.elf
+	rm -f $(obj)/zvmlinux.initrd
 
 znetboot: zImage
 ifneq ($(ZNETBOOT),)
-	cp ../images/$(ZNETBOOT) $(TFTPIMAGE)
+	cp $(images)/$(ZNETBOOT) $(TFTPIMAGE)
 else
-	cp ../images/zImage.* $(TFTPIMAGE)
+	cp $(images)/zImage.* $(TFTPIMAGE)
 endif
 
 znetboot.initrd: zImage.initrd
 ifneq ($(ZNETBOOTRD),)
-	cp ../images/$(ZNETBOOTRD) $(TFTPIMAGE)
+	cp $(images)/$(ZNETBOOTRD) $(TFTPIMAGE)
 else
-	cp ../images/zImage.* $(TFTPIMAGE)
+	cp $(images)/zImage.* $(TFTPIMAGE)
 endif
 
-zImage-STRIPELF: zvmlinux
-	dd if=zvmlinux of=../images/zImage.$(END) skip=64 bs=1k
+$(images)/zImage-STRIPELF: $(obj)/zvmlinux
+	dd if=$(obj)/zvmlinux of=$(images)/zImage.$(END) skip=64 bs=1k
 
-zImage.initrd-STRIPELF: zvmlinux.initrd
-	dd if=zvmlinux.initrd of=../images/zImage.initrd.$(END) skip=64 bs=1k
+$(images)/zImage.initrd-STRIPELF: $(obj)/zvmlinux.initrd
+	dd if=$(obj)/zvmlinux.initrd of=$(images)/zImage.initrd.$(END) \
+		skip=64 bs=1k
 
-zImage-TREE: zvmlinux
-	$(MKTREE) zvmlinux ../images/zImage.$(END) $(ENTRYPOINT)
+$(images)/zImage-TREE: $(obj)/zvmlinux
+	$(MKTREE) $(obj)/zvmlinux $(images)/zImage.$(END) $(ENTRYPOINT)
 
-zImage.initrd-TREE: zvmlinux.initrd
-	$(MKTREE) zvmlinux.initrd ../images/zImage.initrd.$(END) $(ENTRYPOINT)
+$(images)/zImage.initrd-TREE: $(obj)/zvmlinux.initrd
+	$(MKTREE) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(END) \
+		$(ENTRYPOINT)
 
-zImage-MENF1: zvmlinux
-	$(MKPREP) -pbp zvmlinux ../images/zImage.menf1
+$(images)/zImage-MENF1: $(obj)/zvmlinux
+	$(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.menf1
 
-zImage.initrd-MENF1: zvmlinux.initrd
-	$(MKPREP) -pbp zvmlinux.initrd ../images/zImage.initrd.menf1
+$(images)/zImage.initrd-MENF1: $(obj)/zvmlinux.initrd
+	$(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.menf1
 
-zImage-PPLUS: zvmlinux $(MKPREP) $(MKBUGBOOT)
-	$(MKPREP) -pbp zvmlinux ../images/zImage.pplus
-	$(MKBUGBOOT) zvmlinux ../images/zImage.bugboot
+$(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT)
+	$(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.pplus
+	$(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot
 
-zImage.initrd-PPLUS: zvmlinux.initrd $(MKPREP) $(MKBUGBOOT)
-	$(MKPREP) -pbp zvmlinux.initrd ../images/zImage.initrd.pplus
-	$(MKBUGBOOT) zvmlinux.initrd ../images/zImage.initrd.bugboot
-
-include $(TOPDIR)/Rules.make
+$(images)/zImage.initrd-PPLUS: $(obj)/zvmlinux.initrd $(MKPREP) $(MKBUGBOOT)
+	$(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.pplus
+	$(MKBUGBOOT) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.bugboot
diff -Nru a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/boot/simple/misc.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,236 @@
+/*
+ * arch/ppc/common/misc-simple.c
+ *
+ * Misc. bootloader code for many machines.  This assumes you have are using
+ * a 6xx/7xx/74xx CPU in your machine.  This assumes the chunk of memory
+ * below 8MB is free.  Finally, it assumes you have a NS16550-style uart for
+ * your serial console.  If a machine meets these requirements, it can quite
+ * likely use this code during boot.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ * Derived from arch/ppc/boot/prep/misc.c
+ *
+ * Copyright 2001 MontaVista Software 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 the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/elf.h>
+#include <linux/config.h>
+
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/bootinfo.h>
+
+#include "nonstdio.h"
+#include "zlib.h"
+
+/* Default cmdline */
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE ""
+#endif
+
+/* Keyboard (and VGA console)? */
+#ifdef CONFIG_VGA_CONSOLE
+#define HAS_KEYB 1
+#else
+#define HAS_KEYB 0
+#endif
+
+char *avail_ram;
+char *end_avail;
+char *zimage_start;
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+int keyb_present = HAS_KEYB;
+int zimage_size;
+
+unsigned long com_port;
+unsigned long initrd_size = 0;
+
+/* The linker tells us various locations in the image */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin, __ramdisk_end;
+extern char _end[];
+/* Original location */
+extern unsigned long start;
+
+extern int CRT_tstc(void);
+extern unsigned long get_mem_size(void);
+extern unsigned long serial_init(int chan, void *ignored);
+extern void serial_close(unsigned long com_port);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void serial_fixups(void);
+
+struct bi_record *
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
+{
+	int timer = 0;
+	char *cp, ch;
+	struct bi_record *rec, *birecs;
+	unsigned long TotalMemory = 0;
+
+	serial_fixups();
+	com_port = serial_init(0, NULL);
+
+#if defined(CONFIG_LOPEC) || defined(CONFIG_PAL4)
+	/*
+	 * Call get_mem_size(), which is memory controller dependant,
+	 * and we must have the correct file linked in here.
+	 */
+	TotalMemory = get_mem_size();
+#endif
+
+	/* assume the chunk below 8M is free */
+	end_avail = (char *)0x00800000;
+
+	/*
+	 * Reveal where we were loaded at and where we
+	 * were relocated to.
+	 */
+	puts("loaded at:     "); puthex(load_addr);
+	puts(" "); puthex((unsigned long)(load_addr + (4*num_words)));
+	puts("\n");
+	if ( (unsigned long)load_addr != (unsigned long)&start )
+	{
+		puts("relocated to:  "); puthex((unsigned long)&start);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+		puts("\n");
+	}
+
+	/*
+	 * We link ourself to 0x00800000.  When we run, we relocate
+	 * ourselves there.  So we just need __image_begin for the
+	 * start. -- Tom
+	 */
+	zimage_start = (char *)(unsigned long)(&__image_begin);
+	zimage_size = (unsigned long)(&__image_end) -
+			(unsigned long)(&__image_begin);
+
+	initrd_size = (unsigned long)(&__ramdisk_end) -
+		(unsigned long)(&__ramdisk_begin);
+
+	/*
+	 * The zImage and initrd will be between start and _end, so they've
+	 * already been moved once.  We're good to go now. -- Tom
+	 */
+	avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
+	puts("zimage at:     "); puthex((unsigned long)zimage_start);
+	puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
+	puts("\n");
+
+	if ( initrd_size ) {
+		puts("initrd at:     ");
+		puthex((unsigned long)(&__ramdisk_begin));
+		puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
+	}
+
+	avail_ram = (char *)0x00400000;
+	end_avail = (char *)0x00800000;
+	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
+	puthex((unsigned long)end_avail); puts("\n");
+
+	if (keyb_present)
+		CRT_tstc();  /* Forces keyboard to be initialized */
+#ifdef CONFIG_GEMINI
+	/*
+	 * If cmd_line is empty and cmd_preset is not, copy cmd_preset
+	 * to cmd_line.  This way we can override cmd_preset with the
+	 * command line from Smon.
+	 */
+
+	if ( (cmd_line[0] == '\0') && (cmd_preset[0] != '\0'))
+		memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+#endif
+
+	/* Display standard Linux/PPC boot prompt for kernel args */
+	puts("\nLinux/PPC load: ");
+	cp = cmd_line;
+	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+	while ( *cp ) putc(*cp++);
+
+#ifndef CONFIG_GEMINI
+	/* Val Henson has requested that Gemini doesn't wait for the
+	 * user to edit the cmdline or not. */
+	while (timer++ < 5*1000) {
+		if (tstc()) {
+			while ((ch = getc()) != '\n' && ch != '\r') {
+				/* Test for backspace/delete */
+				if (ch == '\b' || ch == '\177') {
+					if (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
+				/* Test for ^x/^u (and wipe the line) */
+				} else if (ch == '\030' || ch == '\025') {
+					while (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
+				} else {
+					*cp++ = ch;
+					putc(ch);
+				}
+			}
+			break;  /* Exit 'timer' loop */
+		}
+		udelay(1000);  /* 1 msec */
+	}
+	*cp = 0;
+#endif
+	puts("\n");
+
+	puts("Uncompressing Linux...");
+	gunzip(0, 0x400000, zimage_start, &zimage_size);
+	puts("done.\n");
+
+	/*
+	 * Create bi_recs for cmd_line and initrds
+	 */
+	rec = (struct bi_record *)_ALIGN((unsigned long)(zimage_size) +
+			(1 << 20) - 1, (1 << 20));
+	birecs = rec;
+
+	rec->tag = BI_FIRST;
+	rec->size = sizeof(struct bi_record);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+	if ( TotalMemory ) {
+		rec->tag = BI_MEMSIZE;
+		rec->data[0] = TotalMemory;
+		rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+		rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	}
+
+	rec->tag = BI_CMD_LINE;
+	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
+	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+	if ( initrd_size ) {
+		rec->tag = BI_INITRD;
+		rec->data[0] = (unsigned long)(&__ramdisk_begin);
+		rec->data[1] = initrd_size;
+		rec->size = sizeof(struct bi_record) + 2 *
+			sizeof(unsigned long);
+		rec = (struct bi_record *)((unsigned long)rec +
+				rec->size);
+	}
+
+	rec->tag = BI_LAST;
+	rec->size = sizeof(struct bi_record);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	puts("Now booting the kernel\n");
+	serial_close(com_port);
+
+	return birecs;
+}
diff -Nru a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/boot/simple/relocate.S	Fri Oct 18 21:03:04 2002
@@ -0,0 +1,205 @@
+/*
+ * arch/ppc/boot/simple/relocate.S
+ *
+ * This is the common part of the loader relocation and initialization
+ * process.  All of the board/processor specific initialization is
+ * done before we get here.
+ *
+ * Author: Tom Rini
+ *	   trini@mvista.com
+ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
+ *
+ * Copyright 2001-2002 MontaVista Software 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 the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/ppc_asm.h>
+
+#define GETSYM(reg, sym)	\
+	lis	reg, sym@h; ori	reg, reg, sym@l	
+	
+	.text
+	/* We get called from the early initialization code.
+	 * Register 3 has the address where we were loaded,
+	 * Register 4 contains any residual data passed from the
+	 * boot rom.
+	 */
+	.globl	relocate
+relocate:
+	/* Save r3, r4 for later.
+	 * The r8/r11 are legacy registers so I don't have to
+	 * rewrite the code below :-).
+	 */
+	mr	r8, r3
+	mr	r11, r4
+
+	/* compute the size of the whole image in words. */
+	GETSYM(r4,start)
+	GETSYM(r5,end)
+
+	addi	r5,r5,3		/* round up */
+	sub	r5,r5,r4	/* end - start */
+	srwi	r5,r5,2
+	mr	r7,r5		/* Save for later use. */
+
+	/*
+	 * Check if we need to relocate ourselves to the link addr or were
+	 * we loaded there to begin with.
+	 */
+	cmp	cr0,r3,r4
+	beq	start_ldr	/* If 0, we don't need to relocate */
+
+	/* Move this code somewhere safe.  This is max(load + size, end) 
+	 * r8 == load address
+	 */
+	GETSYM(r4, start)
+	GETSYM(r5, end)
+
+	sub	r6,r5,r4
+	add	r6,r8,r6	/* r6 == phys(load + size) */
+
+	cmpw	r5,r6
+	bgt	1f
+	b	2f
+1:	
+	mr	r6, r5	
+2: 
+	/* dest is in r6 */	
+	/* Ensure alignment --- this code is precautionary */
+	addi	r6,r6,4
+	li	r5,0x0003
+	andc	r6,r6,r5
+
+	/* Find physical address and size of do_relocate */
+	GETSYM(r5, __relocate_start)
+	GETSYM(r4, __relocate_end)
+	GETSYM(r3, start)
+
+	/* Size to copy */
+	sub	r4,r4,r5	
+	srwi	r4,r4,2
+	
+	/* Src addr to copy (= __relocate_start - start + where_loaded) */
+	sub	r3,r5,r3
+	add	r5,r8,r3	
+
+	/* Save dest */
+	mr	r3, r6
+
+	/* Do the copy */	
+	mtctr	r4	
+3:	lwz	r4,0(r5)
+	stw	r4,0(r3)	
+	addi	r3,r3,4
+	addi	r5,r5,4
+	bdnz	3b
+
+	GETSYM(r4, __relocate_start)
+	GETSYM(r5, do_relocate)
+
+	sub	r4,r5,r4	/* Get entry point for do_relocate in
+	add	r6,r6,r4       * relocated section */
+
+	/* This will return to the relocated do_relocate */
+	mtlr	r6
+	b	flush_instruction_cache
+
+	.section ".relocate_code","xa"
+			
+do_relocate:		
+	/* We have 2 cases --- start < load, or start > load  
+	 * This determines whether we copy from the end, or the start.
+	 * Its easier to have 2 loops than to have paramaterised
+	 * loops.  Sigh.
+	 */
+	li	r6,0		/* Clear checksum */
+	mtctr	r7		/* Setup for a loop */
+			
+	GETSYM(r4, start)
+	mr	r3,r8		/* Get the load addr */
+
+	cmp	cr0,r4,r3	/* If we need to copy from the end, do so */
+	bgt	do_relocate_from_end
+	
+do_relocate_from_start:		
+1:	lwz	r5,0(r3)	/* Load and decrement */
+	stw	r5,0(r4)	/* Store and decrement */
+	addi	r3,r3,4
+	addi	r4,r4,4
+	xor	r6,r6,r5	/* Update checksum */
+	bdnz	1b		/* Are we done? */
+	b	do_relocate_out	/* Finished */
+
+do_relocate_from_end:	
+	GETSYM(r3, end)
+	slwi	r4,r7,2
+	add	r4,r8,r4	/* Get the physical end */
+1:	lwzu	r5,-4(r4)
+	stwu	r5, -4(r3)
+	xor	r6,r6,r5
+	bdnz	1b
+
+do_relocate_out:	
+	GETSYM(r3,start_ldr)
+	mtlr	r3		/* Easiest way to do an absolute jump */
+/* Some boards don't boot up with the I-cache enabled.  Do that
+ * now because the decompress runs much faster that way.
+ * As a side effect, we have to ensure the data cache is not enabled
+ * so we can access the serial I/O without trouble.
+ */
+	b	flush_instruction_cache
+
+	.previous
+		
+start_ldr:
+/* Clear all of BSS and set up stack for C calls */
+	lis	r3,edata@h
+	ori	r3,r3,edata@l
+	lis	r4,end@h
+	ori	r4,r4,end@l
+	subi	r3,r3,4
+	subi	r4,r4,4
+	li	r0,0
+50:	stwu	r0,4(r3)
+	cmp	cr0,r3,r4
+	bne	50b
+90:	mr	r9,r1		/* Save old stack pointer (in case it matters) */
+	lis	r1,.stack@h
+	ori	r1,r1,.stack@l
+	addi	r1,r1,4096*2
+	subi	r1,r1,256
+	li	r2,0x000F	/* Mask pointer to 16-byte boundary */
+	andc	r1,r1,r2
+
+	/*
+	 * Exec kernel loader
+	 */
+	mr	r3,r8		/* Load point */
+	mr	r4,r7		/* Program length */
+	mr	r5,r6		/* Checksum */
+	mr	r6,r11		/* Residual data */
+	bl	decompress_kernel
+
+	/*
+	 * Make sure the kernel knows we don't have things set in
+	 * registers.  -- Tom
+	 */
+	li	r4,0
+	li	r5,0
+	li	r6,0
+
+	/*
+	 * Start at the begining.
+	 */
+	li	r9,0x0000
+	mtlr	r9
+	blr
+
+	.comm	.stack,4096*2,4
diff -Nru a/arch/ppc/config.in b/arch/ppc/config.in
--- a/arch/ppc/config.in	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/config.in	Fri Oct 18 21:03:04 2002
@@ -131,6 +131,7 @@
 	 Motorola-Sandpoint	CONFIG_SANDPOINT	\
 	 SBS-Adirondack		CONFIG_ADIR		\
 	 SBS-K2			CONFIG_K2		\
+	 SBS-Palomar4		CONFIG_PAL4		\
 	 Synergy-Gemini		CONFIG_GEMINI		\
 	 Zynx-ZX4500		CONFIG_ZX4500"		CHRP/PowerMac/PReP
 
@@ -584,23 +585,31 @@
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
-bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
-bool 'Spinlock debugging' CONFIG_DEBUG_SPINLOCK
-bool 'Include kgdb kernel debugger' CONFIG_KGDB
-if [ "$CONFIG_KGDB" = "y" ]; then
-   choice 'Serial Port'			\
-	"ttyS0	CONFIG_KGDB_TTYS0	\
-	 ttyS1	CONFIG_KGDB_TTYS1	\
-	 ttyS2	CONFIG_KGDB_TTYS2	\
-	 ttyS3	CONFIG_KGDB_TTYS3"	ttyS1
-fi
-bool 'Include xmon kernel debugger' CONFIG_XMON
-bool 'Include BDI-2000 user context switcher' CONFIG_BDI_SWITCH
-if [ "$CONFIG_KGDB" = "y" -o "$CONFIG_XMON" = "y" \
-     -o "$CONFIG_BDI_SWITCH" = "y" ]; then
-   bool 'Add any additional compile options' CONFIG_MORE_COMPILE_OPTIONS
-   if [ "$CONFIG_MORE_COMPILE_OPTIONS" = "y" ]; then
-      string 'Additional compile arguments' CONFIG_COMPILE_OPTIONS "-g -ggdb"
+bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+if [ "$CONFIG_DEBUG_KERNEL" = "y" ]; then
+   bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
+   bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
+   bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   if [ "$CONFIG_HIGHMEM" = "y" ]; then
+      bool '  Highmem debugging' CONFIG_DEBUG_HIGHMEM
+   fi
+   bool '  Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
+   bool '  Include kgdb kernel debugger' CONFIG_KGDB
+   if [ "$CONFIG_KGDB" = "y" ]; then
+      choice '    Serial Port'			\
+	"ttyS0	CONFIG_KGDB_TTYS0		\
+	 ttyS1	CONFIG_KGDB_TTYS1		\
+	 ttyS2	CONFIG_KGDB_TTYS2		\
+	 ttyS3	CONFIG_KGDB_TTYS3"		ttyS1
+   fi
+   bool '  Include xmon kernel debugger' CONFIG_XMON
+   bool '  Include BDI-2000 user context switcher' CONFIG_BDI_SWITCH
+   if [ "$CONFIG_KGDB" = "y" -o "$CONFIG_XMON" = "y" \
+	-o "$CONFIG_BDI_SWITCH" = "y" ]; then
+      bool '  Add any additional compile options' CONFIG_MORE_COMPILE_OPTIONS
+      if [ "$CONFIG_MORE_COMPILE_OPTIONS" = "y" ]; then
+	 string '    Additional compile arguments' CONFIG_COMPILE_OPTIONS "-g -ggdb"
+      fi
    fi
 fi
 
diff -Nru a/arch/ppc/configs/FADS_defconfig b/arch/ppc/configs/FADS_defconfig
--- a/arch/ppc/configs/FADS_defconfig	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc/configs/FADS_defconfig	Fri Oct 18 21:03:07 2002
@@ -466,7 +466,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/IVMS8_defconfig b/arch/ppc/configs/IVMS8_defconfig
--- a/arch/ppc/configs/IVMS8_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/IVMS8_defconfig	Fri Oct 18 21:03:03 2002
@@ -587,7 +587,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/SM850_defconfig b/arch/ppc/configs/SM850_defconfig
--- a/arch/ppc/configs/SM850_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/SM850_defconfig	Fri Oct 18 21:03:04 2002
@@ -559,7 +559,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/SPD823TS_defconfig b/arch/ppc/configs/SPD823TS_defconfig
--- a/arch/ppc/configs/SPD823TS_defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/configs/SPD823TS_defconfig	Fri Oct 18 21:03:08 2002
@@ -558,7 +558,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/TQM823L_defconfig b/arch/ppc/configs/TQM823L_defconfig
--- a/arch/ppc/configs/TQM823L_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/TQM823L_defconfig	Fri Oct 18 21:03:03 2002
@@ -559,7 +559,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/TQM850L_defconfig b/arch/ppc/configs/TQM850L_defconfig
--- a/arch/ppc/configs/TQM850L_defconfig	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc/configs/TQM850L_defconfig	Fri Oct 18 21:03:05 2002
@@ -559,7 +559,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/TQM860L_defconfig b/arch/ppc/configs/TQM860L_defconfig
--- a/arch/ppc/configs/TQM860L_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/TQM860L_defconfig	Fri Oct 18 21:03:04 2002
@@ -618,7 +618,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/adir_defconfig b/arch/ppc/configs/adir_defconfig
--- a/arch/ppc/configs/adir_defconfig	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc/configs/adir_defconfig	Fri Oct 18 21:03:07 2002
@@ -637,7 +637,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/apus_defconfig b/arch/ppc/configs/apus_defconfig
--- a/arch/ppc/configs/apus_defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/configs/apus_defconfig	Fri Oct 18 21:03:08 2002
@@ -925,7 +925,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/ash_defconfig b/arch/ppc/configs/ash_defconfig
--- a/arch/ppc/configs/ash_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/ash_defconfig	Fri Oct 18 21:03:03 2002
@@ -558,7 +558,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/bseip_defconfig b/arch/ppc/configs/bseip_defconfig
--- a/arch/ppc/configs/bseip_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/bseip_defconfig	Fri Oct 18 21:03:03 2002
@@ -558,7 +558,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/cedar_defconfig b/arch/ppc/configs/cedar_defconfig
--- a/arch/ppc/configs/cedar_defconfig	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc/configs/cedar_defconfig	Fri Oct 18 21:03:07 2002
@@ -600,7 +600,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
--- a/arch/ppc/configs/common_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/common_defconfig	Fri Oct 18 21:03:04 2002
@@ -972,7 +972,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/cpci405_defconfig b/arch/ppc/configs/cpci405_defconfig
--- a/arch/ppc/configs/cpci405_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/cpci405_defconfig	Fri Oct 18 21:03:04 2002
@@ -624,7 +624,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/ep405_defconfig b/arch/ppc/configs/ep405_defconfig
--- a/arch/ppc/configs/ep405_defconfig	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc/configs/ep405_defconfig	Fri Oct 18 21:03:07 2002
@@ -594,7 +594,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/est8260_defconfig b/arch/ppc/configs/est8260_defconfig
--- a/arch/ppc/configs/est8260_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/est8260_defconfig	Fri Oct 18 21:03:04 2002
@@ -529,7 +529,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/ev64260_defconfig b/arch/ppc/configs/ev64260_defconfig
--- a/arch/ppc/configs/ev64260_defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/configs/ev64260_defconfig	Fri Oct 18 21:03:08 2002
@@ -596,7 +596,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig
--- a/arch/ppc/configs/gemini_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/gemini_defconfig	Fri Oct 18 21:03:04 2002
@@ -626,7 +626,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/iSeries_defconfig b/arch/ppc/configs/iSeries_defconfig
--- a/arch/ppc/configs/iSeries_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/iSeries_defconfig	Fri Oct 18 21:03:03 2002
@@ -466,7 +466,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig
--- a/arch/ppc/configs/ibmchrp_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/ibmchrp_defconfig	Fri Oct 18 21:03:04 2002
@@ -808,7 +808,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/k2_defconfig b/arch/ppc/configs/k2_defconfig
--- a/arch/ppc/configs/k2_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/k2_defconfig	Fri Oct 18 21:03:03 2002
@@ -614,7 +614,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/lopec_defconfig b/arch/ppc/configs/lopec_defconfig
--- a/arch/ppc/configs/lopec_defconfig	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc/configs/lopec_defconfig	Fri Oct 18 21:03:05 2002
@@ -873,7 +873,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Library routines
diff -Nru a/arch/ppc/configs/mbx_defconfig b/arch/ppc/configs/mbx_defconfig
--- a/arch/ppc/configs/mbx_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/mbx_defconfig	Fri Oct 18 21:03:03 2002
@@ -551,7 +551,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/mcpn765_defconfig b/arch/ppc/configs/mcpn765_defconfig
--- a/arch/ppc/configs/mcpn765_defconfig	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc/configs/mcpn765_defconfig	Fri Oct 18 21:03:05 2002
@@ -464,7 +464,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/menf1_defconfig b/arch/ppc/configs/menf1_defconfig
--- a/arch/ppc/configs/menf1_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/menf1_defconfig	Fri Oct 18 21:03:03 2002
@@ -660,7 +660,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/oak_defconfig b/arch/ppc/configs/oak_defconfig
--- a/arch/ppc/configs/oak_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/oak_defconfig	Fri Oct 18 21:03:03 2002
@@ -573,7 +573,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
--- a/arch/ppc/configs/pmac_defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/configs/pmac_defconfig	Fri Oct 18 21:03:08 2002
@@ -1052,7 +1052,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
--- a/arch/ppc/configs/power3_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/power3_defconfig	Fri Oct 18 21:03:03 2002
@@ -830,7 +830,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/pplus_defconfig b/arch/ppc/configs/pplus_defconfig
--- a/arch/ppc/configs/pplus_defconfig	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc/configs/pplus_defconfig	Fri Oct 18 21:03:05 2002
@@ -756,7 +756,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/prpmc750_defconfig b/arch/ppc/configs/prpmc750_defconfig
--- a/arch/ppc/configs/prpmc750_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/prpmc750_defconfig	Fri Oct 18 21:03:03 2002
@@ -557,7 +557,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/prpmc800_defconfig b/arch/ppc/configs/prpmc800_defconfig
--- a/arch/ppc/configs/prpmc800_defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/configs/prpmc800_defconfig	Fri Oct 18 21:03:08 2002
@@ -514,7 +514,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/redwood5_defconfig b/arch/ppc/configs/redwood5_defconfig
--- a/arch/ppc/configs/redwood5_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/redwood5_defconfig	Fri Oct 18 21:03:04 2002
@@ -561,7 +561,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/redwood_defconfig b/arch/ppc/configs/redwood_defconfig
--- a/arch/ppc/configs/redwood_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/redwood_defconfig	Fri Oct 18 21:03:04 2002
@@ -535,7 +535,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/rpxcllf_defconfig b/arch/ppc/configs/rpxcllf_defconfig
--- a/arch/ppc/configs/rpxcllf_defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/configs/rpxcllf_defconfig	Fri Oct 18 21:03:08 2002
@@ -559,7 +559,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/rpxlite_defconfig b/arch/ppc/configs/rpxlite_defconfig
--- a/arch/ppc/configs/rpxlite_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/rpxlite_defconfig	Fri Oct 18 21:03:03 2002
@@ -556,7 +556,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/sandpoint_defconfig b/arch/ppc/configs/sandpoint_defconfig
--- a/arch/ppc/configs/sandpoint_defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/configs/sandpoint_defconfig	Fri Oct 18 21:03:04 2002
@@ -900,7 +900,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Library routines
diff -Nru a/arch/ppc/configs/spruce_defconfig b/arch/ppc/configs/spruce_defconfig
--- a/arch/ppc/configs/spruce_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/spruce_defconfig	Fri Oct 18 21:03:03 2002
@@ -521,7 +521,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/walnut_defconfig b/arch/ppc/configs/walnut_defconfig
--- a/arch/ppc/configs/walnut_defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/configs/walnut_defconfig	Fri Oct 18 21:03:08 2002
@@ -594,7 +594,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/configs/zx4500_defconfig b/arch/ppc/configs/zx4500_defconfig
--- a/arch/ppc/configs/zx4500_defconfig	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/configs/zx4500_defconfig	Fri Oct 18 21:03:03 2002
@@ -469,7 +469,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/defconfig b/arch/ppc/defconfig
--- a/arch/ppc/defconfig	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/defconfig	Fri Oct 18 21:03:08 2002
@@ -972,7 +972,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc/kernel/indirect_pci.c b/arch/ppc/kernel/indirect_pci.c
--- a/arch/ppc/kernel/indirect_pci.c	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/kernel/indirect_pci.c	Fri Oct 18 21:03:03 2002
@@ -27,13 +27,18 @@
 {
 	struct pci_controller *hose = bus->sysdata;
 	volatile unsigned char *cfg_data;
+	u8 cfg_type = 0;
 
 	if (ppc_md.pci_exclude_device)
 		if (ppc_md.pci_exclude_device(bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
+	
+	if (hose->set_cfg_type)
+		if (bus->number != hose->first_busno)
+			cfg_type = 1;
 
 	out_be32(hose->cfg_addr,
-		 ((offset & 0xfc) << 24) | (devfn << 16)
+		 (((offset & 0xfc) | cfg_type) << 24) | (devfn << 16)
 		 | ((bus->number - hose->bus_offset) << 8) | 0x80);
 	/*
 	 * Note: the caller has already checked that offset is
@@ -60,13 +65,18 @@
 {
 	struct pci_controller *hose = bus->sysdata;
 	volatile unsigned char *cfg_data;
+	u8 cfg_type = 0;
 
 	if (ppc_md.pci_exclude_device)
 		if (ppc_md.pci_exclude_device(bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
+	if (hose->set_cfg_type)
+		if (bus->number != hose->first_busno)
+			cfg_type = 1;
+
 	out_be32(hose->cfg_addr,
-		 ((offset & 0xfc) << 24) | (devfn << 16)
+		 (((offset & 0xfc) | cfg_type) << 24) | (devfn << 16)
 		 | ((bus->number - hose->bus_offset) << 8) | 0x80);
 	/*
 	 * Note: the caller has already checked that offset is
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc/kernel/misc.S	Fri Oct 18 21:03:04 2002
@@ -752,21 +752,6 @@
 #endif /* CONFIG_PPC_ISERIES */
 
 /*
- * Atomic [test&set] exchange
- *
- *	unsigned long xchg_u32(void *ptr, unsigned long val)
- * Changes the memory location '*ptr' to be val and returns
- * the previous value stored there.
- */
-_GLOBAL(xchg_u32)
-	mr	r5,r3		/* Save pointer */
-10:	lwarx	r3,0,r5		/* Fetch old value & reserve */
-	PPC405_ERR77(0,r5)
-	stwcx.	r4,0,r5		/* Update with new value */
-	bne-	10b		/* Retry if "reservation" (i.e. lock) lost */
-	blr
-
-/*
  * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
  * void atomic_set_mask(atomic_t mask, atomic_t *addr);
  */
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/kernel/ppc_ksyms.c	Fri Oct 18 21:03:08 2002
@@ -30,6 +30,8 @@
 #include <linux/pmu.h>
 #include <asm/prom.h>
 #include <asm/system.h>
+#define __KERNEL_SYSCALLS__
+#include <asm/unistd.h>
 #include <asm/pci-bridge.h>
 #include <asm/irq.h>
 #include <asm/pmac_feature.h>
@@ -180,6 +182,10 @@
 EXPORT_SYMBOL(consistent_sync);
 #endif
 
+EXPORT_SYMBOL(open);
+EXPORT_SYMBOL(read);
+EXPORT_SYMBOL(lseek);
+EXPORT_SYMBOL(close);
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
@@ -191,7 +197,6 @@
 EXPORT_SYMBOL(flush_icache_user_range);
 EXPORT_SYMBOL(flush_icache_page);
 EXPORT_SYMBOL(flush_dcache_page);
-EXPORT_SYMBOL(xchg_u32);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL(last_task_used_altivec);
 EXPORT_SYMBOL(giveup_altivec);
diff -Nru a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
--- a/arch/ppc/lib/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/lib/Makefile	Fri Oct 18 21:03:03 2002
@@ -4,7 +4,7 @@
 
 export-objs		:= dec_and_lock.o
 
-obj-y			:= checksum.o string.o strcase.o dec_and_lock.o
+obj-y			:= checksum.o string.o strcase.o dec_and_lock.o div64.o
 
 obj-$(CONFIG_SMP)	+= locks.o
 
diff -Nru a/arch/ppc/lib/div64.S b/arch/ppc/lib/div64.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/lib/div64.S	Fri Oct 18 21:03:09 2002
@@ -0,0 +1,58 @@
+/*
+ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
+ * This routine assumes that the top 32 bits of the dividend are
+ * non-zero to start with.
+ * On entry, r3 points to the dividend, which get overwritten with
+ * the 64-bit quotient, and r4 contains the divisor.
+ * On exit, r3 contains the remainder.
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+_GLOBAL(__div64_32)
+	lwz	r5,0(r3)	# get the dividend into r5/r6
+	lwz	r6,4(r3)
+	cmplw	r5,r4
+	li	r7,0
+	li	r8,0
+	blt	1f
+	divwu	r7,r5,r4	# if dividend.hi >= divisor,
+	mullw	r0,r7,r4	# quotient.hi = dividend.hi / divisor
+	subf.	r5,r0,r5	# dividend.hi %= divisor
+	beq	3f
+1:	mr	r11,r5		# here dividend.hi != 0
+	andis.	r0,r5,0xc000
+	bne	2f
+	cntlzw	r0,r5		# we are shifting the dividend right
+	li	r10,-1		# to make it < 2^32, and shifting
+	srw	r10,r10,r0	# the divisor right the same amount,
+	add	r9,r4,r10	# rounding up (so the estimate cannot
+	andc	r11,r6,r10	# ever be too large, only too small)
+	andc	r9,r9,r10
+	or	r11,r5,r11
+	rotlw	r9,r9,r0
+	rotlw	r11,r11,r0
+	divwu	r11,r11,r9	# then we divide the shifted quantities
+2:	mullw	r10,r11,r4	# to get an estimate of the quotient,
+	mulhwu	r9,r11,r4	# multiply the estimate by the divisor,
+	subfc	r6,r10,r6	# take the product from the divisor,
+	add	r8,r8,r11	# and add the estimate to the accumulated
+	subfe.	r5,r9,r5	# quotient
+	bne	1b
+3:	cmplw	r6,r4
+	blt	4f
+	divwu	r0,r6,r4	# perform the remaining 32-bit division
+	mullw	r10,r0,r4	# and get the remainder
+	add	r8,r8,r0
+	subf	r6,r10,r6
+4:	stw	r7,0(r3)	# return the quotient in *r3
+	stw	r8,4(r3)
+	mr	r3,r6		# return the remainder in r3
+	blr
diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
--- a/arch/ppc/platforms/Makefile	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/platforms/Makefile	Fri Oct 18 21:03:08 2002
@@ -37,6 +37,7 @@
 obj-$(CONFIG_MCPN765)		+= mcpn765_setup.o mcpn765_pci.o
 obj-$(CONFIG_MENF1)		+= menf1_setup.o menf1_pci.o
 obj-$(CONFIG_MVME5100)		+= mvme5100_setup.o mvme5100_pci.o
+obj-$(CONFIG_PAL4)		+= pal4_setup.o pal4_pci.o cpc700_pic.o
 obj-$(CONFIG_PCORE)		+= pcore_setup.o pcore_pci.o
 obj-$(CONFIG_POWERPMC250)	+= powerpmc250.o
 obj-$(CONFIG_PPLUS)		+= pplus_pci.o pplus_setup.o
diff -Nru a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/platforms/pal4.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,44 @@
+/*
+ * arch/ppc/platforms/pal4.h
+ * 
+ * Definitions for SBS Palomar IV board
+ *
+ * Author: Dan Cox
+ *
+ * Copyright 2002 MontaVista Software 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 the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PPC_PLATFORMS_PAL4_H
+#define __PPC_PLATFORMS_PAL4_H
+
+#define PAL4_NVRAM             0xfffc0000
+#define PAL4_NVRAM_SIZE        0x8000
+
+#define PAL4_DRAM              0xfff80000
+#define  PAL4_DRAM_BR_MASK     0xc0
+#define  PAL4_DRAM_BR_SHIFT    6
+#define  PAL4_DRAM_RESET       0x10
+#define  PAL4_DRAM_EREADY      0x40
+
+#define PAL4_MISC              0xfff80004
+#define  PAL4_MISC_FB_MASK     0xc0
+#define  PAL4_MISC_FLASH       0x20  /* StratFlash mapping: 1->0xff80, 0->0xfff0 */
+#define  PAL4_MISC_MISC        0x08
+#define  PAL4_MISC_BITF        0x02
+#define  PAL4_MISC_NVKS        0x01
+
+#define PAL4_L2                0xfff80008
+#define  PAL4_L2_MASK          0x07
+
+#define PAL4_PLDR              0xfff8000c
+
+/* Only two Ethernet devices on the board... */
+#define PAL4_ETH               31
+#define PAL4_INTA              20
+
+#endif /* __PPC_PLATFORMS_PAL4_H */
diff -Nru a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/platforms/pal4_pci.c	Fri Oct 18 21:03:09 2002
@@ -0,0 +1,78 @@
+/*
+ * arch/ppc/platforms/pal4_pci.c
+ * 
+ * PCI support for SBS Palomar IV
+ *
+ * Author: Dan Cox 
+ *
+ * Copyright 2002 MontaVista Software 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 the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/uaccess.h>
+
+#include "cpc700.h"
+#include "pal4.h"
+
+/* not much to this.... */
+static inline int __init
+pal4_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	if (idsel == 9)
+		return PAL4_ETH;
+	else
+		return PAL4_INTA + (idsel - 3);
+}
+
+void __init
+pal4_find_bridges(void)
+{
+	struct pci_controller *hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = 0;
+
+	/* Could snatch these from the CPC700.... */
+	pci_init_resource(&hose->io_resource,
+			  0x0, 
+			  0x03ffffff,
+			  IORESOURCE_IO,
+			  "PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			  0x90000000,
+			  0x9fffffff,
+			  IORESOURCE_MEM,
+			  "PCI host bridge");
+
+	hose->io_space.start = 0x00800000;
+	hose->io_space.end = 0x03ffffff;
+	hose->mem_space.start = 0x90000000;
+	hose->mem_space.end = 0x9fffffff;
+	hose->io_base_virt = (void *) 0xf8000000;
+	
+	setup_indirect_pci(hose, CPC700_PCI_CONFIG_ADDR,
+			   CPC700_PCI_CONFIG_DATA);
+	
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = pal4_map_irq;
+}
diff -Nru a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/platforms/pal4_serial.h	Fri Oct 18 21:03:09 2002
@@ -0,0 +1,41 @@
+/*
+ * arch/ppc/platforms/pal4_serial.h
+ * 
+ * Definitions for SBS PalomarIV serial support 
+ *
+ * Author: Dan Cox
+ *
+ * Copyright 2002 MontaVista Software 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 the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PPC_PAL4_SERIAL_H
+#define __PPC_PAL4_SERIAL_H
+
+#define CPC700_SERIAL_1       0xff600300
+#define CPC700_SERIAL_2       0xff600400
+
+#define RS_TABLE_SIZE     2
+#define BASE_BAUD         (33333333 / 4 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define SERIAL_PORT_DFNS \
+      {0, BASE_BAUD, CPC700_SERIAL_1, 3, STD_COM_FLAGS, \
+       iomem_base: (unsigned char *) CPC700_SERIAL_1, \
+       io_type: SERIAL_IO_MEM},   /* ttyS0 */ \
+      {0, BASE_BAUD, CPC700_SERIAL_2, 4, STD_COM_FLAGS, \
+       iomem_base: (unsigned char *) CPC700_SERIAL_2, \
+       io_type: SERIAL_IO_MEM}
+
+#endif
diff -Nru a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/platforms/pal4_setup.c	Fri Oct 18 21:03:09 2002
@@ -0,0 +1,176 @@
+/*
+ * arch/ppc/platforms/pal4_setup.c
+ *
+ * Board setup routines for the SBS PalomarIV.
+ *
+ * Author: Dan Cox
+ *
+ * Copyright 2002 MontaVista Software 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 the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/irq.h>
+#include <linux/kdev_t.h>
+#include <linux/blk.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include "cpc700.h"
+#include "pal4.h"
+
+extern void pal4_find_bridges(void);
+
+unsigned int cpc700_irq_assigns[][2] = {
+        {1, 1},    /* IRQ 0: ECC correctable error */
+        {1, 1},    /* IRQ 1: PCI write to memory range */
+        {0, 1},    /* IRQ 2: PCI write to command register */
+        {0, 1},    /* IRQ 3: UART 0 */
+        {0, 1},    /* IRQ 4: UART 1 */
+        {0, 1},    /* IRQ 5: ICC 0 */
+        {0, 1},    /* IRQ 6: ICC 1 */
+        {0, 1},    /* IRQ 7: GPT compare 0 */
+        {0, 1},    /* IRQ 8: GPT compare 1 */
+        {0, 1},    /* IRQ 9: GPT compare 2 */
+        {0, 1},    /* IRQ 10: GPT compare 3 */
+        {0, 1},    /* IRQ 11: GPT compare 4 */
+        {0, 1},    /* IRQ 12: GPT capture 0 */
+        {0, 1},    /* IRQ 13: GPT capture 1 */
+        {0, 1},    /* IRQ 14: GPT capture 2 */
+        {0, 1},    /* IRQ 15: GPT capture 3 */
+        {0, 1},    /* IRQ 16: GPT capture 4 */
+        {0, 0},    /* IRQ 17: reserved */
+        {0, 0},    /* IRQ 18: reserved */
+        {0, 0},    /* IRQ 19: reserved */
+        {0, 0},    /* IRQ 20: reserved */
+        {0, 1},    /* IRQ 21: Ethernet */
+        {0, 0},    /* IRQ 22: reserved */
+        {0, 0},    /* IRQ 23: reserved */
+        {0, 0},    /* IRQ 24: resreved */
+        {0, 0},    /* IRQ 25: reserved */
+        {0, 0},    /* IRQ 26: reserved */
+        {0, 0},    /* IRQ 27: reserved */
+        {0, 0},    /* IRQ 28: reserved */
+        {0, 0},    /* IRQ 29: reserved */
+        {0, 0},    /* IRQ 30: reserved */
+        {0, 0},    /* IRQ 31: reserved */
+};
+
+static int
+pal4_show_cpuinfo(struct seq_file *m)
+{
+        seq_printf(m, "board\t\t: SBS Palomar IV\n");
+
+        return 0;
+}
+
+static void
+pal4_restart(char *cmd)
+{
+        __cli();
+        __asm__ __volatile__("lis  3,0xfff0\n \
+                              ori  3,3,0x100\n \
+                              mtspr 26,3\n \
+                              li   3,0\n \
+                              mtspr 27,3\n \
+                              rfi");
+
+        for(;;);
+}
+
+static void
+pal4_power_off(void)
+{
+	__cli();
+	for(;;);
+}
+
+static void
+pal4_halt(void)
+{
+	pal4_power_off();
+}
+
+TODC_ALLOC();
+
+static void __init
+pal4_setup_arch(void)
+{
+	unsigned long l2;
+
+	TODC_INIT(TODC_TYPE_MK48T37, 0, 0, 
+		  ioremap(PAL4_NVRAM, PAL4_NVRAM_SIZE), 8);
+
+	pal4_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+		ROOT_DEV = Root_NFS;
+
+	/* The L2 gets disabled in the bootloader, but all the proper
+	   bits should be present from the fw, so just re-enable it */
+	l2 = _get_L2CR();
+	if (!(l2 & L2CR_L2E)) {
+		/* presume that it was initially set if the size is
+		   still present. */
+		if (l2 ^ L2CR_L2SIZ_MASK)
+			_set_L2CR(l2 | L2CR_L2E);
+		else
+			printk("L2 not set by firmware; left disabled.\n");
+	}
+}
+
+static void __init
+pal4_map_io(void)
+{
+	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	isa_io_base = 0 /*PAL4_ISA_IO_BASE*/;
+	pci_dram_offset = 0 /*PAL4_PCI_SYS_MEM_BASE*/;
+	
+	ppc_md.setup_arch = pal4_setup_arch;
+	ppc_md.show_cpuinfo = pal4_show_cpuinfo;
+	
+	ppc_md.setup_io_mappings = pal4_map_io;
+
+	ppc_md.init_IRQ = cpc700_init_IRQ;
+	ppc_md.get_irq = cpc700_get_irq;
+
+	ppc_md.restart = pal4_restart;
+	ppc_md.halt = pal4_halt;
+	ppc_md.power_off = pal4_power_off;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+}
+
diff -Nru a/arch/ppc/platforms/pcore_setup.c b/arch/ppc/platforms/pcore_setup.c
--- a/arch/ppc/platforms/pcore_setup.c	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc/platforms/pcore_setup.c	Fri Oct 18 21:03:03 2002
@@ -168,13 +168,7 @@
 	for ( i = 0 ; i < 16 ; i++ )
 		irq_desc[i].handler = &i8259_pic;
 
-	i8259_init(NULL);
-}
-
-static int
-pcore_get_irq(struct pt_regs *regs)
-{
-	return i8259_poll();
+	i8259_init(0);
 }
 
 /*
@@ -184,22 +178,16 @@
 pcore_set_bat(void)
 {
 	unsigned long   bat3u, bat3l;
-	static int	mapping_set = 0;
 
-	if (!mapping_set) {
-		__asm__ __volatile__(
-				" lis %0,0xf000\n \
-				ori %1,%0,0x002a\n \
-				ori %0,%0,0x1ffe\n \
-				mtspr 0x21e,%0\n \
-				mtspr 0x21f,%1\n \
-				isync\n \
-				sync "
-				: "=r" (bat3u), "=r" (bat3l));
-
-		mapping_set = 1;
-	}
-	return;
+	__asm__ __volatile__(
+			" lis %0,0xf000\n \
+			ori %1,%0,0x002a\n \
+			ori %0,%0,0x1ffe\n \
+			mtspr 0x21e,%0\n \
+			mtspr 0x21f,%1\n \
+			isync\n \
+			sync "
+			: "=r" (bat3u), "=r" (bat3l));
 }
 
 static unsigned long __init
@@ -233,7 +221,7 @@
 	ppc_md.setup_arch	= pcore_setup_arch;
 	ppc_md.show_cpuinfo	= pcore_show_cpuinfo;
 	ppc_md.init_IRQ		= pcore_init_IRQ;
-	ppc_md.get_irq		= pcore_get_irq;
+	ppc_md.get_irq		= i8259_irq;
 
 	ppc_md.find_end_of_memory = pcore_find_end_of_memory;
 	ppc_md.setup_io_mappings = pcore_map_io;
diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S
--- a/arch/ppc/vmlinux.lds.S	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc/vmlinux.lds.S	Fri Oct 18 21:03:08 2002
@@ -87,9 +87,9 @@
 
   . = ALIGN(4096);
   __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { 
-    *(.data.init);
+  .init.text : { *(.init.text) }
+  .init.data : { 
+    *(.init.data);
     __vtop_table_begin = .;
     *(.vtop_fixup);
     __vtop_table_end = .;
@@ -99,7 +99,7 @@
   }
   . = ALIGN(16);
   __setup_start = .;
-  .setup.init : { *(.setup.init) }
+  .init.setup : { *(.init.setup) }
   __setup_end = .;
   __initcall_start = .;
   .initcall.init : {
@@ -121,29 +121,29 @@
 
   . = ALIGN(4096);
   __pmac_begin = .;
-  .text.pmac : { *(.text.pmac) }
-  .data.pmac : { *(.data.pmac) }
+  .pmac.text : { *(.pmac.text) }
+  .pmac.data : { *(.pmac.data) }
   . = ALIGN(4096);
   __pmac_end = .;
 
   . = ALIGN(4096);
   __prep_begin = .;
-  .text.prep : { *(.text.prep) }
-  .data.prep : { *(.data.prep) }
+  .prep.text : { *(.prep.text) }
+  .prep.data : { *(.prep.data) }
   . = ALIGN(4096);
   __prep_end = .;
 
   . = ALIGN(4096);
   __chrp_begin = .;
-  .text.chrp : { *(.text.chrp) }
-  .data.chrp : { *(.data.chrp) }
+  .chrp.text : { *(.chrp.text) }
+  .chrp.data : { *(.chrp.data) }
   . = ALIGN(4096);
   __chrp_end = .;
 
   . = ALIGN(4096);
   __openfirmware_begin = .;
-  .text.openfirmware : { *(.text.openfirmware) }
-  .data.openfirmware : { *(.data.openfirmware) }
+  .openfirmware.text : { *(.openfirmware.text) }
+  .openfirmware.data : { *(.openfirmware.data) }
   . = ALIGN(4096);
   __openfirmware_end = .;
 
diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile
--- a/arch/ppc64/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/Makefile	Fri Oct 18 21:03:03 2002
@@ -29,10 +29,10 @@
 core-y			+= arch/ppc64/kernel/ arch/ppc64/mm/ arch/ppc64/lib/
 core-$(CONFIG_XMON)	+= arch/ppc64/xmon/
 
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+makeboot = $(call descend,arch/ppc64/boot,$(1))
 
 ifdef CONFIG_PPC_PSERIES
-BOOT_TARGETS = zImage znetboot.initrd zImage.initrd
+BOOT_TARGETS = zImage zImage.initrd
 endif
 
 ifdef CONFIG_PPC_ISERIES
@@ -40,22 +40,14 @@
 endif
 
 $(BOOT_TARGETS): vmlinux
-	@$(MAKEBOOT) $@
-
-znetboot: vmlinux
-ifdef CONFIG_SMP
-	cp -f vmlinux /tftpboot/vmlinux.smp
-else
-	cp -f vmlinux /tftpboot/vmlinux
-endif
-	@$(MAKEBOOT) $@
+	@$(call makeboot,arch/ppc64/boot/$@)
 
 %_config: arch/ppc64/configs/%_defconfig
 	rm -f .config arch/ppc64/defconfig
 	cp -f arch/ppc64/configs/$(@:config=defconfig) arch/ppc64/defconfig
 
 archclean:
-	@$(MAKEBOOT) clean
+	@$(call makeboot,clean)
 
 archmrproper:
 
@@ -74,3 +66,4 @@
 
 CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \
 	       include/asm-$(ARCH)/offsets.h
+
diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
--- a/arch/ppc64/boot/Makefile	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc64/boot/Makefile	Fri Oct 18 21:03:08 2002
@@ -38,85 +38,64 @@
 LD_ARGS = -Ttext 0x00400000 -e _start
 OBJCOPYFLAGS := -S -O binary
 
-OBJS = crt0.o start.o main.o zlib.o image.o imagesize.o
-#LIBS = $(TOPDIR)/lib/lib.a
-LIBS =
-
-ifeq ($(CONFIG_SMP),y)
-TFTPIMAGE=/tftpboot/zImage.chrp.smp
-else
-TFTPIMAGE=/tftpboot/zImage.chrp
-endif
-
-
-ifeq ($(CONFIG_PPC_ISERIES),y)
-all:	vmlinux.sm
-else
-all:	$(TOPDIR)/zImage
-endif
-
-
-znetboot: zImage
-	cp zImage $(TFTPIMAGE)
-
+OBJS = $(addprefix $(obj)/,crt0.o start.o main.o zlib.o image.o imagesize.o)
 
 ifeq ($(CONFIG_PPC_ISERIES),y)
 
-addSystemMap: addSystemMap.c
-	$(HOSTCC) $(HOSTCFLAGS) -o addSystemMap addSystemMap.c
+boot:	vmlinux.sm
 
-vmlinux.sm: $(TOPDIR)/vmlinux addSystemMap
-	./addSystemMap $(TOPDIR)/System.map $(TOPDIR)/vmlinux vmlinux.sm
+$(obj)/addSystemMap: $(obj)/addSystemMap.c
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
+$(obj)/vmlinux.sm: vmlinux $(obj)/addSystemMap
+	$(obj)/addSystemMap System.map vmlinux $(obj)/vmlinux.sm
 
-addRamDisk: addRamDisk.c
-	$(HOSTCC) $(HOSTCFLAGS) -o addRamDisk addRamDisk.c
+$(obj)/addRamDisk: $(obj)/addRamDisk.c
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
-vmlinux.initrd: $(TOPDIR)/vmlinux addRamDisk ramdisk.image.gz $(TOPDIR)/System.map
-	./addRamDisk ramdisk.image.gz $(TOPDIR)/System.map $(TOPDIR)/vmlinux vmlinux.initrd
+$(obj)/vmlinux.initrd: vmlinux $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map
+	$(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map vmlinux $(obj)/vmlinux.initrd
 
-vmlinux.sminitrd: vmlinux.sm addRamDisk ramdisk.image.gz $(TOPDIR)/System.map
-	./addRamDisk ramdisk.image.gz $(TOPDIR)/System.map vmlinux.sm vmlinux.sminitrd
+$(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map
+	$(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map $(obj)/vmlinux.sm $(obj)/vmlinux.sminitrd
 
+else
+boot:	zImage
 endif
 
+$(obj)/piggyback: $(obj)/piggyback.c
+	$(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o $@ $<
 
-znetboot.initrd: zImage.initrd
-	cp zImage.initrd $(TFTPIMAGE)
+$(obj)/addnote: $(obj)/addnote.c
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
-floppy: zImage
-	mcopy zImage a:zImage
+$(obj)/image.o: $(obj)/piggyback $(obj)/vmlinux.gz
+	$(obj)/piggyback $(obj)/image < $(obj)/vmlinux.gz | $(BOOTAS) -o $@
 
-piggyback: piggyback.c
-	$(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c
+$(obj)/sysmap.o: $(obj)/piggyback System.map
+	$(obj)/piggyback $(obj)/sysmap < System.map | $(BOOTAS) -o $(obj)/sysmap.o
 
-addnote: addnote.c
-	$(HOSTCC) $(HOSTCFLAGS) -o addnote addnote.c
+$(obj)/initrd.o: $(obj)/ramdisk.image.gz $(obj)/piggyback
+	$(obj)/piggyback $(obj)/initrd < $(obj)/ramdisk.image.gz | $(BOOTAS) -o $(obj)/initrd.o
 
-image.o: piggyback vmlinux.gz
-	./piggyback image < vmlinux.gz | $(BOOTAS) -o image.o
-
-sysmap.o: piggyback ../../../System.map
-	./piggyback sysmap < ../../../System.map | $(BOOTAS) -o sysmap.o
-
-initrd.o: ramdisk.image.gz piggyback
-	./piggyback initrd < ramdisk.image.gz | $(BOOTAS) -o initrd.o
-
-zImage: $(OBJS) no_initrd.o addnote
-	$(BOOTLD) $(LD_ARGS) -T zImage.lds -o $@ $(OBJS) no_initrd.o $(LIBS)
-	./addnote $@
+$(obj)/zImage: $(OBJS) $(obj)/no_initrd.o $(obj)/addnote
+	$(BOOTLD) $(LD_ARGS) -T $(obj)/zImage.lds -o $@ $(OBJS) $(obj)/no_initrd.o
+	$(obj)/addnote $@
 
-zImage.initrd: $(OBJS) initrd.o addnote
-	$(BOOTLD) $(LD_ARGS) -T zImage.lds -o $@ $(OBJS) initrd.o $(LIBS)
+$(obj)/zImage.initrd: $(OBJS) $(obj)/initrd.o $(obj)/addnote
+	$(BOOTLD) $(LD_ARGS) -T $(obj)/zImage.lds -o $@ $(OBJS) $(obj)/initrd.o
 	./addnote $@
 
-vmlinux.gz: $(TOPDIR)/vmlinux
-	$(OBJCOPY) $(OBJCOPYFLAGS) $(TOPDIR)/vmlinux vmlinux
-	ls -l vmlinux | awk '{printf "/* generated -- do not edit! */\nint uncompressed_size = %d;\n", $$5}' > imagesize.c
-	$(CROSS_COMPILE)nm -n $(TOPDIR)/vmlinux | tail -1 | awk '{printf "long vmlinux_end = 0x%s;\n", substr($$1,8)}' >> imagesize.c
-	gzip -vf9 vmlinux
+$(obj)/vmlinux.gz: vmlinux
+	$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux $(obj)/vmlinux
+	ls -l $(obj)/vmlinux | awk '{printf "/* generated -- do not edit! */\nint uncompressed_size = %d;\n", $$5}' > $(obj)/imagesize.c
+	$(CROSS_COMPILE)nm -n vmlinux | tail -1 | awk '{printf "long vmlinux_end = 0x%s;\n", substr($$1,8)}' >> $(obj)/imagesize.c
+	gzip -vf9 $(obj)/vmlinux
 
-imagesize.c: vmlinux.gz
+$(obj)/imagesize.c: $(obj)/vmlinux.gz
 
 clean:
-	rm -f piggyback note addnote $(OBJS) zImage zImage.initrd vmlinux.gz no_initrd.o imagesize.c addSystemMap vmlinux.sm addRamDisk vmlinux.initrd vmlinux.sminitrd 
+	@rm -f $(OBJS)
+	@rm -f $(addprefix $(obj)/,piggyback note addnote zImage \
+		zImage.initrd vmlinux.gz no_initrd.o imagesize.c addSystemMap \
+		vmlinux.sm addRamDisk vmlinux.initrd vmlinux.sminitrd)
diff -Nru a/arch/ppc64/boot/piggyback.c b/arch/ppc64/boot/piggyback.c
--- a/arch/ppc64/boot/piggyback.c	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc64/boot/piggyback.c	Fri Oct 18 21:03:04 2002
@@ -8,6 +8,7 @@
  */
 #include <stdio.h>
 #include <unistd.h>
+#include <string.h>
 
 extern long ce_exec_config[];
 
@@ -17,20 +18,28 @@
 	unsigned int cksum, val;
 	unsigned char *lp;
 	unsigned char buf[8192];
+	char *varname;
 	if (argc != 2)
 	{
 		fprintf(stderr, "usage: %s name <in-file >out-file\n",
 			argv[0]);
 		exit(1);
 	}
+
+	varname = strrchr(argv[1], '/');
+	if (varname)
+		varname++;
+	else
+		varname = argv[1];
+
 	fprintf(stdout, "#\n");
 	fprintf(stdout, "# Miscellaneous data structures:\n");
 	fprintf(stdout, "# WARNING - this file is automatically generated!\n");
 	fprintf(stdout, "#\n");
 	fprintf(stdout, "\n");
 	fprintf(stdout, "\t.data\n");
-	fprintf(stdout, "\t.globl %s_data\n", argv[1]);
-	fprintf(stdout, "%s_data:\n", argv[1]);
+	fprintf(stdout, "\t.globl %s_data\n", varname);
+	fprintf(stdout, "%s_data:\n", varname);
 	pos = 0;
 	cksum = 0;
 	while ((len = read(0, buf, sizeof(buf))) > 0)
@@ -64,8 +73,8 @@
 		}
 		pos += len;
 	}
-	fprintf(stdout, "\t.globl %s_len\n", argv[1]);
-	fprintf(stdout, "%s_len:\t.long\t0x%x\n", argv[1], pos);
+	fprintf(stdout, "\t.globl %s_len\n", varname);
+	fprintf(stdout, "%s_len:\t.long\t0x%x\n", varname, pos);
 	fflush(stdout);
 	fclose(stdout);
 	fprintf(stderr, "cksum = %x\n", cksum);
diff -Nru a/arch/ppc64/config.in b/arch/ppc64/config.in
--- a/arch/ppc64/config.in	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/config.in	Fri Oct 18 21:03:03 2002
@@ -7,6 +7,7 @@
 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 define_bool CONFIG_GENERIC_ISA_DMA y
 define_bool CONFIG_HAVE_DEC_LOCK y
+define_bool CONFIG_EARLY_PRINTK y
 
 source init/Config.in
 
@@ -21,7 +22,7 @@
 bool 'Symmetric multi-processing support' CONFIG_SMP
 if [ "$CONFIG_SMP" = "y" ]; then
   bool '  Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
-  int  'Maximum number of CPUs (2-64)' CONFIG_NR_CPUS 64
+  int  'Maximum number of CPUs (2-64)' CONFIG_NR_CPUS 32
   if [ "$CONFIG_PPC_PSERIES" = "y" ]; then
     bool '  Hardware multithreading' CONFIG_HMT
     bool '  Discontiguous Memory Support' CONFIG_DISCONTIGMEM
diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig
--- a/arch/ppc64/defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc64/defconfig	Fri Oct 18 21:03:04 2002
@@ -6,6 +6,7 @@
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_HAVE_DEC_LOCK=y
+CONFIG_EARLY_PRINTK=y
 
 #
 # Code maturity level options
@@ -36,11 +37,11 @@
 CONFIG_PPC64=y
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
+CONFIG_NR_CPUS=32
 # CONFIG_HMT is not set
 # CONFIG_DISCONTIGMEM is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_RTAS_FLASH is not set
-CONFIG_NR_CPUS=64
 
 #
 # General setup
@@ -132,6 +133,7 @@
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_DPT_I2O is not set
@@ -170,6 +172,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
@@ -228,6 +231,12 @@
 # CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
 CONFIG_IPV6=m
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=m
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_LLC is not set
@@ -287,6 +296,11 @@
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_PCI=y
@@ -312,6 +326,7 @@
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
@@ -356,11 +371,6 @@
 # CONFIG_WAN is not set
 
 #
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-
-#
 # Amateur Radio support
 #
 # CONFIG_HAMRADIO is not set
@@ -412,9 +422,6 @@
 # CONFIG_GAMEPORT_CS461x is not set
 CONFIG_SERIO=y
 CONFIG_SERIO_I8042=y
-CONFIG_I8042_REG_BASE=60
-CONFIG_I8042_KBD_IRQ=1
-CONFIG_I8042_AUX_IRQ=12
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PARKBD is not set
@@ -520,6 +527,7 @@
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
+# CONFIG_SCx200_GPIO is not set
 CONFIG_RAW_DRIVER=y
 
 #
@@ -582,6 +590,9 @@
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
 
 #
 # Network File Systems
@@ -590,16 +601,18 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
-CONFIG_SMB_FS=y
-# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=y
+# CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
@@ -609,6 +622,8 @@
 # CONFIG_NCPFS_SMALLDOS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
+CONFIG_AFS_FS=y
+CONFIG_RXRPC=y
 # CONFIG_ZISOFS_FS is not set
 
 #
@@ -616,7 +631,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
+# CONFIG_SMB_NLS is not set
 CONFIG_NLS=y
 
 #
@@ -673,7 +688,7 @@
 # CONFIG_FB_CLGEN is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
+# CONFIG_FB_OF is not set
 # CONFIG_FB_CONTROL is not set
 # CONFIG_FB_PLATINUM is not set
 # CONFIG_FB_VALKYRIE is not set
@@ -703,7 +718,6 @@
 CONFIG_FBCON_CFB16=y
 CONFIG_FBCON_CFB24=y
 CONFIG_FBCON_CFB32=y
-CONFIG_FBCON_ACCEL=y
 CONFIG_FBCON_FONTWIDTH8_ONLY=y
 CONFIG_FBCON_FONTS=y
 CONFIG_FONT_8x8=y
@@ -711,6 +725,7 @@
 # CONFIG_FONT_SUN8x16 is not set
 # CONFIG_FONT_PEARL_8x8 is not set
 # CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
 
 #
 # Sound
@@ -725,7 +740,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c
--- a/arch/ppc64/kernel/chrp_setup.c	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/kernel/chrp_setup.c	Fri Oct 18 21:03:03 2002
@@ -158,7 +158,6 @@
 		for (openpic = 0; n > 0; --n)
 			openpic = (openpic << 32) + *opprop++;
 		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
-		udbg_printf("OpenPIC addr: %lx\n", openpic);
 		OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
 	}
 
@@ -175,7 +174,9 @@
 	 * -- tibit
 	 */
 	chrp_request_regions();
-	ppc_md.progress(UTS_RELEASE, 0x7777);
+	/* Manually leave the kernel version on the panel. */
+	ppc_md.progress("Linux ppc64\n", 0);
+	ppc_md.progress(UTS_RELEASE, 0);
 }
 
 /* Initialize firmware assisted non-maskable interrupts if
@@ -268,7 +269,6 @@
 
 	ppc_md.progress = chrp_progress;
 
-	ppc_md.progress("Linux ppc64\n", 0x0);
 }
 
 void
@@ -280,10 +280,7 @@
 	static int display_character, set_indicator;
 	static int max_width;
 
-	if (hex)
-		udbg_printf("<chrp_progress> %s\n", s);
-
-	if (!rtas.base || (naca->platform != PLATFORM_PSERIES))
+	if (!rtas.base)
 		return;
 
 	if (max_width == 0) {
diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
--- a/arch/ppc64/kernel/eeh.c	Fri Oct 18 21:03:06 2002
+++ b/arch/ppc64/kernel/eeh.c	Fri Oct 18 21:03:06 2002
@@ -156,8 +156,9 @@
 	ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
 	ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
 	ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
-	if (ibm_set_eeh_option != RTAS_UNKNOWN_SERVICE)
-		eeh_implemented = 1;
+
+	if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
+		return;
 
 	if (eeh_force_off > eeh_force_on) {
 		/* User is forcing EEH off.  Be noisy if it is implemented. */
diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
--- a/arch/ppc64/kernel/entry.S	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/kernel/entry.S	Fri Oct 18 21:03:03 2002
@@ -124,7 +124,7 @@
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 	blrl			/* Call handler */
 _GLOBAL(ret_from_syscall_1)
-20:	std	r3,RESULT(r1)	/* Save result */
+	std	r3,RESULT(r1)	/* Save result */
 #ifdef SHOW_SYSCALLS
 #ifdef SHOW_SYSCALLS_TASK
 	ld	r10, PACACURRENT(13)
@@ -195,7 +195,7 @@
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 	blrl			/* Call handler */
 _GLOBAL(ret_from_syscall_2)
-58:	std	r3,RESULT(r1)	/* Save result */	
+	std	r3,RESULT(r1)	/* Save result */	
 	std	r3,GPR0(r1)	/* temporary gross hack to make strace work */
 	li	r10,-_LAST_ERRNO
 	cmpl	0,r3,r10
@@ -240,9 +240,9 @@
 	bne-	81f
 	cmpi	0,r3,0
 	bge	.ret_from_except
-	b	20b
+	b	.ret_from_syscall_1
 81:	cmpi	0,r3,0
-	blt	58b
+	blt	.ret_from_syscall_2
 	bl	.do_syscall_trace
 	b	.ret_from_except
 
diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
--- a/arch/ppc64/kernel/ioctl32.c	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc64/kernel/ioctl32.c	Fri Oct 18 21:03:08 2002
@@ -754,8 +754,6 @@
 	s32			rtmsg_ifindex;
 };
 
-extern struct socket *sockfd_lookup(int fd, int *err);
-
 static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	int ret;
@@ -804,6 +802,9 @@
 	ret = sys_ioctl (fd, cmd, (long) r);
 	set_fs (old_fs);
 
+	if (mysock)
+		sockfd_put(mysock);
+
 	return ret;
 }
 
@@ -3725,6 +3726,39 @@
 	return ((0 == ret) ? 0 : -EFAULT);
 }	
 
+/* Fix sizeof(sizeof()) breakage */
+#define BLKELVGET_32	_IOR(0x12,106,int)
+#define BLKELVSET_32	_IOW(0x12,107,int)
+#define BLKBSZGET_32	_IOR(0x12,112,int)
+#define BLKBSZSET_32	_IOW(0x12,113,int)
+#define BLKGETSIZE64_32	_IOR(0x12,114,int)
+
+static int do_blkelvget(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return sys_ioctl(fd, BLKELVGET, arg);
+}
+
+static int do_blkelvset(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return sys_ioctl(fd, BLKELVSET, arg);
+}
+
+static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return sys_ioctl(fd, BLKBSZGET, arg);
+}
+
+static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return sys_ioctl(fd, BLKBSZSET, arg);
+}
+
+static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
+			   unsigned long arg)
+{
+	return sys_ioctl(fd, BLKGETSIZE64, arg);
+}
+
 struct ioctl_trans {
 	unsigned long cmd;
 	unsigned long handler;
@@ -3843,10 +3877,6 @@
 COMPATIBLE_IOCTL(BLKFLSBUF),
 COMPATIBLE_IOCTL(BLKSECTSET),
 COMPATIBLE_IOCTL(BLKSSZGET),
-COMPATIBLE_IOCTL(BLKBSZGET),
-COMPATIBLE_IOCTL(BLKBSZSET),
-COMPATIBLE_IOCTL(BLKGETSIZE64),
-
 /* RAID */
 COMPATIBLE_IOCTL(RAID_VERSION),
 COMPATIBLE_IOCTL(GET_ARRAY_INFO),
@@ -4316,9 +4346,6 @@
 COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK),
 COMPATIBLE_IOCTL(DRM_IOCTL_FINISH),
 #endif /* DRM */
-/* elevator */
-COMPATIBLE_IOCTL(BLKELVGET),
-COMPATIBLE_IOCTL(BLKELVSET),
 /* Big W */
 /* WIOC_GETSUPPORT not yet implemented -E */
 COMPATIBLE_IOCTL(WDIOC_GETSTATUS),
@@ -4541,6 +4568,14 @@
 HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb),
 HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb),
 HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal),
+/* take care of sizeof(sizeof()) breakage */
+/* elevator */
+HANDLE_IOCTL(BLKELVGET_32, do_blkelvget),
+HANDLE_IOCTL(BLKELVSET_32, do_blkelvset),
+/* block stuff */
+HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget),
+HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset),
+HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64),
 };
 
 unsigned long ioctl32_hash_table[1024];
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc64/kernel/misc.S	Fri Oct 18 21:03:04 2002
@@ -587,7 +587,7 @@
 	.llong .sys32_settimeofday
 	.llong .sys32_getgroups	        /* 80 */
 	.llong .sys32_setgroups
-	.llong .ppc32_select
+	.llong .sys_ni_syscall		/* old select syscall */
 	.llong .sys_symlink
 	.llong .sys_ni_syscall		/* old lstat syscall */
 	.llong .sys32_readlink	        /* 85 */
@@ -641,7 +641,7 @@
 	.llong .sys_fchdir
 	.llong .sys_bdflush
 	.llong .sys32_sysfs		/* 135 */
-	.llong .sys32_personality
+	.llong .ppc64_personality
 	.llong .sys_ni_syscall	        /* for afs_syscall */
 	.llong .sys_setfsuid
 	.llong .sys_setfsgid
@@ -705,7 +705,7 @@
 	.llong .sys_fstat64
 	.llong .sys32_pciconfig_read
 	.llong .sys32_pciconfig_write
-	.llong .sys_ni_syscall		/* 200 - reserved for sys_pciconfig_iobase */
+	.llong .sys_ni_syscall		/* 200 - old pciconfig_iobase */
 	.llong .sys_ni_syscall		/* reserved for MacOnLinux */
 	.llong .sys_getdents64
 	.llong .sys_pivot_root
@@ -830,7 +830,7 @@
 	.llong .sys_settimeofday
 	.llong .sys_getgroups		/* 80 */
 	.llong .sys_setgroups
-	.llong .sys_select
+	.llong .sys_ni_syscall		/* old select syscall */
 	.llong .sys_symlink
 	.llong .sys_ni_syscall		/* old lstat syscall */
 	.llong .sys_readlink		/* 85 */
@@ -857,7 +857,7 @@
 	.llong .sys_newstat
 	.llong .sys_newlstat
 	.llong .sys_newfstat
-	.llong .sys_uname
+	.llong .sys_ni_syscall		/* old uname syscall */
 	.llong .sys_ni_syscall		/* 110 old iopl syscall */
 	.llong .sys_vhangup
 	.llong .sys_ni_syscall		/* old idle syscall */
@@ -884,7 +884,7 @@
 	.llong .sys_fchdir
 	.llong .sys_bdflush
 	.llong .sys_sysfs		/* 135 */
-	.llong .sys_personality
+	.llong .ppc64_personality
 	.llong .sys_ni_syscall	        /* for afs_syscall */
 	.llong .sys_setfsuid
 	.llong .sys_setfsgid
@@ -948,7 +948,7 @@
 	.llong .sys_ni_syscall		/* 32bit only fstat64 */
 	.llong .sys_ni_syscall		/* 32bit only pciconfig_read */
 	.llong .sys_ni_syscall		/* 32bit only pciconfig_write */
-	.llong .sys_ni_syscall		/* 200 - reserved - sys_pciconfig_iobase */
+	.llong .sys_ni_syscall		/* 200 - old pciconfig_iobase */
 	.llong .sys_ni_syscall		/* reserved for MacOnLinux */
 	.llong .sys_getdents64
 	.llong .sys_pivot_root
diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c
--- a/arch/ppc64/kernel/open_pic.c	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc64/kernel/open_pic.c	Fri Oct 18 21:03:05 2002
@@ -289,7 +289,7 @@
 	}
 	OpenPIC = (volatile struct OpenPIC *)OpenPIC_Addr;
 
-	ppc_md.progress("openpic enter",0x122);
+	ppc64_boot_msg(0x20, "OpenPic Init");
 
 	t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
 	switch (t & OPENPIC_FEATURE_VERSION_MASK) {
@@ -326,7 +326,7 @@
 	find_ISUs();
 
 	/* Initialize timer interrupts */
-	ppc_md.progress("openpic timer",0x3ba);
+	ppc64_boot_msg(0x21, "OpenPic Timer");
 	for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
 		/* Disabled, Priority 0 */
 		openpic_inittimer(i, 0, openpic_vec_timer+i);
@@ -336,7 +336,7 @@
 
 #ifdef CONFIG_SMP
 	/* Initialize IPI interrupts */
-	ppc_md.progress("openpic ipi",0x3bb);
+	ppc64_boot_msg(0x22, "OpenPic IPI");
 	openpic_test_broken_IPI();
 	for (i = 0; i < OPENPIC_NUM_IPI; i++) {
 		/* Disabled, Priority 10..13 */
@@ -348,7 +348,7 @@
 #endif
 
 	/* Initialize external interrupts */
-	ppc_md.progress("openpic ext",0x3bc);
+	ppc64_boot_msg(0x23, "OpenPic Ext");
 
 	openpic_set_priority(0xf);
 
@@ -381,7 +381,7 @@
 		irq_desc[i].handler = &open_pic;
 
 	/* Initialize the spurious interrupt */
-	ppc_md.progress("openpic spurious",0x3bd);
+	ppc64_boot_msg(0x24, "OpenPic Spurious");
 	openpic_set_spurious(openpic_vec_spurious);
 
 	/* Initialize the cascade */
@@ -393,7 +393,7 @@
 	openpic_set_priority(0);
 	openpic_disable_8259_pass_through();
 
-	ppc_md.progress("openpic exit",0x222);
+	ppc64_boot_msg(0x25, "OpenPic Done");
 }
 
 void openpic_setup_ISU(int isu_num, unsigned long addr)
@@ -573,7 +573,7 @@
  * Get IPI's working and start taking interrupts.
  *   -- Cort
  */
-static spinlock_t openpic_setup_lock __initdata = SPIN_LOCK_UNLOCKED;
+static spinlock_t openpic_setup_lock __devinitdata = SPIN_LOCK_UNLOCKED;
 
 void __devinit do_openpic_setup_cpu(void)
 {
diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
--- a/arch/ppc64/kernel/pSeries_lpar.c	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc64/kernel/pSeries_lpar.c	Fri Oct 18 21:03:08 2002
@@ -310,6 +310,8 @@
  */
 void pSeriesLP_init_early(void)
 {
+	struct device_node *np;
+
 	pSeries_lpar_mm_init();
 
 	ppc_md.tce_build	 = tce_build_pSeriesLP;
@@ -324,29 +326,21 @@
 	 * Leave all the interfaces NULL.
 	 */
 
-	if (0 /*naca->serialPortAddr */) {
-		void *comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
-		udbg_init_uart(comport);
-		ppc_md.udbg_putc = udbg_putc;
-		ppc_md.udbg_getc = udbg_getc;
-		ppc_md.udbg_getc_poll = udbg_getc_poll;
-	} else {
-		/* lookup the first virtual terminal number in case we don't have a com port.
-		 * Zero is probably correct in case someone calls udbg before the init.
-		 * The property is a pair of numbers.  The first is the starting termno (the
-		 * one we use) and the second is the number of terminals.
-		 */
-		u32 *termno;
-		struct device_node *np = find_path_device("/rtas");
-		if (np) {
-			termno = (u32 *)get_property(np, "ibm,termno", 0);
-			if (termno)
-				vtermno = termno[0];
-		}
-		ppc_md.udbg_putc = udbg_putcLP;
-		ppc_md.udbg_getc = udbg_getcLP;
-		ppc_md.udbg_getc_poll = udbg_getc_pollLP;
+	/* lookup the first virtual terminal number in case we don't have a
+	 * com port. Zero is probably correct in case someone calls udbg
+	 * before the init. The property is a pair of numbers.  The first
+	 * is the starting termno (the one we use) and the second is the
+	 * number of terminals.
+	 */
+	np = find_path_device("/rtas");
+	if (np) {
+		u32 *termno = (u32 *)get_property(np, "ibm,termno", 0);
+		if (termno)
+			vtermno = termno[0];
 	}
+	ppc_md.udbg_putc = udbg_putcLP;
+	ppc_md.udbg_getc = udbg_getcLP;
+	ppc_md.udbg_getc_poll = udbg_getc_pollLP;
 }
 
 int hvc_get_chars(int index, char *buf, int count)
diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc64/kernel/pci.c	Fri Oct 18 21:03:08 2002
@@ -392,6 +392,7 @@
 	iSeries_pcibios_init(); 
 #endif
 
+	//ppc64_boot_msg(0x40, "PCI Probe");
 	printk("PCI: Probing PCI hardware\n");
 	PPCDBG(PPCDBG_BUSWALK,"PCI: Probing PCI hardware\n");
 
@@ -431,7 +432,9 @@
 
 	printk("PCI: Probing PCI hardware done\n");
 	PPCDBG(PPCDBG_BUSWALK,"PCI: Probing PCI hardware done.\n");
+	//ppc64_boot_msg(0x41, "PCI Done");
 
+	return 0;
 }
 
 subsys_initcall(pcibios_init);
@@ -729,36 +732,6 @@
 	return ret;
 }
 
-/* Provide information on locations of various I/O regions in physical
- * memory.  Do this on a per-card basis so that we choose the right
- * root bridge.
- * Note that the returned IO or memory base is a physical address
- */
-
-long
-sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
-{
-	struct pci_controller* hose = pci_bus_to_hose(bus);
-	long result = -EOPNOTSUPP;
-
-	if (!hose)
-		return -ENODEV;
-	
-	switch (which) {
-	case IOBASE_BRIDGE_NUMBER:
-		return (long)hose->first_busno;
-	case IOBASE_MEMORY:
-		return (long)hose->pci_mem_offset;
-	case IOBASE_IO:
-		return (long)hose->io_base_phys;
-	case IOBASE_ISA_IO:
-		return (long)isa_io_base;
-	case IOBASE_ISA_MEM:
-		return (long)isa_mem_base;
-	}
-
-	return result;
-}
 /************************************************************************/
 /* Formats the device information and location for service.             */
 /* - Pass in pci_dev* pointer to the device.                            */
diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
--- a/arch/ppc64/kernel/pci.h	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/kernel/pci.h	Fri Oct 18 21:03:03 2002
@@ -64,23 +64,6 @@
 void pSeries_pcibios_init_early(void);
 void pSeries_pcibios_init(void);
 
-/* Get a device_node from a pci_dev.  This code must be fast except in the case
- * where the sysdata is incorrect and needs to be fixed up (hopefully just once)
- */
-static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
-{
-	struct device_node *dn = (struct device_node *)(dev->sysdata);
-	if (dn->devfn == dev->devfn && dn->busno == dev->bus->number)
-		return dn;	/* fast path.  sysdata is good */
-	else
-		return fetch_dev_dn(dev);
-}
-/* Use this macro after the PCI bus walk for max performance when it
- * is known that sysdata is correct.
- */
-#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
-
-
 /*******************************************************************
  * Platform configuration flags.. (Live in pci.c)
  *******************************************************************/
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc64/kernel/process.c	Fri Oct 18 21:03:05 2002
@@ -43,6 +43,7 @@
 #include <asm/ppcdebug.h>
 #include <asm/machdep.h>
 #include <asm/iSeries/HvCallHpt.h>
+#include <asm/hardirq.h>
 
 struct task_struct *last_task_used_math = NULL;
 
@@ -455,6 +456,10 @@
 			return 0;
 		if (count > 0) {
 			ip = *(unsigned long *)(sp + 16);
+			/*
+			 * XXX we mask the upper 32 bits until procps
+			 * gets fixed.
+			 */
 			if (ip < first_sched || ip >= last_sched)
 				return (ip & 0xFFFFFFFF);
 		}
@@ -484,4 +489,9 @@
 		}
 	} while (count++ < 16);
 	printk("\n");
+}
+
+void dump_stack(void)
+{
+	show_stack(NULL);
 }
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc64/kernel/prom.c	Fri Oct 18 21:03:07 2002
@@ -620,6 +620,7 @@
 	return mem;
 }
 
+static char hypertas_funcs[1024];
 
 static void __init
 prom_instantiate_rtas(void)
@@ -636,7 +637,6 @@
 #endif
 	prom_rtas = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
 	if (prom_rtas != (ihandle) -1) {
-		char hypertas_funcs[1024];
 		int  rc; 
 		
 		if ((rc = call_prom(RELOC("getprop"), 
diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
--- a/arch/ppc64/kernel/ptrace.c	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc64/kernel/ptrace.c	Fri Oct 18 21:03:04 2002
@@ -210,50 +210,68 @@
 		break;
 
 	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
-		u64 tmp;
-		u64 cntr;
-
-		ret = 0; 
-		for (cntr=0; cntr<32 && ret==0; ++cntr) {
-			tmp = ((u64*)child->thread.regs)[cntr];
-			ret = put_user(tmp, (u64*)(data+cntr));
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned long *tmp = (unsigned long *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = put_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
 		}
 		break;
 	}
 
 	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
-		u64 cntr;
-
-		ret = 0; 
-		for (cntr=0; cntr<32 && ret==0; ++cntr)
-			ret = put_reg(child, cntr, *(u64*)(data+cntr));
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned long *tmp = (unsigned long *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = get_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
 		break;
 	}
 
 	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
-		u64 tmp;
-		u64 cntr;
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+		unsigned long *tmp = (unsigned long *)addr;
 
-		ret = -EIO;
 		if (child->thread.regs->msr & MSR_FP)
 			giveup_fpu(child);
-		ret = 0; 
-		for (cntr=0; cntr<32 && ret==0; ++cntr) {
-			tmp = ((u64*)child->thread.fpr)[cntr];
-			ret = put_user(tmp, (u64*)(data+cntr));
+
+		for (i = 0; i < 32; i++) {
+			ret = put_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
 		}
 		break;
 	}
 
 	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
-		u64 cntr;
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+		unsigned long *tmp = (unsigned long *)addr;
 
-		ret = -EIO;
 		if (child->thread.regs->msr & MSR_FP)
 			giveup_fpu(child);
-		for (cntr=0; cntr<32; ++cntr)
-			((u64*)child->thread.fpr)[cntr] = *(u64*)(data+cntr);
-		ret = 0; 
+
+		for (i = 0; i < 32; i++) {
+			ret = get_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
 		break;
 	}
 
diff -Nru a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
--- a/arch/ppc64/kernel/ptrace32.c	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc64/kernel/ptrace32.c	Fri Oct 18 21:03:05 2002
@@ -344,6 +344,74 @@
 		ret = ptrace_detach(child, data);
 		break;
 
+	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned int *tmp = (unsigned int *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = put_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned int *tmp = (unsigned int *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = get_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+		unsigned int *tmp = (unsigned int *)addr;
+
+		if (child->thread.regs->msr & MSR_FP)
+			giveup_fpu(child);
+
+		for (i = 0; i < 32; i++) {
+			ret = put_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+		unsigned int *tmp = (unsigned int *)addr;
+
+		if (child->thread.regs->msr & MSR_FP)
+			giveup_fpu(child);
+
+		for (i = 0; i < 32; i++) {
+			ret = get_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+
+
 	default:
 		ret = -EIO;
 		break;
diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
--- a/arch/ppc64/kernel/setup.c	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc64/kernel/setup.c	Fri Oct 18 21:03:04 2002
@@ -21,6 +21,8 @@
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/version.h>
 #include <linux/tty.h>
 #include <linux/root_dev.h>
 #include <asm/io.h>
@@ -116,6 +118,23 @@
 	_naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
 }
 
+static struct console udbg_console = {
+	name:	"udbg",
+	write:	udbg_console_write,
+	flags:	CON_PRINTBUFFER,
+	index:	-1,
+};
+
+static int early_console_initialized;
+
+void __init disable_early_printk(void)
+{
+	if (!early_console_initialized)
+		return;
+	unregister_console(&udbg_console);
+	early_console_initialized = 0;
+}
+
 /*
  * Do some initial setup of the system.  The paramters are those which 
  * were passed in from the bootloader.
@@ -162,62 +181,31 @@
 #endif
 	}
 
-	udbg_puts("\n-----------------------------------------------------\n");
-	udbg_puts("Naca Info...\n\n");
-	udbg_puts("naca                       = 0x");
-	udbg_puthex((unsigned long)naca);
-	udbg_putc('\n');
-
-	udbg_puts("naca->physicalMemorySize   = 0x");
-	udbg_puthex(naca->physicalMemorySize);
-	udbg_putc('\n');
-
-	udbg_puts("naca->dCacheL1LineSize     = 0x");
-	udbg_puthex(naca->dCacheL1LineSize);
-	udbg_putc('\n');
-
-	udbg_puts("naca->dCacheL1LogLineSize  = 0x");
-	udbg_puthex(naca->dCacheL1LogLineSize);
-	udbg_putc('\n');
-
-	udbg_puts("naca->dCacheL1LinesPerPage = 0x");
-	udbg_puthex(naca->dCacheL1LinesPerPage);
-	udbg_putc('\n');
-
-	udbg_puts("naca->iCacheL1LineSize     = 0x");
-	udbg_puthex(naca->iCacheL1LineSize);
-	udbg_putc('\n');
-
-	udbg_puts("naca->iCacheL1LogLineSize  = 0x");
-	udbg_puthex(naca->iCacheL1LogLineSize);
-	udbg_putc('\n');
-
-	udbg_puts("naca->iCacheL1LinesPerPage = 0x");
-	udbg_puthex(naca->iCacheL1LinesPerPage);
-	udbg_putc('\n');
-
-	udbg_puts("naca->pftSize              = 0x");
-	udbg_puthex(naca->pftSize);
-	udbg_putc('\n');
-
-	udbg_puts("naca->serialPortAddr       = 0x");
-	udbg_puthex(naca->serialPortAddr);
-	udbg_putc('\n');
-
-	udbg_puts("naca->interrupt_controller = 0x");
-	udbg_puthex(naca->interrupt_controller);
-	udbg_putc('\n');
-
-	udbg_printf("\nHTAB Info ...\n\n"); 
-	udbg_puts("htab_data.htab             = 0x");
-	udbg_puthex((unsigned long)htab_data.htab);
-	udbg_putc('\n');
-	udbg_puts("htab_data.num_ptegs        = 0x");
-	udbg_puthex(htab_data.htab_num_ptegs);
-	udbg_putc('\n');
+	if (naca->platform & PLATFORM_PSERIES) {
+		early_console_initialized = 1;
+		register_console(&udbg_console);
+	}
 
-	udbg_puts("\n-----------------------------------------------------\n");
+	printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
 
+	printk("-----------------------------------------------------\n");
+	printk("naca                       = 0x%p\n", naca);
+#if 0
+	printk("naca->processorCount       = 0x%x\n", naca->processorCount);
+#endif
+	printk("naca->physicalMemorySize   = 0x%lx\n", naca->physicalMemorySize);
+	printk("naca->dCacheL1LineSize     = 0x%x\n", naca->dCacheL1LineSize);
+	printk("naca->dCacheL1LogLineSize  = 0x%x\n", naca->dCacheL1LogLineSize);
+	printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage);
+	printk("naca->iCacheL1LineSize     = 0x%x\n", naca->iCacheL1LineSize);
+	printk("naca->iCacheL1LogLineSize  = 0x%x\n", naca->iCacheL1LogLineSize);
+	printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage);
+	printk("naca->pftSize              = 0x%lx\n", naca->pftSize);
+	printk("naca->debug_switch         = 0x%lx\n", naca->debug_switch);
+	printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller);
+	printk("htab_data.htab             = 0x%p\n", htab_data.htab);
+	printk("htab_data.num_ptegs        = 0x%lx\n", htab_data.htab_num_ptegs);
+	printk("-----------------------------------------------------\n");
 
 	if (naca->platform & PLATFORM_PSERIES) {
 		finish_device_tree();
@@ -411,7 +399,6 @@
 		}
 		__max_memory = maxmem;
 	}
-	ppc_md.progress("id mach: done", 0x200);
 }
 
 
@@ -492,7 +479,6 @@
 	printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
 			       loops_per_jiffy/(500000/HZ),
 			       loops_per_jiffy/(5000/HZ) % 100);
-
 }	
 
 extern void (*calibrate_delay)(void);
@@ -511,13 +497,13 @@
 
 	calibrate_delay = ppc64_calibrate_delay;
 
+	ppc64_boot_msg(0x12, "Setup Arch");
 #ifdef CONFIG_XMON
 	xmon_map_scc();
 	if (strstr(cmd_line, "xmon"))
 		xmon(0);
 #endif /* CONFIG_XMON */
 
-	ppc_md.progress("setup_arch:enter", 0x3eab);
 
 	/*
 	 * Set cache line size based on type of cpu as a default.
@@ -541,13 +527,59 @@
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
-	ppc_md.progress("setup_arch:bootmem", 0x3eab);
 
 	ppc_md.setup_arch();
 
 	paging_init();
 	sort_exception_table();
-	ppc_md.progress("setup_arch: exit", 0x3eab);
+	ppc64_boot_msg(0x15, "Setup Done");
+}
+
+/* ToDo: do something useful if ppc_md is not yet setup. */
+#define PPC64_LINUX_FUNCTION 0x0f000000
+#define PPC64_IPL_MESSAGE 0xc0000000
+#define PPC64_TERM_MESSAGE 0xb0000000
+#define PPC64_ATTN_MESSAGE 0xa0000000
+#define PPC64_DUMP_MESSAGE 0xd0000000
+
+static void ppc64_do_msg(unsigned int src, const char *msg)
+{
+	if (ppc_md.progress) {
+		char buf[32];
+
+		sprintf(buf, "%08x        \n", src);
+		ppc_md.progress(buf, 0);
+		sprintf(buf, "%-16s", msg);
+		ppc_md.progress(buf, 0);
+	}
+}
+
+/* Print a boot progress message. */
+void ppc64_boot_msg(unsigned int src, const char *msg)
+{
+	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
+	printk("[boot]%04x %s\n", src, msg);
+}
+
+/* Print a termination message (print only -- does not stop the kernel) */
+void ppc64_terminate_msg(unsigned int src, const char *msg)
+{
+	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
+	printk("[terminate]%04x %s\n", src, msg);
+}
+
+/* Print something that needs attention (device error, etc) */
+void ppc64_attention_msg(unsigned int src, const char *msg)
+{
+	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
+	printk("[attention]%04x %s\n", src, msg);
+}
+
+/* Print a dump progress message. */
+void ppc64_dump_msg(unsigned int src, const char *msg)
+{
+	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
+	printk("[dump]%04x %s\n", src, msg);
 }
 
 int set_spread_lpevents( char * str )
diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
--- a/arch/ppc64/kernel/signal.c	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/kernel/signal.c	Fri Oct 18 21:03:03 2002
@@ -108,13 +108,15 @@
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
-	regs->gpr[3] = -EINTR;
+	regs->result = -EINTR;
+	regs->gpr[3] = EINTR;
+	regs->ccr |= 0x10000000;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
@@ -144,13 +146,15 @@
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
-	regs->gpr[3] = -EINTR;
+	regs->result = -EINTR;
+	regs->gpr[3] = EINTR;
+	regs->ccr |= 0x10000000;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
@@ -213,7 +217,7 @@
 		     struct pt_regs *regs)
 {
 	struct rt_sigframe *rt_sf;
-	struct sigcontext_struct sigctx;
+	struct sigcontext sigctx;
 	struct sigregs *sr;
 	elf_gregset_t saved_regs;  /* an array of ELF_NGREG unsigned longs */
 	sigset_t set;
@@ -225,10 +229,10 @@
 	    || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st)))
 		goto badframe;
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
 
@@ -331,12 +335,12 @@
 		   unsigned long r6, unsigned long r7, unsigned long r8,
 		   struct pt_regs *regs)
 {
-	struct sigcontext_struct *sc, sigctx;
+	struct sigcontext *sc, sigctx;
 	struct sigregs *sr;
 	elf_gregset_t saved_regs;  /* an array of ELF_NGREG unsigned longs */
 	sigset_t set;
 
-	sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+	sc = (struct sigcontext *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
 	if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
 		goto badframe;
 
@@ -345,10 +349,10 @@
 	set.sig[1] = sigctx._unused[3];
 #endif
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
 
@@ -391,7 +395,7 @@
 	struct funct_descr_entry * funct_desc_ptr;
 	unsigned long temp_ptr;
 
-	struct sigcontext_struct *sc = (struct sigcontext_struct *)newsp;
+	struct sigcontext *sc = (struct sigcontext *)newsp;
   
 	if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto badframe;
@@ -440,7 +444,7 @@
 static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
 	struct pt_regs * regs, unsigned long *newspp, unsigned long frame)
 {
-	struct sigcontext_struct *sc;
+	struct sigcontext *sc;
 	struct rt_sigframe *rt_sf;
 	struct k_sigaction *ka = &current->sig->action[sig-1];
 
@@ -481,7 +485,7 @@
 	} else {
 		/* Put a sigcontext on the stack */
 		*newspp -= sizeof(*sc);
-		sc = (struct sigcontext_struct *)*newspp;
+		sc = (struct sigcontext *)*newspp;
 		if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
 			goto badframe;
 		
@@ -499,11 +503,11 @@
 		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
-		spin_lock_irq(&current->sigmask_lock);
+		spin_lock_irq(&current->sig->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
-		spin_unlock_irq(&current->sigmask_lock);
+		spin_unlock_irq(&current->sig->siglock);
 	}
 	return;
 
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc64/kernel/signal32.c	Fri Oct 18 21:03:08 2002
@@ -218,14 +218,14 @@
 		     unsigned long r6, unsigned long r7, unsigned long r8,
 		     struct pt_regs *regs)
 {
-	struct sigcontext32_struct *sc, sigctx;
+	struct sigcontext32 *sc, sigctx;
 	struct sigregs32 *sr;
 	int ret;
 	elf_gregset_t32 saved_regs;  /* an array of ELF_NGREG unsigned ints (32 bits) */
 	sigset_t set;
 	int i;
 
-	sc = (struct sigcontext32_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32);
+	sc = (struct sigcontext32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32);
 	if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
 		goto badframe;
 
@@ -235,10 +235,10 @@
 	 */
 	set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3]) << 32);
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	if (regs->msr & MSR_FP )
 		giveup_fpu(current);
 	/* Last stacked signal - restore registers */
@@ -315,8 +315,7 @@
 static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
             unsigned int newsp)
 {
-	struct sigcontext32_struct *sc =
-		(struct sigcontext32_struct *)(u64)newsp;
+	struct sigcontext32 *sc = (struct sigcontext32 *)(u64)newsp;
 	int i;
 
 	if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -430,7 +429,7 @@
 			struct pt_regs * regs)
 {
 	struct rt_sigframe_32 *rt_sf;
-	struct sigcontext32_struct sigctx;
+	struct sigcontext32 sigctx;
 	struct sigregs32 *sr;
 	int ret;
 	elf_gregset_t32 saved_regs;   /* an array of 32 bit register values */
@@ -455,10 +454,10 @@
 	 */
 	sigdelsetmask(&set, ~_BLOCKABLE); 
 	/* update the current based on the sigmask found in the rt_stackframe */
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	/* If currently owning the floating point - give them up */
 	if (regs->msr & MSR_FP)
@@ -842,17 +841,27 @@
 
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
-	regs->gpr[3] = -EINTR;
+	regs->result = -EINTR;
+	regs->gpr[3] = EINTR;
+	regs->ccr |= 0x10000000;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
 		if (do_signal(&saveset, regs))
+			/*
+			 * If a signal handler needs to be called,
+			 * do_signal() has set R3 to the signal number (the
+			 * first argument of the signal handler), so don't
+			 * overwrite that with EINTR !
+			 * In the other cases, do_signal() doesn't touch 
+			 * R3, so it's still set to -EINTR (see above).
+			 */
 			return regs->gpr[3];
 	}
 }
@@ -958,7 +967,7 @@
 		sigset_t *oldset, struct pt_regs * regs, unsigned int *newspp,
 		unsigned int frame)
 {
-	struct sigcontext32_struct *sc;
+	struct sigcontext32 *sc;
 	struct rt_sigframe_32 *rt_sf;
 	struct k_sigaction *ka = &current->sig->action[sig-1];
 
@@ -1000,7 +1009,7 @@
 	} else {
 		/* Put a sigcontext on the stack */
 		*newspp -= sizeof(*sc);
-		sc = (struct sigcontext32_struct *)(u64)*newspp;
+		sc = (struct sigcontext32 *)(u64)*newspp;
 		if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
 			goto badframe;
 		/*
@@ -1019,11 +1028,11 @@
 		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
-		spin_lock_irq(&current->sigmask_lock);
+		spin_lock_irq(&current->sig->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
-		spin_unlock_irq(&current->sigmask_lock);
+		spin_unlock_irq(&current->sig->siglock);
 	}
 	return;
 
diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
--- a/arch/ppc64/kernel/smp.c	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc64/kernel/smp.c	Fri Oct 18 21:03:07 2002
@@ -1,6 +1,4 @@
 /*
- * 
- *
  * SMP support for ppc.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
@@ -449,6 +447,9 @@
 	int wait;
 } *call_data;
 
+/* delay of at least 8 seconds on 1GHz cpu */
+#define SMP_CALL_TIMEOUT (1UL << (30 + 3))
+
 /*
  * This function sends a 'generic call function' IPI to all other CPUs
  * in the system.
@@ -469,7 +470,7 @@
 { 
 	struct call_data_struct data;
 	int ret = -1, cpus = num_online_cpus()-1;
-	int timeout;
+	unsigned long timeout;
 
 	if (!cpus)
 		return 0;
@@ -483,47 +484,44 @@
 
 	spin_lock(&call_lock);
 	call_data = &data;
+	wmb();
 	/* Send a message to all other CPUs and wait for them to respond */
 	smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION, 0, 0);
 
 	/* Wait for response */
-	timeout = 8000000;
+	timeout = SMP_CALL_TIMEOUT;
 	while (atomic_read(&data.started) != cpus) {
 		HMT_low();
 		if (--timeout == 0) {
-			printk("smp_call_function on cpu %d: other cpus not responding (%d)\n",
-			       smp_processor_id(), atomic_read(&data.started));
-#ifdef CONFIG_XMON
-                        xmon(0);
-#endif
-#ifdef CONFIG_PPC_ISERIES
-			HvCall_terminateMachineSrc();
-#endif
+			if (debugger)
+				debugger(0);
+			printk("smp_call_function on cpu %d: other cpus not "
+			       "responding (%d)\n", smp_processor_id(),
+			       atomic_read(&data.started));
 			goto out;
 		}
-		barrier();
-		udelay(1);
 	}
 
 	if (wait) {
-		timeout = 1000000;
+		timeout = SMP_CALL_TIMEOUT;
 		while (atomic_read(&data.finished) != cpus) {
 			HMT_low();
 			if (--timeout == 0) {
-				printk("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n",
-				       smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started));
-#ifdef CONFIG_PPC_ISERIES
-				HvCall_terminateMachineSrc();
-#endif
+				if (debugger)
+					debugger(0);
+				printk("smp_call_function on cpu %d: other "
+				       "cpus not finishing (%d/%d)\n",
+				       smp_processor_id(),
+				       atomic_read(&data.finished),
+				       atomic_read(&data.started));
 				goto out;
 			}
-			barrier();
-			udelay(1);
 		}
 	}
+
 	ret = 0;
 
- out:
+out:
 	HMT_medium();
 	spin_unlock(&call_lock);
 	return ret;
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc64/kernel/sys_ppc32.c	Fri Oct 18 21:03:07 2002
@@ -61,6 +61,7 @@
 #include <asm/semaphore.h>
 
 #include <net/scm.h>
+#include <net/sock.h>
 #include <linux/elf.h>
 #include <asm/ppcdebug.h>
 #include <asm/time.h>
@@ -332,12 +333,15 @@
 	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
 	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 
+	if (s32->version != SMB_MOUNT_OLDVERSION)
+		goto out;
 	s->version = s32->version;
 	s->mounted_uid = s32->mounted_uid;
 	s->uid = s32->uid;
 	s->gid = s32->gid;
 	s->file_mode = s32->file_mode;
 	s->dir_mode = s32->dir_mode;
+out:
 	return raw_data;
 }
 
@@ -2361,11 +2365,15 @@
 			set_fs(old_fs);
 		}
 		break;
+	default:
+		err = -EINVAL;
 	}
 out:
 	return err;
 }
 
+#define MAXBUF (64*1024)
+
 static int 
 do_sys32_msgsnd(int first, int second, int third, void *uptr)
 {
@@ -2374,14 +2382,14 @@
 	mm_segment_t old_fs;
 	int err;
 
-	if (second < 0)
+	if (second < 0 || (second >= MAXBUF-sizeof(struct msgbuf)))
 		return -EINVAL;
 
-	p = kmalloc(second + sizeof(struct msgbuf) + 4, GFP_USER);
+	p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
 	if (!p)
 		return -ENOMEM;
 	err = get_user(p->mtype, &up->mtype);
-	err |= __copy_from_user(p->mtext, &up->mtext, second);
+	err |= copy_from_user(p->mtext, &up->mtext, second);
 	if (err) {
 		err = -EFAULT;
 		goto out;
@@ -2404,35 +2412,35 @@
 	mm_segment_t old_fs;
 	int err;
 
-	if (second < 0)
+	if (second < 0 || (second >= MAXBUF-sizeof(struct msgbuf)))
 		return -EINVAL;
 
 	if (!version) {
-		struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
-		struct ipc_kludge ipck;
+		struct ipc_kludge_32 *uipck = (struct ipc_kludge_32 *)uptr;
+		struct ipc_kludge_32 ipck;
 
 		err = -EINVAL;
 		if (!uptr)
 			goto out;
 		err = -EFAULT;
-		if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
+		if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge_32)))
 			goto out;
 		uptr = (void *)A(ipck.msgp);
 		msgtyp = ipck.msgtyp;
 	}
 	err = -ENOMEM;
-	p = kmalloc(second + sizeof (struct msgbuf) + 4, GFP_USER);
+	p = kmalloc(second + sizeof (struct msgbuf), GFP_USER);
 	if (!p)
 		goto out;
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
-	err = sys_msgrcv(first, p, second + 4, msgtyp, third);
+	err = sys_msgrcv(first, p, second, msgtyp, third);
 	set_fs(old_fs);
 	if (err < 0)
 		goto free_then_out;
 	up = (struct msgbuf32 *)uptr;
 	if (put_user(p->mtype, &up->mtype) ||
-	    __copy_to_user(&up->mtext, p->mtext, err))
+	    copy_to_user(&up->mtext, p->mtext, err))
 		err = -EFAULT;
 free_then_out:
 	kfree(p);
@@ -2559,7 +2567,7 @@
 static int
 do_sys32_shmctl(int first, int second, void *uptr)
 {
-	int err = -EFAULT, err2;
+	int err = -EINVAL, err2;
 	mm_segment_t old_fs;
 
 	switch (second & (~IPC_64)) {
@@ -2891,13 +2899,6 @@
 			       __cmsg, __cmsg_len);
 }
 
-extern struct socket *sockfd_lookup(int fd, int *err);
-
-extern __inline__ void sockfd_put(struct socket *sock)
-{
-	fput(sock->file);
-}
-
 static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg)
 {
 	u32 tmp1, tmp2, tmp3;
@@ -3690,7 +3691,7 @@
 
 extern asmlinkage long sys_personality(unsigned long);
 
-asmlinkage int sys32_personality(unsigned long personality)
+asmlinkage int ppc64_personality(unsigned long personality)
 {
 	int ret;
 	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
--- a/arch/ppc64/kernel/syscalls.c	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/kernel/syscalls.c	Fri Oct 18 21:03:03 2002
@@ -41,7 +41,6 @@
 #include <asm/ipc.h>
 #include <asm/semaphore.h>
 #include <asm/ppcdebug.h>
-
 #include <asm/time.h>
 
 extern unsigned long wall_jiffies;
@@ -83,8 +82,7 @@
 
 		if (!ptr)
 			break;
-		if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))
-		    || (ret = get_user(fourth.__pad, (void **)ptr)))
+		if ((ret = get_user(fourth.__pad, (void **)ptr)))
 			break;
 		ret = sys_semctl (first, second, third, fourth);
 		break;
@@ -99,13 +97,12 @@
 
 			if (!ptr)
 				break;
-			if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))
-			    || (ret = copy_from_user(&tmp,
+			if ((ret = copy_from_user(&tmp,
 						(struct ipc_kludge *) ptr,
-						sizeof (tmp))))
+						sizeof (tmp)) ? -EFAULT : 0))
 				break;
-			ret = sys_msgrcv (first, (struct msgbuf *)(unsigned long)tmp.msgp,
-						second, tmp.msgtyp, third);
+			ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
+					  third);
 			break;
 		}
 		default:
@@ -124,10 +121,6 @@
 		switch (version) {
 		default: {
 			ulong raddr;
-
-			if ((ret = verify_area(VERIFY_WRITE, (ulong*) third,
-					       sizeof(ulong))))
-				break;
 			ret = sys_shmat (first, (char *) ptr, second, &raddr);
 			if (ret)
 				break;
@@ -217,7 +210,6 @@
 	
 	return err;
 }
-
 
 asmlinkage time_t sys64_time(time_t* tloc)
 {
diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
--- a/arch/ppc64/kernel/traps.c	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc64/kernel/traps.c	Fri Oct 18 21:03:04 2002
@@ -127,11 +127,10 @@
 SystemResetException(struct pt_regs *regs)
 {
 	if (fwnmi_active) {
-		unsigned long *r3 = __va(regs->gpr[3]); /* for FWNMI debug */
-		struct rtas_error_log *errlog;
-
-		udbg_printf("FWNMI is active with save area at %016lx\n", r3);
-		errlog = FWNMI_get_errinfo(regs);
+		struct rtas_error_log *errhdr = FWNMI_get_errinfo(regs);
+		if (errhdr) {
+			/* XXX Should look at FWNMI information */
+		}
 		FWNMI_release_errinfo();
 	}
 
diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c
--- a/arch/ppc64/kernel/udbg.c	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/kernel/udbg.c	Fri Oct 18 21:03:03 2002
@@ -52,8 +52,6 @@
 
 volatile struct NS16550 *udbg_comport;
 
-spinlock_t udbg_lock = SPIN_LOCK_UNLOCKED;
-
 void
 udbg_init_uart(void *comport)
 {
@@ -84,9 +82,6 @@
 				/* wait for idle */;
 			udbg_comport->thr = '\r'; eieio();
 		}
-	} else if (naca->platform == PLATFORM_ISERIES_LPAR) {
-		/* ToDo: switch this via ppc_md */
-		printk("%c", c);
 	}
 }
 
@@ -161,6 +156,12 @@
 }
 
 void
+udbg_console_write(struct console *con, const char *s, unsigned int n)
+{
+	udbg_write(s, n);
+}
+
+void
 udbg_puthex(unsigned long val)
 {
 	int i, nibbles = sizeof(val)*2;
@@ -190,16 +191,13 @@
 void
 udbg_printf(const char *fmt, ...)
 {
-	unsigned long flags;
 	unsigned char buf[256];
 
 	va_list args;
 	va_start(args, fmt);
 
-	spin_lock_irqsave(&udbg_lock, flags);
 	vsprintf(buf, fmt, args);
 	udbg_puts(buf);
-	spin_unlock_irqrestore(&udbg_lock, flags);
 
 	va_end(args);
 }
@@ -208,7 +206,6 @@
 void
 udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...)
 {
-	unsigned long flags;
 	unsigned long active_debugs = debug_flags & naca->debug_switch;
 
 	if ( active_debugs ) {
@@ -216,7 +213,6 @@
 		unsigned char buf[256];
 		unsigned long i, len = 0;
 
-		spin_lock_irqsave(&udbg_lock, flags);
 		for(i=0; i < PPCDBG_NUM_FLAGS ;i++) {
 			if (((1U << i) & active_debugs) && 
 			    trace_names[i]) {
@@ -237,7 +233,6 @@
 		va_start(ap, fmt);
 		vsprintf(buf, fmt, ap);
 		udbg_puts(buf);
-		spin_unlock_irqrestore(&udbg_lock, flags);
 		
 		va_end(ap);
 	}
diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
--- a/arch/ppc64/kernel/xics.c	Fri Oct 18 21:03:03 2002
+++ b/arch/ppc64/kernel/xics.c	Fri Oct 18 21:03:03 2002
@@ -23,6 +23,7 @@
 #include "i8259.h"
 #include "xics.h"
 #include <asm/ppcdebug.h>
+#include <asm/machdep.h>
 
 void xics_enable_irq(u_int irq);
 void xics_disable_irq(u_int irq);
@@ -296,6 +297,8 @@
 	struct device_node *np;
 	uint *ireg, ilen, indx=0;
 
+	ppc64_boot_msg(0x20, "XICS Init");
+
 	ibm_get_xive = rtas_token("ibm,get-xive");
 	ibm_set_xive = rtas_token("ibm,set-xive");
 	ibm_int_off = rtas_token("ibm,int-off");
@@ -413,6 +416,7 @@
 	request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0);
 	irq_desc[XICS_IPI+XICS_IRQ_OFFSET].status |= IRQ_PER_CPU;
 #endif
+	ppc64_boot_msg(0x21, "XICS Done");
 }
 
 void xics_isa_init(void)
diff -Nru a/arch/ppc64/lib/copyuser.S b/arch/ppc64/lib/copyuser.S
--- a/arch/ppc64/lib/copyuser.S	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc64/lib/copyuser.S	Fri Oct 18 21:03:08 2002
@@ -253,14 +253,16 @@
 	addi	r4,r4,1
 	bne	1b
 	blr
-3:	srdi	r9,r5,3
+3:	cmpldi	cr1,r5,8
+	srdi	r9,r5,3
 	andi.	r5,r5,7
+	blt	cr1,93f
 	mtctr	r9
 91:	std	r0,0(r4)
 	addi	r4,r4,8
 	bdnz	91b
-	beqlr
-	mtctr	r5
+93:	beqlr
+	mtctr	r5	
 92:	stb	r0,0(r4)
 	addi	r4,r4,1
 	bdnz	92b
diff -Nru a/arch/ppc64/mm/extable.c b/arch/ppc64/mm/extable.c
--- a/arch/ppc64/mm/extable.c	Fri Oct 18 21:03:04 2002
+++ b/arch/ppc64/mm/extable.c	Fri Oct 18 21:03:04 2002
@@ -1,5 +1,5 @@
 /*
- * linux/arch/ppc/mm/extable.c
+ * linux/arch/ppc64/mm/extable.c
  *
  * from linux/arch/i386/mm/extable.c
  *
@@ -11,6 +11,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
 extern struct exception_table_entry __start___ex_table[];
@@ -19,8 +20,7 @@
 /*
  * The exception table needs to be sorted because we use the macros
  * which put things into the exception table in a variety of segments
- * such as the prep, pmac, chrp, etc. segments as well as the init
- * segment and the main kernel text segment.
+ * as well as the init segment and the main kernel text segment.
  */
 static inline void
 sort_ex_table(struct exception_table_entry *start,
@@ -56,43 +56,48 @@
 		 const struct exception_table_entry *last,
 		 unsigned long value)
 {
-        while (first <= last) {
+	while (first <= last) {
 		const struct exception_table_entry *mid;
 		long diff;
 
 		mid = (last - first) / 2 + first;
 		diff = mid->insn - value;
-                if (diff == 0)
-                        return mid->fixup;
-                else if (diff < 0)
-                        first = mid+1;
-                else
-                        last = mid-1;
-        }
-        return 0;
+		if (diff == 0)
+			return mid->fixup;
+		else if (diff < 0)
+			first = mid+1;
+		else
+			last = mid-1;
+	}
+	return 0;
 }
 
+extern spinlock_t modlist_lock;
+
 unsigned long
 search_exception_table(unsigned long addr)
 {
-	unsigned long ret;
+	unsigned long ret = 0;
 
 #ifndef CONFIG_MODULES
 	/* There is only the kernel to search.  */
 	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-	if (ret) return ret;
+	return ret;
 #else
+	unsigned long flags;
 	/* The kernel is the last "module" -- no need to treat it special.  */
 	struct module *mp;
+
+	spin_lock_irqsave(&modlist_lock, flags);
 	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->ex_table_start == NULL)
+		if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
 			continue;
 		ret = search_one_table(mp->ex_table_start,
 				       mp->ex_table_end - 1, addr);
 		if (ret)
-			return ret;
+			break;
 	}
+	spin_unlock_irqrestore(&modlist_lock, flags);
+	return ret;
 #endif
-
-	return 0;
 }
diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
--- a/arch/ppc64/mm/fault.c	Fri Oct 18 21:03:07 2002
+++ b/arch/ppc64/mm/fault.c	Fri Oct 18 21:03:07 2002
@@ -27,6 +27,7 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/smp_lock.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -67,11 +68,19 @@
 
 #ifdef CONFIG_DEBUG_KERNEL
 	if (debugger_fault_handler && (regs->trap == 0x300 ||
-				regs->trap == 0x380)) {
+				       regs->trap == 0x380)) {
 		debugger_fault_handler(regs);
 		return;
 	}
+#endif
 
+	/* On an SLB miss we can only check for a valid exception entry */
+	if (regs->trap == 0x380) {
+		bad_page_fault(regs, address, SIGSEGV);
+		return;
+	}
+
+#ifdef CONFIG_DEBUG_KERNEL
 	if (error_code & 0x00400000) {
 		/* DABR match */
 		if (debugger_dabr_match(regs))
@@ -79,7 +88,7 @@
 	}
 #endif
 
-	if (in_interrupt() || mm == NULL) {
+	if (in_atomic() || mm == NULL) {
 		bad_page_fault(regs, address, SIGSEGV);
 		return;
 	}
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	Fri Oct 18 21:03:05 2002
+++ b/arch/ppc64/mm/init.c	Fri Oct 18 21:03:05 2002
@@ -411,7 +411,7 @@
 	struct paca_struct *lpaca;
 	unsigned long guard_page, index;
 
-	ppc_md.progress("MM:init", 0);
+	ppc64_boot_msg(0x100, "MM Init");
 
 	/* Reserve all contexts < FIRST_USER_CONTEXT for kernel use.
 	 * The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT)
@@ -432,7 +432,7 @@
 		ppc_md.hpte_updateboltedpp(PP_RXRX, guard_page);
 	}
 
-	ppc_md.progress("MM:exit", 0x211);
+	ppc64_boot_msg(0x100, "MM Init Done");
 }
 
 /*
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	Fri Oct 18 21:03:08 2002
+++ b/arch/ppc64/xmon/xmon.c	Fri Oct 18 21:03:08 2002
@@ -49,11 +49,6 @@
 #define setjmp xmon_setjmp
 #define longjmp xmon_longjmp
 
-#define memlist_entry list_entry
-#define memlist_next(x) ((x)->next)
-#define memlist_prev(x) ((x)->prev)
-
-
 /* Max number of stack frames we are willing to produce on a backtrace. */
 #define MAXFRAMECOUNT 50
 
@@ -120,6 +115,7 @@
 static void cpu_cmd(void);
 #endif /* CONFIG_SMP */
 static void csum(void);
+static void bootcmds(void);
 static void mem_translate(void);
 static void mem_check(void);
 static void mem_find_real(void);
@@ -141,6 +137,14 @@
 
 #define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
 
+#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'f') \
+			 || ('A' <= (c) && (c) <= 'F'))
+#define isalnum(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'z') \
+			 || ('A' <= (c) && (c) <= 'Z'))
+#define isspace(c)	(c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
+
 static char *help_string = "\
 Commands:\n\
   b	show breakpoints\n\
@@ -170,14 +174,14 @@
   t	print backtrace\n\
   T	Enable/Disable PPCDBG flags\n\
   x	exit monitor\n\
-  z	reboot\n\
-  Z	halt\n\
 ";
 
 static int xmon_trace[NR_CPUS];
 #define SSTEP	1		/* stepping because of 's' command */
 #define BRSTEP	2		/* stepping over breakpoint */
 
+static struct pt_regs *xmon_regs[NR_CPUS];
+
 /*
  * Stuff for reading and writing memory safely
  */
@@ -312,6 +316,7 @@
 
 	msr = get_msr();
 	set_msrd(msr & ~MSR_EE);	/* disable interrupts */
+	xmon_regs[smp_processor_id()] = excp;
 	excprint(excp);
 #ifdef CONFIG_SMP
 	if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
@@ -340,6 +345,7 @@
 		xmon_trace[smp_processor_id()] = 0;
 		insert_bpts();
 	}
+	xmon_regs[smp_processor_id()] = 0;
 #ifdef CONFIG_SMP
 	clear_bit(0, &got_xmon);
 	clear_bit(smp_processor_id(), &cpus_in_xmon);
@@ -347,85 +353,6 @@
 	set_msrd(msr);		/* restore interrupt enable */
 }
 
-/* Code can call this to get a backtrace and continue. */
-void
-xmon_backtrace(const char *fmt, ...)
-{
-	va_list ap;
-	struct pt_regs regs;
-
-
-	/* Ok, grab regs as they are now.
-	 This won't do a particularily good job because the
-	 prologue has already been executed.
-	 ToDo: We could reach back into the callers save
-	 area to do a better job of representing the
-	 caller's state.
-	 */
-	asm volatile ("std	0,0(%0)\n\
-	    std	1,8(%0)\n\
-	    std	2,16(%0)\n\
-	    std	3,24(%0)\n\
-	    std	4,32(%0)\n\
-	    std	5,40(%0)\n\
-	    std	6,48(%0)\n\
-	    std	7,56(%0)\n\
-	    std	8,64(%0)\n\
-	    std	9,72(%0)\n\
-	    std	10,80(%0)\n\
-	    std	11,88(%0)\n\
-	    std	12,96(%0)\n\
-	    std	13,104(%0)\n\
-	    std	14,112(%0)\n\
-	    std	15,120(%0)\n\
-	    std	16,128(%0)\n\
-	    std	17,136(%0)\n\
-	    std	18,144(%0)\n\
-	    std	19,152(%0)\n\
-	    std	20,160(%0)\n\
-	    std	21,168(%0)\n\
-	    std	22,176(%0)\n\
-	    std	23,184(%0)\n\
-	    std	24,192(%0)\n\
-	    std	25,200(%0)\n\
-	    std	26,208(%0)\n\
-	    std	27,216(%0)\n\
-	    std	28,224(%0)\n\
-	    std	29,232(%0)\n\
-	    std	30,240(%0)\n\
-	    std	31,248(%0)" : : "b" (&regs));
-	/* Fetch the link reg for this stack frame.
-	 NOTE: the prev printf fills in the lr. */
-	regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
-	regs.msr = get_msr();
-	regs.ctr = get_ctr();
-	regs.xer = get_xer();
-	regs.ccr = get_cr();
-	regs.trap = 0;
-
-	va_start(ap, fmt);
-	xmon_vfprintf(stdout, fmt, ap);
-	xmon_putc('\n', stdout);
-	va_end(ap);
-	take_input("\n");
-	backtrace(&regs);
-}
-
-/* Call this to poll for ^C during busy operations.
- * Returns true if the user has hit ^C.
- */
-int
-xmon_interrupted(void)
-{
-	int ret = xmon_read_poll();
-	if (ret == 3) {
-		printf("\n^C interrupted.\n");
-		return 1;
-	}
-	return 0;
-}
-
-
 void
 xmon_irq(int irq, void *d, struct pt_regs *regs)
 {
@@ -604,14 +531,6 @@
 			cmd = inchar();
 		}
 		switch (cmd) {
-		case 'z':
-			printf("Rebooting machine now...");
-			machine_restart(NULL);
-			break;
-		case 'Z':
-			printf("Halting machine now...");
-			machine_halt();
-			break;
 		case 'm':
 			cmd = inchar();
 			switch (cmd) {
@@ -695,6 +614,8 @@
 			cpu_cmd();
 			break;
 #endif /* CONFIG_SMP */
+		case 'z':
+			bootcmds();
 		case 'T':
 			debug_trace();
 			break;
@@ -713,6 +634,19 @@
 	}
 }
 
+static void bootcmds(void)
+{
+	int cmd;
+
+	cmd = inchar();
+	if (cmd == 'r')
+		ppc_md.restart(NULL);
+	else if (cmd == 'h')
+		ppc_md.halt();
+	else if (cmd == 'p')
+		ppc_md.power_off();
+}
+
 #ifdef CONFIG_SMP
 static void cpu_cmd(void)
 {
@@ -968,7 +902,9 @@
 	case 0x100:	ret = "(System Reset)"; break; 
 	case 0x200:	ret = "(Machine Check)"; break; 
 	case 0x300:	ret = "(Data Access)"; break; 
+	case 0x380:	ret = "(Data SLB Access)"; break;
 	case 0x400:	ret = "(Instruction Access)"; break; 
+	case 0x480:	ret = "(Instruction SLB Access)"; break;
 	case 0x500:	ret = "(Hardware Interrupt)"; break; 
 	case 0x600:	ret = "(Alignment)"; break; 
 	case 0x700:	ret = "(Program Check)"; break; 
@@ -1116,7 +1052,7 @@
 	printf("    sp: %lx\n", fp->gpr[1]);
 	printf("   msr: %lx\n", fp->msr);
 
-	if (fp->trap == 0x300 || fp->trap == 0x600) {
+	if (fp->trap == 0x300 || fp->trap == 0x380 || fp->trap == 0x600) {
 		printf("   dar: %lx\n", fp->dar);
 		printf(" dsisr: %lx\n", fp->dsisr);
 	}
@@ -1292,34 +1228,6 @@
 	scannl();
 }
 
-#if 0
-static void
-openforth()
-{
-	int c;
-	char *p;
-	char cmd[1024];
-	int args[5];
-	extern int (*prom_entry)(int *);
-
-	p = cmd;
-	c = skipbl();
-	while (c != '\n') {
-		*p++ = c;
-		c = inchar();
-	}
-	*p = 0;
-	args[0] = (int) "interpret";
-	args[1] = 1;
-	args[2] = 1;
-	args[3] = (int) cmd;
-	(*prom_entry)(args);
-	printf("\n");
-	if (args[4] != 0)
-		printf("error %x\n", args[4]);
-}
-#endif
-
 #ifndef CONFIG_PPC64BRIDGE
 static void
 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
@@ -1534,7 +1442,18 @@
 static void
 handle_fault(struct pt_regs *regs)
 {
-	fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
+	switch (regs->trap) {
+	case 0x200:
+		fault_type = 0;
+		break;
+	case 0x300:
+	case 0x380:
+		fault_type = 1;
+		break;
+	default:
+		fault_type = 2;
+	}
+
 	longjmp(bus_error_jmp, 1);
 }
 
@@ -2007,6 +1926,16 @@
 	return c;
 }
 
+#define N_PTREGS	44
+static char *regnames[N_PTREGS] = {
+	"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+	"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+	"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+	"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+	"pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
+	"trap", "dar", "dsisr", "res"
+};
+
 int
 scanhex(vp)
 unsigned long *vp;
@@ -2015,6 +1944,36 @@
 	unsigned long v;
 
 	c = skipbl();
+	if (c == '%') {
+		/* parse register name */
+		char regname[8];
+		int i;
+
+		for (i = 0; i < sizeof(regname) - 1; ++i) {
+			c = inchar();
+			if (!isalnum(c)) {
+				termch = c;
+				break;
+			}
+			regname[i] = c;
+		}
+		regname[i] = 0;
+		for (i = 0; i < N_PTREGS; ++i) {
+			if (strcmp(regnames[i], regname) == 0) {
+				unsigned long *rp = (unsigned long *)
+					xmon_regs[smp_processor_id()];
+				if (rp == NULL) {
+					printf("regs not available\n");
+					return 0;
+				}
+				*vp = rp[i];
+				return 1;
+			}
+		}
+		printf("invalid register name '%%%s'\n", regname);
+		return 0;
+	}
+
 	d = hexdigit(c);
 	if( d == EOF ){
 		termch = c;
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	Fri Oct 18 21:03:03 2002
+++ b/arch/s390x/kernel/linux32.c	Fri Oct 18 21:03:03 2002
@@ -1563,12 +1563,15 @@
 	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
 	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 
+	if (s32->version != SMB_MOUNT_OLDVERSION)
+		goto out;
 	s->version = s32->version;
 	s->mounted_uid = low2highuid(s32->mounted_uid);
 	s->uid = low2highuid(s32->uid);
 	s->gid = low2highgid(s32->gid);
 	s->file_mode = s32->file_mode;
 	s->dir_mode = s32->dir_mode;
+out:
 	return raw_data;
 }
 
@@ -2128,14 +2131,6 @@
 					   16 for IP, 16 for IPX,
 					   24 for IPv6,
 					   about 80 for AX.25 */
-
-extern struct socket *sockfd_lookup(int fd, int *err);
-
-/* XXX This as well... */
-extern __inline__ void sockfd_put(struct socket *sock)
-{
-	fput(sock->file);
-}
 
 struct msghdr32 {
         u32               msg_name;
diff -Nru a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
--- a/arch/sh/kernel/sh_ksyms.c	Fri Oct 18 21:03:03 2002
+++ b/arch/sh/kernel/sh_ksyms.c	Fri Oct 18 21:03:03 2002
@@ -36,9 +36,6 @@
 EXPORT_SYMBOL(irq_desc);
 EXPORT_SYMBOL(no_irq_type);
 
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
-
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
diff -Nru a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
--- a/arch/sh/lib/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/sh/lib/Makefile	Fri Oct 18 21:03:04 2002
@@ -3,7 +3,7 @@
 #
 
 L_TARGET = lib.a
-obj-y  = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \
+obj-y  = delay.o memcpy.o memset.o memmove.o memchr.o \
 	 checksum.o strcasecmp.o strlen.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/sh/lib/old-checksum.c b/arch/sh/lib/old-checksum.c
--- a/arch/sh/lib/old-checksum.c	Fri Oct 18 21:03:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,17 +0,0 @@
-/*
- * FIXME: old compatibility stuff, will be removed soon.
- */
-
-#include <net/checksum.h>
-
-unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum)
-{
-	int src_err=0, dst_err=0;
-
-	sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err);
-
-	if (src_err || dst_err)
-		printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n");
-
-	return sum;
-}
diff -Nru a/arch/sparc/Makefile b/arch/sparc/Makefile
--- a/arch/sparc/Makefile	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc/Makefile	Fri Oct 18 21:03:03 2002
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.49 2001/07/27 09:42:22 davem Exp $
+#
 # sparc/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -47,16 +47,24 @@
 	$(MAKE) -C arch/sparc/boot image
 
 archclean:
+	rm -f arch/sparc/kernel/include
 	rm -f $(TOPDIR)/vmlinux.aout
 	-$(MAKE) -C arch/sparc/boot clean
 
 archmrproper:
 	rm -f $(TOPDIR)/include/asm-sparc/asm_offsets.h
 
-prepare: check_asm
+prepare: include/asm-$(ARCH)/asm_offsets.h
+
+arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
+				   include/config/MARKER
+
+include/asm-$(ARCH)/asm_offsets.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
+	@$(generate-asm-offsets.h) < $< > $@
 
-check_asm: include/linux/version.h include/asm include/config/MARKER
-	$(MAKE) -C arch/sparc/kernel check_asm
+include/asm-$(ARCH)/asm_offsets.h: include/asm-$(ARCH)/asm_offsets.h.tmp
+	@echo -n '  Generating $@'
+	@$(update-if-changed)
 
 tftpboot.img:
 	$(MAKE) -C arch/sparc/boot tftpboot.img
diff -Nru a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
--- a/arch/sparc/boot/Makefile	Fri Oct 18 21:03:08 2002
+++ b/arch/sparc/boot/Makefile	Fri Oct 18 21:03:08 2002
@@ -23,7 +23,7 @@
 	rm -f btfixupprep piggyback tftpboot.img btfix.o btfix.s image
 
 BTOBJS := $(HEAD) $(init-y)
-BTLIBS := $(core-y) $(LIBS) $(drivers-y) $(net-y)
+BTLIBS := $(core-y) $(libs-y) $(drivers-y) $(net-y)
 
 # Actual linking
 image: btfix.o
diff -Nru a/arch/sparc/defconfig b/arch/sparc/defconfig
--- a/arch/sparc/defconfig	Fri Oct 18 21:03:07 2002
+++ b/arch/sparc/defconfig	Fri Oct 18 21:03:07 2002
@@ -416,7 +416,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Watchdog
diff -Nru a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
--- a/arch/sparc/kernel/Makefile	Fri Oct 18 21:03:04 2002
+++ b/arch/sparc/kernel/Makefile	Fri Oct 18 21:03:04 2002
@@ -28,95 +28,3 @@
 endif
 
 include $(TOPDIR)/Rules.make
-
-HPATH := $(objtree)/include
-
-check_asm: FORCE
-	@if [ ! -r $(HPATH)/asm/asm_offsets.h ] ; then \
-	  touch $(HPATH)/asm/asm_offsets.h ; \
-	fi
-	@echo "/* Automatically generated. Do not edit. */" > asm_offsets.h
-	@echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
-	@echo "#define __ASM_OFFSETS_H__" >> asm_offsets.h
-	@echo "" >> asm_offsets.h
-	@echo "#include <linux/config.h>" >> asm_offsets.h
-	@echo "" >> asm_offsets.h
-	@echo "#ifndef CONFIG_SMP" >> asm_offsets.h
-	@echo "" >> asm_offsets.h
-	@echo "#include <linux/config.h>" > tmp.c
-	@echo "#undef CONFIG_SMP" >> tmp.c
-	@echo "#include <linux/sched.h>" >> tmp.c
-	$(CPP) $(CPPFLAGS) tmp.c -o tmp.i
-	@echo "/* Automatically generated. Do not edit. */" > check_asm_data.c
-	@echo "#include <linux/config.h>" >> check_asm_data.c
-	@echo "#undef CONFIG_SMP" >> check_asm_data.c
-	@echo "#include <linux/sched.h>" >> check_asm_data.c
-	@echo "unsigned int check_asm_data[] = {" >> check_asm_data.c
-	$(SH) ./check_asm.sh -data task tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c
-	@echo '};' >> check_asm_data.c
-	$(CC) $(CFLAGS) -S -o check_asm_data.s check_asm_data.c
-	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
-	@echo 'extern int printf(const char *fmt, ...);' >>check_asm.c
-	@echo "unsigned int check_asm_data[] = {" >> check_asm.c
-	$(SH) ./check_asm.sh -ints check_asm_data.s check_asm.c
-	@echo "};" >> check_asm.c
-	@echo 'int main(void) {' >> check_asm.c
-	@echo 'int i = 0;' >> check_asm.c
-	$(SH) ./check_asm.sh -printf task tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf mm tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf thread tmp.i check_asm.c
-	@echo 'return 0; }' >> check_asm.c
-	@rm -f tmp.[ci] check_asm_data.[cs]
-	$(HOSTCC) -o check_asm check_asm.c
-	./check_asm >> asm_offsets.h
-	@rm -f check_asm check_asm.c
-	@echo "" >> asm_offsets.h
-	@echo "#else /* CONFIG_SMP */" >> asm_offsets.h
-	@echo "" >> asm_offsets.h
-	@echo "#include <linux/config.h>" > tmp.c
-	@echo "#undef CONFIG_SMP" >> tmp.c
-	@echo "#define CONFIG_SMP 1" >> tmp.c
-	@echo "#include <linux/sched.h>" >> tmp.c
-	$(CPP) $(CPPFLAGS) tmp.c -o tmp.i
-	@echo "/* Automatically generated. Do not edit. */" > check_asm_data.c
-	@echo "#include <linux/config.h>" >> check_asm_data.c
-	@echo "#undef CONFIG_SMP" >> check_asm_data.c
-	@echo "#define CONFIG_SMP 1" >> check_asm_data.c
-	@echo "#include <linux/sched.h>" >> check_asm_data.c
-	@echo "unsigned int check_asm_data[] = {" >> check_asm_data.c
-	$(SH) ./check_asm.sh -data task tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c
-	@echo '};' >> check_asm_data.c
-	$(CC) $(CFLAGS) -S -o check_asm_data.s check_asm_data.c
-	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
-	@echo 'extern int printf(const char *fmt, ...);' >>check_asm.c
-	@echo "unsigned int check_asm_data[] = {" >> check_asm.c
-	$(SH) ./check_asm.sh -ints check_asm_data.s check_asm.c
-	@echo "};" >> check_asm.c
-	@echo 'int main(void) {' >> check_asm.c
-	@echo 'int i = 0;' >> check_asm.c
-	$(SH) ./check_asm.sh -printf task tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf mm tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf thread tmp.i check_asm.c
-	@echo 'return 0; }' >> check_asm.c
-	@rm -f tmp.[ci] check_asm_data.[cs]
-	$(HOSTCC) -o check_asm check_asm.c
-	./check_asm >> asm_offsets.h
-	@rm -f check_asm check_asm.c
-	@echo "" >> asm_offsets.h
-	@echo "#endif /* CONFIG_SMP */" >> asm_offsets.h
-	@echo "" >> asm_offsets.h
-	@echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h
-	@if test -r $(HPATH)/asm/asm_offsets.h; then \
-	  if cmp -s asm_offsets.h $(HPATH)/asm/asm_offsets.h; then \
-	    echo $(HPATH)/asm/asm_offsets.h is unchanged; \
-	    rm -f asm_offsets.h; \
-	  else \
-	    mv -f asm_offsets.h $(HPATH)/asm/asm_offsets.h; \
-	  fi; \
-	else \
-	  mv -f asm_offsets.h $(HPATH)/asm/asm_offsets.h; \
-	fi
diff -Nru a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/sparc/kernel/asm-offsets.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,53 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ *
+ * On sparc, thread_info data is static and TI_XXX offsets are computed by hand.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+// #include <linux/mm.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int foo(void)
+{
+	DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread));
+	DEFINE(AOFF_task_ptrace, offsetof(struct task_struct, ptrace));
+	DEFINE(AOFF_task_blocked, offsetof(struct task_struct, blocked));
+	BLANK();
+	/* XXX This is the stuff for sclow.S, kill it. */
+	DEFINE(AOFF_task_pid, offsetof(struct task_struct, pid));
+	DEFINE(AOFF_task_uid, offsetof(struct task_struct, uid));
+	DEFINE(AOFF_task_gid, offsetof(struct task_struct, gid));
+	DEFINE(AOFF_task_euid, offsetof(struct task_struct, euid));
+	DEFINE(AOFF_task_egid, offsetof(struct task_struct, egid));
+	/* DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); */
+	DEFINE(ASIZ_task_uid,	sizeof(current->uid));
+	DEFINE(ASIZ_task_gid,	sizeof(current->gid));
+	DEFINE(ASIZ_task_euid,	sizeof(current->euid));
+	DEFINE(ASIZ_task_egid,	sizeof(current->egid));
+	BLANK();
+	DEFINE(AOFF_thread_fork_kpsr,
+			offsetof(struct thread_struct, fork_kpsr));
+	BLANK();
+	DEFINE(AOFF_thread_w_saved, offsetof(struct thread_struct, w_saved));
+	DEFINE(AOFF_thread_rwbuf_stkptrs,
+			offsetof(struct thread_struct, rwbuf_stkptrs));
+	DEFINE(AOFF_thread_reg_window,
+			offsetof(struct thread_struct, reg_window));
+	BLANK();
+	DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context));
+
+	/* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */
+	return 0;
+}
diff -Nru a/arch/sparc/kernel/check_asm.sh b/arch/sparc/kernel/check_asm.sh
--- a/arch/sparc/kernel/check_asm.sh	Fri Oct 18 21:03:07 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,19 +0,0 @@
-#!/bin/sh
-case $1 in
-  -printf)
-    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
-/g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0	0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0	0x%08x\\n", check_asm_data[i++]);/' >> $4
-    echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4
-  ;;
-  -data)
-    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
-/g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/	((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)),	sizeof(((struct '$2'_struct *)0)->\0),/' >> $4
-    echo "	sizeof(struct $2_struct)," >> $4
-  ;;
-  -ints)
-    sed -n -e '/check_asm_data:/,/\.size/p' <$2 | sed -e 's/check_asm_data://' -e 's/\.size.*//' -e 's/\.ident.*//' -e 's/\.global.*//' -e 's/\.long[ 	]\([0-9]*\)/\1,/' >>$3  ;;
-  *)
-    exit 1
-  ;;
-esac
-exit 0
diff -Nru a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
--- a/arch/sparc/kernel/entry.S	Fri Oct 18 21:03:04 2002
+++ b/arch/sparc/kernel/entry.S	Fri Oct 18 21:03:04 2002
@@ -17,6 +17,7 @@
 #include <asm/kgdb.h>
 #include <asm/contregs.h>
 #include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
 #include <asm/psr.h>
 #include <asm/cprefix.h>
 #include <asm/vaddrs.h>
diff -Nru a/arch/sparc/kernel/etrap.S b/arch/sparc/kernel/etrap.S
--- a/arch/sparc/kernel/etrap.S	Fri Oct 18 21:03:08 2002
+++ b/arch/sparc/kernel/etrap.S	Fri Oct 18 21:03:08 2002
@@ -12,6 +12,7 @@
 #include <asm/page.h>
 #include <asm/psr.h>
 #include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
 #include <asm/winmacro.h>
 #include <asm/asmmacro.h>
 #include <asm/thread_info.h>
diff -Nru a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
--- a/arch/sparc/kernel/rtrap.S	Fri Oct 18 21:03:04 2002
+++ b/arch/sparc/kernel/rtrap.S	Fri Oct 18 21:03:04 2002
@@ -7,6 +7,7 @@
 #include <asm/cprefix.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
 #include <asm/psr.h>
 #include <asm/asi.h>
 #include <asm/smp.h>
diff -Nru a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S
--- a/arch/sparc/kernel/sclow.S	Fri Oct 18 21:03:08 2002
+++ b/arch/sparc/kernel/sclow.S	Fri Oct 18 21:03:08 2002
@@ -36,18 +36,6 @@
 LABEL(sunosnop):
 	CC_AND_RETT
 
-#if 0
-/* Not SMP safe */
-	.globl	LABEL(sunosgetpid)
-LABEL(sunosgetpid):
-	LOAD_CURRENT(l4, l5)
-	ld	[%l4 + TI_TASK], %l4
-	ld	[%l4 + AOFF_task_pid], %i0
-	ld	[%l4 + AOFF_task_p_opptr], %l5
-	ld	[%l5 + AOFF_task_pid], %i1
-	CC_AND_RETT
-#endif
-
 #if (ASIZ_task_uid == 2 && ASIZ_task_euid == 2)
 	.globl	LABEL(sunosgetuid)
 LABEL(sunosgetuid):
diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
--- a/arch/sparc/kernel/signal.c	Fri Oct 18 21:03:07 2002
+++ b/arch/sparc/kernel/signal.c	Fri Oct 18 21:03:07 2002
@@ -90,38 +90,6 @@
 	__siginfo_fpu_t		fpu_state;
 };
 
-int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
-{
-	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
-		return -EFAULT;
-	if (from->si_code < 0)
-		return __copy_to_user(to, from, sizeof(siginfo_t));
-	else {
-		int err;
-
-		/* If you change siginfo_t structure, please be sure
-		   this code is fixed accordingly.
-		   It should never copy any pad contained in the structure
-		   to avoid security leaks, but must copy the generic
-		   3 ints plus the relevant union member.  */
-		err = __put_user(from->si_signo, &to->si_signo);
-		err |= __put_user(from->si_errno, &to->si_errno);
-		err |= __put_user((short)from->si_code, &to->si_code);
-		switch (from->si_code >> 16) {
-		case __SI_CHLD >> 16:
-			err |= __put_user(from->si_utime, &to->si_utime);
-			err |= __put_user(from->si_stime, &to->si_stime);
-		/* case __SI_RT: This is not generated by the kernel as of now.  */
-			err |= __put_user(from->si_status, &to->si_status);
-		default:
-			err |= __put_user(from->si_uid, &to->si_uid);
-			err |= __put_user(from->si_pid, &to->si_pid);
-			break;
-		}
-		return err;
-	}
-}
-
 /* Align macros */
 #define SF_ALIGNEDSZ  (((sizeof(struct signal_sframe) + 7) & (~7)))
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame) + 7) & (~7)))
diff -Nru a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
--- a/arch/sparc/kernel/sparc_ksyms.c	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc/kernel/sparc_ksyms.c	Fri Oct 18 21:03:03 2002
@@ -243,6 +243,7 @@
 
 /* sparc library symbols */
 EXPORT_SYMBOL(bcopy);
+EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL_NOVERS(memscan);
 EXPORT_SYMBOL_NOVERS(strlen);
 EXPORT_SYMBOL(strnlen);
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Fri Oct 18 21:03:04 2002
+++ b/arch/sparc/kernel/systbls.S	Fri Oct 18 21:03:04 2002
@@ -59,7 +59,7 @@
 /*190*/	.long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*195*/	.long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
 /*200*/	.long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
-/*205*/	.long sys_readahead, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
+/*205*/	.long sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall
 /*210*/	.long sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
 /*215*/	.long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.long sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c	Fri Oct 18 21:03:05 2002
+++ b/arch/sparc/kernel/time.c	Fri Oct 18 21:03:05 2002
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
+#include <linux/profile.h>
 
 #include <asm/oplib.h>
 #include <asm/segment.h>
diff -Nru a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S
--- a/arch/sparc/kernel/wof.S	Fri Oct 18 21:03:07 2002
+++ b/arch/sparc/kernel/wof.S	Fri Oct 18 21:03:07 2002
@@ -8,6 +8,7 @@
 #include <asm/contregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
 #include <asm/psr.h>
 #include <asm/smp.h>
 #include <asm/asi.h>
diff -Nru a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S
--- a/arch/sparc/kernel/wuf.S	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc/kernel/wuf.S	Fri Oct 18 21:03:03 2002
@@ -8,6 +8,7 @@
 #include <asm/contregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
+#include <asm/asm_offsets.h>
 #include <asm/psr.h>
 #include <asm/smp.h>
 #include <asm/asi.h>
diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
--- a/arch/sparc/vmlinux.lds.S	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc/vmlinux.lds.S	Fri Oct 18 21:03:03 2002
@@ -38,12 +38,12 @@
 
   . = ALIGN(4096);
   __init_begin = .;
-  .text.init : { *(.text.init) }
+  .init.text : { *(.init.text) }
   __init_text_end = .;
-  .data.init : { *(.data.init) }
+  .init.data : { *(.init.data) }
   . = ALIGN(16);
   __setup_start = .;
-  .setup_init : { *(.setup.init) }
+  .init.setup : { *(.init.setup) }
   __setup_end = .;
   __initcall_start = .;
   .initcall.init : {
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	Fri Oct 18 21:03:04 2002
+++ b/arch/sparc64/defconfig	Fri Oct 18 21:03:04 2002
@@ -1024,27 +1024,27 @@
 #
 # Bluetooth support
 #
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
-CONFIG_BLUEZ_SCO=m
-CONFIG_BLUEZ_RFCOMM=m
-CONFIG_BLUEZ_RFCOMM_TTY=y
-CONFIG_BLUEZ_BNEP=m
-CONFIG_BLUEZ_BNEP_MC_FILTER=y
-CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
 
 #
 # Bluetooth device drivers
 #
-CONFIG_BLUEZ_HCIUSB=m
-CONFIG_BLUEZ_USB_ZERO_PACKET=y
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIUART_H4=y
-CONFIG_BLUEZ_HCIUART_BCSP=y
-# CONFIG_BLUEZ_HCIDTL1 is not set
-# CONFIG_BLUEZ_HCIBT3C is not set
-# CONFIG_BLUEZ_HCIBLUECARD is not set
-CONFIG_BLUEZ_HCIVHCI=m
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_USB_ZERO_PACKET=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+CONFIG_BT_HCIVHCI=m
 
 #
 # Watchdog
diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
--- a/arch/sparc64/kernel/ioctl32.c	Fri Oct 18 21:03:08 2002
+++ b/arch/sparc64/kernel/ioctl32.c	Fri Oct 18 21:03:08 2002
@@ -797,8 +797,6 @@
 	s32			rtmsg_ifindex;
 };
 
-extern struct socket *sockfd_lookup(int fd, int *err);
-
 static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	int ret;
@@ -846,6 +844,9 @@
 	set_fs (KERNEL_DS);
 	ret = sys_ioctl (fd, cmd, (long) r);
 	set_fs (old_fs);
+
+	if (mysock)
+		sockfd_put(mysock);
 
 	return ret;
 }
diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
--- a/arch/sparc64/kernel/signal.c	Fri Oct 18 21:03:05 2002
+++ b/arch/sparc64/kernel/signal.c	Fri Oct 18 21:03:05 2002
@@ -36,38 +36,6 @@
 static int do_signal(sigset_t *oldset, struct pt_regs * regs,
 		     unsigned long orig_o0, int ret_from_syscall);
 
-int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
-{
-	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
-		return -EFAULT;
-	if (from->si_code < 0)
-		return __copy_to_user(to, from, sizeof(siginfo_t));
-	else {
-		int err;
-
-		/* If you change siginfo_t structure, please be sure
-		   this code is fixed accordingly.
-		   It should never copy any pad contained in the structure
-		   to avoid security leaks, but must copy the generic
-		   3 ints plus the relevant union member.  */
-		err = __put_user(*(long *)&from->si_signo, (long *)&to->si_signo);
-		err |= __put_user((short)from->si_code, &to->si_code);
-		switch (from->si_code >> 16) {
-		case __SI_CHLD >> 16:
-			err |= __put_user(from->si_utime, &to->si_utime);
-			err |= __put_user(from->si_stime, &to->si_stime);
-		case __SI_FAULT >> 16:
-		case __SI_POLL >> 16:
-			err |= __put_user(from->si_trapno, &to->si_trapno);
-		default:
-			err |= __put_user(from->si_addr, &to->si_addr);
-			break;
-		/* case __SI_RT: This is not generated by the kernel as of now.  */
-		}
-		return err;
-	}
-}
-
 /* {set, get}context() needed for 64-bit SparcLinux userland. */
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 {
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	Fri Oct 18 21:03:08 2002
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	Fri Oct 18 21:03:08 2002
@@ -331,6 +331,7 @@
 EXPORT_SYMBOL(__memcmp);
 EXPORT_SYMBOL(__strncmp);
 EXPORT_SYMBOL(__memmove);
+EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(csum_partial_copy_sparc64);
 EXPORT_SYMBOL(ip_fast_csum);
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Fri Oct 18 21:03:05 2002
+++ b/arch/sparc64/kernel/sys_sparc32.c	Fri Oct 18 21:03:05 2002
@@ -1582,6 +1582,8 @@
 	struct smb_mount_data news, *s = &news;
 	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 
+	if (s32->version != SMB_MOUNT_OLDVERSION)
+		goto out;
 	s->version = s32->version;
 	s->mounted_uid = low2highuid(s32->mounted_uid);
 	s->uid = low2highuid(s32->uid);
@@ -1589,6 +1591,7 @@
 	s->file_mode = s32->file_mode;
 	s->dir_mode = s32->dir_mode;
 	memcpy(raw_data, s, sizeof(struct smb_mount_data)); 
+out:
 	return raw_data;
 }
 
@@ -2130,14 +2133,6 @@
 					   16 for IP, 16 for IPX,
 					   24 for IPv6,
 					   about 80 for AX.25 */
-
-extern struct socket *sockfd_lookup(int fd, int *err);
-
-/* XXX This as well... */
-extern __inline__ void sockfd_put(struct socket *sock)
-{
-	fput(sock->file);
-}
 
 struct msghdr32 {
         u32               msg_name;
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Fri Oct 18 21:03:04 2002
+++ b/arch/sparc64/kernel/systbls.S	Fri Oct 18 21:03:04 2002
@@ -60,7 +60,7 @@
 /*190*/	.word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
 /*200*/	.word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
-	.word sys32_readahead, sys32_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
+	.word sys32_readahead, sys32_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall
 /*210*/	.word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo
 	.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
 /*220*/	.word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid
@@ -119,7 +119,7 @@
 /*190*/	.word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
 /*200*/	.word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
-	.word sys_readahead, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
+	.word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall
 /*210*/	.word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
 	.word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	Fri Oct 18 21:03:04 2002
+++ b/arch/sparc64/kernel/time.c	Fri Oct 18 21:03:04 2002
@@ -22,6 +22,7 @@
 #include <linux/ioport.h>
 #include <linux/mc146818rtc.h>
 #include <linux/delay.h>
+#include <linux/profile.h>
 
 #include <asm/oplib.h>
 #include <asm/mostek.h>
diff -Nru a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc64/lib/U3copy_from_user.S
--- a/arch/sparc64/lib/U3copy_from_user.S	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc64/lib/U3copy_from_user.S	Fri Oct 18 21:03:03 2002
@@ -7,6 +7,8 @@
 #ifdef __KERNEL__
 #include <asm/visasm.h>
 #include <asm/asi.h>
+#include <asm/dcu.h>
+#include <asm/spitfire.h>
 #undef SMALL_COPY_USES_FPU
 #define EXNV(x,y,a,b)			\
 98:	x,y;				\
@@ -181,6 +183,16 @@
 
 	.align		64
 U3copy_from_user_begin:
+#ifdef __KERNEL__
+	.globl		U3copy_from_user_nop_1_6
+U3copy_from_user_nop_1_6:
+	ldxa		[%g0] ASI_DCU_CONTROL_REG, %g3
+	sethi		%uhi(DCU_PE), %o3
+	sllx		%o3, 32, %o3
+	or		%g3, %o3, %o3
+	stxa		%o3, [%g0] ASI_DCU_CONTROL_REG	! Enable P-cache
+	membar		#Sync
+#endif
 	prefetcha	[%o1 + 0x000] %asi, #one_read	! MS	Group1
 	prefetcha	[%o1 + 0x040] %asi, #one_read	! MS	Group2
 	andn		%o2, (0x40 - 1), %o4		! A0
@@ -321,6 +333,13 @@
 	stda		%f16, [%o0] ASI_BLK_P		! MS
 	add		%o0, 0x40, %o0			! A0
 	add		%o1, 0x40, %o1			! A1
+#ifdef __KERNEL__
+	.globl		U3copy_from_user_nop_2_3
+U3copy_from_user_nop_2_3:
+	mov		PRIMARY_CONTEXT, %o3
+	stxa		%g0, [%o3] ASI_DMMU		! Flush P-cache
+	stxa		%g3, [%g0] ASI_DCU_CONTROL_REG	! Disable P-cache
+#endif
 	membar		#Sync				! MS	Group26 (7-cycle stall)
 
 	/* Now we copy the (len modulo 64) bytes at the end.
diff -Nru a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc64/lib/U3copy_to_user.S
--- a/arch/sparc64/lib/U3copy_to_user.S	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc64/lib/U3copy_to_user.S	Fri Oct 18 21:03:03 2002
@@ -7,6 +7,8 @@
 #ifdef __KERNEL__
 #include <asm/visasm.h>
 #include <asm/asi.h>
+#include <asm/dcu.h>
+#include <asm/spitfire.h>
 #undef SMALL_COPY_USES_FPU
 #define EXNV(x,y,a,b)	\
 98:	x,y;				\
@@ -228,6 +230,16 @@
 
 	.align		64
 U3copy_to_user_begin:
+#ifdef __KERNEL__
+	.globl		U3copy_to_user_nop_1_6
+U3copy_to_user_nop_1_6:
+	ldxa		[%g0] ASI_DCU_CONTROL_REG, %g3
+	sethi		%uhi(DCU_PE), %o3
+	sllx		%o3, 32, %o3
+	or		%g3, %o3, %o3
+	stxa		%o3, [%g0] ASI_DCU_CONTROL_REG	! Enable P-cache
+	membar		#Sync
+#endif
 	prefetch	[%o1 + 0x000], #one_read	! MS	Group1
 	prefetch	[%o1 + 0x040], #one_read	! MS	Group2
 	andn		%o2, (0x40 - 1), %o4		! A0
@@ -368,6 +380,13 @@
 	EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)		! MS
 	add		%o0, 0x40, %o0			! A0
 	add		%o1, 0x40, %o1			! A1
+#ifdef __KERNEL__
+	.globl		U3copy_to_user_nop_2_3
+U3copy_to_user_nop_2_3:
+	mov		PRIMARY_CONTEXT, %o3
+	stxa		%g0, [%o3] ASI_DMMU		! Flush P-cache
+	stxa		%g3, [%g0] ASI_DCU_CONTROL_REG	! Disable P-cache
+#endif
 	membar		#Sync				! MS	Group26 (7-cycle stall)
 
 	/* Now we copy the (len modulo 64) bytes at the end.
diff -Nru a/arch/sparc64/lib/U3memcpy.S b/arch/sparc64/lib/U3memcpy.S
--- a/arch/sparc64/lib/U3memcpy.S	Fri Oct 18 21:03:08 2002
+++ b/arch/sparc64/lib/U3memcpy.S	Fri Oct 18 21:03:08 2002
@@ -7,6 +7,8 @@
 #ifdef __KERNEL__
 #include <asm/visasm.h>
 #include <asm/asi.h>
+#include <asm/dcu.h>
+#include <asm/spitfire.h>
 #undef SMALL_COPY_USES_FPU
 #else
 #define ASI_BLK_P 0xf0
@@ -109,6 +111,16 @@
 
 	.align		64
 U3memcpy_begin:
+#ifdef __KERNEL__
+	.globl		U3memcpy_nop_1_6
+U3memcpy_nop_1_6:
+	ldxa		[%g0] ASI_DCU_CONTROL_REG, %g3
+	sethi		%uhi(DCU_PE), %o3
+	sllx		%o3, 32, %o3
+	or		%g3, %o3, %o3
+	stxa		%o3, [%g0] ASI_DCU_CONTROL_REG	! Enable P-cache
+	membar		#Sync
+#endif
 	prefetch	[%o1 + 0x000], #one_read	! MS	Group1
 	prefetch	[%o1 + 0x040], #one_read	! MS	Group2
 	andn		%o2, (0x40 - 1), %o4		! A0
@@ -249,6 +261,13 @@
 	stda		%f16, [%o0] ASI_BLK_P		! MS
 	add		%o0, 0x40, %o0			! A0
 	add		%o1, 0x40, %o1			! A1
+#ifdef __KERNEL__
+	.globl		U3memcpy_nop_2_3
+U3memcpy_nop_2_3:
+	mov		PRIMARY_CONTEXT, %o3
+	stxa		%g0, [%o3] ASI_DMMU		! Flush P-cache
+	stxa		%g3, [%g0] ASI_DCU_CONTROL_REG	! Disable P-cache
+#endif
 	membar		#Sync				! MS	Group26 (7-cycle stall)
 
 	/* Now we copy the (len modulo 64) bytes at the end.
diff -Nru a/arch/sparc64/lib/VIScopy.S b/arch/sparc64/lib/VIScopy.S
--- a/arch/sparc64/lib/VIScopy.S	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc64/lib/VIScopy.S	Fri Oct 18 21:03:03 2002
@@ -368,6 +368,28 @@
 	or	%g3, %lo(NOP), %g3; \
 	stw	%g3, [%g2 + 0x4]; \
 	flush	%g2;
+#define ULTRA3_PCACHE_DO_NOP(symbol)	\
+	sethi	%hi(symbol##_nop_1_6), %g1; \
+	or	%g1, %lo(symbol##_nop_1_6), %g1; \
+	sethi	%hi(NOP), %g2; \
+	stw	%g2, [%g1 + 0x00]; \
+	stw	%g2, [%g1 + 0x04]; \
+	flush	%g1 + 0x00; \
+	stw	%g2, [%g1 + 0x08]; \
+	stw	%g2, [%g1 + 0x0c]; \
+	flush	%g1 + 0x08; \
+	stw	%g2, [%g1 + 0x10]; \
+	stw	%g2, [%g1 + 0x04]; \
+	flush	%g1 + 0x10; \
+	sethi	%hi(symbol##_nop_2_3), %g1; \
+	or	%g1, %lo(symbol##_nop_2_3), %g1; \
+	stw	%g2, [%g1 + 0x00]; \
+	stw	%g2, [%g1 + 0x04]; \
+	flush	%g1 + 0x00; \
+	stw	%g2, [%g1 + 0x08]; \
+	flush	%g1 + 0x08;
+
+#include <asm/dcu.h>
 
 	.globl	cheetah_patch_copyops
 cheetah_patch_copyops:
@@ -375,6 +397,23 @@
 	ULTRA3_DO_PATCH(__copy_from_user, U3copy_from_user)
 	ULTRA3_DO_PATCH(__copy_to_user, U3copy_to_user)
 	ULTRA3_DO_PATCH(__copy_in_user, U3copy_in_user)
+#if 0 /* Causes data corruption, nop out the optimization
+       * for now -DaveM
+       */
+	ldxa			[%g0] ASI_DCU_CONTROL_REG, %g3
+	sethi			%uhi(DCU_PE), %o3
+	sllx			%o3, 32, %o3
+	andcc			%g3, %o3, %g0
+	be,pn			%xcc, pcache_disabled
+	 nop
+#endif
+	ULTRA3_PCACHE_DO_NOP(U3memcpy)
+	ULTRA3_PCACHE_DO_NOP(U3copy_from_user)
+	ULTRA3_PCACHE_DO_NOP(U3copy_to_user)
+	ULTRA3_PCACHE_DO_NOP(cheetah_copy_user_page)
+#if 0
+pcache_disabled:
+#endif
 	retl
 	 nop
 #undef BRANCH_ALWAYS
diff -Nru a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S
--- a/arch/sparc64/lib/blockops.S	Fri Oct 18 21:03:03 2002
+++ b/arch/sparc64/lib/blockops.S	Fri Oct 18 21:03:03 2002
@@ -9,6 +9,8 @@
 #include <asm/visasm.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <asm/dcu.h>
+#include <asm/spitfire.h>
 #include <asm/pgtable.h>
 
 #define TOUCH(reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7)	\
@@ -111,6 +113,15 @@
 	 nop
 
 cheetah_copy_user_page:
+	.globl		cheetah_copy_user_page_nop_1_6
+cheetah_copy_user_page_nop_1_6:
+	ldxa		[%g0] ASI_DCU_CONTROL_REG, %g3
+	sethi		%uhi(DCU_PE), %o2
+	sllx		%o2, 32, %o2
+	or		%g3, %o2, %o2
+	stxa		%o2, [%g0] ASI_DCU_CONTROL_REG	! Enable P-cache
+	membar		#Sync
+
 	sethi		%hi((PAGE_SIZE/64)-7), %o2	! A0 Group
 	prefetch	[%o1 + 0x000], #one_read	! MS
 	or		%o2, %lo((PAGE_SIZE/64)-7), %o2	! A1 Group
@@ -202,6 +213,11 @@
 	fmovd		%f12, %f44			! FGA Group
 	fmovd		%f14, %f46			! FGA Group
 	stda		%f32, [%o0] ASI_BLK_P		! MS
+	.globl		cheetah_copy_user_page_nop_2_3
+cheetah_copy_user_page_nop_2_3:
+	mov		PRIMARY_CONTEXT, %o2
+	stxa		%g0, [%o2] ASI_DMMU		! Flush P-cache
+	stxa		%g3, [%g0] ASI_DCU_CONTROL_REG	! Disable P-cache
 	ba,a,pt		%xcc, copy_user_page_continue
 
 spitfire_copy_user_page:
diff -Nru a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
--- a/arch/sparc64/solaris/socket.c	Fri Oct 18 21:03:06 2002
+++ b/arch/sparc64/solaris/socket.c	Fri Oct 18 21:03:06 2002
@@ -248,31 +248,6 @@
 					   24 for IPv6,
 					   about 80 for AX.25 */
 
-extern __inline__ struct socket *sockfd_lookup(int fd, int *err)
-{
-	struct file *file;
-	struct inode *inode;
-
-	if (!(file = fget(fd))) {
-		*err = -EBADF;
-		return NULL;
-	}
-
-	inode = file->f_dentry->d_inode;
-	if (!inode->i_sock) {
-		*err = -ENOTSOCK;
-		fput(file);
-		return NULL;
-	}
-
-	return SOCKET_I(inode);
-}
-
-extern __inline__ void sockfd_put(struct socket *sock)
-{
-	fput(sock->file);
-}
-
 struct sol_nmsghdr {
 	u32		msg_name;
 	int		msg_namelen;
diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
--- a/arch/sparc64/vmlinux.lds.S	Fri Oct 18 21:03:08 2002
+++ b/arch/sparc64/vmlinux.lds.S	Fri Oct 18 21:03:08 2002
@@ -40,11 +40,11 @@
   __stop___kallsyms = .;
   . = ALIGN(8192);
   __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
+  .init.text : { *(.init.text) }
+  .init.data : { *(.init.data) }
   . = ALIGN(16);
   __setup_start = .;
-  .setup_init : { *(.setup.init) }
+  .init.setup : { *(.init.setup) }
   __setup_end = .;
   __initcall_start = .;
   .initcall.init : {
diff -Nru a/arch/um/Makefile b/arch/um/Makefile
--- a/arch/um/Makefile	Fri Oct 18 21:03:05 2002
+++ b/arch/um/Makefile	Fri Oct 18 21:03:05 2002
@@ -70,7 +70,7 @@
 vmlinux: $(ARCH_DIR)/main.o 
 
 
-$(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S
+$(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S scripts FORCE
 	$(call if_changed_dep,as_s_S)
 
 AFLAGS_uml.lds.o = -U$(SUBARCH) -DSTART=$$(($(TOP_ADDR) - $(SIZE))) \
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	Fri Oct 18 21:03:04 2002
+++ b/arch/um/drivers/ubd_kern.c	Fri Oct 18 21:03:04 2002
@@ -51,22 +51,19 @@
 static int ubd_release(struct inode * inode, struct file * file);
 static int ubd_ioctl(struct inode * inode, struct file * file,
 		     unsigned int cmd, unsigned long arg);
-static int ubd_revalidate(kdev_t rdev);
+static int ubd_revalidate(struct gendisk *disk);
 
 #define MAX_DEV (8)
-#define MAX_MINOR (MAX_DEV << UBD_SHIFT)
-
-#define DEVICE_NR(n) (minor(n) >> UBD_SHIFT)
 
 static struct block_device_operations ubd_blops = {
-        .open =		ubd_open,
-        .release =	ubd_release,
-        .ioctl =	ubd_ioctl,
-        .revalidate =	ubd_revalidate,
+        .open		= ubd_open,
+        .release	= ubd_release,
+        .ioctl		= ubd_ioctl,
+        .revalidate_disk= ubd_revalidate,
 };
 
 /* Protected by the queue_lock */
-static request_queue_t *ubd_queue;
+static request_queue_t ubd_queue;
 
 /* Protected by ubd_lock */
 static int fake_major = 0;
@@ -347,30 +344,31 @@
  */
 int intr_count = 0;
 
-static void ubd_finish(int error)
+static void ubd_finish(struct request *req, int error)
 {
 	int nsect;
 
 	if(error){
  		spin_lock(&ubd_io_lock);
-		end_request(CURRENT, 0);
+		end_request(req, 0);
  		spin_unlock(&ubd_io_lock);
 		return;
 	}
-	nsect = CURRENT->current_nr_sectors;
-	CURRENT->sector += nsect;
-	CURRENT->buffer += nsect << 9;
-	CURRENT->errors = 0;
-	CURRENT->nr_sectors -= nsect;
-	CURRENT->current_nr_sectors = 0;
+	nsect = req->current_nr_sectors;
+	req->sector += nsect;
+	req->buffer += nsect << 9;
+	req->errors = 0;
+	req->nr_sectors -= nsect;
+	req->current_nr_sectors = 0;
 	spin_lock(&ubd_io_lock);
-	end_request(CURRENT, 1);
+	end_request(req, 1);
 	spin_unlock(&ubd_io_lock);
 }
 
 static void ubd_handler(void)
 {
 	struct io_thread_req req;
+	struct request *rq = elv_next_request(&ubd_queue);
 	int n;
 
 	do_ubd = NULL;
@@ -380,18 +378,18 @@
 		printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
 		       "errno = %d\n", os_getpid(), -n);
 		spin_lock(&ubd_io_lock);
-		end_request(CURRENT, 0);
+		end_request(rq, 0);
 		spin_unlock(&ubd_io_lock);
 		return;
 	}
         
-        if((req.offset != ((__u64) (CURRENT->sector)) << 9) ||
-	   (req.length != (CURRENT->current_nr_sectors) << 9))
+        if((req.offset != ((__u64) (rq->sector)) << 9) ||
+	   (req.length != (rq->current_nr_sectors) << 9))
 		panic("I/O op mismatch");
 	
-	ubd_finish(req.error);
+	ubd_finish(rq, req.error);
 	reactivate_fd(thread_fd, UBD_IRQ);	
-	do_ubd_request(ubd_queue);
+	do_ubd_request(&ubd_queue);
 }
 
 static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
@@ -483,9 +481,13 @@
 			goto out_unregister;
 
  		ubd_dev[n].fake = fake;
+		fake_disk->private_data = &ubd_dev[n];
+		fake_disk->queue = &ubd_queue;
 		add_disk(fake_disk);
 	}
  
+	disk->private_data = &ubd_dev[n];
+	disk->queue = &ubd_queue;
 	add_disk(disk);
 	make_ide_entries(disk->disk_name);
 	return(0);
@@ -574,11 +576,6 @@
 
 __initcall(ubd_mc_init);
 
-static request_queue_t *ubd_get_queue(kdev_t device)
-{
-	return(ubd_queue);
-}
-
 int ubd_init(void)
 {
         int i;
@@ -588,9 +585,8 @@
 		printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
 		return -1;
 	}
-	ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
-	blk_init_queue(ubd_queue, do_ubd_request, &ubd_io_lock);
-	elevator_init(ubd_queue, &elevator_noop);
+	blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock);
+	elevator_init(&ubd_queue, &elevator_noop);
 	if(fake_major != 0){
 		char name[sizeof("ubd_nnn\0")];
 
@@ -601,7 +597,6 @@
 			       fake_major);
 			return -1;
 		}
-		blk_dev[fake_major].queue = ubd_get_queue;
 	}
 	for(i = 0; i < MAX_DEV; i++) 
 		ubd_add(i);
@@ -698,8 +693,8 @@
 
 static int ubd_open(struct inode *inode, struct file *filp)
 {
-	int n = DEVICE_NR(inode->i_rdev);
-	struct ubd *dev = &ubd_dev[n];
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct ubd *dev = disk->private_data;
 	int err;
 	if(dev->is_dir == 1)
 		goto out;
@@ -709,8 +704,8 @@
 
 		err = ubd_open_dev(dev);
 		if(err){
-			printk(KERN_ERR "ubd%d: Can't open \"%s\": "
-			       "errno = %d\n", n, dev->file, -err);
+			printk(KERN_ERR "%s: Can't open \"%s\": "
+			       "errno = %d\n", disk->disk_name, dev->file, -err);
 			goto out;
 		}
 	}
@@ -725,9 +720,10 @@
 
 static int ubd_release(struct inode * inode, struct file * file)
 {
-        int n = DEVICE_NR(inode->i_rdev);
-	if(--ubd_dev[n].count == 0)
-		ubd_close(&ubd_dev[n]);
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct ubd *dev = disk->private_data;
+	if(dev->count == 0)
+		ubd_close(dev);
 	return(0);
 }
 
@@ -771,15 +767,13 @@
 
 static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
-	struct ubd *dev;
+	struct gendisk *disk = req->rq_disk;
+	struct ubd *dev = disk->private_data;
 	__u64 block;
-	int nsect, min, n;
+	int nsect;
 
-	if(req->rq_status == RQ_INACTIVE) return(1);
+	if (req->rq_status == RQ_INACTIVE) return(1);
 
-	min = minor(req->rq_dev);
-	n = min >> UBD_SHIFT;
-	dev = &ubd_dev[n];
 	if(dev->is_dir){
 		strcpy(req->buffer, "HOSTFS:");
 		strcat(req->buffer, dev->file);
@@ -790,7 +784,7 @@
 	}
 
 	if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
-		printk("Write attempted on readonly ubd device %d\n", n);
+		printk("Write attempted on readonly ubd device %s\n", disk->disk_name);
  		spin_lock(&ubd_io_lock);
 		end_request(req, 0);
  		spin_unlock(&ubd_io_lock);
@@ -829,7 +823,7 @@
 			err = prepare_request(req, &io_req);
 			if(!err){
 				do_io(&io_req);
-				ubd_finish(io_req.error);
+				ubd_finish(req, io_req.error);
 			}
 		}
 	}
@@ -852,21 +846,15 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
+	struct ubd *dev = inode->i_bdev->bd_disk->private_data;
+	int err;
  	struct ubd *dev;
-	int n, min, err;
 	struct hd_driveid ubd_id = {
 		.cyls =		0,
 		.heads =	128,
 		.sectors =	32,
 	};
 
-
-        if(!inode) return(-EINVAL);
-	min = minor(inode->i_rdev);
-	n = min >> UBD_SHIFT;
-	if(n > MAX_DEV)
-		return(-EINVAL);
-	dev = &ubd_dev[n];
 	switch (cmd) {
 	        struct hd_geometry g;
 		struct cdrom_volctrl volume;
@@ -880,7 +868,7 @@
 
 	case HDIO_SET_UNMASKINTR:
 		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if((arg > 1) || (min & ((1 << UBD_SHIFT) - 1)))
+		if((arg > 1) || inode->i_bdev->bd_contains != inode->i_bdev)
 			return(-EINVAL);
 		return(0);
 
@@ -900,7 +888,7 @@
 
 	case HDIO_SET_MULTCOUNT:
 		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if(min & ((1 << UBD_SHIFT) - 1))
+		if (inode->i_bdev->bd_contains != inode->i_bdev)
 			return(-EINVAL);
 		return(0);
 
@@ -925,14 +913,11 @@
 	return(-EINVAL);
 }
 
-static int ubd_revalidate(kdev_t rdev)
+static int ubd_revalidate(struct gendisk *disk)
 {
 	__u64 size;
-	int n, err;
-	struct ubd *dev;
-
-	n = minor(rdev) >> UBD_SHIFT;
-	dev = &ubd_dev[n];
+	int err;
+	struct ubd *dev = disk->private_data;
 
 	err = 0;
 	spin_lock(&ubd_lock);
@@ -941,9 +926,7 @@
 	
 	err = ubd_file_size(dev, &size);
 	if (!err) {
-		set_capacity(ubd_gendisk[n], size / 512);
-		if(fake_major != 0)
-			set_capacity(fake_gendisk[n], size / 512);
+		set_capacity(disk, size / 512);
 		dev->size = size;
 	}
  out:
diff -Nru a/arch/x86_64/Config.help b/arch/x86_64/Config.help
--- a/arch/x86_64/Config.help	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/Config.help	Fri Oct 18 21:03:03 2002
@@ -435,6 +435,14 @@
   with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
   /dev/cpu/31/cpuid.
 
+CONFIG_NR_CPUS
+  This allows you to specify the maximum number of CPUs which this
+  kernel will support.  The maximum supported value is 32 and the
+  minimum value which makes sense is 2.
+
+  This is purely to save memory - each supported CPU adds
+  approximately eight kilobytes to the kernel image.
+
 CONFIG_PREEMPT
   This option reduces the latency of the kernel when reacting to
   real-time or interactive events by allowing a low priority process to
@@ -487,10 +495,6 @@
   Enables some internal consistency checks for kernel debugging.
   You should normally say N.
 
-CONFIG_SIMNOW
-  Disable some time consuming optional things for slow CPU simulators.
-  Say N unless you're running on a slow simulator like Simics or SimNow. 
-
 CONFIG_EARLY_PRINTK
   Write kernel log output directly into the VGA buffer. This is useful
   for kernel debugging when your machine crashes very early before
@@ -499,13 +503,26 @@
   klogd/syslogd or the X server.You should normally N here, unless
   you want to debug such a crash.
   
-CONFIG_X86_MCE_NONFATAL
-  Enabling this feature starts a timer that triggers every 5 seconds which
-  will look at the machine check registers to see if anything happened.
-  Non-fatal problems automatically get corrected (but still logged).
-  Disable this if you don't want to see these messages.
-  Seeing the messages this option prints out may be indicative of dying hardware,
-  or out-of-spec (ie, overclocked) hardware.
-  This option only does something on hardware with Intel P6 style MCE.
-  (Pentium Pro and above, AMD Athlon/Duron)
+CONFIG_KALLSYMS
+  Say Y here to let the kernel print out symbolic crash information and
+  symbolic stack backtraces. This increases the size of the kernel
+  somewhat, as all symbols have to be loaded into the kernel image.
+
+CONFIG_INIT_DEBUG
+  Fill __init and __initdata at the end of boot. This is only for debugging.
+
+CONFIG_IA32_EMULATION
+  Include code to run 32bit programs under an 64bit kernel. You should likely
+  turn this on, unless you're 100% sure that you don't have any 32bit programs
+  left.
+
+CONFIG_GART_IOMMU
+  Support the K8 IOMMU. Needed to run systems with more than 4GB of memory
+  properly with 32bit devices. You should probably turn this on.
+  The iommu can be turned off at runtime with the iommu=off parameter.
+
+CONFIG_DUMMY_IOMMU
+  Don't use IOMMU code. This will cause problems when you have more than 4GB 
+  of memory and any 32bit devices. Don't turn on unless you know what you
+  are doing.
 
diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile
--- a/arch/x86_64/Makefile	Fri Oct 18 21:03:08 2002
+++ b/arch/x86_64/Makefile	Fri Oct 18 21:03:08 2002
@@ -33,7 +33,7 @@
 export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP
 
 
-LD=$(CROSS_COMPILE)ld -m elf_x86_64
+LDFLAGS		:= -m elf_x86_64
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux := -e stext
 
@@ -47,51 +47,38 @@
 
 HEAD := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
 
-SUBDIRS += arch/x86_64/kernel arch/x86_64/mm arch/x86_64/lib
-CORE_FILES := arch/x86_64/kernel/kernel.o $(CORE_FILES)
-CORE_FILES +=  arch/x86_64/mm/mm.o
-LIBS := $(TOPDIR)/arch/x86_64/lib/lib.a $(LIBS)
-
-ifdef CONFIG_IA32_EMULATION
-SUBDIRS += arch/x86_64/ia32
-CORE_FILES += arch/x86_64/ia32/ia32.o
-endif
-
-ifdef CONFIG_PCI
-SUBDIRS += arch/x86_64/pci
-DRIVERS += arch/x86_64/pci/pci.o
-endif
-
-CORE_FILES += $(core-y)
+libs-y 					+= arch/x86_64/lib/
+core-y					+= arch/x86_64/kernel/ arch/x86_64/mm/
+core-$(CONFIG_IA32_EMULATION)		+= arch/x86_64/ia32/
+drivers-$(CONFIG_PCI)			+= arch/x86_64/pci/
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+makeboot = $(call descend,arch/x86_64/boot,$(1))
 
 .PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
 		clean archclean archmrproper
 
-bzImage: vmlinux
-	@$(MAKEBOOT) bzImage
+BOOTIMAGE=arch/x86_64/boot/bzImage
+zImage zlilo zdisk: BOOTIMAGE=arch/x86_64/boot/zImage
 
-bzImage-padded: vmlinux
-	@$(MAKEBOOT) bzImage-padded
+zImage bzImage: vmlinux
+	+@$(call makeboot,$(BOOTIMAGE))
 
-tmp:
-	@$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
+compressed: zImage
 
-bzlilo: vmlinux
-	@$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
+zlilo bzlilo: vmlinux
+	+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zlilo)
 
-bzdisk: vmlinux
-	@$(MAKEBOOT) BOOTIMAGE=bzImage zdisk
+zdisk bzdisk: vmlinux
+	+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zdisk)
 
 install: vmlinux
-	@$(MAKEBOOT) BOOTIMAGE=bzImage install
+	+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install)
 
 archclean:
-	@$(MAKEBOOT) clean
+	+@$(call makeboot,clean)
 
 archmrproper:
-
 
 prepare: include/asm-$(ARCH)/offset.h
 
diff -Nru a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c
--- a/arch/x86_64/boot/compressed/misc.c	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/boot/compressed/misc.c	Fri Oct 18 21:03:04 2002
@@ -190,7 +190,7 @@
 	outb_p(0xff & (pos >> 1), vidport+1);
 }
 
-void* memset(void* s, int c, size_t n)
+void* memset(void* s, int c, unsigned n)
 {
 	int i;
 	char *ss = (char*)s;
@@ -199,14 +199,13 @@
 	return s;
 }
 
-void* memcpy(void* __dest, __const void* __src,
-			    size_t __n)
+void* memcpy(void* dest, const void* src, unsigned n)
 {
 	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
+	char *d = (char *)dest, *s = (char *)src;
 
-	for (i=0;i<__n;i++) d[i] = s[i];
-	return __dest;
+	for (i=0;i<n;i++) d[i] = s[i];
+	return dest;
 }
 
 /* ===========================================================================
diff -Nru a/arch/x86_64/config.in b/arch/x86_64/config.in
--- a/arch/x86_64/config.in	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/config.in	Fri Oct 18 21:03:03 2002
@@ -21,6 +21,7 @@
 define_bool CONFIG_X86_CMPXCHG y
 
 define_bool CONFIG_EARLY_PRINTK y
+define_bool CONFIG_GENERIC_ISA_DMA y
 
 source init/Config.in
 
@@ -54,11 +55,17 @@
 fi
 if [ "$CONFIG_SMP" = "y" ]; then
     define_bool CONFIG_HAVE_DEC_LOCK y
+    # actually 64 maximum, but you need to fix the APIC code first
+    # to use clustered mode or whatever your big iron needs
     int  'Maximum number of CPUs (2-8)' CONFIG_NR_CPUS 8
 fi
 
+bool 'IOMMU support' CONFIG_GART_IOMMU
+if [ "$CONFIG_GART_IOMMU" != "y" ]; then
+   define_bool CONFIG_DUMMY_IOMMU y
+fi
+
 define_bool CONFIG_X86_MCE y
-bool 'Check for non-fatal machine check errors' CONFIG_X86_MCE_NONFATAL $CONFIG_X86_MCE
 
 endmenu
 
@@ -108,22 +115,20 @@
 
 bool 'IA32 Emulation' CONFIG_IA32_EMULATION
 
+
+
 endmenu
 
 source drivers/mtd/Config.in
 
 source drivers/parport/Config.in
 
-#source drivers/pnp/Config.in
-
 source drivers/block/Config.in
 
-source drivers/md/Config.in
-
 mainmenu_option next_comment
 comment 'ATA/ATAPI/MFM/RLL support'
 
-tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL device support' CONFIG_IDE
 
 if [ "$CONFIG_IDE" != "n" ]; then
   source drivers/ide/Config.in
@@ -133,15 +138,19 @@
 endmenu
 
 mainmenu_option next_comment
-comment 'SCSI support'
+comment 'SCSI device support'
 
-tristate 'SCSI support' CONFIG_SCSI
+tristate 'SCSI device support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
    source drivers/scsi/Config.in
 fi
 endmenu
 
+source drivers/md/Config.in
+
+source drivers/telephony/Config.in
+
 source drivers/message/fusion/Config.in
 
 source drivers/ieee1394/Config.in
@@ -172,8 +181,6 @@
 
 source drivers/isdn/Config.in
 
-source drivers/telephony/Config.in
-
 # no support for non IDE/SCSI cdroms as they were all ISA only
 
 #
@@ -224,6 +231,8 @@
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
    bool '  Additional run-time checks' CONFIG_CHECKING
    bool '  Debug __init statements' CONFIG_INIT_DEBUG
+   bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   bool '  Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
 fi
 endmenu
 
diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig
--- a/arch/x86_64/defconfig	Fri Oct 18 21:03:07 2002
+++ b/arch/x86_64/defconfig	Fri Oct 18 21:03:07 2002
@@ -1,5 +1,5 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 CONFIG_X86_64=y
 CONFIG_X86=y
@@ -10,6 +10,7 @@
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_X86_CMPXCHG=y
 CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
 
 #
 # Code maturity level options
@@ -47,11 +48,12 @@
 # CONFIG_EISA is not set
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
 CONFIG_SMP=y
 CONFIG_HAVE_DEC_LOCK=y
-CONFIG_X86_MCE=y
-# CONFIG_X86_MCE_NONFATAL is not set
 CONFIG_NR_CPUS=8
+CONFIG_GART_IOMMU=y
+CONFIG_X86_MCE=y
 
 #
 # Power management options
@@ -61,7 +63,25 @@
 #
 # ACPI Support
 #
-# CONFIG_ACPI is not set
+CONFIG_ACPI=y
+# CONFIG_ACPI_HT_ONLY is not set
+CONFIG_ACPI_BOOT=y
+# CONFIG_ACPI_SLEEP is not set
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_TOSHIBA=y
+CONFIG_ACPI_DEBUG=y
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
 
 #
 # Bus options (PCI etc.)
@@ -106,81 +126,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_LBD=y
 
 #
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#  
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Telephony Support
+# ATA/ATAPI/MFM/RLL support
 #
-# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
-# CONFIG_PHONE_IXJ_PCMCIA is not set
+CONFIG_IDE=y
 
 #
-# ATA/IDE/MFM/RLL support
+# IDE, ATA and ATAPI Block devices
 #
-CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
 
 #
-# ATA and ATAPI Block devices
+# Please see Documentation/ide.txt for help/info on IDE drives
 #
-CONFIG_BLK_DEV_IDE=y
 # CONFIG_BLK_DEV_HD_IDE is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
@@ -188,27 +148,35 @@
 # CONFIG_IDEDISK_STROKE is not set
 # CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_BLK_DEV_IDE_TCQ is not set
 # CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC6280_BURST is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 CONFIG_BLK_DEV_AMD74XX=y
+# CONFIG_AMD74XX_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
@@ -216,88 +184,58 @@
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NFORCE is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_PDC202XX_BURST is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_IDE_CHIPSETS is not set
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_ATAPI=y
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_DMA_NONPCI is not set
+CONFIG_BLK_DEV_IDE_MODES=y
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+# CONFIG_PHONE_IXJ_PCMCIA is not set
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_BOOT is not set
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LAN is not set
 
 #
 # IEEE 1394 (FireWire) support (EXPERIMENTAL)
@@ -305,6 +243,53 @@
 # CONFIG_IEEE1394 is not set
 
 #
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+# CONFIG_NETFILTER is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -339,6 +324,11 @@
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_PCI is not set
@@ -350,6 +340,7 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
+# CONFIG_E1000_NAPI is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -381,11 +372,6 @@
 # CONFIG_WAN is not set
 
 #
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-
-#
 # Amateur Radio support
 #
 # CONFIG_HAMRADIO is not set
@@ -403,31 +389,106 @@
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_GAMEPORT_NS558 is not set
 # CONFIG_GAMEPORT_L4 is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_GAMEPORT_PCIGAME is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
 # CONFIG_GAMEPORT_FM801 is not set
 # CONFIG_GAMEPORT_CS461x is not set
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+# CONFIG_INPUT_JOYDUMP is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT_PCSPKR is not set
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_HW_CONSOLE=y
 # CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_CS is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
 
@@ -440,10 +501,6 @@
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -451,6 +508,7 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_AMD_RNG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
 # CONFIG_DTLK is not set
@@ -462,9 +520,18 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
+CONFIG_AGP=y
+# CONFIG_AGP_INTEL is not set
+# CONFIG_AGP_I810 is not set
+# CONFIG_AGP_VIA is not set
+# CONFIG_AGP_AMD is not set
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_ALI is not set
+# CONFIG_AGP_SWORKS is not set
 # CONFIG_DRM is not set
 # CONFIG_MWAVE is not set
+# CONFIG_SCx200_GPIO is not set
+CONFIG_RAW_DRIVER=y
 
 #
 # Misc devices
@@ -504,7 +571,7 @@
 # CONFIG_CRAMFS is not set
 CONFIG_TMPFS=y
 CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
+CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
 # CONFIG_JFS_FS is not set
@@ -530,6 +597,9 @@
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
 
 #
 # Network File Systems
@@ -537,14 +607,18 @@
 # CONFIG_CODA_FS is not set
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -555,6 +629,7 @@
 # CONFIG_NCPFS_SMALLDOS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_AFS_FS is not set
 # CONFIG_ZISOFS_FS is not set
 
 #
@@ -590,7 +665,7 @@
 #
 # Bluetooth support
 #
-# CONFIG_BLUEZ is not set
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
@@ -599,8 +674,15 @@
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_CHECKING is not set
+CONFIG_CHECKING=y
 # CONFIG_INIT_DEBUG is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY_CAPABILITIES=y
 
 #
 # Library routines
diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
--- a/arch/x86_64/ia32/ia32_binfmt.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/ia32/ia32_binfmt.c	Fri Oct 18 21:03:03 2002
@@ -25,7 +25,7 @@
 
 #define IA32_EMULATOR 1
 
-#define IA32_PAGE_OFFSET 0xE0000000
+#define IA32_PAGE_OFFSET 0xffff0000
 #define IA32_STACK_TOP IA32_PAGE_OFFSET
 #define ELF_ET_DYN_BASE		(IA32_PAGE_OFFSET/3 + 0x1000000)
 
@@ -216,13 +216,15 @@
 extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address);
  
 
-int ia32_setup_arg_pages(struct linux_binprm *bprm)
+int setup_arg_pages(struct linux_binprm *bprm)
 {
 	unsigned long stack_base;
 	struct vm_area_struct *mpnt;
+	struct mm_struct *mm = current->mm;
 	int i;
 
-	stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
+	stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+	mm->arg_start = bprm->p + stack_base;
 
 	bprm->p += stack_base;
 	if (bprm->loader)
@@ -233,9 +235,14 @@
 	if (!mpnt) 
 		return -ENOMEM; 
 	
-	down_write(&current->mm->mmap_sem);
+	if (!vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+		kmem_cache_free(vm_area_cachep, mpnt);
+		return -ENOMEM;
+	}
+
+	down_write(&mm->mmap_sem);
 	{
-		mpnt->vm_mm = current->mm;
+		mpnt->vm_mm = mm;
 		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
 		mpnt->vm_end = IA32_STACK_TOP;
 		mpnt->vm_page_prot = PAGE_COPY;
@@ -243,24 +250,25 @@
 		mpnt->vm_ops = NULL;
 		mpnt->vm_pgoff = 0;
 		mpnt->vm_file = NULL;
+		INIT_LIST_HEAD(&mpnt->shared);
 		mpnt->vm_private_data = (void *) 0;
-		insert_vm_struct(current->mm, mpnt);
-		current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+		insert_vm_struct(mm, mpnt);
+		mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
 	} 
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
 		struct page *page = bprm->page[i];
 		if (page) {
 			bprm->page[i] = NULL;
-			current->mm->rss++;
 			put_dirty_page(current,page,stack_base);
 		}
 		stack_base += PAGE_SIZE;
 	}
-	up_write(&current->mm->mmap_sem);
+	up_write(&mm->mmap_sem);
 	
 	return 0;
 }
+
 static unsigned long
 elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
 {
diff -Nru a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
--- a/arch/x86_64/ia32/ia32_ioctl.c	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/ia32/ia32_ioctl.c	Fri Oct 18 21:03:04 2002
@@ -1,4 +1,4 @@
-/* $Id: ia32_ioctl.c,v 1.11 2002/04/18 14:36:37 ak Exp $
+/* $Id: ia32_ioctl.c,v 1.25 2002/10/11 07:17:06 ak Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -21,6 +21,7 @@
 #include <linux/hdreg.h>
 #include <linux/raid/md.h>
 #include <linux/kd.h>
+#include <linux/dirent.h>
 #include <linux/route.h>
 #include <linux/in6.h>
 #include <linux/ipv6_route.h>
@@ -55,7 +56,9 @@
 #include <linux/module.h>
 #include <linux/serial.h>
 #include <linux/reiserfs_fs.h>
+#include <linux/if_tun.h>
 #include <linux/dirent.h>
+#include <linux/ctype.h>
 #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
 /* Ugh. This header really is not clean */
 #define min min
@@ -74,8 +77,14 @@
 #include <asm/ia32.h>
 #include <asm/uaccess.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_bonding.h>
+#include <linux/watchdog.h>
+
 #include <asm/module.h>
+#include <asm/ioctl32.h>
 #include <linux/soundcard.h>
+#include <linux/lp.h>
 
 #include <linux/atm.h>
 #include <linux/atmarp.h>
@@ -88,6 +97,19 @@
 #include <linux/atm_tcp.h>
 #include <linux/sonet.h>
 #include <linux/atm_suni.h>
+#include <linux/mtd/mtd.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+
+#include <linux/usb.h>
+#include <linux/usbdevice_fs.h>
+#include <linux/nbd.h>
+#include <linux/random.h>
+#include <linux/filter.h>
+
+#include <asm/mtrr.h>
+
 
 #define A(__x) ((void *)(unsigned long)(__x))
 #define AA(__x)	A(__x)
@@ -114,7 +136,6 @@
 	return err;
 }
  
-#if 0 
 static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
@@ -130,7 +151,6 @@
 		return -EFAULT;
 	return err;
 }
-#endif
 
 static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -443,6 +463,7 @@
         __kernel_caddr_t32  ifcbuf;
 };
 
+#ifdef CONFIG_NET
 static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct net_device *dev;
@@ -458,10 +479,12 @@
 
 	strncpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name)-1);
 	ifr32.ifr_name[sizeof(ifr32.ifr_name)-1] = 0; 
+	dev_put(dev);
 	
 	err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
 	return (err ? -EFAULT : 0);
 }
+#endif
 
 static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -558,9 +581,25 @@
 	}
 	switch (ethcmd) {
 	case ETHTOOL_GDRVINFO:	len = sizeof(struct ethtool_drvinfo); break;
+	case ETHTOOL_GMSGLVL:
+	case ETHTOOL_SMSGLVL:
+	case ETHTOOL_GLINK:
+	case ETHTOOL_NWAY_RST:  len = sizeof(struct ethtool_value); break;
+	case ETHTOOL_GREGS: {
+		struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data);
+		/* darned variable size arguments */
+		if (get_user(len, (u32 *)&regaddr->len)) {
+			err = -EFAULT;
+			goto out;
+		}
+		len += sizeof(struct ethtool_regs);
+		break;
+	}
 	case ETHTOOL_GSET:
-	case ETHTOOL_SSET:
-	default:		len = sizeof(struct ethtool_cmd); break;
+	case ETHTOOL_SSET:      len = sizeof(struct ethtool_cmd); break;
+	default:
+               err = -EOPNOTSUPP;
+               goto out;
 	}
 
 	if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
@@ -586,6 +625,91 @@
 	return err;
 }
 
+
+static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq ifr;
+	mm_segment_t old_fs;
+	int err, len;
+	u32 data;
+	
+	if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+		return -EFAULT;
+	ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL);
+	if (!ifr.ifr_data)
+		return -EAGAIN;
+
+	switch (cmd) {
+	case SIOCBONDENSLAVE:
+	case SIOCBONDRELEASE:
+	case SIOCBONDSETHWADDR:
+	case SIOCBONDCHANGEACTIVE:
+		len = IFNAMSIZ * sizeof(char);
+		break;
+	case SIOCBONDSLAVEINFOQUERY:
+		len = sizeof(struct ifslave);
+		break;
+	case SIOCBONDINFOQUERY:
+		len = sizeof(struct ifbond);
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	};
+
+	__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+	if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+	if (!err) {
+		len = copy_to_user((char *)A(data), ifr.ifr_data, len);
+		if (len)
+			err = -EFAULT;
+	}
+
+out:
+	free_page((unsigned long)ifr.ifr_data);
+	return err;
+}
+
+static __inline__ void *alloc_user_space(long len)
+{
+	struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs); 
+	return (void *)regs->rsp - len; 
+}
+
+static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq *u_ifreq64;
+	struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg;
+	char tmp_buf[IFNAMSIZ];
+	void *data64;
+	u32 data32;
+
+	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
+			   IFNAMSIZ))
+		return -EFAULT;
+	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
+		return -EFAULT;
+	data64 = (void *) A(data32);
+
+	u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
+
+	/* Don't check these user accesses, just let that get trapped
+	 * in the ioctl handler instead.
+	 */
+	copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ);
+	__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data);
+
+	return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64);
+}
+
 static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq ifr;
@@ -604,15 +728,6 @@
 		if (err)
 			return -EFAULT;
 		break;
-	case SIOCGPPPSTATS:
-	case SIOCGPPPCSTATS:
-	case SIOCGPPPVER:
-		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-			return -EFAULT;
-		ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL);
-		if (!ifr.ifr_data)
-			return -EAGAIN;
-		break;
 	default:
 		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
 			return -EFAULT;
@@ -638,27 +753,6 @@
 			if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
 				return -EFAULT;
 			break;
-		case SIOCGPPPSTATS:
-		case SIOCGPPPCSTATS:
-		case SIOCGPPPVER:
-		{
-			u32 data;
-			int len;
-
-			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-			if(cmd == SIOCGPPPVER)
-				len = strlen((char *)ifr.ifr_data) + 1;
-			else if(cmd == SIOCGPPPCSTATS)
-				len = sizeof(struct ppp_comp_stats);
-			else
-				len = sizeof(struct ppp_stats);
-
-			len = copy_to_user((char *)A(data), ifr.ifr_data, len);
-			free_page((unsigned long)ifr.ifr_data);
-			if(len)
-				return -EFAULT;
-			break;
-		}
 		case SIOCGIFMAP:
 			err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name));
 			err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
@@ -671,14 +765,6 @@
 				err = -EFAULT;
 			break;
 		}
-	} else {
-		switch (cmd) {
-		case SIOCGPPPSTATS:
-		case SIOCGPPPCSTATS:
-		case SIOCGPPPVER:
-			free_page((unsigned long)ifr.ifr_data);
-			break;
-		}
 	}
 	return err;
 }
@@ -715,8 +801,6 @@
 	s32			rtmsg_ifindex;
 };
 
-extern struct socket *sockfd_lookup(int fd, int *err);
-
 static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	int ret;
@@ -765,6 +849,9 @@
 	ret = sys_ioctl (fd, cmd, (long) r);
 	set_fs (old_fs);
 
+	if (mysock)
+		sockfd_put(mysock);
+
 	return ret;
 }
 
@@ -791,14 +878,6 @@
 	return err ? -EFAULT : 0;
 }
 
-struct  fbcmap32 {
-	int             index;          /* first element (0 origin) */
-	int             count;
-	u32		red;
-	u32		green;
-	u32		blue;
-};
-
 struct fb_fix_screeninfo32 {
 	char			id[16];
         __kernel_caddr_t32	smem_start;
@@ -882,7 +961,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("%s: Unknown fb ioctl cmd fd(%d) "
 				       "cmd(%08x) arg(%08lx)\n",
@@ -1261,6 +1340,269 @@
 	return err;
 }
 
+
+typedef struct sg_io_hdr32 {
+	s32 interface_id;	/* [i] 'S' for SCSI generic (required) */
+	s32 dxfer_direction;	/* [i] data transfer direction  */
+	u8  cmd_len;		/* [i] SCSI command length ( <= 16 bytes) */
+	u8  mx_sb_len;		/* [i] max length to write to sbp */
+	u16 iovec_count;	/* [i] 0 implies no scatter gather */
+	u32 dxfer_len;		/* [i] byte count of data transfer */
+	u32 dxferp;		/* [i], [*io] points to data transfer memory
+					      or scatter gather list */
+	u32 cmdp;		/* [i], [*i] points to command to perform */
+	u32 sbp;		/* [i], [*o] points to sense_buffer memory */
+	u32 timeout;		/* [i] MAX_UINT->no timeout (unit: millisec) */
+	u32 flags;		/* [i] 0 -> default, see SG_FLAG... */
+	s32 pack_id;		/* [i->o] unused internally (normally) */
+	u32 usr_ptr;		/* [i->o] unused internally */
+	u8  status;		/* [o] scsi status */
+	u8  masked_status;	/* [o] shifted, masked scsi status */
+	u8  msg_status;		/* [o] messaging level data (optional) */
+	u8  sb_len_wr;		/* [o] byte count actually written to sbp */
+	u16 host_status;	/* [o] errors from host adapter */
+	u16 driver_status;	/* [o] errors from software driver */
+	s32 resid;		/* [o] dxfer_len - actual_transferred */
+	u32 duration;		/* [o] time taken by cmd (unit: millisec) */
+	u32 info;		/* [o] auxiliary information */
+} sg_io_hdr32_t;  /* 64 bytes long (on sparc32) */
+
+typedef struct sg_iovec32 {
+	u32 iov_base;
+	u32 iov_len;
+} sg_iovec32_t;
+
+static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+{
+	sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
+	sg_iovec_t *kiov;
+	int i;
+
+	sgp->dxferp = kmalloc(sgp->iovec_count *
+			      sizeof(sg_iovec_t), GFP_KERNEL);
+	if (!sgp->dxferp)
+		return -ENOMEM;
+	memset(sgp->dxferp, 0,
+	       sgp->iovec_count * sizeof(sg_iovec_t));
+
+	kiov = (sg_iovec_t *) sgp->dxferp;
+	for (i = 0; i < sgp->iovec_count; i++) {
+		u32 iov_base32;
+		if (__get_user(iov_base32, &uiov->iov_base) ||
+		    __get_user(kiov->iov_len, &uiov->iov_len))
+			return -EFAULT;
+
+		kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
+		if (!kiov->iov_base)
+			return -ENOMEM;
+		if (copy_from_user(kiov->iov_base,
+				   (void *) A(iov_base32),
+				   kiov->iov_len))
+			return -EFAULT;
+
+		uiov++;
+		kiov++;
+	}
+
+	return 0;
+}
+
+static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+{
+	sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
+	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
+	int i;
+
+	for (i = 0; i < sgp->iovec_count; i++) {
+		u32 iov_base32;
+
+		if (__get_user(iov_base32, &uiov->iov_base))
+			return -EFAULT;
+
+		if (copy_to_user((void *) A(iov_base32),
+				 kiov->iov_base,
+				 kiov->iov_len))
+			return -EFAULT;
+
+		uiov++;
+		kiov++;
+	}
+
+	return 0;
+}
+
+static void free_sg_iovec(sg_io_hdr_t *sgp)
+{
+	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
+	int i;
+
+	for (i = 0; i < sgp->iovec_count; i++) {
+		if (kiov->iov_base) {
+			kfree(kiov->iov_base);
+			kiov->iov_base = NULL;
+		}
+		kiov++;
+	}
+	kfree(sgp->dxferp);
+	sgp->dxferp = NULL;
+}
+
+static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	sg_io_hdr32_t *sg_io32;
+	sg_io_hdr_t sg_io64;
+	u32 dxferp32, cmdp32, sbp32;
+	mm_segment_t old_fs;
+	int err = 0;
+
+	sg_io32 = (sg_io_hdr32_t *)arg;
+	err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
+	err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
+	err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
+	err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
+	err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
+	err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
+	err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
+	err |= __get_user(sg_io64.flags, &sg_io32->flags);
+	err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
+
+	sg_io64.dxferp = NULL;
+	sg_io64.cmdp = NULL;
+	sg_io64.sbp = NULL;
+
+	err |= __get_user(cmdp32, &sg_io32->cmdp);
+	sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
+	if (!sg_io64.cmdp) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(sg_io64.cmdp,
+			   (void *) A(cmdp32),
+			   sg_io64.cmd_len)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	err |= __get_user(sbp32, &sg_io32->sbp);
+	sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
+	if (!sg_io64.sbp) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(sg_io64.sbp,
+			   (void *) A(sbp32),
+			   sg_io64.mx_sb_len)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	err |= __get_user(dxferp32, &sg_io32->dxferp);
+	if (sg_io64.iovec_count) {
+		int ret;
+
+		if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
+			err = ret;
+			goto out;
+		}
+	} else {
+		sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
+		if (!sg_io64.dxferp) {
+			err = -ENOMEM;
+			goto out;
+		}
+		if (copy_from_user(sg_io64.dxferp,
+				   (void *) A(dxferp32),
+				   sg_io64.dxfer_len)) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+
+	/* Unused internally, do not even bother to copy it over. */
+	sg_io64.usr_ptr = NULL;
+
+	if (err)
+		return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
+	set_fs (old_fs);
+
+	if (err < 0)
+		goto out;
+
+	err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
+	err |= __put_user(sg_io64.status, &sg_io32->status);
+	err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
+	err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
+	err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
+	err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
+	err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
+	err |= __put_user(sg_io64.resid, &sg_io32->resid);
+	err |= __put_user(sg_io64.duration, &sg_io32->duration);
+	err |= __put_user(sg_io64.info, &sg_io32->info);
+	err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
+	if (sg_io64.dxferp) {
+		if (sg_io64.iovec_count)
+			err |= copy_back_sg_iovec(&sg_io64, dxferp32);
+		else
+			err |= copy_to_user((void *)A(dxferp32),
+					    sg_io64.dxferp,
+					    sg_io64.dxfer_len);
+	}
+	if (err)
+		err = -EFAULT;
+
+out:
+	if (sg_io64.cmdp)
+		kfree(sg_io64.cmdp);
+	if (sg_io64.sbp)
+		kfree(sg_io64.sbp);
+	if (sg_io64.dxferp) {
+		if (sg_io64.iovec_count) {
+			free_sg_iovec(&sg_io64);
+		} else {
+			kfree(sg_io64.dxferp);
+		}
+	}
+	return err;
+}
+
+struct sock_fprog32 {
+	__u16	len;
+	__u32	filter;
+};
+
+#define PPPIOCSPASS32	_IOW('t', 71, struct sock_fprog32)
+#define PPPIOCSACTIVE32	_IOW('t', 70, struct sock_fprog32)
+
+static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg;
+	struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog));
+	void *fptr64;
+	u32 fptr32;
+	u16 flen;
+
+	if (get_user(flen, &u_fprog32->len) ||
+	    get_user(fptr32, &u_fprog32->filter))
+		return -EFAULT;
+
+	fptr64 = (void *) A(fptr32);
+
+	if (put_user(flen, &u_fprog64->len) ||
+	    put_user(fptr64, &u_fprog64->filter))
+		return -EFAULT;
+
+	if (cmd == PPPIOCSPASS32)
+		cmd = PPPIOCSPASS;
+	else
+		cmd = PPPIOCSACTIVE;
+
+	return sys_ioctl(fd, cmd, (unsigned long) u_fprog64);
+}
+
 struct ppp_option_data32 {
 	__kernel_caddr_t32	ptr;
 	__u32			length;
@@ -1307,7 +1649,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("ppp_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -1417,7 +1759,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("mt_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -1535,7 +1877,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("cdrom_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -1622,7 +1964,7 @@
 		}
 		break;
 	default: {
-		static int count = 0;
+		static int count;
 		if (++count <= 20)
 			printk("%s: Unknown loop ioctl cmd, fd(%d) "
 			       "cmd(%08x) arg(%08lx)\n",
@@ -1651,9 +1993,9 @@
 	
 	/*
 	 * To have permissions to do most of the vt ioctls, we either have
-	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
+	 * to be the owner of the tty, or super-user.
 	 */
-	if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG))
+	if (current->tty == tty || capable(CAP_SYS_ADMIN))
 		return 1;
 	return 0;                                                    
 }
@@ -2023,6 +2365,7 @@
 	u32 pv[ABS_MAX_PV + 1];
 	u32 lv[ABS_MAX_LV + 1];
     	uint8_t vg_uuid[UUID_LEN+1];	/* volume group UUID */
+	uint8_t dummy1[200];
 } vg32_t;
 
 typedef struct {
@@ -2137,7 +2480,8 @@
 	lv_block_exception32_t *lbe32;
 	lv_block_exception_t *lbe;
 	lv32_t *ul = (lv32_t *)A(p);
-	lv_t *l = (lv_t *)kmalloc(sizeof(lv_t), GFP_KERNEL);
+	lv_t *l = (lv_t *) kmalloc(sizeof(lv_t), GFP_KERNEL);
+
 	if (!l) {
 		*errp = -ENOMEM;
 		return NULL;
@@ -2172,7 +2516,6 @@
                                err |= __get_user(lbe->rdev_org, &lbe32->rdev_org);
                                err |= __get_user(lbe->rsector_new, &lbe32->rsector_new);
                                err |= __get_user(lbe->rdev_new, &lbe32->rdev_new);
-
 			}
 		}
 	}
@@ -2210,7 +2553,7 @@
 
 static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	vg_t *v;
+	vg_t *v = NULL;
 	union {
 		lv_req_t lv_req;
 		le_remap_req_t le_remap;
@@ -2228,17 +2571,22 @@
 	switch (cmd) {
 	case VG_STATUS:
 		v = kmalloc(sizeof(vg_t), GFP_KERNEL);
-		if (!v) return -ENOMEM;
+		if (!v)
+			return -ENOMEM;
 		karg = v;
 		break;
+
+	case VG_CREATE_OLD:
 	case VG_CREATE:
 		v = kmalloc(sizeof(vg_t), GFP_KERNEL);
-		if (!v) return -ENOMEM;
-		if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc) ||
-		    __get_user(v->proc, &((vg32_t *)arg)->proc)) {
+		if (!v)
+			return -ENOMEM;
+		if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc)) {
 			kfree(v);
 			return -EFAULT;
 		}
+		/* 'proc' field is unused, just NULL it out. */
+		v->proc = NULL;
 		if (copy_from_user(v->vg_uuid, ((vg32_t *)arg)->vg_uuid, UUID_LEN+1)) {
 			kfree(v);
 			return -EFAULT;
@@ -2250,94 +2598,117 @@
 			return -EPERM;
 		for (i = 0; i < v->pv_max; i++) {
 			err = __get_user(ptr, &((vg32_t *)arg)->pv[i]);
-			if (err) break;
+			if (err)
+				break;
 			if (ptr) {
 				v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL);
 				if (!v->pv[i]) {
 					err = -ENOMEM;
 					break;
 				}
-				err = copy_from_user(v->pv[i], (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1);
+				err = copy_from_user(v->pv[i], (void *)A(ptr),
+						     sizeof(pv32_t) - 8 - UUID_LEN+1);
 				if (err) {
 					err = -EFAULT;
 					break;
 				}
-				err = copy_from_user(v->pv[i]->pv_uuid, ((pv32_t *)A(ptr))->pv_uuid, UUID_LEN+1);
+				err = copy_from_user(v->pv[i]->pv_uuid,
+						     ((pv32_t *)A(ptr))->pv_uuid,
+						     UUID_LEN+1);
 				if (err) {
 				        err = -EFAULT;
 					break;
 				}
 
-				
-				v->pv[i]->pe = NULL; v->pv[i]->inode = NULL;
+				v->pv[i]->pe = NULL;
+				v->pv[i]->bd = NULL;
 			}
 		}
 		if (!err) {
 			for (i = 0; i < v->lv_max; i++) {
 				err = __get_user(ptr, &((vg32_t *)arg)->lv[i]);
-				if (err) break;
+				if (err)
+					break;
 				if (ptr) {
 					v->lv[i] = get_lv_t(ptr, &err);
-					if (err) break;
+					if (err)
+						break;
 				}
 			}
 		}
 		break;
+
 	case LV_CREATE:
 	case LV_EXTEND:
 	case LV_REDUCE:
 	case LV_REMOVE:
 	case LV_RENAME:
 	case LV_STATUS_BYNAME:
-	        err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name));
-		if (err) return -EFAULT;
+	        err = copy_from_user(&u.pv_status, (void*)arg, sizeof(u.pv_status.pv_name));
+		if (err)
+			return -EFAULT;
 		if (cmd != LV_REMOVE) {
 			err = __get_user(ptr, &((lv_req32_t *)arg)->lv);
-			if (err) return err;
+			if (err)
+				return err;
 			u.lv_req.lv = get_lv_t(ptr, &err);
 		} else
 			u.lv_req.lv = NULL;
 		break;
 
-
 	case LV_STATUS_BYINDEX:
-		err = get_user(u.lv_byindex.lv_index, &((lv_status_byindex_req32_t *)arg)->lv_index);
+		err = get_user(u.lv_byindex.lv_index,
+			       &((lv_status_byindex_req32_t *)arg)->lv_index);
 		err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv);
-		if (err) return err;
+		if (err)
+			return err;
 		u.lv_byindex.lv = get_lv_t(ptr, &err);
 		break;
+
 	case LV_STATUS_BYDEV:
 	        err = get_user(u.lv_bydev.dev, &((lv_status_bydev_req32_t *)arg)->dev);
+		err |= __get_user(ptr, &((lv_status_bydev_req32_t *)arg)->lv);
+		if (err)
+			return err;
 		u.lv_bydev.lv = get_lv_t(ptr, &err);
-		if (err) return err;
-		u.lv_bydev.lv = &p;
-		p.pe = NULL; p.inode = NULL;		
 		break;		
+
 	case VG_EXTEND:
 		err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8 - UUID_LEN+1);
-		if (err) return -EFAULT;
+		if (err)
+			return -EFAULT;
 		err = copy_from_user(p.pv_uuid, ((pv32_t *)arg)->pv_uuid, UUID_LEN+1);
-		if (err) return -EFAULT;
-		p.pe = NULL; p.inode = NULL;
+		if (err)
+			return -EFAULT;
+		p.pe = NULL;
+		p.bd = NULL;
 		karg = &p;
 		break;
+
 	case PV_CHANGE:
 	case PV_STATUS:
-		err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name));
-		if (err) return -EFAULT;
+		err = copy_from_user(&u.pv_status, (void*)arg, sizeof(u.lv_req.lv_name));
+		if (err)
+			return -EFAULT;
 		err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv);
-		if (err) return err;
+		if (err)
+			return err;
 		u.pv_status.pv = &p;
 		if (cmd == PV_CHANGE) {
-			err = copy_from_user(&p, (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1);
-			if (err) return -EFAULT;
-			p.pe = NULL; p.inode = NULL;
+			err = copy_from_user(&p, (void *)A(ptr),
+					     sizeof(pv32_t) - 8 - UUID_LEN+1);
+			if (err)
+				return -EFAULT;
+			p.pe = NULL;
+			p.bd = NULL;
 		}
 		break;
-	}
+	};
+
         old_fs = get_fs(); set_fs (KERNEL_DS);
         err = sys_ioctl (fd, cmd, (unsigned long)karg);
         set_fs (old_fs);
+
 	switch (cmd) {
 	case VG_STATUS:
 		if (!err) {
@@ -2350,42 +2721,60 @@
 		}
 		kfree(v);
 		break;
+
+	case VG_CREATE_OLD:
 	case VG_CREATE:
-		for (i = 0; i < v->pv_max; i++)
-			if (v->pv[i]) kfree(v->pv[i]);
-		for (i = 0; i < v->lv_max; i++)
-			if (v->lv[i]) put_lv_t(v->lv[i]);
+		for (i = 0; i < v->pv_max; i++) {
+			if (v->pv[i])
+				kfree(v->pv[i]);
+		}
+		for (i = 0; i < v->lv_max; i++) {
+			if (v->lv[i])
+				put_lv_t(v->lv[i]);
+		}
 		kfree(v);
 		break;
+
 	case LV_STATUS_BYNAME:
-		if (!err && u.lv_req.lv) err = copy_lv_t(ptr, u.lv_req.lv);
+		if (!err && u.lv_req.lv)
+			err = copy_lv_t(ptr, u.lv_req.lv);
 		/* Fall through */
+
         case LV_CREATE:
 	case LV_EXTEND:
 	case LV_REDUCE:
-		if (u.lv_req.lv) put_lv_t(u.lv_req.lv);
+		if (u.lv_req.lv)
+			put_lv_t(u.lv_req.lv);
 		break;
+
 	case LV_STATUS_BYINDEX:
 		if (u.lv_byindex.lv) {
-			if (!err) err = copy_lv_t(ptr, u.lv_byindex.lv);
+			if (!err)
+				err = copy_lv_t(ptr, u.lv_byindex.lv);
 			put_lv_t(u.lv_byindex.lv);
 		}
 		break;
-	case PV_STATUS:
-		if (!err) {
-			err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1);
-			if (err) return -EFAULT;
-			err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1);
-			if (err) return -EFAULT;
-		}
-		break;
+
 	case LV_STATUS_BYDEV:
-	        if (!err) {
-			if (!err) err = copy_lv_t(ptr, u.lv_bydev.lv);
+	        if (u.lv_bydev.lv) {
+			if (!err)
+				err = copy_lv_t(ptr, u.lv_bydev.lv);
 			put_lv_t(u.lv_byindex.lv);
 	        }
 	        break;
+
+	case PV_STATUS:
+		if (!err) {
+			err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1);
+			if (err)
+				return -EFAULT;
+			err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1);
+			if (err)
+				return -EFAULT;
 	}
+		break;
+	};
+
 	return err;
 }
 #endif
@@ -2975,7 +3364,11 @@
 	return err;
 }
 
-/* SuSE extension */ 
+static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
+}
+
 #ifndef TIOCGDEV
 #define TIOCGDEV       _IOR('T',0x32, unsigned int)
 #endif
@@ -3087,6 +3480,15 @@
 }
 
 
+#define REISERFS_IOC_UNPACK32               _IOW(0xCD,1,int)
+
+static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) 
+{ 
+	if (cmd == REISERFS_IOC_UNPACK32) 
+		cmd = REISERFS_IOC_UNPACK; 
+	return sys_ioctl(fd,cmd,ptr); 
+} 
+
 struct dirent32 {
 	unsigned int		d_ino;
 	__kernel_off_t32	d_off;
@@ -3124,32 +3526,6 @@
 	return ret; 
 } 
 
-
-
-#define REISERFS_IOC_UNPACK32               _IOW(0xCD,1,int)
-
-static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) 
-{ 
-	if (cmd == REISERFS_IOC_UNPACK32) 
-		cmd = REISERFS_IOC_UNPACK; 
-	return sys_ioctl(fd,cmd,ptr); 
-} 
-
-#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
-
-static int autofs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) 
-{
-	int ret; 
-	unsigned long val;
-	mm_segment_t oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_ioctl(fd, AUTOFS_IOC_SETTIMEOUT32, (unsigned long)&val); 
-	set_fs(oldfs); 
-	if (!ret) 
-		ret = put_user(val, (int *) ptr); 
-	return ret; 
-} 
-
 #define RTC_IRQP_READ32	_IOR('p', 0x0b, unsigned int)	 /* Read IRQ rate   */
 #define RTC_IRQP_SET32	_IOW('p', 0x0c, unsigned int)	 /* Set IRQ rate    */
 #define RTC_EPOCH_READ32	_IOR('p', 0x0d, unsigned)	 /* Read epoch      */
@@ -3189,6 +3565,572 @@
 	return sys_ioctl(fd,cmd,arg); 
 } 
 
+/* Fix sizeof(sizeof()) breakage */
+#define BLKELVGET_32   _IOR(0x12,106,int)
+#define BLKELVSET_32   _IOW(0x12,107,int)
+#define BLKBSZGET_32   _IOR(0x12,112,int)
+#define BLKBSZSET_32   _IOW(0x12,113,int)
+#define BLKGETSIZE64_32        _IOR(0x12,114,int)
+
+static int do_blkelvget(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       return sys_ioctl(fd, BLKELVGET, arg);
+}
+
+static int do_blkelvset(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       return sys_ioctl(fd, BLKELVSET, arg);
+}
+
+static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       return sys_ioctl(fd, BLKBSZGET, arg);
+}
+
+static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       return sys_ioctl(fd, BLKBSZSET, arg);
+}
+
+static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
+                          unsigned long arg)
+{
+       return sys_ioctl(fd, BLKGETSIZE64, arg);
+}
+
+
+
+struct usbdevfs_ctrltransfer32 {
+	__u8 bRequestType;
+	__u8 bRequest;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+	__u32 timeout;  /* in milliseconds */
+	__u32 data;
+};
+
+#define USBDEVFS_CONTROL32           _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
+
+static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct usbdevfs_ctrltransfer kctrl;
+	struct usbdevfs_ctrltransfer32 *uctrl;
+	mm_segment_t old_fs;
+	__u32 udata;
+	void *uptr, *kptr;
+	int err;
+
+	uctrl = (struct usbdevfs_ctrltransfer32 *) arg;
+
+	if (copy_from_user(&kctrl, uctrl,
+			   (sizeof(struct usbdevfs_ctrltransfer) -
+			    sizeof(void *))))
+		return -EFAULT;
+
+	if (get_user(udata, &uctrl->data))
+		return -EFAULT;
+	uptr = (void *) A(udata);
+
+	/* In usbdevice_fs, it limits the control buffer to a page,
+	 * for simplicity so do we.
+	 */
+	if (!uptr || kctrl.wLength > PAGE_SIZE)
+		return -EINVAL;
+
+	kptr = (void *)__get_free_page(GFP_KERNEL);
+
+	if ((kctrl.bRequestType & 0x80) == 0) {
+		err = -EFAULT;
+		if (copy_from_user(kptr, uptr, kctrl.wLength))
+			goto out;
+	}
+
+	kctrl.data = kptr;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl);
+	set_fs(old_fs);
+
+	if (err >= 0 &&
+	    ((kctrl.bRequestType & 0x80) != 0)) {
+		if (copy_to_user(uptr, kptr, kctrl.wLength))
+			err = -EFAULT;
+	}
+
+out:
+	free_page((unsigned long) kptr);
+	return err;
+}
+
+struct usbdevfs_bulktransfer32 {
+	unsigned int ep;
+	unsigned int len;
+	unsigned int timeout; /* in milliseconds */
+	__u32 data;
+};
+
+#define USBDEVFS_BULK32              _IOWR('U', 2, struct usbdevfs_bulktransfer32)
+
+static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct usbdevfs_bulktransfer kbulk;
+	struct usbdevfs_bulktransfer32 *ubulk;
+	mm_segment_t old_fs;
+	__u32 udata;
+	void *uptr, *kptr;
+	int err;
+
+	ubulk = (struct usbdevfs_bulktransfer32 *) arg;
+
+	if (get_user(kbulk.ep, &ubulk->ep) ||
+	    get_user(kbulk.len, &ubulk->len) ||
+	    get_user(kbulk.timeout, &ubulk->timeout) ||
+	    get_user(udata, &ubulk->data))
+		return -EFAULT;
+
+	uptr = (void *) A(udata);
+
+	/* In usbdevice_fs, it limits the control buffer to a page,
+	 * for simplicity so do we.
+	 */
+	if (!uptr || kbulk.len > PAGE_SIZE)
+		return -EINVAL;
+
+	kptr = (void *) __get_free_page(GFP_KERNEL);
+
+	if ((kbulk.ep & 0x80) == 0) {
+		err = -EFAULT;
+		if (copy_from_user(kptr, uptr, kbulk.len))
+			goto out;
+	}
+
+	kbulk.data = kptr;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk);
+	set_fs(old_fs);
+
+	if (err >= 0 &&
+	    ((kbulk.ep & 0x80) != 0)) {
+		if (copy_to_user(uptr, kptr, kbulk.len))
+			err = -EFAULT;
+	}
+
+out:
+	free_page((unsigned long) kptr);
+	return err;
+}
+
+/* This needs more work before we can enable it.  Unfortunately
+ * because of the fancy asynchronous way URB status/error is written
+ * back to userspace, we'll need to fiddle with USB devio internals
+ * and/or reimplement entirely the frontend of it ourselves. -DaveM
+ *
+ * The issue is:
+ *
+ *	When an URB is submitted via usbdevicefs it is put onto an
+ *	asynchronous queue.  When the URB completes, it may be reaped
+ *	via another ioctl.  During this reaping the status is written
+ *	back to userspace along with the length of the transfer.
+ *
+ *	We must translate into 64-bit kernel types so we pass in a kernel
+ *	space copy of the usbdevfs_urb structure.  This would mean that we
+ *	must do something to deal with the async entry reaping.  First we
+ *	have to deal somehow with this transitory memory we've allocated.
+ *	This is problematic since there are many call sites from which the
+ *	async entries can be destroyed (and thus when we'd need to free up
+ *	this kernel memory).  One of which is the close() op of usbdevicefs.
+ *	To handle that we'd need to make our own file_operations struct which
+ *	overrides usbdevicefs's release op with our own which runs usbdevicefs's
+ *	real release op then frees up the kernel memory.
+ *
+ *	But how to keep track of these kernel buffers?  We'd need to either
+ *	keep track of them in some table _or_ know about usbdevicefs internals
+ *	(ie. the exact layout of it's file private, which is actually defined
+ *	in linux/usbdevice_fs.h, the layout of the async queues are private to
+ *	devio.c)
+ *
+ * There is one possible other solution I considered, also involving knowledge
+ * of usbdevicefs internals:
+ *
+ *	After an URB is submitted, we "fix up" the address back to the user
+ *	space one.  This would work if the status/length fields written back
+ *	by the async URB completion lines up perfectly in the 32-bit type with
+ *	the 64-bit kernel type.  Unfortunately, it does not because the iso
+ *	frame descriptors, at the end of the struct, can be written back.
+ *
+ * I think we'll just need to simply duplicate the devio URB engine here.
+ */
+#if 0
+struct usbdevfs_urb32 {
+	__u8 type;
+	__u8 endpoint;
+	__s32 status;
+	__u32 flags;
+	__u32 buffer;
+	__s32 buffer_length;
+	__s32 actual_length;
+	__s32 start_frame;
+	__s32 number_of_packets;
+	__s32 error_count;
+	__u32 signr;
+	__u32 usercontext; /* unused */
+	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+};
+
+#define USBDEVFS_SUBMITURB32       _IOR('U', 10, struct usbdevfs_urb32)
+
+static int get_urb32(struct usbdevfs_urb *kurb,
+		     struct usbdevfs_urb32 *uurb)
+{
+	if (get_user(kurb->type, &uurb->type) ||
+	    __get_user(kurb->endpoint, &uurb->endpoint) ||
+	    __get_user(kurb->status, &uurb->status) ||
+	    __get_user(kurb->flags, &uurb->flags) ||
+	    __get_user(kurb->buffer_length, &uurb->buffer_length) ||
+	    __get_user(kurb->actual_length, &uurb->actual_length) ||
+	    __get_user(kurb->start_frame, &uurb->start_frame) ||
+	    __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
+	    __get_user(kurb->error_count, &uurb->error_count) ||
+	    __get_user(kurb->signr, &uurb->signr))
+		return -EFAULT;
+
+	kurb->usercontext = 0; /* unused currently */
+
+	return 0;
+}
+
+/* Just put back the values which usbdevfs actually changes. */
+static int put_urb32(struct usbdevfs_urb *kurb,
+		     struct usbdevfs_urb32 *uurb)
+{
+	if (put_user(kurb->status, &uurb->status) ||
+	    __put_user(kurb->actual_length, &uurb->actual_length) ||
+	    __put_user(kurb->error_count, &uurb->error_count))
+		return -EFAULT;
+
+	if (kurb->number_of_packets != 0) {
+		int i;
+
+		for (i = 0; i < kurb->number_of_packets; i++) {
+			if (__put_user(kurb->iso_frame_desc[i].actual_length,
+				       &uurb->iso_frame_desc[i].actual_length) ||
+			    __put_user(kurb->iso_frame_desc[i].status,
+				       &uurb->iso_frame_desc[i].status))
+				return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
+			       struct usbdevfs_urb32 *uurb)
+{
+	unsigned int totlen;
+	int i;
+
+	if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
+		kurb->number_of_packets = 0;
+		return 0;
+	}
+
+	if (kurb->number_of_packets < 1 ||
+	    kurb->number_of_packets > 128)
+		return -EINVAL;
+
+	if (copy_from_user(&kurb->iso_frame_desc[0],
+			   &uurb->iso_frame_desc[0],
+			   sizeof(struct usbdevfs_iso_packet_desc) *
+			   kurb->number_of_packets))
+		return -EFAULT;
+
+	totlen = 0;
+	for (i = 0; i < kurb->number_of_packets; i++) {
+		unsigned int this_len;
+
+		this_len = kurb->iso_frame_desc[i].length;
+		if (this_len > 1023)
+			return -EINVAL;
+
+		totlen += this_len;
+	}
+
+	if (totlen > 32768)
+		return -EINVAL;
+
+	kurb->buffer_length = totlen;
+
+	return 0;
+}
+
+static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct usbdevfs_urb *kurb;
+	struct usbdevfs_urb32 *uurb;
+	mm_segment_t old_fs;
+	__u32 udata;
+	void *uptr, *kptr;
+	unsigned int buflen;
+	int err;
+
+	uurb = (struct usbdevfs_urb32 *) arg;
+
+	err = -ENOMEM;
+	kurb = kmalloc(sizeof(struct usbdevfs_urb) +
+		       (sizeof(struct usbdevfs_iso_packet_desc) * 128),
+		       GFP_KERNEL);
+	if (!kurb)
+		goto out;
+
+	err = -EFAULT;
+	if (get_urb32(kurb, uurb))
+		goto out;
+
+	err = get_urb32_isoframes(kurb, uurb);
+	if (err)
+		goto out;
+
+	err = -EFAULT;
+	if (__get_user(udata, &uurb->buffer))
+		goto out;
+	uptr = (void *) A(udata);
+
+	err = -ENOMEM;
+	buflen = kurb->buffer_length;
+	kptr = kmalloc(buflen, GFP_KERNEL);
+	if (!kptr)
+		goto out;
+
+	kurb->buffer = kptr;
+
+	err = -EFAULT;
+	if (copy_from_user(kptr, uptr, buflen))
+		goto out_kptr;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
+	set_fs(old_fs);
+
+	if (err >= 0) {
+		/* RED-PEN Shit, this doesn't work for async URBs :-( XXX */
+		if (put_urb32(kurb, uurb)) {
+			err = -EFAULT;
+		} else if ((kurb->endpoint & USB_DIR_IN) != 0) {
+			if (copy_to_user(uptr, kptr, buflen))
+				err = -EFAULT;
+		}
+	}
+
+out_kptr:
+	kfree(kptr);
+
+out:
+	kfree(kurb);
+	return err;
+}
+#endif
+
+#define USBDEVFS_REAPURB32         _IOW('U', 12, u32)
+#define USBDEVFS_REAPURBNDELAY32   _IOW('U', 13, u32)
+
+static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs;
+	void *kptr;
+	int err;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd,
+			(cmd == USBDEVFS_REAPURB32 ?
+			 USBDEVFS_REAPURB :
+			 USBDEVFS_REAPURBNDELAY),
+			(unsigned long) &kptr);
+	set_fs(old_fs);
+
+	if (err >= 0 &&
+	    put_user(((u32)(long)kptr), (u32 *) A(arg)))
+		err = -EFAULT;
+
+	return err;
+}
+
+struct usbdevfs_disconnectsignal32 {
+	unsigned int signr;
+	u32 context;
+};
+
+#define USBDEVFS_DISCSIGNAL32      _IOR('U', 14, struct usbdevfs_disconnectsignal32)
+
+static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct usbdevfs_disconnectsignal kdis;
+	struct usbdevfs_disconnectsignal32 *udis;
+	mm_segment_t old_fs;
+	u32 uctx;
+	int err;
+
+	udis = (struct usbdevfs_disconnectsignal32 *) arg;
+
+	if (get_user(kdis.signr, &udis->signr) ||
+	    __get_user(uctx, &udis->context))
+		return -EFAULT;
+
+	kdis.context = (void *) (long)uctx;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis);
+	set_fs(old_fs);
+
+	return err;
+}
+
+struct mtd_oob_buf32 {
+	u32 start;
+	u32 length;
+	u32 ptr;	/* unsigned char* */
+};
+
+#define MEMWRITEOOB32 	_IOWR('M',3,struct mtd_oob_buf32)
+#define MEMREADOOB32 	_IOWR('M',4,struct mtd_oob_buf32)
+
+static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t 			old_fs 	= get_fs();
+	struct mtd_oob_buf32	*uarg 	= (struct mtd_oob_buf32 *)arg;
+	struct mtd_oob_buf		karg;
+	u32 tmp;
+	char *ptr;
+	int ret;
+
+	if (get_user(karg.start, &uarg->start) 		||
+	    get_user(karg.length, &uarg->length)	||
+	    get_user(tmp, &uarg->ptr))
+		return -EFAULT;
+
+	ptr = (char *)A(tmp);
+	if (0 >= karg.length) 
+		return -EINVAL;
+
+	karg.ptr = kmalloc(karg.length, GFP_KERNEL);
+	if (NULL == karg.ptr)
+		return -ENOMEM;
+
+	if (copy_from_user(karg.ptr, ptr, karg.length)) {
+		kfree(karg.ptr);
+		return -EFAULT;
+	}
+
+	set_fs(KERNEL_DS);
+	if (MEMREADOOB32 == cmd) 
+		ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg);
+	else if (MEMWRITEOOB32 == cmd)
+		ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg);
+	else
+		ret = -EINVAL;
+	set_fs(old_fs);
+
+	if (0 == ret && cmd == MEMREADOOB32) {
+		ret = copy_to_user(ptr, karg.ptr, karg.length);
+		ret |= put_user(karg.start, &uarg->start);
+		ret |= put_user(karg.length, &uarg->length);
+	}
+
+	kfree(karg.ptr);
+	return ((0 == ret) ? 0 : -EFAULT);
+}	
+
+/* /proc/mtrr ioctls */
+
+
+struct mtrr_sentry32
+{
+    unsigned int base;    /*  Base address     */
+    unsigned int size;    /*  Size of region   */
+    unsigned int type;     /*  Type of region   */
+};
+
+struct mtrr_gentry32
+{
+    unsigned int regnum;   /*  Register number  */
+    unsigned int base;    /*  Base address     */
+    unsigned int size;    /*  Size of region   */
+    unsigned int type;     /*  Type of region   */
+};
+
+#define	MTRR_IOCTL_BASE	'M'
+
+#define MTRRIOC32_ADD_ENTRY        _IOW(MTRR_IOCTL_BASE,  0, struct mtrr_sentry32)
+#define MTRRIOC32_SET_ENTRY        _IOW(MTRR_IOCTL_BASE,  1, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_ENTRY        _IOW(MTRR_IOCTL_BASE,  2, struct mtrr_sentry32)
+#define MTRRIOC32_GET_ENTRY        _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_ENTRY       _IOW(MTRR_IOCTL_BASE,  4, struct mtrr_sentry32)
+#define MTRRIOC32_ADD_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  5, struct mtrr_sentry32)
+#define MTRRIOC32_SET_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  6, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  7, struct mtrr_sentry32)
+#define MTRRIOC32_GET_PAGE_ENTRY   _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_PAGE_ENTRY  _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry32)
+
+
+static int mtrr_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg)
+{ 
+	struct mtrr_gentry g;
+	struct mtrr_sentry s;
+	int get = 0, err = 0; 
+	struct mtrr_gentry32 *g32 = (struct mtrr_gentry32 *)arg; 
+	mm_segment_t oldfs = get_fs(); 
+
+	switch (cmd) { 
+#define SET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; break 
+#define GET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; get=1; break
+		SET(ADD);
+		SET(SET); 
+		SET(DEL);
+		GET(GET); 
+		SET(KILL);
+		SET(ADD_PAGE); 
+		SET(SET_PAGE); 
+		SET(DEL_PAGE); 
+		GET(GET_PAGE); 
+		SET(KILL_PAGE); 
+	} 
+	
+	if (get) { 
+		err = get_user(g.regnum, &g32->regnum);
+		err |= get_user(g.base, &g32->base);
+		err |= get_user(g.size, &g32->size);
+		err |= get_user(g.type, &g32->type); 
+
+		arg = (unsigned long)&g; 
+	} else { 
+		struct mtrr_sentry32 *s32 = (struct mtrr_sentry32 *)arg;
+		err = get_user(s.base, &s32->base);
+		err |= get_user(s.size, &s32->size);
+		err |= get_user(s.type, &s32->type);
+
+		arg = (unsigned long)&s; 
+	} 
+	if (err) return err;
+	
+	set_fs(KERNEL_DS); 
+	err = sys_ioctl(fd, cmd, arg); 
+	set_fs(oldfs); 
+		
+	if (!err && get) { 
+		err = put_user(g.base, &g32->base);
+		err |= put_user(g.size, &g32->size);
+		err |= put_user(g.regnum, &g32->regnum);
+		err |= put_user(g.type, &g32->type); 
+	} 
+	return err;
+} 
+
 struct ioctl_trans {
 	unsigned long cmd;
 	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
@@ -3219,7 +4161,6 @@
 COMPATIBLE_IOCTL(TCSETSW)
 COMPATIBLE_IOCTL(TCSETSF)
 COMPATIBLE_IOCTL(TIOCLINUX)
-HANDLE_IOCTL(TIOCGDEV, tiocgdev)
 /* Little t */
 COMPATIBLE_IOCTL(TIOCGETD)
 COMPATIBLE_IOCTL(TIOCSETD)
@@ -3244,6 +4185,7 @@
 COMPATIBLE_IOCTL(TIOCGPTN)
 COMPATIBLE_IOCTL(TIOCSPTLCK)
 COMPATIBLE_IOCTL(TIOCSERGETLSR)
+/* Big F */
 COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO)
 COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO)
 COMPATIBLE_IOCTL(FBIOPAN_DISPLAY)
@@ -3268,12 +4210,14 @@
  */
 COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
 COMPATIBLE_IOCTL(HDIO_SET_DMA)
+COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS)
 COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR)
 COMPATIBLE_IOCTL(HDIO_SET_NOWERR)
 COMPATIBLE_IOCTL(HDIO_SET_32BIT)
 COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT)
 COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
 COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE)
+COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
 COMPATIBLE_IOCTL(HDIO_SET_NICE)
 /* 0x02 -- Floppy ioctls */
 COMPATIBLE_IOCTL(FDMSGON)
@@ -3301,7 +4245,6 @@
 COMPATIBLE_IOCTL(BLKFRASET)
 COMPATIBLE_IOCTL(BLKSECTSET)
 COMPATIBLE_IOCTL(BLKSSZGET)
-
 /* RAID */
 COMPATIBLE_IOCTL(RAID_VERSION)
 COMPATIBLE_IOCTL(GET_ARRAY_INFO)
@@ -3322,7 +4265,6 @@
 COMPATIBLE_IOCTL(STOP_ARRAY)
 COMPATIBLE_IOCTL(STOP_ARRAY_RO)
 COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
-
 /* Big K */
 COMPATIBLE_IOCTL(PIO_FONT)
 COMPATIBLE_IOCTL(GIO_FONT)
@@ -3344,6 +4286,7 @@
 COMPATIBLE_IOCTL(KDSKBSENT)
 COMPATIBLE_IOCTL(KDGKBDIACR)
 COMPATIBLE_IOCTL(KDSKBDIACR)
+COMPATIBLE_IOCTL(KDKBDREP)
 COMPATIBLE_IOCTL(KDGKBLED)
 COMPATIBLE_IOCTL(KDSKBLED)
 COMPATIBLE_IOCTL(KDGETLED)
@@ -3363,6 +4306,14 @@
 COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE)
 COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
 COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
+COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
+/* Big T */
+COMPATIBLE_IOCTL(TUNSETNOCSUM)
+COMPATIBLE_IOCTL(TUNSETDEBUG)
+COMPATIBLE_IOCTL(TUNSETIFF)
+COMPATIBLE_IOCTL(TUNSETPERSIST)
+COMPATIBLE_IOCTL(TUNSETOWNER)
 /* Big V */
 COMPATIBLE_IOCTL(VT_SETMODE)
 COMPATIBLE_IOCTL(VT_GETMODE)
@@ -3376,7 +4327,8 @@
 COMPATIBLE_IOCTL(VT_RESIZEX)
 COMPATIBLE_IOCTL(VT_LOCKSWITCH)
 COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
-/* Little v, the video4linux ioctls */
+/* Little v */
+/* Little v, the video4linux ioctls (conflict?) */
 COMPATIBLE_IOCTL(VIDIOCGCAP)
 COMPATIBLE_IOCTL(VIDIOCGCHAN)
 COMPATIBLE_IOCTL(VIDIOCSCHAN)
@@ -3416,10 +4368,6 @@
 COMPATIBLE_IOCTL(RTC_SET_TIME)
 COMPATIBLE_IOCTL(RTC_WKALM_SET)
 COMPATIBLE_IOCTL(RTC_WKALM_RD)
-HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl)
-HANDLE_IOCTL(RTC_IRQP_SET32,rtc32_ioctl)
-HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl)
-HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl)
 /* Little m */
 COMPATIBLE_IOCTL(MTIOCTOP)
 /* Socket level stuff */
@@ -3441,6 +4389,11 @@
 COMPATIBLE_IOCTL(SIOCDRARP)
 COMPATIBLE_IOCTL(SIOCADDDLCI)
 COMPATIBLE_IOCTL(SIOCDELDLCI)
+COMPATIBLE_IOCTL(SIOCGMIIPHY)
+COMPATIBLE_IOCTL(SIOCGMIIREG)
+COMPATIBLE_IOCTL(SIOCSMIIREG)
+COMPATIBLE_IOCTL(SIOCGIFVLAN)
+COMPATIBLE_IOCTL(SIOCSIFVLAN)
 /* SG stuff */
 COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
 COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
@@ -3462,7 +4415,6 @@
 COMPATIBLE_IOCTL(SG_GET_VERSION_NUM)
 COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN)
 COMPATIBLE_IOCTL(SG_SCSI_RESET)
-COMPATIBLE_IOCTL(SG_IO)
 COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
 COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
 COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
@@ -3480,10 +4432,14 @@
 COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
 COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
 COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
+/* PPPIOCSCOMPRESS is translated */
 COMPATIBLE_IOCTL(PPPIOCGNPMODE)
 COMPATIBLE_IOCTL(PPPIOCSNPMODE)
 COMPATIBLE_IOCTL(PPPIOCGDEBUG)
 COMPATIBLE_IOCTL(PPPIOCSDEBUG)
+/* PPPIOCSPASS is translated */
+/* PPPIOCSACTIVE is translated */
+/* PPPIOCGIDLE is translated */
 COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
 COMPATIBLE_IOCTL(PPPIOCATTACH)
 COMPATIBLE_IOCTL(PPPIOCDETACH)
@@ -3493,8 +4449,10 @@
 COMPATIBLE_IOCTL(PPPIOCATTCHAN)
 COMPATIBLE_IOCTL(PPPIOCGCHAN)
 /* PPPOX */
-COMPATIBLE_IOCTL(PPPOEIOCSFWD);
-COMPATIBLE_IOCTL(PPPOEIOCDFWD);
+COMPATIBLE_IOCTL(PPPOEIOCSFWD)
+COMPATIBLE_IOCTL(PPPOEIOCDFWD)
+/* LP */
+COMPATIBLE_IOCTL(LPGETSTATUS)
 /* CDROM stuff */
 COMPATIBLE_IOCTL(CDROMPAUSE)
 COMPATIBLE_IOCTL(CDROMRESUME)
@@ -3526,9 +4484,15 @@
 COMPATIBLE_IOCTL(CDROM_LOCKDOOR)
 COMPATIBLE_IOCTL(CDROM_DEBUG)
 COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* DVD ioctls */
+COMPATIBLE_IOCTL(DVD_READ_STRUCT)
+COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
+COMPATIBLE_IOCTL(DVD_AUTH)
 /* Big L */
 COMPATIBLE_IOCTL(LOOP_SET_FD)
 COMPATIBLE_IOCTL(LOOP_CLR_FD)
+/* Big A */
+/* sparc only */
 /* Big Q for sound/OSS */
 COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET)
 COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC)
@@ -3687,7 +4651,6 @@
 COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
 COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
 COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
-HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, autofs_ioctl32); 
 /* DEVFS */
 COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
@@ -3754,15 +4717,68 @@
 COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK)
 COMPATIBLE_IOCTL(DRM_IOCTL_FINISH)
 #endif /* DRM */
-HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32);
-HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32);
-HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32);
-/* serial driver */ 
-HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl);
-HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl);
-/* elevator */
-COMPATIBLE_IOCTL(BLKELVGET)
-COMPATIBLE_IOCTL(BLKELVSET)
+#ifdef CONFIG_AUTOFS_FS
+COMPATIBLE_IOCTL(AUTOFS_IOC_READY)
+COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL)
+COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
+COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
+COMPATIBLE_IOCTL(AUTOFS_IOC_SETTIMEOUT)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
+#endif
+#ifdef CONFIG_RTC
+COMPATIBLE_IOCTL(RTC_AIE_ON)
+COMPATIBLE_IOCTL(RTC_AIE_OFF)
+COMPATIBLE_IOCTL(RTC_UIE_ON)
+COMPATIBLE_IOCTL(RTC_UIE_OFF)
+COMPATIBLE_IOCTL(RTC_PIE_ON)
+COMPATIBLE_IOCTL(RTC_PIE_OFF)
+COMPATIBLE_IOCTL(RTC_WIE_ON)
+COMPATIBLE_IOCTL(RTC_WIE_OFF)
+COMPATIBLE_IOCTL(RTC_ALM_SET)
+COMPATIBLE_IOCTL(RTC_ALM_READ)
+COMPATIBLE_IOCTL(RTC_RD_TIME)
+COMPATIBLE_IOCTL(RTC_SET_TIME)
+COMPATIBLE_IOCTL(RTC_WKALM_SET)
+COMPATIBLE_IOCTL(RTC_WKALM_RD)
+#endif
+/* Big W */
+/* WIOC_GETSUPPORT not yet implemented -E */
+COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
+COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS)
+COMPATIBLE_IOCTL(WDIOC_GETTEMP)
+COMPATIBLE_IOCTL(WDIOC_SETOPTIONS)
+COMPATIBLE_IOCTL(WDIOC_KEEPALIVE)
+#if 0 /* sparc only ? */
+COMPATIBLE_IOCTL(WIOCSTART)
+COMPATIBLE_IOCTL(WIOCSTOP)
+COMPATIBLE_IOCTL(WIOCGSTAT)
+#endif
+/* Big R */
+COMPATIBLE_IOCTL(RNDGETENTCNT)
+COMPATIBLE_IOCTL(RNDADDTOENTCNT)
+COMPATIBLE_IOCTL(RNDGETPOOL)
+COMPATIBLE_IOCTL(RNDADDENTROPY)
+COMPATIBLE_IOCTL(RNDZAPENTCNT)
+COMPATIBLE_IOCTL(RNDCLEARPOOL)
+/* Bluetooth ioctls */
+COMPATIBLE_IOCTL(HCIDEVUP)
+COMPATIBLE_IOCTL(HCIDEVDOWN)
+COMPATIBLE_IOCTL(HCIDEVRESET)
+COMPATIBLE_IOCTL(HCIDEVRESTAT)
+COMPATIBLE_IOCTL(HCIGETDEVLIST)
+COMPATIBLE_IOCTL(HCIGETDEVINFO)
+COMPATIBLE_IOCTL(HCIGETCONNLIST)
+COMPATIBLE_IOCTL(HCIGETCONNINFO)
+COMPATIBLE_IOCTL(HCISETRAW)
+COMPATIBLE_IOCTL(HCISETSCAN)
+COMPATIBLE_IOCTL(HCISETAUTH)
+COMPATIBLE_IOCTL(HCISETENCRYPT)
+COMPATIBLE_IOCTL(HCISETPTYPE)
+COMPATIBLE_IOCTL(HCISETLINKPOL)
+COMPATIBLE_IOCTL(HCISETLINKMODE)
+COMPATIBLE_IOCTL(HCISETACLMTU)
+COMPATIBLE_IOCTL(HCISETSCOMTU)
+COMPATIBLE_IOCTL(HCIINQUIRY)
 /* Misc. */
 COMPATIBLE_IOCTL(0x41545900)		/* ATYIO_CLKR */
 COMPATIBLE_IOCTL(0x41545901)		/* ATYIO_CLKW */
@@ -3770,8 +4786,46 @@
 COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO)
 COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM)
 COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE)
+COMPATIBLE_IOCTL(0x4B50);   /* KDGHWCLK - not in the kernel, but don't complain */
+COMPATIBLE_IOCTL(0x4B51);   /* KDSHWCLK - not in the kernel, but don't complain */
+/* USB */
+COMPATIBLE_IOCTL(USBDEVFS_RESETEP)
+COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE)
+COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION)
+COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER)
+COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB)
+COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE)
+COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE)
+COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO)
+COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO)
+COMPATIBLE_IOCTL(USBDEVFS_RESET)
+COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT)
+/* MTD */
+COMPATIBLE_IOCTL(MEMGETINFO)
+COMPATIBLE_IOCTL(MEMERASE)
+COMPATIBLE_IOCTL(MEMLOCK)
+COMPATIBLE_IOCTL(MEMUNLOCK)
+COMPATIBLE_IOCTL(MEMGETREGIONCOUNT)
+COMPATIBLE_IOCTL(MEMGETREGIONINFO)
+/* NBD */
+COMPATIBLE_IOCTL(NBD_SET_SOCK)
+COMPATIBLE_IOCTL(NBD_SET_BLKSIZE)
+COMPATIBLE_IOCTL(NBD_SET_SIZE)
+COMPATIBLE_IOCTL(NBD_DO_IT)
+COMPATIBLE_IOCTL(NBD_CLEAR_SOCK)
+COMPATIBLE_IOCTL(NBD_CLEAR_QUE)
+COMPATIBLE_IOCTL(NBD_PRINT_DEBUG)
+COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS)
+COMPATIBLE_IOCTL(NBD_DISCONNECT)
 /* And these ioctls need translation */
+HANDLE_IOCTL(TIOCGDEV, tiocgdev)
+HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl)
+HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)
+HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
+HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
+#ifdef CONFIG_NET
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
+#endif
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
 HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
@@ -3798,26 +4852,42 @@
 HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc)
 HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
 HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
 HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl)
+HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl)
 HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
 HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
+/* realtime device */
+HANDLE_IOCTL(RTC_IRQP_READ,  rtc32_ioctl)
+HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl)
+HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl)
+HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl)
+HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl)
+HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32)
+HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
+HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
 /* Raw devices */
 HANDLE_IOCTL(RAW_SETBIND, raw_ioctl)
 /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
 HANDLE_IOCTL(SIOCRTMSG, ret_einval)
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
+HANDLE_IOCTL(BLKRAGET, w_long)
 HANDLE_IOCTL(BLKGETSIZE, w_long)
 HANDLE_IOCTL(0x1260, broken_blkgetsize)
+HANDLE_IOCTL(BLKFRAGET, w_long)
 HANDLE_IOCTL(BLKSECTGET, w_long)
+HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans)
 HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
 HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans)
 HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans)
 HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans)
 HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans)
 HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans)
@@ -3833,8 +4903,11 @@
 HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans)
 HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
 HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
+HANDLE_IOCTL(SG_IO,sg_ioctl_trans)
 HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
 HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
 HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
@@ -3848,6 +4921,8 @@
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
 HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
 HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
+HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
 HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
 HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
 HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
@@ -3906,18 +4981,48 @@
 HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl)
 HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl)
 HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl)
+HANDLE_IOCTL(VG_CREATE_OLD, do_lvm_ioctl)
+HANDLE_IOCTL(LV_STATUS_BYDEV, do_lvm_ioctl)
 #endif /* LVM */
 #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
-HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version);
-HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique);
-HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique);
-HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap);
-HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs);
-HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs);
-HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs);
-HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma);
-HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx);
+HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version)
+HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique)
+HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique)
+HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap)
+HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs)
+HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs)
+HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs)
+HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma)
+HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx)
 #endif /* DRM */
+/* VFAT */
+HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
+HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
+HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
+HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
+/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
+HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
+HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
+HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+/* take care of sizeof(sizeof()) breakage */
+/* elevator */
+HANDLE_IOCTL(BLKELVGET_32, do_blkelvget)
+HANDLE_IOCTL(BLKELVSET_32, do_blkelvset)
+/* block stuff */
+HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget)
+HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset)
+HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64)
+/* mtrr */
+HANDLE_IOCTL(MTRRIOC32_ADD_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_SET_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_DEL_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_GET_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_KILL_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_ADD_PAGE_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_SET_PAGE_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_DEL_PAGE_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_GET_PAGE_ENTRY, mtrr_ioctl32)
+HANDLE_IOCTL(MTRRIOC32_KILL_PAGE_ENTRY, mtrr_ioctl32)
 IOCTL_TABLE_END
 
 #define IOCTL_HASHSIZE 256
@@ -3925,6 +5030,8 @@
 
 extern struct ioctl_trans ioctl_start[], ioctl_end[]; 
 
+extern struct ioctl_trans ioctl_start[], ioctl_end[]; 
+
 static inline unsigned long ioctl32_hash(unsigned long cmd)
 {
 	return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
@@ -4021,7 +5128,7 @@
 /* Problem: 
    This function cannot unregister duplicate ioctls, because they are not
    unique.
-   When they happen we need to extend the prototype to pass handler too. */
+   When they happen we need to extend the prototype to pass the handler too. */
 
 int unregister_ioctl32_conversion(unsigned int cmd)
 {
@@ -4095,13 +5202,35 @@
 	if (t) {
 		handler = t->handler;
 		error = handler(fd, cmd, arg, filp);
+	} else if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+		error = siocdevprivate_ioctl(fd, cmd, arg);
 	} else {
-		static int count = 0;
-		if (++count <= 50)
-			printk("sys32_ioctl(%s:%d): Unknown cmd fd(%d) "
-			       "cmd(%08x) arg(%08x)\n",
+		static int count;
+		if (++count <= 50) { 
+			char buf[10];
+			char *path = (char *)__get_free_page(GFP_KERNEL), *fn = "?"; 
+
+			/* find the name of the device. */
+			if (path) {
+				struct file *f = fget(fd); 
+				if (f) {
+					fn = d_path(f->f_dentry, f->f_vfsmnt, 
+						    path, PAGE_SIZE);
+					fput(f);
+				}
+			}
+
+			sprintf(buf,"'%c'", (cmd>>24) & 0x3f); 
+			if (!isprint(buf[1]))
+			    sprintf(buf, "%02x", buf[1]);
+			printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
+			       "cmd(%08x){%s} arg(%08x) on %s\n",
 			       current->comm, current->pid,
-			       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+			       (int)fd, (unsigned int)cmd, buf, (unsigned int)arg,
+			       fn);
+			if (path) 
+				free_page((unsigned long)path); 
+		}
 		error = -EINVAL;
 	}
 out:
@@ -4109,3 +5238,4 @@
 out2:
 	return error;
 }
+
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	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/ia32/ia32_signal.c	Fri Oct 18 21:03:04 2002
@@ -7,7 +7,7 @@
  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  *  2000-12-*   x86-64 compatibility mode signal handling by Andi Kleen
  * 
- *  $Id: ia32_signal.c,v 1.17 2002/03/21 14:16:32 ak Exp $
+ *  $Id: ia32_signal.c,v 1.22 2002/07/29 10:34:03 ak Exp $
  */
 
 #include <linux/sched.h>
@@ -39,6 +39,7 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+void signal_fault(struct pt_regs *regs, void *frame, char *where);
 
 static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from)
 {
@@ -163,32 +164,38 @@
 	regs->r ## x = reg;			\
 }
 
-#define RELOAD_SEG(seg)							\
+#define RELOAD_SEG(seg,mask)						\
 	{ unsigned int cur; 				\
 	  unsigned short pre;				\
 	  err |= __get_user(pre, &sc->seg);				\
     	  asm volatile("movl %%" #seg ",%0" : "=r" (cur));		\
+	  pre |= mask; 							\
 	  if (pre != cur) loadsegment(seg,pre); }
 
-	/* Reload fs and gs if they have changed in the signal handler. */
+	/* Reload fs and gs if they have changed in the signal handler.
+	   This does not handle long fs/gs base changes in the handler, but 
+	   does not clobber them at least in the normal case. */ 
 	
 	{
-		unsigned short gs; 
+		unsigned gs, oldgs; 
 		err |= __get_user(gs, &sc->gs);
+		gs |= 3; 
+		asm("movl %%gs,%0" : "=r" (oldgs));
+		if (gs != oldgs)
 		load_gs_index(gs); 
 	} 
-	RELOAD_SEG(fs);
-	RELOAD_SEG(ds);
-	RELOAD_SEG(es);
+	RELOAD_SEG(fs,3);
+	RELOAD_SEG(ds,3);
+	RELOAD_SEG(es,3);
 
 	COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
 	COPY(dx); COPY(cx); COPY(ip);
 	/* Don't touch extended registers */ 
 	
 	err |= __get_user(regs->cs, &sc->cs); 
-	regs->cs |= 2;  
+	regs->cs |= 3;  
 	err |= __get_user(regs->ss, &sc->ss); 
-	regs->ss |= 2; 
+	regs->ss |= 3; 
 
 	{
 		unsigned int tmpflags;
@@ -284,7 +291,7 @@
 	return eax;
 
 badframe:
-	signal_fault(&regs, frame, "32bit rt sigreturn"); 
+	signal_fault(&regs,frame,"32bit rt sigreturn");
 	return 0;
 }	
 
@@ -377,8 +384,9 @@
 
 	{
 		struct exec_domain *ed = current_thread_info()->exec_domain;
-		
-		err |= __put_user((ed && ed->signal_invmap && sig < 32
+	err |= __put_user((ed
+		           && ed->signal_invmap
+		           && sig < 32
 		           ? ed->signal_invmap[sig]
 		           : sig),
 		          &frame->sig);
@@ -435,7 +443,7 @@
 give_sigsegv:
 	if (sig == SIGSEGV)
 		ka->sa.sa_handler = SIG_DFL;
-	signal_fault(regs,frame,"32bit signal setup"); 
+	signal_fault(regs,frame,"32bit signal deliver");
 }
 
 void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -449,9 +457,12 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
+
 	{
 		struct exec_domain *ed = current_thread_info()->exec_domain;
-		err |= __put_user((ed && ed->signal_invmap && sig < 32
+	err |= __put_user((ed
+		    	   && ed->signal_invmap
+		    	   && sig < 32
 		    	   ? ed->signal_invmap[sig]
 			   : sig),
 			  &frame->sig);
diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/ia32/ia32entry.S	Fri Oct 18 21:03:04 2002
@@ -27,7 +27,7 @@
  */ 	
 ENTRY(ia32_cstar_target)
 	movq $-ENOSYS,%rax
-	sysret
+	sysretl
 	
 /* 
  * Emulated IA32 system calls via int 0x80. 
@@ -77,6 +77,7 @@
 	jmp ia32_do_syscall
 
 ia32_badsys:
+	movq $0,ORIG_RAX-ARGOFFSET(%rsp)
 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
 	jmp int_ret_from_sys_call
 
@@ -84,6 +85,10 @@
 	movq %rax,%rdi
 	jmp  sys32_ni_syscall			
 
+quiet_ni_syscall:
+	movq $-ENOSYS,%rax
+	ret
+	
 	.macro PTREGSCALL label, func
 	.globl \label
 \label:
@@ -229,7 +234,7 @@
 	.quad stub32_iopl		/* 110 */
 	.quad sys_vhangup
 	.quad ni_syscall	/* old "idle" system call */
-	.quad ni_syscall	/* vm86old */ 
+	.quad sys32_vm86_warning	/* vm86old */ 
 	.quad sys32_wait4
 	.quad sys_swapoff		/* 115 */
 	.quad sys32_sysinfo
@@ -238,7 +243,7 @@
 	.quad stub32_sigreturn
 	.quad stub32_clone		/* 120 */
 	.quad sys_setdomainname
-	.quad sys32_newuname
+	.quad sys_uname
 	.quad sys_modify_ldt
 	.quad sys32_adjtimex
 	.quad sys32_mprotect		/* 125 */
@@ -282,8 +287,8 @@
 	.quad sys_mremap
 	.quad sys_setresuid16
 	.quad sys_getresuid16	/* 165 */
-	.quad ni_syscall	/* vm86 */ 
-	.quad ni_syscall	/* query_module */
+	.quad sys32_vm86_warning	/* vm86 */ 
+	.quad quiet_ni_syscall	/* query_module */
 	.quad sys_poll
 	.quad sys32_nfsservctl
 	.quad sys_setresgid16	/* 170 */
@@ -368,7 +373,7 @@
 	.quad sys_io_cancel
 	.quad sys_ni_syscall /* 250 alloc_huge_pages */
 	.quad sys_ni_syscall /* free_huge_pages */
-	.quad sys_ni_syscall /* exit_group */
+	.quad sys_exit_group /* exit_group */
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
 		.quad ni_syscall
diff -Nru a/arch/x86_64/ia32/ipc32.c b/arch/x86_64/ia32/ipc32.c
--- a/arch/x86_64/ia32/ipc32.c	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/ia32/ipc32.c	Fri Oct 18 21:03:04 2002
@@ -264,6 +264,9 @@
 		if (err2)
 		    err = -EFAULT;
 		break;
+	default:
+		err = -EINVAL;
+		break;
 	}
 	return err;
 }
@@ -284,7 +287,7 @@
 	if (!p)
 		return -ENOMEM;
 	err = get_user(p->mtype, &up->mtype);
-	err |= copy_from_user(p->mtext, &up->mtext, second);
+	err |= (copy_from_user(p->mtext, &up->mtext, second) ? -EFAULT : 0);
 	if (err)
 		goto out;
 	old_fs = get_fs();
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	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/ia32/sys_ia32.c	Fri Oct 18 21:03:04 2002
@@ -35,7 +35,6 @@
 #include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
-#include <linux/binfmts.h>
 #include <linux/mm.h>
 #include <linux/shm.h>
 #include <linux/slab.h>
@@ -56,6 +55,7 @@
 #include <linux/stat.h>
 #include <linux/ipc.h>
 #include <linux/rwsem.h>
+#include <linux/binfmts.h>
 #include <linux/init.h>
 #include <linux/aio_abi.h>
 #include <asm/mman.h>
@@ -264,8 +264,11 @@
 		if (!file)
 			return -EBADF;
 	}
+	
+#if 0 /* reenable when noexec works */
 	if (a.prot & PROT_READ) 
 		a.prot |= PROT_EXEC; 
+#endif
 
 	a.flags |= MAP_32BIT;
 
@@ -275,8 +278,8 @@
 	if (file)
 		fput(file);
 
-	/* Should not happen */
-	if (retval >= 0xFFFFFFFF && (long)retval > 0) { 
+	/* Cannot wrap */
+	if (retval+a.len >= 0xFFFFFFFF && (long)retval > 0) { 
 		do_munmap(mm, retval, a.len); 
 		retval = -ENOMEM; 
 	} 
@@ -964,22 +967,24 @@
 asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long);
 asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
 
-struct iovec *
-get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
+static struct iovec *
+get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp)
 {
 	int i;
 	u32 buf, len;
 	struct iovec *ivp, *iov;
+	unsigned long totlen; 
 
 	/* Get the "struct iovec" from user memory */
 
 	if (!count)
 		return 0;
-	if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
-		return(struct iovec *)0;
 	if (count > UIO_MAXIOV)
 		return(struct iovec *)0;
+	if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+		return(struct iovec *)0;
 	if (count > UIO_FASTIOV) {
+		*errp = -ENOMEM; 
 		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
 		if (!iov)
 			return((struct iovec *)0);
@@ -987,24 +992,33 @@
 		iov = iov_buf;
 
 	ivp = iov;
+	totlen = 0;
 	for (i = 0; i < count; i++) {
-		if (__get_user(len, &iov32->iov_len) ||
-		    __get_user(buf, &iov32->iov_base)) {
-			if (iov != iov_buf)
-				kfree(iov);
-			return((struct iovec *)0);
-		}
-		if (verify_area(type, (void *)A(buf), len)) {
-			if (iov != iov_buf)
-				kfree(iov);
-			return((struct iovec *)0);
-		}
+		*errp = __get_user(len, &iov32->iov_len) |
+		  	__get_user(buf, &iov32->iov_base);	
+		if (*errp)
+			goto error;
+		*errp = verify_area(type, (void *)A(buf), len);
+		if (*errp) 
+			goto error;
+		/* SuS checks: */
+		*errp = -EINVAL; 
+		if ((int)len < 0)
+			goto error;
+		if ((totlen += len) >= 0x7fffffff)
+			goto error;			
 		ivp->iov_base = (void *)A(buf);
 		ivp->iov_len = (__kernel_size_t)len;
 		iov32++;
 		ivp++;
 	}
+	*errp = 0;
 	return(iov);
+
+error:
+	if (iov != iov_buf)
+		kfree(iov);
+	return NULL;
 }
 
 asmlinkage long
@@ -1015,8 +1029,8 @@
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
-	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE)) == (struct iovec *)0)
-		return -EFAULT;
+	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL)
+		return ret;
 	set_fs(KERNEL_DS);
 	ret = sys_readv(fd, iov, count);
 	set_fs(old_fs);
@@ -1033,8 +1047,8 @@
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
-	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ)) == (struct iovec *)0)
-		return -EFAULT;
+	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL)
+		return ret;
 	set_fs(KERNEL_DS);
 	ret = sys_writev(fd, iov, count);
 	set_fs(old_fs);
@@ -1121,7 +1135,7 @@
 
 /*
  * sys_time() can be implemented in user-level using
- * sys_gettimeofday().  IA64 did this but i386 Linux did not
+ * sys_gettimeofday().  x86-64 did this but i386 Linux did not
  * so we have to implement this system call here.
  */
 asmlinkage long sys32_time(int * tloc)
@@ -1288,6 +1302,39 @@
 }
 
 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_flock(&f, (struct flock32 *)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_flock(&f, (struct flock32 *)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)
 {
@@ -1319,40 +1366,34 @@
 {
 	struct flock fl64;  
 	mm_segment_t oldfs = get_fs(); 
-	int ret = 0, origcmd; 
-	unsigned long origarg;
+	int ret = 0; 
+	int oldcmd = cmd;
+	unsigned long oldarg = arg;
 
-	origcmd = cmd; 
-	origarg = arg;
 	switch (cmd) {
-	case F_GETLK: 
-	case F_SETLK:
-	case F_SETLKW:
-		ret = get_flock(&fl64, (struct flock32 *)arg); 
-		arg = (unsigned long) &fl64; 
-		set_fs(KERNEL_DS); 
-		break;
 	case F_GETLK64: 
 		cmd = F_GETLK; 
-		goto cnv64;
+		goto cnv;
 	case F_SETLK64: 
 		cmd = F_SETLK; 
-		goto cnv64; 
+		goto cnv; 
 	case F_SETLKW64:
 		cmd = F_SETLKW; 
-	cnv64:
+	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 (origcmd == F_GETLK && !ret)
-		ret = put_flock(&fl64, (struct flock32 *)origarg); 
-	else if (cmd == F_GETLK && !ret)
-		ret = put_flock64((struct ia32_flock64 *)origarg, &fl64); 
+	if (oldcmd == F_GETLK64 && !ret)
+		ret = put_flock64((struct ia32_flock64 *)oldarg, &fl64); 
 	return ret; 
 }
 
@@ -1804,19 +1845,6 @@
 #endif
 }
 
-extern asmlinkage long sys_newuname(struct new_utsname * name);
-
-asmlinkage long
-sys32_newuname(struct new_utsname * name)
-{
-	int ret = sys_newuname(name);
-	
-	if (current->personality == PER_LINUX32 && !ret) {
-		ret = copy_to_user(name->machine, "i686\0\0", 6);
-	}
-	return ret;
-}
-
 extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
 				    size_t count, loff_t pos);
 
@@ -1825,7 +1853,8 @@
 
 typedef __kernel_ssize_t32 ssize_t32;
 
-/* warning. next two assume LE */
+
+/* warning: next two assume little endian */ 
 asmlinkage ssize_t32
 sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count,
 	    u32 poslo, u32 poshi)
@@ -1849,7 +1878,8 @@
 sys32_personality(unsigned long personality)
 {
 	int ret;
-	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+	if (personality(current->personality) == PER_LINUX32 && 
+		personality == PER_LINUX)
 		personality = PER_LINUX32;
 	ret = sys_personality(personality);
 	if (ret == PER_LINUX32)
@@ -1956,42 +1986,39 @@
 	return ret;
 }
 
-
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-	unsigned long addr, unsigned long len,
+asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags,
 	unsigned long fd, unsigned long pgoff)
 {
-	int error = -EBADF;
+	struct mm_struct *mm = current->mm;
+	unsigned long error;
 	struct file * file = NULL;
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
-			goto out;
+			return -EBADF;
 	}
 
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
+	/* later add PROT_EXEC for PROT_READ here */
+
+	down_write(&mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags|MAP_32BIT, pgoff);
+	up_write(&mm->mmap_sem);
+
+	/* cannot wrap */
+	if (error+len >= 0xFFFFFFFF && (long)error >= 0) { 
+		do_munmap(mm, error, len); 
+		error = -ENOMEM; 
+	} 
 
 	if (file)
 		fput(file);
-out:
 	return error;
 }
 
-asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
-
-asmlinkage int sys32_olduname(struct oldold_utsname * name)
+asmlinkage long sys32_olduname(struct oldold_utsname * name)
 {
 	int error;
 
@@ -2580,6 +2607,19 @@
 		ret = put_user((u32)ctx64, ctx32p);
 	return ret;
 } 
+
+
+int sys32_vm86_warning(void)
+{ 
+	static long warn_time = -(60*HZ); 
+	if (time_before(warn_time + 60*HZ,jiffies)) { 
+		printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n",
+		       current->comm);
+		warn_time = jiffies;
+	} 
+	return -ENOSYS ;
+} 
+
 
 struct exec_domain ia32_exec_domain = { 
 	.name = "linux/x86",
diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
--- a/arch/x86_64/kernel/Makefile	Fri Oct 18 21:03:07 2002
+++ b/arch/x86_64/kernel/Makefile	Fri Oct 18 21:03:07 2002
@@ -9,7 +9,7 @@
 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 \
-		setup64.o bluesmoke.o bootflag.o e820.o reboot.o
+		setup64.o bluesmoke.o bootflag.o e820.o reboot.o profile.o
 
 obj-$(CONFIG_MTRR)	+= mtrr.o
 obj-$(CONFIG_X86_MSR)	+= msr.o
diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
--- a/arch/x86_64/kernel/apic.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/kernel/apic.c	Fri Oct 18 21:03:03 2002
@@ -897,17 +897,9 @@
 
 inline void smp_local_timer_interrupt(struct pt_regs *regs)
 {
-	int user = user_mode(regs);
 	int cpu = smp_processor_id();
 
-	/*
-	 * The profiling function is SMP safe. (nothing can mess
-	 * around with "current", and the profiling counters are
-	 * updated with atomic operations). This is especially
-	 * useful with a profiling multiplier != 1
-	 */
-	if (!user)
-		x86_do_profile(regs->rip);
+	x86_do_profile(regs);
 
 	if (--prof_counter[cpu] <= 0) {
 		/*
@@ -925,7 +917,7 @@
 		}
 
 #ifdef CONFIG_SMP
-		update_process_times(user);
+		update_process_times(user_mode(regs));
 #endif
 	}
 
@@ -951,8 +943,6 @@
  */
 void smp_apic_timer_interrupt(struct pt_regs *regs)
 {
-	int cpu = smp_processor_id();
-
 	/*
 	 * the NMI deadlock-detector uses this.
 	 */
@@ -1084,11 +1074,13 @@
 static __init int setup_disableapic(char *str) 
 { 
 	disable_apic = 1;
+	return 0;
 } 
 
 static __init int setup_noapictimer(char *str) 
 { 
 	disable_apic_timer = 1;
+	return 0;
 } 
 
 __setup("disableapic", setup_disableapic); 
diff -Nru a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
--- a/arch/x86_64/kernel/mpparse.c	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/kernel/mpparse.c	Fri Oct 18 21:03:04 2002
@@ -785,7 +785,7 @@
 	mp_ioapic_routing[idx].irq_end = irq_base + 
 		io_apic_get_redir_entries(idx);
 
-	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, "
+	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
 		"IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
 		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
 		mp_ioapic_routing[idx].irq_start,
diff -Nru a/arch/x86_64/kernel/mtrr.c b/arch/x86_64/kernel/mtrr.c
--- a/arch/x86_64/kernel/mtrr.c	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/kernel/mtrr.c	Fri Oct 18 21:03:04 2002
@@ -1,7 +1,7 @@
 /*  x86-64 MTRR (Memory Type Range Register) driver.
 	Based largely upon arch/i386/kernel/mtrr.c
 
-    Copyright (C) 1997-2000  Richard Gooch
+	Copyright (C) 1997-2000  Richard Gooch
 	Copyright (C) 2002 Dave Jones.
 
     This library is free software; you can redistribute it and/or
@@ -20,7 +20,7 @@
 
 	(For earlier history, see arch/i386/kernel/mtrr.c)
 	v2.00	September 2001	Dave Jones <davej@suse.de>
-		Initial rewrite for x86-64.
+	  Initial rewrite for x86-64.
 	  Removal of non-Intel style MTRR code.
 	v2.01  June 2002  Dave Jones <davej@suse.de>
 	  Removal of redundant abstraction layer.
@@ -84,7 +84,7 @@
 
 typedef u8 mtrr_type;
 
-#define LINE_SIZE      80
+#define LINE_SIZE 80
 
 #ifdef CONFIG_SMP
 #define set_mtrr(reg,base,size,type) set_mtrr_smp (reg, base, size, type)
@@ -124,42 +124,42 @@
 	local_irq_save(ctxt->flags);
 	local_irq_disable();
 
-    /*  Save value of CR4 and clear Page Global Enable (bit 7)  */
+	/* Save value of CR4 and clear Page Global Enable (bit 7)  */
 	if (cpu_has_pge) { 
 	 ctxt->cr4val = read_cr4();
 		write_cr4(ctxt->cr4val & ~(1UL << 7));
-    }
+	}
 
-    /*  Disable and flush caches. Note that wbinvd flushes the TLBs as
-	a side-effect  */
+	/* Disable and flush caches. Note that wbinvd flushes the TLBs as
+	   a side-effect */
 	cr0 = read_cr0() | 0x40000000;
-           wbinvd();
+	wbinvd();
 	write_cr0(cr0);
-           wbinvd();
+	wbinvd();
 
-	/*  Disable MTRRs, and set the default type to uncached  */
+	/* Disable MTRRs, and set the default type to uncached */
 	rdmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
 	wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
 }
 
 
-/*  Restore the processor after a set_mtrr_prepare  */
+/* Restore the processor after a set_mtrr_prepare */
 static void set_mtrr_done (struct set_mtrr_context *ctxt)
 {
-    /*  Flush caches and TLBs  */
-    wbinvd();
+	/* Flush caches and TLBs */
+	wbinvd();
 
-    /*  Restore MTRRdefType  */
+	/* Restore MTRRdefType */
 	wrmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
 
-    /*  Enable caches  */
+	/* Enable caches */
 	write_cr0(read_cr0() & 0xbfffffff);
 
-    /*  Restore value of CR4  */
+	/* Restore value of CR4 */
 	if (cpu_has_pge)
 		write_cr4 (ctxt->cr4val);
 
-    /*  Re-enable interrupts locally (if enabled previously)  */
+	/* Re-enable interrupts locally (if enabled previously) */
 	local_irq_restore(ctxt->flags);
 }
 
@@ -193,21 +193,21 @@
 
 	rdmsr (MSR_MTRRphysMask(reg), mask_lo, mask_hi);
 	if ((mask_lo & 0x800) == 0) {
-	/*  Invalid (i.e. free) range  */
-	*base = 0;
-	*size = 0;
-	*type = 0;
-	return;
-    }
+		/*  Invalid (i.e. free) range  */
+		*base = 0;
+		*size = 0;
+		*type = 0;
+		return;
+	}
 
 	rdmsr (MSR_MTRRphysBase(reg), base_lo, base_hi);
 
-    /* Work out the shifted address mask. */
+	/* Work out the shifted address mask. */
 	newsize = (u64) mask_hi << 32 | (mask_lo & ~0x800);
 	newsize = ~newsize+1;
 	*size = (u32) newsize >> PAGE_SHIFT;
-     *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
-     *type = base_lo & 0xff;
+	*base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
+	*type = base_lo & 0xff;
 }
 
 
@@ -224,7 +224,7 @@
 static void set_mtrr_up (unsigned int reg, u64 base,
 		   u32 size, mtrr_type type, int do_safe)
 {
-    struct set_mtrr_context ctxt;
+	struct set_mtrr_context ctxt;
 	u64 base64;
 	u64 size64;
 
@@ -232,8 +232,8 @@
 		set_mtrr_prepare (&ctxt);
 
 	if (size == 0) {
-	/* The invalid bit is kept in the mask, so we simply clear the
-	   relevant mask register to disable a range. */
+		/* The invalid bit is kept in the mask, so we simply clear the
+		   relevant mask register to disable a range. */
 		wrmsr (MSR_MTRRphysMask(reg), 0, 0);
 	} else {
 		base64 = (base << PAGE_SHIFT) & size_and_mask;
@@ -242,7 +242,7 @@
 		size64 = ~((size << PAGE_SHIFT) - 1);
 		size64 = size64 & size_and_mask;
 		wrmsr (MSR_MTRRphysMask(reg), (u32) (size64 | 0x800), (u32) (size64 >> 32));
-    }
+	}
 	if (do_safe)
 		set_mtrr_done (&ctxt);
 }
@@ -259,7 +259,7 @@
 
 /*  Get the MSR pair relating to a var range  */
 static void __init get_mtrr_var_range (unsigned int index,
-					   struct mtrr_var_range *vr)
+		struct mtrr_var_range *vr)
 {
 	rdmsr (MSR_MTRRphysBase(index), vr->base_lo, vr->base_hi);
 	rdmsr (MSR_MTRRphysMask(index), vr->mask_lo, vr->mask_hi);
@@ -272,35 +272,35 @@
 		struct mtrr_var_range *vr)
 {
 	u32 lo, hi;
-    int changed = FALSE;
+	int changed = FALSE;
 
 	rdmsr (MSR_MTRRphysBase(index), lo, hi);
 	if ((vr->base_lo & 0xfffff0ff) != (lo & 0xfffff0ff) ||
 		(vr->base_hi & 0x000fffff) != (hi & 0x000fffff)) {
 		wrmsr (MSR_MTRRphysBase(index), vr->base_lo, vr->base_hi);
-	changed = TRUE;
-    }
+		changed = TRUE;
+	}
 
 	rdmsr (MSR_MTRRphysMask(index), lo, hi);
 	if ((vr->mask_lo & 0xfffff800) != (lo & 0xfffff800) ||
 		(vr->mask_hi & 0x000fffff) != (hi & 0x000fffff)) {
 		wrmsr (MSR_MTRRphysMask(index), vr->mask_lo, vr->mask_hi);
-	changed = TRUE;
-    }
-    return changed;
+		changed = TRUE;
+	}
+	return changed;
 }
 
 
 static void __init get_fixed_ranges (mtrr_type * frs)
 {
 	u32 *p = (u32 *) frs;
-    int i;
+	int i;
 
 	rdmsr (MSR_MTRRfix64K_00000, p[0], p[1]);
 
-    for (i = 0; i < 2; i++)
+	for (i = 0; i < 2; i++)
 		rdmsr (MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
-    for (i = 0; i < 8; i++)
+	for (i = 0; i < 8; i++)
 		rdmsr (MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
 }
 
@@ -308,8 +308,8 @@
 static int __init set_fixed_ranges_testing (mtrr_type * frs)
 {
 	u32 *p = (u32 *) frs;
-    int changed = FALSE;
-    int i;
+	int changed = FALSE;
+	int i;
 	u32 lo, hi;
 
 	printk (KERN_INFO "mtrr: rdmsr 64K_00000\n");
@@ -317,8 +317,8 @@
 	if (p[0] != lo || p[1] != hi) {
 		printk (KERN_INFO "mtrr: Writing %x:%x to 64K MSR. lohi were %x:%x\n", p[0], p[1], lo, hi);
 		wrmsr (MSR_MTRRfix64K_00000, p[0], p[1]);
-	changed = TRUE;
-    }
+		changed = TRUE;
+	}
 
 	printk (KERN_INFO "mtrr: rdmsr 16K_80000\n");
 	for (i = 0; i < 2; i++) {
@@ -326,9 +326,9 @@
 		if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) {
 			printk (KERN_INFO "mtrr: Writing %x:%x to 16K MSR%d. lohi were %x:%x\n", p[2 + i * 2], p[3 + i * 2], i, lo, hi );
 			wrmsr (MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
-	    changed = TRUE;
+			changed = TRUE;
+		}
 	}
-    }
 
 	printk (KERN_INFO "mtrr: rdmsr 4K_C0000\n");
 	for (i = 0; i < 8; i++) {
@@ -337,18 +337,18 @@
 		if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) {
 			printk (KERN_INFO "mtrr: Writing %x:%x to 4K MSR%d. lohi were %x:%x\n", p[6 + i * 2], p[7 + i * 2], i, lo, hi);
 			wrmsr (MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
-	    changed = TRUE;
+			changed = TRUE;
+		}
 	}
-    }
-    return changed;
+	return changed;
 }
 
 
 struct mtrr_state {
-    unsigned int num_var_ranges;
-    struct mtrr_var_range *var_ranges;
-    mtrr_type fixed_ranges[NUM_FIXED_RANGES];
-    mtrr_type def_type;
+	unsigned int num_var_ranges;
+	struct mtrr_var_range *var_ranges;
+	mtrr_type fixed_ranges[NUM_FIXED_RANGES];
+	mtrr_type def_type;
 	unsigned char enabled;
 };
 
@@ -356,23 +356,23 @@
 /*  Grab all of the MTRR state for this CPU into *state  */
 static void __init get_mtrr_state (struct mtrr_state *state)
 {
-    unsigned int nvrs, i;
-    struct mtrr_var_range *vrs;
+	unsigned int nvrs, i;
+	struct mtrr_var_range *vrs;
 	u32 lo, dummy;
 
 	nvrs = state->num_var_ranges = get_num_var_ranges();
-    vrs = state->var_ranges
-              = kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL);
-    if (vrs == NULL)
-	nvrs = state->num_var_ranges = 0;
-
-    for (i = 0; i < nvrs; i++)
-	get_mtrr_var_range (i, &vrs[i]);
-    get_fixed_ranges (state->fixed_ranges);
+	vrs = state->var_ranges
+	    = kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL);
+	if (vrs == NULL)
+		nvrs = state->num_var_ranges = 0;
+
+	for (i = 0; i < nvrs; i++)
+		get_mtrr_var_range (i, &vrs[i]);
+	get_fixed_ranges (state->fixed_ranges);
 
 	rdmsr (MSR_MTRRdefType, lo, dummy);
-    state->def_type = (lo & 0xff);
-    state->enabled = (lo & 0xc00) >> 10;
+	state->def_type = (lo & 0xff);
+	state->enabled = (lo & 0xc00) >> 10;
 }
 
 
@@ -392,26 +392,26 @@
  *  [RETURNS] 0 if no changes made, else a mask indication what was changed.
  */
 static u64 __init set_mtrr_state (struct mtrr_state *state,
-						struct set_mtrr_context *ctxt)
+		struct set_mtrr_context *ctxt)
 {
-    unsigned int i;
+	unsigned int i;
 	u64 change_mask = 0;
 
-    for (i = 0; i < state->num_var_ranges; i++)
+	for (i = 0; i < state->num_var_ranges; i++)
 		if (set_mtrr_var_range_testing (i, &state->var_ranges[i]))
-	    change_mask |= MTRR_CHANGE_MASK_VARIABLE;
+			change_mask |= MTRR_CHANGE_MASK_VARIABLE;
 
 	if (set_fixed_ranges_testing (state->fixed_ranges))
-	change_mask |= MTRR_CHANGE_MASK_FIXED;
-    /*  Set_mtrr_restore restores the old value of MTRRdefType,
-	so to set it we fiddle with the saved value  */
+		change_mask |= MTRR_CHANGE_MASK_FIXED;
+	/* Set_mtrr_restore restores the old value of MTRRdefType,
+	   so to set it we fiddle with the saved value  */
 	if ((ctxt->deftype_lo & 0xff) != state->def_type
 	    || ((ctxt->deftype_lo & 0xc00) >> 10) != state->enabled) {
-	ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
-	change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
-    }
+		ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
+		change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
+	}
 
-    return change_mask;
+	return change_mask;
 }
 
 
@@ -422,8 +422,8 @@
 struct set_mtrr_data {
 	u64 smp_base;
 	u32 smp_size;
-    unsigned int smp_reg;
-    mtrr_type smp_type;
+	unsigned int smp_reg;
+	mtrr_type smp_type;
 };
 
 /*
@@ -431,67 +431,67 @@
  */
 static void ipi_handler (void *info)
 {
-    struct set_mtrr_data *data = info;
-    struct set_mtrr_context ctxt;
+	struct set_mtrr_data *data = info;
+	struct set_mtrr_context ctxt;
 
 	set_mtrr_prepare (&ctxt);
-    /*  Notify master that I've flushed and disabled my cache  */
-    atomic_dec (&undone_count);
+	/* Notify master that I've flushed and disabled my cache  */
+	atomic_dec (&undone_count);
 	while (wait_barrier_execute)
 		barrier ();
 
-    /*  The master has cleared me to execute  */
+	/* The master has cleared me to execute  */
 	set_mtrr_up (data->smp_reg, data->smp_base, data->smp_size,
-		    data->smp_type, FALSE);
+			data->smp_type, FALSE);
 
-    /*  Notify master CPU that I've executed the function  */
-    atomic_dec (&undone_count);
+	/* Notify master CPU that I've executed the function  */
+	atomic_dec (&undone_count);
 
-    /*  Wait for master to clear me to enable cache and return  */
+	/* Wait for master to clear me to enable cache and return  */
 	while (wait_barrier_cache_enable)
 		barrier ();
-    set_mtrr_done (&ctxt);
+	set_mtrr_done (&ctxt);
 }
 
 
 static void set_mtrr_smp (unsigned int reg, u64 base, u32 size, mtrr_type type)
 {
-    struct set_mtrr_data data;
-    struct set_mtrr_context ctxt;
+	struct set_mtrr_data data;
+	struct set_mtrr_context ctxt;
 
-    data.smp_reg = reg;
-    data.smp_base = base;
-    data.smp_size = size;
-    data.smp_type = type;
-    wait_barrier_execute = TRUE;
-    wait_barrier_cache_enable = TRUE;
+	data.smp_reg = reg;
+	data.smp_base = base;
+	data.smp_size = size;
+	data.smp_type = type;
+	wait_barrier_execute = TRUE;
+	wait_barrier_cache_enable = TRUE;
 	atomic_set (&undone_count, num_online_cpus() - 1);
 
-    /*  Start the ball rolling on other CPUs  */
-    if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
-	panic ("mtrr: timed out waiting for other CPUs\n");
+	/*  Start the ball rolling on other CPUs  */
+	if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
+		panic ("mtrr: timed out waiting for other CPUs\n");
 
-    /* Flush and disable the local CPU's cache */
+	/* Flush and disable the local CPU's cache */
 	set_mtrr_prepare (&ctxt);
 
-    /*  Wait for all other CPUs to flush and disable their caches  */
+	/*  Wait for all other CPUs to flush and disable their caches  */
 	while (atomic_read (&undone_count) > 0)
 		barrier ();
 
 	/* Set up for completion wait and then release other CPUs to change MTRRs */
 	atomic_set (&undone_count, num_online_cpus() - 1);
-    wait_barrier_execute = FALSE;
+	wait_barrier_execute = FALSE;
 	set_mtrr_up (reg, base, size, type, FALSE);
 
-    /*  Now wait for other CPUs to complete the function  */
+	/*  Now wait for other CPUs to complete the function  */
 	while (atomic_read (&undone_count) > 0)
 		barrier ();
 
-    /*  Now all CPUs should have finished the function. Release the barrier to
-	allow them to re-enable their caches and return from their interrupt,
-	then enable the local cache and return  */
-    wait_barrier_cache_enable = FALSE;
-    set_mtrr_done (&ctxt);
+	/*  Now all CPUs should have finished the function. Release the barrier to
+	   allow them to re-enable their caches and return from their interrupt,
+	   then enable the local cache and return  */
+	wait_barrier_cache_enable = FALSE;
+	set_mtrr_done (&ctxt);
 }
 
 
@@ -500,44 +500,44 @@
 {
 	if (!mask)
 		return;
-    if (mask & MTRR_CHANGE_MASK_FIXED)
-	printk ("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
-    if (mask & MTRR_CHANGE_MASK_VARIABLE)
-	printk ("mtrr: your CPUs had inconsistent variable MTRR settings\n");
-    if (mask & MTRR_CHANGE_MASK_DEFTYPE)
-	printk ("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
-    printk ("mtrr: probably your BIOS does not setup all CPUs\n");
+	if (mask & MTRR_CHANGE_MASK_FIXED)
+		printk ("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
+	if (mask & MTRR_CHANGE_MASK_VARIABLE)
+		printk ("mtrr: your CPUs had inconsistent variable MTRR settings\n");
+	if (mask & MTRR_CHANGE_MASK_DEFTYPE)
+		printk ("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
+	printk ("mtrr: probably your BIOS does not setup all CPUs\n");
 }
 
-#endif  /*  CONFIG_SMP  */
+#endif	/*  CONFIG_SMP  */
 
 
 static inline char * attrib_to_str (int x)
 {
-    return (x <= 6) ? mtrr_strings[x] : "?";
+	return (x <= 6) ? mtrr_strings[x] : "?";
 }
 
 
 static void __init init_table (void)
 {
-    int i, max;
+	int i, max;
 
-    max = get_num_var_ranges ();
+	max = get_num_var_ranges ();
 	if ((usage_table = kmalloc (max * sizeof *usage_table, GFP_KERNEL))==NULL) {
-	printk ("mtrr: could not allocate\n");
-	return;
-    }
+		printk ("mtrr: could not allocate\n");
+		return;
+	}
 
 	for (i = 0; i < max; i++)
 		usage_table[i] = 1;
 
 #ifdef USERSPACE_INTERFACE
 	if ((ascii_buffer = kmalloc (max * LINE_SIZE, GFP_KERNEL)) == NULL) {
-	printk ("mtrr: could not allocate\n");
-	return;
-    }
-    ascii_buf_bytes = 0;
-    compute_ascii ();
+		printk ("mtrr: could not allocate\n");
+		return;
+	}
+	ascii_buf_bytes = 0;
+	compute_ascii ();
 #endif
 }
 
@@ -548,18 +548,18 @@
 */
 static int get_free_region(void)
 {
-    int i, max;
-    mtrr_type ltype;
+	int i, max;
+	mtrr_type ltype;
 	u64 lbase;
 	u32 lsize;
 
-    max = get_num_var_ranges ();
+	max = get_num_var_ranges ();
 	for (i = 0; i < max; ++i) {
 		get_mtrr (i, &lbase, &lsize, &ltype);
 		if (lsize == 0)
 			return i;
-    }
-    return -ENOSPC;
+	}
+	return -ENOSPC;
 }
 
 
@@ -597,16 +597,16 @@
 
 int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment)
 {
-    int i, max;
-    mtrr_type ltype;
+	int i, max;
+	mtrr_type ltype;
 	u64 lbase, last;
 	u32 lsize;
 
 	if (base + size < 0x100) {
 		printk (KERN_WARNING
 			"mtrr: cannot set region below 1 MiB (0x%Lx000,0x%x000)\n",
-		    base, size);
-	    return -EINVAL;
+			base, size);
+		return -EINVAL;
 	}
 
 #if defined(__x86_64__) && defined(CONFIG_AGP) 
@@ -621,7 +621,7 @@
 #endif
 
 	/*  Check upper bits of base and last are equal and lower bits are 0
-	    for base and 1 for last  */
+	   for base and 1 for last  */
 	last = base + size - 1;
 	for (lbase = base; !(lbase & 1) && (last & 1);
 	     lbase = lbase >> 1, last = last >> 1) ;
@@ -630,35 +630,36 @@
 		printk (KERN_WARNING
 			"mtrr: base(0x%Lx000) is not aligned on a size(0x%x000) boundary\n",
 			base, size);
-	return -EINVAL;
-    }
+		return -EINVAL;
+	}
 
 	if (type >= MTRR_NUM_TYPES) {
-	printk ("mtrr: type: %u illegal\n", type);
-	return -EINVAL;
-    }
+		printk ("mtrr: type: %u illegal\n", type);
+		return -EINVAL;
+	}
 
-    /*  If the type is WC, check that this processor supports it  */
+	/*  If the type is WC, check that this processor supports it  */
 	if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) {
 		printk (KERN_WARNING
 			"mtrr: your processor doesn't support write-combining\n");
-        return -ENOSYS;
-    }
+		return -ENOSYS;
+	}
 
 	if (base & (size_or_mask>>PAGE_SHIFT)) {
-		printk (KERN_WARNING "mtrr: base(%lx) exceeds the MTRR width(%lx)\n",
-				base, (size_or_mask>>PAGE_SHIFT));
+		printk (KERN_WARNING "mtrr: base(%Lx) exceeds the MTRR width(%Lx)\n",
+				(unsigned long) base,
+				(unsigned long) (size_or_mask>>PAGE_SHIFT));
 		return -EINVAL;
 	}
 
 	if (size & (size_or_mask>>PAGE_SHIFT)) {
 		printk (KERN_WARNING "mtrr: size exceeds the MTRR width\n");
-	return -EINVAL;
-    }
+		return -EINVAL;
+	}
 
-    increment = increment ? 1 : 0;
-    max = get_num_var_ranges ();
-    /*  Search for existing MTRR  */
+	increment = increment ? 1 : 0;
+	max = get_num_var_ranges ();
+	/*  Search for existing MTRR  */
 	down (&mtrr_lock);
 	for (i = 0; i < max; ++i) {
 		get_mtrr (i, &lbase, &lsize, &ltype);
@@ -667,15 +668,15 @@
 		if ((base < lbase) && (base + size <= lbase))
 			continue;
 
-	/*  At this point we know there is some kind of overlap/enclosure  */
+		/*  At this point we know there is some kind of overlap/enclosure  */
 		if ((base < lbase) || (base + size > lbase + lsize)) {
 			up (&mtrr_lock);
 			printk (KERN_WARNING
 				"mtrr: 0x%Lx000,0x%x000 overlaps existing"
 				" 0x%Lx000,0x%x000\n", base, size, lbase, lsize);
-	    return -EINVAL;
-	}
-	/*  New region is enclosed by an existing region  */
+			return -EINVAL;
+		}
+		/*  New region is enclosed by an existing region  */
 		if (ltype != type) {
 			if (type == MTRR_TYPE_UNCACHABLE)
 				continue;
@@ -685,26 +686,26 @@
 			     base, size,
 				 attrib_to_str (ltype),
 			     attrib_to_str (type));
-	    return -EINVAL;
-	}
+			return -EINVAL;
+		}
 		if (increment)
 			++usage_table[i];
-	compute_ascii ();
+		compute_ascii ();
 		up (&mtrr_lock);
-	return i;
-    }
-    /*  Search for an empty MTRR  */
+		return i;
+	}
+	/*  Search for an empty MTRR  */
 	i = get_free_region();
 	if (i < 0) {
 		up (&mtrr_lock);
-	printk ("mtrr: no more MTRRs available\n");
-	return i;
-    }
-    set_mtrr (i, base, size, type);
-    usage_table[i] = 1;
-    compute_ascii ();
+		printk ("mtrr: no more MTRRs available\n");
+		return i;
+	}
+	set_mtrr (i, base, size, type);
+	usage_table[i] = 1;
+	compute_ascii ();
 	up (&mtrr_lock);
-    return i;
+	return i;
 }
 
 
@@ -744,10 +745,10 @@
 int mtrr_add (u64 base, u32 size, unsigned int type, char increment)
 {
 	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
-	printk ("mtrr: size and base must be multiples of 4 kiB\n");
+		printk ("mtrr: size and base must be multiples of 4 kiB\n");
 		printk ("mtrr: size: 0x%x  base: 0x%Lx\n", size, base);
-	return -EINVAL;
-    }
+		return -EINVAL;
+	}
 	return mtrr_add_page (base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
 			      increment);
 }
@@ -767,56 +768,56 @@
  *	On success the register is returned, on failure a negative error
  *	code.
  */
- 
+
 int mtrr_del_page (int reg, u64 base, u32 size)
 {
-    int i, max;
-    mtrr_type ltype;
+	int i, max;
+	mtrr_type ltype;
 	u64 lbase;
 	u32 lsize;
 
-    max = get_num_var_ranges ();
+	max = get_num_var_ranges ();
 	down (&mtrr_lock);
 	if (reg < 0) {
-	/*  Search for existing MTRR  */
+		/*  Search for existing MTRR  */
 		for (i = 0; i < max; ++i) {
 			get_mtrr (i, &lbase, &lsize, &ltype);
 			if (lbase == base && lsize == size) {
-		reg = i;
-		break;
-	    }
-	}
+				reg = i;
+				break;
+			}
+		}
 		if (reg < 0) {
 			up (&mtrr_lock);
 			printk ("mtrr: no MTRR for %Lx000,%x000 found\n", base, size);
-	    return -EINVAL;
+			return -EINVAL;
+		}
 	}
-    }
 
 	if (reg >= max) {
 		up (&mtrr_lock);
-	printk ("mtrr: register: %d too big\n", reg);
-	return -EINVAL;
-    }
+		printk ("mtrr: register: %d too big\n", reg);
+		return -EINVAL;
+	}
 	get_mtrr (reg, &lbase, &lsize, &ltype);
 
 	if (lsize < 1) {
 		up (&mtrr_lock);
-	printk ("mtrr: MTRR %d not used\n", reg);
-	return -EINVAL;
-    }
+		printk ("mtrr: MTRR %d not used\n", reg);
+		return -EINVAL;
+	}
 
 	if (usage_table[reg] < 1) {
 		up (&mtrr_lock);
-	printk ("mtrr: reg: %d has count=0\n", reg);
-	return -EINVAL;
-    }
+		printk ("mtrr: reg: %d has count=0\n", reg);
+		return -EINVAL;
+	}
 
 	if (--usage_table[reg] < 1)
 		set_mtrr (reg, 0, 0, 0);
-    compute_ascii ();
+	compute_ascii ();
 	up (&mtrr_lock);
-    return reg;
+	return reg;
 }
 
 
@@ -834,14 +835,14 @@
  *	On success the register is returned, on failure a negative error
  *	code.
  */
- 
+
 int mtrr_del (int reg, u64 base, u32 size)
 {
 	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
-	printk ("mtrr: size and base must be multiples of 4 kiB\n");
+		printk ("mtrr: size and base must be multiples of 4 kiB\n");
 		printk ("mtrr: size: 0x%x  base: 0x%Lx\n", size, base);
-	return -EINVAL;
-    }
+		return -EINVAL;
+	}
 	return mtrr_del_page (reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
 }
 
@@ -851,64 +852,64 @@
 static int mtrr_file_add (u64 base, u32 size, unsigned int type,
 		struct file *file, int page)
 {
-    int reg, max;
-    unsigned int *fcount = file->private_data;
+	int reg, max;
+	unsigned int *fcount = file->private_data;
 
-    max = get_num_var_ranges ();
+	max = get_num_var_ranges ();
 	if (fcount == NULL) {
 		if ((fcount =
 		     kmalloc (max * sizeof *fcount, GFP_KERNEL)) == NULL) {
-	    printk ("mtrr: could not allocate\n");
-	    return -ENOMEM;
+			printk ("mtrr: could not allocate\n");
+			return -ENOMEM;
+		}
+		memset (fcount, 0, max * sizeof *fcount);
+		file->private_data = fcount;
 	}
-	memset (fcount, 0, max * sizeof *fcount);
-	file->private_data = fcount;
-    }
 
-    if (!page) {
+	if (!page) {
 		if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
 			printk
 			    ("mtrr: size and base must be multiples of 4 kiB\n");
 			printk ("mtrr: size: 0x%x  base: 0x%Lx\n", size, base);
-	    return -EINVAL;
+			return -EINVAL;
+		}
+		base >>= PAGE_SHIFT;
+		size >>= PAGE_SHIFT;
 	}
-	base >>= PAGE_SHIFT;
-	size >>= PAGE_SHIFT;
-    }
 
-    reg = mtrr_add_page (base, size, type, 1);
+	reg = mtrr_add_page (base, size, type, 1);
 
 	if (reg >= 0)
 		++fcount[reg];
-    return reg;
+	return reg;
 }
 
 
 static int mtrr_file_del (u64 base, u32 size,
-			  struct file *file, int page)
+		struct file *file, int page)
 {
-    int reg;
-    unsigned int *fcount = file->private_data;
+	int reg;
+	unsigned int *fcount = file->private_data;
 
-    if (!page) {
+	if (!page) {
 		if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
 			printk
 			    ("mtrr: size and base must be multiples of 4 kiB\n");
 			printk ("mtrr: size: 0x%x  base: 0x%Lx\n", size, base);
-	    return -EINVAL;
+			return -EINVAL;
+		}
+		base >>= PAGE_SHIFT;
+		size >>= PAGE_SHIFT;
 	}
-	base >>= PAGE_SHIFT;
-	size >>= PAGE_SHIFT;
-    }
-    reg = mtrr_del_page (-1, base, size);
+	reg = mtrr_del_page (-1, base, size);
 	if (reg < 0)
 		return reg;
 	if (fcount == NULL)
 		return reg;
 	if (fcount[reg] < 1)
 		return -EINVAL;
-    --fcount[reg];
-    return reg;
+	--fcount[reg];
+	return reg;
 }
 
 
@@ -924,8 +925,8 @@
 	if (copy_to_user (buf, ascii_buffer + *ppos, len))
 		return -EFAULT;
 
-    *ppos += len;
-    return len;
+	*ppos += len;
+	return len;
 }
 
 
@@ -939,240 +940,240 @@
 	int i, err, reg;
 	u64 base;
 	u32 size;
-    char *ptr;
-    char line[LINE_SIZE];
+	char *ptr;
+	char line[LINE_SIZE];
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-    /*  Can't seek (pwrite) on this device  */
+	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
-    memset (line, 0, LINE_SIZE);
+	memset (line, 0, LINE_SIZE);
 
 	if (len > LINE_SIZE)
 		len = LINE_SIZE;
 
 	if (copy_from_user (line, buf, len - 1))
 		return -EFAULT;
-    ptr = line + strlen (line) - 1;
+	ptr = line + strlen (line) - 1;
 
 	if (*ptr == '\n')
 		*ptr = '\0';
 
 	if (!strncmp (line, "disable=", 8)) {
-	reg = simple_strtoul (line + 8, &ptr, 0);
-	err = mtrr_del_page (reg, 0, 0);
+		reg = simple_strtoul (line + 8, &ptr, 0);
+		err = mtrr_del_page (reg, 0, 0);
 		if (err < 0)
 			return err;
-	return len;
-    }
+		return len;
+	}
 
 	if (strncmp (line, "base=", 5)) {
-	printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
-	return -EINVAL;
-    }
+		printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
+		return -EINVAL;
+	}
 
-    base = simple_strtoull (line + 5, &ptr, 0);
+	base = simple_strtoull (line + 5, &ptr, 0);
 
 	for (; isspace (*ptr); ++ptr) ;
 
 	if (strncmp (ptr, "size=", 5)) {
-	printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
-	return -EINVAL;
-    }
+		printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
+		return -EINVAL;
+	}
 
-    size = simple_strtoull (ptr + 5, &ptr, 0);
+	size = simple_strtoull (ptr + 5, &ptr, 0);
 
 	if ((base & 0xfff) || (size & 0xfff)) {
-	printk ("mtrr: size and base must be multiples of 4 kiB\n");
+		printk ("mtrr: size and base must be multiples of 4 kiB\n");
 		printk ("mtrr: size: 0x%x  base: 0x%Lx\n", size, base);
-	return -EINVAL;
-    }
+		return -EINVAL;
+	}
 
 	for (; isspace (*ptr); ++ptr) ;
 
 	if (strncmp (ptr, "type=", 5)) {
-	printk ("mtrr: no \"type=\" in line: \"%s\"\n", line);
-	return -EINVAL;
-    }
-    ptr += 5;
+		printk ("mtrr: no \"type=\" in line: \"%s\"\n", line);
+		return -EINVAL;
+	}
+	ptr += 5;
 
 	for (; isspace (*ptr); ++ptr) ;
 
 	for (i = 0; i < MTRR_NUM_TYPES; ++i) {
 		if (strcmp (ptr, mtrr_strings[i]))
 			continue;
-	base >>= PAGE_SHIFT;
-	size >>= PAGE_SHIFT;
+		base >>= PAGE_SHIFT;
+		size >>= PAGE_SHIFT;
 		err = mtrr_add_page ((u64) base, size, i, 1);
 		if (err < 0)
 			return err;
-	return len;
-    }
-    printk ("mtrr: illegal type: \"%s\"\n", ptr);
-    return -EINVAL;
+		return len;
+	}
+	printk ("mtrr: illegal type: \"%s\"\n", ptr);
+	return -EINVAL;
 }
 
 
 static int mtrr_ioctl (struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg)
+		unsigned int cmd, unsigned long arg)
 {
-    int err;
-    mtrr_type type;
-    struct mtrr_sentry sentry;
-    struct mtrr_gentry gentry;
+	int err;
+	mtrr_type type;
+	struct mtrr_sentry sentry;
+	struct mtrr_gentry gentry;
 
 	switch (cmd) {
-      default:
-	return -ENOIOCTLCMD;
+	default:
+		return -ENOIOCTLCMD;
 
-      case MTRRIOC_ADD_ENTRY:
+	case MTRRIOC_ADD_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
+			return -EFAULT;
 		err = mtrr_file_add (sentry.base, sentry.size, sentry.type,
 				   file, 0);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_SET_ENTRY:
+	case MTRRIOC_SET_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
-	err = mtrr_add (sentry.base, sentry.size, sentry.type, 0);
+			return -EFAULT;
+		err = mtrr_add (sentry.base, sentry.size, sentry.type, 0);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_DEL_ENTRY:
+	case MTRRIOC_DEL_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
-	err = mtrr_file_del (sentry.base, sentry.size, file, 0);
+			return -EFAULT;
+		err = mtrr_file_del (sentry.base, sentry.size, file, 0);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_KILL_ENTRY:
+	case MTRRIOC_KILL_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
-	err = mtrr_del (-1, sentry.base, sentry.size);
+			return -EFAULT;
+		err = mtrr_del (-1, sentry.base, sentry.size);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_GET_ENTRY:
+	case MTRRIOC_GET_ENTRY:
 		if (copy_from_user (&gentry, (void *) arg, sizeof gentry))
-	    return -EFAULT;
+			return -EFAULT;
 		if (gentry.regnum >= get_num_var_ranges ())
 			return -EINVAL;
 		get_mtrr (gentry.regnum, (u64*) &gentry.base, &gentry.size, &type);
 
-	/* Hide entries that go above 4GB */
+		/* Hide entries that go above 4GB */
 		if (gentry.base + gentry.size > 0x100000
 		    || gentry.size == 0x100000)
-	    gentry.base = gentry.size = gentry.type = 0;
-	else {
-	    gentry.base <<= PAGE_SHIFT;
-	    gentry.size <<= PAGE_SHIFT;
-	    gentry.type = type;
-	}
+			gentry.base = gentry.size = gentry.type = 0;
+		else {
+			gentry.base <<= PAGE_SHIFT;
+			gentry.size <<= PAGE_SHIFT;
+			gentry.type = type;
+		}
 
 		if (copy_to_user ((void *) arg, &gentry, sizeof gentry))
-	     return -EFAULT;
-	break;
+			return -EFAULT;
+		break;
 
-      case MTRRIOC_ADD_PAGE_ENTRY:
+	case MTRRIOC_ADD_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
+			return -EFAULT;
 		err = mtrr_file_add (sentry.base, sentry.size, sentry.type, file, 1);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_SET_PAGE_ENTRY:
+	case MTRRIOC_SET_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
-	err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
+			return -EFAULT;
+		err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_DEL_PAGE_ENTRY:
+	case MTRRIOC_DEL_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
-	err = mtrr_file_del (sentry.base, sentry.size, file, 1);
+			return -EFAULT;
+		err = mtrr_file_del (sentry.base, sentry.size, file, 1);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_KILL_PAGE_ENTRY:
+	case MTRRIOC_KILL_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (copy_from_user (&sentry, (void *) arg, sizeof sentry))
-	    return -EFAULT;
-	err = mtrr_del_page (-1, sentry.base, sentry.size);
+			return -EFAULT;
+		err = mtrr_del_page (-1, sentry.base, sentry.size);
 		if (err < 0)
 			return err;
-	break;
+		break;
 
-      case MTRRIOC_GET_PAGE_ENTRY:
+	case MTRRIOC_GET_PAGE_ENTRY:
 		if (copy_from_user (&gentry, (void *) arg, sizeof gentry))
-	    return -EFAULT;
+			return -EFAULT;
 		if (gentry.regnum >= get_num_var_ranges ())
 			return -EINVAL;
 		get_mtrr (gentry.regnum, (u64*) &gentry.base, &gentry.size, &type);
-	gentry.type = type;
+		gentry.type = type;
 
 		if (copy_to_user ((void *) arg, &gentry, sizeof gentry))
-	     return -EFAULT;
-	break;
-    }
-    return 0;
+			return -EFAULT;
+		break;
+	}
+	return 0;
 }
 
 
 static int mtrr_close (struct inode *ino, struct file *file)
 {
-    int i, max;
-    unsigned int *fcount = file->private_data;
+	int i, max;
+	unsigned int *fcount = file->private_data;
 
 	if (fcount == NULL)
 		return 0;
 
 	lock_kernel ();
-    max = get_num_var_ranges ();
+	max = get_num_var_ranges ();
 	for (i = 0; i < max; ++i) {
 		while (fcount[i] > 0) {
 			if (mtrr_del (i, 0, 0) < 0)
 				printk ("mtrr: reg %d not used\n", i);
-	    --fcount[i];
+			--fcount[i];
+		}
 	}
-    }
 	unlock_kernel ();
-    kfree (fcount);
-    file->private_data = NULL;
-    return 0;
+	kfree (fcount);
+	file->private_data = NULL;
+	return 0;
 }
 
 
 static struct file_operations mtrr_fops = {
 	.owner   = THIS_MODULE,
-	.read	 = mtrr_read,
-	.write	 = mtrr_write,
+	.read    = mtrr_read,
+	.write   = mtrr_write,
 	.ioctl   = mtrr_ioctl,
 	.release = mtrr_close,
 };
@@ -1185,38 +1186,38 @@
 
 static void compute_ascii (void)
 {
-    char factor;
-    int i, max;
-    mtrr_type type;
+	char factor;
+	int i, max;
+	mtrr_type type;
 	u64 base;
 	u32 size;
 
-    ascii_buf_bytes = 0;
-    max = get_num_var_ranges ();
+	ascii_buf_bytes = 0;
+	max = get_num_var_ranges ();
 	for (i = 0; i < max; i++) {
 		get_mtrr (i, &base, &size, &type);
 		if (size == 0)
 			usage_table[i] = 0;
 		else {
 			if (size < (0x100000 >> PAGE_SHIFT)) {
-		/* less than 1MB */
-		factor = 'K';
-		size <<= PAGE_SHIFT - 10;
+				/* less than 1MB */
+				factor = 'K';
+				size <<= PAGE_SHIFT - 10;
 			} else {
-		factor = 'M';
-		size >>= 20 - PAGE_SHIFT;
-	    }
+				factor = 'M';
+				size >>= 20 - PAGE_SHIFT;
+			}
 			sprintf (ascii_buffer + ascii_buf_bytes,
 				"reg%02i: base=0x%05Lx000 (%4iMB), size=%4i%cB: %s, count=%d\n",
 				i, base, (u32) base >> (20 - PAGE_SHIFT), size, factor,
-		 attrib_to_str (type), usage_table[i]);
+				attrib_to_str (type), usage_table[i]);
 			ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes);
+		}
 	}
-    }
-    devfs_set_file_size (devfs_handle, ascii_buf_bytes);
+	devfs_set_file_size (devfs_handle, ascii_buf_bytes);
 #ifdef CONFIG_PROC_FS
-    if (proc_root_mtrr)
-	proc_root_mtrr->size = ascii_buf_bytes;
+	if (proc_root_mtrr)
+		proc_root_mtrr->size = ascii_buf_bytes;
 #endif
 }
 
@@ -1225,7 +1226,7 @@
 EXPORT_SYMBOL (mtrr_add);
 EXPORT_SYMBOL (mtrr_del);
 
- 
+
 static void __init mtrr_setup (void)
 {
 	printk ("mtrr: v%s)\n", MTRR_VERSION);
@@ -1234,7 +1235,7 @@
 		 /* Query the width (in bits) of the physical
 		   addressable memory on the Hammer family. */
 		if ((cpuid_eax (0x80000000) >= 0x80000008)) {
-			u32	phys_addr;
+			u32 phys_addr;
 			phys_addr = cpuid_eax (0x80000008) & 0xff;
 			size_or_mask = ~((1L << phys_addr) - 1);
 			/*
@@ -1263,30 +1264,30 @@
 {
 	u64 mask;
 	int count;
-    struct set_mtrr_context ctxt;
+	struct set_mtrr_context ctxt;
 
-    /*  Note that this is not ideal, since the cache is only flushed/disabled
-	for this CPU while the MTRRs are changed, but changing this requires
-	more invasive changes to the way the kernel boots  */
+	/* Note that this is not ideal, since the cache is only flushed/disabled
+	   for this CPU while the MTRRs are changed, but changing this requires
+	   more invasive changes to the way the kernel boots  */
 	set_mtrr_prepare (&ctxt);
-    mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
-    set_mtrr_done (&ctxt);
+	mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
+	set_mtrr_done (&ctxt);
 
-    /*  Use the atomic bitops to update the global mask  */
+	/*  Use the atomic bitops to update the global mask  */
 	for (count = 0; count < sizeof mask * 8; ++count) {
 		if (mask & 0x01)
 			set_bit (count, &smp_changes_mask);
-	mask >>= 1;
-    }
+		mask >>= 1;
+	}
 }
 
-#endif  /*  CONFIG_SMP  */
+#endif	/*  CONFIG_SMP  */
 
 
 int __init mtrr_init (void)
 {
 #ifdef CONFIG_SMP
-    /* mtrr_setup() should already have been called from mtrr_init_boot_cpu() */
+	/* mtrr_setup() should already have been called from mtrr_init_boot_cpu() */
 
 	finalize_mtrr_state (&smp_mtrr_state);
 	mtrr_state_warn (smp_changes_mask);
@@ -1295,17 +1296,17 @@
 #endif
 
 #ifdef CONFIG_PROC_FS
-    proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
-    if (proc_root_mtrr) {
-	proc_root_mtrr->owner = THIS_MODULE;
-	proc_root_mtrr->proc_fops = &mtrr_fops;
-    }
+	proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
+	if (proc_root_mtrr) {
+		proc_root_mtrr->owner = THIS_MODULE;
+		proc_root_mtrr->proc_fops = &mtrr_fops;
+	}
 #endif
 #ifdef CONFIG_DEVFS_FS
-    devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
-				   S_IFREG | S_IRUGO | S_IWUSR,
-				   &mtrr_fops, NULL);
+	devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
+				S_IFREG | S_IRUGO | S_IWUSR,
+				&mtrr_fops, NULL);
 #endif
-    init_table ();
-    return 0;
+	init_table ();
+	return 0;
 }
diff -Nru a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
--- a/arch/x86_64/kernel/nmi.c	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/kernel/nmi.c	Fri Oct 18 21:03:04 2002
@@ -23,6 +23,7 @@
 #include <asm/smp.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
+#include <asm/nmi.h>
 
 unsigned int nmi_watchdog = NMI_LOCAL_APIC;
 static unsigned int nmi_hz = HZ;
@@ -137,6 +138,18 @@
 	return 0;
 }
 
+struct pm_dev * set_nmi_pm_callback(pm_callback callback)
+{
+	apic_pm_unregister(nmi_pmdev);
+	return apic_pm_register(PM_SYS_DEV, 0, callback);
+}
+
+void unset_nmi_pm_callback(struct pm_dev * dev)
+{
+	apic_pm_unregister(dev);
+	nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
+}
+
 static void nmi_pm_init(void)
 {
 	if (!nmi_pmdev)
@@ -178,7 +191,7 @@
 		| K7_NMI_EVENT;
 
 	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
-	printk(KERN_INFO "watchdog: setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
+	printk(KERN_INFO "watchdog: setting K7_PERFCTR0 to %08x\n", -(cpu_khz/nmi_hz*1000));
 	wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= K7_EVNTSEL_ENABLE;
@@ -274,4 +287,31 @@
 	}
 	if (nmi_perfctr_msr)
 		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+}
+
+static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
+{
+	return 0;
+}
+ 
+static nmi_callback_t nmi_callback = dummy_nmi_callback;
+ 
+asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
+{
+	int cpu = smp_processor_id();
+
+	add_pda(__nmi_count,1);
+
+	if (!nmi_callback(regs, cpu))
+		default_do_nmi(regs);
+}
+
+void set_nmi_callback(nmi_callback_t callback)
+{
+	nmi_callback = callback;
+}
+
+void unset_nmi_callback(void)
+{
+	nmi_callback = dummy_nmi_callback;
 }
diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
--- a/arch/x86_64/kernel/process.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/kernel/process.c	Fri Oct 18 21:03:03 2002
@@ -32,6 +32,7 @@
 #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>
diff -Nru a/arch/x86_64/kernel/profile.c b/arch/x86_64/kernel/profile.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/x86_64/kernel/profile.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,45 @@
+/*
+ *	linux/arch/i386/kernel/profile.c
+ *
+ *	(C) 2002 John Levon <levon@movementarian.org>
+ *
+ */
+
+#include <linux/profile.h>
+#include <linux/spinlock.h>
+#include <linux/notifier.h>
+#include <linux/irq.h>
+#include <asm/hw_irq.h> 
+ 
+static struct notifier_block * profile_listeners;
+static rwlock_t profile_lock = RW_LOCK_UNLOCKED;
+ 
+int register_profile_notifier(struct notifier_block * nb)
+{
+	int err;
+	write_lock_irq(&profile_lock);
+	err = notifier_chain_register(&profile_listeners, nb);
+	write_unlock_irq(&profile_lock);
+	return err;
+}
+
+
+int unregister_profile_notifier(struct notifier_block * nb)
+{
+	int err;
+	write_lock_irq(&profile_lock);
+	err = notifier_chain_unregister(&profile_listeners, nb);
+	write_unlock_irq(&profile_lock);
+	return err;
+}
+
+
+void x86_profile_hook(struct pt_regs * regs)
+{
+	/* we would not even need this lock if
+	 * we had a global cli() on register/unregister
+	 */ 
+	read_lock(&profile_lock);
+	notifier_call_chain(&profile_listeners, 0, regs);
+	read_unlock(&profile_lock);
+}
diff -Nru a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c
--- a/arch/x86_64/kernel/reboot.c	Fri Oct 18 21:03:04 2002
+++ b/arch/x86_64/kernel/reboot.c	Fri Oct 18 21:03:04 2002
@@ -8,6 +8,7 @@
 #include <asm/io.h>
 #include <asm/kdebug.h>
 #include <asm/delay.h>
+#include <asm/hw_irq.h>
 
 
 /*
diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
--- a/arch/x86_64/kernel/setup.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/kernel/setup.c	Fri Oct 18 21:03:03 2002
@@ -234,7 +234,6 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-	unsigned long bootmap_size, low_mem_size;
 	int i;
 
  	ROOT_DEV = ORIG_ROOT_DEV;
@@ -284,14 +283,8 @@
 
 	contig_initmem_init(); 
 
-	/*
-	 * Reserve the bootmem bitmap itself as well. We do this in two
-	 * steps (first step was init_bootmem()) because this catches
-	 * the (very unlikely) case of us accidentally initializing the
-	 * bootmem allocator with an invalid RAM area.
-	 */
-	reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
-			 bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+	/* reserve kernel */
+	reserve_bootmem(HIGH_MEMORY, PFN_PHYS(start_pfn) - HIGH_MEMORY); 
 
 	/*
 	 * reserve physical page 0 - it's a special BIOS page on many boxes,
diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
--- a/arch/x86_64/kernel/traps.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/kernel/traps.c	Fri Oct 18 21:03:03 2002
@@ -559,11 +559,10 @@
 	printk("Do you have a strange power saving mode enabled?\n");
 }
 
-asmlinkage void do_nmi(struct pt_regs * regs)
+asmlinkage void default_do_nmi(struct pt_regs * regs)
 {
 	unsigned char reason = inb(0x61);
 
-	add_pda(__nmi_count,1);
 	if (!(reason & 0xc0)) {
 #if CONFIG_X86_LOCAL_APIC
 		/*
diff -Nru a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile
--- a/arch/x86_64/mm/Makefile	Fri Oct 18 21:03:07 2002
+++ b/arch/x86_64/mm/Makefile	Fri Oct 18 21:03:07 2002
@@ -1,13 +1,9 @@
 #
 # Makefile for the linux i386-specific parts of the memory manager.
 #
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
 
-O_TARGET := mm.o
-obj-y	 := init.o fault.o ioremap.o extable.o modutil.o
+export-objs := pageattr.o
+
+obj-y	 := init.o fault.o ioremap.o extable.o modutil.o pageattr.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
--- a/arch/x86_64/mm/fault.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/mm/fault.c	Fri Oct 18 21:03:03 2002
@@ -32,18 +32,14 @@
 
 extern void die(const char *,struct pt_regs *,long);
 
-extern spinlock_t console_lock, timerlist_lock;
+extern spinlock_t console_lock;
 
 void bust_spinlocks(int yes)
 {
- 	spin_lock_init(&timerlist_lock);
+	int loglevel_save = console_loglevel;
 	if (yes) {
 		oops_in_progress = 1;
-#ifdef CONFIG_SMP
-		global_irq_lock = 0;	/* Many serial drivers do __global_cli() */
-#endif
 	} else {
-	int loglevel_save = console_loglevel;
 #ifdef CONFIG_VT
 		unblank_screen();
 #endif
@@ -108,6 +104,18 @@
 	int write;
 	siginfo_t info;
 
+#ifdef CONFIG_CHECKING
+	{ 
+		unsigned long gs; 
+		struct x8664_pda *pda = cpu_pda + stack_smp_processor_id(); 
+		rdmsrl(MSR_GS_BASE, gs); 
+		if (gs != (unsigned long)pda) { 
+			wrmsrl(MSR_GS_BASE, pda); 
+			printk("page_fault: wrong gs %lx expected %p\n", gs, pda);
+		}
+	}
+#endif
+
 	/* get the address */
 	__asm__("movq %%cr2,%0":"=r" (address));
 
@@ -129,7 +137,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;
 
  again:
@@ -223,7 +231,7 @@
 	/* Are we prepared to handle this kernel fault?  */
 	if ((fixup = search_exception_table(regs->rip)) != 0) {
 		regs->rip = fixup;
-		if (exception_trace) 
+		if (0 && exception_trace) 
 		printk(KERN_ERR 
 		       "%s: fixed kernel exception at %lx address %lx err:%ld\n", 
 		       current->comm, regs->rip, address, error_code);
diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
--- a/arch/x86_64/mm/init.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/mm/init.c	Fri Oct 18 21:03:03 2002
@@ -37,6 +37,8 @@
 #include <asm/tlb.h>
 #include <asm/mmu_context.h>
 
+unsigned long start_pfn, end_pfn;
+
 mmu_gather_t mmu_gathers[NR_CPUS];
 
 /*
@@ -49,19 +51,24 @@
 {
 	int i, total = 0, reserved = 0;
 	int shared = 0, cached = 0;
+	pg_data_t *pgdat;
+	struct page *page;
 
 	printk("Mem-info:\n");
 	show_free_areas();
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	i = max_mapnr;
-	while (i-- > 0) {
+
+	for_each_pgdat(pgdat) {
+               for (i = 0; i < pgdat->node_size; ++i) {
+                       page = pgdat->node_mem_map + i;
 		total++;
-		if (PageReserved(mem_map+i))
+                       if (PageReserved(page))
 			reserved++;
-		else if (PageSwapCache(mem_map+i))
+                       else if (PageSwapCache(page))
 			cached++;
-		else if (page_count(mem_map+i))
-			shared += page_count(mem_map+i) - 1;
+                       else if (page_count(page))
+                               shared += page_count(page) - 1;
+               }
 	}
 	printk("%d pages of RAM\n", total);
 	printk("%d reserved pages\n",reserved);
@@ -264,16 +271,15 @@
 {
 	{
 		unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
-		unsigned int max_dma, low;
+		unsigned int max_dma;
 
 		max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-		low = max_low_pfn;
 
-		if (low < max_dma)
-			zones_size[ZONE_DMA] = low;
+		if (end_pfn < max_dma)
+			zones_size[ZONE_DMA] = end_pfn;
 		else {
 			zones_size[ZONE_DMA] = max_dma;
-			zones_size[ZONE_NORMAL] = low - max_dma;
+			zones_size[ZONE_NORMAL] = end_pfn - max_dma;
 		}
 		free_area_init(zones_size);
 	}
@@ -308,11 +314,15 @@
 	int codesize, reservedpages, datasize, initsize;
 	int tmp;
 
+	printk("mem_init\n");
+
 	if (!mem_map)
 		BUG();
 
-	max_mapnr = num_physpages = max_low_pfn;
-	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+	max_low_pfn = end_pfn;
+	max_pfn = end_pfn;
+	max_mapnr = num_physpages = end_pfn;
+	high_memory = (void *) __va(end_pfn * PAGE_SIZE);
 
 	/* clear the zero-page */
 	memset(empty_zero_page, 0, PAGE_SIZE);
@@ -323,7 +333,7 @@
 	after_bootmem = 1;
 
 	reservedpages = 0;
-	for (tmp = 0; tmp < max_low_pfn; tmp++)
+	for (tmp = 0; tmp < end_pfn; tmp++)
 		/*
 		 * Only count reserved RAM pages
 		 */
diff -Nru a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
--- a/arch/x86_64/mm/ioremap.c	Fri Oct 18 21:03:08 2002
+++ b/arch/x86_64/mm/ioremap.c	Fri Oct 18 21:03:08 2002
@@ -10,6 +10,7 @@
 
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
@@ -157,14 +158,72 @@
 		return NULL;
 	addr = area->addr;
 	if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
-		vfree(addr);
+		vunmap(addr);
 		return NULL;
 	}
 	return (void *) (offset + (char *)addr);
 }
 
+/**
+ * ioremap_nocache     -   map bus memory into CPU space
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap_nocache performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address. 
+ *
+ * This version of ioremap ensures that the memory is marked uncachable
+ * on the CPU as well as honouring existing caching rules from things like
+ * the PCI bus. Note that there are other caches and buffers on many 
+ * busses. In particular driver authors should read up on PCI writes
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
+ * 
+ * Must be freed with iounmap.
+ */
+
+void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+{
+	void *p = __ioremap(phys_addr, size, _PAGE_PCD);
+	if (!p) 
+		return p; 
+
+	if (phys_addr + size < virt_to_phys(high_memory)) { 
+		struct page *ppage = virt_to_page(__va(phys_addr));		
+		unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+		BUG_ON(phys_addr+size > (unsigned long)high_memory);
+		BUG_ON(phys_addr + size < phys_addr);
+
+		if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { 
+			iounmap(p); 
+			p = NULL;
+		}
+	} 
+
+	return p;					
+}
+
 void iounmap(void *addr)
 {
-	if (addr > high_memory)
-		vfree((void *) (PAGE_MASK & (unsigned long) addr));
+	struct vm_struct *p;
+	if (addr <= high_memory) 
+		return; 
+	p = remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr)); 
+	if (!p) { 
+		printk("__iounmap: bad address %p\n", addr);
+		return;
+	} 
+
+	unmap_vm_area(p);
+	if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { 
+		change_page_attr(virt_to_page(__va(p->phys_addr)),
+				 p->size >> PAGE_SHIFT,
+				 PAGE_KERNEL); 				 
+	} 
+	kfree(p); 
 }
diff -Nru a/arch/x86_64/mm/modutil.c b/arch/x86_64/mm/modutil.c
--- a/arch/x86_64/mm/modutil.c	Fri Oct 18 21:03:03 2002
+++ b/arch/x86_64/mm/modutil.c	Fri Oct 18 21:03:03 2002
@@ -13,12 +13,15 @@
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
 
 static struct vm_struct * modvmlist = NULL;
 
 void module_unmap (void * addr)
 {
 	struct vm_struct **p, *tmp;
+	int i;
 
 	if (!addr)
 		return;
@@ -29,21 +32,33 @@
 	for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
 		if (tmp->addr == addr) {
 			*p = tmp->next;
-			vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
-			kfree(tmp);
-			return;
+			goto found;
 		}
 	}
 	printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
+	return;
+ found:
+	unmap_vm_area(tmp);
+	for (i = 0; i < tmp->nr_pages; i++) {
+		if (unlikely(!tmp->pages[i]))
+			BUG();
+		__free_page(tmp->pages[i]);
+	}
+	
+	kfree(tmp->pages);
+	kfree(tmp);					
 }
 
 void * module_map (unsigned long size)
 {
-	void * addr;
 	struct vm_struct **p, *tmp, *area;
+	struct page **pages;
+	void * addr;
+	unsigned int nr_pages, array_size, i;
 
 	size = PAGE_ALIGN(size);
-	if (!size || size > MODULES_LEN) return NULL;
+	if (!size || size > MODULES_LEN)
+		return NULL;
 		
 	addr = (void *) MODULES_VADDR;
 	for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) {
@@ -51,18 +66,53 @@
 			break;
 		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
 	}
-	if ((unsigned long) addr + size >= MODULES_END) return NULL;
+	if ((unsigned long) addr + size >= MODULES_END)
+		return NULL;
 	
 	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
-	if (!area) return NULL;
+	if (!area)
+		return NULL;
 	area->size = size + PAGE_SIZE;
 	area->addr = addr;
 	area->next = *p;
+	area->pages = NULL;
+	area->nr_pages = 0;
+	area->phys_addr = 0;
 	*p = area;
 
-	if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL)) {
-		module_unmap(addr);
-		return NULL;
+	nr_pages = size >> PAGE_SHIFT;
+	array_size = (nr_pages * sizeof(struct page *));
+
+	area->nr_pages = nr_pages;
+	area->pages = pages = kmalloc(array_size, GFP_KERNEL);
+	if (!area->pages)
+		goto fail;
+
+	memset(area->pages, 0, array_size);
+
+	for (i = 0; i < area->nr_pages; i++) {
+		area->pages[i] = alloc_page(GFP_KERNEL);
+		if (unlikely(!area->pages[i]))
+			goto fail;
 	}
-	return addr;
+	
+	if (map_vm_area(area, PAGE_KERNEL, &pages)) {
+		unmap_vm_area(area);
+		goto fail;
+	}
+
+	return area->addr;
+
+fail:
+	if (area->pages) {
+		for (i = 0; i < area->nr_pages; i++) {
+			if (area->pages[i])
+				__free_page(area->pages[i]);
+		}
+		kfree(area->pages);
+	}
+	kfree(area);
+
+	return NULL;
 }
+
diff -Nru a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/x86_64/mm/pageattr.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,210 @@
+/* 
+ * Copyright 2002 Andi Kleen, SuSE Labs. 
+ * Thanks to Ben LaHaise for precious feedback.
+ */ 
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/tlbflush.h>
+#include <asm/io.h>
+
+static inline pte_t *lookup_address(unsigned long address) 
+{ 
+	pgd_t *pgd = pgd_offset_k(address); 
+	pmd_t *pmd;
+	pte_t *pte;
+	if (!pgd || !pgd_present(*pgd))
+		return NULL; 
+	pmd = pmd_offset(pgd, address); 	       
+	if (!pmd_present(*pmd))
+		return NULL; 
+	if (pmd_large(*pmd))
+		return (pte_t *)pmd;
+	pte = pte_offset_kernel(pmd, address);
+	if (pte && !pte_present(*pte))
+		pte = NULL; 
+	return pte;
+} 
+
+static struct page *split_large_page(unsigned long address, pgprot_t prot)
+{ 
+	int i; 
+	unsigned long addr;
+	struct page *base = alloc_pages(GFP_KERNEL, 0);
+	pte_t *pbase;
+	if (!base) 
+		return NULL;
+	address = __pa(address);
+	addr = address & LARGE_PAGE_MASK; 
+	pbase = (pte_t *)page_address(base);
+	for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
+		pbase[i] = pfn_pte(addr >> PAGE_SHIFT, 
+				   addr == address ? prot : PAGE_KERNEL);
+	}
+	return base;
+} 
+
+
+static void flush_kernel_map(void *address) 
+{
+	if (address && cpu_has_clflush) {
+		/* is this worth it? */ 
+		int i;
+		for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) 
+			asm volatile("clflush %0" :: "m" (address + i)); 
+	} else
+		asm volatile("wbinvd":::"memory"); 
+	__flush_tlb_one(address);
+}
+
+/* 
+ * No more special protections in this 2/4MB area - revert to a
+ * large page again. 
+ */
+static inline void revert_page(struct page *kpte_page, unsigned long address)
+{
+       pgd_t *pgd;
+       pmd_t *pmd; 
+       pte_t large_pte; 
+       
+       pgd = pgd_offset_k(address); 
+       if (!pgd) BUG(); 
+       pmd = pmd_offset(pgd, address);
+       if (!pmd) BUG(); 
+       if ((pmd_val(*pmd) & _PAGE_GLOBAL) == 0) BUG(); 
+       
+       large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, PAGE_KERNEL_LARGE);
+       set_pte((pte_t *)pmd, large_pte);
+}      
+
+static int
+__change_page_attr(unsigned long address, struct page *page, pgprot_t prot, 
+		   struct page **oldpage) 
+{ 
+	pte_t *kpte; 
+	struct page *kpte_page;
+	unsigned kpte_flags;
+
+	kpte = lookup_address(address);
+	if (!kpte) return 0;
+	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
+	kpte_flags = pte_val(*kpte); 
+	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { 
+		if ((kpte_flags & _PAGE_PSE) == 0) { 
+			pte_t old = *kpte;
+			pte_t standard = mk_pte(page, PAGE_KERNEL); 
+
+			set_pte(kpte, mk_pte(page, prot)); 
+			if (pte_same(old,standard))
+				atomic_inc(&kpte_page->count);
+		} else {
+			struct page *split = split_large_page(address, prot); 
+			if (!split)
+				return -ENOMEM;
+			set_pte(kpte,mk_pte(split, PAGE_KERNEL));
+		}	
+	} else if ((kpte_flags & _PAGE_PSE) == 0) { 
+		set_pte(kpte, mk_pte(page, PAGE_KERNEL));
+		atomic_dec(&kpte_page->count); 
+	}
+
+	if (atomic_read(&kpte_page->count) == 1) { 
+		*oldpage = kpte_page;
+		revert_page(kpte_page, address);
+	} 
+	return 0;
+} 
+
+static inline void flush_map(unsigned long address)
+{	
+#ifdef CONFIG_SMP 
+	smp_call_function(flush_kernel_map, (void *)address, 1, 1);
+#endif	
+	flush_kernel_map((void *)address);
+}
+
+struct deferred_page { 
+	struct deferred_page *next; 
+	struct page *fpage;
+	unsigned long address;
+}; 
+static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */
+
+static inline void save_page(unsigned long address, struct page *fpage)
+{
+	struct deferred_page *df;
+	df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); 
+	if (!df) {
+		flush_map(address);
+		__free_page(fpage);
+	} else { 
+		df->next = df_list;
+		df->fpage = fpage;
+		df->address = address;
+		df_list = df;
+	} 			
+}
+
+/*
+ * Change the page attributes of an page in the linear mapping.
+ *
+ * This should be used when a page is mapped with a different caching policy
+ * than write-back somewhere - some CPUs do not like it when mappings with
+ * different caching policies exist. This changes the page attributes of the
+ * in kernel linear mapping too.
+ * 
+ * The caller needs to ensure that there are no conflicting mappings elsewhere.
+ * This function only deals with the kernel linear map.
+ * 
+ * Caller must call global_flush_tlb() after this.
+ */
+int change_page_attr(struct page *page, int numpages, pgprot_t prot)
+{
+	int err = 0; 
+	struct page *fpage, *fpage2; 
+	int i; 
+
+	down_write(&init_mm.mmap_sem);
+	for (i = 0; i < numpages; i++, page++) { 
+		unsigned long address = (unsigned long)page_address(page); 
+		fpage = NULL;
+		err = __change_page_attr(address, page, prot, &fpage); 
+		/* Handle kernel mapping too which aliases part of the lowmem */
+		if (!err && page_to_phys(page) < KERNEL_TEXT_SIZE) {		
+			unsigned long addr2 = __START_KERNEL_map + page_to_phys(page);
+			fpage2 = NULL;
+			err = __change_page_attr(addr2, page, prot, &fpage2); 
+			if (fpage2) 
+				save_page(addr2, fpage2); 		     
+		} 
+		if (fpage)
+			save_page(address, fpage);
+	} 	
+	up_write(&init_mm.mmap_sem); 
+	return err;
+}
+
+void global_flush_tlb(void)
+{ 
+	struct deferred_page *df, *next_df;
+
+	down_read(&init_mm.mmap_sem);
+	df = xchg(&df_list, NULL);
+	up_read(&init_mm.mmap_sem);
+	flush_map((df && !df->next) ? df->address : 0);
+	for (; df; df = next_df) { 
+		next_df = df->next;
+		if (df->fpage) 
+			__free_page(df->fpage);
+		kfree(df);
+	} 
+} 
+
+EXPORT_SYMBOL(change_page_attr);
+EXPORT_SYMBOL(global_flush_tlb);
diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
--- a/drivers/acorn/block/fd1772.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/acorn/block/fd1772.c	Fri Oct 18 21:03:04 2002
@@ -156,6 +156,7 @@
 #define FLOPPY_DMA 0
 #define DEVICE_NAME "floppy"
 #define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&floppy_queue)
 #include <linux/blk.h>
 
 /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
@@ -179,6 +180,8 @@
 #define DPRINT(a)
 #endif
 
+static struct request_queue floppy_queue;
+
 /* Disk types: DD */
 static struct archy_disk_type {
 	const char *name;
@@ -1140,14 +1143,11 @@
    - but if it sees a disc change line go high (?) it flips to using
    it. Well  maybe I'll add that in the future (!?)
 */
-static int check_floppy_change(dev_t dev)
+static int check_floppy_change(struct gendisk *disk)
 {
-	unsigned int drive = (dev & 0x03);
+	struct archy_floppy_struct *p = disk->private_data;
+	unsigned int drive = p - unit;
 
-	if (major(dev) != MAJOR_NR) {
-		printk("floppy_changed: not a floppy\n");
-		return 0;
-	}
 	if (test_bit(drive, &fake_change)) {
 		/* simulated change (e.g. after formatting) */
 		return 1;
@@ -1156,7 +1156,7 @@
 		/* surely changed (the WP signal changed at least once) */
 		return 1;
 	}
-	if (unit[drive].wpstat) {
+	if (p->wpstat) {
 		/* WP is on -> could be changed: to be sure, buffers should be
 		   * invalidated...
 		 */
@@ -1165,9 +1165,10 @@
 	return 1; /* DAG - was 0 */
 }
 
-static int floppy_revalidate(dev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
 {
-	int drive = dev & 3;
+	struct archy_floppy_struct *p = disk->private_data;
+	unsigned int drive = p - unit;
 
 	if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
 	    || unit[drive].disktype == 0) {
@@ -1176,7 +1177,7 @@
 #endif
 		clear_bit(drive, &fake_change);
 		clear_bit(drive, &changed_floppies);
-		unit[drive].disktype = 0;
+		p->disktype = 0;
 	}
 	return 0;
 }
@@ -1521,23 +1522,24 @@
 
 static struct block_device_operations floppy_fops =
 {
-	.open			= floppy_open,
-	.release		= floppy_release,
-	.ioctl			= fd_ioctl,
-	.check_media_change	= check_floppy_change,
-	.revalidate		= floppy_revalidate,
+	.open		= floppy_open,
+	.release	= floppy_release,
+	.ioctl		= fd_ioctl,
+	.media_changed	= check_floppy_change,
+	.revalidate_disk= floppy_revalidate,
 };
 
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
 {
-	int drive = minor & 3;
-	if ((minor>> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
+	int drive = *part & 3;
+	if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
 		return NULL;
-	return disks[drive];
+	return get_disk(disks[drive]);
 }
 
 int fd1772_init(void)
 {
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
 	int i;
 
 	if (!machine_is_archimedes())
@@ -1580,16 +1582,19 @@
 	   out of some special memory... */
 	DMABuffer = (char *) kmalloc(2048);	/* Copes with pretty large sectors */
 #endif
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request);
+	blk_init_queue(&floppy_queue, do_fd_request, &lock);
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].track = -1;
 		disks[i]->major = MAJOR_NR;
 		disks[i]->first_minor = 0;
 		disks[i]->fops = &floppy_fops;
 		sprintf(disks[i]->disk_name, "fd%d", i);
+		disks[i]->private_data = &unit[i];
+		disks[i]->queue = &floppy_queue;
 		set_capacity(disks[i], MAX_DISK_SIZE * 2);
 	}
-	blk_set_probe(MAJOR_NR, floppy_find);
+	blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+				floppy_find, NULL, NULL);
 
 	for (i = 0; i < FD_MAX_UNITS; i++)
 		add_disk(disks[i]);
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/acorn/block/mfmhd.c	Fri Oct 18 21:03:03 2002
@@ -114,7 +114,7 @@
 #include <linux/delay.h>
 
 #define MAJOR_NR	MFM_ACORN_MAJOR
-#define DEVICE_NR(device) (minor(device) >> 6)
+#define QUEUE (&mfm_queue)
 #include <linux/blk.h>
 #include <linux/blkpg.h>
 
@@ -128,6 +128,8 @@
 #include <asm/hardware/ioc.h>
 
 static void (*do_mfm)(void) = NULL;
+static struct request_queue mfm_queue;
+static spinlock_t mfm_lock = SPIN_LOCK_UNLOCKED;
 /*
  * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
  */
@@ -225,7 +227,7 @@
 static void mfm_rerequest(void);
 static void mfm_request(void);
 static void mfm_specify (void);
-static void issue_request(int dev, unsigned int block, unsigned int nsect,
+static void issue_request(unsigned int block, unsigned int nsect,
 			  struct request *req);
 
 static unsigned int mfm_addr;		/* Controller address */
@@ -739,7 +741,7 @@
 			/* Yep - a partial access */
 
 			/* and issue the remainder */
-			issue_request(minor(CURRENT->rq_dev), PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
+			issue_request(PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
 			return;
 		}
 
@@ -794,30 +796,31 @@
  * Actually gets round to issuing the request - note everything at this
  * point is in 256 byte sectors not Linux 512 byte blocks
  */
-static void issue_request(int dev, unsigned int block, unsigned int nsect,
+static void issue_request(unsigned int block, unsigned int nsect,
 			  struct request *req)
 {
+	struct gendisk *disk = req->rq_disk;
+	struct mfm_info *p = disk->private_data;
 	int track, start_head, start_sector;
 	int sectors_to_next_cyl;
+	dev = p - mfm_info;
 
-	dev >>= 6;
-
-	track = block / mfm_info[dev].sectors;
-	start_sector = block % mfm_info[dev].sectors;
-	start_head = track % mfm_info[dev].heads;
+	track = block / p->sectors;
+	start_sector = block % p->sectors;
+	start_head = track % p->heads;
 
 	/* First get the number of whole tracks which are free before the next
 	   track */
-	sectors_to_next_cyl = (mfm_info[dev].heads - (start_head + 1)) * mfm_info[dev].sectors;
+	sectors_to_next_cyl = (p->heads - (start_head + 1)) * p->sectors;
 	/* Then add in the number of sectors left on this track */
-	sectors_to_next_cyl += (mfm_info[dev].sectors - start_sector);
+	sectors_to_next_cyl += (p->sectors - start_sector);
 
-	DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", mfm_info[dev].sectors, track);
+	DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", p->sectors, track);
 
 	raw_cmd.dev = dev;
 	raw_cmd.sector = start_sector;
 	raw_cmd.head = start_head;
-	raw_cmd.cylinder = track / mfm_info[dev].heads;
+	raw_cmd.cylinder = track / p->heads;
 	raw_cmd.cmdtype = CURRENT->cmd;
 	raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
 	raw_cmd.cmddata[0] = dev + 1;	/* DAG: +1 to get US */
@@ -895,7 +898,7 @@
 	Busy = 1;
 
 	while (1) {
-		unsigned int dev, block, nsect, unit;
+		unsigned int block, nsect;
 		struct gendisk *disk;
 
 		DBG("mfm_request: loop start\n");
@@ -912,16 +915,9 @@
 
 		DBG("mfm_request:                 before arg extraction\n");
 
-		dev = minor(CURRENT->rq_dev);
-		unit = dev>>6;
+		disk = CURRENT->rq_disk;
 		block = CURRENT->sector;
 		nsect = CURRENT->nr_sectors;
-#ifdef DEBUG
-		/*if (unit==1) */ console_printf("mfm_request:                                raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect);
-#endif
-		if (unit >= mfm_drives)
-			printk("mfm: bad disk number: %d\n", unit);
-		disk = mfm_gendisk[unit];
 		if (block >= get_capacity(disk) ||
 		    block+nsect > get_capacity(disk)) {
 			printk("%s: bad access: block=%d, count=%d, nr_sects=%ld\n",
@@ -951,7 +947,7 @@
 			printk("mfm: continue 4\n");
 			continue;
 		}
-		issue_request(dev, block, nsect, CURRENT);
+		issue_request(block, nsect, CURRENT);
 
 		break;
 	}
@@ -1006,6 +1002,7 @@
 {
 	struct mfm_info *p = mfm_info + drive;
 	struct gendisk *disk = mfm_gendisk[drive];
+	disk->private_data = p;
 	if (p->cylinders)
 		printk ("%s: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n",
 			disk->disk_name,
@@ -1166,21 +1163,18 @@
 
 static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
 {
+	struct mfm_info *p = inode->i_bdev->bd_disk->private_data;
 	struct hd_geometry *geo = (struct hd_geometry *) arg;
-	int device = DEVICE_NR(minor(inode->i_rdev));
-	if (device >= mfm_drives)
-		return -EINVAL;
 	if (cmd != HDIO_GETGEO)
 		return -EINVAL;
 	if (!arg)
 		return -EINVAL;
-	if (put_user (mfm_info[device].heads, &geo->heads))
+	if (put_user (p->heads, &geo->heads))
 		return -EFAULT;
-	if (put_user (mfm_info[device].sectors, &geo->sectors))
+	if (put_user (p->sectors, &geo->sectors))
 		return -EFAULT;
-	if (put_user (mfm_info[device].cylinders, &geo->cylinders))
+	if (put_user (p->cylinders, &geo->cylinders))
 		return -EFAULT;
-	start = get_start_sect(inode->i_bdev);
 	if (put_user (get_start_sect(inode->i_bdev), &geo->start))
 		return -EFAULT;
 	return 0;
@@ -1203,24 +1197,26 @@
 void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
 			unsigned char heads, unsigned int secsize)
 {
-	int drive = MINOR(bdev->bd_dev) >> 6;
+	struct mfm_info *p = bdev->bd_disk->private_data;
+	int drive = p - mfm_info;
 	unsigned long disksize = bdev->bd_inode->i_size;
 
-	if (mfm_info[drive].cylinders == 1) {
-		mfm_info[drive].sectors = secsptrack;
-		mfm_info[drive].heads = heads;
-		mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize);
-
-		if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) {
-			printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + drive);
+	if (p->cylinders == 1) {
+		p->sectors = secsptrack;
+		p->heads = heads;
+		p->cylinders = discsize / (secsptrack * heads * secsize);
+
+		if ((heads < 1) || (p->cylinders > 1024)) {
+			printk("%s: Insane disc shape! Setting to 512/4/32\n",
+				bdev->bd_disk->disk_name);
 
 			/* These values are fairly arbitary, but are there so that if your
 			 * lucky you can pick apart your disc to find out what is going on -
 			 * I reckon these figures won't hurt MOST drives
 			 */
-			mfm_info[drive].sectors = 32;
-			mfm_info[drive].heads = 4;
-			mfm_info[drive].cylinders = 512;
+			p->sectors = 32;
+			p->heads = 4;
+			p->cylinders = 512;
 		}
 		if (raw_cmd.dev == drive)
 			mfm_specify ();
@@ -1317,7 +1313,7 @@
 	hdc63463_irqpolladdress	= mfm_IRQPollLoc;
 	hdc63463_irqpollmask	= irqmask;
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request);
+	blk_init_queue(&mfm_queue, do_mfm_request, &mfm_lock);
 
 	Busy = 0;
 	lastspecifieddrive = -1;
@@ -1349,6 +1345,7 @@
 
 	for (i = 0; i < mfm_drives; i++) {
 		mfm_geometry(i);
+		mfm_gendisk[i]->queue = &mfm_queue;
 		add_disk(mfm_gendisk[i]);
 	}
 	return 0;
@@ -1357,7 +1354,7 @@
 	for (i = 0; i < mfm_drives; i++)
 		put_disk(mfm_gendisk[i]);
 out3:
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&mfm_queue);
 	unregister_blkdev(MAJOR_NR, "mfm");
 out2:
 	release_region(mfm_addr, 10);
@@ -1380,7 +1377,7 @@
 		del_gendisk(mfm_gendisk[i]);
 		put_disk(mfm_gendisk[i]);
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&mfm_queue);
 	unregister_blkdev(MAJOR_NR, "mfm");
 	if (ecs)
 		ecard_release(ecs);
diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
--- a/drivers/acorn/scsi/acornscsi.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/acorn/scsi/acornscsi.c	Fri Oct 18 21:03:03 2002
@@ -3010,14 +3010,12 @@
 			int length, int host_no, int inout)
 {
     int pos, begin = 0, devidx;
-    struct Scsi_Host *instance = scsi_hostlist;
+    struct Scsi_Host *instance;
     Scsi_Device *scd;
     AS_Host *host;
     char *p = buffer;
 
-    for (instance = scsi_hostlist;
-	    instance && instance->host_no != host_no;
-		instance = instance->next);
+    instance = scsi_host_hn_get(host_no);
 
     if (inout == 1 || !instance)
 	return -EINVAL;
diff -Nru a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c
--- a/drivers/acorn/scsi/arxescsi.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/acorn/scsi/arxescsi.c	Fri Oct 18 21:03:03 2002
@@ -384,15 +384,11 @@
 			    int length, int host_no, int inout)
 {
 	int pos, begin;
-	struct Scsi_Host *host = scsi_hostlist;
+	struct Scsi_Host *host;
 	ARXEScsi_Info *info;
 	Scsi_Device *scd;
 
-	while (host) {
-		if (host->host_no == host_no)
-			break;
-		host = host->next;
-	}
+	host = scsi_host_hn_get(host_no);
 	if (!host)
 		return 0;
 
diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c
--- a/drivers/acorn/scsi/cumana_2.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/acorn/scsi/cumana_2.c	Fri Oct 18 21:03:07 2002
@@ -498,15 +498,11 @@
 			    int length, int host_no, int inout)
 {
 	int pos, begin;
-	struct Scsi_Host *host = scsi_hostlist;
+	struct Scsi_Host *host;
 	CumanaScsi2_Info *info;
 	Scsi_Device *scd;
 
-	while (host) {
-		if (host->host_no == host_no)
-			break;
-		host = host->next;
-	}
+	host = scsi_host_hn_get(host_no);
 	if (!host)
 		return 0;
 
diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
--- a/drivers/acorn/scsi/eesox.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/acorn/scsi/eesox.c	Fri Oct 18 21:03:08 2002
@@ -499,15 +499,11 @@
 			    int length, int host_no, int inout)
 {
 	int pos, begin;
-	struct Scsi_Host *host = scsi_hostlist;
+	struct Scsi_Host *host;
 	EESOXScsi_Info *info;
 	Scsi_Device *scd;
 
-	while (host) {
-		if (host->host_no == host_no)
-			break;
-		host = host->next;
-	}
+	host = scsi_host_hn_get(host_no);
 	if (!host)
 		return 0;
 
diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c
--- a/drivers/acorn/scsi/powertec.c	Fri Oct 18 21:03:06 2002
+++ b/drivers/acorn/scsi/powertec.c	Fri Oct 18 21:03:06 2002
@@ -404,15 +404,11 @@
 			    int length, int host_no, int inout)
 {
 	int pos, begin;
-	struct Scsi_Host *host = scsi_hostlist;
+	struct Scsi_Host *host;
 	PowerTecScsi_Info *info;
 	Scsi_Device *scd;
 
-	while (host) {
-		if (host->host_no == host_no)
-			break;
-		host = host->next;
-	}
+	host = scsi_host_hn_get(host_no);
 	if (!host)
 		return 0;
 
diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile
--- a/drivers/atm/Makefile	Fri Oct 18 21:03:03 2002
+++ b/drivers/atm/Makefile	Fri Oct 18 21:03:03 2002
@@ -8,6 +8,10 @@
 fore_200e-objs	:= fore200e.o
 host-progs	:= fore200e_mkfirm
 
+# Files generated that shall be removed upon make clean
+clean-files := {atmsar11,pca200e,pca200e_ecd,sba200e_ecd}.{bin,bin1,bin2}
+# Firmware generated that shall be removed upon make clean
+clean-files += fore200e_pca_fw.c fore200e_sba_fw.c
 
 obj-$(CONFIG_ATM_ZATM)		+= zatm.o uPD98402.o
 obj-$(CONFIG_ATM_NICSTAR)	+= nicstar.o
@@ -61,6 +65,6 @@
 	  -i $(CONFIG_ATM_FORE200E_SBA_FW) -o $@
 
 # deal with the various suffixes of the binary firmware images
-$(obj)/%.bin $(obj)/%.bin1 $(obj)/%.bin2: $(obj)/%.data
+$(obj)/%.bin $(obj)/%.bin1 $(obj)/%.bin2: $(src)/%.data
 	objcopy -Iihex $< -Obinary $@.gz
 	gzip -df $@.gz
diff -Nru a/drivers/base/base.h b/drivers/base/base.h
--- a/drivers/base/base.h	Fri Oct 18 21:03:04 2002
+++ b/drivers/base/base.h	Fri Oct 18 21:03:04 2002
@@ -8,6 +8,7 @@
 
 extern struct list_head global_device_list;
 extern spinlock_t device_lock;
+extern struct semaphore device_sem;
 
 extern struct device * get_device_locked(struct device *);
 
@@ -20,6 +21,9 @@
 extern int bus_make_dir(struct bus_type * bus);
 extern void bus_remove_dir(struct bus_type * bus);
 
+extern int bus_add_driver(struct device_driver *);
+extern void bus_remove_driver(struct device_driver *);
+
 extern int driver_make_dir(struct device_driver * drv);
 extern void driver_remove_dir(struct device_driver * drv);
 
@@ -47,9 +51,6 @@
 extern int interface_add(struct device_class *, struct device *);
 extern void interface_remove(struct device_class *, struct device *);
 
-
-extern int driver_attach(struct device_driver * drv);
-extern void driver_detach(struct device_driver * drv);
 
 #ifdef CONFIG_HOTPLUG
 extern int dev_hotplug(struct device *dev, const char *action);
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/base/bus.c	Fri Oct 18 21:03:03 2002
@@ -43,28 +43,23 @@
 		     int (*callback)(struct device * dev, void * data))
 {
 	struct list_head * node;
-	struct device * prev = NULL;
 	int error = 0;
 
-	get_bus(bus);
-	spin_lock(&device_lock);
-	list_for_each(node,&bus->devices) {
-		struct device * dev = get_device_locked(to_dev(node));
-		if (dev) {
-			spin_unlock(&device_lock);
-			error = callback(dev,data);
-			if (prev)
-				put_device(prev);
-			prev = dev;
-			spin_lock(&device_lock);
-			if (error)
-				break;
+	bus = get_bus(bus);
+	if (bus) {
+		down_read(&bus->rwsem);
+		list_for_each(node,&bus->devices) {
+			struct device * dev = get_device(to_dev(node));
+			if (dev) {
+				error = callback(dev,data);
+				put_device(dev);
+				if (error)
+					break;
+			}
 		}
+		up_read(&bus->rwsem);
+		put_bus(bus);
 	}
-	spin_unlock(&device_lock);
-	if (prev)
-		put_device(prev);
-	put_bus(bus);
 	return error;
 }
 
@@ -72,33 +67,127 @@
 		     int (*callback)(struct device_driver * drv, void * data))
 {
 	struct list_head * node;
-	struct device_driver * prev = NULL;
 	int error = 0;
 
-	/* pin bus in memory */
-	get_bus(bus);
+	bus = get_bus(bus);
+	if (bus) {
+		down_read(&bus->rwsem);
+		list_for_each(node,&bus->drivers) {
+			struct device_driver * drv = get_driver(to_drv(node));
+			if (drv) {
+				error = callback(drv,data);
+				put_driver(drv);
+				if (error)
+					break;
+			}
+		}
+		up_read(&bus->rwsem);
+		put_bus(bus);
+	}
+	return error;
+}
 
-	spin_lock(&device_lock);
-	list_for_each(node,&bus->drivers) {
-		struct device_driver * drv = get_driver(to_drv(node));
-		if (drv) {
-			spin_unlock(&device_lock);
-			error = callback(drv,data);
-			if (prev)
-				put_driver(prev);
-			prev = drv;
-			spin_lock(&device_lock);
-			if (error)
-				break;
+static void attach(struct device * dev)
+{
+	pr_debug("bound device '%s' to driver '%s'\n",
+		 dev->bus_id,dev->driver->name);
+	list_add_tail(&dev->driver_list,&dev->driver->devices);
+}
+
+static int bus_match(struct device * dev, struct device_driver * drv)
+{
+	int error = -ENODEV;
+	if (dev->bus->match(dev,drv)) {
+		dev->driver = drv;
+		if (drv->probe) {
+			if (!(error = drv->probe(dev)))
+				attach(dev);
+			else
+				dev->driver = NULL;
+		} else 
+			attach(dev);
+	}
+	return error;
+}
+
+static int device_attach(struct device * dev)
+{
+	struct bus_type * bus = dev->bus;
+	struct list_head * entry;
+	int error = 0;
+
+	if (dev->driver) {
+		attach(dev);
+		return 0;
+	}
+
+	if (!bus->match)
+		return 0;
+
+	list_for_each(entry,&bus->drivers) {
+		struct device_driver * drv = 
+			get_driver(container_of(entry,struct device_driver,bus_list));
+		if (!drv)
+			continue;
+		error = bus_match(dev,drv);
+		put_driver(drv);
+		if (!error)
+			break;
+	}
+	return error;
+}
+
+static int driver_attach(struct device_driver * drv)
+{
+	struct bus_type * bus = drv->bus;
+	struct list_head * entry;
+	int error = 0;
+
+	if (!bus->match)
+		return 0;
+
+	list_for_each(entry,&bus->devices) {
+		struct device * dev = container_of(entry,struct device,bus_list);
+		if (get_device(dev)) {
+			if (!dev->driver) {
+				if (!bus_match(dev,drv) && dev->driver)
+					devclass_add_device(dev);
+			}
+			put_device(dev);
 		}
 	}
-	spin_unlock(&device_lock);
-	if (prev)
-		put_driver(prev);
-	put_bus(bus);
 	return error;
 }
 
+static void detach(struct device * dev, struct device_driver * drv)
+{
+	if (drv) {
+		list_del_init(&dev->driver_list);
+		devclass_remove_device(dev);
+		if (drv->remove)
+			drv->remove(dev);
+		dev->driver = NULL;
+	}
+}
+
+static void device_detach(struct device * dev)
+{
+	detach(dev,dev->driver);
+}
+
+static void driver_detach(struct device_driver * drv)
+{
+	struct list_head * entry, * next;
+	list_for_each_safe(entry,next,&drv->devices) {
+		struct device * dev = container_of(entry,struct device,driver_list);
+		if (get_device(dev)) {
+			detach(dev,drv);
+			put_device(dev);
+		}
+	}
+	
+}
+
 /**
  * bus_add_device - add device to bus
  * @dev:	device being added
@@ -110,12 +199,13 @@
  */
 int bus_add_device(struct device * dev)
 {
-	if (dev->bus) {
-		pr_debug("registering %s with bus '%s'\n",dev->bus_id,dev->bus->name);
-		get_bus(dev->bus);
-		spin_lock(&device_lock);
+	struct bus_type * bus = get_bus(dev->bus);
+	if (bus) {
+		down_write(&dev->bus->rwsem);
+		pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id);
 		list_add_tail(&dev->bus_list,&dev->bus->devices);
-		spin_unlock(&device_lock);
+		device_attach(dev);
+		up_write(&dev->bus->rwsem);
 		device_bus_link(dev);
 	}
 	return 0;
@@ -131,17 +221,70 @@
 void bus_remove_device(struct device * dev)
 {
 	if (dev->bus) {
+		down_write(&dev->bus->rwsem);
+		pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id);
 		device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
+		device_detach(dev);
+		list_del_init(&dev->bus_list);
+		up_write(&dev->bus->rwsem);
 		put_bus(dev->bus);
 	}
 }
 
+int bus_add_driver(struct device_driver * drv)
+{
+	struct bus_type * bus = get_bus(drv->bus);
+	if (bus) {
+		down_write(&bus->rwsem);
+		pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
+		list_add_tail(&drv->bus_list,&bus->drivers);
+		driver_attach(drv);
+		up_write(&bus->rwsem);
+		driver_make_dir(drv);
+	}
+	return 0;
+}
+
+void bus_remove_driver(struct device_driver * drv)
+{
+	if (drv->bus) {
+		down_write(&drv->bus->rwsem);
+		pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name);
+		driver_detach(drv);
+		list_del_init(&drv->bus_list);
+		up_write(&drv->bus->rwsem);
+	}
+}
+
+struct bus_type * get_bus(struct bus_type * bus)
+{
+	struct bus_type * ret = bus;
+	spin_lock(&device_lock);
+	if (bus && bus->present && atomic_read(&bus->refcount))
+		atomic_inc(&bus->refcount);
+	else
+		ret = NULL;
+	spin_unlock(&device_lock);
+	return ret;
+}
+
+void put_bus(struct bus_type * bus)
+{
+	if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
+		return;
+	list_del_init(&bus->node);
+	spin_unlock(&device_lock);
+	WARN_ON(bus->present);
+	bus_remove_dir(bus);
+}
+
 int bus_register(struct bus_type * bus)
 {
-	rwlock_init(&bus->lock);
+	init_rwsem(&bus->rwsem);
 	INIT_LIST_HEAD(&bus->devices);
 	INIT_LIST_HEAD(&bus->drivers);
 	atomic_set(&bus->refcount,2);
+	bus->present = 1;
 
 	spin_lock(&device_lock);
 	list_add_tail(&bus->node,&bus_driver_list);
@@ -156,13 +299,14 @@
 	return 0;
 }
 
-void put_bus(struct bus_type * bus)
+void bus_unregister(struct bus_type * bus)
 {
-	if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
-		return;
-	list_del_init(&bus->node);
+	spin_lock(&device_lock);
+	bus->present = 0;
 	spin_unlock(&device_lock);
-	bus_remove_dir(bus);
+
+	pr_debug("bus %s: unregistering\n",bus->name);
+	put_bus(bus);
 }
 
 EXPORT_SYMBOL(bus_for_each_dev);
@@ -170,4 +314,6 @@
 EXPORT_SYMBOL(bus_add_device);
 EXPORT_SYMBOL(bus_remove_device);
 EXPORT_SYMBOL(bus_register);
+EXPORT_SYMBOL(bus_unregister);
+EXPORT_SYMBOL(get_bus);
 EXPORT_SYMBOL(put_bus);
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/base/class.c	Fri Oct 18 21:03:08 2002
@@ -10,27 +10,29 @@
 
 int devclass_add_driver(struct device_driver * drv)
 {
-	if (drv->devclass) {
-		pr_debug("Registering driver %s:%s with class %s\n",
-			 drv->bus->name,drv->name,drv->devclass->name);
-
-		spin_lock(&device_lock);
-		list_add_tail(&drv->class_list,&drv->devclass->drivers);
-		spin_unlock(&device_lock);
+	struct device_class * cls = get_devclass(drv->devclass);
+	if (cls) {
+		down_write(&cls->rwsem);
+		pr_debug("device class %s: adding driver %s:%s\n",
+			 cls->name,drv->bus->name,drv->name);
+		list_add_tail(&drv->class_list,&cls->drivers);
 		devclass_drv_link(drv);
+		up_write(&cls->rwsem);
 	}
 	return 0;
 }
 
 void devclass_remove_driver(struct device_driver * drv)
 {
-	if (drv->devclass) {
-		pr_debug("Removing driver %s:%s:%s\n",
-			 drv->devclass->name,drv->bus->name,drv->name);
-		spin_lock(&device_lock);
+	struct device_class * cls = drv->devclass;
+	if (cls) {
+		down_write(&cls->rwsem);
+		pr_debug("device class %s: removing driver %s:%s\n",
+			 cls->name,drv->bus->name,drv->name);
 		list_del_init(&drv->class_list);
-		spin_unlock(&device_lock);
 		devclass_drv_unlink(drv);
+		up_write(&cls->rwsem);
+		put_devclass(cls);
 	}
 }
 
@@ -38,9 +40,7 @@
 static void enum_device(struct device_class * cls, struct device * dev)
 {
 	u32 val;
-	spin_lock(&device_lock);
 	val = cls->devnum++;
-	spin_unlock(&device_lock);
 	dev->class_num = val;
 	devclass_dev_link(cls,dev);
 }
@@ -51,18 +51,44 @@
 	dev->class_num = 0;
 }
 
+/**
+ *	devclass_add_device - register device with device class
+ *	@dev:   device to be registered 
+ *
+ *	This is called when a device is either registered with the 
+ *	core, or after the a driver module is loaded and bound to
+ *	the device. 
+ *	The class is determined by looking at @dev's driver, so one
+ *	way or another, it must be bound to something. Once the 
+ *	class is determined, it's set to prevent against concurrent
+ *	calls for the same device stomping on each other. 
+ *
+ *	/sbin/hotplug should be called once the device is added to 
+ *	class and all the interfaces. 
+ */
 int devclass_add_device(struct device * dev)
 {
-	struct device_class * cls = dev->driver->devclass;
+	struct device_class * cls;
 	int error = 0;
-	if (cls) {
-		pr_debug("adding device '%s' to class '%s'\n",
-			 dev->name,cls->name);
-		if (cls->add_device) 
-			error = cls->add_device(dev);
-		if (!error) {
-			enum_device(cls,dev);
-			interface_add(cls,dev);
+
+	if (dev->driver) {
+		cls = get_devclass(dev->driver->devclass);
+		if (cls) {
+			down_write(&cls->rwsem);
+			pr_debug("device class %s: adding device %s\n",
+				 cls->name,dev->name);
+			if (cls->add_device) 
+				error = cls->add_device(dev);
+			if (!error) {
+				enum_device(cls,dev);
+				interface_add(cls,dev);
+			}
+
+			/* notify userspace (call /sbin/hotplug) here */
+
+			up_write(&cls->rwsem);
+			if (error)
+				put_devclass(cls);
 		}
 	}
 	return error;
@@ -70,40 +96,74 @@
 
 void devclass_remove_device(struct device * dev)
 {
-	struct device_class * cls = dev->driver->devclass;
-	if (cls) {
-		pr_debug("removing device '%s' from class '%s'\n",
-			 dev->name,cls->name);
-		interface_remove(cls,dev);
-		unenum_device(cls,dev);
-		if (cls->remove_device)
-			cls->remove_device(dev);
+	struct device_class * cls;
+
+	if (dev->driver) {
+		cls = dev->driver->devclass;
+		if (cls) {
+			down_write(&cls->rwsem);
+			pr_debug("device class %s: removing device %s\n",
+				 cls->name,dev->name);
+			interface_remove(cls,dev);
+			unenum_device(cls,dev);
+			if (cls->remove_device)
+				cls->remove_device(dev);
+			up_write(&cls->rwsem);
+			put_devclass(cls);
+		}
 	}
 }
 
+struct device_class * get_devclass(struct device_class * cls)
+{
+	struct device_class * ret = cls;
+	spin_lock(&device_lock);
+	if (cls && cls->present && atomic_read(&cls->refcount) > 0)
+		atomic_inc(&cls->refcount);
+	else
+		ret = NULL;
+	spin_unlock(&device_lock);
+	return ret;
+}
+
+void put_devclass(struct device_class * cls)
+{
+	if (atomic_dec_and_lock(&cls->refcount,&device_lock)) {
+		list_del_init(&cls->node);
+		spin_unlock(&device_lock);
+		devclass_remove_dir(cls);
+	}
+}
+
+
 int devclass_register(struct device_class * cls)
 {
 	INIT_LIST_HEAD(&cls->drivers);
 	INIT_LIST_HEAD(&cls->intf_list);
-
-	pr_debug("registering device class '%s'\n",cls->name);
+	init_rwsem(&cls->rwsem);
+	atomic_set(&cls->refcount,2);
+	cls->present = 1;
+	pr_debug("device class '%s': registering\n",cls->name);
 
 	spin_lock(&device_lock);
 	list_add_tail(&cls->node,&class_list);
 	spin_unlock(&device_lock);
 	devclass_make_dir(cls);
+	put_devclass(cls);
 	return 0;
 }
 
 void devclass_unregister(struct device_class * cls)
 {
-	pr_debug("unregistering device class '%s'\n",cls->name);
-	devclass_remove_dir(cls);
 	spin_lock(&device_lock);
-	list_del_init(&class_list);
+	cls->present = 0;
 	spin_unlock(&device_lock);
+	pr_debug("device class '%s': unregistering\n",cls->name);
+	put_devclass(cls);
 }
 
 EXPORT_SYMBOL(devclass_register);
 EXPORT_SYMBOL(devclass_unregister);
+EXPORT_SYMBOL(get_devclass);
+EXPORT_SYMBOL(put_devclass);
 
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/base/core.c	Fri Oct 18 21:03:03 2002
@@ -19,136 +19,12 @@
 int (*platform_notify)(struct device * dev) = NULL;
 int (*platform_notify_remove)(struct device * dev) = NULL;
 
+DECLARE_MUTEX(device_sem);
+
 spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
 
 #define to_dev(node) container_of(node,struct device,driver_list)
 
-static int probe(struct device * dev, struct device_driver * drv)
-{
-	dev->driver = drv;
-	return drv->probe ? drv->probe(dev) : 0;
-}
-
-static void attach(struct device * dev)
-{
-	spin_lock(&device_lock);
-	list_add_tail(&dev->driver_list,&dev->driver->devices);
-	spin_unlock(&device_lock);
-	devclass_add_device(dev);
-}
-
-/**
- * found_match - do actual binding of device to driver
- * @dev:	device 
- * @drv:	driver
- *
- * We're here because the bus's match callback returned success for this 
- * pair. We call the driver's probe callback to verify they're really a
- * match made in heaven.
- *
- * In the future, we may want to notify userspace of the binding. (But, 
- * we might not want to do it here).
- * 
- * We may also want to create a symlink in the driver's directory to the 
- * device's physical directory.
- */
-static int found_match(struct device * dev, struct device_driver * drv)
-{
-	int error = 0;
-
-	if (!(error = probe(dev,get_driver(drv)))) {
-		pr_debug("bound device '%s' to driver '%s'\n",
-			 dev->bus_id,drv->name);
-		attach(dev);
-	} else {
-		put_driver(drv);
-		dev->driver = NULL;
-	}
-	return error;
-}
-
-/**
- * device_attach - try to associated device with a driver
- * @drv:	current driver to try
- * @data:	device in disguise
- *
- * This function is used as a callback to bus_for_each_drv.
- * It calls the bus's match callback to check if the driver supports
- * the device. If so, it calls the found_match() function above to 
- * take care of all the details.
- */
-static int do_device_attach(struct device_driver * drv, void * data)
-{
-	struct device * dev = (struct device *)data;
-	int error = 0;
-
-	if (drv->bus->match && drv->bus->match(dev,drv))
-		error = found_match(dev,drv);
-	return error;
-}
-
-static int device_attach(struct device * dev)
-{
-	int error = 0;
-	if (!dev->driver) {
-		if (dev->bus)
-			error = bus_for_each_drv(dev->bus,dev,do_device_attach);
-	} else
-		attach(dev);
-	return error;
-}
-
-static void device_detach(struct device * dev)
-{
-	struct device_driver * drv = dev->driver;
-
-	if (drv) {
-		devclass_remove_device(dev);
-		if (drv && drv->remove)
-			drv->remove(dev);
-		dev->driver = NULL;
-	}
-}
-
-static int do_driver_attach(struct device * dev, void * data)
-{
-	struct device_driver * drv = (struct device_driver *)data;
-	int error = 0;
-
-	if (!dev->driver) {
-		if (dev->bus->match && dev->bus->match(dev,drv))
-			error = found_match(dev,drv);
-	}
-	return error;
-}
-
-int driver_attach(struct device_driver * drv)
-{
-	return bus_for_each_dev(drv->bus,drv,do_driver_attach);
-}
-
-void driver_detach(struct device_driver * drv)
-{
-	struct list_head * node;
-	struct device * prev = NULL;
-
-	spin_lock(&device_lock);
-	list_for_each(node,&drv->devices) {
-		struct device * dev = get_device_locked(to_dev(node));
-		if (dev) {
-			if (prev)
-				list_del_init(&prev->driver_list);
-			spin_unlock(&device_lock);
-			device_detach(dev);
-			if (prev)
-				put_device(prev);
-			prev = dev;
-			spin_lock(&device_lock);
-		}
-	}
-	spin_unlock(&device_lock);
-}
-
 int device_add(struct device *dev)
 {
 	int error;
@@ -156,14 +32,14 @@
 	if (!dev || !strlen(dev->bus_id))
 		return -EINVAL;
 
-	spin_lock(&device_lock);
-	dev->present = 1;
+	down(&device_sem);
+	dev->state = DEVICE_REGISTERED;
 	if (dev->parent) {
 		list_add_tail(&dev->g_list,&dev->parent->g_list);
 		list_add_tail(&dev->node,&dev->parent->children);
 	} else
 		list_add_tail(&dev->g_list,&global_device_list);
-	spin_unlock(&device_lock);
+	up(&device_sem);
 
 	pr_debug("DEV: registering device: ID = '%s', name = %s\n",
 		 dev->bus_id, dev->name);
@@ -173,9 +49,6 @@
 
 	bus_add_device(dev);
 
-	/* bind to driver */
-	device_attach(dev);
-
 	/* notify platform of device entry */
 	if (platform_notify)
 		platform_notify(dev);
@@ -183,12 +56,13 @@
 	/* notify userspace of device entry */
 	dev_hotplug(dev, "add");
 
+	devclass_add_device(dev);
  register_done:
 	if (error) {
-		spin_lock(&device_lock);
+		up(&device_sem);
 		list_del_init(&dev->g_list);
 		list_del_init(&dev->node);
-		spin_unlock(&device_lock);
+		up(&device_sem);
 	}
 	return error;
 }
@@ -203,6 +77,7 @@
 	INIT_LIST_HEAD(&dev->intf_list);
 	spin_lock_init(&dev->lock);
 	atomic_set(&dev->refcount,1);
+	dev->state = DEVICE_INITIALIZED;
 	if (dev->parent)
 		get_device(dev->parent);
 }
@@ -234,22 +109,15 @@
 	return error;
 }
 
-struct device * get_device_locked(struct device * dev)
+struct device * get_device(struct device * dev)
 {
 	struct device * ret = dev;
-	if (dev && dev->present && atomic_read(&dev->refcount) > 0)
+	down(&device_sem);
+	if (device_present(dev) && atomic_read(&dev->refcount) > 0)
 		atomic_inc(&dev->refcount);
 	else
 		ret = NULL;
-	return ret;
-}
-
-struct device * get_device(struct device * dev)
-{
-	struct device * ret;
-	spin_lock(&device_lock);
-	ret = get_device_locked(dev);
-	spin_unlock(&device_lock);
+	up(&device_sem);
 	return ret;
 }
 
@@ -259,34 +127,24 @@
  */
 void put_device(struct device * dev)
 {
-	struct device * parent;
-	if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
+	down(&device_sem);
+	if (!atomic_dec_and_test(&dev->refcount)) {
+		up(&device_sem);
 		return;
-	parent = dev->parent;
-	dev->parent = NULL;
-	spin_unlock(&device_lock);
-
-	BUG_ON(dev->present);
+	}
+	list_del_init(&dev->node);
+	list_del_init(&dev->g_list);
+	up(&device_sem);
 
-	if (dev->release)
-		dev->release(dev);
+	WARN_ON(dev->state == DEVICE_REGISTERED);
 
-	if (parent)
-		put_device(parent);
+	if (dev->state == DEVICE_GONE)
+		device_del(dev);
 }
 
 void device_del(struct device * dev)
 {
-	spin_lock(&device_lock);
-	dev->present = 0;
-	list_del_init(&dev->node);
-	list_del_init(&dev->g_list);
-	list_del_init(&dev->bus_list);
-	list_del_init(&dev->driver_list);
-	spin_unlock(&device_lock);
-
-	pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
-		 dev->bus_id,dev->name);
+	struct device * parent = dev->parent;
 
 	/* Notify the platform of the removal, in case they
 	 * need to do anything...
@@ -297,11 +155,16 @@
 	/* notify userspace that this device is about to disappear */
 	dev_hotplug (dev, "remove");
 
-	device_detach(dev);
 	bus_remove_device(dev);
 
 	/* remove the driverfs directory */
 	device_remove_dir(dev);
+
+	if (dev->release)
+		dev->release(dev);
+
+	if (parent)
+		put_device(parent);
 }
 
 /**
@@ -315,21 +178,14 @@
  */
 void device_unregister(struct device * dev)
 {
-	device_del(dev);
-	put_device(dev);
-}
-
-static int __init device_init(void)
-{
-	int error;
+	down(&device_sem);
+	dev->state = DEVICE_GONE;
+	up(&device_sem);
 
-	error = init_driverfs_fs();
-	if (error)
-		panic("DEV: could not initialize driverfs");
-	return 0;
+	pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
+		 dev->bus_id,dev->name);
+	put_device(dev);
 }
-
-core_initcall(device_init);
 
 EXPORT_SYMBOL(device_register);
 EXPORT_SYMBOL(device_unregister);
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/base/driver.c	Fri Oct 18 21:03:08 2002
@@ -16,29 +16,61 @@
 			int (*callback)(struct device *, void * ))
 {
 	struct list_head * node;
-	struct device * prev = NULL;
 	int error = 0;
 
-	get_driver(drv);
-	spin_lock(&device_lock);
-	list_for_each(node,&drv->devices) {
-		struct device * dev = get_device_locked(to_dev(node));
-		if (dev) {
-			spin_unlock(&device_lock);
-			error = callback(dev,data);
-			if (prev)
-				put_device(prev);
-			prev = dev;
-			spin_lock(&device_lock);
-			if (error)
-				break;
+	drv = get_driver(drv);
+	if (drv) {
+		down_read(&drv->bus->rwsem);
+		list_for_each(node,&drv->devices) {
+			struct device * dev = get_device(to_dev(node));
+			if (dev) {
+				error = callback(dev,data);
+				put_device(dev);
+				if (error)
+					break;
+			}
 		}
+		up_read(&drv->bus->rwsem);
+		put_driver(drv);
 	}
-	spin_unlock(&device_lock);
-	put_driver(drv);
 	return error;
 }
 
+struct device_driver * get_driver(struct device_driver * drv)
+{
+	struct device_driver * ret = drv;
+	spin_lock(&device_lock);
+	if (drv && drv->present && atomic_read(&drv->refcount) > 0)
+		atomic_inc(&drv->refcount);
+	else
+		ret = NULL;
+	spin_unlock(&device_lock);
+	return ret;
+}
+
+
+void remove_driver(struct device_driver * drv)
+{
+	BUG();
+}
+
+/**
+ * put_driver - decrement driver's refcount and clean up if necessary
+ * @drv:	driver in question
+ */
+void put_driver(struct device_driver * drv)
+{
+	struct bus_type * bus = drv->bus;
+	if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
+		return;
+	spin_unlock(&device_lock);
+	BUG_ON(drv->present);
+	bus_remove_driver(drv);
+	if (drv->release)
+		drv->release(drv);
+	put_bus(bus);
+}
+
 /**
  * driver_register - register driver with bus
  * @drv:	driver to register
@@ -50,54 +82,29 @@
 	if (!drv->bus)
 		return -EINVAL;
 
-	pr_debug("Registering driver '%s' with bus '%s'\n",drv->name,drv->bus->name);
+	pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name);
 
 	get_bus(drv->bus);
 	atomic_set(&drv->refcount,2);
 	rwlock_init(&drv->lock);
 	INIT_LIST_HEAD(&drv->devices);
-	spin_lock(&device_lock);
-	list_add(&drv->bus_list,&drv->bus->drivers);
-	spin_unlock(&device_lock);
-	driver_make_dir(drv);
-	driver_attach(drv);
+	drv->present = 1;
+	bus_add_driver(drv);
 	put_driver(drv);
 	return 0;
 }
 
-static void __remove_driver(struct device_driver * drv)
-{
-	pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
-	driver_detach(drv);
-	driver_remove_dir(drv);
-	if (drv->release)
-		drv->release(drv);
-	put_bus(drv->bus);
-}
-
-void remove_driver(struct device_driver * drv)
+void driver_unregister(struct device_driver * drv)
 {
 	spin_lock(&device_lock);
-	atomic_set(&drv->refcount,0);
-	list_del_init(&drv->bus_list);
+	drv->present = 0;
 	spin_unlock(&device_lock);
-	__remove_driver(drv);
-}
-
-/**
- * put_driver - decrement driver's refcount and clean up if necessary
- * @drv:	driver in question
- */
-void put_driver(struct device_driver * drv)
-{
-	if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
-		return;
-	list_del_init(&drv->bus_list);
-	spin_unlock(&device_lock);
-	__remove_driver(drv);
+	pr_debug("driver %s:%s: unregistering\n",drv->bus->name,drv->name);
+	put_driver(drv);
 }
 
 EXPORT_SYMBOL(driver_for_each_dev);
 EXPORT_SYMBOL(driver_register);
+EXPORT_SYMBOL(driver_unregister);
+EXPORT_SYMBOL(get_driver);
 EXPORT_SYMBOL(put_driver);
-EXPORT_SYMBOL(remove_driver);
diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c
--- a/drivers/base/interface.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/base/interface.c	Fri Oct 18 21:03:03 2002
@@ -19,7 +19,7 @@
 static ssize_t
 device_read_power(struct device * dev, char * page, size_t count, loff_t off)
 {
-	return off ? 0 : sprintf(page,"%d\n",dev->current_state);
+	return off ? 0 : sprintf(page,"%d\n",dev->power_state);
 }
 
 static ssize_t
diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/base/platform.c	Fri Oct 18 21:03:03 2002
@@ -39,7 +39,7 @@
 void platform_device_unregister(struct platform_device * pdev)
 {
 	if (pdev)
-		put_device(&pdev->dev);
+		device_unregister(&pdev->dev);
 }
 	
 static int platform_match(struct device * dev, struct device_driver * drv)
diff -Nru a/drivers/base/power.c b/drivers/base/power.c
--- a/drivers/base/power.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/base/power.c	Fri Oct 18 21:03:05 2002
@@ -8,6 +8,8 @@
  *
  */
 
+#define DEBUG 0
+
 #include <linux/device.h>
 #include <linux/module.h>
 #include "base.h"
@@ -28,34 +30,21 @@
 int device_suspend(u32 state, u32 level)
 {
 	struct list_head * node;
-	struct device * prev = NULL;
 	int error = 0;
 
-	if(level == SUSPEND_POWER_DOWN)
-		printk(KERN_EMERG "Shutting down devices\n");
-	else
-		printk(KERN_EMERG "Suspending devices\n");
+	printk(KERN_EMERG "Suspending devices\n");
 
-	spin_lock(&device_lock);
+	down(&device_sem);
 	list_for_each(node,&global_device_list) {
-		struct device * dev = get_device_locked(to_dev(node));
-		if (dev) {
-			spin_unlock(&device_lock);
-			if(dev->driver) {
-				if(level == SUSPEND_POWER_DOWN) {
-				       	if(dev->driver->remove)
-						dev->driver->remove(dev);
-				} else if(dev->driver->suspend) 
-					error = dev->driver->suspend(dev,state,level);
-			}
-			if (prev)
-				put_device(prev);
-			prev = dev;
-			spin_lock(&device_lock);
+		struct device * dev = to_dev(node);
+		if (device_present(dev) && dev->driver && dev->driver->suspend) {
+			pr_debug("suspending device %s\n",dev->name);
+			error = dev->driver->suspend(dev,state,level);
+			if (error)
+				printk(KERN_ERR "%s: suspend returned %d\n",dev->name,error);
 		}
 	}
-	spin_unlock(&device_lock);
-
+	up(&device_sem);
 	return error;
 }
 
@@ -70,33 +59,38 @@
 void device_resume(u32 level)
 {
 	struct list_head * node;
-	struct device * prev = NULL;
 
-	spin_lock(&device_lock);
+	down(&device_sem);
 	list_for_each_prev(node,&global_device_list) {
-		struct device * dev = get_device_locked(to_dev(node));
-		if (dev) {
-			spin_unlock(&device_lock);
-			if (dev->driver && dev->driver->resume)
-				dev->driver->resume(dev,level);
-			if (prev)
-				put_device(prev);
-			prev = dev;
-			spin_lock(&device_lock);
+		struct device * dev = to_dev(node);
+		if (device_present(dev) && dev->driver && dev->driver->resume) {
+			pr_debug("resuming device %s\n",dev->name);
+			dev->driver->resume(dev,level);
 		}
 	}
-	spin_unlock(&device_lock);
+	up(&device_sem);
 
 	printk(KERN_EMERG "Devices Resumed\n");
 }
 
 /**
- * device_shutdown - call device_suspend with status set to shutdown, to 
- * cause all devices to remove themselves cleanly 
+ * device_shutdown - call ->remove() on each device to shutdown. 
  */
 void device_shutdown(void)
 {
-	device_suspend(4, SUSPEND_POWER_DOWN);
+	struct list_head * entry;
+	
+	printk(KERN_EMERG "Shutting down devices\n");
+
+	down(&device_sem);
+	list_for_each(entry,&global_device_list) {
+		struct device * dev = to_dev(entry);
+		if (device_present(dev) && dev->driver && dev->driver->shutdown) {
+			pr_debug("shutting down %s\n",dev->name);
+			dev->driver->shutdown(dev);
+		}
+	}
+	up(&device_sem);
 }
 
 EXPORT_SYMBOL(device_suspend);
diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c
--- a/drivers/base/sys.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/base/sys.c	Fri Oct 18 21:03:03 2002
@@ -10,6 +10,8 @@
  * add themselves as children of the system bus.
  */
 
+#define DEBUG 1
+
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -76,8 +78,8 @@
  */
 void sys_unegister_root(struct sys_root *  root)
 {
-	put_device(&root->sysdev);
-	put_device(&root->dev);
+	device_unregister(&root->sysdev);
+	device_unregister(&root->dev);
 }
 
 /**
@@ -125,7 +127,7 @@
 void sys_device_unregister(struct sys_device * sysdev)
 {
 	if (sysdev)
-		put_device(&sysdev->dev);
+		device_unregister(&sysdev->dev);
 }
 
 struct bus_type system_bus_type = {
diff -Nru a/drivers/block/Config.in b/drivers/block/Config.in
--- a/drivers/block/Config.in	Fri Oct 18 21:03:04 2002
+++ b/drivers/block/Config.in	Fri Oct 18 21:03:04 2002
@@ -48,7 +48,7 @@
 fi
 dep_bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
 
-if [ "$CONFIG_X86" = "y" -o "$CONFIG_PPC32" = "y" ]; then
+if [ "$CONFIG_X86" = "y" ]; then
    bool 'Support for Large Block Devices' CONFIG_LBD
 fi
 endmenu
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/block/DAC960.c	Fri Oct 18 21:03:07 2002
@@ -75,18 +75,18 @@
   *DAC960_Controllers[DAC960_MaxControllers] =	{ NULL };
 
 
-static int DAC960_revalidate(kdev_t);
+static int DAC960_revalidate(struct gendisk *);
 /*
   DAC960_BlockDeviceOperations is the Block Device Operations structure for
   DAC960 Logical Disk Devices.
 */
 
 static struct block_device_operations DAC960_BlockDeviceOperations = {
-	owner:		THIS_MODULE,
-	open:		DAC960_Open,
-	release:	DAC960_Release,
-	ioctl:		DAC960_IOCTL,
-	revalidate:	DAC960_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= DAC960_Open,
+	.release	= DAC960_Release,
+	.ioctl		= DAC960_IOCTL,
+	.revalidate_disk= DAC960_revalidate,
 };
 
 
@@ -308,9 +308,9 @@
 
 static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
 {
-  spin_unlock_irq(Controller->RequestQueue->queue_lock);
+  spin_unlock_irq(Controller->RequestQueue.queue_lock);
   __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands);
-  spin_lock_irq(Controller->RequestQueue->queue_lock);
+  spin_lock_irq(Controller->RequestQueue.queue_lock);
 }
 
 
@@ -1931,7 +1931,6 @@
 {
   int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
   RequestQueue_T *RequestQueue;
-  int MinorNumber;
   int n;
 
   /*
@@ -1947,7 +1946,7 @@
   /*
     Initialize the I/O Request Queue.
   */
-  RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber);
+  RequestQueue = &Controller->RequestQueue;
   Controller->queue_lock = SPIN_LOCK_UNLOCKED;
   blk_init_queue(RequestQueue, DAC960_RequestFunction, &Controller->queue_lock);
   RequestQueue->queuedata = Controller;
@@ -1956,7 +1955,6 @@
   blk_queue_max_phys_segments(RequestQueue, ~0);
   blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
 
-  Controller->RequestQueue = RequestQueue;
   for (n = 0; n < DAC960_MaxLogicalDrives; n++) {
 	struct gendisk *disk = Controller->disks[n];
 	sprintf(disk->disk_name, "rd/c%dd%d", Controller->ControllerNumber, n);
@@ -1989,7 +1987,7 @@
   /*
     Remove the I/O Request Queue.
   */
-  blk_cleanup_queue(BLK_DEFAULT_QUEUE(MajorNumber));
+  blk_cleanup_queue(&Controller->RequestQueue);
 }
 
 static long disk_size(DAC960_Controller_T *Controller, int disk)
@@ -2019,12 +2017,16 @@
 		set_capacity(Controller->disks[disk], disk_size(Controller, disk));
 }
 
-static int DAC960_revalidate(kdev_t dev)
+static int DAC960_revalidate(struct gendisk *disk)
 {
-	int ctlr = DAC960_ControllerNumber(dev);
-	int disk = DAC960_LogicalDriveNumber(dev);
-	DAC960_Controller_T *p = DAC960_Controllers[ctlr];
-	set_capacity(p->disks[disk], disk_size(p, disk));
+	DAC960_Controller_T *p = disk->private_data;
+	int unit;
+	for (unit = 0; unit < DAC960_MaxLogicalDrives; unit++) {
+		if (p->disks[unit] == disk) {
+			set_capacity(disk, disk_size(p, unit));
+			return 0;
+		}
+	}
 	return 0;
 }
 
@@ -2093,6 +2095,7 @@
 static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 {
   void (*InterruptHandler)(int, void *, Registers_T *) = NULL;
+  DAC960_Controller_T *Controller = NULL;
   DAC960_FirmwareType_T FirmwareType = 0;
   unsigned short VendorID = 0, DeviceID = 0;
   unsigned int MemoryWindowSize = 0;
@@ -2145,7 +2148,6 @@
     }
   while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
     {
-      DAC960_Controller_T *Controller = NULL;
       DAC960_IO_Address_T IO_Address = 0;
       DAC960_PCI_Address_T PCI_Address = 0;
       unsigned char Bus = PCI_Device->bus->number;
@@ -2155,6 +2157,7 @@
       unsigned char ErrorStatus, Parameter0, Parameter1;
       unsigned int IRQ_Channel = PCI_Device->irq;
       void *BaseAddress;
+      Controller = NULL;
       if (pci_enable_device(PCI_Device) != 0) continue;
       switch (HardwareType)
 	{
@@ -2202,6 +2205,8 @@
 		Controller->disks[i] = alloc_disk(1<<DAC960_MaxPartitionsBits);
 		if (!Controller->disks[i])
 			goto Enomem;
+		Controller->disks[i]->private_data = Controller;
+		Controller->disks[i]->queue = &Controller->RequestQueue;
       }
       Controller->ControllerNumber = DAC960_ControllerCount;
       init_waitqueue_head(&Controller->CommandWaitQueue);
@@ -2831,7 +2836,7 @@
 static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
 				     boolean WaitForCommand)
 {
-  RequestQueue_T *RequestQueue = Controller->RequestQueue;
+  RequestQueue_T *RequestQueue = &Controller->RequestQueue;
   ListHead_T *RequestQueueHead;
   IO_Request_T *Request;
   DAC960_Command_T *Command;
@@ -5225,7 +5230,6 @@
     }
 }
 
-
 /*
   DAC960_Open is the Device Open Function for the DAC960 Driver.
 */
@@ -5265,9 +5269,8 @@
       long size;
       Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
       size = disk_size(Controller, LogicalDriveNumber);
-      /* BROKEN, same as modular ide-floppy/ide-disk; same fix - ->probe() */
       set_capacity(Controller->disks[LogicalDriveNumber], size);
-      add_disk(Controller->disks[LogicalDriveNumber]);
+      Inode->i_bdev->bd_invalidated = 1;
     }
   if (!get_capacity(Controller->disks[LogicalDriveNumber]))
     return -ENXIO;
@@ -5314,7 +5317,6 @@
   int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
   DiskGeometry_T Geometry, *UserGeometry;
   DAC960_Controller_T *Controller;
-  int res;
 
   if (File != NULL && (File->f_flags & O_NONBLOCK))
     return DAC960_UserIOCTL(Inode, File, Request, Argument);
@@ -5379,7 +5381,7 @@
 static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 			    unsigned int Request, unsigned long Argument)
 {
-  int ErrorCode;
+  int ErrorCode = 0;
   if (!capable(CAP_SYS_ADMIN)) return -EACCES;
   switch (Request)
     {
@@ -5492,11 +5494,11 @@
 	    while (Controller->V1.DirectCommandActive[DCDB.Channel]
 						     [DCDB.TargetID])
 	      {
-		spin_unlock_irq(Controller->RequestQueue->queue_lock);
+		spin_unlock_irq(Controller->RequestQueue.queue_lock);
 		__wait_event(Controller->CommandWaitQueue,
 			     !Controller->V1.DirectCommandActive
 					     [DCDB.Channel][DCDB.TargetID]);
-		spin_lock_irq(Controller->RequestQueue->queue_lock);
+		spin_lock_irq(Controller->RequestQueue.queue_lock);
 	      }
 	    Controller->V1.DirectCommandActive[DCDB.Channel]
 					      [DCDB.TargetID] = true;
diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h
--- a/drivers/block/DAC960.h	Fri Oct 18 21:03:07 2002
+++ b/drivers/block/DAC960.h	Fri Oct 18 21:03:07 2002
@@ -2364,7 +2364,7 @@
   DAC960_Command_T *FreeCommands;
   unsigned char *CombinedStatusBuffer;
   unsigned char *CurrentStatusBuffer;
-  RequestQueue_T *RequestQueue;
+  RequestQueue_T RequestQueue;
   spinlock_t queue_lock;
   WaitQueue_T CommandWaitQueue;
   WaitQueue_T HealthStatusWaitQueue;
@@ -2504,7 +2504,7 @@
 void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+  spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
 }
 
 
@@ -2516,7 +2516,7 @@
 void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
 }
 
 
@@ -2553,7 +2553,7 @@
 void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+  spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
 }
 
 
@@ -2566,7 +2566,7 @@
 void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(Controller->RequestQueue->queue_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
 }
 
 #error I am a non-portable driver, please convert me to use the Documentation/DMA-mapping.txt interfaces
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/block/acsi.c	Fri Oct 18 21:03:08 2002
@@ -45,7 +45,6 @@
 
 #define MAJOR_NR ACSI_MAJOR
 #define DEVICE_NAME "ACSI"
-#define DEVICE_NR(device) (minor(device) >> 4)
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -59,6 +58,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/major.h>
+#define QUEUE (&acsi_queue)
 #include <linux/blk.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -80,6 +80,7 @@
 #include <asm/atari_stram.h>
 
 static void (*do_acsi)(void) = NULL;
+static struct request_queue acsi_queue;
 
 #define DEBUG
 #undef DEBUG_DETECT
@@ -119,6 +120,7 @@
 	unsigned		old_atari_disk : 1; /* Is an old Atari disk       */
 	unsigned		changed : 1;	/* Medium has been changed */
 	unsigned long 	size;			/* #blocks */
+	int access_count;
 } acsi_info[MAX_DEV];
 
 /*
@@ -232,8 +234,8 @@
 /* Default size if capacity cannot be determined (1 GByte) */
 #define	DEFAULT_SIZE	0x1fffff
 
-#define CARTRCH_STAT(dev,buf)					\
-	(acsi_info[(dev)].old_atari_disk ?			\
+#define CARTRCH_STAT(aip,buf)						\
+	(aip->old_atari_disk ?						\
 	 (((buf)[0] & 0x7f) == 0x28) :					\
 	 ((((buf)[0] & 0x70) == 0x70) ?					\
 	  (((buf)[2] & 0x0f) == 0x06) :					\
@@ -245,7 +247,6 @@
 unsigned long 	phys_acsi_buffer;
 
 static int NDevices;
-static int access_count[MAX_DEV];
 
 static int				CurrentNReq;
 static int				CurrentNSect;
@@ -348,7 +349,7 @@
 static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
                         rwflag, int enable);
 static int acsi_reqsense( char *buffer, int targ, int lun);
-static void acsi_print_error( const unsigned char *errblk, int dev );
+static void acsi_print_error(const unsigned char *errblk, int struct acsi_info_struct *aip);
 static void acsi_interrupt (int irq, void *data, struct pt_regs *fp);
 static void unexpected_acsi_interrupt( void );
 static void bad_rw_intr( void );
@@ -364,10 +365,10 @@
                        cmd, unsigned long arg );
 static int acsi_open( struct inode * inode, struct file * filp );
 static int acsi_release( struct inode * inode, struct file * file );
-static void acsi_prevent_removal( int target, int flag );
+static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
 static int acsi_change_blk_size( int target, int lun);
 static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static int acsi_revalidate (kdev_t);
+static int acsi_revalidate (struct gendisk *disk);
 
 /************************* End of Prototypes **************************/
 
@@ -691,12 +692,12 @@
 #endif
 
 
-static void acsi_print_error( const unsigned char *errblk, int dev  )
+static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip)
 
 {	int atari_err, i, errcode;
 	struct acsi_error *arr;
 
-	atari_err = acsi_info[dev].old_atari_disk;
+	atari_err = aip->old_atari_disk;
 	if (atari_err)
 		errcode = errblk[0] & 0x7f;
 	else
@@ -780,15 +781,15 @@
 	
 	status = acsi_getstatus();
 	if (status != 0) {
-		int dev = DEVICE_NR(CURRENT->rq_dev);
-		printk( KERN_ERR "ad%c: ", dev+'a' );
-		if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target, 
-					acsi_info[dev].lun))
+		struct gendisk *disk = CURRENT->rq_disk;
+		struct acsi_info_struct *aip = disk->private_data;
+		printk(KERN_ERR "%s: ", disk->disk_name);
+		if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun))
 			printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
 		else {
-			acsi_print_error( acsi_buffer, dev );
-			if (CARTRCH_STAT( dev, acsi_buffer ))
-				acsi_info[dev].changed = 1;
+			acsi_print_error(acsi_buffer, aip);
+			if (CARTRCH_STAT(aip, acsi_buffer))
+				aip->changed = 1;
 		}
 		ENABLE_IRQ();
 		bad_rw_intr();
@@ -811,15 +812,15 @@
 
 	status = acsi_getstatus();
 	if (status != 0) {
-		int	dev = DEVICE_NR(CURRENT->rq_dev);
-		printk( KERN_ERR "ad%c: ", dev+'a' );
-		if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target,
-					acsi_info[dev].lun))
+		struct gendisk *disk = CURRENT->rq_disk;
+		struct acsi_info_struct *aip = disk->private_data;
+		printk( KERN_ERR "%s: ", disk->disk_name);
+		if (!acsi_reqsense( acsi_buffer, aip->target, aip->lun))
 			printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
 		else {
-			acsi_print_error( acsi_buffer, dev );
-			if (CARTRCH_STAT( dev, acsi_buffer ))
-				acsi_info[dev].changed = 1;
+			acsi_print_error(acsi_buffer, aip);
+			if (CARTRCH_STAT(aip, acsi_buffer))
+				aip->changed = 1;
 		}
 		bad_rw_intr();
 		redo_acsi_request();
@@ -944,11 +945,13 @@
 
 
 static void redo_acsi_request( void )
-
-{	unsigned			block, dev, target, lun, nsect;
+{
+	unsigned			block, target, lun, nsect;
 	char 				*buffer;
 	unsigned long		pbuffer;
 	struct buffer_head	*bh;
+	struct gendisk *disk;
+	struct acsi_info_struct *aip;
 
   repeat:
 	CLEAR_TIMER();
@@ -963,35 +966,33 @@
 		return;
 	}
 
-	if (major(CURRENT->rq_dev) != MAJOR_NR)
-		panic(DEVICE_NAME ": request list destroyed");
+	disk = CURRENT->rq_disk;
+	aip = disk->private_data;
 	if (CURRENT->bh) {
 		if (!CURRENT->bh && !buffer_locked(CURRENT->bh))
 			panic(DEVICE_NAME ": block not locked");
 	}
 
-	dev = DEVICE_NR(CURRENT->rq_dev);
 	block = CURRENT->sector;
-	if (dev >= NDevices ||
-		block+CURRENT->nr_sectors >= get_capacity(acsi_gendisk[dev])) {
+	if (block+CURRENT->nr_sectors >= get_capacity(disk)) {
 #ifdef DEBUG
-		printk( "ad%c: attempted access for blocks %d...%ld past end of device at block %ld.\n",
-		       dev+'a',
+		printk( "%s: attempted access for blocks %d...%ld past end of device at block %ld.\n",
+		       disk->disk_name,
 		       block, block + CURRENT->nr_sectors - 1,
-		       get_capacity(acsi_gendisk[dev]));
+		       get_capacity(disk));
 #endif
 		end_request(CURRENT, 0);
 		goto repeat;
 	}
-	if (acsi_info[dev].changed) {
-		printk( KERN_NOTICE "ad%c: request denied because cartridge has "
-				"been changed.\n", dev+'a' );
+	if (aip->changed) {
+		printk( KERN_NOTICE "%s: request denied because cartridge has "
+				"been changed.\n", disk->disk_name);
 		end_request(CURRENT, 0);
 		goto repeat;
 	}
 	
-	target = acsi_info[dev].target;
-	lun    = acsi_info[dev].lun;
+	target = aip->target;
+	lun    = aip->lun;
 
 	/* Find out how many sectors should be transferred from/to
 	 * consecutive buffers and thus can be done with a single command.
@@ -1085,7 +1086,8 @@
 static int acsi_ioctl( struct inode *inode, struct file *file,
 					   unsigned int cmd, unsigned long arg )
 {
-	int dev = DEVICE_NR(inode->i_rdev);
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct acsi_info_struct *aip = disk->private_data;
 	switch (cmd) {
 	  case HDIO_GETGEO:
 		/* HDIO_GETGEO is supported more for getting the partition's
@@ -1095,13 +1097,13 @@
 		 * easy, use Adaptec's usual 64/32 mapping */
 	    put_user( 64, &geo->heads );
 	    put_user( 32, &geo->sectors );
-	    put_user( acsi_info[dev].size >> 11, &geo->cylinders );
+	    put_user( aip->size >> 11, &geo->cylinders );
 		put_user(get_start_sect(inode->i_bdev), &geo->start);
 		return 0;
 	  }
 	  case SCSI_IOCTL_GET_IDLUN:
 		/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
-		put_user( acsi_info[dev].target | (acsi_info[dev].lun << 8),
+		put_user( aip->target | (aip->lun << 8),
 				  &((Scsi_Idlun *) arg)->dev_id );
 		put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
 		return 0;
@@ -1128,19 +1130,19 @@
 
 static int acsi_open( struct inode * inode, struct file * filp )
 {
-	int device = DEVICE_NR(inode->i_rdev);
-	struct acsi_info_struct *aip = &acsi_info[device];
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct acsi_info_struct *aip = disk->private_data;
 
-	if (access_count[device] == 0 && aip->removable) {
+	if (aip->access_count == 0 && aip->removable) {
 #if 0
 		aip->changed = 1;	/* safety first */
 #endif
 		check_disk_change( inode->i_bdev );
 		if (aip->changed)	/* revalidate was not successful (no medium) */
 			return -ENXIO;
-		acsi_prevent_removal(device, 1);
+		acsi_prevent_removal(aip, 1);
 	}
-	access_count[device]++;
+	aip->access_count++;
 
 	if (filp && filp->f_mode) {
 		check_disk_change( inode->i_bdev );
@@ -1162,9 +1164,10 @@
 
 static int acsi_release( struct inode * inode, struct file * file )
 {
-	int device = DEVICE_NR(inode->i_rdev);
-	if (--access_count[device] == 0 && acsi_info[device].removable)
-		acsi_prevent_removal(device, 0);
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct acsi_info_struct *aip = disk->private_data;
+	if (--aip->access_count == 0 && aip->removable)
+		acsi_prevent_removal(aip, 0);
 	return( 0 );
 }
 
@@ -1172,12 +1175,11 @@
  * Prevent or allow a media change for removable devices.
  */
 
-static void acsi_prevent_removal(int device, int flag)
+static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag)
 {
 	stdma_lock( NULL, NULL );
 	
-	CMDSET_TARG_LUN(pa_med_rem_cmd, acsi_info[device].target,
-			acsi_info[device].lun);
+	CMDSET_TARG_LUN(pa_med_rem_cmd, aip->target, aip->lun);
 	CMDSET_LEN( pa_med_rem_cmd, flag );
 	
 	if (acsicmd_nodma(pa_med_rem_cmd, 0) && acsi_wait_for_IRQ(3*HZ))
@@ -1188,12 +1190,10 @@
 	stdma_release();
 }
 
-static int acsi_media_change (kdev_t dev)
+static int acsi_media_change(struct gendisk *disk)
 {
-	int device = DEVICE_NR(dev);
-	struct acsi_info_struct *aip;
+	struct acsi_info_struct *aip = disk->private_data;
 
-	aip = &acsi_info[device];
 	if (!aip->removable) 
 		return 0;
 
@@ -1214,19 +1214,19 @@
 	    acsi_wait_for_IRQ(3*HZ)) {
 		if (acsi_getstatus()) {
 			if (acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
-				if (CARTRCH_STAT(device, acsi_buffer))
+				if (CARTRCH_STAT(aip, acsi_buffer))
 					aip->changed = 1;
 			}
 			else {
-				printk( KERN_ERR "ad%c: REQUEST SENSE failed in test for "
-				       "medium change; assuming a change\n", device + 'a' );
+				printk( KERN_ERR "%s: REQUEST SENSE failed in test for "
+				       "medium change; assuming a change\n", disk->disk_name );
 				aip->changed = 1;
 			}
 		}
 	}
 	else {
-		printk( KERN_ERR "ad%c: Test for medium changed timed out; "
-				"assuming a change\n", device + 'a');
+		printk( KERN_ERR "%s: Test for medium changed timed out; "
+				"assuming a change\n", disk->disk_name);
 		aip->changed = 1;
 	}
 	ENABLE_IRQ();
@@ -1591,12 +1591,12 @@
 #endif
 
 static struct block_device_operations acsi_fops = {
-	owner:			THIS_MODULE,
-	open:			acsi_open,
-	release:		acsi_release,
-	ioctl:			acsi_ioctl,
-	check_media_change:	acsi_media_change,
-	revalidate:		acsi_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= acsi_open,
+	.release	= acsi_release,
+	.ioctl		= acsi_ioctl,
+	.media_changed	= acsi_media_change,
+	.revalidate_disk= acsi_revalidate,
 };
 
 #ifdef CONFIG_ATARI_SLM_MODULE
@@ -1640,7 +1640,7 @@
 	phys_acsi_buffer = virt_to_phys( acsi_buffer );
 	STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
 	
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_acsi_request, &acsi_lock);
+	blk_init_queue(&acsi_queue, do_acsi_request, &acsi_lock);
 #ifdef CONFIG_ATARI_SLM
 	err = slm_init();
 #endif
@@ -1737,7 +1737,9 @@
 			disk->minors = 1;
 		}
 		disk->fops = &acsi_fops;
+		disk->private_data = &acsi_info[i];
 		set_capacity(disk, acsi_info[i].size);
+		disk->queue = &acsi_queue;
 		add_disk(disk);
 	}
 	return 0;
@@ -1745,7 +1747,7 @@
 	while (i--)
 		put_disk(acsi_gendisk[i]);
 out3:
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&acsi_queue);
 	atari_stram_free( acsi_buffer );
 out2:
 	unregister_blkdev( MAJOR_NR, "ad" );
@@ -1772,7 +1774,7 @@
 {
 	int i;
 	del_timer( &acsi_timer );
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&acsi_queue);
 	atari_stram_free( acsi_buffer );
 
 	if (unregister_blkdev( MAJOR_NR, "ad" ) != 0)
@@ -1804,10 +1806,9 @@
  *
  */
 
-static int acsi_revalidate(kdev_t dev)
+static int acsi_revalidate(struct gendisk *disk)
 {
-	int unit = DEVICE_NR(dev);
-	struct acsi_info_struct *aip = &acsi_info[unit];
+	struct acsi_info_struct *aip = disk->private_data;
 	stdma_lock( NULL, NULL );
 	if (acsi_devinit(aip) != DEV_SUPPORTED) {
 		printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
@@ -1820,6 +1821,6 @@
 
 	ENABLE_IRQ();
 	stdma_release();
-	set_capacity(acsi_gendisk[unit], aip->size);
+	set_capacity(disk, aip->size);
 	return 0;
 }
diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c
--- a/drivers/block/amiflop.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/block/amiflop.c	Fri Oct 18 21:03:04 2002
@@ -81,7 +81,7 @@
 
 #define MAJOR_NR FLOPPY_MAJOR
 #define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&floppy_queue)
 #include <linux/blk.h>
 
 #undef DEBUG /* print _LOTS_ of infos */
@@ -123,6 +123,8 @@
 MODULE_PARM(fd_def_df0,"l");
 MODULE_LICENSE("GPL");
 
+static struct request_queue floppy_queue;
+
 /*
  *  Macros
  */
@@ -1377,14 +1379,10 @@
 		return;
 	}
 
-	if (major(CURRENT->rq_dev) != MAJOR_NR)
-		panic(DEVICE_NAME ": request list destroyed");
-
 	device = minor(CURRENT->rq_dev);
 	if (device < 8) {
 		/* manual selection */
 		drive = device & 3;
-		floppy = unit + drive;
 	} else {
 		/* Auto-detection */
 #ifdef DEBUG
@@ -1392,8 +1390,8 @@
 		printk("redo_fd_request: default to normal\n");
 #endif
 		drive = device & 3;
-		floppy = unit + drive;
 	}
+	floppy = CURRENT->rq_disk->private_data;
 
 	/* Here someone could investigate to be more efficient */
 	for (cnt = 0; cnt < CURRENT->current_nr_sectors; cnt++) { 
@@ -1428,11 +1426,11 @@
 
 		switch (rq_data_dir(CURRENT)) {
 		case READ:
-			memcpy(data, unit[drive].trackbuf + sector * 512, 512);
+			memcpy(data, floppy->trackbuf + sector * 512, 512);
 			break;
 
 		case WRITE:
-			memcpy(unit[drive].trackbuf + sector * 512, data, 512);
+			memcpy(floppy->trackbuf + sector * 512, data, 512);
 
 			/* keep the drive spinning while writes are scheduled */
 			if (!fd_motor_on(drive)) {
@@ -1446,7 +1444,7 @@
 			save_flags (flags);
 			cli();
 
-			unit[drive].dirty = 1;
+			floppy->dirty = 1;
 		        /* reset the timer */
 		        del_timer (flush_track_timer + drive);
 			    
@@ -1674,9 +1672,10 @@
  * to the desired drive, but it will probably not survive the sleep if
  * several floppies are used at the same time: thus the loop.
  */
-static int amiga_floppy_change(kdev_t dev)
+static int amiga_floppy_change(struct gendisk *disk)
 {
-	int drive = minor(dev) & 3;
+	struct amiga_floppy_struct *p = disk->private_data;
+	int drive = p - unit;
 	int changed;
 	static int first_time = 1;
 
@@ -1692,8 +1691,8 @@
 
 	if (changed) {
 		fd_probe(drive);
-		unit[drive].track = -1;
-		unit[drive].dirty = 0;
+		p->track = -1;
+		p->dirty = 0;
 		writepending = 0; /* if this was true before, too bad! */
 		writefromint = 0;
 		return 1;
@@ -1702,11 +1701,11 @@
 }
 
 static struct block_device_operations floppy_fops = {
-	.owner			= THIS_MODULE,
-	.open			= floppy_open,
-	.release		= floppy_release,
-	.ioctl			= fd_ioctl,
-	.check_media_change	= amiga_floppy_change,
+	.owner		= THIS_MODULE,
+	.open		= floppy_open,
+	.release	= floppy_release,
+	.ioctl		= fd_ioctl,
+	.media_changed	= amiga_floppy_change,
 };
 
 void __init amiga_floppy_setup (char *str, int *ints)
@@ -1745,6 +1744,8 @@
 		disk->first_minor = drive;
 		disk->fops = &floppy_fops;
 		sprintf(disk->disk_name, "fd%d", drive);
+		disk->private_data = &unit[drive];
+		disk->queue = &floppy_queue;
 		set_capacity(disk, 880*2);
 		add_disk(disk);
 	}
@@ -1758,12 +1759,12 @@
 	return -ENOMEM;
 }
  
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
 {
-	int drive = minor & 3;
+	int drive = *part & 3;
 	if (unit[drive].type->code == FD_NODRIVE)
 		return NULL;
-	return unit[drive].gendisk;
+	return get_disk(unit[drive].gendisk);
 }
 
 int __init amiga_floppy_init(void)
@@ -1808,9 +1809,7 @@
 		unregister_blkdev(MAJOR_NR,"fd");
 		return -EBUSY;
 	}
-	blk_set_probe(MAJOR_NR, floppy_find);
 	if (fd_probe_drives() < 1) { /* No usable drives */
-		blk_set_probe(MAJOR_NR, NULL);
 		free_irq(IRQ_AMIGA_CIAA_TB, NULL);
 		free_irq(IRQ_AMIGA_DSKBLK, NULL);
 		amiga_chip_free(raw_buf);
@@ -1818,6 +1817,8 @@
 		unregister_blkdev(MAJOR_NR,"fd");
 		return -ENXIO;
 	}
+	blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+				floppy_find, NULL, NULL);
 
 	/* initialize variables */
 	init_timer(&motor_on_timer);
@@ -1842,7 +1843,7 @@
 	post_write_timer.data = 0;
 	post_write_timer.function = post_write;
   
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &amiflop_lock);
+	blk_init_queue(&floppy_queue, do_fd_request, &amiflop_lock);
 	for (i = 0; i < 128; i++)
 		mfmdecode[i]=255;
 	for (i = 0; i < 16; i++)
@@ -1877,12 +1878,12 @@
 			kfree(unit[i].trackbuf);
 		}
 	}
-	blk_set_probe(MAJOR_NR, NULL);
+	blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
 	free_irq(IRQ_AMIGA_CIAA_TB, NULL);
 	free_irq(IRQ_AMIGA_DSKBLK, NULL);
 	custom.dmacon = DMAF_DISK; /* disable DMA */
 	amiga_chip_free(raw_buf);
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&floppy_queue);
 	release_mem_region(CUSTOM_PHYSADDR+0x20, 8);
 	unregister_blkdev(MAJOR_NR, "fd");
 }
diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c
--- a/drivers/block/ataflop.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/ataflop.c	Fri Oct 18 21:03:03 2002
@@ -94,7 +94,7 @@
 
 #define MAJOR_NR FLOPPY_MAJOR
 #define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&floppy_queue)
 #include <linux/blk.h>
 #include <linux/blkpg.h>
 
@@ -102,6 +102,8 @@
 
 #undef DEBUG
 
+static struct request_queue floppy_queue;
+
 /* Disk types: DD, HD, ED */
 static struct atari_disk_type {
 	const char	*name;
@@ -1355,9 +1357,10 @@
  * due to unrecognised disk changes.
  */
 
-static int check_floppy_change (kdev_t dev)
+static int check_floppy_change(struct gendisk *disk)
 {
-	unsigned int drive = minor(dev) & 0x03;
+	struct atari_floppy_struct *p = disk->private_data;
+	unsigned int drive = p - unit;
 	if (test_bit (drive, &fake_change)) {
 		/* simulated change (e.g. after formatting) */
 		return 1;
@@ -1376,9 +1379,10 @@
 	return 0;
 }
 
-static int floppy_revalidate (kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
 {
-	int drive = minor(dev) & 3;
+	struct atari_floppy_struct *p = disk->private_data;
+	unsigned int drive = p - unit;
 
 	if (test_bit(drive, &changed_floppies) ||
 	    test_bit(drive, &fake_change) ||
@@ -1530,6 +1534,7 @@
 {
 	int drive, type;
 	kdev_t device;
+	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct atari_format_descr fmt_desc;
 	struct atari_disk_type *dtp;
 	struct floppy_struct getprm;
@@ -1591,8 +1596,8 @@
 		 * or the next access will revalidate - and clear UDT :-(
 		 */
 
-		if (check_floppy_change(device))
-		        floppy_revalidate(device);
+		if (check_floppy_change(disk))
+		        floppy_revalidate(disk);
 
 		if (UD.flags & FTD_MSG)
 		    printk (KERN_INFO "floppy%d: setting size %d spt %d str %d!\n",
@@ -1902,21 +1907,21 @@
 }
 
 static struct block_device_operations floppy_fops = {
-	owner:			THIS_MODULE,
-	open:			floppy_open,
-	release:		floppy_release,
-	ioctl:			fd_ioctl,
-	check_media_change:	check_floppy_change,
-	revalidate:		floppy_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= floppy_open,
+	.release	= floppy_release,
+	.ioctl		= fd_ioctl,
+	.media_changed	= check_floppy_change,
+	.revalidate_disk= floppy_revalidate,
 };
 
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
 {
-	int drive = minor & 3;
-	int type  = minor >> 2;
+	int drive = *part & 3;
+	int type  = *part >> 2;
 	if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
 		return NULL;
-	return unit[drive].disk;
+	return get_disk(unit[drive].disk);
 }
 
 int __init atari_floppy_init (void)
@@ -1963,6 +1968,8 @@
 	PhysTrackBuffer = virt_to_phys(TrackBuffer);
 	BufferDrive = BufferSide = BufferTrack = -1;
 
+	blk_init_queue(&floppy_queue, do_fd_request, &ataflop_lock);
+
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].track = -1;
 		unit[i].flags = 0;
@@ -1970,12 +1977,14 @@
 		unit[i].disk->first_minor = i;
 		sprintf(unit[i].disk->disk_name, "fd%d", i);
 		unit[i].disk->fops = &floppy_fops;
+		unit[i].disk->private_data = &unit[i];
+		unit[i].disk->queue = &floppy_queue;
 		set_capacity(unit[i].disk, MAX_DISK_SIZE * 2);
 		add_disk(unit[i].disk);
 	}
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &ataflop_lock);
-	blk_set_probe(MAJOR_NR, floppy_find);
+	blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+				floppy_find, NULL, NULL);
 
 	printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n",
 	       DriveType == 0 ? 'D' : DriveType == 1 ? 'H' : 'E',
@@ -2033,14 +2042,14 @@
 void cleanup_module (void)
 {
 	int i;
+	blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		del_gendisk(unit[i].disk);
 		put_disk(unit[i].disk);
 	}
 	unregister_blkdev(MAJOR_NR, "fd");
-	blk_set_probe(MAJOR_NR, NULL);
 
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&floppy_queue);
 	del_timer_sync(&fd_timer);
 	atari_stram_free( DMABuffer );
 }
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/block/cciss.c	Fri Oct 18 21:03:08 2002
@@ -105,7 +105,7 @@
 		unsigned int cmd, unsigned long arg);
 
 static int revalidate_allvol(kdev_t dev);
-static int cciss_revalidate(kdev_t dev);
+static int cciss_revalidate(struct gendisk *disk);
 static int deregister_disk(int ctlr, int logvol);
 static int register_new_disk(int cltr);
 
@@ -125,11 +125,11 @@
 #endif /* CONFIG_PROC_FS */
 
 static struct block_device_operations cciss_fops  = {
-	owner:			THIS_MODULE,
-	open:			cciss_open, 
-	release:        	cciss_release,
-        ioctl:			cciss_ioctl,
-	revalidate:		cciss_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= cciss_open, 
+	.release       	= cciss_release,
+        .ioctl		= cciss_ioctl,
+	.revalidate_disk= cciss_revalidate,
 };
 
 #include "cciss_scsi.c"		/* For SCSI tape support */
@@ -699,12 +699,10 @@
 	
 }
 
-static int cciss_revalidate(kdev_t dev)
+static int cciss_revalidate(struct gendisk *disk)
 {
-        int ctlr = major(dev) - MAJOR_NR;
-	int target = minor(dev) >> NWD_SHIFT;
-        struct gendisk *disk = hba[ctlr]->gendisk[target];
-	set_capacity(disk, hba[ctlr]->drv[target].nr_blocks);
+	drive_info_struct *drv = disk->private_data;
+	set_capacity(disk, drv->nr_blocks);
 	return 0;
 }
 
@@ -765,7 +763,7 @@
 		drive_info_struct *drv = &(hba[ctlr]->drv[i]);
 		if (!drv->nr_blocks)
 			continue;
-		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->block_size;
+		hba[ctlr]->queue.hardsect_size = drv->block_size;
 		set_capacity(disk, drv->nr_blocks);
 		add_disk(disk);
 	}
@@ -1690,10 +1688,11 @@
 {
 	ctlr_info_t *h= q->queuedata; 
 	CommandList_struct *c;
-	int log_unit, start_blk, seg;
+	int start_blk, seg;
 	struct request *creq;
 	u64bit temp64;
 	struct scatterlist tmp_sg[MAXSGENTRIES];
+	drive_info_struct *drv;
 	int i, dir;
 
 	if (blk_queue_plugged(q))
@@ -1707,16 +1706,6 @@
 	if (creq->nr_phys_segments > MAXSGENTRIES)
                 BUG();
 
-        if (h->ctlr != major(creq->rq_dev)-MAJOR_NR )
-        {
-                printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
-                                h->ctlr, major(creq->rq_dev), creq);
-                blkdev_dequeue_request(creq);
-                complete_buffers(creq->bio, 0);
-		end_that_request_last(creq);
-		goto startio;
-        }
-
 	if (( c = cmd_alloc(h, 1)) == NULL)
 		goto startio;
 
@@ -1728,10 +1717,10 @@
 	c->rq = creq;
 	
 	/* fill in the request */ 
-	log_unit = minor(creq->rq_dev) >> NWD_SHIFT; 
+	drv = creq->rq_disk->private_data;
 	c->Header.ReplyQueue = 0;  // unused in simple mode
 	c->Header.Tag.lower = c->busaddr;  // use the physical address the cmd block for tag
-	c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID;
+	c->Header.LUN.LogDev.VolId= drv->LunID;
 	c->Header.LUN.LogDev.Mode = 1;
 	c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
 	c->Request.Type.Type =  TYPE_CMD; // It is a command. 
@@ -1854,7 +1843,7 @@
 	 * See if we can queue up some more IO
 	 */
 	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
-	blk_start_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
+	blk_start_queue(&h->queue);
 }
 /* 
  *  We cannot read the structure directly, for portablity we must use 
@@ -2425,7 +2414,7 @@
 
 	cciss_procinit(i);
 
-	q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+	q = &hba[i]->queue;
         q->queuedata = hba[i];
 	spin_lock_init(&hba[i]->lock);
         blk_init_queue(q, do_cciss_request, &hba[i]->lock);
@@ -2447,9 +2436,12 @@
 		sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
 		disk->major = MAJOR_NR + i;
 		disk->first_minor = j << NWD_SHIFT;
+		disk->fops = &cciss_fops;
+		disk->queue = &hba[i]->queue;
+		disk->private_data = drv;
 		if( !(drv->nr_blocks))
 			continue;
-		(BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->block_size;
+		hba[i]->queue.hardsect_size = drv->block_size;
 		set_capacity(disk, drv->nr_blocks);
 		add_disk(disk);
 	}
diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h
--- a/drivers/block/cciss.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/cciss.h	Fri Oct 18 21:03:03 2002
@@ -70,6 +70,7 @@
 	unsigned int maxQsinceinit;
 	unsigned int maxSG;
 	spinlock_t lock;
+	struct request_queue queue;
 
 	//* pointers to command and error info pool */ 
 	CommandList_struct 	*cmd_pool;
@@ -245,7 +246,7 @@
 	struct access_method *access;
 };
 
-#define CCISS_LOCK(i)	((BLK_DEFAULT_QUEUE(MAJOR_NR + i))->queue_lock)
+#define CCISS_LOCK(i)	(hba[i]->queue.queue_lock)
 
 #endif /* CCISS_H */
 
diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
--- a/drivers/block/cciss_scsi.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/cciss_scsi.c	Fri Oct 18 21:03:03 2002
@@ -1250,8 +1250,6 @@
 	return length;
 }
 
-/* It's a pity that we need this, but, we do... */
-extern struct Scsi_Host *scsi_hostlist;  /* from ../scsi/hosts.c */
 
 int
 cciss_scsi_proc_info(char *buffer, /* data buffer */
@@ -1268,24 +1266,9 @@
 	ctlr_info_t *ci;
 	int cntl_num;
 
-	/* Lets see if we can find our Scsi_Host... 
-	   this might be kind of "bad", searching scis_hostlist this way
-	   but how else can we find the scsi host?  I think I've seen
-	   this coded both ways, (circular list and null terminated list)
-	   I coded it to work either way, since I wasn't sure.  */
 
-	sh = scsi_hostlist;
-	found=0;
-	do {
-		if (sh == NULL) break;
-		if (sh->host_no == hostnum) {
-			found++;
-			break;
-		}
-		sh = sh->next;
-	} while (sh != scsi_hostlist && sh != NULL);
-
-	if (sh == NULL || found == 0) /* This really shouldn't ever happen. */
+	sh = scsi_host_hn_get(hostnum);
+	if (sh == NULL) /* This really shouldn't ever happen. */
 		return -EINVAL;
 
 	ci = (ctlr_info_t *) sh->hostdata[0];
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/cpqarray.c	Fri Oct 18 21:03:03 2002
@@ -150,7 +150,7 @@
 
 static void do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
 static void ida_timer(unsigned long tdata);
-static int ida_revalidate(kdev_t dev);
+static int ida_revalidate(struct gendisk *disk);
 static int revalidate_allvol(kdev_t dev);
 
 #ifdef CONFIG_PROC_FS
@@ -163,11 +163,11 @@
 #endif
 
 static struct block_device_operations ida_fops  = {
-	owner:		THIS_MODULE,
-	open:		ida_open,
-	release:	ida_release,
-	ioctl:		ida_ioctl,
-	revalidate:	ida_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= ida_open,
+	.release	= ida_release,
+	.ioctl		= ida_ioctl,
+	.revalidate_disk= ida_revalidate,
 };
 
 
@@ -296,7 +296,7 @@
 		iounmap(hba[i]->vaddr);
 		unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
 		del_timer(&hba[i]->timer);
-		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
+		blk_cleanup_queue(&hba[i]->queue);
 		remove_proc_entry(hba[i]->devname, proc_array);
 		pci_free_consistent(hba[i]->pci_dev, 
 			NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool), 
@@ -378,7 +378,7 @@
 
 		ida_procinit(i);
 
-		q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+		q = &hba[i]->queue;
 		q->queuedata = hba[i];
 		spin_lock_init(&hba[i]->lock);
 		blk_init_queue(q, do_ida_request, &hba[i]->lock);
@@ -409,8 +409,10 @@
 			disk->fops = &ida_fops; 
 			if (!drv->nr_blks)
 				continue;
-			(BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->blk_size;
+			hba[i]->queue.hardsect_size = drv->blk_size;
 			set_capacity(disk, drv->nr_blks);
+			disk->queue = &hba[i]->queue;
+			disk->private_data = drv;
 			add_disk(disk);
 		}
 	}
@@ -1004,7 +1006,7 @@
 	/*
 	 * See if we can queue up some more IO
 	 */
-	do_ida_request(BLK_DEFAULT_QUEUE(MAJOR_NR+h->ctlr));
+	do_ida_request(&h->queue);
 	spin_unlock_irqrestore(IDA_LOCK(h->ctlr), flags); 
 }
 
@@ -1427,7 +1429,7 @@
 	 */
 	for (i = 0; i < NWD; i++) {
 		struct gendisk *disk = ida_gendisk[ctlr][i];
-		if (disk->flags & GENDH_FL_UP)
+		if (disk->flags & GENHD_FL_UP)
 			del_gendisk(disk);
 	}
 	memset(hba[ctlr]->drv,            0, sizeof(drv_info_t)*NWD);
@@ -1446,8 +1448,10 @@
 		drv_info_t *drv = &hba[ctlr]->drv[i];
 		if (!drv->nr_blks)
 			continue;
-		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size;
+		hba[ctlr]->queue.hardsect_size = drv->blk_size;
 		set_capacity(disk, drv->nr_blks);
+		disk->queue = &hba[ctlr]->queue;
+		disk->private_data = drv;
 		add_disk(disk);
 	}
 
@@ -1455,12 +1459,10 @@
 	return 0;
 }
 
-static int ida_revalidate(kdev_t dev)
+static int ida_revalidate(struct gendisk *disk)
 {
-        int ctlr = major(dev) - MAJOR_NR;
-	int target = DEVICE_NR(dev);
-        struct gendisk *gdev = ida_gendisk[ctlr][target];
-	set_capacity(gdev, hba[ctlr]->drv[target].nr_blks);
+	drv_info_t *drv = disk->private_data;
+	set_capacity(disk, drv->nr_blks);
 	return 0;
 }
 
diff -Nru a/drivers/block/cpqarray.h b/drivers/block/cpqarray.h
--- a/drivers/block/cpqarray.h	Fri Oct 18 21:03:06 2002
+++ b/drivers/block/cpqarray.h	Fri Oct 18 21:03:06 2002
@@ -105,6 +105,7 @@
 	cmdlist_t *cmd_pool;
 	dma_addr_t cmd_pool_dhandle;
 	unsigned long *cmd_pool_bits;
+	struct request_queue queue;
 	spinlock_t lock;
 
 	unsigned int Qdepth;
@@ -117,7 +118,7 @@
 	unsigned int misc_tflags;
 };
 
-#define IDA_LOCK(i)	((BLK_DEFAULT_QUEUE(MAJOR_NR + i))->queue_lock)
+#define IDA_LOCK(i)	(&hba[i]->lock)
 
 #endif
 
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/floppy.c	Fri Oct 18 21:03:03 2002
@@ -243,13 +243,13 @@
 #define MAJOR_NR FLOPPY_MAJOR
 #define DEVICE_NAME "floppy"
 #define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
-
 #include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h> /* for the compatibility eject ioctl */
 #include <linux/completion.h>
 
 static struct request *current_req;
+static struct request_queue floppy_queue;
 
 #ifndef fd_get_dma_residue
 #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@ -2295,12 +2295,10 @@
 
 static inline void end_request(struct request *req, int uptodate)
 {
-	kdev_t dev = req->rq_dev;
-
 	if (end_that_request_first(req, uptodate, current_count_sectors))
 		return;
-	add_blkdev_randomness(major(dev));
-	floppy_off(DEVICE_NR(dev));
+	add_blkdev_randomness(MAJOR_NR);
+	floppy_off((int)req->rq_disk->private_data);
 	blkdev_dequeue_request(req);
 	end_that_request_last(req);
 
@@ -2313,7 +2311,7 @@
  * logical buffer */
 static void request_done(int uptodate)
 {
-	struct request_queue *q = QUEUE;
+	struct request_queue *q = &floppy_queue;
 	struct request *req = current_req;
 	unsigned long flags;
 	int block;
@@ -2913,7 +2911,7 @@
 
 	for (;;) {
 		if (!current_req) {
-			struct request *req = elv_next_request(QUEUE);
+			struct request *req = elv_next_request(&floppy_queue);
 			if (!req) {
 				do_floppy = NULL;
 				unlock_fdc();
@@ -2921,9 +2919,6 @@
 			}
 			current_req = req;
 		}
-		if (major(current_req->rq_dev) != MAJOR_NR)
-			panic(DEVICE_NAME ": request list destroyed");
-
 		device = current_req->rq_dev;
 		set_fdc(DRIVE(device));
 		reschedule_timeout(current_reqD, "redo fd request", 0);
@@ -3796,14 +3791,9 @@
 /*
  * Check if the disk has been changed or if a change has been faked.
  */
-static int check_floppy_change(kdev_t dev)
+static int check_floppy_change(struct gendisk *disk)
 {
-	int drive = DRIVE(dev);
-
-	if (major(dev) != MAJOR_NR) {
-		DPRINT("check_floppy_change: not a floppy\n");
-		return 0;
-	}
+	int drive = (int)disk->private_data;
 
 	if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
 		return 1;
@@ -3822,7 +3812,7 @@
 	if (UTESTF(FD_DISK_CHANGED) ||
 	   UTESTF(FD_VERIFY) ||
 	   test_bit(drive, &fake_change) ||
-	   (!TYPE(dev) && !current_type[drive]))
+	   (!ITYPE(UDRS->fd_device) && !current_type[drive]))
 		return 1;
 	return 0;
 }
@@ -3884,16 +3874,17 @@
 	return 0;
 }
 
-static int floppy_read_block_0(kdev_t dev)
+static int floppy_read_block_0(struct gendisk *disk)
 {
 	struct block_device *bdev;
 	int ret;
 
-	bdev = bdget(kdev_t_to_nr(dev));
+	bdev = bdget(MKDEV(disk->major, disk->first_minor));
 	if (!bdev) {
-		printk("No block device for %s\n", __bdevname(dev));
+		printk("No block device for %s\n", disk->disk_name);
 		BUG();
 	}
+	bdev->bd_disk = disk;	/* ewww */
 	ret = __floppy_read_block_0(bdev);
 	atomic_dec(&bdev->bd_count);
 	return ret;
@@ -3903,10 +3894,10 @@
  * the bootblock (block 0). "Autodetection" is also needed to check whether
  * there is a disk in the drive at all... Thus we also do it for fixed
  * geometry formats */
-static int floppy_revalidate(kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
 {
-#define NO_GEOM (!current_type[drive] && !TYPE(dev))
-	int drive=DRIVE(dev);
+	int drive=(int)disk->private_data;
+#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
 	int cf;
 	int res = 0;
 
@@ -3934,24 +3925,24 @@
 			UDRS->generation++;
 		if (NO_GEOM){
 			/* auto-sensing */
-			res = floppy_read_block_0(dev);
+			res = floppy_read_block_0(disk);
 		} else {
 			if (cf)
 				poll_drive(0, FD_RAW_NEED_DISK);
 			process_fd_request();
 		}
 	}
-	set_capacity(disks[drive], floppy_sizes[minor(dev)]);
+	set_capacity(disk, floppy_sizes[UDRS->fd_device]);
 	return res;
 }
 
 static struct block_device_operations floppy_fops = {
-	owner:			THIS_MODULE,
-	open:			floppy_open,
-	release:		floppy_release,
-	ioctl:			fd_ioctl,
-	check_media_change:	check_floppy_change,
-	revalidate:		floppy_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= floppy_open,
+	.release	= floppy_release,
+	.ioctl		= fd_ioctl,
+	.media_changed	= check_floppy_change,
+	.revalidate_disk= floppy_revalidate,
 };
 
 static void __init register_devfs_entries (int drive)
@@ -4212,14 +4203,14 @@
 	},
 };
 
-static struct gendisk *floppy_find(int minor)
+static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
 {
-	int drive = (minor&3) | ((minor&0x80) >> 5);
+	int drive = (*part&3) | ((*part&0x80) >> 5);
 	if (drive >= N_DRIVE ||
 	    !(allowed_drive_mask & (1 << drive)) ||
 	    fdc_state[FDC(drive)].version == FDC_NONE)
 		return NULL;
-	return disks[drive];
+	return get_disk(disks[drive]);
 }
 
 int __init floppy_init(void)
@@ -4249,7 +4240,8 @@
 		sprintf(disks[i]->disk_name, "fd%d", i);
 	}
 
-	blk_set_probe(MAJOR_NR, floppy_find);
+	blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
+				floppy_find, NULL, NULL);
 
 	for (i=0; i<256; i++)
 		if (ITYPE(i))
@@ -4257,7 +4249,7 @@
 		else
 			floppy_sizes[i] = MAX_DISK_SIZE << 1;
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &floppy_lock);
+	blk_init_queue(&floppy_queue, do_fd_request, &floppy_lock);
 	reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
 	config_types();
 
@@ -4359,6 +4351,9 @@
 			continue;
 		if (fdc_state[FDC(drive)].version == FDC_NONE)
 			continue;
+		/* to be cleaned up... */
+		disks[drive]->private_data = (void*)drive;
+		disks[drive]->queue = &floppy_queue;
 		add_disk(disks[drive]);
 	}
 
@@ -4368,9 +4363,9 @@
 out1:
 	del_timer(&fd_timeout);
 out2:
+	blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
 	unregister_blkdev(MAJOR_NR,"fd");
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-	blk_set_probe(MAJOR_NR, NULL);
+	blk_cleanup_queue(&floppy_queue);
 out:
 	for (i=0; i<N_DRIVE; i++)
 		put_disk(disks[i]);
@@ -4563,8 +4558,8 @@
 		
 	platform_device_unregister(&floppy_device);
 	devfs_unregister (devfs_handle);
+	blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
 	unregister_blkdev(MAJOR_NR, "fd");
-	blk_set_probe(MAJOR_NR, NULL);
 	for (drive = 0; drive < N_DRIVE; drive++) {
 		if ((allowed_drive_mask & (1 << drive)) &&
 		    fdc_state[FDC(drive)].version != FDC_NONE)
@@ -4572,7 +4567,7 @@
 		put_disk(disks[drive]);
 	}
 
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&floppy_queue);
 	/* eject disk, if any */
 	fd_eject(0);
 }
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/block/genhd.c	Fri Oct 18 21:03:04 2002
@@ -24,6 +24,7 @@
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/kmod.h>
 
 
 static rwlock_t gendisk_lock;
@@ -33,22 +34,74 @@
  */
 static LIST_HEAD(gendisk_list);
 
-/*
- *  TEMPORARY KLUDGE.
- */
-static struct {
-	struct list_head list;
-	struct gendisk *(*get)(int minor);
-} gendisks[MAX_BLKDEV];
+struct blk_probe {
+	struct blk_probe *next;
+	dev_t dev;
+	unsigned long range;
+	struct module *owner;
+	struct gendisk *(*get)(dev_t dev, int *part, void *data);
+	void (*lock)(dev_t, void *);
+	void *data;
+} *probes[MAX_BLKDEV];
+
+/* index in the above */
+static inline int dev_to_index(dev_t dev)
+{
+	return MAJOR(dev);
+}
+
+void blk_register_region(dev_t dev, unsigned long range, struct module *module,
+		    struct gendisk *(*probe)(dev_t, int *, void *),
+		    void (*lock)(dev_t, void *), void *data)
+{
+	int index = dev_to_index(dev);
+	struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
+	struct blk_probe **s;
+	p->owner = module;
+	p->get = probe;
+	p->lock = lock;
+	p->dev = dev;
+	p->range = range;
+	p->data = data;
+	write_lock(&gendisk_lock);
+	for (s = &probes[index]; *s && (*s)->range < range; s = &(*s)->next)
+		;
+	p->next = *s;
+	*s = p;
+	write_unlock(&gendisk_lock);
+}
 
-void blk_set_probe(int major, struct gendisk *(p)(int))
+void blk_unregister_region(dev_t dev, unsigned long range)
 {
+	int index = dev_to_index(dev);
+	struct blk_probe **s;
 	write_lock(&gendisk_lock);
-	gendisks[major].get = p;
+	for (s = &probes[index]; *s; s = &(*s)->next) {
+		struct blk_probe *p = *s;
+		if (p->dev == dev || p->range == range) {
+			*s = p->next;
+			kfree(p);
+			break;
+		}
+	}
 	write_unlock(&gendisk_lock);
 }
-EXPORT_SYMBOL(blk_set_probe);	/* Will go away */
-	
+
+EXPORT_SYMBOL(blk_register_region);
+EXPORT_SYMBOL(blk_unregister_region);
+
+static struct gendisk *exact_match(dev_t dev, int *part, void *data)
+{
+	struct gendisk *p = data;
+	*part = MINOR(dev) - p->first_minor;
+	return p;
+}
+
+static void exact_lock(dev_t dev, void *data)
+{
+	struct gendisk *p = data;
+	get_disk(p);
+}
 
 /**
  * add_gendisk - add partitioning information to kernel list
@@ -60,10 +113,11 @@
 void add_disk(struct gendisk *disk)
 {
 	write_lock(&gendisk_lock);
-	list_add(&disk->list, &gendisks[disk->major].list);
 	list_add_tail(&disk->full_list, &gendisk_list);
 	write_unlock(&gendisk_lock);
 	disk->flags |= GENHD_FL_UP;
+	blk_register_region(MKDEV(disk->major, disk->first_minor), disk->minors,
+			NULL, exact_match, exact_lock, disk);
 	register_disk(disk);
 }
 
@@ -74,8 +128,9 @@
 {
 	write_lock(&gendisk_lock);
 	list_del_init(&disk->full_list);
-	list_del_init(&disk->list);
 	write_unlock(&gendisk_lock);
+	blk_unregister_region(MKDEV(disk->major, disk->first_minor),
+			      disk->minors);
 }
 
 /**
@@ -88,30 +143,40 @@
 struct gendisk *
 get_gendisk(dev_t dev, int *part)
 {
+	int index = dev_to_index(dev);
 	struct gendisk *disk;
-	struct list_head *p;
-	int major = MAJOR(dev);
-	int minor = MINOR(dev);
+	struct blk_probe *p;
+	unsigned best = ~0U;
 
-	*part = 0;
+retry:
 	read_lock(&gendisk_lock);
-	if (gendisks[major].get) {
-		disk = gendisks[major].get(minor);
-		if (disk)
-			get_disk(disk);
-		read_unlock(&gendisk_lock);
-		return disk;
-	}
-	list_for_each(p, &gendisks[major].list) {
-		disk = list_entry(p, struct gendisk, list);
-		if (disk->first_minor > minor)
+	for (p = probes[index]; p; p = p->next) {
+		struct gendisk *(*probe)(dev_t, int *, void *);
+		struct module *owner;
+		void *data;
+		if (p->dev > dev || p->dev + p->range <= dev)
 			continue;
-		if (disk->first_minor + disk->minors <= minor)
+		if (p->range >= best) {
+			read_unlock(&gendisk_lock);
+			return NULL;
+		}
+		if (!try_inc_mod_count(p->owner))
 			continue;
-		get_disk(disk);
+		owner = p->owner;
+		data = p->data;
+		probe = p->get;
+		best = p->range;
+		*part = dev - p->dev;
+		if (p->lock)
+			p->lock(dev, data);
 		read_unlock(&gendisk_lock);
-		*part = minor - disk->first_minor;
-		return disk;
+		disk = probe(dev, part, data);
+		/* Currently ->owner protects _only_ ->probe() itself. */
+		if (owner)
+			__MOD_DEC_USE_COUNT(owner);
+		if (disk)
+			return disk;
+		goto retry;
 	}
 	read_unlock(&gendisk_lock);
 	return NULL;
@@ -183,8 +248,6 @@
 
 
 extern int blk_dev_init(void);
-extern int soc_probe(void);
-extern int atmdev_init(void);
 
 struct device_class disk_devclass = {
 	.name		= "disk",
@@ -193,13 +256,26 @@
 static struct bus_type disk_bus = {
 	name:		"block",
 };
+ 
+static struct gendisk *base_probe(dev_t dev, int *part, void *data)
+{
+	char name[20];
+	sprintf(name, "block-major-%d", MAJOR(dev));
+	request_module(name);
+	return NULL;
+}
 
 int __init device_init(void)
 {
+	struct blk_probe *base = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
 	int i;
 	rwlock_init(&gendisk_lock);
-	for (i = 0; i < MAX_BLKDEV; i++)
-		INIT_LIST_HEAD(&gendisks[i].list);
+	memset(base, 0, sizeof(struct blk_probe));
+	base->dev = MKDEV(1,0);
+	base->range = MKDEV(MAX_BLKDEV-1, 255) - base->dev + 1;
+	base->get = base_probe;
+	for (i = 1; i < MAX_BLKDEV; i++)
+		probes[i] = base;
 	blk_dev_init();
 	devclass_register(&disk_devclass);
 	bus_register(&disk_bus);
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/ll_rw_blk.c	Fri Oct 18 21:03:03 2002
@@ -670,12 +670,10 @@
 		bit++;
 	} while (bit < __REQ_NR_BITS);
 
-	if (rq->flags & REQ_CMD)
-		printk("sector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector,
+	printk("sector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector,
 						       rq->nr_sectors,
 						       rq->current_nr_sectors);
-
-	printk("\n");
+	printk("bio %p, biotail %p\n", rq->bio, rq->biotail);
 }
 
 void blk_recount_segments(request_queue_t *q, struct bio *bio)
@@ -1927,7 +1925,7 @@
 
 inline void blk_recalc_rq_sectors(struct request *rq, int nsect)
 {
-	if (rq->flags & REQ_CMD) {
+	if (rq->bio) {
 		rq->hard_sector += nsect;
 		rq->nr_sectors = rq->hard_nr_sectors -= nsect;
 		rq->sector = rq->hard_sector;
@@ -1968,20 +1966,28 @@
 
 	req->errors = 0;
 	if (!uptodate) {
-		printk("end_request: I/O error, dev %s, sector %llu\n",
-			kdevname(req->rq_dev), (unsigned long long)req->sector);
 		error = -EIO;
+		if (!(req->flags & REQ_QUIET))
+			printk("end_request: I/O error, dev %s, sector %llu\n",
+				kdevname(req->rq_dev),
+				(unsigned long long)req->sector);
 	}
 
 	while ((bio = req->bio)) {
-		const int nsect = bio_iovec(bio)->bv_len >> 9;
-		int new_bio = 0;
+		int new_bio = 0, nsect;
+
+		if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
+			printk("%s: bio idx %d >= vcnt %d\n", __FUNCTION__,
+						bio->bi_idx, bio->bi_vcnt);
+			break;
+		}
 
 		BIO_BUG_ON(bio_iovec(bio)->bv_len > bio->bi_size);
 
 		/*
 		 * not a complete bvec done
 		 */
+		nsect = bio_iovec(bio)->bv_len >> 9;
 		if (unlikely(nsect > nr_sectors)) {
 			int partial = nr_sectors << 9;
 
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/block/loop.c	Fri Oct 18 21:03:05 2002
@@ -437,7 +437,7 @@
 static int loop_end_io_transfer(struct bio *bio, unsigned int bytes_done, int err)
 {
 	struct bio *rbh = bio->bi_private;
-	struct loop_device *lo = &loop_dev[minor(to_kdev_t(rbh->bi_bdev->bd_dev))];
+	struct loop_device *lo = rbh->bi_bdev->bd_disk->private_data;
 
 	if (bio->bi_size)
 		return 1;
@@ -916,20 +916,9 @@
 static int lo_ioctl(struct inode * inode, struct file * file,
 	unsigned int cmd, unsigned long arg)
 {
-	struct loop_device *lo;
-	int dev, err;
+	struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+	int err;
 
-	if (!inode)
-		return -EINVAL;
-	if (major(inode->i_rdev) != MAJOR_NR) {
-		printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n",
-		       MAJOR_NR);
-		return -ENODEV;
-	}
-	dev = minor(inode->i_rdev);
-	if (dev >= max_loop)
-		return -ENODEV;
-	lo = &loop_dev[dev];
 	down(&lo->lo_ctl_mutex);
 	switch (cmd) {
 	case LOOP_SET_FD:
@@ -953,14 +942,9 @@
 
 static int lo_open(struct inode *inode, struct file *file)
 {
-	struct loop_device *lo;
-	int	dev, type;
-
-	dev = minor(inode->i_rdev);
-	if (dev >= max_loop)
-		return -ENODEV;
+	struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+	int type;
 
-	lo = &loop_dev[dev];
 	down(&lo->lo_ctl_mutex);
 
 	type = lo->lo_encrypt_type; 
@@ -973,14 +957,9 @@
 
 static int lo_release(struct inode *inode, struct file *file)
 {
-	struct loop_device *lo;
-	int	dev, type;
+	struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+	int type;
 
-	dev = minor(inode->i_rdev);
-	if (dev >= max_loop)
-		return 0;
-
-	lo = &loop_dev[dev];
 	down(&lo->lo_ctl_mutex);
 	type = lo->lo_encrypt_type;
 	--lo->lo_refcnt;
@@ -1034,16 +1013,6 @@
 EXPORT_SYMBOL(loop_register_transfer);
 EXPORT_SYMBOL(loop_unregister_transfer);
 
-request_queue_t *loop_get_queue(kdev_t dev)
-{
-	int minor = minor(dev);
-
-	if (minor < max_loop)
-		return &loop_dev[minor].lo_queue;
-
-	return NULL;
-}
-
 int __init loop_init(void) 
 {
 	int	i;
@@ -1093,11 +1062,10 @@
 		disk->first_minor = i;
 		disk->fops = &lo_fops;
 		sprintf(disk->disk_name, "loop%d", i);
+		disk->private_data = lo;
+		disk->queue = &lo->lo_queue;
 		add_disk(disk);
 	}
-
-	blk_dev[LOOP_MAJOR].queue = loop_get_queue;
-
 	printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
 	return 0;
 
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/nbd.c	Fri Oct 18 21:03:03 2002
@@ -52,15 +52,10 @@
 #include <asm/types.h>
 
 #define MAJOR_NR NBD_MAJOR
-#define DEVICE_NR(device) (minor(device))
 #include <linux/nbd.h>
 
 #define LO_MAGIC 0x68797548
 
-static int nbd_blksizes[MAX_NBD];
-static int nbd_blksize_bits[MAX_NBD];
-static u64 nbd_bytesizes[MAX_NBD];
-
 static struct nbd_device nbd_dev[MAX_NBD];
 static devfs_handle_t devfs_handle;
 
@@ -77,11 +72,8 @@
 
 static int nbd_open(struct inode *inode, struct file *file)
 {
-	int dev = minor(inode->i_rdev);
-	if (dev >= MAX_NBD)
-		return -ENODEV;
-
-	nbd_dev[dev].refcnt++;
+	struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
+	lo->refcnt++;
 	return 0;
 }
 
@@ -270,7 +262,7 @@
 			goto out;
 		}
 #ifdef PARANOIA
-		if (lo != &nbd_dev[minor(req->rq_dev)]) {
+		if (lo != req->rq_disk->private_data) {
 			printk(KERN_ALERT "NBD: request corrupted!\n");
 			continue;
 		}
@@ -320,29 +312,19 @@
  */
 
 #undef FAIL
-#define FAIL( s ) { printk( KERN_ERR "NBD, minor %d: " s "\n", dev ); goto error_out; }
+#define FAIL( s ) { printk( KERN_ERR "%s: " s "\n", req->rq_disk->disk_name ); goto error_out; }
 
 static void do_nbd_request(request_queue_t * q)
 {
-	struct request *req;
-	int dev = 0;
-	struct nbd_device *lo;
 
-	while (!blk_queue_empty(QUEUE)) {
-		req = CURRENT;
-#ifdef PARANOIA
-		if (!req)
-			FAIL("queue not empty but no request?");
-#endif
-		dev = minor(req->rq_dev);
-#ifdef PARANOIA
-		if (dev >= MAX_NBD)
-			FAIL("Minor too big.");		/* Probably can not happen */
-#endif
+	while (!blk_queue_empty(q)) {
+		struct request *req = elv_next_request(q);
+		struct nbd_device *lo;
+
 		if (!(req->flags & REQ_CMD))
 			goto error_out;
 
-		lo = &nbd_dev[dev];
+		lo = req->rq_disk->private_data;
 		if (!lo->file)
 			FAIL("Request when not-ready.");
 		nbd_cmd(req) = NBD_CMD_READ;
@@ -382,8 +364,7 @@
 static int nbd_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	int dev = minor(inode->i_rdev);
-	struct nbd_device *lo = &nbd_dev[dev];
+	struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
 	int error, temp;
 	struct request sreq ;
 
@@ -436,23 +417,23 @@
 	case NBD_SET_BLKSIZE:
 		if ((arg & (arg-1)) || (arg < 512) || (arg > PAGE_SIZE))
 			return -EINVAL;
-		nbd_blksizes[dev] = arg;
+		lo->blksize = arg;
 		temp = arg >> 9;
-		nbd_blksize_bits[dev] = 9;
+		lo->blksize_bits = 9;
 		while (temp > 1) {
-			nbd_blksize_bits[dev]++;
+			lo->blksize_bits++;
 			temp >>= 1;
 		}
-		nbd_bytesizes[dev] &= ~(nbd_blksizes[dev]-1); 
-		set_capacity(lo->disk, nbd_bytesizes[dev] >> 9);
+		lo->bytesize &= ~(lo->blksize-1); 
+		set_capacity(lo->disk, lo->bytesize >> 9);
 		return 0;
 	case NBD_SET_SIZE:
-		nbd_bytesizes[dev] = arg & ~(nbd_blksizes[dev]-1); 
-		set_capacity(lo->disk, nbd_bytesizes[dev] >> 9);
+		lo->bytesize = arg & ~(lo->blksize-1); 
+		set_capacity(lo->disk, lo->bytesize >> 9);
 		return 0;
 	case NBD_SET_SIZE_BLOCKS:
-		nbd_bytesizes[dev] = ((u64) arg) << nbd_blksize_bits[dev]; 
-		set_capacity(lo->disk, nbd_bytesizes[dev] >> 9);
+		lo->bytesize = ((u64) arg) << lo->blksize_bits;
+		set_capacity(lo->disk, lo->bytesize >> 9);
 		return 0;
 	case NBD_DO_IT:
 		if (!lo->file)
@@ -464,8 +445,9 @@
 		return 0;
 #ifdef PARANOIA
 	case NBD_PRINT_DEBUG:
-		printk(KERN_INFO "NBD device %d: next = %p, prev = %p. Global: in %d, out %d\n",
-		       dev, lo->queue_head.next, lo->queue_head.prev, requests_in, requests_out);
+		printk(KERN_INFO "%s: next = %p, prev = %p. Global: in %d, out %d\n",
+		       inode->i_bdev->bd_disk->disk_name, lo->queue_head.next,
+		       lo->queue_head.prev, requests_in, requests_out);
 		return 0;
 #endif
 	}
@@ -474,8 +456,7 @@
 
 static int nbd_release(struct inode *inode, struct file *file)
 {
-	int dev = minor(inode->i_rdev);
-	struct nbd_device *lo = &nbd_dev[dev];
+	struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
 	if (lo->refcnt <= 0)
 		printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt);
 	lo->refcnt--;
@@ -496,6 +477,8 @@
  *  (Just smiley confuses emacs :-)
  */
 
+static struct request_queue nbd_queue;
+
 static int __init nbd_init(void)
 {
 	int err = -ENOMEM;
@@ -522,7 +505,7 @@
 #ifdef MODULE
 	printk("nbd: registered device at major %d\n", MAJOR_NR);
 #endif
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request, &nbd_lock);
+	blk_init_queue(&nbd_queue, do_nbd_request, &nbd_lock);
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
 		nbd_dev[i].refcnt = 0;
@@ -532,12 +515,13 @@
 		spin_lock_init(&nbd_dev[i].queue_lock);
 		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
 		init_MUTEX(&nbd_dev[i].tx_lock);
-		nbd_blksizes[i] = 1024;
-		nbd_blksize_bits[i] = 10;
-		nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
+		nbd_dev[i].blksize = 1024;
+		nbd_dev[i].blksize_bits = 10;
+		nbd_dev[i].bytesize = 0x7ffffc00; /* 2GB */
 		disk->major = MAJOR_NR;
 		disk->first_minor = i;
 		disk->fops = &nbd_fops;
+		disk->private_data = &nbd_dev[i];
 		sprintf(disk->disk_name, "nbd%d", i);
 		set_capacity(disk, 0x3ffffe);
 		add_disk(disk);
@@ -563,7 +547,7 @@
 		put_disk(nbd_dev[i].disk);
 	}
 	devfs_unregister (devfs_handle);
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&nbd_queue);
 
 	if (unregister_blkdev(MAJOR_NR, "nbd") != 0)
 		printk("nbd: cleanup_module failed\n");
diff -Nru a/drivers/block/paride/epat.c b/drivers/block/paride/epat.c
--- a/drivers/block/paride/epat.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/block/paride/epat.c	Fri Oct 18 21:03:08 2002
@@ -304,7 +304,6 @@
 static void epat_init_proto( PIA *pi)
 
 {  	MOD_INC_USE_COUNT;
-	printk("epat_init_proto");
 }
 
 static void epat_release_proto( PIA *pi)
diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
--- a/drivers/block/paride/pcd.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/block/paride/pcd.c	Fri Oct 18 21:03:04 2002
@@ -239,6 +239,7 @@
 */
 
 static struct pcd_unit *pcd_current; /* current request's drive */
+static struct request *pcd_req;
 static int pcd_retries;		/* retries on current request */
 static int pcd_busy;		/* request being processed ? */
 static int pcd_sector;		/* address of next requested sector */
@@ -249,12 +250,37 @@
 
 /* kernel glue structures */
 
+static int pcd_block_open(struct inode *inode, struct file *file)
+{
+	struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+	return cdrom_open(&cd->info, inode, file);
+}
+
+static int pcd_block_release(struct inode *inode, struct file *file)
+{
+	struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+	return cdrom_release(&cd->info, file);
+}
+
+static int pcd_block_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+	return cdrom_ioctl(&cd->info, inode, cmd, arg);
+}
+
+static int pcd_block_media_changed(struct gendisk *disk)
+{
+	struct pcd_unit *cd = disk->private_data;
+	return cdrom_media_changed(&cd->info);
+}
+
 static struct block_device_operations pcd_bdops = {
-	.owner			= THIS_MODULE,
-	.open			= cdrom_open,
-	.release		= cdrom_release,
-	.ioctl			= cdrom_ioctl,
-	.check_media_change	= cdrom_media_changed,
+	.owner		= THIS_MODULE,
+	.open		= pcd_block_open,
+	.release	= pcd_block_release,
+	.ioctl		= pcd_block_ioctl,
+	.media_changed	= pcd_block_media_changed,
 };
 
 static struct cdrom_device_ops pcd_dops = {
@@ -297,7 +323,6 @@
 		snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
 		cd->info.ops = &pcd_dops;
 		cd->info.handle = cd;
-		cd->info.dev = mk_kdev(major, unit);
 		cd->info.speed = 0;
 		cd->info.capacity = 1;
 		cd->info.mask = 0;
@@ -714,32 +739,43 @@
 }
 
 /* I/O request processing */
+static struct request_queue pcd_queue;
 
 static void do_pcd_request(request_queue_t * q)
 {
 	if (pcd_busy)
 		return;
 	while (1) {
-		struct request *req;
-		if (blk_queue_empty(QUEUE))
+		if (blk_queue_empty(q))
 			return;
-		req = CURRENT;
-		if (rq_data_dir(req) == READ) {
-			struct pcd_unit *cd = pcd + minor(req->rq_dev);
+		pcd_req = elv_next_request(q);
+		if (rq_data_dir(pcd_req) == READ) {
+			struct pcd_unit *cd = pcd_req->rq_disk->private_data;
 			if (cd != pcd_current)
 				pcd_bufblk = -1;
 			pcd_current = cd;
-			pcd_sector = req->sector;
-			pcd_count = req->current_nr_sectors;
-			pcd_buf = req->buffer;
+			pcd_sector = pcd_req->sector;
+			pcd_count = pcd_req->current_nr_sectors;
+			pcd_buf = pcd_req->buffer;
 			pcd_busy = 1;
 			ps_set_intr(do_pcd_read, 0, 0, nice);
 			return;
 		} else
-			end_request(req, 0);
+			end_request(pcd_req, 0);
 	}
 }
 
+static inline void next_request(int success)
+{
+	long saved_flags;
+
+	spin_lock_irqsave(&pcd_lock, saved_flags);
+	end_request(pcd_req, success);
+	pcd_busy = 0;
+	do_pcd_request(&pcd_queue);
+	spin_unlock_irqrestore(&pcd_lock, saved_flags);
+}
+
 static int pcd_ready(void)
 {
 	return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
@@ -761,7 +797,6 @@
 {
 	int b, i;
 	char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
-	unsigned long saved_flags;
 
 	pcd_bufblk = pcd_sector / 4;
 	b = pcd_bufblk;
@@ -772,11 +807,7 @@
 
 	if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
 		pcd_bufblk = -1;
-		spin_lock_irqsave(&pcd_lock, saved_flags);
-		pcd_busy = 0;
-		end_request(CURRENT, 0);
-		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&pcd_lock, saved_flags);
+		next_request(0);
 		return;
 	}
 
@@ -791,12 +822,7 @@
 	pcd_retries = 0;
 	pcd_transfer();
 	if (!pcd_count) {
-		unsigned long saved_flags;
-		spin_lock_irqsave(&pcd_lock, saved_flags);
-		end_request(CURRENT, 1);
-		pcd_busy = 0;
-		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&pcd_lock, saved_flags);
+		next_request(1);
 		return;
 	}
 
@@ -814,18 +840,14 @@
 			pi_do_claimed(pcd_current->pi, pcd_start);
 			return;
 		}
-		spin_lock_irqsave(&pcd_lock, saved_flags);
-		pcd_busy = 0;
 		pcd_bufblk = -1;
-		end_request(CURRENT, 0);
-		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&pcd_lock, saved_flags);
+		next_request(0);
 		return;
 	}
 
 	do_pcd_read();
 	spin_lock_irqsave(&pcd_lock, saved_flags);
-	do_pcd_request(NULL);
+	do_pcd_request(&pcd_queue);
 	spin_unlock_irqrestore(&pcd_lock, saved_flags);
 }
 
@@ -934,15 +956,17 @@
 		return -1;
 	}
 
+	blk_init_queue(&pcd_queue, do_pcd_request, &pcd_lock);
+
 	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 		if (cd->present) {
 			register_cdrom(&cd->info);
+			cd->disk->private_data = cd;
+			cd->disk->queue = &pcd_queue;
 			add_disk(cd->disk);
 		}
 	}
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_pcd_request, &pcd_lock);
-
 	return 0;
 }
 
@@ -959,6 +983,7 @@
 		}
 		put_disk(cd->disk);
 	}
+	blk_cleanup_queue(&pcd_queue);
 	unregister_blkdev(MAJOR_NR, name);
 }
 
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/block/paride/pd.c	Fri Oct 18 21:03:08 2002
@@ -196,9 +196,6 @@
 #include "pseudo.h"
 
 #define PD_BITS    4
-#define DEVICE_NR(device) (minor(device)>>PD_BITS)
-#define PD_PARTNS  	(1<<PD_BITS)
-#define PD_DEVS		PD_PARTNS*PD_UNITS
 
 /* numbers for "SCSI" geometry */
 
@@ -249,7 +246,7 @@
 static int pd_ioctl(struct inode *inode, struct file *file,
 		    unsigned int cmd, unsigned long arg);
 static int pd_release(struct inode *inode, struct file *file);
-static int pd_revalidate(kdev_t dev);
+static int pd_revalidate(struct gendisk *p);
 static int pd_detect(void);
 static void do_pd_read(void);
 static void do_pd_read_start(void);
@@ -284,7 +281,7 @@
 static int pd_identify(struct pd_unit *disk);
 static void pd_media_check(struct pd_unit *disk);
 static void pd_doorlock(struct pd_unit *disk, int func);
-static int pd_check_media(kdev_t dev);
+static int pd_check_media(struct gendisk *p);
 static void pd_eject(struct pd_unit *disk);
 
 static char pd_scratch[512];	/* scratch block buffer */
@@ -315,12 +312,12 @@
 extern struct block_device_operations pd_fops;
 
 static struct block_device_operations pd_fops = {
-	.owner			= THIS_MODULE,
-	.open			= pd_open,
-	.release		= pd_release,
-	.ioctl			= pd_ioctl,
-	.check_media_change	= pd_check_media,
-	.revalidate		= pd_revalidate
+	.owner		= THIS_MODULE,
+	.open		= pd_open,
+	.release	= pd_release,
+	.ioctl		= pd_ioctl,
+	.media_changed	= pd_check_media,
+	.revalidate_disk= pd_revalidate
 };
 
 static void pd_init_units(void)
@@ -347,8 +344,7 @@
 
 static int pd_open(struct inode *inode, struct file *file)
 {
-	int unit = DEVICE_NR(inode->i_rdev);
-	struct pd_unit *disk = pd + unit;
+	struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
 
 	disk->access++;
 
@@ -362,9 +358,9 @@
 static int pd_ioctl(struct inode *inode, struct file *file,
 	 unsigned int cmd, unsigned long arg)
 {
+	struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
 	struct hd_geometry *geo = (struct hd_geometry *) arg;
 	struct hd_geometry g;
-	struct pd_unit *disk = pd + DEVICE_NR(inode->i_rdev);
 
 	switch (cmd) {
 	case CDROMEJECT:
@@ -392,8 +388,7 @@
 
 static int pd_release(struct inode *inode, struct file *file)
 {
-	int unit = DEVICE_NR(inode->i_rdev);
-	struct pd_unit *disk = pd + unit;
+	struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
 
 	if (!--disk->access && disk->removable)
 		pd_doorlock(disk, IDE_DOORUNLOCK);
@@ -401,10 +396,10 @@
 	return 0;
 }
 
-static int pd_check_media(kdev_t dev)
+static int pd_check_media(struct gendisk *p)
 {
-	int r, unit = DEVICE_NR(dev);
-	struct pd_unit *disk = pd + unit;
+	struct pd_unit *disk = p->private_data;
+	int r;
 	if (!disk->removable)
 		return 0;
 	pd_media_check(disk);
@@ -413,14 +408,13 @@
 	return r;
 }
 
-static int pd_revalidate(kdev_t dev)
+static int pd_revalidate(struct gendisk *p)
 {
-	int unit = DEVICE_NR(dev);
-	struct pd_unit *disk = pd + unit;
+	struct pd_unit *disk = p->private_data;
 	if (pd_identify(disk))
-		set_capacity(disk->gd, disk->capacity);
+		set_capacity(p, disk->capacity);
 	else
-		set_capacity(disk->gd, 0);
+		set_capacity(p, 0);
 	return 0;
 }
 
@@ -665,6 +659,8 @@
 	return pd_identify(disk);
 }
 
+static struct request_queue pd_queue;
+
 static int pd_detect(void)
 {
 	int k, unit;
@@ -712,6 +708,8 @@
 			p->first_minor = unit << PD_BITS;
 			set_capacity(p, disk->capacity);
 			disk->gd = p;
+			p->private_data = disk;
+			p->queue = &pd_queue;
 			add_disk(p);
 		}
 	}
@@ -730,26 +728,18 @@
 
 static void do_pd_request(request_queue_t * q)
 {
-	int unit;
-
 	if (pd_busy)
 		return;
 repeat:
-	if (blk_queue_empty(QUEUE))
+	if (blk_queue_empty(q))
 		return;
 
-	pd_req = elv_next_request(QUEUE);
-	unit = DEVICE_NR(pd_req->rq_dev);
-	if (unit >= PD_UNITS) {
-		end_request(pd_req, 0);
-		goto repeat;
-	}
-
+	pd_req = elv_next_request(q);
 	pd_block = pd_req->sector;
 	pd_run = pd_req->nr_sectors;
 	pd_count = pd_req->current_nr_sectors;
-	pd_current = pd + unit;
-	if (pd_block + pd_count > get_capacity(pd_current->gd)) {
+	pd_current = pd_req->rq_disk->private_data;
+	if (pd_block + pd_count > get_capacity(pd_req->rq_disk)) {
 		end_request(pd_req, 0);
 		goto repeat;
 	}
@@ -797,7 +787,7 @@
 	spin_lock_irqsave(&pd_lock, saved_flags);
 	end_request(pd_req, success);
 	pd_busy = 0;
-	do_pd_request(NULL);
+	do_pd_request(&pd_queue);
 	spin_unlock_irqrestore(&pd_lock, saved_flags);
 }
 
@@ -903,16 +893,14 @@
 
 static int __init pd_init(void)
 {
-	request_queue_t *q;
 	if (disable)
 		return -1;
 	if (register_blkdev(MAJOR_NR, name, &pd_fops)) {
 		printk("%s: unable to get major number %d\n", name, major);
 		return -1;
 	}
-	q = BLK_DEFAULT_QUEUE(MAJOR_NR);
-	blk_init_queue(q, do_pd_request, &pd_lock);
-	blk_queue_max_sectors(q, cluster);
+	blk_init_queue(&pd_queue, do_pd_request, &pd_lock);
+	blk_queue_max_sectors(&pd_queue, cluster);
 
 	printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
 	       name, name, PD_VERSION, major, cluster, nice);
@@ -938,6 +926,7 @@
 			pi_release(disk->pi);
 		}
 	}
+	blk_cleanup_queue(&pd_queue);
 }
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
--- a/drivers/block/paride/pf.c	Fri Oct 18 21:03:06 2002
+++ b/drivers/block/paride/pf.c	Fri Oct 18 21:03:06 2002
@@ -191,7 +191,6 @@
 /* set up defines for blk.h,  why don't all drivers do it this way ? */
 
 #define MAJOR_NR   major
-#define DEVICE_NR(device) minor(device)
 
 #include <linux/blk.h>
 #include <linux/blkpg.h>
@@ -272,7 +271,7 @@
 static int pf_identify(struct pf_unit *pf);
 static void pf_lock(struct pf_unit *pf, int func);
 static void pf_eject(struct pf_unit *pf);
-static int pf_check_media(kdev_t dev);
+static int pf_check_media(struct gendisk *disk);
 
 static char pf_scratch[512];	/* scratch block buffer */
 
@@ -294,11 +293,11 @@
 /* kernel glue structures */
 
 static struct block_device_operations pf_fops = {
-	.owner			= THIS_MODULE,
-	.open			= pf_open,
-	.release		= pf_release,
-	.ioctl			= pf_ioctl,
-	.check_media_change	= pf_check_media,
+	.owner		= THIS_MODULE,
+	.open		= pf_open,
+	.release	= pf_release,
+	.ioctl		= pf_ioctl,
+	.media_changed	= pf_check_media,
 };
 
 void pf_init_units(void)
@@ -328,8 +327,7 @@
 
 static int pf_open(struct inode *inode, struct file *file)
 {
-	int unit = DEVICE_NR(inode->i_rdev);
-	struct pf_unit *pf = units + unit;
+	struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
 
 	pf_identify(pf);
 
@@ -348,10 +346,9 @@
 
 static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	int unit = DEVICE_NR(inode->i_rdev);
+	struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
 	struct hd_geometry *geo = (struct hd_geometry *) arg;
 	struct hd_geometry g;
-	struct pf_unit *pf = units + unit;
 	sector_t capacity;
 
 	if (cmd == CDROMEJECT) {
@@ -380,10 +377,9 @@
 
 static int pf_release(struct inode *inode, struct file *file)
 {
-	int unit = DEVICE_NR(inode->i_rdev);
-	struct pf_unit *pf = units + unit;
+	struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
 
-	if ((unit >= PF_UNITS) || (pf->access <= 0))
+	if (pf->access <= 0)
 		return -EINVAL;
 
 	pf->access--;
@@ -395,7 +391,7 @@
 
 }
 
-static int pf_check_media(kdev_t dev)
+static int pf_check_media(struct gendisk *disk)
 {
 	return 1;
 }
@@ -784,25 +780,23 @@
 	return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask));
 }
 
+static struct request_queue pf_queue;
+
 static void do_pf_request(request_queue_t * q)
 {
-	int unit;
-
 	if (pf_busy)
 		return;
-      repeat:
-	if (elv_queue_empty(QUEUE))
+repeat:
+	if (elv_queue_empty(q))
 		return;
 
-	pf_req = elv_next_request(QUEUE);
-	unit = DEVICE_NR(pf_req->rq_dev);
-	pf_current = units + unit;
+	pf_req = elv_next_request(q);
+	pf_current = pf_req->rq_disk->private_data;
 	pf_block = pf_req->sector;
 	pf_run = pf_req->nr_sectors;
 	pf_count = pf_req->current_nr_sectors;
 
-	if ((unit >= PF_UNITS) ||
-	    (pf_block + pf_count > get_capacity(pf_current->disk))) {
+	if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
 		end_request(pf_req, 0);
 		goto repeat;
 	}
@@ -849,7 +843,7 @@
 	spin_lock_irqsave(&pf_spin_lock, saved_flags);
 	end_request(pf_req, success);
 	pf_busy = 0;
-	do_pf_request(NULL);
+	do_pf_request(&pf_queue);
 	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
 }
 
@@ -960,7 +954,6 @@
 {				/* preliminary initialisation */
 	struct pf_unit *pf;
 	int unit;
-	request_queue_t *q;
 
 	if (disable)
 		return -1;
@@ -977,15 +970,16 @@
 			put_disk(pf->disk);
 		return -1;
 	}
-	q = BLK_DEFAULT_QUEUE(MAJOR_NR);
-	blk_init_queue(q, do_pf_request, &pf_spin_lock);
-	blk_queue_max_phys_segments(q, cluster);
-	blk_queue_max_hw_segments(q, cluster);
+	blk_init_queue(&pf_queue, do_pf_request, &pf_spin_lock);
+	blk_queue_max_phys_segments(&pf_queue, cluster);
+	blk_queue_max_hw_segments(&pf_queue, cluster);
 
 	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
 		struct gendisk *disk = pf->disk;
 		if (!pf->present)
 			continue;
+		disk->private_data = pf;
+		disk->queue = &pf_queue;
 		add_disk(disk);
 	}
 	return 0;
@@ -1003,6 +997,7 @@
 		put_disk(pf->disk);
 		pi_release(pf->pi);
 	}
+	blk_cleanup_queue(&pf_queue);
 }
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/block/rd.c	Fri Oct 18 21:03:05 2002
@@ -51,6 +51,7 @@
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/buffer_head.h>		/* for invalidate_bdev() */
+#include <linux/backing-dev.h>
 #include <asm/uaccess.h>
 
 /*
@@ -89,7 +90,7 @@
  */
 int rd_size = CONFIG_BLK_DEV_RAM_SIZE;		/* Size of the RAM disks */
 /*
- * It would be very desiderable to have a soft-blocksize (that in the case
+ * It would be very desirable to have a soft-blocksize (that in the case
  * of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because
  * doing that we'll achieve a far better MM footprint. Using a rd_blocksize of
  * BLOCK_SIZE in the worst case we'll make PAGE_SIZE/BLOCK_SIZE buffer-pages
@@ -351,6 +352,10 @@
 
 #endif
 
+static struct backing_dev_info rd_backing_dev_info = {
+	.ra_pages	= 0,	/* No readahead */
+	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+};
 
 static int rd_open(struct inode * inode, struct file * filp)
 {
@@ -379,6 +384,7 @@
 		rd_bdev[unit]->bd_openers++;
 		rd_bdev[unit]->bd_block_size = rd_blocksize;
 		rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops;
+		rd_bdev[unit]->bd_inode->i_mapping->backing_dev_info = &rd_backing_dev_info;
 		rd_bdev[unit]->bd_inode->i_size = rd_length[unit];
 		rd_bdev[unit]->bd_queue = &blk_dev[MAJOR_NR].request_queue;
 		rd_bdev[unit]->bd_disk = get_disk(rd_disks[unit]);
diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c
--- a/drivers/block/swim3.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/block/swim3.c	Fri Oct 18 21:03:04 2002
@@ -34,10 +34,11 @@
 
 #define MAJOR_NR	FLOPPY_MAJOR
 #define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&swim3_queue)
 #include <linux/blk.h>
 #include <linux/devfs_fs_kernel.h>
 
+static struct request_queue swim3_queue;
 static struct gendisk *disks[2];
 
 #define MAX_FLOPPIES	2
@@ -246,8 +247,8 @@
 			unsigned int cmd, unsigned long param);
 static int floppy_open(struct inode *inode, struct file *filp);
 static int floppy_release(struct inode *inode, struct file *filp);
-static int floppy_check_change(kdev_t dev);
-static int floppy_revalidate(kdev_t dev);
+static int floppy_check_change(struct gendisk *disk);
+static int floppy_revalidate(struct gendisk *disk);
 static int swim3_add_device(struct device_node *swims);
 int swim3_init(void);
 
@@ -819,18 +820,12 @@
 static int floppy_ioctl(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long param)
 {
-	struct floppy_state *fs;
+	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
 	int err;
-	int devnum = minor(inode->i_rdev);
-
-	if (devnum >= floppy_count)
-		return -ENODEV;
 		
 	if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	fs = &floppy_states[devnum];
-
 	if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
 		return -ENXIO;
 
@@ -851,19 +846,10 @@
 
 static int floppy_open(struct inode *inode, struct file *filp)
 {
-	struct floppy_state *fs;
-	volatile struct swim3 *sw;
-	int n, err;
-	int devnum = minor(inode->i_rdev);
+	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+	volatile struct swim3 *sw = fs->swim3;
+	int n, err = 0;
 
-	if (devnum >= floppy_count)
-		return -ENODEV;
-	if (filp == 0)
-		return -EIO;
-		
-	fs = &floppy_states[devnum];
-	sw = fs->swim3;
-	err = 0;
 	if (fs->ref_count == 0) {
 		if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
 			return -ENXIO;
@@ -926,15 +912,8 @@
 
 static int floppy_release(struct inode *inode, struct file *filp)
 {
-	struct floppy_state *fs;
-	volatile struct swim3 *sw;
-	int devnum = minor(inode->i_rdev);
-
-	if (devnum >= floppy_count)
-		return -ENODEV;
-
-	fs = &floppy_states[devnum];
-	sw = fs->swim3;
+	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+	volatile struct swim3 *sw = fs->swim3;
 	if (fs->ref_count > 0 && --fs->ref_count == 0) {
 		swim3_action(fs, MOTOR_OFF);
 		out_8(&sw->control_bic, 0xff);
@@ -942,29 +921,17 @@
 	return 0;
 }
 
-static int floppy_check_change(kdev_t dev)
+static int floppy_check_change(struct gendisk *disk)
 {
-	struct floppy_state *fs;
-	int devnum = minor(dev);
-
-	if (major(dev) != MAJOR_NR || (devnum >= floppy_count))
-		return 0;
-		
-	fs = &floppy_states[devnum];
+	struct floppy_state *fs = disk->private_data;
 	return fs->ejected;
 }
 
-static int floppy_revalidate(kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
 {
-	struct floppy_state *fs;
+	struct floppy_state *fs = disk->private_data;
 	volatile struct swim3 *sw;
 	int ret, n;
-	int devnum = minor(dev);
-
-	if (major(dev) != MAJOR_NR || (devnum >= floppy_count))
-		return 0;
-
-	fs = &floppy_states[devnum];
 
 	if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
 		return -ENXIO;
@@ -1002,11 +969,11 @@
 }
 
 static struct block_device_operations floppy_fops = {
-	open:			floppy_open,
-	release:		floppy_release,
-	ioctl:			floppy_ioctl,
-	check_media_change:	floppy_check_change,
-	revalidate:		floppy_revalidate,
+	.open		= floppy_open,
+	.release	= floppy_release,
+	.ioctl		= floppy_ioctl,
+	.media_changed	= floppy_check_change,
+	.revalidate_disk= floppy_revalidate,
 };
 
 static devfs_handle_t floppy_devfs_handle;
@@ -1047,12 +1014,14 @@
 		err = -EBUSY;
 		goto out;
 	}
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &swim3_lock);
+	blk_init_queue(&swim3_queue, do_fd_request, &swim3_lock);
 	for (i = 0; i < floppy_count; i++) {
 		struct gendisk *disk = disks[i];
 		disk->major = MAJOR_NR;
 		disk->first_minor = i;
 		disk->fops = &floppy_fops;
+		disk->private_data = &floppy_states[i];
+		disk->queue = &swim3_queue;
 		sprintf(disk->disk_name, "fd%d", i);
 		set_capacity(disk, 2880);
 		add_disk(disk);
diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
--- a/drivers/block/swim_iop.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/block/swim_iop.c	Fri Oct 18 21:03:03 2002
@@ -28,7 +28,7 @@
 
 #define MAJOR_NR  FLOPPY_MAJOR
 #define DEVICE_NAME "floppy"
-#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
+#define QUEUE (&swim_queue)
 
 #include <linux/stddef.h>
 #include <linux/kernel.h>
@@ -97,7 +97,7 @@
 
 int swimiop_init(void);
 static void swimiop_init_request(struct swim_iop_req *);
-static int swimiop_send_request(CURRENT, struct swim_iop_req *);
+static int swimiop_send_request(struct swim_iop_req *);
 static void swimiop_receive(struct iop_msg *, struct pt_regs *);
 static void swimiop_status_update(int, struct swim_drvstatus *);
 static int swimiop_eject(struct floppy_state *fs);
@@ -106,8 +106,8 @@
 			unsigned int cmd, unsigned long param);
 static int floppy_open(struct inode *inode, struct file *filp);
 static int floppy_release(struct inode *inode, struct file *filp);
-static int floppy_check_change(kdev_t dev);
-static int floppy_revalidate(kdev_t dev);
+static int floppy_check_change(struct gendisk *disk);
+static int floppy_revalidate(struct gendisk *disk);
 static int grab_drive(struct floppy_state *fs, enum swim_state state,
 		      int interruptible);
 static void release_drive(struct floppy_state *fs);
@@ -118,13 +118,14 @@
 static void start_request(struct floppy_state *fs);
 
 static struct block_device_operations floppy_fops = {
-	open:			floppy_open,
-	release:		floppy_release,
-	ioctl:			floppy_ioctl,
-	check_media_change:	floppy_check_change,
-	revalidate:		floppy_revalidate,
+	.open		= floppy_open,
+	.release	= floppy_release,
+	.ioctl		= floppy_ioctl,
+	.media_changed	= floppy_check_change,
+	.revalidate_disk= floppy_revalidate,
 };
 
+static struct request_queue swim_queue;
 /*
  * SWIM IOP initialization
  */
@@ -147,8 +148,7 @@
 		       MAJOR_NR);
 		return -EBUSY;
 	}
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request,
-			&swim_iop_lock);
+	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);
 
@@ -166,7 +166,7 @@
 		swimiop_init_request(&req);
 		cmd->code = CMD_STATUS;
 		cmd->drive_num = i + 1;
-		if (swimiop_send_request(CURRENT, &req) != 0) continue;
+		if (swimiop_send_request(&req) != 0) continue;
 		while (!req.complete);
 		if (cmd->error != 0) {
 			printk(KERN_ERR "SWIM-IOP: probe on drive %d returned error %d\n", i, (uint) cmd->error);
@@ -195,6 +195,8 @@
 		disk->first_minor = i;
 		disk->fops = &floppy_fops;
 		sprintf(disk->disk_name, "fd%d", i);
+		disk->private_data = &floppy_states[i];
+		disk->queue = &swim_queue;
 		set_capacity(disk, 2880 * 2);
 		add_disk(disk);
 	}
@@ -209,7 +211,7 @@
 	req->done = NULL;
 }
 
-static int swimiop_send_request(CURRENT, struct swim_iop_req *req)
+static int swimiop_send_request(struct swim_iop_req *req)
 {
 	unsigned long cpu_flags;
 	int err;
@@ -324,7 +326,7 @@
 	swimiop_init_request(&req);
 	cmd->code = CMD_EJECT;
 	cmd->drive_num = fs->drive_num;
-	err = swimiop_send_request(CURRENT, &req);
+	err = swimiop_send_request(&req);
 	if (err) {
 		release_drive(fs);
 		return err;
@@ -348,18 +350,12 @@
 static int floppy_ioctl(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long param)
 {
-	struct floppy_state *fs;
+	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
 	int err;
-	int devnum = MINOR(inode->i_rdev);
 
-	if (devnum >= floppy_count)
-		return -ENODEV;
-		
 	if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	fs = &floppy_states[devnum];
-
 	switch (cmd) {
 	case FDEJECT:
 		if (fs->ref_count != 1)
@@ -377,32 +373,19 @@
 
 static int floppy_open(struct inode *inode, struct file *filp)
 {
-	struct floppy_state *fs;
-	int err;
-	int devnum = MINOR(inode->i_rdev);
+	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
 
-	if (devnum >= floppy_count)
-		return -ENODEV;
-	if (filp == 0)
-		return -EIO;
-		
-	fs = &floppy_states[devnum];
-	err = 0;
-	if (fs->ref_count == -1 || filp->f_flags & O_EXCL) return -EBUSY;
+	if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
+		return -EBUSY;
 
-	if (err == 0 && (filp->f_flags & O_NDELAY) == 0
-	    && (filp->f_mode & 3)) {
+	if ((filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) {
 		check_disk_change(inode->i_bdev);
 		if (fs->ejected)
-			err = -ENXIO;
+			return -ENXIO;
 	}
 
-	if (err == 0 && (filp->f_mode & 2)) {
-		if (fs->write_prot)
-			err = -EROFS;
-	}
-
-	if (err) return err;
+	if ((filp->f_mode & 2) && fs->write_prot)
+		return -EROFS;
 
 	if (filp->f_flags & O_EXCL)
 		fs->ref_count = -1;
@@ -414,43 +397,24 @@
 
 static int floppy_release(struct inode *inode, struct file *filp)
 {
-	struct floppy_state *fs;
-	int devnum = MINOR(inode->i_rdev);
-
-	if (devnum >= floppy_count)
-		return -ENODEV;
-
-	fs = &floppy_states[devnum];
-	if (fs->ref_count > 0) fs->ref_count--;
+	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+	if (fs->ref_count > 0)
+		fs->ref_count--;
 	return 0;
 }
 
-static int floppy_check_change(kdev_t dev)
+static int floppy_check_change(struct gendisk *disk)
 {
-	struct floppy_state *fs;
-	int devnum = MINOR(dev);
-
-	if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
-		return 0;
-		
-	fs = &floppy_states[devnum];
+	struct floppy_state *fs = disk->private_data;
 	return fs->ejected;
 }
 
-static int floppy_revalidate(kdev_t dev)
+static int floppy_revalidate(struct gendisk *disk)
 {
-	struct floppy_state *fs;
-	int devnum = MINOR(dev);
-
-	if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
-		return 0;
-
-	fs = &floppy_states[devnum];
-
+	struct floppy_state *fs = disk->private_data;
 	grab_drive(fs, revalidating, 0);
 	/* yadda, yadda */
 	release_drive(fs);
-
 	return 0;
 }
 
@@ -604,7 +568,7 @@
 		cmd->first_block = CURRENT->sector;
 		cmd->num_blocks = CURRENT->current_nr_sectors;
 
-		if (swimiop_send_request(CURRENT, &req)) {
+		if (swimiop_send_request(&req)) {
 			end_request(CURRENT, 0);
 			continue;
 		}
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/block/umem.c	Fri Oct 18 21:03:08 2002
@@ -67,7 +67,6 @@
 #define MM_BLKSIZE 1024  /* 1k blocks */
 #define MM_HARDSECT 512  /* 512-byte hardware sectors */
 #define MM_SHIFT 6       /* max 64 partitions on 4 cards  */
-#define DEVICE_NR(device) (minor(device)>>MM_SHIFT)
 
 /*
  * Version Information
@@ -812,10 +811,10 @@
  *	That's crap, since doing that while some partitions are opened
  * or mounted will give you really nasty results.
  */
-static int mm_revalidate(kdev_t i_rdev)
+static int mm_revalidate(struct gendisk *disk)
 {
-	int card_number = DEVICE_NR(i_rdev);
-	set_capacity(mm_gendisk[card_number], cards[card_number].mm_size << 1);
+	struct cardinfo *card = disk->private_data;
+	set_capacity(disk, card->mm_size << 1);
 	return 0;
 }
 /*
@@ -826,17 +825,14 @@
 static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
 {
 	if (cmd == HDIO_GETGEO) {
-		unsigned int minor = minor(i->i_rdev);
-		int err, size, card_number = (minor >> MM_SHIFT);
+		struct cardinfo *card = i->i_bdev->bd_disk->private_data;
+		int size = card->mm_size * (1024 / MM_HARDSECT);
 		struct hd_geometry geo;
 		/*
 		 * get geometry: we have to fake one...  trim the size to a
 		 * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
 		 * whatever cylinders.
 		 */
-		err = ! access_ok(VERIFY_WRITE, arg, sizeof(geo));
-		if (err) return -EFAULT;
-		size = cards[card_number].mm_size * (1024 / MM_HARDSECT);
 		geo.heads     = 64;
 		geo.sectors   = 32;
 		geo.start     = get_start_sect(i->i_bdev);
@@ -855,13 +851,9 @@
 -----------------------------------------------------------------------------------
   Future support for removable devices
 */
-static int mm_check_change(kdev_t i_rdev)
+static int mm_check_change(struct gendisk *disk)
 {
-	int card_number = DEVICE_NR(i_rdev);
-/*  struct cardinfo *dev = cards + card_number; */
-	if (card_number >= num_cards) /* paranoid */
-		return 0;
-
+/*  struct cardinfo *dev = disk->private_data; */
 	return 0;
 }
 /*
@@ -870,10 +862,10 @@
 -----------------------------------------------------------------------------------
 */
 static struct block_device_operations mm_fops = {
-	owner:		THIS_MODULE,
-	ioctl:		mm_ioctl,
-	revalidate:	mm_revalidate,
-	check_media_change: mm_check_change,
+	.owner		= THIS_MODULE,
+	.ioctl		= mm_ioctl,
+	.revalidate_disk= mm_revalidate,
+	.media_changed	= mm_check_change,
 };
 /*
 -----------------------------------------------------------------------------------
@@ -1149,16 +1141,6 @@
 -----------------------------------------------------------------------------------
 */
 
-static request_queue_t * mm_queue_proc(kdev_t dev)
-{
-	int c = DEVICE_NR(dev);
-
-	if (c < MM_MAXCARDS)
-		return &cards[c].queue;
-	else
-		return BLK_DEFAULT_QUEUE(MAJOR_NR);
-}
-	
 int __init mm_init(void)
 {
 	int retval, i;
@@ -1183,7 +1165,6 @@
 	}
 	devfs_handle = devfs_mk_dir(NULL, "umem", NULL);
 
-	blk_dev[MAJOR_NR].queue = mm_queue_proc;
 	for (i = 0; i < num_cards; i++) {
 		struct gendisk *disk = mm_gendisk[i];
 		sprintf(disk->disk_name, "umem%c", 'a'+i);
@@ -1191,6 +1172,8 @@
 		disk->major = major_nr;
 		disk->first_minor  = i << MM_SHIFT;
 		disk->fops = &mm_fops;
+		disk->private_data = &cards[i];
+		disk->queue = &cards[i].queue;
 		set_capacity(disk, cards[i].mm_size << 1);
 		add_disk(disk);
 	}
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/block/xd.c	Fri Oct 18 21:03:08 2002
@@ -150,6 +150,7 @@
 static int __init xd_init(void)
 {
 	u_char i,controller;
+	u_char count = 0;
 	unsigned int address;
 	int err;
 
diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c
--- a/drivers/block/z2ram.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/block/z2ram.c	Fri Oct 18 21:03:05 2002
@@ -345,11 +345,10 @@
 	.release	= z2_release,
 };
 
-static struct gendisk *z2_find(int minor)
+static struct gendisk *z2_find(dev_t dev, int *part, void *data)
 {
-	if (minor > Z2MINOR_COUNT)
-		return NULL;
-	return z2ram_gendisk;
+	*part = 0;
+	return get_disk(z2ram_gendisk);
 }
 
 int __init 
@@ -377,7 +376,8 @@
 
     blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_z2_request, &z2ram_lock);
     add_disk(z2ram_gendisk);
-    blk_set_probe(MAJOR_NR, z2_find);
+    blk_register_region(MKDEV(MAJOR_NR, 0), Z2MINOR_COUNT, THIS_MODULE,
+				z2_find, NULL, NULL);
 
     return 0;
 }
@@ -404,8 +404,7 @@
 cleanup_module( void )
 {
     int i, j;
-
-    blk_set_probe(MAJOR_NR, NULL);
+    blk_unregister_region(MKDEV(MAJOR_NR, 0), 256);
     if ( unregister_blkdev( MAJOR_NR, DEVICE_NAME ) != 0 )
 	printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
 
diff -Nru a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
--- a/drivers/bluetooth/Makefile	Fri Oct 18 21:03:08 2002
+++ b/drivers/bluetooth/Makefile	Fri Oct 18 21:03:08 2002
@@ -2,7 +2,7 @@
 # Makefile for the Linux Bluetooth HCI device drivers.
 #
 
-obj-$(CONFIG_BT_HCIUSB)	+= hci_usb.o
+obj-$(CONFIG_BT_HCIUSB)		+= hci_usb.o
 obj-$(CONFIG_BT_HCIVHCI)	+= hci_vhci.o
 obj-$(CONFIG_BT_HCIUART)	+= hci_uart.o
 obj-$(CONFIG_BT_HCIDTL1)	+= dtl1_cs.o
diff -Nru a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
--- a/drivers/bluetooth/hci_h4.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/bluetooth/hci_h4.c	Fri Oct 18 21:03:04 2002
@@ -149,9 +149,9 @@
 {
 	struct h4_struct *h4 = hu->priv;
 	register char *ptr;
-	hci_event_hdr *eh;
-	hci_acl_hdr   *ah;
-	hci_sco_hdr   *sh;
+	struct hci_event_hdr *eh;
+	struct hci_acl_hdr   *ah;
+	struct hci_sco_hdr   *sh;
 	register int len, type, dlen;
 
 	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", 
@@ -180,7 +180,7 @@
 				continue;
 
 			case H4_W4_EVENT_HDR:
-				eh = (hci_event_hdr *) h4->rx_skb->data;
+				eh = (struct hci_event_hdr *) h4->rx_skb->data;
 
 				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
 
@@ -188,7 +188,7 @@
 				continue;
 
 			case H4_W4_ACL_HDR:
-				ah = (hci_acl_hdr *) h4->rx_skb->data;
+				ah = (struct hci_acl_hdr *) h4->rx_skb->data;
 				dlen = __le16_to_cpu(ah->dlen);
 
 				BT_DBG("ACL header: dlen %d", dlen);
@@ -197,7 +197,7 @@
 				continue;
 
 			case H4_W4_SCO_HDR:
-				sh = (hci_sco_hdr *) h4->rx_skb->data;
+				sh = (struct hci_sco_hdr *) h4->rx_skb->data;
 
 				BT_DBG("SCO header: dlen %d", sh->dlen);
 
diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
--- a/drivers/bluetooth/hci_usb.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/bluetooth/hci_usb.c	Fri Oct 18 21:03:08 2002
@@ -434,7 +434,7 @@
 	struct hci_usb *husb = (void *) urb->context;
 	struct hci_usb_scb *scb;
 	struct sk_buff *skb;
-	hci_event_hdr *eh;
+	struct hci_event_hdr *eh;
 	__u8 *data = urb->transfer_buffer;
 	int count = urb->actual_length;
 	int len = HCI_EVENT_HDR_SIZE;
@@ -459,7 +459,7 @@
 		if (count < HCI_EVENT_HDR_SIZE)
 			goto bad_len;
 
-		eh  = (hci_event_hdr *) data;
+		eh  = (struct hci_event_hdr *) data;
 		len = eh->plen + HCI_EVENT_HDR_SIZE;
 
 		if (count > len)
@@ -545,7 +545,7 @@
 	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
 	struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
 	int status, count = urb->actual_length;
-	hci_acl_hdr *ah;
+	struct hci_acl_hdr *ah;
 	int dlen, size;
 
 	BT_DBG("%s urb %p status %d count %d flags %x", husb->hdev.name, urb,
@@ -561,7 +561,7 @@
 
 	husb->hdev.stat.byte_rx += count;
 
-	ah   = (hci_acl_hdr *) skb->data;
+	ah   = (struct hci_acl_hdr *) skb->data;
 	dlen = __le16_to_cpu(ah->dlen);
 	size = HCI_ACL_HDR_SIZE + dlen;
 
diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/cdrom/aztcd.c	Fri Oct 18 21:03:08 2002
@@ -168,8 +168,7 @@
 #include <linux/version.h>
 
 #define MAJOR_NR AZTECH_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
-
+#define QUEUE (&azt_queue)
 #include <linux/blk.h>
 #include "aztcd.h"
 
@@ -227,10 +226,11 @@
 #define AZT_DEBUG_MULTISESSION
 #endif
 
+static struct request_queue azt_queue;
+
 static int current_valid(void)
 {
         return !blk_queue_empty(QUEUE) &&
-	        major(CURRENT->rq_dev) == MAJOR_NR &&
 		CURRENT->cmd == READ &&
 		CURRENT->sector != -1;
 }
@@ -329,18 +329,18 @@
 static int aztGetToc(int multi);
 
 /* Kernel Interface Functions */
-static int check_aztcd_media_change(kdev_t full_dev);
+static int check_aztcd_media_change(struct gendisk *disk);
 static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
 		       unsigned long arg);
 static int aztcd_open(struct inode *ip, struct file *fp);
 static int aztcd_release(struct inode *inode, struct file *file);
 
 static struct block_device_operations azt_fops = {
-	.owner			= THIS_MODULE,
-	.open			= aztcd_open,
-	.release		= aztcd_release,
-	.ioctl			= aztcd_ioctl,
-	.check_media_change	= check_aztcd_media_change,
+	.owner		= THIS_MODULE,
+	.open		= aztcd_open,
+	.release	= aztcd_release,
+	.ioctl		= aztcd_ioctl,
+	.media_changed	= check_aztcd_media_change,
 };
 
 /* Aztcd State Machine: Controls Drive Operating State */
@@ -790,7 +790,7 @@
 /*
  * Read the table of contents (TOC) and TOC header if necessary
  */
-static int aztUpdateToc()
+static int aztUpdateToc(void)
 {
 	int st;
 
@@ -1141,7 +1141,7 @@
 /* 
  * Checking if the media has been changed
 */
-static int check_aztcd_media_change(kdev_t full_dev)
+static int check_aztcd_media_change(struct gendisk *disk)
 {
 	if (aztDiskChanged) {	/* disk changed */
 		aztDiskChanged = 0;
@@ -1677,8 +1677,8 @@
 {
 #ifdef AZT_DEBUG
 	printk("aztcd: executing aztcd_release\n");
-	printk("inode: %p, inode->i_rdev: %x    file: %p\n", inode,
-	       inode->i_rdev, file);
+	printk("inode: %p, device: %s    file: %p\n", inode,
+	       inode->i_bdev->bd_disk->disk_name, file);
 #endif
 	if (!--azt_open_count) {
 		azt_invalidate_buffers();
@@ -1917,12 +1917,13 @@
 		ret = -EIO;
 		goto err_out3;
 	}
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin);
-	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
+	blk_init_queue(&azt_queue, do_aztcd_request, &aztSpin);
+	blk_queue_hardsect_size(&azt_queue, 2048);
 	azt_disk->major = MAJOR_NR;
 	azt_disk->first_minor = 0;
 	azt_disk->fops = &azt_fops;
 	sprintf(azt_disk->disk_name, "aztcd");
+	azt_disk->queue = &azt_queue;
 	add_disk(azt_disk);
 
 	azt_invalidate_buffers();
@@ -1952,7 +1953,7 @@
 		printk("What's that: can't unregister aztcd\n");
 		return;
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&azt_queue);
 	if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
 		SWITCH_IDE_MASTER;
 		release_region(azt_port, 8);	/*IDE-interface */
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/cdrom/cdrom.c	Fri Oct 18 21:03:03 2002
@@ -267,6 +267,7 @@
 #include <linux/blkpg.h>
 #include <linux/init.h>
 #include <linux/fcntl.h>
+#include <linux/blkdev.h>
 
 #include <asm/uaccess.h>
 
@@ -338,14 +339,11 @@
 int register_cdrom(struct cdrom_device_info *cdi)
 {
 	static char banner_printed;
-	int major = major(cdi->dev);
         struct cdrom_device_ops *cdo = cdi->ops;
         int *change_capability = (int *)&cdo->capability; /* hack */
 
 	cdinfo(CD_OPEN, "entering register_cdrom\n"); 
 
-	if (major < 0 || major >= MAX_BLKDEV)
-		return -1;
 	if (cdo->open == NULL || cdo->release == NULL)
 		return -2;
 	if ( !banner_printed ) {
@@ -389,16 +387,11 @@
 int unregister_cdrom(struct cdrom_device_info *unreg)
 {
 	struct cdrom_device_info *cdi, *prev;
-	int major = major(unreg->dev);
-
 	cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 
 
-	if (major < 0 || major >= MAX_BLKDEV)
-		return -1;
-
 	prev = NULL;
 	cdi = topCdromPtr;
-	while (cdi != NULL && !kdev_same(cdi->dev, unreg->dev)) {
+	while (cdi && cdi != unreg) {
 		prev = cdi;
 		cdi = cdi->next;
 	}
@@ -414,17 +407,6 @@
 	return 0;
 }
 
-static struct cdrom_device_info *cdrom_find_device(kdev_t dev)
-{
-	struct cdrom_device_info *cdi;
-
-	cdi = topCdromPtr;
-	while (cdi != NULL && !kdev_same(cdi->dev, dev))
-		cdi = cdi->next;
-
-	return cdi;
-}
-
 /* We use the open-option O_NONBLOCK to indicate that the
  * purpose of opening is only for subsequent ioctl() calls; no device
  * integrity checks are performed.
@@ -433,16 +415,11 @@
  * is in their own interest: device control becomes a lot easier
  * this way.
  */
-int cdrom_open(struct inode *ip, struct file *fp)
+int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
 {
-	struct cdrom_device_info *cdi;
-	kdev_t dev = ip->i_rdev;
 	int ret;
 
 	cdinfo(CD_OPEN, "entering cdrom_open\n"); 
-	if ((cdi = cdrom_find_device(dev)) == NULL)
-		return -ENODEV;
-
 	/* if this was a O_NONBLOCK open and we should honor the flags,
 	 * do a quick open without drive/disc integrity checks. */
 	if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS))
@@ -627,10 +604,8 @@
 
 
 /* Admittedly, the logic below could be performed in a nicer way. */
-int cdrom_release(struct inode *ip, struct file *fp)
+int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
 {
-	kdev_t dev = ip->i_rdev;
-	struct cdrom_device_info *cdi = cdrom_find_device(dev);
 	struct cdrom_device_ops *cdo = cdi->ops;
 	int opened_for_data;
 
@@ -843,9 +818,8 @@
 	return ret;
 }
 
-int cdrom_media_changed(kdev_t dev)
+int cdrom_media_changed(struct cdrom_device_info *cdi)
 {
-	struct cdrom_device_info *cdi = cdrom_find_device(dev);
 	/* This talks to the VFS, which doesn't like errors - just 1 or 0.  
 	 * Returning "0" is always safe (media hasn't been changed). Do that 
 	 * if the low-level cdrom driver dosn't support media changed. */ 
@@ -1457,14 +1431,17 @@
  * these days. ATAPI / SCSI specific code now mainly resides in
  * mmc_ioct().
  */
-int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-		       unsigned long arg)
+int cdrom_ioctl(struct cdrom_device_info *cdi, struct inode *ip,
+		unsigned int cmd, unsigned long arg)
 {
-	kdev_t dev = ip->i_rdev;
-	struct cdrom_device_info *cdi = cdrom_find_device(dev);
 	struct cdrom_device_ops *cdo = cdi->ops;
 	int ret;
 
+	/* Try the generic SCSI command ioctl's first.. */
+	ret = scsi_cmd_ioctl(ip->i_bdev, cmd, arg);
+	if (ret != -ENOTTY)
+		return ret;
+
 	/* the first few commands do not deal with audio drive_info, but
 	   only with routines in cdrom device operations. */
 	switch (cmd) {
@@ -1614,7 +1591,7 @@
 		cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
 		if (!CDROM_CAN(CDC_RESET))
 			return -ENOSYS;
-		invalidate_buffers(dev);
+		invalidate_bdev(ip->i_bdev, 0);
 		return cdo->reset(cdi);
 		}
 
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/cdrom/cdu31a.c	Fri Oct 18 21:03:03 2002
@@ -177,7 +177,6 @@
 #include "cdu31a.h"
 
 #define MAJOR_NR CDU31A_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
 #include <linux/blk.h>
 
 #define CDU31A_READAHEAD 4	/* 128 sector, 64kB, 32 reads read-ahead */
@@ -238,6 +237,7 @@
 static volatile unsigned short sony_cd_read_reg;
 static volatile unsigned short sony_cd_fifost_reg;
 
+static struct request_queue cdu31a_queue;
 static spinlock_t cdu31a_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
 
 static int sony_spun_up = 0;	/* Has the drive been spun up? */
@@ -1531,6 +1531,7 @@
  */
 static void do_cdu31a_request(request_queue_t * q)
 {
+	struct request *req;
 	int block;
 	int nblock;
 	unsigned char res_reg[12];
@@ -1578,125 +1579,111 @@
 	del_timer(&cdu31a_abort_timer);
 
 	while (1) {
-	      cdu31a_request_startover:
 		/*
 		 * The beginning here is stolen from the hard disk driver.  I hope
 		 * it's right.
 		 */
-		if (blk_queue_empty(QUEUE))
+		if (blk_queue_empty(q))
 			goto end_do_cdu31a_request;
 
-		if (!sony_spun_up) {
+		if (!sony_spun_up)
 			scd_spinup();
-		}
 
-		block = CURRENT->sector;
-		nblock = CURRENT->nr_sectors;
+		req = elv_next_request(q);
+		block = req->sector;
+		nblock = req->nr_sectors;
 
 		if (!sony_toc_read) {
 			printk("CDU31A: TOC not read\n");
-			end_request(CURRENT, 0);
-			goto cdu31a_request_startover;
+			end_request(req, 0);
+			continue;
 		}
 
-		if(CURRENT->flags & REQ_CMD) {
-			switch (rq_data_dir(CURRENT)) {
-			case READ:
-				/*
-				 * If the block address is invalid or the request goes beyond the end of
-				 * the media, return an error.
-				 */
-				if ((block / 4) >= sony_toc.lead_out_start_lba) {
-					printk
-						("CDU31A: Request past end of media\n");
-					end_request(CURRENT, 0);
-					goto cdu31a_request_startover;
-				}
-				if (((block + nblock) / 4) >=
-				    sony_toc.lead_out_start_lba) {
-					printk
-						("CDU31A: Request past end of media\n");
-					end_request(CURRENT, 0);
-					goto cdu31a_request_startover;
-				}
+		/* WTF??? */
+		if (!(req->flags & REQ_CMD))
+			continue;
+		if (rq_data_dir(req) == WRITE) {
+			end_request(req, 0);
+			continue;
+		}
+		if (rq_data_dir(req) != READ)
+			panic("CDU31A: Unknown cmd");
+		/*
+		 * If the block address is invalid or the request goes beyond the end of
+		 * the media, return an error.
+		 */
+		if ((block / 4) >= sony_toc.lead_out_start_lba) {
+			printk("CDU31A: Request past end of media\n");
+			end_request(req, 0);
+			continue;
+		}
+		if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
+			printk("CDU31A: Request past end of media\n");
+			end_request(req, 0);
+			continue;
+		}
 
-				num_retries = 0;
+		num_retries = 0;
 
-			try_read_again:
-				while (handle_sony_cd_attention());
+	try_read_again:
+		while (handle_sony_cd_attention());
 
-				if (!sony_toc_read) {
-					printk("CDU31A: TOC not read\n");
-					end_request(CURRENT, 0);
-					goto cdu31a_request_startover;
-				}
+		if (!sony_toc_read) {
+			printk("CDU31A: TOC not read\n");
+			end_request(req, 0);
+			continue;
+		}
 
-				/* If no data is left to be read from the drive, start the
-				   next request. */
-				if (sony_blocks_left == 0) {
-					if (start_request
-					    (block / 4, CDU31A_READAHEAD / 4, 0)) {
-						end_request(CURRENT, 0);
-						goto cdu31a_request_startover;
-					}
-				}
-				/* If the requested block is not the next one waiting in
-				   the driver, abort the current operation and start a
-				   new one. */
-				else if (block != sony_next_block) {
+		/* If no data is left to be read from the drive, start the
+		   next request. */
+		if (sony_blocks_left == 0) {
+			if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) {
+				end_request(req, 0);
+				continue;
+			}
+		}
+		/* If the requested block is not the next one waiting in
+		   the driver, abort the current operation and start a
+		   new one. */
+		else if (block != sony_next_block) {
 #if DEBUG
-					printk
-						("CDU31A Warning: Read for block %d, expected %d\n",
-						 block, sony_next_block);
+			printk("CDU31A Warning: Read for block %d, expected %d\n",
+				 block, sony_next_block);
 #endif
-					abort_read();
-					if (!sony_toc_read) {
-						printk("CDU31A: TOC not read\n");
-						end_request(CURRENT, 0);
-						goto cdu31a_request_startover;
-					}
-					if (start_request
-					    (block / 4, CDU31A_READAHEAD / 4, 0)) {
-						printk
-							("CDU31a: start request failed\n");
-						end_request(CURRENT, 0);
-						goto cdu31a_request_startover;
-					}
-				}
+			abort_read();
+			if (!sony_toc_read) {
+				printk("CDU31A: TOC not read\n");
+				end_request(req, 0);
+				continue;
+			}
+			if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) {
+				printk("CDU31a: start request failed\n");
+				end_request(req, 0);
+				continue;
+			}
+		}
 
-				read_data_block(CURRENT->buffer, block, nblock,
-						res_reg, &res_size);
-				if (res_reg[0] == 0x20) {
-					if (num_retries > MAX_CDU31A_RETRIES) {
-						end_request(CURRENT, 0);
-						goto cdu31a_request_startover;
-					}
+		read_data_block(req->buffer, block, nblock, res_reg, &res_size);
 
-					num_retries++;
-					if (res_reg[1] == SONY_NOT_SPIN_ERR) {
-						do_sony_cd_cmd(SONY_SPIN_UP_CMD,
-							       NULL, 0, res_reg,
-							       &res_size);
-					} else {
-						printk
-							("CDU31A: %s error for block %d, nblock %d\n",
-							 translate_error(res_reg[1]),
-							 block, nblock);
-					}
-					goto try_read_again;
-				} else {
-					end_request(CURRENT, 1);
-				}
-				break;
+		if (res_reg[0] != 0x20) {
+			end_request(req, 1);
+			continue;
+		}
 
-			case WRITE:
-				end_request(CURRENT, 0);
-				break;
+		if (num_retries > MAX_CDU31A_RETRIES) {
+			end_request(req, 0);
+			continue;
+		}
 
-			default:
-				panic("CDU31A: Unknown cmd");
-			}
+		num_retries++;
+		if (res_reg[1] == SONY_NOT_SPIN_ERR) {
+			do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
+					&res_size);
+		} else {
+			printk("CDU31A: %s error for block %d, nblock %d\n",
+				 translate_error(res_reg[1]), block, nblock);
 		}
+		goto try_read_again;
 	}
       end_do_cdu31a_request:
 	spin_lock_irq(q->queue_lock);
@@ -3151,15 +3138,6 @@
 	sony_usage--;
 }
 
-struct block_device_operations scd_bdops =
-{
-	.owner			= THIS_MODULE,
-	.open			= cdrom_open,
-	.release		= cdrom_release,
-	.ioctl			= cdrom_ioctl,
-	.check_media_change	= cdrom_media_changed,
-};
-
 static struct cdrom_device_ops scd_dops = {
 	.open			= scd_open,
 	.release		= scd_release,
@@ -3188,6 +3166,36 @@
 	.name		= "cdu31a"
 };
 
+static int scd_block_open(struct inode *inode, struct file *file)
+{
+	return cdrom_open(&scd_info, inode, file);
+}
+
+static int scd_block_release(struct inode *inode, struct file *file)
+{
+	return cdrom_release(&scd_info, file);
+}
+
+static int scd_block_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	return cdrom_ioctl(&scd_info, inode, cmd, arg);
+}
+
+static int scd_block_media_changed(struct gendisk *disk)
+{
+	return cdrom_media_changed(&scd_info);
+}
+
+struct block_device_operations scd_bdops =
+{
+	.owner		= THIS_MODULE,
+	.open		= scd_block_open,
+	.release	= scd_block_release,
+	.ioctl		= scd_block_ioctl,
+	.media_changed	= scd_block_media_changed,
+};
+
 static struct gendisk *scd_gendisk;
 
 /* The different types of disc loading mechanisms supported */
@@ -3430,18 +3438,16 @@
 	is_a_cdu31a =
 	    strcmp("CD-ROM CDU31A", drive_config.product_id) == 0;
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR),
-		       do_cdu31a_request,
-		       &cdu31a_lock);
+	blk_init_queue(&cdu31a_queue, do_cdu31a_request, &cdu31a_lock);
 
 	init_timer(&cdu31a_abort_timer);
 	cdu31a_abort_timer.function = handle_abort_timeout;
 
-	scd_info.dev = mk_kdev(MAJOR_NR, 0);
 	scd_info.mask = deficiency;
 	scd_gendisk = disk;
 	if (register_cdrom(&scd_info))
 		goto errout0;
+	disk->queue = &cdu31a_queue;
 	add_disk(disk);
 
 	disk_changed = 1;
@@ -3449,7 +3455,7 @@
 
 errout0:
 	printk("Unable to register CDU-31a with Uniform cdrom driver\n");
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&cdu31a_queue);
 	put_disk(disk);
 errout1:
 	if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
@@ -3476,7 +3482,7 @@
 		return;
 	}
 
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&cdu31a_queue);
 
 	if (cdu31a_irq > 0)
 		free_irq(cdu31a_irq, NULL);
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/cdrom/cm206.c	Fri Oct 18 21:03:08 2002
@@ -198,7 +198,6 @@
 #include <asm/io.h>
 
 #define MAJOR_NR CM206_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
 
 #include <linux/blk.h>
 
@@ -302,6 +301,7 @@
 #define PLAY_TO cd->toc[0]	/* toc[0] records end-time in play */
 
 static struct cm206_struct *cd;	/* the main memory structure */
+static struct request_queue cm206_queue;
 static spinlock_t cm206_lock = SPIN_LOCK_UNLOCKED;
 
 /* First, we define some polling functions. These are actually
@@ -770,15 +770,6 @@
 	}
 }
 
-struct block_device_operations cm206_bdops =
-{
-	.owner			= THIS_MODULE,
-	.open			= cdrom_open,
-	.release		= cdrom_release,
-	.ioctl			= cdrom_ioctl,
-	.check_media_change	= cdrom_media_changed,
-};
-
 /* The new open. The real opening strategy is defined in cdrom.c. */
 
 static int cm206_open(struct cdrom_device_info *cdi, int purpose)
@@ -860,24 +851,25 @@
 	long int i, cd_sec_no;
 	int quarter, error;
 	uch *source, *dest;
+	struct request *req;
 
-	while (1) {		/* repeat until all requests have been satisfied */
-		if (blk_queue_empty(QUEUE))
+	while (1) {	/* repeat until all requests have been satisfied */
+		if (blk_queue_empty(q))
 			return;
 
-		if (CURRENT->cmd != READ) {
-			debug(("Non-read command %d on cdrom\n",
-			       CURRENT->cmd));
-			end_request(CURRENT, 0);
+		req = elv_next_request(q);
+		if (req->cmd != READ) {
+			debug(("Non-read command %d on cdrom\n", req->cmd));
+			end_request(req, 0);
 			continue;
 		}
 		spin_unlock_irq(q->queue_lock);
 		error = 0;
-		for (i = 0; i < CURRENT->nr_sectors; i++) {
+		for (i = 0; i < req->nr_sectors; i++) {
 			int e1, e2;
-			cd_sec_no = (CURRENT->sector + i) / BLOCKS_ISO;	/* 4 times 512 bytes */
-			quarter = (CURRENT->sector + i) % BLOCKS_ISO;
-			dest = CURRENT->buffer + i * LINUX_BLOCK_SIZE;
+			cd_sec_no = (req->sector + i) / BLOCKS_ISO;	/* 4 times 512 bytes */
+			quarter = (req->sector + i) % BLOCKS_ISO;
+			dest = req->buffer + i * LINUX_BLOCK_SIZE;
 			/* is already in buffer memory? */
 			if (cd->sector_first <= cd_sec_no
 			    && cd_sec_no < cd->sector_last) {
@@ -899,7 +891,7 @@
 			}
 		}
 		spin_lock_irq(q->queue_lock);
-		end_request(CURRENT, !error);
+		end_request(req, !error);
 	}
 }
 
@@ -1357,6 +1349,36 @@
 	.name		= "cm206",
 };
 
+static int cm206_block_open(struct inode *inode, struct file *file)
+{
+	return cdrom_open(&cm206_info, inode, file);
+}
+
+static int cm206_block_release(struct inode *inode, struct file *file)
+{
+	return cdrom_release(&cm206_info, file);
+}
+
+static int cm206_block_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	return cdrom_ioctl(&cm206_info, inode, cmd, arg);
+}
+
+static int cm206_block_media_changed(struct gendisk *disk)
+{
+	return cdrom_media_changed(&cm206_info);
+}
+
+static struct block_device_operations cm206_bdops =
+{
+	.owner		= THIS_MODULE,
+	.open		= cm206_block_open,
+	.release	= cm206_block_release,
+	.ioctl		= cm206_block_ioctl,
+	.media_changed	= cm206_block_media_changed,
+};
+
 static struct gendisk *cm206_gendisk;
 
 /* This function probes for the adapter card. It returns the base
@@ -1479,15 +1501,14 @@
 	disk->fops = &cm206_bdops;
 	disk->flags = GENHD_FL_CD;
 	cm206_gendisk = disk;
-	cm206_info.dev = mk_kdev(MAJOR_NR, 0);
 	if (register_cdrom(&cm206_info) != 0) {
 		printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
 		goto out_cdrom;
 	}
+	blk_init_queue(&cm206_queue, do_cm206_request, &cm206_lock);
+	blk_queue_hardsect_size(&cm206_queue, 2048);
+	disk->queue = &cm206_queue;
 	add_disk(disk);
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cm206_request,
-		       &cm206_lock);
-	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
 
 	memset(cd, 0, sizeof(*cd));	/* give'm some reasonable value */
 	cd->sector_last = -1;	/* flag no data buffered */
@@ -1550,7 +1571,7 @@
 		printk("Can't unregister major cm206\n");
 		return;
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&cm206_queue);
 	free_irq(cm206_irq, NULL);
 	kfree(cd);
 	release_region(cm206_base, 16);
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/cdrom/gscd.c	Fri Oct 18 21:03:03 2002
@@ -70,7 +70,6 @@
 #include <asm/uaccess.h>
 
 #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
 #include <linux/blk.h>
 #define gscd_port gscd		/* for compatible parameter passing with "insmod" */
 #include "gscd.h"
@@ -86,7 +85,7 @@
  *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
  */
 
-static void gscd_read_cmd(void);
+static void gscd_read_cmd(struct request *req);
 static void gscd_hsg2msf(long hsg, struct msf *msf);
 static void gscd_bin2bcd(unsigned char *p);
 
@@ -97,7 +96,7 @@
 		      unsigned long);
 static int gscd_open(struct inode *, struct file *);
 static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(kdev_t);
+static int check_gscd_med_chg(struct gendisk *disk);
 
 /*      GoldStar Funktionen    */
 
@@ -151,35 +150,25 @@
 
 static struct timer_list gscd_timer;
 static spinlock_t gscd_lock = SPIN_LOCK_UNLOCKED;
+struct request_queue gscd_queue;
 
 static struct block_device_operations gscd_fops = {
-	.owner			= THIS_MODULE,
-	.open			= gscd_open,
-	.release		= gscd_release,
-	.ioctl			= gscd_ioctl,
-	.check_media_change	= check_gscd_med_chg,
+	.owner		= THIS_MODULE,
+	.open		= gscd_open,
+	.release	= gscd_release,
+	.ioctl		= gscd_ioctl,
+	.media_changed	= check_gscd_med_chg,
 };
 
 /* 
  * Checking if the media has been changed
  * (not yet implemented)
  */
-static int check_gscd_med_chg(kdev_t full_dev)
+static int check_gscd_med_chg(struct gendisk *disk)
 {
-	int target;
-
-
-	target = minor(full_dev);
-
-	if (target > 0) {
-		printk
-		    ("GSCD: GoldStar CD-ROM request error: invalid device.\n");
-		return 0;
-	}
 #ifdef GSCD_DEBUG
 	printk("gscd: check_med_change\n");
 #endif
-
 	return 0;
 }
 
@@ -240,16 +229,14 @@
  * When Linux gets variable block sizes this will probably go away.
  */
 
-static void gscd_transfer(void)
+static void gscd_transfer(struct request *req)
 {
-	long offs;
-
-	while (CURRENT->nr_sectors > 0 && gscd_bn == CURRENT->sector / 4) {
-		offs = (CURRENT->sector & 3) * 512;
-		memcpy(CURRENT->buffer, gscd_buf + offs, 512);
-		CURRENT->nr_sectors--;
-		CURRENT->sector++;
-		CURRENT->buffer += 512;
+	while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
+		long offs = (req->sector & 3) * 512;
+		memcpy(req->buffer, gscd_buf + offs, 512);
+		req->nr_sectors--;
+		req->sector++;
+		req->buffer += 512;
 	}
 }
 
@@ -265,46 +252,40 @@
 
 static void __do_gscd_request(unsigned long dummy)
 {
-	unsigned int block, dev;
+	struct request *req;
+	unsigned int block;
 	unsigned int nsect;
 
-      repeat:
-	if (blk_queue_empty(QUEUE))
+repeat:
+	if (blk_queue_empty(&gscd_queue))
 		return;
 
-	dev = minor(CURRENT->rq_dev);
-	block = CURRENT->sector;
-	nsect = CURRENT->nr_sectors;
+	req = elv_next_request(&gscd_queue);
+	block = req->sector;
+	nsect = req->nr_sectors;
 
-	if (CURRENT->sector == -1)
+	if (req->sector == -1)
 		goto out;
 
-	if (CURRENT->cmd != READ) {
-		printk("GSCD: bad cmd %p\n", CURRENT->cmd);
-		end_request(CURRENT, 0);
+	if (req->cmd != READ) {
+		printk("GSCD: bad cmd %d\n", req->cmd);
+		end_request(req, 0);
 		goto repeat;
 	}
 
-	if (dev != 0) {
-		printk("GSCD: this version supports only one device\n");
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-
-	gscd_transfer();
+	gscd_transfer(req);
 
 	/* if we satisfied the request from the buffer, we're done. */
 
-	if (CURRENT->nr_sectors == 0) {
-		end_request(CURRENT, 1);
+	if (req->nr_sectors == 0) {
+		end_request(req, 1);
 		goto repeat;
 	}
 #ifdef GSCD_DEBUG
-	printk("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect);
+	printk("GSCD: block %d, nsect %d\n", block, nsect);
 #endif
-
-	gscd_read_cmd();
-      out:
+	gscd_read_cmd(req);
+out:
 	return;
 }
 
@@ -315,25 +296,23 @@
  * read-data command.
  */
 
-static void gscd_read_cmd(void)
+static void gscd_read_cmd(struct request *req)
 {
 	long block;
 	struct gscd_Play_msf gscdcmd;
 	char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 };	/* cmd mode M-S-F secth sectl */
 
-
-
 	cmd_status();
 	if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
 		printk("GSCD: no disk or door open\n");
-		end_request(CURRENT, 0);
+		end_request(req, 0);
 	} else {
 		if (disk_state & ST_INVALID) {
 			printk("GSCD: disk invalid\n");
-			end_request(CURRENT, 0);
+			end_request(req, 0);
 		} else {
 			gscd_bn = -1;	/* purge our buffer */
-			block = CURRENT->sector / 4;
+			block = req->sector / 4;
 			gscd_hsg2msf(block, &gscdcmd.start);	/* cvt to msf format */
 
 			cmd[2] = gscdcmd.start.min;
@@ -347,9 +326,9 @@
 			cmd_out(TYPE_DATA, (char *) &cmd,
 				(char *) &gscd_buf[0], 1);
 
-			gscd_bn = CURRENT->sector / 4;
-			gscd_transfer();
-			end_request(CURRENT, 1);
+			gscd_bn = req->sector / 4;
+			gscd_transfer(req);
+			end_request(req, 1);
 		}
 	}
 	SET_TIMER(__do_gscd_request, 1);
@@ -911,7 +890,7 @@
 		printk("What's that: can't unregister GoldStar-module\n");
 		return;
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&gscd_queue);
 	release_region(gscd_port, GSCD_IO_EXTENT);
 	printk(KERN_INFO "GoldStar-module released.\n");
 }
@@ -989,11 +968,12 @@
 	devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 		       S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_gscd_request, &gscd_lock);
+	blk_init_queue(&gscd_queue, do_gscd_request, &gscd_lock);
 
 	disk_state = 0;
 	gscdPresent = 1;
 
+	gscd_disk->queue = &gscd_queue;
 	add_disk(gscd_disk);
 
 	printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/cdrom/mcd.c	Fri Oct 18 21:03:05 2002
@@ -102,7 +102,7 @@
 #include <asm/uaccess.h>
 
 #define MAJOR_NR MITSUMI_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
+#define QUEUE (&mcd_queue)
 #include <linux/blk.h>
 
 #define mcd_port mcd		/* for compatible parameter passing with "insmod" */
@@ -116,6 +116,7 @@
 
 /* Is the drive connected properly and responding?? */
 static int mcdPresent;
+static struct request_queue mcd_queue;
 
 #define QUICK_LOOP_DELAY udelay(45)	/* use udelay */
 #define QUICK_LOOP_COUNT 20
@@ -123,7 +124,6 @@
 static int current_valid(void)
 {
         return !blk_queue_empty(QUEUE) &&
-	        major(CURRENT->rq_dev) == MAJOR_NR &&
 		CURRENT->cmd == READ &&
 		CURRENT->sector != -1;
 }
@@ -188,18 +188,9 @@
 static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr);
 static int mcd_tray_move(struct cdrom_device_info *cdi, int position);
 static spinlock_t mcd_spinlock = SPIN_LOCK_UNLOCKED;
-int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+static int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
 		    void *arg);
-int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
-
-struct block_device_operations mcd_bdops =
-{
-	.owner			= THIS_MODULE,
-	.open			= cdrom_open,
-	.release		= cdrom_release,
-	.ioctl			= cdrom_ioctl,
-	.check_media_change	= cdrom_media_changed,
-};
+static int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
 
 static struct timer_list mcd_timer;
 
@@ -221,6 +212,36 @@
 	.name		= "mcd",
 };
 
+static int mcd_block_open(struct inode *inode, struct file *file)
+{
+	return cdrom_open(&mcd_info, inode, file);
+}
+
+static int mcd_block_release(struct inode *inode, struct file *file)
+{
+	return cdrom_release(&mcd_info, file);
+}
+
+static int mcd_block_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	return cdrom_ioctl(&mcd_info, inode, cmd, arg);
+}
+
+static int mcd_block_media_changed(struct gendisk *disk)
+{
+	return cdrom_media_changed(&mcd_info);
+}
+
+static struct block_device_operations mcd_bdops =
+{
+	.owner		= THIS_MODULE,
+	.open		= mcd_block_open,
+	.release	= mcd_block_release,
+	.ioctl		= mcd_block_ioctl,
+	.media_changed	= mcd_block_media_changed,
+};
+
 static struct gendisk *mcd_gendisk;
 
 #ifndef MODULE
@@ -1055,8 +1076,7 @@
 		goto out_region;
 	}
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mcd_request,
-		       &mcd_spinlock);
+	blk_init_queue(&mcd_queue, do_mcd_request, &mcd_spinlock);
 
 	/* check for card */
 
@@ -1128,12 +1148,12 @@
 	disk->fops = &mcd_bdops;
 	disk->flags = GENHD_FL_CD;
 	mcd_gendisk = disk;
-	mcd_info.dev = mk_kdev(MAJOR_NR, 0);
 
 	if (register_cdrom(&mcd_info) != 0) {
 		printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n");
 		goto out_cdrom;
 	}
+	disk->queue = &mcd_queue;
 	add_disk(disk);
 	printk(msg);
 	return 0;
@@ -1144,7 +1164,7 @@
 	release_region(mcd_port, 4);
 out_region:
 	unregister_blkdev(MAJOR_NR, "mcd");
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&mcd_queue);
 	put_disk(disk);
 	return -EIO;
 }
@@ -1523,7 +1543,7 @@
 		printk(KERN_WARNING "Can't unregister major mcd\n");
 		return;
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&mcd_queue);
 	del_timer_sync(&mcd_timer);
 }
 
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/cdrom/mcdx.c	Fri Oct 18 21:03:04 2002
@@ -220,13 +220,38 @@
 int mcdx_init(void);
 void do_mcdx_request(request_queue_t * q);
 
-struct block_device_operations mcdx_bdops =
+static int mcdx_block_open(struct inode *inode, struct file *file)
 {
-	owner:			THIS_MODULE,
-	open:			cdrom_open,
-	release:		cdrom_release,
-	ioctl:			cdrom_ioctl,
-	check_media_change:	cdrom_media_changed,
+	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+	return cdrom_open(&p->info, inode, file);
+}
+
+static int mcdx_block_release(struct inode *inode, struct file *file)
+{
+	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+	return cdrom_release(&p->info, file);
+}
+
+static int mcdx_block_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+	return cdrom_ioctl(&p->info, inode, cmd, arg);
+}
+
+static int mcdx_block_media_changed(struct gendisk *disk)
+{
+	struct s_drive_stuff *p = disk->private_data;
+	return cdrom_media_changed(&p->info);
+}
+
+static struct block_device_operations mcdx_bdops =
+{
+	.owner		= THIS_MODULE,
+	.open		= mcdx_block_open,
+	.release	= mcdx_block_release,
+	.ioctl		= mcdx_block_ioctl,
+	.media_changed	= mcdx_block_media_changed,
 };
 
 
@@ -292,6 +317,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0
 };
 static spinlock_t mcdx_lock = SPIN_LOCK_UNLOCKED;
+static struct request_queue mcdx_queue;
 MODULE_PARM(mcdx, "1-4i");
 
 static struct cdrom_device_ops mcdx_dops = {
@@ -550,66 +576,63 @@
 
 void do_mcdx_request(request_queue_t * q)
 {
-	int dev;
 	struct s_drive_stuff *stuffp;
+	struct request *req;
 
       again:
 
-	if (blk_queue_empty(QUEUE))
+	if (blk_queue_empty(q))
 		return;
 
-	dev = minor(CURRENT->rq_dev);
-	stuffp = mcdx_stuffp[dev];
+	req = elv_next_request(q);
+	stuffp = req->rq_disk->private_data;
 
-	if ((dev < 0)
-	    || (dev >= MCDX_NDRIVES)
-	    || !stuffp || (!stuffp->present)) {
-		xwarn("do_request(): bad device: %s\n",
-		      kdevname(CURRENT->rq_dev));
+	if (!stuffp->present) {
+		xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
 		xtrace(REQUEST, "end_request(0): bad device\n");
-		end_request(CURRENT, 0);
+		end_request(req, 0);
 		return;
 	}
 
 	if (stuffp->audio) {
 		xwarn("do_request() attempt to read from audio cd\n");
 		xtrace(REQUEST, "end_request(0): read from audio\n");
-		end_request(CURRENT, 0);
+		end_request(req, 0);
 		return;
 	}
 
 	xtrace(REQUEST, "do_request() (%lu + %lu)\n",
-	       CURRENT->sector, CURRENT->nr_sectors);
+	       req->sector, req->nr_sectors);
 
-	if (CURRENT->cmd != READ) {
+	if (req->cmd != READ) {
 		xwarn("do_request(): non-read command to cd!!\n");
 		xtrace(REQUEST, "end_request(0): write\n");
-		end_request(CURRENT, 0);
+		end_request(req, 0);
 		return;
 	}
 	else {
 		stuffp->status = 0;
-		while (CURRENT->nr_sectors) {
+		while (req->nr_sectors) {
 			int i;
 
 			i = mcdx_transfer(stuffp,
-					  CURRENT->buffer,
-					  CURRENT->sector,
-					  CURRENT->nr_sectors);
+					  req->buffer,
+					  req->sector,
+					  req->nr_sectors);
 
 			if (i == -1) {
-				end_request(CURRENT, 0);
+				end_request(req, 0);
 				goto again;
 			}
-			CURRENT->sector += i;
-			CURRENT->nr_sectors -= i;
-			CURRENT->buffer += (i * 512);
+			req->sector += i;
+			req->nr_sectors -= i;
+			req->buffer += (i * 512);
 		}
-		end_request(CURRENT, 1);
+		end_request(req, 1);
 		goto again;
 
 		xtrace(REQUEST, "end_request(1)\n");
-		end_request(CURRENT, 1);
+		end_request(req, 1);
 	}
 
 	goto again;
@@ -1041,10 +1064,10 @@
 		kfree(stuffp);
 	}
 
-	if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
+	if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
 		xwarn("cleanup() unregister_blkdev() failed\n");
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&mcdx_queue);
 #if !MCDX_QUIET
 	else
 	xinfo("cleanup() succeeded\n");
@@ -1179,8 +1202,7 @@
 		return 1;
 	}
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mcdx_request,
-		       &mcdx_lock);
+	blk_init_queue(&mcdx_queue, do_mcdx_request, &mcdx_lock);
 
 	xtrace(INIT, "init() subscribe irq and i/o\n");
 	mcdx_irq_map[stuffp->irq] = stuffp;
@@ -1190,7 +1212,7 @@
 		xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
 		      MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
 		stuffp->irq = 0;
-		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+		blk_cleanup_queue(&mcdx_queue);
 		kfree(stuffp);
 		put_disk(disk);
 		return 0;
@@ -1218,7 +1240,6 @@
 	stuffp->info.capacity = 1;
 	stuffp->info.handle = stuffp;
 	sprintf(stuffp->info.name, "mcdx%d", drive);
-	stuffp->info.dev = mk_kdev(MAJOR_NR, drive);
 	disk->major = MAJOR_NR;
 	disk->first_minor = drive;
 	strcpy(disk->disk_name, stuffp->info.name);
@@ -1240,9 +1261,11 @@
 		put_disk(disk);
 		if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
 			xwarn("cleanup() unregister_blkdev() failed\n");
-		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+		blk_cleanup_queue(&mcdx_queue);
 		return 2;
 	}
+	disk->private_data = stuffp;
+	disk->queue = &mcdx_queue;
 	add_disk(disk);
 	printk(msg);
 	return 0;
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/cdrom/optcd.c	Fri Oct 18 21:03:03 2002
@@ -76,7 +76,7 @@
 #include <asm/io.h>
 
 #define MAJOR_NR OPTICS_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
+#define QUEUE (&opt_queue)
 #include <linux/blk.h>
 
 #include <linux/cdrom.h>
@@ -265,8 +265,8 @@
 static DECLARE_WAIT_QUEUE_HEAD(waitq);
 static void sleep_timer(unsigned long data);
 static struct timer_list delay_timer = {function: sleep_timer};
-spinlock_t optcd_lock = SPIN_LOCK_UNLOCKED;
-
+static spinlock_t optcd_lock = SPIN_LOCK_UNLOCKED;
+static struct request_queue opt_queue;
 
 /* Timer routine: wake up when desired flag goes low,
    or when timeout expires. */
@@ -977,7 +977,6 @@
 static int current_valid(void)
 {
         return !blk_queue_empty(QUEUE) &&
-	        major(CURRENT->rq_dev) == MAJOR_NR &&
 		CURRENT->cmd == READ &&
 		CURRENT->sector != -1;
 }
@@ -1896,8 +1895,8 @@
 	int status;
 
 	DEBUG((DEBUG_VFS, "executing opt_release"));
-	DEBUG((DEBUG_VFS, "inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
-		ip, ip -> i_rdev, fp));
+	DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
+		ip, ip->i_bdev->bd_disk->disk_name, fp));
 
 	if (!--open_count) {
 		toc_uptodate = 0;
@@ -1918,10 +1917,11 @@
 
 
 /* Check if disk has been changed */
-static int opt_media_change(kdev_t dev)
+static int opt_media_change(struct gendisk *disk)
 {
 	DEBUG((DEBUG_VFS, "executing opt_media_change"));
-	DEBUG((DEBUG_VFS, "dev: 0x%x; disk_changed = %d\n", dev, disk_changed));
+	DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
+			disk->disk_name, disk_changed));
 
 	if (disk_changed) {
 		disk_changed = 0;
@@ -1973,11 +1973,11 @@
 
 
 static struct block_device_operations opt_fops = {
-	.owner			= THIS_MODULE,
-	.open			= opt_open,
-	.release		= opt_release,
-	.ioctl			= opt_ioctl,
-	.check_media_change	= opt_media_change,
+	.owner		= THIS_MODULE,
+	.open		= opt_open,
+	.release	= opt_release,
+	.ioctl		= opt_ioctl,
+	.media_changed	= opt_media_change,
 };
 
 #ifndef MODULE
@@ -2054,9 +2054,9 @@
 	}
 	devfs_register (NULL, "optcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 			S_IFBLK | S_IRUGO | S_IWUGO, &opt_fops, NULL);
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_optcd_request,
-		       &optcd_lock);
-	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
+	blk_init_queue(&opt_queue, do_optcd_request, &optcd_lock);
+	blk_queue_hardsect_size(&opt_queue, 2048);
+	optcd_disk->queue = &opt_queue;
 	add_disk(optcd_disk);
 
 	printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
@@ -2073,7 +2073,7 @@
 		printk(KERN_ERR "optcd: what's that: can't unregister\n");
 		return;
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&opt_queue);
 	release_region(optcd_port, 4);
 	printk(KERN_INFO "optcd: module released.\n");
 }
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/cdrom/sbpcd.c	Fri Oct 18 21:03:03 2002
@@ -354,6 +354,13 @@
  * Marcin Dalecki
  */
 
+/*
+ * Add bio/kdev_t changes for 2.5.x required to make it work again. 
+ * Still room for improvement in the request handling here if anyone
+ * actually cares.  Bring your own chainsaw.    Paul G.  02/2002
+ */
+
+
 #include <linux/module.h>
 
 #include <linux/version.h>
@@ -456,6 +463,7 @@
  * Protects access to global structures etc.
  */
 static spinlock_t sbpcd_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+static struct request_queue sbpcd_queue;
 
 MODULE_PARM(sbpcd, "2i");
 MODULE_PARM(max_drives, "i");
@@ -4841,7 +4849,7 @@
 #ifdef DEBUG_GTL
 	xnr=++xx_nr;
 
-	if(blk_queue_empty(QUEUE))
+	if(blk_queue_empty(q))
 	{
 		printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
 			xnr, current->pid, jiffies);
@@ -4850,32 +4858,26 @@
 		return;
 	}
 
+	req = elv_next_request(q);
+
 	printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
-		xnr, CURRENT, CURRENT->sector, CURRENT->nr_sectors, current->pid, jiffies);
+		xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
 #endif
-
-	if (blk_queue_empty(QUEUE))
+	if (blk_queue_empty(q))
 		return;
 
-	req = CURRENT;		/* take out our request so no other */
-	blkdev_dequeue_request(req);	/* task can fuck it up         GTL  */
-
+	req = elv_next_request(q);		/* take out our request so no other */
 	if (req -> sector == -1)
-		end_request(CURRENT, 0);
+		end_request(req, 0);
 	spin_unlock_irq(q->queue_lock);
 
 	down(&ioctl_read_sem);
-	if (req->cmd != READ)
+	if (rq_data_dir(elv_next_request(q)) != READ)
 	{
-		msg(DBG_INF, "bad cmd %d\n", req->cmd);
-		goto err_done;
-	}
-	p = D_S + minor(req->rq_dev);
-	if (p->drv_id==-1) {
-		msg(DBG_INF, "do_request: bad device: %s\n",
-			kdevname(req->rq_dev));
+		msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
 		goto err_done;
 	}
+	p = req->rq_disk->private_data;
 #if OLD_BUSY
 	while (busy_audio) sbp_sleep(HZ); /* wait a bit */
 	busy_data=1;
@@ -4903,7 +4905,7 @@
 #endif
 		up(&ioctl_read_sem);
 		spin_lock_irq(q->queue_lock);
-		end_request(CURRENT, 1);
+		end_request(req, 1);
 		goto request_loop;
 	}
 
@@ -4944,7 +4946,7 @@
 #endif
 			up(&ioctl_read_sem);
 			spin_lock_irq(q->queue_lock);
-			end_request(CURRENT, 1);
+			end_request(req, 1);
 			goto request_loop;
 		}
 	}
@@ -4960,7 +4962,7 @@
 	up(&ioctl_read_sem);
 	sbp_sleep(0);    /* wait a bit, try again */
 	spin_lock_irq(q->queue_lock);
-	end_request(CURRENT, 0);
+	end_request(req, 0);
 	goto request_loop;
 }
 /*==========================================================================*/
@@ -5351,13 +5353,38 @@
 }
 /*==========================================================================*/
 
+static int sbpcd_block_open(struct inode *inode, struct file *file)
+{
+	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+	return cdrom_open(p->sbpcd_infop, inode, file);
+}
+
+static int sbpcd_block_release(struct inode *inode, struct file *file)
+{
+	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+	return cdrom_release(p->sbpcd_infop, file);
+}
+
+static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+	return cdrom_ioctl(p->sbpcd_infop, inode, cmd, arg);
+}
+
+static int sbpcd_block_media_changed(struct gendisk *disk)
+{
+	struct sbpcd_drive *p = disk->private_data;
+	return cdrom_media_changed(p->sbpcd_infop);
+}
+
 static struct block_device_operations sbpcd_bdops =
 {
-	owner:			THIS_MODULE,
-	open:			cdrom_open,
-	release:		cdrom_release,
-	ioctl:			cdrom_ioctl,
-	check_media_change:	cdrom_media_changed,
+	.owner		= THIS_MODULE,
+	.open		= sbpcd_block_open,
+	.release	= sbpcd_block_release,
+	.ioctl		= sbpcd_block_ioctl,
+	.media_changed	= sbpcd_block_media_changed,
 };
 /*==========================================================================*/
 /*
@@ -5752,6 +5779,12 @@
 		if (i>=0) p->CD_changed=1;
 	}
 
+	if (!request_region(CDo_command,4,major_name))
+	{
+		printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
+		return -EIO;
+	}
+
 	/*
 	 * Turn on the CD audio channels.
 	 * The addresses are obtained from SOUND_BASE (see sbpcd.h).
@@ -5770,11 +5803,10 @@
 		goto init_done;
 #endif /* MODULE */
 	}
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sbpcd_request, &sbpcd_lock);
-
-	request_region(CDo_command,4,major_name);
+	blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock);
 
 	devfs_handle = devfs_mk_dir (NULL, "sbp", NULL);
+
 	for (j=0;j<NR_SBPCD;j++)
 	{
 		struct cdrom_device_info * sbpcd_infop;
@@ -5804,7 +5836,7 @@
 				printk("Can't unregister %s\n", major_name);
 			}
 			release_region(CDo_command,4);
-			blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+			blk_cleanup_queue(&sbpcd_queue);
 			return -EIO;
 		}
 #ifdef MODULE
@@ -5820,7 +5852,7 @@
 		if (sbpcd_infop == NULL)
 		{
                         release_region(CDo_command,4);
-			blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+			blk_cleanup_queue(&sbpcd_queue);
                         return -ENOMEM;
 		}
 		memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
@@ -5828,7 +5860,6 @@
 		sbpcd_infop->speed = 2;
 		sbpcd_infop->capacity = 1;
 		sprintf(sbpcd_infop->name, "sbpcd%d", j);
-		sbpcd_infop->dev = mk_kdev(MAJOR_NR, j);
 		sbpcd_infop->handle = p;
 		p->sbpcd_infop = sbpcd_infop;
 		disk = alloc_disk(1);
@@ -5844,9 +5875,11 @@
 		{
 			printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
 		}
+		disk->private_data = p;
+		disk->queue = &sbpcd_queue;
 		add_disk(disk);
 	}
-	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CD_FRAMESIZE);
+	blk_queue_hardsect_size(&sbpcd_queue, CD_FRAMESIZE);
 
 #ifndef MODULE
  init_done:
@@ -5865,7 +5898,7 @@
 		return;
 	}
 	release_region(CDo_command,4);
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&sbpcd_queue);
 	devfs_unregister (devfs_handle);
 	for (j=0;j<NR_SBPCD;j++)
 	{
@@ -5874,7 +5907,6 @@
 		put_disk(D_S[j].disk);
 		vfree(D_S[j].sbp_buf);
 		if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
-		devfs_unregister(D_S[j].disk.de);
 		if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
 		{
 			msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
@@ -5885,6 +5917,7 @@
 	msg(DBG_INF, "%s module released.\n", major_name);
 }
 
+
 module_init(__sbpcd_init) /*HACK!*/;
 module_exit(sbpcd_exit);
 
@@ -5899,9 +5932,8 @@
         {
                 p->CD_changed=0;
                 msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
-		/* BUG! Should invalidate buffers! --AJK */
-		/* Why should it do the above at all?! --mdcki */
 		current_drive->diskstate_flags &= ~toc_bit;
+		/* we *don't* need invalidate here, it's done by caller */
 		current_drive->diskstate_flags &= ~cd_size_bit;
 #if SAFE_MIXED
 		current_drive->has_data=0;
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Fri Oct 18 21:03:06 2002
+++ b/drivers/cdrom/sjcd.c	Fri Oct 18 21:03:06 2002
@@ -77,11 +77,12 @@
 #include <asm/uaccess.h>
 
 #define MAJOR_NR SANYO_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
+#define QUEUE (&sjcd_queue)
 #include <linux/blk.h>
 #include "sjcd.h"
 
 static int sjcd_present = 0;
+static struct request_queue sjcd_queue;
 
 #define SJCD_BUF_SIZ 32		/* cdr-h94a has internal 64K buffer */
 
@@ -453,15 +454,11 @@
 /*
  * Check the drive if the disk is changed. Should be revised.
  */
-static int sjcd_disk_change(kdev_t full_dev)
+static int sjcd_disk_change(struct gendisk *disk)
 {
 #if 0
-	printk("SJCD: sjcd_disk_change( 0x%x )\n", full_dev);
+	printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
 #endif
-	if (minor(full_dev) > 0) {
-		printk("SJCD: request error: invalid device minor.\n");
-		return 0;
-	}
 	if (!sjcd_command_is_in_progress)
 		sjcd_get_status();
 	return (sjcd_status_valid ? sjcd_media_is_changed : 0);
@@ -1067,7 +1064,6 @@
 static int current_valid(void)
 {
         return !blk_queue_empty(QUEUE) &&
-	        major(CURRENT->rq_dev) == MAJOR_NR &&
 		CURRENT->cmd == READ &&
 		CURRENT->sector != -1;
 }
@@ -1645,11 +1641,11 @@
  * A list of file operations allowed for this cdrom.
  */
 static struct block_device_operations sjcd_fops = {
-	.owner			= THIS_MODULE,
-	.open			= sjcd_open,
-	.release		= sjcd_release,
-	.ioctl			= sjcd_ioctl,
-	.check_media_change	= sjcd_disk_change,
+	.owner		= THIS_MODULE,
+	.open		= sjcd_open,
+	.release	= sjcd_release,
+	.ioctl		= sjcd_ioctl,
+	.media_changed	= sjcd_disk_change,
 };
 
 /*
@@ -1686,8 +1682,8 @@
 		return (-EIO);
 	}
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sjcd_request, &sjcd_lock);
-	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
+	blk_init_queue(&sjcd_queue, do_sjcd_request, &sjcd_lock);
+	blk_queue_hardsect_size(&sjcd_queue, 2048);
 
 	sjcd_disk = alloc_disk(1);
 	if (!sjcd_disk) {
@@ -1786,13 +1782,14 @@
 	printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
 	devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 		       S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);
+	sjcd_disk->queue = &sjcd_queue;
 	add_disk(sjcd_disk);
 
 	sjcd_present++;
 	return (0);
 out3:
 	release_region(sjcd_base, 4);
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&sjcd_queue);
 out2:
 	put_disk(sjcd_disk);
 out1:
@@ -1807,11 +1804,10 @@
 	del_gendisk(sjcd_disk);
 	put_disk(sjcd_disk);
 	release_region(sjcd_base, 4);
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&sjcd_queue);
 	if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
 		printk("SJCD: cannot unregister device.\n");
 	printk(KERN_INFO "SJCD: module: removed.\n");
-	return (0);
 }
 
 module_init(sjcd_init);
diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
--- a/drivers/cdrom/sonycd535.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/cdrom/sonycd535.c	Fri Oct 18 21:03:04 2002
@@ -135,7 +135,6 @@
 #include <linux/cdrom.h>
 
 #define MAJOR_NR CDU535_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
 #include <linux/blk.h>
 
 #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
@@ -221,6 +220,7 @@
 static unsigned short data_reg;
 
 static spinlock_t sonycd535_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
+static struct request_queue sonycd535_queue;
 
 static int initialized;			/* Has the drive been initialized? */
 static int sony_disc_changed = 1;	/* Has the disk been changed
@@ -280,17 +280,10 @@
  * check or 0 if it hasn't.  Setting flag to 0 resets the changed flag.
  */
 static int
-cdu535_check_media_change(kdev_t full_dev)
+cdu535_check_media_change(struct gendisk *disk)
 {
-	int retval;
-
-	if (minor(full_dev) != 0) {
-		printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");
-		return 0;
-	}
-
 	/* if driver is not initialized, always return 0 */
-	retval = initialized ? sony_disc_changed : 0;
+	int retval = initialized ? sony_disc_changed : 0;
 	sony_disc_changed = 0;
 	return retval;
 }
@@ -793,7 +786,7 @@
 static void
 do_cdu535_request(request_queue_t * q)
 {
-	unsigned int dev;
+	struct request *req;
 	unsigned int read_size;
 	int  block;
 	int  nsect;
@@ -804,130 +797,121 @@
 	Byte cmd[2];
 
 	while (1) {
-		if (blk_queue_empty(QUEUE))
+		if (blk_queue_empty(q))
 			return;
 
-		dev = minor(CURRENT->rq_dev);
-		block = CURRENT->sector;
-		nsect = CURRENT->nr_sectors;
-		if (dev != 0) {
-			end_request(CURRENT, 0);
+		req = elv_next_request(q);
+		block = req->sector;
+		nsect = req->nr_sectors;
+		if (!(req->flags & REQ_CMD))
+			continue;	/* FIXME */
+		if (rq_data_dir(req) == WRITE) {
+			end_request(req, 0);
 			continue;
 		}
-		if(CURRENT->flags & REQ_CMD) {
-			switch (rq_data_dir(CURRENT)) {
-			case READ:
+		if (rq_data_dir(req) != READ)
+			panic("Unknown SONY CD cmd");
+		/*
+		 * If the block address is invalid or the request goes beyond
+		 * the end of the media, return an error.
+		 */
+		if (sony_toc->lead_out_start_lba <= (block/4)) {
+			end_request(req, 0);
+			return;
+		}
+		if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
+			end_request(req, 0);
+			return;
+		}
+		while (0 < nsect) {
+			/*
+			 * If the requested sector is not currently in
+			 * the read-ahead buffer, it must be read in.
+			 */
+			if ((block < sony_first_block) || (sony_last_block < block)) {
+				sony_first_block = (block / 4) * 4;
+				log_to_msf(block / 4, params);
+				
 				/*
-				 * If the block address is invalid or the request goes beyond the end of
-				 * the media, return an error.
+				 * If the full read-ahead would go beyond the end of the media, trim
+				 * it back to read just till the end of the media.
 				 */
-				if (sony_toc->lead_out_start_lba <= (block / 4)) {
-					end_request(CURRENT, 0);
-					return;
-				}
-				if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
-					end_request(CURRENT, 0);
-					return;
+				if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
+					sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
+					read_size = sony_toc->lead_out_start_lba - (block / 4);
+				} else {
+					sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
+					read_size = sony_buffer_sectors;
 				}
-				while (0 < nsect) {
+				size_to_buf(read_size, &params[3]);
+				
+				/*
+				 * Read the data.  If the drive was not spinning,
+				 * spin it up and try some more.
+				 */
+				for (spin_up_retry=0 ;; ++spin_up_retry) {
+					/* This loop has been modified to support the Sony
+					 * CDU-510/515 series, thanks to Claudio Porfiri 
+					 * <C.Porfiri@nisms.tei.ericsson.se>.
+					 */
 					/*
-					 * If the requested sector is not currently in the read-ahead buffer,
-					 * it must be read in.
+					 * This part is to deal with very slow hardware.  We
+					 * try at most MAX_SPINUP_RETRY times to read the same
+					 * block.  A check for seek_and_read_N_blocks' result is
+					 * performed; if the result is wrong, the CDROM's engine
+					 * is restarted and the operation is tried again.
 					 */
-					if ((block < sony_first_block) || (sony_last_block < block)) {
-						sony_first_block = (block / 4) * 4;
-						log_to_msf(block / 4, params);
-						
-						/*
-						 * If the full read-ahead would go beyond the end of the media, trim
-						 * it back to read just till the end of the media.
-						 */
-						if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
-							sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
-							read_size = sony_toc->lead_out_start_lba - (block / 4);
-						} else {
-							sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
-							read_size = sony_buffer_sectors;
-						}
-						size_to_buf(read_size, &params[3]);
-						
-						/*
-						 * Read the data.  If the drive was not spinning,
-						 * spin it up and try some more.
-						 */
-						for (spin_up_retry=0 ;; ++spin_up_retry) {
-							/* This loop has been modified to support the Sony
-							 * CDU-510/515 series, thanks to Claudio Porfiri 
-							 * <C.Porfiri@nisms.tei.ericsson.se>.
-							 */
-							/*
-							 * This part is to deal with very slow hardware.  We
-							 * try at most MAX_SPINUP_RETRY times to read the same
-							 * block.  A check for seek_and_read_N_blocks' result is
-							 * performed; if the result is wrong, the CDROM's engine
-							 * is restarted and the operation is tried again.
-							 */
-							/*
-							 * 1995-06-01: The system got problems when downloading
-							 * from Slackware CDROM, the problem seems to be:
-							 * seek_and_read_N_blocks returns BAD_STATUS and we
-							 * should wait for a while before retrying, so a new
-							 * part was added to discriminate the return value from
-							 * seek_and_read_N_blocks for the various cases.
-							 */
-							int readStatus = seek_and_read_N_blocks(params, read_size,
-												status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
-							if (0 <= readStatus)	/* Good data; common case, placed first */
-								break;
-							if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
-								/* give up */
-								if (readStatus == NO_ROOM)
-									printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
-								else
-									printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
-									       status[0]);
-								sony_first_block = -1;
-								sony_last_block = -1;
-								end_request(CURRENT, 0);
-								return;
-							}
-							if (readStatus == BAD_STATUS) {
-								/* Sleep for a while, then retry */
-								current->state = TASK_INTERRUPTIBLE;
-								schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
-							}
-#if DEBUG > 0
-							printk(CDU535_MESSAGE_NAME
-							       " debug: calling spin up when reading data!\n");
-#endif
-							cmd[0] = SONY535_SPIN_UP;
-							do_sony_cmd(cmd, 1, status, NULL, 0, 0);
-						}
-					}
 					/*
-					 * The data is in memory now, copy it to the buffer and advance to the
-					 * next block to read.
+					 * 1995-06-01: The system got problems when downloading
+					 * from Slackware CDROM, the problem seems to be:
+					 * seek_and_read_N_blocks returns BAD_STATUS and we
+					 * should wait for a while before retrying, so a new
+					 * part was added to discriminate the return value from
+					 * seek_and_read_N_blocks for the various cases.
 					 */
-					copyoff = block - sony_first_block;
-					memcpy(CURRENT->buffer,
-					       sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-					
-					block += 1;
-					nsect -= 1;
-					CURRENT->buffer += 512;
+					int readStatus = seek_and_read_N_blocks(params, read_size,
+										status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
+					if (0 <= readStatus)	/* Good data; common case, placed first */
+						break;
+					if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
+						/* give up */
+						if (readStatus == NO_ROOM)
+							printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
+						else
+							printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
+							       status[0]);
+						sony_first_block = -1;
+						sony_last_block = -1;
+						end_request(req, 0);
+						return;
+					}
+					if (readStatus == BAD_STATUS) {
+						/* Sleep for a while, then retry */
+						current->state = TASK_INTERRUPTIBLE;
+						schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
+					}
+#if DEBUG > 0
+					printk(CDU535_MESSAGE_NAME
+					       " debug: calling spin up when reading data!\n");
+#endif
+					cmd[0] = SONY535_SPIN_UP;
+					do_sony_cmd(cmd, 1, status, NULL, 0, 0);
 				}
-
-				end_request(CURRENT, 1);
-				break;
-				
-			case WRITE:
-				end_request(CURRENT, 0);
-				break;
-				
-			default:
-				panic("Unknown SONY CD cmd");
 			}
+			/*
+			 * The data is in memory now, copy it to the buffer and advance to the
+			 * next block to read.
+			 */
+			copyoff = block - sony_first_block;
+			memcpy(req->buffer,
+			       sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
+			
+			block += 1;
+			nsect -= 1;
+			req->buffer += 512;
 		}
+
+		end_request(req, 1);
 	}
 }
 
@@ -1071,20 +1055,12 @@
 		  unsigned int cmd,
 		  unsigned long arg)
 {
-	unsigned int dev;
 	Byte status[2];
 	Byte cmd_buff[10], params[10];
 	int  i;
 	int  dsc_status;
 	int  err;
 
-	if (!inode) {
-		return -EINVAL;
-	}
-	dev = minor(inode->i_rdev) >> 6;
-	if (dev != 0) {
-		return -EINVAL;
-	}
 	if (check_drive_status() != 0)
 		return -EIO;
 
@@ -1447,11 +1423,11 @@
 
 static struct block_device_operations cdu_fops =
 {
-	.owner			= THIS_MODULE,
-	.open			= cdu_open,
-	.release		= cdu_release,
-	.ioctl			= cdu_ioctl,
-	.check_media_change	= cdu535_check_media_change,
+	.owner		= THIS_MODULE,
+	.open		= cdu_open,
+	.release	= cdu_release,
+	.ioctl		= cdu_ioctl,
+	.media_changed	= cdu535_check_media_change,
 };
 
 static struct gendisk *cdu_disk;
@@ -1582,10 +1558,9 @@
 		err = -EIO;
 		goto out1;
 	}
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cdu535_request,
-			&sonycd535_lock);
-	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CDU535_BLOCK_SIZE);
-	sony_toc = kamlloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
+	blk_init_queue(&sonycd535_queue, do_cdu535_request, &sonycd535_lock);
+	blk_queue_hardsect_size(&sonycd535_queue, CDU535_BLOCK_SIZE);
+	sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
 	err = -ENOMEM;
 	if (!sony_toc)
 		goto out2;
@@ -1618,6 +1593,7 @@
 			sony535_cd_base_io);
 		goto out7;
 	}
+	cdu_disk->queue = &sonycd535_queue;
 	add_disk(cdu_disk);
 	return 0;
 
@@ -1634,7 +1610,7 @@
 out3:
 	kfree(sony_toc);
 out2:
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&sonycd535_queue);
 	unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
 out1:
 	devfs_unregister(sony_devfs_handle);
@@ -1699,6 +1675,7 @@
 				  DEVFS_SPECIAL_BLK, 0);
 	del_gendisk(cdu_disk);
 	put_disk(cdu_disk);
+	blk_cleanup_queue(&sonycd535_queue);
 	if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
 		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
 	else
diff -Nru a/drivers/char/Config.help b/drivers/char/Config.help
--- a/drivers/char/Config.help	Fri Oct 18 21:03:04 2002
+++ b/drivers/char/Config.help	Fri Oct 18 21:03:04 2002
@@ -40,93 +40,6 @@
   The module will be called mwave.o. If you want to compile it as
   a module, say M here and read Documentation/modules.txt.
 
-CONFIG_AGP
-  AGP (Accelerated Graphics Port) is a bus system mainly used to
-  connect graphics cards to the rest of the system.
-
-  If you have an AGP system and you say Y here, it will be possible to
-  use the AGP features of your 3D rendering video card. This code acts
-  as a sort of "AGP driver" for the motherboard's chipset.
-
-  If you need more texture memory than you can get with the AGP GART
-  (theoretically up to 256 MB, but in practice usually 64 or 128 MB
-  due to kernel allocation issues), you could use PCI accesses
-  and have up to a couple gigs of texture space.
-
-  Note that this is the only means to have XFree4/GLX use
-  write-combining with MTRR support on the AGP bus. Without it, OpenGL
-  direct rendering will be a lot slower but still faster than PIO.
-
-  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-  use GLX or DRI.  If unsure, say N.
-
-  This driver is available as a module.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.  The
-  module will be called agpgart.o.
-
-CONFIG_AGP_INTEL
-  This option gives you AGP support for the GLX component of the
-  XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850 and 860 chipsets.
-
-  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-  use GLX or DRI.  If unsure, say N.
-
-CONFIG_AGP_I810
-  This option gives you AGP support for the Xserver on the Intel 810
-  815 and 830m chipset boards for their on-board integrated graphics. This
-  is required to do any useful video modes with these boards.
-
-CONFIG_AGP_I460
-  This option gives you AGP GART support for the Intel 460GX chipset
-  for IA64 processors.
-
-CONFIG_AGP_VIA
-  This option gives you AGP support for the GLX component of the
-  XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
-
-  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-  use GLX or DRI.  If unsure, say N.
-
-CONFIG_AGP_AMD
-  This option gives you AGP support for the GLX component of the
-  XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
-
-  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-  use GLX or DRI.  If unsure, say N.
-
-CONFIG_AGP_SIS
-  This option gives you AGP support for the GLX component of the "soon
-  to be released" XFree86 4.x on Silicon Integrated Systems [SiS]
-  chipsets.
-
-  Note that 5591/5592 AGP chipsets are NOT supported.
-
-  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-  use GLX or DRI.  If unsure, say N.
-
-CONFIG_AGP_SWORKS
-  Say Y here to support the Serverworks AGP card.  See 
-  <http://www.serverworks.com/> for product descriptions and images.
-
-CONFIG_AGP_ALI
-  This option gives you AGP support for the GLX component of the
-  XFree86 4.x on the following ALi chipsets.  The supported chipsets
-  include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
-  For the ALi-chipset question, ALi suggests you refer to
-  <http://www.ali.com.tw/eng/support/index.shtml>.
-
-  The M1541 chipset can do AGP 1x and 2x, but note that there is an
-  acknowledged incompatibility with Matrox G200 cards. Due to
-  timing issues, this chipset cannot do AGP 2x with the G200.
-  This is a hardware limitation. AGP 1x seems to be fine, though.
-
-  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-  use GLX or DRI.  If unsure, say N.
-
-CONFIG_AGP_HP_ZX1
-  This option gives you AGP GART support for the HP ZX1 chipset
-  for IA64 processors.
-
 CONFIG_I810_TCO
   Hardware driver for the TCO timer built into the Intel i810 and i815
   chipset family.  The TCO (Total Cost of Ownership) timer is a
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Fri Oct 18 21:03:08 2002
+++ b/drivers/char/Makefile	Fri Oct 18 21:03:08 2002
@@ -104,6 +104,9 @@
 obj-$(CONFIG_DRM) += drm/
 obj-$(CONFIG_PCMCIA) += pcmcia/
 
+# Files generated that shall be removed upon make clean
+clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
+
 include $(TOPDIR)/Rules.make
 
 $(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE)
diff -Nru a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
--- a/drivers/char/drm/sis_ds.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/char/drm/sis_ds.c	Fri Oct 18 21:03:08 2002
@@ -50,15 +50,16 @@
   set_t *set;
 
   set = (set_t *)MALLOC(sizeof(set_t));
-  for(i = 0; i < SET_SIZE; i++){
-    set->list[i].free_next = i+1;    
-    set->list[i].alloc_next = -1;
-  }    
-  set->list[SET_SIZE-1].free_next = -1;
-  set->free = 0;
-  set->alloc = -1;
-  set->trace = -1;
-  
+  if (set) {
+    for(i = 0; i < SET_SIZE; i++){
+      set->list[i].free_next = i+1;    
+      set->list[i].alloc_next = -1;
+    }    
+    set->list[SET_SIZE-1].free_next = -1;
+    set->free = 0;
+    set->alloc = -1;
+    set->trace = -1;
+  }  
   return set;
 }
 
@@ -172,7 +173,8 @@
 {
   void *addr;
   addr = kmalloc(nmemb*size, GFP_KERNEL);
-  memset(addr, 0, nmemb*size);
+  if (addr)
+    memset(addr, 0, nmemb*size);
   return addr;
 }
 #define free(n) kfree(n)
diff -Nru a/drivers/char/ftape/lowlevel/ftape-rw.h b/drivers/char/ftape/lowlevel/ftape-rw.h
--- a/drivers/char/ftape/lowlevel/ftape-rw.h	Fri Oct 18 21:03:08 2002
+++ b/drivers/char/ftape/lowlevel/ftape-rw.h	Fri Oct 18 21:03:08 2002
@@ -71,7 +71,7 @@
 
 /*      Count nr of 1's in pattern.
  */
-extern inline int count_ones(unsigned long mask)
+static inline int count_ones(unsigned long mask)
 {
 	int bits;
 
diff -Nru a/drivers/char/ftape/zftape/zftape-vtbl.h b/drivers/char/ftape/zftape/zftape-vtbl.h
--- a/drivers/char/ftape/zftape/zftape-vtbl.h	Fri Oct 18 21:03:04 2002
+++ b/drivers/char/ftape/zftape/zftape-vtbl.h	Fri Oct 18 21:03:04 2002
@@ -168,11 +168,11 @@
 extern int   zft_weof                  (unsigned int count, zft_position *pos);
 extern void  zft_move_past_eof         (zft_position *pos);
 
-extern inline int   zft_tape_at_eod         (const zft_position *pos);
-extern inline int   zft_tape_at_lbot        (const zft_position *pos);
-extern inline void  zft_position_before_eof (zft_position *pos, 
+static inline int   zft_tape_at_eod         (const zft_position *pos);
+static inline int   zft_tape_at_lbot        (const zft_position *pos);
+static inline void  zft_position_before_eof (zft_position *pos, 
 					     const zft_volinfo *volume);
-extern inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
+static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
 				      const zft_position *pos);
 
 /* this function decrements the zft_seg_pos counter if we are right
@@ -180,7 +180,7 @@
  * need to position before the eof mark.  NOTE: zft_tape_pos is not
  * changed 
  */
-extern inline void zft_position_before_eof(zft_position *pos, 
+static inline void zft_position_before_eof(zft_position *pos, 
 					   const zft_volinfo *volume)
 { 
 	TRACE_FUN(ft_t_flow);
@@ -195,7 +195,7 @@
 /*  Mmmh. Is the position at the end of the last volume, that is right
  *  before the last EOF mark also logical an EOD condition?
  */
-extern inline int zft_tape_at_eod(const zft_position *pos)
+static inline int zft_tape_at_eod(const zft_position *pos)
 { 
 	TRACE_FUN(ft_t_any);
 
@@ -207,7 +207,7 @@
 	}
 }
 
-extern inline int zft_tape_at_lbot(const zft_position *pos)
+static inline int zft_tape_at_lbot(const zft_position *pos)
 {
 	if (zft_qic_mode) {
 		return (pos->seg_pos <= zft_first_vtbl->start_seg &&
@@ -220,7 +220,7 @@
 
 /* This one checks for EOF.  return remaing space (may be negative) 
  */
-extern inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
+static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
 				      const zft_position *pos)
 {     
 	return (__s64)(vtbl->size - pos->volume_pos);
diff -Nru a/drivers/char/isicom.c b/drivers/char/isicom.c
--- a/drivers/char/isicom.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/char/isicom.c	Fri Oct 18 21:03:03 2002
@@ -122,7 +122,7 @@
 };
 
  
-extern inline int WaitTillCardIsFree(unsigned short base)
+static inline int WaitTillCardIsFree(unsigned short base)
 {
 	unsigned long count=0;
 	while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
@@ -358,7 +358,7 @@
 	return 0;
 }
 			
-extern inline void schedule_bh(struct isi_port * port)
+static inline void schedule_bh(struct isi_port * port)
 {
 	queue_task(&port->bh_tqueue, &tq_isicom);
 	mark_bh(ISICOM_BH);
@@ -823,7 +823,7 @@
  
 /* open et all */ 
 
-extern inline void isicom_setup_board(struct isi_board * bp)
+static inline void isicom_setup_board(struct isi_board * bp)
 {
 	int channel;
 	struct isi_port * port;
@@ -1091,7 +1091,7 @@
  
 /* close et all */
 
-extern inline void isicom_shutdown_board(struct isi_board * bp)
+static inline void isicom_shutdown_board(struct isi_board * bp)
 {
 	int channel;
 	struct isi_port * port;
@@ -1353,7 +1353,7 @@
 }
 
 /* ioctl et all */
-extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
+static inline void isicom_send_break(struct isi_port * port, unsigned long length)
 {
 	struct isi_board * card = port->card;
 	short wait = 10;
diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
--- a/drivers/char/rio/rio_linux.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/char/rio/rio_linux.c	Fri Oct 18 21:03:05 2002
@@ -53,7 +53,6 @@
 #include <linux/fcntl.h>
 #include <linux/major.h>
 #include <linux/delay.h>
-#include <linux/tqueue.h>
 #include <linux/version.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
diff -Nru a/drivers/char/specialix.c b/drivers/char/specialix.c
--- a/drivers/char/specialix.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/char/specialix.c	Fri Oct 18 21:03:08 2002
@@ -239,28 +239,28 @@
  */
 
 /* Get board number from pointer */
-extern inline int board_No (struct specialix_board * bp)
+static inline int board_No (struct specialix_board * bp)
 {
 	return bp - sx_board;
 }
 
 
 /* Get port number from pointer */
-extern inline int port_No (struct specialix_port const * port)
+static inline int port_No (struct specialix_port const * port)
 {
 	return SX_PORT(port - sx_port); 
 }
 
 
 /* Get pointer to board from pointer to port */
-extern inline struct specialix_board * port_Board(struct specialix_port const * port)
+static inline struct specialix_board * port_Board(struct specialix_port const * port)
 {
 	return &sx_board[SX_BOARD(port - sx_port)];
 }
 
 
 /* Input Byte from CL CD186x register */
-extern inline unsigned char sx_in(struct specialix_board  * bp, unsigned short reg)
+static inline unsigned char sx_in(struct specialix_board  * bp, unsigned short reg)
 {
 	bp->reg = reg | 0x80;
 	outb (reg | 0x80, bp->base + SX_ADDR_REG);
@@ -269,7 +269,7 @@
 
 
 /* Output Byte to CL CD186x register */
-extern inline void sx_out(struct specialix_board  * bp, unsigned short reg,
+static inline void sx_out(struct specialix_board  * bp, unsigned short reg,
 			  unsigned char val)
 {
 	bp->reg = reg | 0x80;
@@ -279,7 +279,7 @@
 
 
 /* Input Byte from CL CD186x register */
-extern inline unsigned char sx_in_off(struct specialix_board  * bp, unsigned short reg)
+static inline unsigned char sx_in_off(struct specialix_board  * bp, unsigned short reg)
 {
 	bp->reg = reg;
 	outb (reg, bp->base + SX_ADDR_REG);
@@ -288,7 +288,7 @@
 
 
 /* Output Byte to CL CD186x register */
-extern inline void sx_out_off(struct specialix_board  * bp, unsigned short reg,
+static inline void sx_out_off(struct specialix_board  * bp, unsigned short reg,
 			  unsigned char val)
 {
 	bp->reg = reg;
@@ -298,7 +298,7 @@
 
 
 /* Wait for Channel Command Register ready */
-extern inline void sx_wait_CCR(struct specialix_board  * bp)
+static inline void sx_wait_CCR(struct specialix_board  * bp)
 {
 	unsigned long delay;
 
@@ -311,7 +311,7 @@
 
 
 /* Wait for Channel Command Register ready */
-extern inline void sx_wait_CCR_off(struct specialix_board  * bp)
+static inline void sx_wait_CCR_off(struct specialix_board  * bp)
 {
 	unsigned long delay;
 
@@ -327,13 +327,13 @@
  *  specialix IO8+ IO range functions.
  */
 
-extern inline int sx_check_io_range(struct specialix_board * bp)
+static inline int sx_check_io_range(struct specialix_board * bp)
 {
 	return check_region (bp->base, SX_IO_SPACE);
 }
 
 
-extern inline void sx_request_io_range(struct specialix_board * bp)
+static inline void sx_request_io_range(struct specialix_board * bp)
 {
 	request_region(bp->base, 
 	               bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE,
@@ -341,7 +341,7 @@
 }
 
 
-extern inline void sx_release_io_range(struct specialix_board * bp)
+static inline void sx_release_io_range(struct specialix_board * bp)
 {
 	release_region(bp->base, 
 	               bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
@@ -351,7 +351,7 @@
 /* Must be called with enabled interrupts */
 /* Ugly. Very ugly. Don't use this for anything else than initialization 
    code */
-extern inline void sx_long_delay(unsigned long delay)
+static inline void sx_long_delay(unsigned long delay)
 {
 	unsigned long i;
 	
@@ -599,7 +599,7 @@
  *  Interrupt processing routines.
  * */
 
-extern inline void sx_mark_event(struct specialix_port * port, int event)
+static inline void sx_mark_event(struct specialix_port * port, int event)
 {
 	/* 
 	 * I'm not quite happy with current scheme all serial
@@ -616,7 +616,7 @@
 }
 
 
-extern inline struct specialix_port * sx_get_port(struct specialix_board * bp,
+static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
 					       unsigned char const * what)
 {
 	unsigned char channel;
@@ -635,7 +635,7 @@
 }
 
 
-extern inline void sx_receive_exc(struct specialix_board * bp)
+static inline void sx_receive_exc(struct specialix_board * bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
@@ -701,7 +701,7 @@
 }
 
 
-extern inline void sx_receive(struct specialix_board * bp)
+static inline void sx_receive(struct specialix_board * bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
@@ -732,7 +732,7 @@
 }
 
 
-extern inline void sx_transmit(struct specialix_board * bp)
+static inline void sx_transmit(struct specialix_board * bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
@@ -802,7 +802,7 @@
 }
 
 
-extern inline void sx_check_modem(struct specialix_board * bp)
+static inline void sx_check_modem(struct specialix_board * bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
@@ -962,7 +962,7 @@
 
 
 /* Called with disabled interrupts */
-extern inline int sx_setup_board(struct specialix_board * bp)
+static inline int sx_setup_board(struct specialix_board * bp)
 {
 	int error;
 
@@ -986,7 +986,7 @@
 
 
 /* Called with disabled interrupts */
-extern inline void sx_shutdown_board(struct specialix_board *bp)
+static inline void sx_shutdown_board(struct specialix_board *bp)
 {
 	if (!(bp->flags & SX_BOARD_ACTIVE))
 		return;
@@ -1867,7 +1867,7 @@
 }
 
 
-extern inline void sx_send_break(struct specialix_port * port, unsigned long length)
+static inline void sx_send_break(struct specialix_port * port, unsigned long length)
 {
 	struct specialix_board *bp = port_Board(port);
 	unsigned long flags;
@@ -1886,7 +1886,7 @@
 }
 
 
-extern inline int sx_set_serial_info(struct specialix_port * port,
+static inline int sx_set_serial_info(struct specialix_port * port,
                                      struct serial_struct * newinfo)
 {
 	struct serial_struct tmp;
@@ -1942,7 +1942,7 @@
 }
 
 
-extern inline int sx_get_serial_info(struct specialix_port * port,
+static inline int sx_get_serial_info(struct specialix_port * port,
 				     struct serial_struct * retinfo)
 {
 	struct serial_struct tmp;
diff -Nru a/drivers/char/sysrq.c b/drivers/char/sysrq.c
--- a/drivers/char/sysrq.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/char/sysrq.c	Fri Oct 18 21:03:08 2002
@@ -349,8 +349,8 @@
 /* 8 */	&sysrq_loglevel_op,
 /* 9 */	&sysrq_loglevel_op,
 /* a */	NULL, /* Don't use for system provided sysrqs,
-		 it is handled specially on the spark
-		 and will never arive */
+		 it is handled specially on the sparc
+		 and will never arrive */
 /* b */	&sysrq_reboot_op,
 /* c */	NULL,
 /* d */	NULL,
diff -Nru a/drivers/char/tipar.c b/drivers/char/tipar.c
--- a/drivers/char/tipar.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/char/tipar.c	Fri Oct 18 21:03:07 2002
@@ -284,7 +284,6 @@
 	    minor(file->f_dentry->d_inode->i_rdev) - TIPAR_MINOR;
 	ssize_t n;
 
-	printk("_write\n");
 	parport_claim_or_block(table[minor].dev);
 
 	for (n = 0; n < count; n++) {
@@ -321,7 +320,6 @@
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
-	printk("_read\n");
 	parport_claim_or_block(table[minor].dev);
 
 	while (n < count) {
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/ide/ide-cd.c	Fri Oct 18 21:03:04 2002
@@ -2647,7 +2647,6 @@
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *devinfo = &info->devinfo;
 
-	devinfo->dev = mk_kdev(drive->disk->major, drive->disk->first_minor);
 	devinfo->ops = &ide_cdrom_dops;
 	devinfo->mask = 0;
 	devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
@@ -3026,15 +3025,9 @@
 		     struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	int error;
-
-	/* Try the generic SCSI command ioctl's first.. */
-	error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
-	if (error != -ENOTTY)
-		return error;
+	struct cdrom_info *info = drive->driver_data;
 
-	/* Then the generic cdrom ioctl's.. */
-	return cdrom_ioctl(inode, file, cmd, arg);
+	return cdrom_ioctl(&info->devinfo, inode, cmd, arg);
 }
 
 static
@@ -3044,9 +3037,9 @@
 	int rc = -ENOMEM;
 
 	MOD_INC_USE_COUNT;
-	if (info->buffer == NULL)
+	if (!info->buffer)
 		info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
-        if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) {
+        if (!info->buffer || (rc = cdrom_open(&info->devinfo, ip, fp))) {
 		drive->usage--;
 		MOD_DEC_USE_COUNT;
 	}
@@ -3057,15 +3050,16 @@
 void ide_cdrom_release (struct inode *inode, struct file *file,
 			ide_drive_t *drive)
 {
-	cdrom_release (inode, file);
+	struct cdrom_info *info = drive->driver_data;
+	cdrom_release (&info->devinfo, file);
 	MOD_DEC_USE_COUNT;
 }
 
 static
 int ide_cdrom_check_media_change (ide_drive_t *drive)
 {
-	return cdrom_media_changed(mk_kdev(drive->disk->major,
-			drive->disk->first_minor));
+	struct cdrom_info *info = drive->driver_data;
+	return cdrom_media_changed(&info->devinfo);
 }
 
 static
diff -Nru a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c
--- a/drivers/ide/ide-geometry.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/ide/ide-geometry.c	Fri Oct 18 21:03:08 2002
@@ -83,7 +83,6 @@
 }
 
 
-extern ide_drive_t * get_info_ptr(kdev_t);
 extern unsigned long current_capacity (ide_drive_t *);
 
 /*
@@ -147,18 +146,14 @@
  * Returns 1 if the geometry translation was successful.
  */
 
-int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg)
+int ide_xlate_1024 (struct block_device *bdev, int xparm, int ptheads, const char *msg)
 {
-	ide_drive_t *drive;
+	ide_drive_t *drive = bdev->bd_disk->private_data;
 	const char *msg1 = "";
 	int heads = 0;
 	int c, h, s;
 	int transl = 1;		/* try translation */
 	int ret = 0;
-
-	drive = get_info_ptr(i_rdev);
-	if (!drive)
-		return 0;
 
 	/* remap? */
 	if (drive->remap_0_to_1 != 2) {
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/ide/ide-probe.c	Fri Oct 18 21:03:05 2002
@@ -47,6 +47,7 @@
 #include <linux/ide.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
+#include <linux/kmod.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -971,6 +972,41 @@
 
 EXPORT_SYMBOL(init_irq);
 
+static void ata_lock(dev_t dev, void *data)
+{
+	ide_hwif_t *hwif = data;
+	int unit = MINOR(dev) >> PARTN_BITS;
+	get_disk(hwif->drives[unit].disk);
+}
+
+struct gendisk *ata_probe(dev_t dev, int *part, void *data)
+{
+	ide_hwif_t *hwif = data;
+	int unit = MINOR(dev) >> PARTN_BITS;
+	ide_drive_t *drive = &hwif->drives[unit];
+	if (!drive->present) {
+		put_disk(drive->disk);
+		return NULL;
+	}
+	if (!drive->driver) {
+		if (drive->media == ide_disk)
+			(void) request_module("ide-disk");
+		if (drive->scsi)
+			(void) request_module("ide-scsi");
+		if (drive->media == ide_cdrom)
+			(void) request_module("ide-cd");
+		if (drive->media == ide_tape)
+			(void) request_module("ide-tape");
+		if (drive->media == ide_floppy)
+			(void) request_module("ide-floppy");
+	}
+	if (!drive->driver) {
+		put_disk(drive->disk);
+		return NULL;
+	}
+	return drive->disk;
+}
+
 /*
  * init_gendisk() (as opposed to ide_geninit) is called for each major device,
  * after probing for drives, to allocate partition tables and other data
@@ -992,12 +1028,15 @@
 	}
 
 	for (unit = 0; unit < units; ++unit) {
+		ide_drive_t *drive = &hwif->drives[unit];
 		struct gendisk *disk = disks[unit];
 		disk->major  = hwif->major;
 		disk->first_minor = unit << PARTN_BITS;
 		sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit);
 		disk->fops = ide_fops;
-		hwif->drives[unit].disk = disk;
+		disk->private_data = drive;
+		disk->queue = &drive->queue;
+		drive->disk = disk;
 	}
 
 	for (unit = 0; unit < units; ++unit) {
@@ -1024,6 +1063,9 @@
 			device_register(&drive->gendev);
 	}
 
+	blk_register_region(MKDEV(hwif->major, 0), units << PARTN_BITS,
+			THIS_MODULE, ata_probe, ata_lock, hwif);
+
 	return;
 
 err_kmalloc_gd:
@@ -1083,10 +1125,7 @@
 		printk("%s: probed IRQ %d failed, using default.\n",
 			hwif->name, hwif->irq);
 	}
-	
 	init_gendisk(hwif);
-	blk_dev[hwif->major].data = hwif;
-	blk_dev[hwif->major].queue = ide_get_queue;
 	hwif->present = 1;	/* success */
 	return 1;
 }
@@ -1150,7 +1189,7 @@
 }
 
 #ifdef MODULE
-extern int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *);
+extern int (*ide_xlate_1024_hook)(struct block_device *, int, int, const char *);
 
 int init_module (void)
 {
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/ide/ide.c	Fri Oct 18 21:03:04 2002
@@ -878,7 +878,6 @@
 {
 	ide_startstop_t startstop;
 	unsigned long block;
-	unsigned int minor = minor(rq->rq_dev), unit = minor >> PARTN_BITS;
 	ide_hwif_t *hwif = HWIF(drive);
 
 	BUG_ON(!(rq->flags & REQ_STARTED));
@@ -897,15 +896,8 @@
 	 * bail early if we've sent a device to sleep, however how to wake
 	 * this needs to be a masked flag.  FIXME for proper operations.
 	 */
-	if (drive->suspend_reset) {
+	if (drive->suspend_reset)
 		goto kill_rq;
-	}
-
-	if (unit >= MAX_DRIVES) {
-		printk("%s: bad device number: %s\n",
-			hwif->name, kdevname(rq->rq_dev));
-		goto kill_rq;
-	}
 
 	block    = rq->sector;
 	if (blk_fs_request(rq) &&
@@ -1172,18 +1164,6 @@
 EXPORT_SYMBOL(ide_do_request);
 
 /*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-request_queue_t *ide_get_queue (kdev_t dev)
-{
-	ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[major(dev)].data;
-
-	return &hwif->drives[DEVICE_NR(dev) & 1].queue;
-}
-
-EXPORT_SYMBOL(ide_get_queue);
-
-/*
  * Passes the stuff to ide_do_request
  */
 void do_ide_request(request_queue_t *q)
@@ -1496,32 +1476,6 @@
 EXPORT_SYMBOL(ide_intr);
 
 /*
- * get_info_ptr() returns the (ide_drive_t *) for a given device number.
- * It returns NULL if the given device number does not match any present drives.
- */
-ide_drive_t *get_info_ptr (kdev_t i_rdev)
-{
-	int		major = major(i_rdev);
-	unsigned int	h;
-
-	for (h = 0; h < MAX_HWIFS; ++h) {
-		ide_hwif_t  *hwif = &ide_hwifs[h];
-		if (hwif->present && major == hwif->major) {
-			unsigned unit = DEVICE_NR(i_rdev);
-			if (unit < MAX_DRIVES) {
-				ide_drive_t *drive = &hwif->drives[unit];
-				if (drive->present)
-					return drive;
-			}
-			break;
-		}
-	}
-	return NULL;
-}
-
-EXPORT_SYMBOL(get_info_ptr);
-
-/*
  * This function is intended to be used prior to invoking ide_do_drive_cmd().
  */
 void ide_init_drive_cmd (struct request *rq)
@@ -1572,7 +1526,20 @@
 #endif
 	rq->errors = 0;
 	rq->rq_status = RQ_ACTIVE;
-	rq->rq_dev = mk_kdev(major,(drive->select.b.unit)<<PARTN_BITS);
+
+	/*
+	 * Aiee. This is ugly, but it gets called before "drive->disk"
+	 * has been initialized. Al will fix it, I'm sure.
+	 */
+	if (drive->disk)
+		rq->rq_dev = mk_kdev(drive->disk->major, drive->disk->first_minor);
+	else {
+		printk("IDE init is ugly:");
+		dump_stack();
+		rq->rq_dev = mk_kdev(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS);
+	}
+
+	rq->rq_disk = drive->disk;
 	if (action == ide_wait)
 		rq->waiting = &wait;
 	spin_lock_irqsave(&ide_lock, flags);
@@ -1615,18 +1582,14 @@
  * usage == 1 (we need an open channel to use an ioctl :-), so this
  * is our limit.
  */
-int ide_revalidate_disk (kdev_t i_rdev)
+static int ide_revalidate_disk(struct gendisk *disk)
 {
-	ide_drive_t *drive;
-	if ((drive = get_info_ptr(i_rdev)) == NULL)
-		return -ENODEV;
+	ide_drive_t *drive = disk->private_data;
 	if (DRIVER(drive)->revalidate)
 		DRIVER(drive)->revalidate(drive);
 	return  0;
 }
 
-EXPORT_SYMBOL(ide_revalidate_disk);
-
 void ide_probe_module (void)
 {
 	if (!ide_probe) {
@@ -1642,28 +1605,9 @@
 
 static int ide_open (struct inode * inode, struct file * filp)
 {
-	ide_drive_t *drive;
-
-	if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
-		return -ENXIO;
-	if (drive->driver == NULL) {
-		if (drive->media == ide_disk)
-			(void) request_module("ide-disk");
-		if (drive->scsi)
-			(void) request_module("ide-scsi");
-		if (drive->media == ide_cdrom)
-			(void) request_module("ide-cd");
-		if (drive->media == ide_tape)
-			(void) request_module("ide-tape");
-		if (drive->media == ide_floppy)
-			(void) request_module("ide-floppy");
-	}
+	ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
 	drive->usage++;
-	if (drive->driver != NULL)
-		return DRIVER(drive)->open(inode, filp, drive);
-	printk (KERN_WARNING "%s: driver not present\n", drive->name);
-	drive->usage--;
-	return -ENXIO;
+	return DRIVER(drive)->open(inode, filp, drive);
 }
 
 /*
@@ -1672,13 +1616,9 @@
  */
 static int ide_release (struct inode * inode, struct file * file)
 {
-	ide_drive_t *drive;
-
-	if ((drive = get_info_ptr(inode->i_rdev)) != NULL) {
-		drive->usage--;
-		if (drive->driver != NULL)
-			DRIVER(drive)->release(inode, file, drive);
-	}
+	ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+	DRIVER(drive)->release(inode, file, drive);
+	drive->usage--;
 	return 0;
 }
 
@@ -1772,7 +1712,6 @@
 	ide_hwgroup_t *hwgroup;
 	int irq_count = 0, unit, i;
 	unsigned long flags;
-	unsigned int p, minor;
 	ide_hwif_t old_hwif;
 
 	if (index >= MAX_HWIFS)
@@ -1792,25 +1731,10 @@
 	}
 	hwif->present = 0;
 	
-	/*
-	 * All clear?  Then blow away the buffer cache
-	 */
 	spin_unlock_irqrestore(&ide_lock, flags);
-	for (unit = 0; unit < MAX_DRIVES; ++unit) {
-		drive = &hwif->drives[unit];
-		if (!drive->present)
-			continue;
-		minor = drive->select.b.unit << PARTN_BITS;
-		for (p = 0; p < (1<<PARTN_BITS); ++p) {
-			if (get_capacity(drive->disk)) {
-				kdev_t devp = mk_kdev(hwif->major, minor+p);
-				invalidate_device(devp, 0);
-			}
-		}
 #ifdef CONFIG_PROC_FS
-		destroy_proc_ide_drives(hwif);
+	destroy_proc_ide_drives(hwif);
 #endif
-	}
 	spin_lock_irqsave(&ide_lock, flags);
 	hwgroup = hwif->hwgroup;
 
@@ -1885,9 +1809,8 @@
 	/*
 	 * Remove us from the kernel's knowledge
 	 */
+	blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
 	unregister_blkdev(hwif->major, hwif->name);
-	blk_dev[hwif->major].data = NULL;
-	blk_dev[hwif->major].queue = NULL;
 	for (i = 0; i < MAX_DRIVES; i++) {
 		struct gendisk *disk = hwif->drives[i].disk;
 		hwif->drives[i].disk = NULL;
@@ -2482,28 +2405,21 @@
 static int ide_ioctl (struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	int err = 0, major, minor;
-	ide_drive_t *drive;
-	struct request rq;
-	kdev_t dev;
+	ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
 	ide_settings_t *setting;
-
-	major = major(dev); minor = minor(dev);
-	if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
-		return -ENODEV;
+	int err = 0;
 
 	if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {
 		if (cmd == setting->read_ioctl) {
 			err = ide_read_setting(drive, setting);
 			return err >= 0 ? put_user(err, (long *) arg) : err;
 		} else {
-			if ((minor(inode->i_rdev) & PARTN_MASK))
+			if (inode->i_bdev != inode->i_bdev->bd_contains)
 				return -EINVAL;
 			return ide_write_setting(drive, setting, arg);
 		}
 	}
 
-	ide_init_drive_cmd (&rq);
 	switch (cmd) {
 		case HDIO_GETGEO:
 		{
@@ -2532,7 +2448,7 @@
 
 		case HDIO_OBSOLETE_IDENTITY:
 		case HDIO_GET_IDENTITY:
-			if (minor(inode->i_rdev) & PARTN_MASK)
+			if (inode->i_bdev != inode->i_bdev->bd_contains)
 				return -EINVAL;
 			if (drive->id == NULL)
 				return -ENOMSG;
@@ -2662,12 +2578,9 @@
 	}
 }
 
-static int ide_check_media_change (kdev_t i_rdev)
+static int ide_check_media_change(struct gendisk *disk)
 {
-	ide_drive_t *drive;
-
-	if ((drive = get_info_ptr(i_rdev)) == NULL)
-		return -ENODEV;
+	ide_drive_t *drive = disk->private_data;
 	if (drive->driver != NULL)
 		return DRIVER(drive)->media_change(drive);
 	return 0;
@@ -3491,12 +3404,12 @@
 EXPORT_SYMBOL(ide_unregister_driver);
 
 struct block_device_operations ide_fops[] = {{
-	.owner			= THIS_MODULE,
-	.open			= ide_open,
-	.release		= ide_release,
-	.ioctl			= ide_ioctl,
-	.check_media_change	= ide_check_media_change,
-	.revalidate		= ide_revalidate_disk
+	.owner		= THIS_MODULE,
+	.open		= ide_open,
+	.release	= ide_release,
+	.ioctl		= ide_ioctl,
+	.media_changed	= ide_check_media_change,
+	.revalidate_disk= ide_revalidate_disk
 }};
 
 EXPORT_SYMBOL(ide_fops);
@@ -3538,8 +3451,6 @@
 	return 0;
 }
 
-module_init(ide_init);
-
 #ifdef MODULE
 char *options = NULL;
 MODULE_PARM(options,"s");
@@ -3588,5 +3499,7 @@
 #else /* !MODULE */
 
 __setup("", ide_setup);
+
+module_init(ide_init);
 
 #endif /* MODULE */
diff -Nru a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
--- a/drivers/input/serio/sa1111ps2.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/input/serio/sa1111ps2.c	Fri Oct 18 21:03:04 2002
@@ -354,7 +354,7 @@
 
 static void __exit ps2_exit(void)
 {
-	remove_driver(&ps2_driver.drv);
+	driver_unregister(&ps2_driver.drv);
 }
 
 module_init(ps2_init);
diff -Nru a/drivers/isdn/i4l/Makefile b/drivers/isdn/i4l/Makefile
--- a/drivers/isdn/i4l/Makefile	Fri Oct 18 21:03:04 2002
+++ b/drivers/isdn/i4l/Makefile	Fri Oct 18 21:03:04 2002
@@ -19,7 +19,7 @@
 
 # Optional parts of multipart objects.
 
-isdn-objs-$(CONFIG_ISDN_PPP)		+= isdn_ppp.o
+isdn-objs-$(CONFIG_ISDN_PPP)		+= isdn_ppp.o isdn_ppp_ccp.o
 isdn-objs-$(CONFIG_ISDN_X25)		+= isdn_concap.o isdn_x25iface.o
 isdn-objs-$(CONFIG_ISDN_AUDIO)		+= isdn_audio.o
 isdn-objs-$(CONFIG_ISDN_TTY_FAX)	+= isdn_ttyfax.o
diff -Nru a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
--- a/drivers/isdn/i4l/isdn_bsdcomp.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c	Fri Oct 18 21:03:04 2002
@@ -907,16 +907,15 @@
  *************************************************************/
 
 static struct isdn_ppp_compressor ippp_bsd_compress = {
-	NULL,NULL,		/* prev,next: overwritten by isdn_ppp */
-	CI_BSD_COMPRESS,	/* compress_proto */
-	bsd_alloc,		/* alloc */
-	bsd_free,		/* free */
-	bsd_init,		/* init */
-	bsd_reset,		/* reset */
-	bsd_compress,		/* compress */
-	bsd_decompress,		/* decompress */
-	bsd_incomp,		/* incomp */
-	bsd_stats		/* comp_stat */
+	.num            = CI_BSD_COMPRESS,
+	.alloc          = bsd_alloc,
+	.free           = bsd_free,
+	.init           = bsd_init,
+	.reset          = bsd_reset,
+	.compress       = bsd_compress,
+	.decompress     = bsd_decompress,
+	.incomp         = bsd_incomp,
+	.stat           = bsd_stats,
 };
 
 /*************************************************************
diff -Nru a/drivers/isdn/i4l/isdn_ciscohdlck.c b/drivers/isdn/i4l/isdn_ciscohdlck.c
--- a/drivers/isdn/i4l/isdn_ciscohdlck.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/isdn/i4l/isdn_ciscohdlck.c	Fri Oct 18 21:03:03 2002
@@ -20,6 +20,19 @@
 #include <linux/if_arp.h>
 #include <linux/inetdevice.h>
 
+/*
+ * Definitions for Cisco-HDLC header.
+ */
+
+#define CISCO_ADDR_UNICAST    0x0f
+#define CISCO_ADDR_BROADCAST  0x8f
+#define CISCO_CTRL            0x00
+#define CISCO_TYPE_CDP        0x2000
+#define CISCO_TYPE_SLARP      0x8035
+#define CISCO_SLARP_REQUEST   0
+#define CISCO_SLARP_REPLY     1
+#define CISCO_SLARP_KEEPALIVE 2
+
 /* 
  * CISCO HDLC keepalive specific stuff
  */
diff -Nru a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
--- a/drivers/isdn/i4l/isdn_common.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/isdn/i4l/isdn_common.h	Fri Oct 18 21:03:03 2002
@@ -47,7 +47,7 @@
 #endif
 
 #define isdn_BUG() \
-do { printk(KERN_WARNING "ISDN Bug at %s:%d\n", __FILE__, __LINE__); \
+do { printk(KERN_WARNING "ISDN BUG at %s:%d\n", __FILE__, __LINE__); \
 } while(0)
 
 #define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
diff -Nru a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
--- a/drivers/isdn/i4l/isdn_net.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/isdn/i4l/isdn_net.c	Fri Oct 18 21:03:08 2002
@@ -33,412 +33,8 @@
 #include "isdn_concap.h"
 #include "isdn_ciscohdlck.h"
 
-/*
- * Outline of new tbusy handling: 
- *
- * Old method, roughly spoken, consisted of setting tbusy when entering
- * isdn_net_start_xmit() and at several other locations and clearing
- * it from isdn_net_start_xmit() thread when sending was successful.
- *
- * With 2.3.x multithreaded network core, to prevent problems, tbusy should
- * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
- * condition is detected. Other threads (in particular isdn_net_stat_callb())
- * are only allowed to clear tbusy.
- *
- * -HE
- */
-
-/*
- * About SOFTNET:
- * Most of the changes were pretty obvious and basically done by HE already.
- *
- * One problem of the isdn net device code is that is uses struct net_device
- * for masters and slaves. However, only master interface are registered to 
- * the network layer, and therefore, it only makes sense to call netif_* 
- * functions on them.
- *
- * --KG
- */
-
-/* 
- * Find out if the netdevice has been ifup-ed yet.
- */
-static inline int
-isdn_net_device_started(isdn_net_dev *idev)
-{
-	return netif_running(&idev->mlp->dev);
-}
-
-/*
- * stop the network -> net_device queue.
- */
-static inline void
-isdn_net_dev_stop_queue(isdn_net_dev *idev)
-{
-	netif_stop_queue(&idev->mlp->dev);
-}
-
-/*
- * find out if the net_device which this lp belongs to (lp can be
- * master or slave) is busy. It's busy iff all (master and slave) 
- * queues are busy
- */
-static inline int
-isdn_net_device_busy(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	unsigned long flags;
-	int retval = 1;
-
-	if (!isdn_net_dev_busy(idev))
-		return 0;
-
-	spin_lock_irqsave(&mlp->online_lock, flags);
-	list_for_each_entry(idev, &mlp->online, online) {
-		if (!isdn_net_dev_busy(idev)) {
-			retval = 0;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&mlp->online_lock, flags);
-	return retval;
-}
-
-static inline
-void isdn_net_inc_frame_cnt(isdn_net_dev *idev)
-{
-	atomic_inc(&idev->frame_cnt);
-	if (isdn_net_device_busy(idev))
-		isdn_net_dev_stop_queue(idev);
-}
-
-static inline void
-isdn_net_dec_frame_cnt(isdn_net_dev *idev)
-{
-	atomic_dec(&idev->frame_cnt);
-
-	if (!isdn_net_device_busy(idev)) {
-		if (!skb_queue_empty(&idev->super_tx_queue))
-			tasklet_schedule(&idev->tlet);
-		else
-			isdn_net_dev_wake_queue(idev);
-       }                                                                      
-}
-
-static inline
-void isdn_net_zero_frame_cnt(isdn_net_dev *idev)
-{
-	atomic_set(&idev->frame_cnt, 0);
-}
-
-/* Prototypes */
-
-int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg);
-
 char *isdn_net_revision = "$Revision: 1.140.6.11 $";
 
-/* A packet has successfully been sent out. */
-
-int
-isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c)
-{
-	isdn_net_local *mlp = idev->mlp;
-
-	isdn_net_dec_frame_cnt(idev);
-	mlp->stats.tx_packets++;
-	mlp->stats.tx_bytes += c->parm.length;
-	return 1;
-}
-
-static void
-isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
-{
-	u_short proto = ntohs(skb->protocol);
-	
-	printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
-	       dev->name,
-	       (reason != NULL) ? reason : "unknown",
-	       (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
-	
-	dst_link_failure(skb);
-}
-
-static void
-isdn_net_log_skb(struct sk_buff *skb, isdn_net_dev *idev)
-{
-	unsigned char *p = skb->nh.raw; /* hopefully, this was set correctly */
-	unsigned short proto = ntohs(skb->protocol);
-	int data_ofs;
-	struct ip_ports {
-		unsigned short source;
-		unsigned short dest;
-	} *ipp;
-	char addinfo[100];
-
-	data_ofs = ((p[0] & 15) * 4);
-	switch (proto) {
-	case ETH_P_IP:
-		switch (p[9]) {
-		case IPPROTO_ICMP:
-			strcpy(addinfo, "ICMP");
-			break;
-		case IPPROTO_TCP:
-		case IPPROTO_UDP:
-			ipp = (struct ip_ports *) (&p[data_ofs]);
-			sprintf(addinfo, "%s, port: %d -> %d",
-				p[9] == IPPROTO_TCP ? "TCP" : "UDP",
-				ntohs(ipp->source), ntohs(ipp->dest));
-			break;
-		default:
-			sprintf(addinfo, "type %d", p[9]);
-		}
-		printk(KERN_INFO
-		       "OPEN: %u.%u.%u.%u -> %u.%u.%u.%u %s\n",
-		       
-		       NIPQUAD(*(u32 *)(p + 12)), NIPQUAD(*(u32 *)(p + 16)),
-		       addinfo);
-		break;
-	case ETH_P_ARP:
-		printk(KERN_INFO
-		       "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
-		       NIPQUAD(*(u32 *)(p + 14)), NIPQUAD(*(u32 *)(p + 24)));
-		break;
-	default:
-		printk(KERN_INFO "OPEN: unknown proto %#x\n", proto);
-	}
-}
-
-/*
- * this function is used to send supervisory data, i.e. data which was
- * not received from the network layer, but e.g. frames from ipppd, CCP
- * reset frames etc.
- */
-void
-isdn_net_write_super(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	if (in_irq()) {
-		// we can't grab the lock from irq context, 
-		// so we just queue the packet
-		skb_queue_tail(&idev->super_tx_queue, skb); 
-
-		tasklet_schedule(&idev->tlet);
-		return;
-	}
-
-	spin_lock_bh(&idev->xmit_lock);
-	if (!isdn_net_dev_busy(idev)) {
-		isdn_net_writebuf_skb(idev, skb);
-	} else {
-		skb_queue_tail(&idev->super_tx_queue, skb);
-	}
-	spin_unlock_bh(&idev->xmit_lock);
-}
-
-/* 
- * all frames sent from the (net) LL to a HL driver should go via this function
- * it's serialized by the caller holding the idev->xmit_lock spinlock
- */
-void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	isdn_net_local *mlp = idev->mlp;
-	int ret;
-	int len = skb->len;     /* save len */
-
-	/* before obtaining the lock the caller should have checked that
-	   the lp isn't busy */
-	if (isdn_net_dev_busy(idev)) {
-		isdn_BUG();
-		goto error;
-	}
-
-	if (!isdn_net_online(idev)) {
-		isdn_BUG();
-		goto error;
-	}
-	ret = isdn_slot_write(idev->isdn_slot, skb);
-	if (ret != len) {
-		/* we should never get here */
-		printk(KERN_WARNING "%s: HL driver queue full\n", idev->name);
-		goto error;
-	}
-	
-	idev->transcount += len;
-	isdn_net_inc_frame_cnt(idev);
-	return;
-
- error:
-	dev_kfree_skb(skb);
-	mlp->stats.tx_errors++;
-}
-
-static void
-isdn_net_dial_slave(isdn_net_local *mlp)
-{
-	isdn_net_dev *idev;
-
-	list_for_each_entry(idev, &mlp->slaves, slaves) {
-		if (!isdn_net_bound(idev)) {
-			isdn_net_dial(idev);
-			break;
-		}
-	}
-}
-
-/*
- *  Based on cps-calculation, check if device is overloaded.
- *  If so, and if a slave exists, trigger dialing for it.
- *  If any slave is online, deliver packets using a simple round robin
- *  scheme.
- *
- *  Return: 0 on success, !0 on failure.
- */
-
-int
-isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	isdn_net_dev *idev;
-	isdn_net_local *mlp = ndev->priv;
-
-	ndev->trans_start = jiffies;
-
-	if (list_empty(&mlp->online))
-		return isdn_net_autodial(skb, ndev);
-
-	idev = isdn_net_get_locked_dev(mlp);
-	if (!idev) {
-		printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
-		netif_stop_queue(ndev);
-		return 1;
-	}
-	/* we have our idev locked from now on */
-
-	isdn_net_writebuf_skb(idev, skb);
-	spin_unlock_bh(&idev->xmit_lock);
-
-	/* the following stuff is here for backwards compatibility.
-	 * in future, start-up and hangup of slaves (based on current load)
-	 * should move to userspace and get based on an overall cps
-	 * calculation
-	 */
-	if (jiffies != idev->last_jiffies) {
-		idev->cps = idev->transcount * HZ / (jiffies - idev->last_jiffies);
-		idev->last_jiffies = jiffies;
-		idev->transcount = 0;
-	}
-	if (dev->net_verbose > 3)
-		printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
-
-	if (idev->cps > mlp->triggercps) {
-		if (!idev->sqfull) {
-			/* First time overload: set timestamp only */
-			idev->sqfull = 1;
-			idev->sqfull_stamp = jiffies;
-		} else {
-			/* subsequent overload: if slavedelay exceeded, start dialing */
-			if (time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay)) {
-				isdn_net_dial_slave(mlp);
-			}
-		}
-	} else {
-		if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay + 10 * HZ)) {
-			idev->sqfull = 0;
-		}
-		/* this is a hack to allow auto-hangup for slaves on moderate loads */
-		list_del(&mlp->online);
-		list_add_tail(&mlp->online, &idev->online);
-	}
-
-	return 0;
-}
-
-int
-isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
-{
-	isdn_net_local *mlp = ndev->priv;
-	isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves);
-
-	/* are we dialing already? */
-	if (isdn_net_bound(idev))
-		goto stop_queue;
-
-	if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
-		goto discard;
-
-	if (isdn_net_dial(idev) < 0)
-		goto discard;
-
-	/* Log packet, which triggered dialing */
-	if (dev->net_verbose)
-		isdn_net_log_skb(skb, idev);
-
- stop_queue:
-	netif_stop_queue(ndev);
-	return 1;
-
- discard:
-	isdn_net_unreachable(ndev, skb, "dial rejected");
-	dev_kfree_skb(skb);
-	return 0;
-}
-
-
-/*
- * Got a packet from ISDN-Channel.
- */
-static void
-isdn_net_receive(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	isdn_net_local *mlp = idev->mlp;
-
-	idev->transcount += skb->len;
-
-	mlp->stats.rx_packets++;
-	mlp->stats.rx_bytes += skb->len;
-	skb->dev = &mlp->dev;
-	skb->pkt_type = PACKET_HOST;
-	skb->mac.raw = skb->data;
-	isdn_dumppkt("R:", skb->data, skb->len, 40);
-
-	mlp->ops->receive(mlp, idev, skb);
-}
-
-/*
- * A packet arrived via ISDN. Search interface-chain for a corresponding
- * interface. If found, deliver packet to receiver-function and return 1,
- * else return 0.
- */
-int
-isdn_net_rcv_skb(int idx, struct sk_buff *skb)
-{
-	isdn_net_dev *idev = isdn_slot_idev(idx);
-
-	if (!idev) {
-		HERE;
-		return 0;
-	}
-	if (!isdn_net_online(idev))
-		return 0;
-
-	isdn_net_receive(idev, skb);
-	return 0;
-}
-
-/*
- * This is called from certain upper protocol layers (multilink ppp
- * and x25iface encapsulation module) that want to initiate dialing
- * themselves.
- */
-int
-isdn_net_dial_req(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	/* is there a better error code? */
-	if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
-		return -EBUSY;
-
-	return isdn_net_dial(idev);
-}
-
 // ISDN_NET_ENCAP_IPTYP
 // ethernet type field
 // ======================================================================
@@ -581,6 +177,8 @@
 void
 isdn_net_init(void)
 {
+	isdn_net_lib_init();
+
 	register_isdn_netif(ISDN_NET_ENCAP_ETHER,      &ether_ops);
 	register_isdn_netif(ISDN_NET_ENCAP_RAWIP,      &rawip_ops);
 	register_isdn_netif(ISDN_NET_ENCAP_IPTYP,      &iptyp_ops);
@@ -593,7 +191,11 @@
 #ifdef CONFIG_ISDN_PPP
 	register_isdn_netif(ISDN_NET_ENCAP_SYNCPPP,    &isdn_ppp_ops);
 #endif
+}
 
-	isdn_net_lib_init();
+void
+isdn_net_exit(void)
+{
+	isdn_net_lib_exit();
 }
 
diff -Nru a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h
--- a/drivers/isdn/i4l/isdn_net.h	Fri Oct 18 21:03:08 2002
+++ b/drivers/isdn/i4l/isdn_net.h	Fri Oct 18 21:03:08 2002
@@ -14,138 +14,29 @@
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/isdn.h>
-  			      /* Definitions for hupflags:                */
-#define ISDN_CHARGEHUP   4      /* We want to use the charge mechanism      */
-#define ISDN_INHUP       8      /* Even if incoming, close after huptimeout */
-#define ISDN_MANCHARGE  16      /* Charge Interval manually set             */
 
-/*
- * Definitions for Cisco-HDLC header.
- */
-
-#define CISCO_ADDR_UNICAST    0x0f
-#define CISCO_ADDR_BROADCAST  0x8f
-#define CISCO_CTRL            0x00
-#define CISCO_TYPE_CDP        0x2000
-#define CISCO_TYPE_SLARP      0x8035
-#define CISCO_SLARP_REQUEST   0
-#define CISCO_SLARP_REPLY     1
-#define CISCO_SLARP_KEEPALIVE 2
-
-extern void isdn_net_init(void);
-extern void isdn_net_exit(void);
-extern void isdn_net_lib_init(void);
-extern void isdn_net_lib_exit(void);
-extern void isdn_net_hangup_all(void);
-extern int isdn_net_ioctl(struct inode *, struct file *, uint, ulong);
-
-extern int register_isdn_netif(int encap, struct isdn_netif_ops *ops);
-extern int isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev);
-extern int isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev);
-
-extern int  isdn_net_dial(isdn_net_dev *idev);
-
-extern int  isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c);
-
-extern int isdn_net_stat_callback(int, isdn_ctrl *);
-extern int isdn_net_find_icall(int, int, int, setup_parm *);
-extern int isdn_net_hangup(isdn_net_dev *);
-extern int isdn_net_rcv_skb(int, struct sk_buff *);
-extern int isdn_net_dial_req(isdn_net_dev *);
-extern void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb);
-extern void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb);
-extern int isdn_net_online(isdn_net_dev *);
-
-enum {
-	ST_CHARGE_NULL,
-	ST_CHARGE_GOT_CINF,  /* got a first charge info */
-	ST_CHARGE_HAVE_CINT, /* got a second chare info and thus the timing */
-};
-
-#define ISDN_NET_MAX_QUEUE_LENGTH 2
-
-/*
- * is this particular channel busy?
- */
-static inline int
-isdn_net_dev_busy(isdn_net_dev *idev)
-{
-	if (atomic_read(&idev->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH)
-		return 0;
-	else 
-		return 1;
-}
-
-/*
- * For the given net device, this will get a non-busy channel out of the
- * corresponding bundle. The returned channel is locked.
- */
-static inline isdn_net_dev *
-isdn_net_get_locked_dev(isdn_net_local *mlp)
-{
-	unsigned long flags;
-	isdn_net_dev *idev;
-
-	spin_lock_irqsave(&mlp->online_lock, flags);
-
-	list_for_each_entry(idev, &mlp->online, online) {
-		spin_lock_bh(&idev->xmit_lock);
-		if (!isdn_net_dev_busy(idev)) {
-			/* point the head to next online channel */
-			list_del(&mlp->online);
-			list_add(&mlp->online, &idev->online);
-			goto found;
-		}
-		spin_unlock_bh(&idev->xmit_lock);
-	}
-	idev = NULL;
-
- found:
-	spin_unlock_irqrestore(&mlp->online_lock, flags);
-	return idev;
-}
-
-/*
- * add a channel to a bundle
- */
-static inline void
-isdn_net_add_to_bundle(isdn_net_local *mlp, isdn_net_dev *idev)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&mlp->online_lock, flags);
-	list_add(&idev->online, &mlp->online);
-	spin_unlock_irqrestore(&mlp->online_lock, flags);
-}
-/*
- * remove a channel from the bundle it belongs to
- */
-static inline void
-isdn_net_rm_from_bundle(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mlp->online_lock, flags);
-	//	list_del(&idev->online); FIXME
-	spin_unlock_irqrestore(&mlp->online_lock, flags);
-}
-
-/*
- * wake up the network -> net_device queue.
- * For slaves, wake the corresponding master interface.
- */
-static inline void
-isdn_net_dev_wake_queue(isdn_net_dev *idev)
-{
-	netif_wake_queue(&idev->mlp->dev);
-}
-
-static inline int
-isdn_net_bound(isdn_net_dev *idev)
-{
-	return idev->isdn_slot >= 0;
-}
+void isdn_net_init(void);
+void isdn_net_exit(void);
+void isdn_net_lib_init(void);
+void isdn_net_lib_exit(void);
+void isdn_net_hangup_all(void);
+int  isdn_net_ioctl(struct inode *, struct file *, uint, ulong);
+
+int  register_isdn_netif(int encap, struct isdn_netif_ops *ops);
+int  isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+void isdn_net_online(isdn_net_dev *idev);
+void isdn_net_offline(isdn_net_dev *idev);
+
+int  isdn_net_stat_callback(int, isdn_ctrl *);
+int  isdn_net_find_icall(int, int, int, setup_parm *);
+int  isdn_net_rcv_skb(int, struct sk_buff *);
+
+int  isdn_net_hangup(isdn_net_dev *);
+int  isdn_net_dial_req(isdn_net_dev *);
+void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb);
+void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb);
+int  isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev);
+isdn_net_dev *isdn_net_get_xmit_dev(isdn_net_local *mlp);
 
 static inline int
 put_u8(unsigned char *p, u8 x)
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	Fri Oct 18 21:03:03 2002
+++ b/drivers/isdn/i4l/isdn_net_lib.c	Fri Oct 18 21:03:03 2002
@@ -80,12 +80,13 @@
 		isdn_BUG();
 }
 
-int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg); /* FIXME */
-
+static int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg);
 static void isdn_net_tasklet(unsigned long data);
 static void isdn_net_dial_timer(unsigned long data);
 static int isdn_init_netif(struct net_device *ndev);
 static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...);
+static int isdn_net_dial(isdn_net_dev *idev);
+static int isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c);
 
 static struct fsm isdn_net_fsm;
 
@@ -151,6 +152,18 @@
 	"EV_DO_ACCEPT",
 };
 
+/* Definitions for hupflags: */
+
+#define ISDN_CHARGEHUP   4      /* We want to use the charge mechanism      */
+#define ISDN_INHUP       8      /* Even if incoming, close after huptimeout */
+#define ISDN_MANCHARGE  16      /* Charge Interval manually set             */
+
+enum {
+	ST_CHARGE_NULL,
+	ST_CHARGE_GOT_CINF,  /* got a first charge info */
+	ST_CHARGE_HAVE_CINT, /* got a second chare info and thus the timing */
+};
+
 /* ====================================================================== */
 /* Registration of ISDN network interface types                           */
 /* ====================================================================== */
@@ -208,7 +221,8 @@
 	if (lp->ops && lp->ops->cleanup)
 		lp->ops->cleanup(lp);
 
-	if (encap < 0 || encap >= ISDN_NET_ENCAP_NR) {
+	if (encap < 0 || encap >= ISDN_NET_ENCAP_NR ||
+	    !isdn_netif_ops[encap]) {
 		lp->p_encap = -1;
 		lp->ops = NULL;
 		retval = -EINVAL;
@@ -348,7 +362,6 @@
 	strcpy(idev->name, name);
 
 	tasklet_init(&idev->tlet, isdn_net_tasklet, (unsigned long) idev);
-	spin_lock_init(&idev->xmit_lock);
 	skb_queue_head_init(&idev->super_tx_queue);
 
 	idev->isdn_slot = -1;
@@ -356,7 +369,7 @@
 	idev->pre_channel = -1;
 	idev->exclusive = -1;
 
-	idev->ppp_slot = -1;
+	idev->ipppd = NULL;
 	idev->pppbind = -1;
 
 	init_timer(&idev->dial_timer);
@@ -380,6 +393,7 @@
 		mlp->magic = ISDN_NET_MAGIC;
 		INIT_LIST_HEAD(&mlp->slaves);
 		INIT_LIST_HEAD(&mlp->online);
+		spin_lock_init(&mlp->xmit_lock);
 
 		mlp->p_encap = -1;
 		isdn_net_set_encap(mlp, ISDN_NET_ENCAP_RAWIP);
@@ -1007,7 +1021,7 @@
  * Remove all network-interfaces
  */
 void
-isdn_net_exit(void)
+isdn_net_cleanup(void)
 {
 	isdn_net_dev *idev;
 	int retval;
@@ -1025,9 +1039,6 @@
 			isdn_BUG();
 	}
 	up(&sem);
-
-	// FIXME
-	isdn_net_lib_exit();
 }
 
 /* ====================================================================== */
@@ -1053,7 +1064,7 @@
 	if (lp->ops->open)
 		retval = lp->ops->open(lp);
 
-	if (!retval)
+	if (retval)
 		return retval;
 	
 	netif_start_queue(dev);
@@ -1069,7 +1080,6 @@
 /*
  * Shutdown a net-interface.
  */
-// FIXME share?
 static int
 isdn_net_close(struct net_device *dev)
 {
@@ -1083,14 +1093,14 @@
 
 	netif_stop_queue(dev);
 
-	list_for_each_safe(l, n, &lp->online) {
-		sdev = list_entry(l, isdn_net_dev, online);
+	list_for_each_safe(l, n, &lp->slaves) {
+		sdev = list_entry(l, isdn_net_dev, slaves);
 		isdn_net_hangup(sdev);
 	}
 	/* The hangup will make the refcnt drop back to
 	 * 1 (referenced by list only) soon. */
 	spin_lock_irqsave(&running_devs_lock, flags);
-	while (atomic_read(&dev->refcnt) != 1) {
+	while (atomic_read(&lp->refcnt) != 1) {
 		spin_unlock_irqrestore(&running_devs_lock, flags);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(HZ/10);
@@ -1147,29 +1157,12 @@
 }
 
 /* ====================================================================== */
-
-static void
-isdn_net_tasklet(unsigned long data)
-{
-	isdn_net_dev *idev = (isdn_net_dev *) data;
-	struct sk_buff *skb;
-
-	spin_lock_bh(&idev->xmit_lock);
-	while (!isdn_net_dev_busy(idev)) {
-		skb = skb_dequeue(&idev->super_tx_queue);
-		if (!skb)
-			break;
-		isdn_net_writebuf_skb(idev, skb);
-	}
-	spin_unlock_bh(&idev->xmit_lock);
-}
-
-/* ====================================================================== */
 /* call control state machine                                             */
 /* ====================================================================== */
 
 // FIXME
-int isdn_net_online(isdn_net_dev *idev)
+static int
+isdn_net_is_connected(isdn_net_dev *idev)
 {
 	return idev->fi.state == ST_ACTIVE;
 }
@@ -1234,7 +1227,7 @@
 	return retval;
 }
 
-int
+static int
 isdn_net_dial(isdn_net_dev *idev)
 {
 	int retval;
@@ -1250,6 +1243,127 @@
 	return retval;
 }
 
+static void
+isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
+{
+	u_short proto = ntohs(skb->protocol);
+	
+	printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
+	       dev->name,
+	       (reason != NULL) ? reason : "unknown",
+	       (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
+	
+	dst_link_failure(skb);
+}
+
+/*
+ * This is called from certain upper protocol layers (multilink ppp
+ * and x25iface encapsulation module) that want to initiate dialing
+ * themselves.
+ */
+int
+isdn_net_dial_req(isdn_net_dev *idev)
+{
+	isdn_net_local *mlp = idev->mlp;
+	/* is there a better error code? */
+	if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
+		return -EBUSY;
+
+	return isdn_net_dial(idev);
+}
+
+static void
+isdn_net_log_skb(struct sk_buff *skb, isdn_net_dev *idev)
+{
+	unsigned char *p = skb->nh.raw; /* hopefully, this was set correctly */
+	unsigned short proto = ntohs(skb->protocol);
+	int data_ofs;
+	struct ip_ports {
+		unsigned short source;
+		unsigned short dest;
+	} *ipp;
+	char addinfo[100];
+
+	data_ofs = ((p[0] & 15) * 4);
+	switch (proto) {
+	case ETH_P_IP:
+		switch (p[9]) {
+		case IPPROTO_ICMP:
+			strcpy(addinfo, "ICMP");
+			break;
+		case IPPROTO_TCP:
+		case IPPROTO_UDP:
+			ipp = (struct ip_ports *) (&p[data_ofs]);
+			sprintf(addinfo, "%s, port: %d -> %d",
+				p[9] == IPPROTO_TCP ? "TCP" : "UDP",
+				ntohs(ipp->source), ntohs(ipp->dest));
+			break;
+		default:
+			sprintf(addinfo, "type %d", p[9]);
+		}
+		printk(KERN_INFO
+		       "OPEN: %u.%u.%u.%u -> %u.%u.%u.%u %s\n",
+		       
+		       NIPQUAD(*(u32 *)(p + 12)), NIPQUAD(*(u32 *)(p + 16)),
+		       addinfo);
+		break;
+	case ETH_P_ARP:
+		printk(KERN_INFO
+		       "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
+		       NIPQUAD(*(u32 *)(p + 14)), NIPQUAD(*(u32 *)(p + 24)));
+		break;
+	default:
+		printk(KERN_INFO "OPEN: unknown proto %#x\n", proto);
+	}
+}
+
+int
+isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
+{
+	isdn_net_local *mlp = ndev->priv;
+	isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves);
+	int retval;
+
+	if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
+		goto discard;
+
+	retval = isdn_net_dial(idev);
+	if (retval == -ESRCH)
+		goto stop_queue;
+
+	if (retval < 0)
+		goto discard;
+
+	/* Log packet, which triggered dialing */
+	if (dev->net_verbose)
+		isdn_net_log_skb(skb, idev);
+
+ stop_queue:
+	netif_stop_queue(ndev);
+	return 1;
+
+ discard:
+	isdn_net_unreachable(ndev, skb, "dial rejected");
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+
+static void
+isdn_net_dial_slave(isdn_net_local *mlp)
+{
+	isdn_net_dev *idev;
+
+	if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
+		return;
+
+	list_for_each_entry(idev, &mlp->slaves, slaves) {
+		if (fsm_event(&idev->fi, EV_DO_DIAL, NULL) != -ESRCH) {
+			break;
+		}
+	}
+}
+
 static int
 accept_icall(struct fsm_inst *fi, int pr, void *arg)
 {
@@ -1640,14 +1754,12 @@
 		del_timer(&idev->dial_timer);
 	}
 
-	isdn_net_add_to_bundle(mlp, idev);
-
 	printk(KERN_INFO "%s connected\n", idev->name);
 	/* If first Chargeinfo comes before B-Channel connect,
 	 * we correct the timestamp here.
 	 */
 	idev->chargetime = jiffies;
-	
+	idev->frame_cnt = 0;
 	idev->transcount = 0;
 	idev->cps = 0;
 	idev->last_jiffies = jiffies;
@@ -1655,8 +1767,8 @@
 	if (mlp->ops->connected)
 		mlp->ops->connected(idev);
 	else
-		isdn_net_dev_wake_queue(idev);
-
+		isdn_net_online(idev);
+       
 	return 0;
 }
 
@@ -1669,11 +1781,11 @@
 	del_timer(&idev->dial_timer);
 	if (mlp->ops->disconnected)
 		mlp->ops->disconnected(idev);
+	else 
+		isdn_net_offline(idev);
 
 	printk(KERN_INFO "%s: disconnected\n", idev->name);
 	fsm_change_state(fi, ST_WAIT_DHUP);
-	isdn_net_rm_from_bundle(idev);
-	return 0;
 }
 
 static int
@@ -1748,10 +1860,7 @@
 	isdn_ctrl cmd;
 
 	del_timer(&idev->dial_timer);
-	if (!isdn_net_bound(idev)) {
-		isdn_BUG();
-		return 1;
-	}
+
 	printk(KERN_INFO "%s: local hangup\n", idev->name);
 	isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
 	return 1;
@@ -1769,7 +1878,6 @@
 	isdn_net_dev *idev = isdn_slot_idev(idx);
 
 	if (!idev) {
-		HERE;
 		return 0;
 	}
 	switch (c->command) {
@@ -1791,7 +1899,7 @@
 	}
 }
 
-int
+static int
 isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
 {
 	fsm_event(&idev->fi, pr, arg);
@@ -1873,6 +1981,326 @@
 	printk(KERN_DEBUG "%s\n", buf);
 }
 
+/* ====================================================================== */
+/* xmit path                                                              */
+/* ====================================================================== */
+
+#define ISDN_NET_MAX_QUEUE_LENGTH 2
+
+/*
+ * is this particular channel busy?
+ */
+static inline int
+isdn_net_dev_busy(isdn_net_dev *idev)
+{
+	return idev->frame_cnt >= ISDN_NET_MAX_QUEUE_LENGTH;
+}
+
+/*
+ * find out if the net_device which this mlp is belongs to is busy.
+ * It's busy iff all channels are busy.
+ * must hold mlp->xmit_lock
+ * FIXME: Use a mlp->frame_cnt instead of loop?
+ */
+static inline int
+isdn_net_local_busy(isdn_net_local *mlp)
+{
+	isdn_net_dev *idev;
+
+	list_for_each_entry(idev, &mlp->online, online) {
+		if (!isdn_net_dev_busy(idev))
+			return 0;
+	}
+	return 1;
+}
+
+/*
+ * For the given net device, this will get a non-busy channel out of the
+ * corresponding bundle.
+ * must hold mlp->xmit_lock
+ */
+isdn_net_dev *
+isdn_net_get_xmit_dev(isdn_net_local *mlp)
+{
+	isdn_net_dev *idev;
+
+	list_for_each_entry(idev, &mlp->online, online) {
+		if (!isdn_net_dev_busy(idev)) {
+			/* point the head to next online channel */
+			list_del(&mlp->online);
+			list_add(&mlp->online, &idev->online);
+			return idev;
+		}
+	}
+	return NULL;
+}
+
+/* mlp->xmit_lock must be held */
+static inline void
+isdn_net_inc_frame_cnt(isdn_net_dev *idev)
+{
+	isdn_net_local *mlp = idev->mlp;
+
+	if (isdn_net_dev_busy(idev))
+		isdn_BUG();
+		
+	idev->frame_cnt++;
+	if (isdn_net_local_busy(mlp))
+		netif_stop_queue(&mlp->dev);
+}
+
+/* mlp->xmit_lock must be held */
+static inline void
+isdn_net_dec_frame_cnt(isdn_net_dev *idev)
+{
+	isdn_net_local *mlp = idev->mlp;
+
+	idev->frame_cnt--;
+
+	if (isdn_net_dev_busy(idev))
+		isdn_BUG();
+
+	if (!skb_queue_empty(&idev->super_tx_queue))
+		tasklet_schedule(&idev->tlet);
+	else
+		netif_wake_queue(&mlp->dev);
+}
+
+static void
+isdn_net_tasklet(unsigned long data)
+{
+	isdn_net_dev *idev = (isdn_net_dev *) data;
+	isdn_net_local *mlp = idev->mlp;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mlp->xmit_lock, flags);
+	while (!isdn_net_dev_busy(idev) &&
+	       (skb = skb_dequeue(&idev->super_tx_queue))) {
+		isdn_net_writebuf_skb(idev, skb);
+	}
+	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+}
+
+/* We're good to accept (IP/whatever) traffic now */
+
+void
+isdn_net_online(isdn_net_dev *idev)
+{
+	// FIXME check we're connected
+	isdn_net_local *mlp = idev->mlp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mlp->xmit_lock, flags);
+	list_add(&idev->online, &mlp->online);
+	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+
+	netif_wake_queue(&mlp->dev);
+}
+
+/* No more (IP/whatever) traffic over the net interface */
+
+void
+isdn_net_offline(isdn_net_dev *idev)
+{
+	isdn_net_local *mlp = idev->mlp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mlp->xmit_lock, flags);
+	list_del(&idev->online);
+	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+	
+	skb_queue_purge(&idev->super_tx_queue);
+}
+
+/* 
+ * all frames sent from the (net) LL to a HL driver should go via this function
+ * must hold mlp->xmit_lock
+ */
+void
+isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
+{
+	isdn_net_local *mlp = idev->mlp;
+	int ret;
+	int len = skb->len;     /* save len */
+
+	/* before obtaining the lock the caller should have checked that
+	   the lp isn't busy */
+	if (isdn_net_dev_busy(idev)) {
+		isdn_BUG();
+		goto error;
+	}
+
+	if (!isdn_net_is_connected(idev)) {
+		isdn_BUG();
+		goto error;
+	}
+	ret = isdn_slot_write(idev->isdn_slot, skb);
+	if (ret != len) {
+		/* we should never get here */
+		printk(KERN_WARNING "%s: HL driver queue full\n", idev->name);
+		goto error;
+	}
+	
+	idev->transcount += len;
+	isdn_net_inc_frame_cnt(idev);
+	return;
+
+ error:
+	dev_kfree_skb(skb);
+	mlp->stats.tx_errors++;
+}
+
+/* A packet has successfully been sent out. */
+
+static int
+isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c)
+{
+	isdn_net_local *mlp = idev->mlp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mlp->xmit_lock, flags);
+	isdn_net_dec_frame_cnt(idev);
+	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+	mlp->stats.tx_packets++;
+	mlp->stats.tx_bytes += c->parm.length;
+	return 1;
+}
+
+/*
+ *  Based on cps-calculation, check if device is overloaded.
+ *  If so, and if a slave exists, trigger dialing for it.
+ *  If any slave is online, deliver packets using a simple round robin
+ *  scheme.
+ *
+ *  Return: 0 on success, !0 on failure.
+ */
+
+int
+isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	isdn_net_dev *idev;
+	isdn_net_local *mlp = ndev->priv;
+	unsigned long flags;
+	int retval;
+
+	ndev->trans_start = jiffies;
+
+	spin_lock_irqsave(&mlp->xmit_lock, flags);
+
+	if (list_empty(&mlp->online)) {
+		retval = isdn_net_autodial(skb, ndev);
+		goto out;
+	}
+
+	idev = isdn_net_get_xmit_dev(mlp);
+	if (!idev) {
+		printk(KERN_INFO "%s: all channels busy - requeuing!\n", ndev->name);
+		netif_stop_queue(ndev);
+		retval = 1;
+		goto out;
+	}
+
+	isdn_net_writebuf_skb(idev, skb);
+
+	/* the following stuff is here for backwards compatibility.
+	 * in future, start-up and hangup of slaves (based on current load)
+	 * should move to userspace and get based on an overall cps
+	 * calculation
+	 */
+	if (jiffies != idev->last_jiffies) {
+		idev->cps = idev->transcount * HZ / (jiffies - idev->last_jiffies);
+		idev->last_jiffies = jiffies;
+		idev->transcount = 0;
+	}
+	if (dev->net_verbose > 3)
+		printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
+
+	if (idev->cps > mlp->triggercps) {
+		if (!idev->sqfull) {
+			/* First time overload: set timestamp only */
+			idev->sqfull = 1;
+			idev->sqfull_stamp = jiffies;
+		} else {
+			/* subsequent overload: if slavedelay exceeded, start dialing */
+			if (time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay)) {
+				isdn_net_dial_slave(mlp);
+			}
+		}
+	} else {
+		if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay + 10 * HZ)) {
+			idev->sqfull = 0;
+		}
+		/* this is a hack to allow auto-hangup for slaves on moderate loads */
+		list_del(&mlp->online);
+		list_add_tail(&mlp->online, &idev->online);
+	}
+
+	retval = 0;
+ out:
+	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
+	return retval;
+}
+
+/*
+ * this function is used to send supervisory data, i.e. data which was
+ * not received from the network layer, but e.g. frames from ipppd, CCP
+ * reset frames etc.
+ * must hold mlp->xmit_lock
+ */
+void
+isdn_net_write_super(isdn_net_dev *idev, struct sk_buff *skb)
+{
+	if (!isdn_net_dev_busy(idev)) {
+		isdn_net_writebuf_skb(idev, skb);
+	} else {
+		skb_queue_tail(&idev->super_tx_queue, skb);
+	}
+}
+
+/* ====================================================================== */
+/* receive path                                                           */
+/* ====================================================================== */
+
+/*
+ * A packet arrived via ISDN. Search interface-chain for a corresponding
+ * interface. If found, deliver packet to receiver-function and return 1,
+ * else return 0.
+ */
+int
+isdn_net_rcv_skb(int idx, struct sk_buff *skb)
+{
+	isdn_net_dev *idev = isdn_slot_idev(idx);
+	isdn_net_local *mlp;
+
+	if (!idev) {
+		isdn_BUG();
+		return 0;
+	}
+	if (!isdn_net_is_connected(idev)) {
+		isdn_BUG();
+		return 0;
+	}
+
+	mlp = idev->mlp;
+
+	idev->transcount += skb->len;
+
+	mlp->stats.rx_packets++;
+	mlp->stats.rx_bytes += skb->len;
+	skb->dev = &mlp->dev;
+	skb->pkt_type = PACKET_HOST;
+	isdn_dumppkt("R:", skb->data, skb->len, 40);
+
+	mlp->ops->receive(mlp, idev, skb);
+
+	return 1;
+}
+
+/* ====================================================================== */
+/* init / exit                                                            */
+/* ====================================================================== */
+
 void
 isdn_net_lib_init(void)
 {
@@ -1882,5 +2310,7 @@
 void
 isdn_net_lib_exit(void)
 {
+	isdn_net_cleanup();
+
 	fsm_free(&isdn_net_fsm);
 }
diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
--- a/drivers/isdn/i4l/isdn_ppp.c	Fri Oct 18 21:03:06 2002
+++ b/drivers/isdn/i4l/isdn_ppp.c	Fri Oct 18 21:03:06 2002
@@ -18,635 +18,535 @@
 
 #include "isdn_common.h"
 #include "isdn_ppp.h"
+#include "isdn_ppp_ccp.h"
 #include "isdn_net.h"
 
-/* Prototypes */
-static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
-static int isdn_ppp_closewait(int slot);
-static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
-				 struct sk_buff *skb, int proto);
-static int isdn_ppp_if_get_unit(char *namebuf);
-static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
-				struct ippp_struct *,struct ippp_struct *,int *proto);
-static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
-				struct sk_buff *skb,int proto);
-static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
-	struct ippp_struct *is,struct ippp_struct *master,int type);
-static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
-	 struct sk_buff *skb);
+static struct sk_buff *
+isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask);
 
-/* New CCP stuff */
-static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
-static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
-				    unsigned char code, unsigned char id,
-				    unsigned char *data, int len);
-static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
-static void isdn_ppp_ccp_reset_free(struct ippp_struct *is);
-static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
-					  unsigned char id);
-static void isdn_ppp_ccp_timer_callback(unsigned long closure);
-static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
-						      unsigned char id);
-static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
-				     struct isdn_ppp_resetparams *rp);
-static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
-					unsigned char id);
+static int
+isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *);
 
+/* ====================================================================== */
+/* IPPPD handling                                                         */
+/* ====================================================================== */
+
+/* We use reference counting for struct ipppd. It is alloced on
+ * open() on /dev/ipppX and saved into file->private, making for one
+ * reference. release() will release this reference, after all other
+ * references are gone, the destructor frees it.
+ *
+ * Another reference is taken by isdn_ppp_bind() and freed by
+ * isdn_ppp_unbind(). The callbacks from isdn_net_lib.c happen only
+ * between isdn_ppp_bind() and isdn_ppp_unbind(), i.e. access to 
+ * idev->ipppd is safe without further locking.
+ */
 
+#define IPPPD_DEBUG
+
+#ifdef IPPPD_DEBUG
+#define ipppd_debug(i, fmt, arg...) \
+        printk(KERN_DEBUG "ipppd %p minor %d state %#x %s: " fmt "\n", (i), \
+               (i)->minor, (i)->state, __FUNCTION__ , ## arg)
+#else
+#define ipppd_debug(...) do { } while (0)
+#endif
 
-#ifdef CONFIG_ISDN_MPP
-static ippp_bundle * isdn_ppp_bundle_arr = NULL;
- 
-static int isdn_ppp_mp_bundle_array_init(void);
-static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to);
-static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *idev, 
-				struct sk_buff *skb);
-static void isdn_ppp_mp_cleanup(isdn_net_local *lp );
+/* ipppd::flags */
+enum {
+	IPPPD_FL_HUP    = 0x01,
+	IPPPD_FL_WAKEUP = 0x02,
+};
 
-static int isdn_ppp_bundle(struct ippp_struct *, int unit);
-#endif	/* CONFIG_ISDN_MPP */
-  
-char *isdn_ppp_revision = "$Revision: 1.85.6.9 $";
+/* ipppd::state */
+enum {
+	IPPPD_ST_OPEN,
+	IPPPD_ST_ASSIGNED,
+	IPPPD_ST_CONNECTED,
+};
 
-static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
+struct ipppd {
+	struct list_head ipppds;
+	int state;
+	int flags;
+	struct sk_buff_head rq;
+	wait_queue_head_t wq;
+	struct isdn_net_dev_s *idev;
+	int unit;
+	int minor;
+	unsigned long debug;
+	atomic_t refcnt;
+};
 
-static struct isdn_ppp_compressor *ipc_head = NULL;
+/* ====================================================================== */
+
+static spinlock_t ipppds_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(ipppds);
 
-/*
- * frame log (debug)
- */
 static void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
+ipppd_destroy(struct ipppd *ipppd)
 {
-	int cnt,
-	 j,
-	 i;
-	char buf[80];
+	HERE;
 
-	if (len < maxlen)
-		maxlen = len;
+	skb_queue_purge(&ipppd->rq);
+	kfree(ipppd);
+}
 
-	for (i = 0, cnt = 0; cnt < maxlen; i++) {
-		for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
-			sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
-		printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
-	}
+static inline struct ipppd *
+ipppd_get(struct ipppd *ipppd)
+{
+	atomic_inc(&ipppd->refcnt);
+	printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt));
+	return ipppd;
 }
 
-/*
- * unbind isdn_net_local <=> ippp-device
- * note: it can happen, that we hangup/free the master before the slaves
- *       in this case we bind another lp to the master device
- */
-static void
-isdn_ppp_free(isdn_net_dev *idev)
+static inline void 
+ipppd_put(struct ipppd *ipppd)
+{
+	printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt));
+
+	if (atomic_dec_and_test(&ipppd->refcnt))
+		ipppd_destroy(ipppd);
+}
+
+/* ====================================================================== */
+/* char dev ops                                                           */
+
+/* --- open ------------------------------------------------------------- */
+
+static int
+ipppd_open(struct inode *ino, struct file *file)
 {
 	unsigned long flags;
-	struct ippp_struct *is;
+	unsigned int minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
+	struct ipppd *ipppd;
 
-	if (idev->ppp_slot < 0 || idev->ppp_slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
-		       __FUNCTION__ , idev->ppp_slot);
-		return;
-	}
+	ipppd = kmalloc(sizeof(*ipppd), GFP_KERNEL);
+	if (!ipppd)
+		return -ENOMEM;
 
-	save_flags(flags);
-	cli();
+	memset(ipppd, 0, sizeof(*ipppd));
+	atomic_set(&ipppd->refcnt, 0);
+	
+	/* file->private_data holds a reference */
+	file->private_data = ipppd_get(ipppd);
 
-#ifdef CONFIG_ISDN_MPP
-	spin_lock(&idev->pb->lock);
-#endif
-	isdn_net_rm_from_bundle(idev);
-#ifdef CONFIG_ISDN_MPP
-	if (lp->netdev->pb->ref_ct == 1)	/* last link in queue? */
-		isdn_ppp_mp_cleanup(lp);
+	ipppd->unit = -1;          /* set by isdn_ppp_bind */
+	ipppd->minor = minor;
+	ipppd->state = IPPPD_ST_OPEN;
+	init_waitqueue_head(&ipppd->wq);
+	skb_queue_head_init(&ipppd->rq);
+
+	spin_lock_irqsave(&ipppds, flags);
+	list_add(&ipppd->ipppds, &ipppds);
+	spin_unlock_irqrestore(&ipppds, flags);
+	
+	ipppd_debug(ipppd, "minor %d", minor);
 
-	lp->netdev->pb->ref_ct--;
-	spin_unlock(&lp->netdev->pb->lock);
-#endif /* CONFIG_ISDN_MPP */
-	if (idev->ppp_slot < 0 || idev->ppp_slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
-		       __FUNCTION__ , idev->ppp_slot);
-		restore_flags(flags);
-		return;
-	}
-	is = ippp_table[idev->ppp_slot];
-	if ((is->state & IPPP_CONNECT))
-		isdn_ppp_closewait(idev->ppp_slot);	/* force wakeup on ippp device */
-	else if (is->state & IPPP_ASSIGNED)
-		is->state = IPPP_OPEN;	/* fallback to 'OPEN but not ASSIGNED' state */
+	return 0;
+}
 
-	if (is->debug & 0x1)
-		printk(KERN_DEBUG "isdn_ppp_free %d %p\n", idev->ppp_slot, is->idev);
+/* --- release  --------------------------------------------------------- */
 
-	is->idev = NULL;          /* link is down .. set lp to NULL */
-	idev->ppp_slot = -1;      /* is this OK ?? */
+static int
+ipppd_release(struct inode *ino, struct file *file)
+{
+	unsigned long flags;
+	struct ipppd *ipppd = file->private_data;
 
-	restore_flags(flags);
-	return;
+	ipppd_debug(ipppd, "");
+
+	if (ipppd->state == IPPPD_ST_CONNECTED)
+		isdn_net_hangup(ipppd->idev);
+
+	spin_lock_irqsave(&ipppds, flags);
+	list_del(&ipppd->ipppds);
+	spin_unlock_irqrestore(&ipppds, flags);
+
+	ipppd_put(ipppd);
+
+	return 0;
 }
 
-/*
- * bind isdn_net_local <=> ippp-device
- */
-int
-isdn_ppp_bind(isdn_net_dev *idev)
+/* --- read ------------------------------------------------------------- */
+
+/* read() is always non blocking */
+static ssize_t
+ipppd_read(struct file *file, char *buf, size_t count, loff_t *off)
 {
-	int i;
-	int unit = 0;
-	long flags;
-	struct ippp_struct *is;
+	struct ipppd *is;
+	struct sk_buff *skb;
 	int retval;
 
-	save_flags(flags);
-	cli();
-	if (idev->pppbind < 0) {  /* device bound to ippp device ? */
-		struct list_head *l;
-		char exclusive[ISDN_MAX_CHANNELS];	/* exclusive flags */
-		memset(exclusive, 0, ISDN_MAX_CHANNELS);
-		/* step through net devices to find exclusive minors */
-		list_for_each(l, &isdn_net_devs) {
-			isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
-			if (p->pppbind >= 0)
-				exclusive[p->pppbind] = 1;
-		}
-		/*
-		 * search a free device / slot
-		 */
-		for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-			if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) {	/* OPEN, but not connected! */
-				break;
-			}
-		}
-	} else {
-		for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-			if (ippp_table[i]->minor == idev->pppbind &&
-			    (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
-				break;
-		}
-	}
+	if (off != &file->f_pos)
+		return -ESPIPE;
+	
+	is = file->private_data;
 
-	if (i >= ISDN_MAX_CHANNELS) {
-		restore_flags(flags);
-		printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
-		retval = -1;
+	skb = skb_dequeue(&is->rq);
+	if (!skb) {
+		retval = -EAGAIN;
 		goto out;
 	}
-	unit = isdn_ppp_if_get_unit(idev->name);	/* get unit number from interface name .. ugly! */
-	if (unit < 0) {
-		printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", idev->name);
-		retval = -1;
-		goto out;
+	if (skb->len > count) {
+		retval = -EMSGSIZE;
+		goto out_free;
 	}
-	
-	idev->ppp_slot = i;
-	is = ippp_table[i];
-	is->idev = idev;
-	is->unit = unit;
-	is->state = IPPP_OPEN | IPPP_ASSIGNED;	/* assigned to a netdevice but not connected */
-#ifdef CONFIG_ISDN_MPP
-	retval = isdn_ppp_mp_init(lp, NULL);
-	if (retval < 0)
-		goto out;
-#endif /* CONFIG_ISDN_MPP */
-
-	retval = idev->ppp_slot;
+	if (copy_to_user(buf, skb->data, skb->len)) {
+		retval = -EFAULT;
+		goto out_free;
+	}
+	retval = skb->len;
 
+ out_free:
+	dev_kfree_skb(skb);
  out:
-	restore_flags(flags);
 	return retval;
 }
 
-/*
- * kick the ipppd on the device
- * (wakes up daemon after B-channel connect)
- */
+/* --- write ------------------------------------------------------------ */
 
-static void
-isdn_ppp_wakeup_daemon(isdn_net_dev *idev)
+/* write() is always non blocking */
+static ssize_t
+ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off)
 {
-	if (idev->ppp_slot < 0 || idev->ppp_slot >= ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
-		       __FUNCTION__, idev->ppp_slot);
-		return;
-	}
-	ippp_table[idev->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
-	wake_up_interruptible(&ippp_table[idev->ppp_slot]->wq);
-}
+	isdn_net_dev *idev;
+	struct ipppd *ipppd;
+	struct sk_buff *skb;
+	char *p;
+	int retval;
+	u16 proto;
 
-/*
- * there was a hangup on the netdevice
- * force wakeup of the ippp device
- * go into 'device waits for release' state
- */
-static int
-isdn_ppp_closewait(int slot)
-{
-	struct ippp_struct *is;
+	if (off != &file->f_pos)
+		return -ESPIPE;
 
-	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "%s: slot(%d) out of range\n",
-		       __FUNCTION__ , slot);
-		return 0;
-	}
-	is = ippp_table[slot];
-	if (is->state)
-		wake_up_interruptible(&is->wq);
-	is->state = IPPP_CLOSEWAIT;
-	return 1;
-}
+	ipppd = file->private_data;
+	ipppd_debug(ipppd, "count = %d", count);
 
-/*
- * isdn_ppp_find_slot / isdn_ppp_free_slot
- */
+	if (ipppd->state != IPPPD_ST_CONNECTED) {
+		retval = -ENOTCONN;
+		goto out;
+	}
 
-static int
-isdn_ppp_get_slot(void)
-{
-	int i;
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		if (!ippp_table[i]->state)
-			return i;
+	idev = ipppd->idev;
+	if (!idev) {
+		isdn_BUG();
+		retval = -ENODEV;
+		goto out;
 	}
-	return -1;
+	/* Daemon needs to send at least full header, AC + proto */
+	if (count < 4) {
+		retval = -EMSGSIZE;
+		goto out;
+	}
+	skb = isdn_ppp_dev_alloc_skb(idev, count, GFP_KERNEL);
+	if (!skb) {
+		retval = -ENOMEM;
+		goto out;
+	}
+	p = skb_put(skb, count);
+	if (copy_from_user(p, buf, count)) {
+		kfree_skb(skb);
+		retval = -EFAULT;
+		goto out;
+	}
+	/* Don't reset huptimer for LCP packets. (Echo requests). */
+	proto = PPP_PROTOCOL(p);
+	if (proto != PPP_LCP)
+		idev->huptimer = 0;
+	
+	/* Keeps CCP/compression states in sync */
+	switch (proto) {
+	case PPP_CCP:
+		ippp_ccp_send_ccp(idev->mlp->ccp, skb);
+		break;
+	case PPP_CCPFRAG:
+		ippp_ccp_send_ccp(idev->ccp, skb);
+		break;
+	}
+	/* FIXME: Somewhere we need protection against the
+	 * queue growing too large */
+	isdn_net_write_super(idev, skb);
+
+	retval = count;
+	
+ out:
+	return retval;
 }
 
-/*
- * isdn_ppp_open
- */
+/* --- poll ------------------------------------------------------------- */
 
-static int
-isdn_ppp_open(struct inode *ino, struct file *file)
+static unsigned int
+ipppd_poll(struct file *file, poll_table * wait)
 {
-	uint minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
-	int slot;
-	struct ippp_struct *is;
+	unsigned int mask;
+	struct ipppd *is;
 
-	slot = isdn_ppp_get_slot();
-	if (slot < 0) {
-		return -EBUSY;
-	}
-	is = file->private_data = ippp_table[slot];
+	is = file->private_data;
 
-	printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, minor, is->state);
+	ipppd_debug(is, "");
 
-	/* compression stuff */
-	is->link_compressor   = is->compressor = NULL;
-	is->link_decompressor = is->decompressor = NULL;
-	is->link_comp_stat    = is->comp_stat = NULL;
-	is->link_decomp_stat  = is->decomp_stat = NULL;
-	is->compflags = 0;
+	/* just registers wait_queue hook. This doesn't really wait. */
+	poll_wait(file, &is->wq, wait);
 
-	is->reset = isdn_ppp_ccp_reset_alloc(is);
+	if (is->flags & IPPPD_FL_HUP) {
+		mask = POLLHUP;
+		goto out;
+	}
+	/* we're always ready to send .. */
+	mask = POLLOUT | POLLWRNORM;
 
-	is->idev = NULL;
-	is->mp_seqno = 0;       /* MP sequence number */
-	is->pppcfg = 0;         /* ppp configuration */
-	is->mpppcfg = 0;        /* mppp configuration */
-	is->last_link_seqno = -1;	/* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
-	is->unit = -1;          /* set, when we have our interface */
-	is->mru = 1524;         /* MRU, default 1524 */
-	is->maxcid = 16;        /* VJ: maxcid */
-	is->tk = current;
-	init_waitqueue_head(&is->wq);
-	is->minor = minor;
-#ifdef CONFIG_ISDN_PPP_VJ
 	/*
-	 * VJ header compression init
+	 * if IPPP_FL_WAKEUP is set we return even if we have nothing to read
 	 */
-	is->slcomp = slhc_init(16, 16);	/* not necessary for 2. link in bundle */
-#endif
-
-	is->state = IPPP_OPEN;
-	isdn_lock_drivers();
-
-	return 0;
-}
-
-/*
- * release ippp device
- */
-static int
-isdn_ppp_release(struct inode *ino, struct file *file)
-{
-	uint minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
-	struct ippp_struct *is;
-
-	lock_kernel();
-
-	is = file->private_data;
-
-	if (is->debug & 0x1)
-		printk(KERN_DEBUG "ippp: release, minor: %d %p\n", minor, is->idev);
-
-	if (is->idev) {           /* a lp address says: this link is still up */
-		/*
-		 * isdn_net_hangup() calls isdn_ppp_free()
-		 * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
-		 * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
-		 */
-		is->state &= ~IPPP_CONNECT;
-		isdn_net_hangup(is->idev);
+	if (!skb_queue_empty(&is->rq) || is->flags & IPPPD_FL_WAKEUP) {
+		is->flags &= ~IPPPD_FL_WAKEUP;
+		mask |= POLLIN | POLLRDNORM;
+		set_current_state(TASK_INTERRUPTIBLE); // FIXME
+		schedule_timeout(HZ);
 	}
-	skb_queue_purge(&is->rq);
 
-#ifdef CONFIG_ISDN_PPP_VJ
-/* TODO: if this was the previous master: link the slcomp to the new master */
-	slhc_free(is->slcomp);
-	is->slcomp = NULL;
-#endif
-
-/* TODO: if this was the previous master: link the the stuff to the new master */
-	if(is->comp_stat)
-		is->compressor->free(is->comp_stat);
-	if(is->link_comp_stat)
-		is->link_compressor->free(is->link_comp_stat);
-	if(is->link_decomp_stat)
-		is->link_decompressor->free(is->link_decomp_stat);
-	if(is->decomp_stat)
-		is->decompressor->free(is->decomp_stat);
-        is->compressor   = is->link_compressor   = NULL;
-        is->decompressor = is->link_decompressor = NULL;
-	is->comp_stat    = is->link_comp_stat    = NULL;
-        is->decomp_stat  = is->link_decomp_stat  = NULL;
-
-	/* Clean up if necessary */
-	if(is->reset)
-		isdn_ppp_ccp_reset_free(is);
-
-	/* this slot is ready for new connections */
-	is->state = 0;
-
-	isdn_unlock_drivers();
-	
-	unlock_kernel();
-	return 0;
+ out:
+	return mask;
 }
 
-/*
- * get_arg .. ioctl helper
- */
+/* --- ioctl ------------------------------------------------------------ */
+
+/* get_arg .. ioctl helper */
 static int
-get_arg(void *b, void *val, int len)
+get_arg(unsigned long arg, void *val, int len)
 {
-	if (len <= 0)
-		len = sizeof(void *);
-	if (copy_from_user((void *) val, b, len))
+	if (copy_from_user((void *) val, (void *) arg, len))
 		return -EFAULT;
 	return 0;
 }
 
-/*
- * set arg .. ioctl helper
- */
+/* set arg .. ioctl helper */
 static int
-set_arg(void *b, void *val,int len)
+set_arg(unsigned long arg, void *val,int len)
 {
-	if (copy_to_user(b, (void *) val, len))
+	if (copy_to_user((void *) arg, (void *) val, len))
 		return -EFAULT;
 	return 0;
 }
 
-/*
- * ippp device ioctl
- */
 static int
-isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned long arg)
+ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
+	    unsigned long arg)
 {
 	isdn_net_dev *idev;
 	unsigned long val;
-	int r,i,j;
-	struct ippp_struct *is;
+	int r;
+	struct ipppd *is;
 	struct isdn_ppp_comp_data data;
+	unsigned int cfg;
 
-	is = (struct ippp_struct *) file->private_data;
+	is = file->private_data;
 	idev = is->idev;
 
-	if (is->debug & 0x1)
-		printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", is->minor, cmd, is->state);
-
-	if (!(is->state & IPPP_OPEN))
-		return -EINVAL;
+	ipppd_debug(is, "cmd %#x", cmd);
 
 	switch (cmd) {
-		case PPPIOCBUNDLE:
+	case PPPIOCBUNDLE:
 #ifdef CONFIG_ISDN_MPP
-			if (!(is->state & IPPP_CONNECT))
-				return -EINVAL;
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
-				return r;
-			printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
-			       (int) is->minor, (int) is->unit, (int) val);
-			return isdn_ppp_bundle(is, val);
-#else
-			return -1;
-#endif
+		if (is->state != IPPPD_ST_CONNECTED) {
+			r = -EINVAL;
 			break;
-		case PPPIOCGUNIT:	/* get ppp/isdn unit number */
-			if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
-				return r;
-			break;
-		case PPPIOCGIFNAME:
-			if(!idev)
-				return -EINVAL;
-			if ((r = set_arg((void *) arg, idev->name, strlen(idev->name))))
-				return r;
-			break;
-		case PPPIOCGMPFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
-				return r;
-			break;
-		case PPPIOCSMPFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
-				return r;
-			is->mpppcfg = val;
-			break;
-		case PPPIOCGFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
-				return r;
-			break;
-		case PPPIOCSFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
-				return r;
-			}
-			if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
-				if (idev) {
-					/* OK .. we are ready to send buffers */
-					isdn_net_dev_wake_queue(idev);
-				}
-			}
-			is->pppcfg = val;
+		}
+		r = get_arg(arg, &val, sizeof(val));
+		if (r)
 			break;
-		case PPPIOCGIDLE:	/* get idle time information */
-			if (idev) {
-				struct ppp_idle pidle;
-				pidle.xmit_idle = pidle.recv_idle = idev->huptimer;
-				if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
-					 return r;
-			}
+
+		printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
+		       is->minor, is->unit, val);
+		r = isdn_ppp_bundle(is, val);
+#else
+		r = -EINVAL;
+#endif
+		break;
+	case PPPIOCGUNIT:	/* get ppp/isdn unit number */
+		r = set_arg(arg, &is->unit, sizeof(is->unit));
+		break;
+	case PPPIOCGDEBUG:
+		r = set_arg(arg, &is->debug, sizeof(is->debug));
+		break;
+	case PPPIOCSDEBUG:
+		r = get_arg(arg, &val, sizeof(val));
+		if (r)
+			break;
+		is->debug = val;
+		if (idev) {
+			idev->debug = val;
+			idev->mlp->debug = val;
+		}
+		break;
+	case PPPIOCGCOMPRESSORS:
+	{
+		unsigned long protos[8];
+		ippp_ccp_get_compressors(protos);
+		r = set_arg(arg, protos, sizeof(protos));
+		break;
+	}
+	default:
+		r = -ENOTTY;
+		break;
+	}
+
+	if (r != -ENOTTY)
+		goto out;
+
+	if (!idev) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	switch (cmd) {
+	case PPPIOCGIFNAME:
+		r = set_arg(arg, idev->name, strlen(idev->name)+1);
+		break;
+	case PPPIOCGMPFLAGS:	/* get configuration flags */
+		r = set_arg(arg, &idev->mlp->mpppcfg, sizeof(idev->mlp->mpppcfg));
+		break;
+	case PPPIOCSMPFLAGS:	/* set configuration flags */
+		r = get_arg(arg, &val, sizeof(val));
+		if (r)
 			break;
-		case PPPIOCSMRU:	/* set receive unit size for PPP */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
-				return r;
-			is->mru = val;
+		idev->mlp->mpppcfg = val;
+		break;
+	case PPPIOCGFLAGS:	/* get configuration flags */
+		cfg = idev->pppcfg | ippp_ccp_get_flags(idev->ccp);
+		r = set_arg(arg, &cfg, sizeof(cfg));
+		break;
+	case PPPIOCSFLAGS:	/* set configuration flags */
+		r = get_arg(arg, &val, sizeof(val));
+		if (r)
 			break;
-		case PPPIOCSMPMRU:
+		if ((val & SC_ENABLE_IP) && !(idev->pppcfg & SC_ENABLE_IP)) {
+			idev->pppcfg = val;
+			/* OK .. we are ready to send buffers */
+			isdn_net_online(idev);
 			break;
-		case PPPIOCSMPMTU:
+		}
+		idev->pppcfg = val;
+		break;
+	case PPPIOCGIDLE:	/* get idle time information */
+	{
+		struct ppp_idle pidle;
+		pidle.xmit_idle = pidle.recv_idle = idev->huptimer;
+		r = set_arg(arg, &pidle,sizeof(pidle));
+		break;
+	}
+	case PPPIOCSMRU:	/* set receive unit size for PPP */
+		r = get_arg(arg, &val, sizeof(val));
+		if (r)
 			break;
-		case PPPIOCSMAXCID:	/* set the maximum compression slot id */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
-				return r;
-			val++;
-			if (is->maxcid != val) {
-#ifdef CONFIG_ISDN_PPP_VJ
-				struct slcompress *sltmp;
-#endif
-				if (is->debug & 0x1)
-					printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
-				is->maxcid = val;
+		r = ippp_ccp_set_mru(idev->ccp, val);
+		break;
+	case PPPIOCSMPMRU:
+		break;
+	case PPPIOCSMPMTU:
+		break;
 #ifdef CONFIG_ISDN_PPP_VJ
-				sltmp = slhc_init(16, val);
-				if (!sltmp) {
-					printk(KERN_ERR "ippp, can't realloc slhc struct\n");
-					return -ENOMEM;
-				}
-				if (is->slcomp)
-					slhc_free(is->slcomp);
-				is->slcomp = sltmp;
-#endif
-			}
-			break;
-		case PPPIOCGDEBUG:
-			if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
-				return r;
-			break;
-		case PPPIOCSDEBUG:
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
-				return r;
-			is->debug = val;
+	case PPPIOCSMAXCID:	/* set the maximum compression slot id */
+	{
+		struct slcompress *sltmp;
+		r = get_arg(arg, &val, sizeof(val));
+		if (r)
+			break;
+		val++;
+		sltmp = slhc_init(16, val);
+		if (!sltmp) {
+			r = -ENOMEM;
 			break;
-		case PPPIOCGCOMPRESSORS:
-			{
-				unsigned long protos[8] = {0,};
-				struct isdn_ppp_compressor *ipc = ipc_head;
-				while(ipc) {
-					j = ipc->num / (sizeof(long)*8);
-					i = ipc->num % (sizeof(long)*8);
-					if(j < 8)
-						protos[j] |= (0x1<<i);
-					ipc = ipc->next;
-				}
-				if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
-					return r;
-			}
+		}
+		if (idev->mlp->slcomp)
+			slhc_free(idev->mlp->slcomp);
+		idev->mlp->slcomp = sltmp;
+		r = 0;
+		break;
+	}
+#endif
+	case PPPIOCSCOMPRESSOR:
+		r = get_arg(arg, &data, sizeof(data));
+		if (r)
 			break;
-		case PPPIOCSCOMPRESSOR:
-			if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
-				return r;
-			return isdn_ppp_set_compressor(is, &data);
-		case PPPIOCGCALLINFO:
-			{
-				isdn_net_local *mlp;
-				struct isdn_net_phone *phone;
-				struct pppcallinfo pci;
-				int i;
-				memset((char *) &pci,0,sizeof(struct pppcallinfo));
-				if(idev) {
-					mlp = idev->mlp;
-					strncpy(pci.local_num, mlp->msn, 63);
-					i = 0;
-					list_for_each_entry(phone, &mlp->phone[1], list) {
-						if (i++ == idev->dial) {
-							strncpy(pci.remote_num,phone->num,63);
-							break;
-						}
-					}
-					pci.charge_units = idev->charge;
-					if(idev->outgoing)
-						pci.calltype = CALLTYPE_OUTGOING;
-					else
-						pci.calltype = CALLTYPE_INCOMING;
-					if(mlp->flags & ISDN_NET_CALLBACK)
-						pci.calltype |= CALLTYPE_CALLBACK;
-				}
-				return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
+		r = isdn_ppp_set_compressor(idev, &data);
+		break;
+	case PPPIOCGCALLINFO:
+	{
+		isdn_net_local *mlp;
+		struct isdn_net_phone *phone;
+		struct pppcallinfo pci;
+		int i;
+		memset(&pci, 0, sizeof(pci));
+
+		mlp = idev->mlp;
+		strncpy(pci.local_num, mlp->msn, 63);
+		i = 0;
+		list_for_each_entry(phone, &mlp->phone[1], list) {
+			if (i++ == idev->dial) {
+				strncpy(pci.remote_num,phone->num,63);
+				break;
 			}
-		default:
-			break;
-	}
-	return 0;
-}
-
-static unsigned int
-isdn_ppp_poll(struct file *file, poll_table * wait)
-{
-	unsigned int mask;
-	struct ippp_struct *is;
-
-	is = file->private_data;
-
-	if (is->debug & 0x2)
-		printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
-				minor(file->f_dentry->d_inode->i_rdev));
-
-	/* just registers wait_queue hook. This doesn't really wait. */
-	poll_wait(file, &is->wq, wait);
-
-	if (!(is->state & IPPP_OPEN)) {
-		if(is->state == IPPP_CLOSEWAIT) {
-			mask = POLLHUP;
-			goto out;
 		}
-		printk(KERN_DEBUG "isdn_ppp: device not open\n");
-		mask = POLLERR;
-		goto out;
+		pci.charge_units = idev->charge;
+		if (idev->outgoing)
+			pci.calltype = CALLTYPE_OUTGOING;
+		else
+			pci.calltype = CALLTYPE_INCOMING;
+		if (mlp->flags & ISDN_NET_CALLBACK)
+			pci.calltype |= CALLTYPE_CALLBACK;
+		r = set_arg(arg, &pci, sizeof(pci));
+		break;
 	}
-	/* we're always ready to send .. */
-	mask = POLLOUT | POLLWRNORM;
-
-	/*
-	 * if IPPP_NOBLOCK is set we return even if we have nothing to read
-	 */
-	if (!skb_queue_empty(&is->rq) || is->state & IPPP_NOBLOCK) {
-		is->state &= ~IPPP_NOBLOCK;
-		mask |= POLLIN | POLLRDNORM;
+	default:
+		r = -ENOTTY;
+		break;
 	}
-
  out:
-	return mask;
+	return r;
 }
 
-/*
- *  fill up isdn_ppp_read() queue ..
- */
+/* --- fops ------------------------------------------------------------- */
+
+struct file_operations isdn_ppp_fops =
+{
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.read		= ipppd_read,
+	.write		= ipppd_write,
+	.poll		= ipppd_poll,
+	.ioctl		= ipppd_ioctl,
+	.open		= ipppd_open,
+	.release	= ipppd_release,
+};
+
+/* --- ipppd_queue_read ------------------------------------------------- */
+
+/* Queue packets for ipppd to read(). */
 
 static int
-isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
+ipppd_queue_read(struct ipppd *is, u16 proto, unsigned char *buf, int len)
 {
 	struct sk_buff *skb;
 	unsigned char *p;
-	struct ippp_struct *is;
-
-	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-		printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
-		return 0;
-	}
-	is = ippp_table[slot];
+	int retval;
 
-	if (!(is->state & IPPP_CONNECT)) {
-		printk(KERN_DEBUG "ippp: device not activated.\n");
-		return 0;
+	if (is->state != IPPPD_ST_CONNECTED) {
+		printk(KERN_DEBUG "ippp: device not connected.\n");
+		retval = -ENOTCONN;
+		goto out;
 	}
 	if (skb_queue_len(&is->rq) > IPPP_MAX_RQ_LEN) {
 		printk(KERN_WARNING "ippp: Queue is full\n");
-		return 0;
+		retval = -EBUSY;
+		goto out;
 	}
 	skb = dev_alloc_skb(len + 4);
 	if (!skb) {
 		printk(KERN_WARNING "ippp: Can't alloc buf\n");
-		return 0;
+		retval = -ENOMEM;
+		goto out;
 	}
 	p = skb_put(skb, 4);
 	p += put_u8(p, PPP_ALLSTATIONS);
@@ -655,151 +555,274 @@
 	memcpy(skb_put(skb, len), buf, len);
 
 	skb_queue_tail(&is->rq, skb);
-	wake_up_interruptible(&is->wq);
+	wake_up(&is->wq);
 
-	return len;
+	retval = len;
+ out:
+	return retval;
 }
 
+/* ====================================================================== */
+
+/* Prototypes */
+static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
+				 struct sk_buff *skb, int proto);
+static int isdn_ppp_if_get_unit(char *namebuf);
+
+static void
+isdn_ppp_dev_push_header(void *priv, struct sk_buff *skb, u16 proto);
+
+static void
+isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb);
+
+static struct sk_buff *
+isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask);
+
+static void
+isdn_ppp_lp_push_header(void *priv, struct sk_buff *skb, u16 proto);
+
+/* New CCP stuff */
+static void
+isdn_ppp_dev_kick_up(void *priv);
+
+#ifdef CONFIG_ISDN_MPP
+static ippp_bundle * isdn_ppp_bundle_arr = NULL;
+ 
+static int isdn_ppp_mp_bundle_array_init(void);
+static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to);
+static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *idev, 
+				struct sk_buff *skb);
+static void isdn_ppp_mp_cleanup(isdn_net_local *lp );
+
+static int isdn_ppp_bundle(struct ipppd *, int unit);
+#endif	/* CONFIG_ISDN_MPP */
+  
+char *isdn_ppp_revision = "$Revision: 1.85.6.9 $";
+
 /*
- * read() .. non-blocking: ipppd calls it only after select()
- *           reports, that there is data
+ * frame log (debug)
  */
-
-static ssize_t
-isdn_ppp_read(struct file *file, char *buf, size_t count, loff_t *off)
+void
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
 {
-	struct ippp_struct *is;
-	struct sk_buff *skb;
-	int retval;
+	int cnt,
+	 j,
+	 i;
+	char buf[80];
 
-	if (off != &file->f_pos)
-		return -ESPIPE;
-	
-	is = file->private_data;
+	if (len < maxlen)
+		maxlen = len;
 
-	if (!(is->state & IPPP_OPEN)) {
-		retval = 0;
-		goto out;
-	}
-	skb = skb_dequeue(&is->rq);
-	if (!skb) {
-		retval = -EAGAIN;
-		goto out;
-	}
-	if (skb->len > count) {
-		retval = -EMSGSIZE;
-		goto out_free;
+	for (i = 0, cnt = 0; cnt < maxlen; i++) {
+		for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
+			sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
+		printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
 	}
-	if (copy_to_user(buf, skb->data, skb->len)) {
-		retval = -EFAULT;
-		goto out_free;
+}
+
+
+static void
+isdn_ppp_push_header(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+{
+	unsigned char *p;
+
+	if (skb_headroom(skb) < 4) {
+		isdn_BUG();
+		return;
 	}
-	retval = skb->len;
 
- out_free:
-	dev_kfree_skb(skb);
- out:
-	return retval;
+	if ((idev->pppcfg & SC_COMP_PROT) && proto <= 0xff)
+		put_u8(skb_push(skb, 1), proto);
+	else
+		put_u16(skb_push(skb, 2), proto);
+
+	if (idev->pppcfg & SC_COMP_AC)
+		return;
+
+	p = skb_push(skb, 2);	
+	p += put_u8(p, PPP_ALLSTATIONS);
+	p += put_u8(p, PPP_UI);
 }
 
 /*
- * ipppd wanna write a packet to the card .. non-blocking
+ * unbind isdn_net_local <=> ippp-device
+ * note: it can happen, that we hangup/free the master before the slaves
+ *       in this case we bind another lp to the master device
  */
-
-static ssize_t
-isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
+static void
+isdn_ppp_unbind(isdn_net_dev *idev)
 {
-	isdn_net_dev *idev;
-	struct ippp_struct *is;
-	int proto;
-	unsigned char protobuf[4];
-	int retval;
+	struct ipppd *is = idev->ipppd;
+	
+	if (!is) {
+		isdn_BUG();
+		return;
+	}
 
-	if (off != &file->f_pos)
-		return -ESPIPE;
+	ipppd_debug(is, "");
 
-	lock_kernel();
+	if (is->state != IPPPD_ST_ASSIGNED)
+		isdn_BUG();
 
-	is = file->private_data;
+	is->state = IPPPD_ST_OPEN;
 
-	if (!(is->state & IPPP_CONNECT)) {
-		retval = 0;
-		goto out;
-	}
+	/* is->idev will be invalid shortly */
+	ippp_ccp_free(idev->ccp);
 
-	/* -> push it directly to the lowlevel interface */
+	is->idev = NULL;
+	/* lose the reference we took on isdn_ppp_bind */
+	ipppd_put(is); 
+	idev->ipppd = NULL;
 
-	idev = is->idev;
-	if (!idev)
-		printk(KERN_DEBUG "isdn_ppp_write: idev == NULL\n");
-	else {
+	return;
+}
+
+/*
+ * bind isdn_net_local <=> ippp-device
+ */
+int
+isdn_ppp_bind(isdn_net_dev *idev)
+{
+	int unit = 0;
+	unsigned long flags;
+	int retval = 0;
+	struct ipppd *ipppd;
+
+	if (idev->ipppd) {
+		isdn_BUG();
+		return 0;
+	}
+
+	spin_lock_irqsave(&ipppds_lock, flags);
+	if (idev->pppbind < 0) {  /* device bound to ippp device ? */
+		struct list_head *l;
+		char exclusive[ISDN_MAX_CHANNELS];	/* exclusive flags */
+		memset(exclusive, 0, ISDN_MAX_CHANNELS);
+		/* step through net devices to find exclusive minors */
+		list_for_each(l, &isdn_net_devs) {
+			isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
+			if (p->pppbind >= 0 && p->pppbind < ISDN_MAX_CHANNELS)
+				exclusive[p->pppbind] = 1;
+		}
 		/*
-		 * Don't reset huptimer for
-		 * LCP packets. (Echo requests).
+		 * search a free device / slot
 		 */
-		if (copy_from_user(protobuf, buf, 4)) {
-			retval = -EFAULT;
-			goto out;
+		list_for_each_entry(ipppd, &ipppds, ipppds) {
+			if (!ipppd)
+				continue;
+			if (ipppd->state != IPPPD_ST_OPEN)
+				continue;
+			if (!exclusive[ipppd->minor])
+				break;
+			goto found;
 		}
-		proto = PPP_PROTOCOL(protobuf);
-		if (proto != PPP_LCP)
-			idev->huptimer = 0;
-
-		if (idev->isdn_slot < 0) {
-			retval = 0;
-			goto out;
+	} else {
+		list_for_each_entry(ipppd, &ipppds, ipppds) {
+			if (!ipppd)
+				continue;
+			if (ipppd->state != IPPPD_ST_OPEN)
+				continue;
+			if (ipppd->minor == idev->pppbind)
+				goto found;
 		}
-		if ((dev->drv[isdn_slot_driver(idev->isdn_slot)]->flags & DRV_FLAG_RUNNING) &&
-		    isdn_net_online(idev)) {
-			unsigned short hl;
-			struct sk_buff *skb;
-			/*
-			 * we need to reserve enought space in front of
-			 * sk_buff. old call to dev_alloc_skb only reserved
-			 * 16 bytes, now we are looking what the driver want
-			 */
-			hl = isdn_slot_hdrlen(idev->isdn_slot);
-			skb = alloc_skb(hl+count, GFP_ATOMIC);
-			if (!skb) {
-				printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
-				retval = count;
-				goto out;
-			}
-			skb_reserve(skb, hl);
-			if (copy_from_user(skb_put(skb, count), buf, count))
-			{
-				kfree_skb(skb);
-				retval = -EFAULT;
-				goto out;
-			}
-			if (is->debug & 0x40) {
-				printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
-				isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,idev->ppp_slot);
-			}
+	}
 
-			isdn_ppp_send_ccp(idev,idev->mlp,skb); /* keeps CCP/compression states in sync */
+	printk(KERN_INFO "isdn_ppp_bind: no ipppd\n");
+	retval = -ESRCH;
+	goto err;
 
-			isdn_net_write_super(idev, skb);
-		}
+ found:
+	unit = isdn_ppp_if_get_unit(idev->name);	/* get unit number from interface name .. ugly! */
+	if (unit < 0) {
+		printk(KERN_INFO "isdn_ppp_bind: illegal interface name %s.\n", idev->name);
+		retval = -ENODEV;
+		goto err;
 	}
-	retval = count;
 	
+	ipppd->unit = unit;
+	ipppd->state = IPPPD_ST_ASSIGNED;
+	ipppd->idev = idev;
+	/* we hold a reference until isdn_ppp_unbind() */
+	idev->ipppd = ipppd_get(ipppd);
+	spin_unlock_irqrestore(&ipppds_lock, flags);
+
+	idev->pppcfg = 0;         /* config flags */
+	/* seq no last seen, maybe set to bundle min, when joining? */
+	idev->pppseq = -1;
+
+	idev->ccp = ippp_ccp_alloc();
+	if (!idev->ccp) {
+		retval = -ENOMEM;
+		goto out;
+	}
+	idev->ccp->proto       = PPP_COMPFRAG;
+	idev->ccp->priv        = idev;
+	idev->ccp->alloc_skb   = isdn_ppp_dev_alloc_skb;
+	idev->ccp->push_header = isdn_ppp_dev_push_header;
+	idev->ccp->xmit        = isdn_ppp_dev_xmit;
+	idev->ccp->kick_up     = isdn_ppp_dev_kick_up;
+
+#ifdef CONFIG_ISDN_MPP
+	retval = isdn_ppp_mp_init(lp, NULL);
+#endif /* CONFIG_ISDN_MPP */
  out:
-	unlock_kernel();
+	if (retval) {
+		idev->ipppd->state = IPPPD_ST_OPEN;
+		ipppd_put(idev->ipppd);
+		idev->ipppd = NULL;
+	}
+
+	return retval;
+
+ err:
+	spin_unlock_irqrestore(&ipppds_lock, flags);
 	return retval;
 }
 
-struct file_operations isdn_ppp_fops =
+/*
+ * kick the ipppd on the device
+ * (wakes up daemon after B-channel connect)
+ */
+
+static void
+isdn_ppp_connected(isdn_net_dev *idev)
 {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= isdn_ppp_read,
-	.write		= isdn_ppp_write,
-	.poll		= isdn_ppp_poll,
-	.ioctl		= isdn_ppp_ioctl,
-	.open		= isdn_ppp_open,
-	.release	= isdn_ppp_release,
-};
+	struct ipppd *ipppd = idev->ipppd;
+
+	ipppd_debug(ipppd, "");
+
+	ipppd->state  = IPPPD_ST_CONNECTED;
+	ipppd->flags |= IPPPD_FL_WAKEUP;
+	wake_up(&ipppd->wq);
+}
+
+static void
+isdn_ppp_disconnected(isdn_net_dev *idev)
+{
+	struct ipppd *ipppd = idev->ipppd;
+
+	ipppd_debug(ipppd, "");
+
+	if (idev->pppcfg & SC_ENABLE_IP)
+		isdn_net_offline(idev);
+
+	if (ipppd->state != IPPPD_ST_CONNECTED)
+		isdn_BUG();
+	
+	ipppd->state  = IPPPD_ST_ASSIGNED;
+	ipppd->flags |= IPPPD_FL_HUP;
+	wake_up(&ipppd->wq);
+
+#ifdef CONFIG_ISDN_MPP
+	spin_lock(&idev->pb->lock);
+	if (lp->netdev->pb->ref_ct == 1)	/* last link in queue? */
+		isdn_ppp_mp_cleanup(lp);
+
+	lp->netdev->pb->ref_ct--;
+	spin_unlock(&lp->netdev->pb->lock);
+#endif /* CONFIG_ISDN_MPP */
+
+}
 
 /*
  * init memory, structures etc.
@@ -808,37 +831,17 @@
 int
 isdn_ppp_init(void)
 {
-	int i,
-	 j;
-	 
 #ifdef CONFIG_ISDN_MPP
 	if( isdn_ppp_mp_bundle_array_init() < 0 )
 		return -ENOMEM;
 #endif /* CONFIG_ISDN_MPP */
 
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		if (!(ippp_table[i] = (struct ippp_struct *)
-		      kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
-			printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
-			for (j = 0; j < i; j++)
-				kfree(ippp_table[j]);
-			return -1;
-		}
-		memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
-		ippp_table[i]->state = 0;
-		skb_queue_head_init(&ippp_table[i]->rq);
-	}
 	return 0;
 }
 
 void
 isdn_ppp_cleanup(void)
 {
-	int i;
-
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-		kfree(ippp_table[i]);
-
 #ifdef CONFIG_ISDN_MPP
 	if (isdn_ppp_bundle_arr)
 		kfree(isdn_ppp_bundle_arr);
@@ -850,25 +853,31 @@
  * check for address/control field and skip if allowed
  * retval != 0 -> discard packet silently
  */
-static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb) 
+static int isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb) 
 {
+	u8 val;
+
 	if (skb->len < 1)
 		return -1;
 
-	if (skb->data[0] == 0xff) {
-		if (skb->len < 2)
+	get_u8(skb->data, &val);
+	if (val != PPP_ALLSTATIONS) {
+		/* if AC compression was not negotiated, but no AC present,
+		   discard packet */
+		if (idev->pppcfg & SC_REJ_COMP_AC)
 			return -1;
 
-		if (skb->data[1] != 0x03)
-			return -1;
-
-		// skip address/control (AC) field
-		skb_pull(skb, 2);
-	} else { 
-		if (is->pppcfg & SC_REJ_COMP_AC)
-			// if AC compression was not negotiated, but used, discard packet
-			return -1;
+		return 0;
 	}
+	if (skb->len < 2)
+		return -1;
+
+	get_u8(skb->data + 1, &val);
+	if (val != PPP_UI)
+		return -1;
+
+	/* skip address/control (AC) field */
+	skb_pull(skb, 2);
 	return 0;
 }
 
@@ -876,84 +885,80 @@
  * get the PPP protocol header and pull skb
  * retval < 0 -> discard packet silently
  */
-static int isdn_ppp_strip_proto(struct sk_buff *skb) 
+int isdn_ppp_strip_proto(struct sk_buff *skb) 
 {
-	int proto;
-	
+	u16 proto;
+	u8 val;
+
 	if (skb->len < 1)
 		return -1;
 
-	if (skb->data[0] & 0x1) {
-		// protocol field is compressed
-		proto = skb->data[0];
+	get_u8(skb->data, &val);
+	if (val & 0x1) {
+		/* protocol field is compressed */
+		proto = val;
 		skb_pull(skb, 1);
 	} else {
 		if (skb->len < 2)
 			return -1;
-		proto = ((int) skb->data[0] << 8) + skb->data[1];
+		get_u16(skb->data, &proto);
 		skb_pull(skb, 2);
 	}
 	return proto;
 }
 
-
 /*
  * handler for incoming packets on a syncPPP interface
  */
 static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, 
 			     struct sk_buff *skb)
 {
-	struct ippp_struct *is;
-	int slot;
+	struct ipppd *is;
 	int proto;
 
-	/*
-	 * If encapsulation is syncppp, don't reset
-	 * huptimer on LCP packets.
-	 */
-	if (PPP_PROTOCOL(skb->data) != PPP_LCP)
-		idev->huptimer = 0;
-
-	slot = idev->ppp_slot;
-	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
-		       slot);
-		kfree_skb(skb);
-		return;
-	}
-	is = ippp_table[slot];
+	is = idev->ipppd;
+	if (!is) 
+		goto err;
 
 	if (is->debug & 0x4) {
-		printk(KERN_DEBUG "ippp_receive: is:%p lp:%p slot:%d unit:%d len:%d\n",
-		       is,lp,idev->ppp_slot,is->unit,(int) skb->len);
-		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,idev->ppp_slot);
+		printk(KERN_DEBUG "ippp_receive: is:%p lp:%p unit:%d len:%d\n",
+		       is, lp, is->unit, skb->len);
+		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,-1);
 	}
 
- 	if (isdn_ppp_skip_ac(is, skb) < 0) {
- 		kfree_skb(skb);
- 		return;
- 	}
+ 	if (isdn_ppp_skip_ac(idev, skb) < 0)
+		goto err;
+
   	proto = isdn_ppp_strip_proto(skb);
- 	if (proto < 0) {
- 		kfree_skb(skb);
- 		return;
- 	}
+ 	if (proto < 0)
+		goto err;
+
+	/* Don't reset huptimer on LCP packets. */
+	if (proto != PPP_LCP)
+		idev->huptimer = 0;
   
 #ifdef CONFIG_ISDN_MPP
  	if (is->compflags & SC_LINK_DECOMP_ON) {
  		skb = isdn_ppp_decompress(skb, is, NULL, &proto);
  		if (!skb) // decompression error
- 			return;
+			goto put;
  	}
 	
  	if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
   		if (proto == PPP_MP) {
   			isdn_ppp_mp_receive(lp, idev, skb);
- 			return;
+			goto put;
  		}
  	} 
-#endif
  	isdn_ppp_push_higher(lp, idev, skb, proto);
+ put:
+#else
+ 	isdn_ppp_push_higher(lp, idev, skb, proto);
+#endif
+	return;
+
+ err:
+	kfree_skb(skb);
 }
 
 /*
@@ -966,28 +971,16 @@
 		     struct sk_buff *skb, int proto)
 {
 	struct net_device *dev = &lp->dev;
- 	struct ippp_struct *is, *mis;
-	int slot;
-
-	slot = idev->ppp_slot;
-	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
-		       slot);
-		goto drop_packet;
-	}
-	is = ippp_table[slot];
- 	
- 	mis = ippp_table[slot];
+ 	struct ipppd *is = idev->ipppd;
 
 	if (is->debug & 0x10) {
 		printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
-		isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,slot);
+		isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit, -1);
 	}
-	if (mis->compflags & SC_DECOMP_ON) {
-		skb = isdn_ppp_decompress(skb, is, mis, &proto);
-		if (!skb) // decompression error
-  			return;
-  	}
+	skb = ippp_ccp_decompress(lp->ccp, skb, &proto);
+	if (!skb) // decompression error
+		goto out;
+
 	switch (proto) {
 		case PPP_IPX:  /* untested */
 			if (is->debug & 0x20)
@@ -1002,19 +995,14 @@
 		case PPP_COMP:
 		case PPP_COMPFRAG:
 			printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
-			goto drop_packet;
+			goto drop;
 #ifdef CONFIG_ISDN_PPP_VJ
 		case PPP_VJC_UNCOMP:
 			if (is->debug & 0x20)
 				printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
-			if (idev->ppp_slot < 0) {
-				printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
-				       __FUNCTION__ , idev->ppp_slot);
-				goto drop_packet;
-			}
-			if (slhc_remember(ippp_table[idev->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
+			if (slhc_remember(lp->slcomp, skb->data, skb->len) <= 0) {
 				printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
-				goto drop_packet;
+				goto drop;
 			}
 			skb->protocol = htons(ETH_P_IP);
 			break;
@@ -1029,82 +1017,55 @@
 				if (!skb) {
 					printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
 					skb = skb_old;
-					goto drop_packet;
+					goto drop;
 				}
 				skb_put(skb, skb_old->len + 128);
 				memcpy(skb->data, skb_old->data, skb_old->len);
-				if (idev->ppp_slot < 0) {
-					printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
-					       __FUNCTION__ , idev->ppp_slot);
-					goto drop_packet;
-				}
-				pkt_len = slhc_uncompress(ippp_table[idev->ppp_slot]->slcomp,
+				pkt_len = slhc_uncompress(lp->slcomp,
 						skb->data, skb_old->len);
 				kfree_skb(skb_old);
 				if (pkt_len < 0)
-					goto drop_packet;
+					goto drop;
 
 				skb_trim(skb, pkt_len);
 				skb->protocol = htons(ETH_P_IP);
 			}
 			break;
 #endif
-		case PPP_CCP:
 		case PPP_CCPFRAG:
-			isdn_ppp_receive_ccp(idev,lp,skb,proto);
+			ippp_ccp_receive_ccp(idev->ccp, skb);
+			goto ccp;
+		case PPP_CCP:
+			ippp_ccp_receive_ccp(lp->ccp, skb);
+	ccp:
 			/* Dont pop up ResetReq/Ack stuff to the daemon any
 			   longer - the job is done already */
 			if(skb->data[0] == CCP_RESETREQ ||
 			   skb->data[0] == CCP_RESETACK)
-				break;
+				goto free;
 			/* fall through */
 		default:
-			isdn_ppp_fill_rq(skb->data, skb->len, proto, idev->ppp_slot);	/* push data to pppd device */
-			kfree_skb(skb);
-			return;
+			// FIXME use skb directly
+			ipppd_queue_read(is, proto, skb->data, skb->len);
+			goto free;
 	}
 
  	/* Reset hangup-timer */
  	idev->huptimer = 0;
 
 	skb->dev = dev;
-	skb->mac.raw = skb->data;
 	netif_rx(skb);
 	/* net_dev->local->stats.rx_packets++; done in isdn_net.c */
+ out:
 	return;
 
- drop_packet:
+ drop:
 	lp->stats.rx_dropped++;
+ free:
 	kfree_skb(skb);
 }
 
 /*
- * isdn_ppp_skb_push ..
- * checks whether we have enough space at the beginning of the skb
- * and allocs a new SKB if necessary
- */
-static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
-{
-	struct sk_buff *skb = *skb_p;
-
-	if(skb_headroom(skb) < len) {
-		struct sk_buff *nskb = skb_realloc_headroom(skb, len);
-
-		if (!nskb) {
-			printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
-			dev_kfree_skb(skb);
-			return NULL;
-		}
-		printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
-		dev_kfree_skb(skb);
-		*skb_p = nskb;
-		return skb_push(nskb, len);
-	}
-	return skb_push(skb,len);
-}
-
-
-/*
  * send ppp frame .. we expect a PIDCOMPressable proto --
  *  (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
  *
@@ -1118,30 +1079,13 @@
 	isdn_net_local *mlp = ndev->priv;
 	isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online);
 	unsigned int proto = PPP_IP;     /* 0x21 */
-	struct ippp_struct *ipt,*ipts;
-	int slot;
+	struct ipppd *ipppd;
 
 	ndev->trans_start = jiffies;
 
 	if (list_empty(&mlp->online))
 		return isdn_net_autodial(skb, ndev);
 
-	slot = idev->ppp_slot;
-	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
-		       slot);
-		kfree_skb(skb);
-		return 0;
-	}
-	ipts = ippp_table[slot];
-
-	if (!(ipts->pppcfg & SC_ENABLE_IP)) {	/* PPP connected ? */
-		if (ipts->debug & 0x1)
-			printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
-		netif_stop_queue(ndev);
-		return 1;
-	}
-
 	switch (ntohs(skb->protocol)) {
 		case ETH_P_IP:
 			proto = PPP_IP;
@@ -1153,42 +1097,32 @@
 			printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", 
 			       skb->protocol);
 			dev_kfree_skb(skb);
-			return 0;
+			goto out;
 	}
 
-	idev = isdn_net_get_locked_dev(mlp);
+	idev = isdn_net_get_xmit_dev(mlp);
 	if (!idev) {
-		printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
-		netif_stop_queue(ndev);
-		return 1;
+		printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
+		goto stop;
 	}
-	/* we have our lp locked from now on */
-	slot = idev->ppp_slot;
-	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
-		       slot);
-		kfree_skb(skb);
-		return 0;
+	if (!(idev->pppcfg & SC_ENABLE_IP)) {	/* PPP connected ? */
+		isdn_BUG();
+		goto stop;
 	}
-	ipt = ippp_table[slot];
+	ipppd = idev->ipppd;
 	idev->huptimer = 0;
 
 	/*
 	 * after this line .. requeueing in the device queue is no longer allowed!!!
 	 */
 
-	/* Pull off the fake header we stuck on earlier to keep
-	 * the fragmentation code happy.
-	 */
-	skb_pull(skb,IPPP_MAX_HEADER);
-
-	if (ipt->debug & 0x4)
+	if (ipppd->debug & 0x4)
 		printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
-        if (ipts->debug & 0x40)
-                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,idev->ppp_slot);
+        if (ipppd->debug & 0x40)
+                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32, ipppd->unit, -1);
 
 #ifdef CONFIG_ISDN_PPP_VJ
-	if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes, but check this again */
+	if (proto == PPP_IP && idev->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes, but check this again */
 		struct sk_buff *new_skb;
 	        unsigned short hl;
 		/*
@@ -1213,8 +1147,8 @@
 			skb_put(new_skb, skb->len);
 			buf = skb->data;
 
-			pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
-				 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
+			pktlen = slhc_compress(mlp->slcomp, skb->data, skb->len, new_skb->data,
+				 &buf, !(idev->pppcfg & SC_NO_TCP_CCID));
 
 			if (buf != skb->data) {	
 				if (new_skb->data != buf)
@@ -1241,17 +1175,9 @@
 	/*
 	 * normal (single link) or bundle compression
 	 */
-	if(ipts->compflags & SC_COMP_ON) {
-		/* We send compressed only if both down- und upstream
-		   compression is negotiated, that means, CCP is up */
-		if(ipts->compflags & SC_DECOMP_ON) {
-			skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
-		} else {
-			printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
-		}
-	}
+	skb = ippp_ccp_compress(mlp->ccp, skb, &proto);
 
-	if (ipt->debug & 0x24)
+	if (ipppd->debug & 0x24)
 		printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
 
 #ifdef CONFIG_ISDN_MPP
@@ -1281,45 +1207,29 @@
 	}
 #endif
 
+#if 0
 	/*
 	 * 'link in bundle' compression  ...
 	 */
-	if(ipt->compflags & SC_LINK_COMP_ON)
+	if (ipt->compflags & SC_LINK_COMP_ON)
 		skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
+#endif
 
-	if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
-		unsigned char *data = isdn_ppp_skb_push(&skb,1);
-		if(!data)
-			goto unlock;
-		data[0] = proto & 0xff;
-	}
-	else {
-		unsigned char *data = isdn_ppp_skb_push(&skb,2);
-		if(!data)
-			goto unlock;
-		data[0] = (proto >> 8) & 0xff;
-		data[1] = proto & 0xff;
-	}
-	if(!(ipt->pppcfg & SC_COMP_AC)) {
-		unsigned char *data = isdn_ppp_skb_push(&skb,2);
-		if(!data)
-			goto unlock;
-		data[0] = 0xff;    /* All Stations */
-		data[1] = 0x03;    /* Unnumbered information */
-	}
-
-	/* tx-stats are now updated via BSENT-callback */
+	isdn_ppp_push_header(idev, skb, proto);
 
-	if (ipts->debug & 0x40) {
+	if (ipppd->debug & 0x40) {
 		printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
-		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,idev->ppp_slot);
+		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, ipppd->unit, -1);
 	}
 	
 	isdn_net_writebuf_skb(idev, skb);
 
- unlock:
-	spin_unlock_bh(&idev->xmit_lock);
+ out:
 	return 0;
+
+ stop:
+	netif_stop_queue(ndev);
+	return 1;
 }
 
 #ifdef CONFIG_ISDN_MPP
@@ -1372,7 +1282,7 @@
 static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
 {
 	isdn_net_dev *idev = lp->netdev;
-	struct ippp_struct * is;
+	struct ipppd * is;
 
 	if (idev->ppp_slot < 0) {
 		printk(KERN_ERR "%s: >ppp_slot(%d) out of range\n",
@@ -1396,7 +1306,7 @@
 	}
 	lp->netdev->pb->ref_ct++;
 	
-	is->last_link_seqno = 0;
+	is->pppseq = 0;
 	return 0;
 }
 
@@ -1413,7 +1323,7 @@
 				struct sk_buff *skb)
 {
 	isdn_net_dev *idev = lp->netdev;
-	struct ippp_struct *is;
+	struct ipppd *is;
 	isdn_net_dev *qdev;
 	ippp_bundle * mp;
 	isdn_mppp_stats * stats;
@@ -1442,7 +1352,7 @@
 		isdn_ppp_mp_print_recv_pkt(slot, skb);
 
 	newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, 
-						skb, is->last_link_seqno);
+						skb, is->pppseq);
 
 
 	/* if this packet seq # is less than last already processed one,
@@ -1460,14 +1370,14 @@
 	}
 	
 	/* find the minimum received sequence number over all links */
-	is->last_link_seqno = minseq = newseq;
+	is->pppseq = minseq = newseq;
 	list_for_each_entry(qdev, &lp->online, online) {
 		slot = qdev->ppp_slot;
 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
 			printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
 			       __FUNCTION__ ,slot);
 		} else {
-			u32 lls = ippp_table[slot]->last_link_seqno;
+			u32 lls = ippp_table[slot]->pppseq;
 			if (MP_LT(lls, minseq))
 				minseq = lls;
 		}
@@ -1754,7 +1664,7 @@
 }
 
 static int
-isdn_ppp_bundle(struct ippp_struct *is, int unit)
+isdn_ppp_bundle(struct ipppd *is, int unit)
 {
 	char ifn[IFNAMSIZ + 1];
 	isdn_net_dev *p;
@@ -1804,11 +1714,11 @@
  */
 
 static int
-isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
+isdn_ppp_dev_ioctl_stats(struct ifreq *ifr, struct net_device *dev)
 {
-	struct ppp_stats *res,
-	 t;
+	struct ppp_stats *res, t;
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
+	struct slcompress *slcomp;
 	int err;
 
 	res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
@@ -1828,8 +1738,8 @@
 		t.p.ppp_obytes = lp->stats.tx_bytes;
 		t.p.ppp_oerrors = lp->stats.tx_errors;
 #ifdef CONFIG_ISDN_PPP_VJ
-		if (slot >= 0 && ippp_table[slot]->slcomp) {
-			struct slcompress *slcomp = ippp_table[slot]->slcomp;
+		slcomp = lp->slcomp;
+		if (slcomp) {
 			t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
 			t.vj.vjs_compressed = slcomp->sls_o_compressed;
 			t.vj.vjs_searches = slcomp->sls_o_searches;
@@ -1858,17 +1768,18 @@
 		return -EINVAL;
 
 	switch (cmd) {
-		case SIOCGPPPVER:
-			r = (char *) ifr->ifr_ifru.ifru_data;
-			len = strlen(PPP_VERSION) + 1;
-			if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
-			break;
-		case SIOCGPPPSTATS:
-			error = isdn_ppp_dev_ioctl_stats(0, ifr, dev);
-			break;
-		default:
-			error = -EINVAL;
-			break;
+	case SIOCGPPPVER:
+		r = (char *) ifr->ifr_ifru.ifru_data;
+		len = strlen(PPP_VERSION) + 1;
+		if (copy_to_user(r, PPP_VERSION, len))
+			error = -EFAULT;
+		break;
+	case SIOCGPPPSTATS:
+		error = isdn_ppp_dev_ioctl_stats(ifr, dev);
+		break;
+	default:
+		error = -EINVAL;
+		break;
 	}
 	return error;
 }
@@ -1962,868 +1873,167 @@
 /* Push an empty CCP Data Frame up to the daemon to wake it up and let it
    generate a CCP Reset-Request or tear down CCP altogether */
 
-static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
+static void isdn_ppp_dev_kick_up(void *priv)
 {
-	isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->idev->ppp_slot);
+	isdn_net_dev *idev = priv;
+
+	ipppd_queue_read(idev->ipppd, PPP_COMPFRAG, NULL, 0);
 }
 
-/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
-   but absolutely nontrivial. The most abstruse problem we are facing is
-   that the generation, reception and all the handling of timeouts and
-   resends including proper request id management should be entirely left
-   to the (de)compressor, but indeed is not covered by the current API to
-   the (de)compressor. The API is a prototype version from PPP where only
-   some (de)compressors have yet been implemented and all of them are
-   rather simple in their reset handling. Especially, their is only one
-   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
-   not have parameters. For this very special case it was sufficient to
-   just return an error code from the decompressor and have a single
-   reset() entry to communicate all the necessary information between
-   the framework and the (de)compressor. Bad enough, LZS is different
-   (and any other compressor may be different, too). It has multiple
-   histories (eventually) and needs to Reset each of them independently
-   and thus uses multiple outstanding Acks and history numbers as an
-   additional parameter to Reqs/Acks.
-   All that makes it harder to port the reset state engine into the
-   kernel because it is not just the same simple one as in (i)pppd but
-   it must be able to pass additional parameters and have multiple out-
-   standing Acks. We are trying to achieve the impossible by handling
-   reset transactions independent by their id. The id MUST change when
-   the data portion changes, thus any (de)compressor who uses more than
-   one resettable state must provide and recognize individual ids for
-   each individual reset transaction. The framework itself does _only_
-   differentiate them by id, because it has no other semantics like the
-   (de)compressor might.
-   This looks like a major redesign of the interface would be nice,
-   but I don't have an idea how to do it better. */
-
-/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
-   getting that lengthy because there is no simple "send-this-frame-out"
-   function above but every wrapper does a bit different. Hope I guess
-   correct in this hack... */
-
-static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
-				    unsigned char code, unsigned char id,
-				    unsigned char *data, int len)
+static void isdn_ppp_lp_kick_up(void *priv)
 {
-	struct sk_buff *skb;
-	unsigned char *p;
-	int hl;
-	int cnt = 0;
-	isdn_net_dev *idev = is->idev;
-
-	/* Alloc large enough skb */
-	hl = isdn_slot_hdrlen(idev->isdn_slot);
-	skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
-	if(!skb) {
-		printk(KERN_WARNING
-		       "ippp: CCP cannot send reset - out of memory\n");
+	isdn_net_local *lp = priv;
+	isdn_net_dev *idev;
+
+	if (list_empty(&lp->online)) {
+		isdn_BUG();
 		return;
 	}
-	skb_reserve(skb, hl);
-
-	/* We may need to stuff an address and control field first */
-	if(!(is->pppcfg & SC_COMP_AC)) {
-		p = skb_put(skb, 2);
-		*p++ = 0xff;
-		*p++ = 0x03;
-	}
-
-	/* Stuff proto, code, id and length */
-	p = skb_put(skb, 6);
-	*p++ = (proto >> 8);
-	*p++ = (proto & 0xff);
-	*p++ = code;
-	*p++ = id;
-	cnt = 4 + len;
-	*p++ = (cnt >> 8);
-	*p++ = (cnt & 0xff);
-
-	/* Now stuff remaining bytes */
-	if(len) {
-		p = skb_put(skb, len);
-		memcpy(p, data, len);
-	}
-
-	/* skb is now ready for xmit */
-	printk(KERN_DEBUG "Sending CCP Frame:\n");
-	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
-
-	isdn_net_write_super(idev, skb);
+	idev = list_entry(lp->online.next, isdn_net_dev, online);
+	ipppd_queue_read(idev->ipppd, PPP_COMP, NULL, 0);
 }
 
-/* Allocate the reset state vector */
-static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
-{
-	struct ippp_ccp_reset *r;
-	r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
-	if(!r) {
-		printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
-		       " structure - no mem\n");
-		return NULL;
-	}
-	memset(r, 0, sizeof(struct ippp_ccp_reset));
-	printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
-	is->reset = r;
-	return r;
-}
+/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */
 
-/* Destroy the reset state vector. Kill all pending timers first. */
-static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
+static struct sk_buff *
+__isdn_ppp_alloc_skb(isdn_net_dev *idev, int len, unsigned int gfp_mask)
 {
-	unsigned int id;
+	int hl = IPPP_MAX_HEADER + isdn_slot_hdrlen(idev->isdn_slot); 
+	struct sk_buff *skb;
 
-	printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
-	       is->reset);
-	for(id = 0; id < 256; id++) {
-		if(is->reset->rs[id]) {
-			isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
-		}
-	}
-	kfree(is->reset);
-	is->reset = NULL;
-}
+	skb = alloc_skb(hl + len, gfp_mask);
+	if (!skb)
+		return NULL;
 
-/* Free a given state and clear everything up for later reallocation */
-static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
-					  unsigned char id)
-{
-	struct ippp_ccp_reset_state *rs;
-
-	if(is->reset->rs[id]) {
-		printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
-		rs = is->reset->rs[id];
-		/* Make sure the kernel will not call back later */
-		if(rs->ta)
-			del_timer(&rs->timer);
-		is->reset->rs[id] = NULL;
-		kfree(rs);
-	} else {
-		printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
-	}
+	skb_reserve(skb, hl);
+	return skb;
 }
 
-/* The timer callback function which is called when a ResetReq has timed out,
-   aka has never been answered by a ResetAck */
-static void isdn_ppp_ccp_timer_callback(unsigned long closure)
+static struct sk_buff *
+isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask)
 {
-	struct ippp_ccp_reset_state *rs =
-		(struct ippp_ccp_reset_state *)closure;
+	isdn_net_dev *idev = priv;
 
-	if(!rs) {
-		printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
-		return;
-	}
-	if(rs->ta && rs->state == CCPResetSentReq) {
-		/* We are correct here */
-		if(!rs->expra) {
-			/* Hmm, there is no Ack really expected. We can clean
-			   up the state now, it will be reallocated if the
-			   decompressor insists on another reset */
-			rs->ta = 0;
-			isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
-			return;
-		}
-		printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
-		       rs->id);
-		/* Push it again */
-		isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
-					rs->data, rs->dlen);
-		/* Restart timer */
-		rs->timer.expires = jiffies + HZ*5;
-		add_timer(&rs->timer);
-	} else {
-		printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
-		       rs->state);
-	}
+	return __isdn_ppp_alloc_skb(idev, len, gfp_mask);
 }
 
-/* Allocate a new reset transaction state */
-static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
-						      unsigned char id)
+static struct sk_buff *
+isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask)
 {
-	struct ippp_ccp_reset_state *rs;
-	if(is->reset->rs[id]) {
-		printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
-		       id);
-		return NULL;
-	} else {
-		rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
-		if(!rs)
-			return NULL;
-		memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
-		rs->state = CCPResetIdle;
-		rs->is = is;
-		rs->id = id;
-		rs->timer.data = (unsigned long)rs;
-		rs->timer.function = isdn_ppp_ccp_timer_callback;
-		is->reset->rs[id] = rs;
-	}
-	return rs;
-}
-
-
-/* A decompressor wants a reset with a set of parameters - do what is
-   necessary to fulfill it */
-static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
-				     struct isdn_ppp_resetparams *rp)
-{
-	struct ippp_ccp_reset_state *rs;
-
-	if(rp->valid) {
-		/* The decompressor defines parameters by itself */
-		if(rp->rsend) {
-			/* And he wants us to send a request */
-			if(!(rp->idval)) {
-				printk(KERN_ERR "ippp_ccp: decompressor must"
-				       " specify reset id\n");
-				return;
-			}
-			if(is->reset->rs[rp->id]) {
-				/* There is already a transaction in existence
-				   for this id. May be still waiting for a
-				   Ack or may be wrong. */
-				rs = is->reset->rs[rp->id];
-				if(rs->state == CCPResetSentReq && rs->ta) {
-					printk(KERN_DEBUG "ippp_ccp: reset"
-					       " trans still in progress"
-					       " for id %d\n", rp->id);
-				} else {
-					printk(KERN_WARNING "ippp_ccp: reset"
-					       " trans in wrong state %d for"
-					       " id %d\n", rs->state, rp->id);
-				}
-			} else {
-				/* Ok, this is a new transaction */
-				printk(KERN_DEBUG "ippp_ccp: new trans for id"
-				       " %d to be started\n", rp->id);
-				rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
-				if(!rs) {
-					printk(KERN_ERR "ippp_ccp: out of mem"
-					       " allocing ccp trans\n");
-					return;
-				}
-				rs->state = CCPResetSentReq;
-				rs->expra = rp->expra;
-				if(rp->dtval) {
-					rs->dlen = rp->dlen;
-					memcpy(rs->data, rp->data, rp->dlen);
-				}
-				/* HACK TODO - add link comp here */
-				isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
-							CCP_RESETREQ, rs->id,
-							rs->data, rs->dlen);
-				/* Start the timer */
-				rs->timer.expires = jiffies + 5*HZ;
-				add_timer(&rs->timer);
-				rs->ta = 1;
-			}
-		} else {
-			printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
-		}
-	} else {
-		/* The reset params are invalid. The decompressor does not
-		   care about them, so we just send the minimal requests
-		   and increase ids only when an Ack is received for a
-		   given id */
-		if(is->reset->rs[is->reset->lastid]) {
-			/* There is already a transaction in existence
-			   for this id. May be still waiting for a
-			   Ack or may be wrong. */
-			rs = is->reset->rs[is->reset->lastid];
-			if(rs->state == CCPResetSentReq && rs->ta) {
-				printk(KERN_DEBUG "ippp_ccp: reset"
-				       " trans still in progress"
-				       " for id %d\n", rp->id);
-			} else {
-				printk(KERN_WARNING "ippp_ccp: reset"
-				       " trans in wrong state %d for"
-				       " id %d\n", rs->state, rp->id);
-			}
-		} else {
-			printk(KERN_DEBUG "ippp_ccp: new trans for id"
-			       " %d to be started\n", is->reset->lastid);
-			rs = isdn_ppp_ccp_reset_alloc_state(is,
-							    is->reset->lastid);
-			if(!rs) {
-				printk(KERN_ERR "ippp_ccp: out of mem"
-				       " allocing ccp trans\n");
-				return;
-			}
-			rs->state = CCPResetSentReq;
-			/* We always expect an Ack if the decompressor doesnt
-			   know	better */
-			rs->expra = 1;
-			rs->dlen = 0;
-			/* HACK TODO - add link comp here */
-			isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
-						rs->id, NULL, 0);
-			/* Start the timer */
-			rs->timer.expires = jiffies + 5*HZ;
-			add_timer(&rs->timer);
-			rs->ta = 1;
-		}
-	}
-}
-
-/* An Ack was received for this id. This means we stop the timer and clean
-   up the state prior to calling the decompressors reset routine. */
-static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
-					unsigned char id)
-{
-	struct ippp_ccp_reset_state *rs = is->reset->rs[id];
-
-	if(rs) {
-		if(rs->ta && rs->state == CCPResetSentReq) {
-			/* Great, we are correct */
-			if(!rs->expra)
-				printk(KERN_DEBUG "ippp_ccp: ResetAck received"
-				       " for id %d but not expected\n", id);
-		} else {
-			printk(KERN_INFO "ippp_ccp: ResetAck received out of"
-			       "sync for id %d\n", id);
-		}
-		if(rs->ta) {
-			rs->ta = 0;
-			del_timer(&rs->timer);
-		}
-		isdn_ppp_ccp_reset_free_state(is, id);
-	} else {
-		printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
-		       " %d\n", id);
-	}
-	/* Make sure the simple reset stuff uses a new id next time */
-	is->reset->lastid++;
-}
-
-/* 
- * decompress packet
- *
- * if master = 0, we're trying to uncompress an per-link compressed packet,
- * as opposed to an compressed reconstructed-from-MPPP packet.
- * proto is updated to protocol field of uncompressed packet.
- *
- * retval: decompressed packet,
- *         same packet if uncompressed,
- *	   NULL if decompression error
- */
+	isdn_net_local *lp = priv;
+	isdn_net_dev *idev;
 
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
-	int *proto)
-{
-	void *stat = NULL;
-	struct isdn_ppp_compressor *ipc = NULL;
-	struct sk_buff *skb_out;
-	int len;
-	struct ippp_struct *ri;
-	struct isdn_ppp_resetparams rsparm;
-	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
-
-	if(!master) {
-		// per-link decompression 
-		stat = is->link_decomp_stat;
-		ipc = is->link_decompressor;
-		ri = is;
-	} else {
-		stat = master->decomp_stat;
-		ipc = master->decompressor;
-		ri = master;
-	}
-
-	if (!ipc) {
-		// no decompressor -> we can't decompress.
-		printk(KERN_DEBUG "ippp: no decompressor defined!\n");
-		return skb;
-	}
-	if (!stat) // if we have a compressor, stat has been set as well
-		BUG();
-
-	if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) {
-		// compressed packets are compressed by their protocol type
-
-		// Set up reset params for the decompressor
-  		memset(&rsparm, 0, sizeof(rsparm));
-  		rsparm.data = rsdata;
-  		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
-  
-  		skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
-		len = ipc->decompress(stat, skb, skb_out, &rsparm);
-		kfree_skb(skb);
-		if (len <= 0) {
-			switch(len) {
-			case DECOMP_ERROR:
-				printk(KERN_INFO "ippp: decomp wants reset %s params\n",
-				       rsparm.valid ? "with" : "without");
-				
-				isdn_ppp_ccp_reset_trans(ri, &rsparm);
-				break;
-			case DECOMP_FATALERROR:
-				ri->pppcfg |= SC_DC_FERROR;
-				/* Kick ipppd to recognize the error */
-				isdn_ppp_ccp_kickup(ri);
-				break;
-			}
-			kfree_skb(skb_out);
-			return NULL;
-		}
-		*proto = isdn_ppp_strip_proto(skb_out);
-		if (*proto < 0) {
-			kfree_skb(skb_out);
-			return NULL;
-		}
-		return skb_out;
-	} else { 
-		// uncompressed packets are fed through the decompressor to
-		// update the decompressor state
-		ipc->incomp(stat, skb, *proto);
-		return skb;
+	if (list_empty(&lp->online)) {
+		isdn_BUG();
+		return NULL;
 	}
+	idev = list_entry(lp->online.next, isdn_net_dev, online);
+	return __isdn_ppp_alloc_skb(idev, len, gfp_mask);
 }
 
-/*
- * compress a frame 
- *   type=0: normal/bundle compression
- *       =1: link compression
- * returns original skb if we haven't compressed the frame
- * and a new skb pointer if we've done it
- */
-static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
-	struct ippp_struct *is,struct ippp_struct *master,int type)
+static void
+isdn_ppp_dev_push_header(void *priv, struct sk_buff *skb, u16 proto)
 {
-    int ret;
-    int new_proto;
-    struct isdn_ppp_compressor *compressor;
-    void *stat;
-    struct sk_buff *skb_out;
-
-	/* we do not compress control protocols */
-    if(*proto < 0 || *proto > 0x3fff) {
-	    return skb_in;
-    }
-
-	if(type) { /* type=1 => Link compression */
-		return skb_in;
-	}
-	else {
-		if(!master) {
-			compressor = is->compressor;
-			stat = is->comp_stat;
-		}
-		else {
-			compressor = master->compressor;
-			stat = master->comp_stat;
-		}
-		new_proto = PPP_COMP;
-	}
+	isdn_net_dev *idev = priv;
 
-	if(!compressor) {
-		printk(KERN_ERR "isdn_ppp: No compressor set!\n");
-		return skb_in;
-	}
-	if(!stat) {
-		printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
-		return skb_in;
-	}
-
-	/* Allow for at least 150 % expansion (for now) */
-	skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 +
-		skb_headroom(skb_in), GFP_ATOMIC);
-	if(!skb_out)
-		return skb_in;
-	skb_reserve(skb_out, skb_headroom(skb_in));
-
-	ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
-	if(!ret) {
-		dev_kfree_skb(skb_out);
-		return skb_in;
-	}
-	
-	dev_kfree_skb(skb_in);
-	*proto = new_proto;
-	return skb_out;
+	isdn_ppp_push_header(idev, skb, proto);
 }
 
-/*
- * we received a CCP frame .. 
- * not a clean solution, but we MUST handle a few cases in the kernel
- */
-static void isdn_ppp_receive_ccp(isdn_net_dev *idev, isdn_net_local *lp,
-	 struct sk_buff *skb,int proto)
+static void
+isdn_ppp_lp_push_header(void *priv, struct sk_buff *skb, u16 proto)
 {
-	struct ippp_struct *is;
-	struct ippp_struct *mis;
-	int len;
-	struct isdn_ppp_resetparams rsparm;
-	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];	
+	isdn_net_local *lp = priv;
+	isdn_net_dev *idev;
 
-	printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
-	       idev->ppp_slot);
-	if (idev->ppp_slot < 0 || idev->ppp_slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
-		       __FUNCTION__ , idev->ppp_slot);
+	if (list_empty(&lp->online)) {
+		isdn_BUG();
 		return;
 	}
-	is = ippp_table[idev->ppp_slot];
-	isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
-
-	mis = is;
-
-	switch(skb->data[0]) {
-	case CCP_CONFREQ:
-		if(is->debug & 0x10)
-			printk(KERN_DEBUG "Disable compression here!\n");
-		if(proto == PPP_CCP)
-			mis->compflags &= ~SC_COMP_ON;		
-		else
-			is->compflags &= ~SC_LINK_COMP_ON;		
-		break;
-	case CCP_TERMREQ:
-	case CCP_TERMACK:
-		if(is->debug & 0x10)
-			printk(KERN_DEBUG "Disable (de)compression here!\n");
-		if(proto == PPP_CCP)
-			mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);		
-		else
-			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);		
-		break;
-	case CCP_CONFACK:
-		/* if we RECEIVE an ackowledge we enable the decompressor */
-		if(is->debug & 0x10)
-			printk(KERN_DEBUG "Enable decompression here!\n");
-		if(proto == PPP_CCP) {
-			if (!mis->decompressor)
-				break;
-			mis->compflags |= SC_DECOMP_ON;
-		} else {
-			if (!is->decompressor)
-				break;
-			is->compflags |= SC_LINK_DECOMP_ON;
-		}
-		break;
-
-	case CCP_RESETACK:
-		printk(KERN_DEBUG "Received ResetAck from peer\n");
-		len = (skb->data[2] << 8) | skb->data[3];
-		len -= 4;
-
-		if(proto == PPP_CCP) {
-			/* If a reset Ack was outstanding for this id, then
-			   clean up the state engine */
-			isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
-			if(mis->decompressor && mis->decomp_stat)
-				mis->decompressor->
-					reset(mis->decomp_stat,
-					      skb->data[0],
-					      skb->data[1],
-					      len ? &skb->data[4] : NULL,
-					      len, NULL);
-			/* TODO: This is not easy to decide here */
-			mis->compflags &= ~SC_DECOMP_DISCARD;
-		}
-		else {
-			isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
-			if(is->link_decompressor && is->link_decomp_stat)
-				is->link_decompressor->
-					reset(is->link_decomp_stat,
-					      skb->data[0],
-					      skb->data[1],
-					      len ? &skb->data[4] : NULL,
-					      len, NULL);
-			/* TODO: neither here */
-			is->compflags &= ~SC_LINK_DECOMP_DISCARD;
-		}
-		break;
-
-	case CCP_RESETREQ:
-		printk(KERN_DEBUG "Received ResetReq from peer\n");
-		/* Receiving a ResetReq means we must reset our compressor */
-		/* Set up reset params for the reset entry */
-		memset(&rsparm, 0, sizeof(rsparm));
-		rsparm.data = rsdata;
-		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; 
-		/* Isolate data length */
-		len = (skb->data[2] << 8) | skb->data[3];
-		len -= 4;
-		if(proto == PPP_CCP) {
-			if(mis->compressor && mis->comp_stat)
-				mis->compressor->
-					reset(mis->comp_stat,
-					      skb->data[0],
-					      skb->data[1],
-					      len ? &skb->data[4] : NULL,
-					      len, &rsparm);
-		}
-		else {
-			if(is->link_compressor && is->link_comp_stat)
-				is->link_compressor->
-					reset(is->link_comp_stat,
-					      skb->data[0],
-					      skb->data[1],
-					      len ? &skb->data[4] : NULL,
-					      len, &rsparm);
-		}
-		/* Ack the Req as specified by rsparm */
-		if(rsparm.valid) {
-			/* Compressor reset handler decided how to answer */
-			if(rsparm.rsend) {
-				/* We should send a Frame */
-				isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
-							rsparm.idval ? rsparm.id
-							: skb->data[1],
-							rsparm.dtval ?
-							rsparm.data : NULL,
-							rsparm.dtval ?
-							rsparm.dlen : 0);
-			} else {
-				printk(KERN_DEBUG "ResetAck suppressed\n");
-			}
-		} else {
-			/* We answer with a straight reflected Ack */
-			isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
-						skb->data[1],
-						len ? &skb->data[4] : NULL,
-						len);
-		}
-		break;
-	}
+	idev = list_entry(lp->online.next, isdn_net_dev, online);
+	isdn_ppp_push_header(idev, skb, proto);
 }
 
+static void
+isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb)
+{
+	isdn_net_dev *idev = priv;
 
-/*
- * Daemon sends a CCP frame ...
- */
-
-/* TODO: Clean this up with new Reset semantics */
-
-/* I believe the CCP handling as-is is done wrong. Compressed frames
- * should only be sent/received after CCP reaches UP state, which means
- * both sides have sent CONF_ACK. Currently, we handle both directions
- * independently, which means we may accept compressed frames too early
- * (supposedly not a problem), but may also mean we send compressed frames
- * too early, which may turn out to be a problem.
- * This part of state machine should actually be handled by (i)pppd, but
- * that's too big of a change now. --kai
- */
-
-/* Actually, we might turn this into an advantage: deal with the RFC in
- * the old tradition of beeing generous on what we accept, but beeing
- * strict on what we send. Thus we should just
- * - accept compressed frames as soon as decompression is negotiated
- * - send compressed frames only when decomp *and* comp are negotiated
- * - drop rx compressed frames if we cannot decomp (instead of pushing them
- *   up to ipppd)
- * and I tried to modify this file according to that. --abp
- */
+	isdn_net_write_super(idev, skb);
+}
 
-static void isdn_ppp_send_ccp(isdn_net_dev *idev, isdn_net_local *lp, struct sk_buff *skb)
+static void
+isdn_ppp_lp_xmit(void *priv, struct sk_buff *skb)
 {
-	struct ippp_struct *mis,*is;
-	int proto, slot = idev->ppp_slot;
-	unsigned char *data;
-
-	if(!skb || skb->len < 3)
-		return;
-	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
-		       __FUNCTION__ , slot);
-		return;
-	}	
-	is = ippp_table[slot];
-	/* Daemon may send with or without address and control field comp */
-	data = skb->data;
-	if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
-		data += 2;
-		if(skb->len < 5)
-			return;
-	}
+	isdn_net_local *lp = priv;
+	isdn_net_dev *idev;
 
-	proto = ((int)data[0]<<8)+data[1];
-	if(proto != PPP_CCP && proto != PPP_CCPFRAG)
+	if (list_empty(&lp->online)) {
+		isdn_BUG();
 		return;
-
-	printk(KERN_DEBUG "Received CCP frame from daemon:\n");
-	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
-
-	mis = is;
-	if (mis != is)
-		printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
-	
-        switch(data[2]) {
-	case CCP_CONFREQ:
-		if(is->debug & 0x10)
-			printk(KERN_DEBUG "Disable decompression here!\n");
-		if(proto == PPP_CCP)
-			is->compflags &= ~SC_DECOMP_ON;
-		else
-			is->compflags &= ~SC_LINK_DECOMP_ON;
-		break;
-	case CCP_TERMREQ:
-	case CCP_TERMACK:
-		if(is->debug & 0x10)
-			printk(KERN_DEBUG "Disable (de)compression here!\n");
-		if(proto == PPP_CCP)
-			is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
-		else
-			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
-		break;
-	case CCP_CONFACK:
-		/* if we SEND an ackowledge we can/must enable the compressor */
-		if(is->debug & 0x10)
-			printk(KERN_DEBUG "Enable compression here!\n");
-		if(proto == PPP_CCP) {
-			if (!is->compressor)
-				break;
-			is->compflags |= SC_COMP_ON;
-		} else {
-			if (!is->compressor)
-				break;
-			is->compflags |= SC_LINK_COMP_ON;
-		}
-		break;
-	case CCP_RESETACK:
-		/* If we send a ACK we should reset our compressor */
-		if(is->debug & 0x10)
-			printk(KERN_DEBUG "Reset decompression state here!\n");
-		printk(KERN_DEBUG "ResetAck from daemon passed by\n");
-		if(proto == PPP_CCP) {
-			/* link to master? */
-			if(is->compressor && is->comp_stat)
-				is->compressor->reset(is->comp_stat, 0, 0,
-						      NULL, 0, NULL);
-			is->compflags &= ~SC_COMP_DISCARD;	
-		}
-		else {
-			if(is->link_compressor && is->link_comp_stat)
-				is->link_compressor->reset(is->link_comp_stat,
-							   0, 0, NULL, 0, NULL);
-			is->compflags &= ~SC_LINK_COMP_DISCARD;	
-		}
-		break;
-	case CCP_RESETREQ:
-		/* Just let it pass by */
-		printk(KERN_DEBUG "ResetReq from daemon passed by\n");
-		break;
 	}
+	idev = list_entry(lp->online.next, isdn_net_dev, online);
+	isdn_net_write_super(idev, skb);
 }
 
-int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
+static int
+isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *data)
 {
-	ipc->next = ipc_head;
-	ipc->prev = NULL;
-	if(ipc_head) {
-		ipc_head->prev = ipc;
-	}
-	ipc_head = ipc;
-	return 0;
-}
+	struct ippp_ccp *ccp;
 
-int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
-{
-	if(ipc->prev)
-		ipc->prev->next = ipc->next;
+	if (data->flags & IPPP_COMP_FLAG_LINK)
+		ccp = idev->ccp;
 	else
-		ipc_head = ipc->next;
-	if(ipc->next)
-		ipc->next->prev = ipc->prev;
-	ipc->prev = ipc->next = NULL;
-	return 0;
-}
+		ccp = idev->mlp->ccp;
 
-static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
-{
-	struct isdn_ppp_compressor *ipc = ipc_head;
-	int ret;
-	void *stat;
-	int num = data->num;
-
-	if(is->debug & 0x10)
-		printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
-			(data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
-
-	/* If is has no valid reset state vector, we cannot allocate a
-	   decompressor. The decompressor would cause reset transactions
-	   sooner or later, and they need that vector. */
-
-	if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
-		printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
-		       " allow decompression.\n");
-		return -ENOMEM;
-	}
-
-	while(ipc) {
-		if(ipc->num == num) {
-			stat = ipc->alloc(data);
-			if(stat) {
-				ret = ipc->init(stat,data,is->unit,0);
-				if(!ret) {
-					printk(KERN_ERR "Can't init (de)compression!\n");
-					ipc->free(stat);
-					stat = NULL;
-					break;
-				}
-			}
-			else {
-				printk(KERN_ERR "Can't alloc (de)compression!\n");
-				break;
-			}
-
-                        if(data->flags & IPPP_COMP_FLAG_XMIT) {
-				if(data->flags & IPPP_COMP_FLAG_LINK) {
-					if(is->link_comp_stat)
-						is->link_compressor->free(is->link_comp_stat);
-					is->link_comp_stat = stat;
-                                	is->link_compressor = ipc;
-				}
-				else {
-					if(is->comp_stat)
-						is->compressor->free(is->comp_stat);
-					is->comp_stat = stat;
-                                	is->compressor = ipc;
-				}
-			}
-                        else {
-				if(data->flags & IPPP_COMP_FLAG_LINK) {
-					if(is->link_decomp_stat)
-						is->link_decompressor->free(is->link_decomp_stat);
-					is->link_decomp_stat = stat;
-        	                        is->link_decompressor = ipc;
-				}
-				else {
-					if(is->decomp_stat)
-						is->decompressor->free(is->decomp_stat);
-					is->decomp_stat = stat;
-        	                        is->decompressor = ipc;
-				}
-			}
-			return 0;
-		}
-		ipc = ipc->next;
-	}
-	return -EINVAL;
+	return ippp_ccp_set_compressor(ccp, idev->ipppd->unit, data);
 }
 
 // ISDN_NET_ENCAP_SYNCPPP
 // ======================================================================
 
 static int
-isdn_ppp_header(struct sk_buff *skb, struct net_device *dev,
-		unsigned short type, void *daddr, void *saddr, 
-		unsigned plen)
+isdn_ppp_open(isdn_net_local *lp)
 {
-	skb_push(skb, IPPP_MAX_HEADER);
+	lp->mpppcfg = 0;        /* mppp configuration */
+	lp->mp_seqno = 0;       /* MP sequence number */
 
-	return IPPP_MAX_HEADER;
+#ifdef CONFIG_ISDN_PPP_VJ
+	lp->slcomp = slhc_init(16, 16);
+#endif
+	lp->ccp = ippp_ccp_alloc();
+	if (!lp->ccp)
+		return -ENOMEM;
+	lp->ccp->proto       = PPP_COMP;
+	lp->ccp->priv        = lp;
+	lp->ccp->alloc_skb   = isdn_ppp_lp_alloc_skb;
+	lp->ccp->push_header = isdn_ppp_lp_push_header;
+	lp->ccp->xmit        = isdn_ppp_lp_xmit;
+	lp->ccp->kick_up     = isdn_ppp_lp_kick_up;
+
+	return 0;
+}
+
+static void
+isdn_ppp_close(isdn_net_local *lp)
+{
+#ifdef CONFIG_ISDN_PPP_VJ
+	slhc_free(lp->slcomp);
+	lp->slcomp = NULL;
+#endif
+	ippp_ccp_free(lp->ccp);
+	lp->ccp = NULL;
 }
 
 struct isdn_netif_ops isdn_ppp_ops = {
 	.hard_start_xmit     = isdn_ppp_start_xmit,
-	.hard_header         = isdn_ppp_header,
 	.do_ioctl            = isdn_ppp_dev_ioctl,
 	.flags               = IFF_NOARP | IFF_POINTOPOINT,
 	.type                = ARPHRD_PPP,
 	.receive             = isdn_ppp_receive,
-	.connected           = isdn_ppp_wakeup_daemon,
+	.connected           = isdn_ppp_connected,
+	.disconnected        = isdn_ppp_disconnected,
 	.bind                = isdn_ppp_bind,
-	.unbind              = isdn_ppp_free,
-	
+	.unbind              = isdn_ppp_unbind,
+	.open                = isdn_ppp_open,
+	.close               = isdn_ppp_close,
 };
diff -Nru a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h
--- a/drivers/isdn/i4l/isdn_ppp.h	Fri Oct 18 21:03:04 2002
+++ b/drivers/isdn/i4l/isdn_ppp.h	Fri Oct 18 21:03:04 2002
@@ -15,17 +15,15 @@
 extern struct file_operations isdn_ppp_fops;
 extern struct isdn_netif_ops isdn_ppp_ops;
 
-extern int isdn_ppp_init(void);
-extern void isdn_ppp_cleanup(void);
-extern int isdn_ppp_dial_slave(char *);
-extern int isdn_ppp_hangup_slave(char *);
+int isdn_ppp_init(void);
+void isdn_ppp_cleanup(void);
+int isdn_ppp_dial_slave(char *);
+int isdn_ppp_hangup_slave(char *);
 
-#define IPPP_OPEN	0x01
-#define IPPP_CONNECT	0x02
-#define IPPP_CLOSEWAIT	0x04
-#define IPPP_NOBLOCK	0x08
-#define IPPP_ASSIGNED	0x10
+void
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen, 
+		   int unit, int slot);
+int
+isdn_ppp_strip_proto(struct sk_buff *skb);
 
 #define IPPP_MAX_HEADER 10
-
-
diff -Nru a/drivers/isdn/i4l/isdn_ppp_ccp.c b/drivers/isdn/i4l/isdn_ppp_ccp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/isdn/i4l/isdn_ppp_ccp.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,601 @@
+
+#include "isdn_ppp_ccp.h"
+#include "isdn_common.h"
+#include "isdn_net.h"
+#include "isdn_ppp.h"
+#include <linux/ppp-comp.h>
+
+/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
+   but absolutely nontrivial. The most abstruse problem we are facing is
+   that the generation, reception and all the handling of timeouts and
+   resends including proper request id management should be entirely left
+   to the (de)compressor, but indeed is not covered by the current API to
+   the (de)compressor. The API is a prototype version from PPP where only
+   some (de)compressors have yet been implemented and all of them are
+   rather simple in their reset handling. Especially, their is only one
+   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
+   not have parameters. For this very special case it was sufficient to
+   just return an error code from the decompressor and have a single
+   reset() entry to communicate all the necessary information between
+   the framework and the (de)compressor. Bad enough, LZS is different
+   (and any other compressor may be different, too). It has multiple
+   histories (eventually) and needs to Reset each of them independently
+   and thus uses multiple outstanding Acks and history numbers as an
+   additional parameter to Reqs/Acks.
+   All that makes it harder to port the reset state engine into the
+   kernel because it is not just the same simple one as in (i)pppd but
+   it must be able to pass additional parameters and have multiple out-
+   standing Acks. We are trying to achieve the impossible by handling
+   reset transactions independent by their id. The id MUST change when
+   the data portion changes, thus any (de)compressor who uses more than
+   one resettable state must provide and recognize individual ids for
+   each individual reset transaction. The framework itself does _only_
+   differentiate them by id, because it has no other semantics like the
+   (de)compressor might.
+   This looks like a major redesign of the interface would be nice,
+   but I don't have an idea how to do it better. */
+
+/* ====================================================================== */
+
+/* Free a given state and clear everything up for later reallocation */
+static void
+ippp_ccp_reset_free_state(struct ippp_ccp *ccp, unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs	= ccp->reset->rs[id];
+
+	if (!rs)
+		return;
+	
+	if (rs->ta) // FIXME?
+		del_timer_sync(&rs->timer);
+
+	kfree(rs);
+	ccp->reset->rs[id] = NULL;
+}
+
+static void
+do_xmit_reset(struct ippp_ccp *ccp, unsigned char code, unsigned char id,
+	      unsigned char *data, int len)
+{
+	struct sk_buff *skb;
+	unsigned char *p;
+	u16 proto = ccp->proto == PPP_COMP ? PPP_CCP : PPP_CCPFRAG;
+
+	skb = ccp->alloc_skb(ccp->priv, 4 + len, GFP_ATOMIC);
+	ccp->push_header(ccp->priv, skb, proto);
+
+	p = skb_put(skb, 4);
+	p += put_u8 (p, code);
+	p += put_u8 (p, id);
+	p += put_u16(p, len + 4);
+
+	if (len)
+		memcpy(skb_put(skb, len), data, len);
+
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1);
+
+	ccp->xmit(ccp->priv, skb);
+}
+
+/* The timer callback function which is called when a ResetReq has timed out,
+   aka has never been answered by a ResetAck */
+static void
+isdn_ppp_ccp_timer_callback(unsigned long data)
+{
+	struct ippp_ccp_reset_state *rs = (struct ippp_ccp_reset_state *) data;
+
+	if (!rs->ta) {
+		isdn_BUG();
+		return;
+	}
+	if (rs->state != CCPResetSentReq) {
+		printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
+		       rs->state);
+		rs->ta = 0;
+		return;
+	}
+	/* We are correct here */
+	if (!rs->expra) {
+		/* Hmm, there is no Ack really expected. We can clean
+		   up the state now, it will be reallocated if the
+		   decompressor insists on another reset */
+		rs->ta = 0;
+		ippp_ccp_reset_free_state(rs->ccp, rs->id);
+		return;
+	}
+	printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
+	       rs->id);
+	/* Push it again */
+	do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen);
+
+	mod_timer(&rs->timer, jiffies + 5 * HZ);
+}
+
+/* Allocate a new reset transaction state */
+static struct ippp_ccp_reset_state *
+ippp_ccp_reset_alloc_state(struct ippp_ccp *ccp, unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs;
+
+	rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+	if(!rs)
+		return NULL;
+	memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
+	rs->state = CCPResetIdle;
+	rs->ccp = ccp;
+	rs->id = id;
+	init_timer(&rs->timer);
+	rs->timer.data = (unsigned long)rs;
+	rs->timer.function = isdn_ppp_ccp_timer_callback;
+
+	ccp->reset->rs[id] = rs;
+	return rs;
+}
+
+/* A decompressor wants a reset with a set of parameters - do what is
+   necessary to fulfill it */
+static void
+ippp_ccp_reset_xmit(struct ippp_ccp *ccp,
+		    struct isdn_ppp_resetparams *rp)
+{
+	struct ippp_ccp_reset_state *rs;
+	int id;
+
+	if (rp->valid) {
+		/* The decompressor defines parameters by itself */
+		if (!rp->rsend)
+			return;
+
+		/* And it wants us to send a request */
+		if (!rp->idval) {
+			isdn_BUG();
+			return;
+		}
+		id = rp->id;
+	} else {
+		/* The reset params are invalid. The decompressor does not
+		   care about them, so we just send the minimal requests
+		   and increase ids only when an Ack is received for a
+		   given id */
+		id = ccp->reset->lastid++;
+		/* We always expect an Ack if the decompressor doesnt
+		   know	better */
+		rp->expra = 1;
+		rp->dtval = 0;
+	}
+	rs = ccp->reset->rs[id];
+	if (rs) {
+		printk(KERN_INFO "ippp_ccp: reset xmit in wrong state %d "
+		       "for id %d (%d)\n", rs->state, id, rs->ta);
+		return;
+	}
+	/* Ok, this is a new transaction */
+	printk(KERN_DEBUG "ippp_ccp: new xmit for id %d\n", id);
+	rs = ippp_ccp_reset_alloc_state(ccp, id);
+	if(!rs) {
+		printk(KERN_INFO "ippp_ccp: out of mem allocing ccp trans\n");
+		return;
+	}
+	rs->expra = rp->expra;
+	rs->id = id;
+	if (rp->dtval) {
+		rs->dlen = rp->dlen;
+		memcpy(rs->data, rp->data, rp->dlen);
+	} else {
+		rs->dlen = 0;
+	}
+
+	rs->state = CCPResetSentReq;
+	do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen);
+
+	/* Start the timer */
+	rs->timer.expires = jiffies + 5*HZ;
+	add_timer(&rs->timer);
+	rs->ta = 1;
+}
+
+/* ====================================================================== */
+
+struct ippp_ccp *
+ippp_ccp_alloc(void)
+{
+	struct ippp_ccp *ccp;
+
+	ccp = kmalloc(sizeof(*ccp), GFP_ATOMIC); // FIXME
+	memset(ccp, 0, sizeof(*ccp));
+	ccp->mru = 1524;      /* MRU, default 1524 */
+	ccp->reset = kmalloc(sizeof(*ccp->reset), GFP_ATOMIC); // FIXME alloc together?
+	if (!ccp->reset) {
+		kfree(ccp);
+		return NULL;
+	}
+	memset(ccp->reset, 0, sizeof(*ccp->reset));
+	return ccp;
+}
+
+void
+ippp_ccp_free(struct ippp_ccp *ccp)
+{
+	int id;
+
+	if (ccp->comp_stat)
+		ccp->compressor->free(ccp->comp_stat);
+	if (ccp->decomp_stat)
+		ccp->decompressor->free(ccp->decomp_stat);
+
+	for (id = 0; id < 256; id++) {
+		if (ccp->reset->rs[id])
+			ippp_ccp_reset_free_state(ccp, id);
+	}
+	kfree(ccp->reset);
+	kfree(ccp);
+}
+
+int
+ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru)
+{
+	ccp->mru = mru;
+	return 0;
+}
+
+unsigned int
+ippp_ccp_get_flags(struct ippp_ccp *ccp)
+{
+	return ccp->compflags & (SC_DC_ERROR|SC_DC_FERROR);
+}
+
+/*
+ * compress a frame 
+ * returns original skb if we did not compress the frame
+ * and a new skb otherwise
+ */
+struct sk_buff *
+ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto)
+{
+	struct sk_buff *skb;
+
+	if (!(ccp->compflags & (SC_COMP_ON|SC_DECOMP_ON))) {
+		/* We send compressed only if both down- und upstream
+		   compression is negotiated, that means, CCP is up */
+		return skb_in;
+	}
+	/* we do not compress control protocols */
+	if (*proto < 0 || *proto > 0x3fff) {
+		return skb_in;
+	}
+	if (!ccp->compressor || !ccp->comp_stat) {
+		isdn_BUG();
+		return skb_in;
+	}
+	/* Allow for at least 150 % expansion (for now) */
+	skb = alloc_skb(skb_in->len*2 + skb_headroom(skb_in), GFP_ATOMIC);
+	if (!skb)
+		return skb_in;
+
+	skb_reserve(skb, skb_headroom(skb_in));
+	if (!ccp->compressor->compress(ccp->comp_stat, skb_in, skb, *proto)) {
+		dev_kfree_skb(skb);
+		return skb_in;
+	}
+	isdn_ppp_frame_log("comp  in:", skb_in->data, skb_in->len, 20, -1, -1);
+	isdn_ppp_frame_log("comp out:", skb->data, skb->len, 20, -1, -1);
+	dev_kfree_skb(skb_in);
+	*proto = ccp->proto;
+	return skb;
+}
+
+/* 
+ * decompress packet
+ *
+ * proto is updated to protocol field of uncompressed packet.
+ * retval: decompressed packet,
+ *         same packet if uncompressed,
+ *	   NULL if decompression error
+ */
+
+struct sk_buff *
+ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto)
+{
+	struct sk_buff *skb;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+	int len;
+
+	if (!(ccp->compflags & SC_DECOMP_ON)) {
+		return skb_in;
+	}
+	if (!ccp->decompressor || !ccp->decomp_stat) {
+		isdn_BUG();
+		return skb_in;
+	}
+	if (*proto != ccp->proto) {
+		/* uncompressed packets are fed through the decompressor to
+		 * update the decompressor state */
+		ccp->decompressor->incomp(ccp->decomp_stat, skb_in, *proto);
+		return skb_in;
+	}
+	skb = dev_alloc_skb(ccp->mru + PPP_HDRLEN); // FIXME oom?
+
+	// Set up reset params for the decompressor
+	memset(&rsparm, 0, sizeof(rsparm));
+	rsparm.data = rsdata;
+	rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+
+	len = ccp->decompressor->decompress(ccp->decomp_stat, skb_in, skb,
+					    &rsparm);
+	isdn_ppp_frame_log("deco  in:", skb_in->data, skb_in->len, 20, -1, -1);
+	isdn_ppp_frame_log("deco out:", skb->data, skb->len, 20, -1, -1);
+	kfree_skb(skb_in);
+
+	if (len <= 0) {
+		switch(len) {
+		case DECOMP_ERROR:
+			printk(KERN_INFO "ippp: decomp wants reset with%s params\n",
+			       rsparm.valid ? "" : "out");
+			
+			ippp_ccp_reset_xmit(ccp, &rsparm);
+			break;
+		case DECOMP_FATALERROR:
+			ccp->compflags |= SC_DC_FERROR;
+			/* Kick ipppd to recognize the error */
+			ccp->kick_up(ccp->priv);
+			break;
+		}
+		kfree_skb(skb);
+		return NULL;
+	}
+	*proto = isdn_ppp_strip_proto(skb);
+	if (*proto < 0) {
+		kfree_skb(skb);
+		return NULL;
+	}
+	return skb;
+}
+
+/* An Ack was received for this id. This means we stop the timer and clean
+   up the state prior to calling the decompressors reset routine. */
+static void
+isdn_ppp_ccp_reset_ack_rcvd(struct ippp_ccp *ccp, unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs = ccp->reset->rs[id];
+
+	if (!rs) {
+		printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
+		       " %d\n", id);
+		return;
+	}
+
+	if (rs->ta && rs->state == CCPResetSentReq) {
+		/* Great, we are correct */
+		if(!rs->expra)
+			printk(KERN_DEBUG "ippp_ccp: ResetAck received"
+			       " for id %d but not expected\n", id);
+	} else {
+		printk(KERN_INFO "ippp_ccp: ResetAck received out of"
+		       "sync for id %d\n", id);
+	}
+	if(rs->ta) {
+		rs->ta = 0;
+		del_timer(&rs->timer);
+	}
+	ippp_ccp_reset_free_state(ccp, id);
+}
+
+void
+ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb)
+{
+	int len;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];	
+
+	isdn_ppp_frame_log("ccp-recv", skb->data, skb->len, 32, -1, -1);
+
+	switch(skb->data[0]) {
+	case CCP_CONFREQ:
+		if (ccp->debug & 0x10)
+			printk(KERN_DEBUG "Disable compression here!\n");
+
+		ccp->compflags &= ~SC_COMP_ON;		
+		break;
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if (ccp->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+
+		ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);		
+		break;
+	case CCP_CONFACK:
+		/* if we RECEIVE an ackowledge we enable the decompressor */
+		if (ccp->debug & 0x10)
+			printk(KERN_DEBUG "Enable decompression here!\n");
+
+		if (!ccp->decomp_stat)
+			break;
+		ccp->compflags |= SC_DECOMP_ON;
+		break;
+	case CCP_RESETACK:
+		printk(KERN_DEBUG "Received ResetAck from peer\n");
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+
+		/* If a reset Ack was outstanding for this id, then
+		   clean up the state engine */
+		isdn_ppp_ccp_reset_ack_rcvd(ccp, skb->data[1]);
+		if (ccp->decomp_stat)
+			ccp->decompressor->reset(ccp->decomp_stat,
+						 skb->data[0], skb->data[1],
+						 len ? &skb->data[4] : NULL,
+						 len, NULL);
+		/* TODO: This is not easy to decide here */
+		ccp->compflags &= ~SC_DECOMP_DISCARD;
+		break;
+	case CCP_RESETREQ:
+		printk(KERN_DEBUG "Received ResetReq from peer\n");
+		/* Receiving a ResetReq means we must reset our compressor */
+		/* Set up reset params for the reset entry */
+		memset(&rsparm, 0, sizeof(rsparm));
+		rsparm.data = rsdata;
+		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; 
+		/* Isolate data length */
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+		if (ccp->comp_stat)
+			ccp->compressor->reset(ccp->comp_stat,
+					       skb->data[0], skb->data[1],
+					       len ? &skb->data[4] : NULL,
+					       len, &rsparm);
+		/* Ack the Req as specified by rsparm */
+		if (rsparm.valid) {
+			/* Compressor reset handler decided how to answer */
+			if (!rsparm.rsend) {
+				printk(KERN_DEBUG "ResetAck suppressed\n");
+				return;
+			}
+			/* We should send a Frame */
+			do_xmit_reset(ccp, CCP_RESETACK,
+				      rsparm.idval ? rsparm.id : skb->data[1],
+				      rsparm.data,
+				      rsparm.dtval ? rsparm.dlen : 0);
+			return;
+		}
+		/* We answer with a straight reflected Ack */
+		do_xmit_reset(ccp, CCP_RESETACK, skb->data[1], 
+			      skb->data + 4, len);
+	}
+}
+
+void
+ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb)
+{
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1);
+
+        switch (skb->data[2]) {
+	case CCP_CONFREQ:
+		if (ccp->debug & 0x10)
+			printk(KERN_DEBUG "Disable decompression here!\n");
+
+		ccp->compflags &= ~SC_DECOMP_ON;
+		break;
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if (ccp->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+
+		ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+		break;
+	case CCP_CONFACK:
+		/* if we SEND an ackowledge we can/must enable the compressor */
+		if (ccp->debug & 0x10)
+			printk(KERN_DEBUG "Enable compression here!\n");
+
+		if (!ccp->compressor)
+			break;
+
+		ccp->compflags |= SC_COMP_ON;
+		break;
+	case CCP_RESETACK:
+		/* If we send a ACK we should reset our compressor */
+		if (ccp->debug & 0x10)
+			printk(KERN_DEBUG "Reset decompression state here!\n");
+
+		printk(KERN_DEBUG "ResetAck from daemon passed by\n");
+
+		if (!ccp->comp_stat)
+			break;
+
+		ccp->compressor->reset(ccp->comp_stat, 0, 0, NULL, 0, NULL);
+		ccp->compflags &= ~SC_COMP_DISCARD;	
+		break;
+	case CCP_RESETREQ:
+		/* Just let it pass by */
+		printk(KERN_DEBUG "ResetReq from daemon passed by\n");
+		break;
+	}
+}
+
+static struct isdn_ppp_compressor *ipc_head = NULL;
+
+int
+ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
+			struct isdn_ppp_comp_data *data)
+{
+	struct isdn_ppp_compressor *ipc = ipc_head;
+	int ret;
+	void *stat;
+	int num = data->num;
+
+	if (ccp->debug & 0x10)
+		printk(KERN_DEBUG "[%d] Set %scompressor type %d\n", unit,
+		       data->flags & IPPP_COMP_FLAG_XMIT ? "" : "de", num);
+
+	for (ipc = ipc_head; ipc; ipc = ipc->next) {
+		if (ipc->num != num)
+			continue;
+		
+		stat = ipc->alloc(data);
+		if (!stat) {
+			printk(KERN_ERR "Can't alloc (de)compression!\n");
+			break;
+		}
+		ret = ipc->init(stat, data, unit, 0);
+		if(!ret) {
+			printk(KERN_ERR "Can't init (de)compression!\n");
+			ipc->free(stat);
+			break;
+		}
+		if (data->flags & IPPP_COMP_FLAG_XMIT) {
+			if (ccp->comp_stat)
+				ccp->compressor->free(ccp->comp_stat);
+			ccp->comp_stat = stat;
+			ccp->compressor = ipc;
+		} else {
+			if (ccp->decomp_stat)
+				ccp->decompressor->free(ccp->decomp_stat);
+			ccp->decomp_stat = stat;
+			ccp->decompressor = ipc;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+
+void
+ippp_ccp_get_compressors(unsigned long protos[8])
+{
+	struct isdn_ppp_compressor *ipc;
+	int i, j;
+
+	memset(protos, 0, sizeof(unsigned long) * 8);
+	for (ipc = ipc_head; ipc; ipc = ipc->next) {
+		j = ipc->num / (sizeof(long)*8);
+		i = ipc->num % (sizeof(long)*8);
+		if (j < 8)
+			protos[j] |= 1 << i;
+	}
+}
+
+int
+isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
+{
+	ipc->next = ipc_head;
+	ipc->prev = NULL;
+	if (ipc_head) {
+		ipc_head->prev = ipc;
+	}
+	ipc_head = ipc;
+	return 0;
+}
+
+int
+isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
+{
+	if (ipc->prev)
+		ipc->prev->next = ipc->next;
+	else
+		ipc_head = ipc->next;
+	if (ipc->next)
+		ipc->next->prev = ipc->prev;
+	ipc->prev = ipc->next = NULL;
+	return 0;
+}
+
diff -Nru a/drivers/isdn/i4l/isdn_ppp_ccp.h b/drivers/isdn/i4l/isdn_ppp_ccp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/isdn/i4l/isdn_ppp_ccp.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,66 @@
+
+#include <linux/kernel.h>
+#include <linux/isdn_ppp.h>
+
+/* for ippp_ccp::flags */
+
+#define SC_DECOMP_ON		0x01
+#define SC_COMP_ON		0x02
+#define SC_DECOMP_DISCARD	0x04
+#define SC_COMP_DISCARD		0x08
+
+/* SC_DC_ERROR/FERROR go in here as well, but are defined elsewhere
+
+   #define SC_DC_FERROR	0x00800000
+   #define SC_DC_ERROR	0x00400000
+*/
+
+struct ippp_ccp {
+	int proto;
+	struct isdn_ppp_compressor *compressor;
+	struct isdn_ppp_compressor *decompressor;
+	void                       *comp_stat;
+	void                       *decomp_stat;
+	unsigned long               compflags;
+	struct ippp_ccp_reset      *reset;
+	int                         mru;
+	int                         debug;
+	void                       *priv;
+	void            (*xmit)(void *priv, struct sk_buff *skb);
+	void            (*kick_up)(void *priv);
+	void            (*push_header)(void *priv, struct sk_buff *skb, u16);
+	struct sk_buff *(*alloc_skb)(void *priv, int len, int gfp_mask);
+};
+
+struct ippp_ccp *
+ippp_ccp_alloc(void);
+
+void
+ippp_ccp_free(struct ippp_ccp *ccp);
+
+int
+ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru);
+
+unsigned int
+ippp_ccp_get_flags(struct ippp_ccp *ccp);
+
+struct sk_buff *
+ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb, int *proto);
+
+struct sk_buff *
+ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb, int *proto);
+
+void
+ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb);
+
+void
+ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb);
+
+void
+ippp_ccp_get_compressors(unsigned long protos[8]);
+
+int
+ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
+			struct isdn_ppp_comp_data *data);
+
+
diff -Nru a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
--- a/drivers/isdn/isdnloop/isdnloop.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/isdn/isdnloop/isdnloop.c	Fri Oct 18 21:03:03 2002
@@ -11,11 +11,12 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 #include "isdnloop.h"
 
 static char *revision = "$Revision: 1.11.6.7 $";
-static char *isdnloop_id;
+static char *isdnloop_id = "loop0";
 
 MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
 MODULE_AUTHOR("Fritz Elfert");
@@ -76,7 +77,7 @@
 			};
 			cmd.command = ISDN_STAT_BSENT;
 			cmd.parm.length = len;
-			if ( ack ) card->interface.statcallb(&cmd);
+			card->interface.statcallb(&cmd);
 		} else
 			card->sndcount[ch] = 0;
 	}
@@ -421,8 +422,9 @@
 			return 0;
 		save_flags(flags);
 		cli();
-		nskb = skb_clone(skb, GFP_ATOMIC);
+		nskb = dev_alloc_skb(skb->len);
 		if (nskb) {
+			memcpy(skb_put(nskb, len), skb->data, len);
 			skb_queue_tail(&card->bqueue[channel], nskb);
 			dev_kfree_skb(skb);
 		} else
diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c
--- a/drivers/md/linear.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/md/linear.c	Fri Oct 18 21:03:04 2002
@@ -28,6 +28,45 @@
 #define MD_PERSONALITY
 #define DEVICE_NR(device) (minor(device))
 
+/*
+ * find which device holds a particular offset 
+ */
+static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
+{
+	struct linear_hash *hash;
+	linear_conf_t *conf = mddev_to_conf(mddev);
+	sector_t block = sector >> 1;
+
+	hash = conf->hash_table + sector_div(block, conf->smallest->size);
+
+	if ((sector>>1) >= (hash->dev0->size + hash->dev0->offset))
+		return hash->dev1;
+	else
+		return hash->dev0;
+}
+
+
+/**
+ *	linear_mergeable_bvec -- tell bio layer if a two requests can be merged
+ *	@q: request queue
+ *	@bio: the buffer head that's been built up so far
+ *	@biovec: the request that could be merged to it.
+ *
+ *	Return 1 if the merge is not permitted (because the
+ *	result would cross a device boundary), 0 otherwise.
+ */
+static int linear_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec)
+{
+	mddev_t *mddev = q->queuedata;
+	dev_info_t *dev0, *dev1;
+
+	dev0 = which_dev(mddev, bio->bi_sector);
+	dev1 = which_dev(mddev, bio->bi_sector +
+			        ((bio->bi_size + biovec->bv_len - 1) >> 9));
+
+	return dev0 != dev1;
+}
+
 static int linear_run (mddev_t *mddev)
 {
 	linear_conf_t *conf;
@@ -110,6 +149,7 @@
 	if (table-conf->hash_table != nb_zone)
 		BUG();
 
+	blk_queue_merge_bvec(&mddev->queue, linear_mergeable_bvec);
 	return 0;
 
 out:
@@ -134,28 +174,23 @@
 static int linear_make_request (request_queue_t *q, struct bio *bio)
 {
 	mddev_t *mddev = q->queuedata;
-	linear_conf_t *conf = mddev_to_conf(mddev);
-	struct linear_hash *hash;
 	dev_info_t *tmp_dev;
-	long block;
+	sector_t block;
 
+	tmp_dev = which_dev(mddev, bio->bi_sector);
 	block = bio->bi_sector >> 1;
-	hash = conf->hash_table + (block / conf->smallest->size);
   
-	if (block >= (hash->dev0->size + hash->dev0->offset)) {
-		if (!hash->dev1) {
-			printk ("linear_make_request : hash->dev1==NULL for block %ld\n",
-						block);
-			bio_io_error(bio, bio->bi_size);
-			return 0;
-		}
-		tmp_dev = hash->dev1;
-	} else
-		tmp_dev = hash->dev0;
+	if (unlikely(!tmp_dev)) {
+		printk ("linear_make_request : hash->dev1==NULL for block %llu\n",
+			(unsigned long long)block);
+		bio_io_error(bio, bio->bi_size);
+		return 0;
+	}
     
-	if (block >= (tmp_dev->size + tmp_dev->offset)
-				|| block < tmp_dev->offset) {
-		printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, bdevname(tmp_dev->rdev->bdev), tmp_dev->size, tmp_dev->offset);
+	if (unlikely(block >= (tmp_dev->size + tmp_dev->offset)
+		     || block < tmp_dev->offset)) {
+		printk ("linear_make_request: Block %llu out of bounds on dev %s size %ld offset %ld\n",
+			(unsigned long long)block, bdevname(tmp_dev->rdev->bdev), tmp_dev->size, tmp_dev->offset);
 		bio_io_error(bio, bio->bi_size);
 		return 0;
 	}
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/md/md.c	Fri Oct 18 21:03:04 2002
@@ -200,6 +200,7 @@
 	INIT_LIST_HEAD(&new->disks);
 	INIT_LIST_HEAD(&new->all_mddevs);
 	atomic_set(&new->active, 1);
+	blk_queue_make_request(&new->queue, md_fail_request);
 
 	goto retry;
 }
@@ -1275,6 +1276,39 @@
 	return 1;
 }
 
+static struct gendisk *md_probe(dev_t dev, int *part, void *data)
+{
+	static DECLARE_MUTEX(disks_sem);
+	int unit = MINOR(dev);
+	mddev_t *mddev = mddev_find(unit);
+	struct gendisk *disk;
+
+	if (!mddev)
+		return NULL;
+
+	down(&disks_sem);
+	if (disks[unit]) {
+		up(&disks_sem);
+		mddev_put(mddev);
+		return NULL;
+	}
+	disk = alloc_disk(1);
+	if (!disk) {
+		up(&disks_sem);
+		mddev_put(mddev);
+		return NULL;
+	}
+	disk->major = MD_MAJOR;
+	disk->first_minor = mdidx(mddev);
+	sprintf(disk->disk_name, "md%d", mdidx(mddev));
+	disk->fops = &md_fops;
+	disk->private_data = mddev;
+	disk->queue = &mddev->queue;
+	add_disk(disk);
+	disks[mdidx(mddev)] = disk;
+	up(&disks_sem);
+	return NULL;
+}
 
 #define TOO_BIG_CHUNKSIZE KERN_ERR \
 "too big chunk_size: %d > %d\n"
@@ -1394,14 +1428,10 @@
 #endif
 	}
 
-	disk = alloc_disk(1);
+	md_probe(mdidx(mddev), NULL, NULL);
+	disk = disks[mdidx(mddev)];
 	if (!disk)
 		return -ENOMEM;
-	disk->major = MD_MAJOR;
-	disk->first_minor = mdidx(mddev);
-	sprintf(disk->disk_name, "md%d", mdidx(mddev));
-	disk->fops = &md_fops;
-
 	mddev->pers = pers[pnum];
 
 	blk_queue_make_request(&mddev->queue, mddev->pers->make_request);
@@ -1417,7 +1447,6 @@
 	if (err) {
 		printk(KERN_ERR "md: pers->run() failed ...\n");
 		mddev->pers = NULL;
-		put_disk(disk);
 		return -EINVAL;
 	}
 
@@ -1430,9 +1459,6 @@
 	md_update_sb(mddev);
 	md_recover_arrays();
 	set_capacity(disk, md_size[mdidx(mddev)]<<1);
-	add_disk(disk);
-	disks[mdidx(mddev)] = disk;
-
 	return (0);
 }
 
@@ -1543,13 +1569,8 @@
 
 		md_size[mdidx(mddev)] = 0;
 		disk = disks[mdidx(mddev)];
-		disks[mdidx(mddev)] = NULL;
-
-		if (disk) {
-			del_gendisk(disk);
-			put_disk(disk);
-		}
-
+		if (disk)
+			set_capacity(disk, 0);
 	} else
 		printk(KERN_INFO "md: md%d switched to read-only mode.\n", mdidx(mddev));
 	err = 0;
@@ -3083,18 +3104,6 @@
 #endif
 }
 
-request_queue_t * md_queue_proc(kdev_t dev)
-{
-	mddev_t *mddev = mddev_find(minor(dev));
-	request_queue_t *q = BLK_DEFAULT_QUEUE(MAJOR_NR);
-	if (mddev) {
-		if (mddev->pers)
-			q = &mddev->queue;
-		mddev_put(mddev);
-	}
-	return q;
-}
-
 int __init md_init(void)
 {
 	static char * name = "mdrecoveryd";
@@ -3109,6 +3118,8 @@
 		return (-1);
 	}
 	devfs_handle = 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) {
 		char devname[128];
 		sprintf (devname, "%u", minor);
@@ -3117,10 +3128,6 @@
 			S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL);
 	}
 
-	/* all requests on an uninitialised device get failed... */
-	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), md_fail_request);
-	blk_dev[MAJOR_NR].queue = md_queue_proc;
-
 	md_recovery_thread = md_register_thread(md_do_recovery, NULL, name);
 	if (!md_recovery_thread)
 		printk(KERN_ALERT
@@ -3447,6 +3454,8 @@
 
 void cleanup_module(void)
 {
+	int i;
+	blk_unregister_region(MKDEV(MAJOR_NR,0), MAX_MD_DEVS);
 	md_unregister_thread(md_recovery_thread);
 	devfs_unregister(devfs_handle);
 
@@ -3456,8 +3465,16 @@
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("mdstat", NULL);
 #endif
-
-	blk_dev[MAJOR_NR].queue = NULL;
+	for (i = 0; i < MAX_MD_DEVS; i++) {
+		struct gendisk *disk = disks[i];
+		mddev_t *mddev;
+		if (!disks[i])
+			continue;
+		mddev = disk->private_data;
+		del_gendisk(disk);
+		put_disk(disk);
+		mddev_put(mddev);
+	}
 }
 #endif
 
diff -Nru a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h
--- a/drivers/media/video/cpia.h	Fri Oct 18 21:03:08 2002
+++ b/drivers/media/video/cpia.h	Fri Oct 18 21:03:08 2002
@@ -386,11 +386,11 @@
 #define ERROR_FLICKER_BELOW_MIN_EXP     0x01 /*flicker exposure got below minimum exposure */
 
 #define ALOG(fmt,args...) printk(fmt, ##args)
-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__, __LINE__, ##args)
+#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args)
 
 #ifdef _CPIA_DEBUG_
 #define ADBG(lineno,fmt,args...) printk(fmt, jiffies, lineno, ##args)
-#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):"__FUNCTION__"(%d):"fmt,##args)
+#define DBG(fmt,args...) ADBG((__LINE__), KERN_DEBUG __FILE__" (%ld):" __FUNCTION__ "(%d):" fmt, ##args)
 #else
 #define DBG(fmn,args...) do {} while(0)
 #endif
diff -Nru a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h
--- a/drivers/message/fusion/linux_compat.h	Fri Oct 18 21:03:04 2002
+++ b/drivers/message/fusion/linux_compat.h	Fri Oct 18 21:03:04 2002
@@ -75,11 +75,11 @@
 typedef void (*__cleanup_module_func_t)(void);
 #define module_init(x) \
 	int init_module(void) __attribute__((alias(#x))); \
-	extern inline __init_module_func_t __init_module_inline(void) \
+	static inline __init_module_func_t __init_module_inline(void) \
 	{ return x; }
 #define module_exit(x) \
 	void cleanup_module(void) __attribute__((alias(#x))); \
-	extern inline __cleanup_module_func_t __cleanup_module_inline(void) \
+	static inline __cleanup_module_func_t __cleanup_module_inline(void) \
 	{ return x; }
 
 #else
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/message/i2o/i2o_block.c	Fri Oct 18 21:03:07 2002
@@ -225,7 +225,6 @@
 static void i2ob_end_request(struct request *);
 static void i2ob_request(request_queue_t *);
 static int i2ob_init_iop(unsigned int);
-static request_queue_t* i2ob_get_queue(kdev_t);
 static int i2ob_query_device(struct i2ob_device *, int, int, void*, int);
 static int i2ob_evt(void *);
 
@@ -1284,14 +1283,6 @@
 }
 
 /*
- * Get the request queue for the given device.
- */	
-static request_queue_t* i2ob_get_queue(kdev_t dev)
-{
-	return I2O_UNIT(dev).req_queue;
-}
-
-/*
  * Probe the I2O subsytem for block class devices
  */
 static void i2ob_scan(int bios)
@@ -1551,10 +1542,9 @@
 /*
  *	Have we seen a media change ?
  */
-static int i2ob_media_change(kdev_t dev)
+static int i2ob_media_change(struct gendisk *disk)
 {
-	int i=minor(dev);
-	i>>=4;
+	int i = (int)disk->private_data;
 	if(i2ob_media_change_flag[i])
 	{
 		i2ob_media_change_flag[i]=0;
@@ -1563,11 +1553,11 @@
 	return 0;
 }
 
-static int i2ob_revalidate(kdev_t dev)
+static int i2ob_revalidate(struct gendisk *disk)
 {
-	int minor = minor(dev) & ~15;
-	return i2ob_install_device(i2ob_dev[minor].controller, i2ob_dev[minor].i2odev,
-		minor);
+	int i = (int)disk->private_data;
+	return i2ob_install_device(i2ob_dev[i<<4].controller,
+				   i2ob_dev[i<<4].i2odev, i<<4);
 }
 
 /*
@@ -1616,12 +1606,12 @@
 
 static struct block_device_operations i2ob_fops =
 {
-	owner:			THIS_MODULE,
-	open:			i2ob_open,
-	release:		i2ob_release,
-	ioctl:			i2ob_ioctl,
-	check_media_change:	i2ob_media_change,
-	revalidate:		i2ob_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= i2ob_open,
+	.release	= i2ob_release,
+	.ioctl		= i2ob_ioctl,
+	.media_changed	= i2ob_media_change,
+	.revalidate_disk= i2ob_revalidate,
 };
 
 /*
@@ -1650,6 +1640,9 @@
 		struct gendisk *disk = alloc_disk(16);
 		if (!disk)
 			goto oom;
+		/* to be cleaned up */
+		disk->private_data = (void*)i;
+		disk->queue = i2ob_dev[i<<4].req_queue;
 		i2o_disk[i] = disk;
 	}
 #ifdef MODULE
@@ -1660,8 +1653,6 @@
 	 *	Now fill in the boiler plate
 	 */
 	 
-	blk_dev[MAJOR_NR].queue = i2ob_get_queue;
-
 	for (i = 0; i < MAX_I2OB << 4; i++) {
 		i2ob_dev[i].refcnt = 0;
 		i2ob_dev[i].flags = 0;
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/mtd/ftl.c	Fri Oct 18 21:03:04 2002
@@ -175,16 +175,16 @@
 		     u_int cmd, u_long arg);
 static int ftl_open(struct inode *inode, struct file *file);
 static release_t ftl_close(struct inode *inode, struct file *file);
-static int ftl_revalidate(kdev_t dev);
+static int ftl_revalidate(struct gendisk *disk);
 
 static void ftl_erase_callback(struct erase_info *done);
 
 static struct block_device_operations ftl_blk_fops = {
-    owner:	THIS_MODULE,
-    open:	ftl_open,
-    release:	ftl_close,
-    ioctl:	ftl_ioctl,
-    revalidate:	ftl_revalidate,
+	.owner		= THIS_MODULE,
+	.open		= ftl_open,
+	.release	= ftl_close,
+	.ioctl		= ftl_ioctl,
+	.revalidate_disk= ftl_revalidate,
 };
 
 /*======================================================================
@@ -823,61 +823,53 @@
 
 static int ftl_open(struct inode *inode, struct file *file)
 {
-    int minor = minor(inode->i_rdev);
-    partition_t *partition;
-
-    if (minor>>4 >= MAX_MTD_DEVICES)
-	return -ENODEV;
-
-    partition = myparts[minor>>4];
-
-    if (!partition)
-	return -ENODEV;
-
-    if (partition->state != FTL_FORMATTED)
-	return -ENXIO;
-    
-    if (get_capacity(partition->disk) == 0)
-	return -ENXIO;
-
-    if (!get_mtd_device(partition->mtd, -1))
-	    return /* -E'SBUGGEREDOFF */ -ENXIO;
-
-    if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) {
-	    put_mtd_device(partition->mtd);
-            return -EROFS;
-    }
+	partition_t *partition = inode->i_bdev->bd_disk->private_data;
+	if (!partition)
+		return -ENODEV;
+
+	if (partition->state != FTL_FORMATTED)
+		return -ENXIO;
+    
+	if (get_capacity(partition->disk) == 0)
+		return -ENXIO;
+
+	if (!get_mtd_device(partition->mtd, -1))
+		return /* -E'SBUGGEREDOFF */ -ENXIO;
+
+	if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) {
+		put_mtd_device(partition->mtd);
+		return -EROFS;
+	}
     
-    DEBUG(0, "ftl_cs: ftl_open(%d)\n", minor);
+	DEBUG(0, "ftl_cs: ftl_open(%s)\n", inode->i_bdev->b_disk->disk_name);
 
-    atomic_inc(&partition->open);
+	atomic_inc(&partition->open);
 
-    return 0;
+	return 0;
 }
 
 /*====================================================================*/
 
 static release_t ftl_close(struct inode *inode, struct file *file)
 {
-    int minor = minor(inode->i_rdev);
-    partition_t *part = myparts[minor >> 4];
-    int i;
+	partition_t *part = inode->i_bdev->bd_disk->private_data;
+	int i;
     
-    DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor);
+	DEBUG(0, "ftl_cs: ftl_close(%s)\n", inode->i_bdev->b_disk->disk_name);
 
-    /* Wait for any pending erase operations to complete */
-    if (part->mtd->sync)
-	    part->mtd->sync(part->mtd);
+	/* Wait for any pending erase operations to complete */
+	if (part->mtd->sync)
+		part->mtd->sync(part->mtd);
     
-    for (i = 0; i < part->header.NumTransferUnits; i++) {
-	if (part->XferInfo[i].state == XFER_ERASED)
-	    prepare_xfer(part, i);
-    }
+	for (i = 0; i < part->header.NumTransferUnits; i++) {
+		if (part->XferInfo[i].state == XFER_ERASED)
+			prepare_xfer(part, i);
+	}
 
-    atomic_dec(&part->open);
+	atomic_dec(&part->open);
 
-    put_mtd_device(part->mtd);
-    release_return(0);
+	put_mtd_device(part->mtd);
+	release_return(0);
 } /* ftl_close */
 
 
@@ -1091,25 +1083,26 @@
 static int ftl_ioctl(struct inode *inode, struct file *file,
 		     u_int cmd, u_long arg)
 {
-    struct hd_geometry *geo = (struct hd_geometry *)arg;
-    int ret = 0, minor = minor(inode->i_rdev);
-    partition_t *part= myparts[minor >> 4];
-    u_long sect;
-
-    if (!part)
-	return -ENODEV; /* How? */
-
-    if (cmd != HDIO_GETGEO)
-	return -EINVAL;
-    ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo));
-    if (ret) return ret;
-    /* Sort of arbitrary: round size down to 4K boundary */
-    sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
-    put_user(1, (char *)&geo->heads);
-    put_user(8, (char *)&geo->sectors);
-    put_user((sect>>3), (short *)&geo->cylinders);
-    put_user(get_start_sect(inode->i_bdev), (u_long *)&geo->start);
-    return 0;
+	partition_t *part = inode->i_bdev->bd_disk->private_data;
+	struct hd_geometry *geo = (struct hd_geometry *)arg;
+	int ret = 0;
+	u_long sect;
+
+	if (!part)
+		return -ENODEV; /* How? */
+
+	if (cmd != HDIO_GETGEO)
+		return -EINVAL;
+	ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo));
+	if (ret)
+		return ret;
+	/* Sort of arbitrary: round size down to 4K boundary */
+	sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
+	put_user(1, (char *)&geo->heads);
+	put_user(8, (char *)&geo->sectors);
+	put_user((sect>>3), (short *)&geo->cylinders);
+	put_user(get_start_sect(inode->i_bdev), (u_long *)&geo->start);
+	return 0;
 } /* ftl_ioctl */
 
 /*======================================================================
@@ -1118,13 +1111,11 @@
 
 ======================================================================*/
 
-static int ftl_revalidate(kdev_t dev)
+static int ftl_revalidate(struct gendisk *disk)
 {
-	int unit = minor(dev) >> 4;
-	partition_t *part = myparts[unit];
+	partition_t *part = disk->private_data;
 	scan_header(part);
-	set_capacity(part->disk,
-		le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
+	set_capacity(disk, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
 	return 0;
 }
 
@@ -1134,50 +1125,48 @@
 
 ======================================================================*/
 
-static void do_ftl_request(request_arg_t)
-{
-    int ret, minor;
-    partition_t *part;
-
-    do {
-	//	    sti();
-	if (blk_queue_empty(QUEUE))
-		return;
+static struct request_queue ftl_queue;
 
-	minor = minor(CURRENT->rq_dev);
+static void do_ftl_request(struct request_queue *q)
+{
+	struct request *req;
+	partition_t *part;
+	int ret;
+
+	do {
+		//	    sti();
+		if (blk_queue_empty(q))
+			return;
+		req = elv_next_request(q);
+		part = req->rq_disk->private_data;
+		if (part) {
+			ret = 0;
+			switch (rq_data_dir(CURRENT)) {
+			case READ:
+				ret = ftl_read(part, req->buffer, req->sector,
+						req->current_nr_sectors);
+				if (ret)
+					printk("ftl_read returned %d\n", ret);
+				break;
+			case WRITE:
+				ret = ftl_write(part, req->buffer, req->sector,
+						req->current_nr_sectors);
+				if (ret)
+					printk("ftl_write returned %d\n", ret);
+				break;
+			default:
+				panic("ftl_cs: unknown block command!\n");
+			}
+		} else {
+			ret = 1;
+			printk("NULL part in ftl_request\n");
+		}
+		 
+		if (!ret)
+			req->sector += req->current_nr_sectors;
 
-	part = myparts[minor >> 4];
-	if (part) {
-	  ret = 0;
-	  
-	  switch (rq_data_dir(CURRENT)) {
-	  case READ:
-	    ret = ftl_read(part, CURRENT->buffer, CURRENT->sector,
-			   CURRENT->current_nr_sectors);
-	    if (ret) printk("ftl_read returned %d\n", ret);
-	    break;
-	    
-	  case WRITE:
-	    ret = ftl_write(part, CURRENT->buffer, CURRENT->sector,
-			    CURRENT->current_nr_sectors);
-	    if (ret) printk("ftl_write returned %d\n", ret);
-	    break;
-	    
-	  default:
-	    panic("ftl_cs: unknown block command!\n");
-	    
-	  }
-	} else {
-	  ret = 1;
-	  printk("NULL part in ftl_request\n");
-	}
-	 
-	if (!ret) {
-	  CURRENT->sector += CURRENT->current_nr_sectors;
-	}
-	
-	end_request(CURRENT, (ret == 0) ? 1 : 0);
-    } while (1);
+		end_request(req, (ret == 0) ? 1 : 0);
+	} while (1);
 } /* do_ftl_request */
 
 /*====================================================================*/
@@ -1246,6 +1235,8 @@
 		atomic_set(&partition->open, 0);
 		myparts[device] = partition;
 		set_capacity(disk, le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE);
+		disk->private_data = partition;
+		disk->queue = &ftl_queue;
 		add_disk(disk);
 #ifdef PCMCIA_DEBUG
 		printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n",
@@ -1287,30 +1278,28 @@
 
 int init_ftl(void)
 {
-    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");
-	return -EAGAIN;
-    }
-    blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request, &lock);
-    register_mtd_user(&ftl_notifier);
-    
-    return 0;
+	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");
+		return -EAGAIN;
+	}
+	blk_init_queue(&ftl_queue, &do_ftl_request, &lock);
+	register_mtd_user(&ftl_notifier);
+	return 0;
 }
 
 static void __exit cleanup_ftl(void)
 {
-    unregister_mtd_user(&ftl_notifier);
-    unregister_blkdev(FTL_MAJOR, "ftl");
-    blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR));
+	unregister_mtd_user(&ftl_notifier);
+	unregister_blkdev(FTL_MAJOR, "ftl");
+	blk_cleanup_queue(&ftl_queue);
 }
 
 module_init(init_ftl);
 module_exit(cleanup_ftl);
-
 
 MODULE_LICENSE("Dual MPL/GPL");
 MODULE_AUTHOR("David Hinds <dhinds@sonic.net>");
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/net/3c59x.c	Fri Oct 18 21:03:03 2002
@@ -2052,7 +2052,7 @@
 	if (skb->ip_summed != CHECKSUM_HW)
 			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
 	else
-			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum);
+			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum);
 
 	if (!skb_shinfo(skb)->nr_frags) {
 		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data,
diff -Nru a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h
--- a/drivers/net/e100/e100.h	Fri Oct 18 21:03:04 2002
+++ b/drivers/net/e100/e100.h	Fri Oct 18 21:03:04 2002
@@ -121,7 +121,6 @@
 #define E100_DEFAULT_CPUSAVER_BUNDLE_MAX	6
 #define E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY	0x600
 #define E100_DEFAULT_BUNDLE_SMALL_FR		false
-#define E100_DEFAULT_RX_CONGESTION_CONTROL	true
 
 /* end of configurables */
 
@@ -146,8 +145,6 @@
 	unsigned long xmt_tco_pkts;
 	unsigned long rcv_tco_pkts;
 	unsigned long rx_intr_pkts;
-	unsigned long rx_tasklet_pkts;
-	unsigned long poll_intr_switch;
 };
 
 /* TODO: kill me when we can do C99 */
@@ -838,7 +835,6 @@
 #define PRM_FC           0x00000004
 #define PRM_IFS          0x00000008
 #define PRM_BUNDLE_SMALL 0x00000010
-#define PRM_RX_CONG      0x00000020
 
 struct cfg_params {
 	int e100_speed_duplex;
@@ -847,7 +843,6 @@
 	int IntDelay;
 	int BundleMax;
 	int ber;
-	int PollingMaxWork;
 	u32 b_params;
 };
 struct ethtool_lpbk_data{
@@ -949,8 +944,6 @@
 
 	u32 speed_duplex_caps;	/* adapter's speed/duplex capabilities */
 
-	struct tasklet_struct polling_tasklet;
-
 	/* WOL params for ethtool */
 	u32 wolsupported;
 	u32 wolopts;
@@ -961,6 +954,7 @@
 #ifdef CONFIG_PM
 	u32 pci_state[16];
 #endif
+	char ifname[IFNAMSIZ];
 };
 
 #define E100_AUTONEG        0
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/net/e100/e100_main.c	Fri Oct 18 21:03:04 2002
@@ -46,6 +46,15 @@
 
 /* Change Log
  *
+ * 2.1.24       10/7/02
+ *   o Bug fix: Wrong files under /proc/net/PRO_LAN_Adapters/ when interface
+ *     name is changed
+ *   o Bug fix: Rx skb corruption when Rx polling code and Rx interrupt code
+ *     are executing during stress traffic at shared interrupt system. 
+ *     Removed Rx polling code
+ *   o Added detailed printk if selftest failed when insmod
+ *   o Removed misleading printks
+ *
  * 2.1.12       8/2/02
  *   o Feature: ethtool register dump
  *   o Bug fix: Driver passes wrong name to /proc/interrupts
@@ -62,25 +71,6 @@
  *   o Bug fix: PHY loopback diagnostic fails
  *
  * 2.1.6        7/5/02
- *   o Added device ID support for Dell LOM.
- *   o Added device ID support for 82511QM mobile nics.
- *   o Bug fix: ethtool get/set EEPROM routines modified to use byte
- *     addressing rather than word addressing.
- *   o Feature: added MDIX mode support for 82550 and up.
- *   o Bug fix: added reboot notifer to setup WOL settings when
- *     shutting system down.
- *   o Cleanup: removed yield() redefinition (Andrew Morton, 
- *     akpm@zip.com.au).
- *   o Bug fix: flow control now working when link partner is 
- *     autoneg capable but not flow control capable.
- *   o Bug fix: added check for corrupted EEPROM
- *   o Bug fix: don't report checksum offloading for the older
- *     controllers that don't support the feature.
- *   o Bug fix: calculate cable diagnostics when link goes down
- *     rather than when queuering /proc file.
- *   o Cleanup: move mdi_access_lock to local get/set mdi routines.
- *
- * 2.0.30       5/30/02
  */
  
 #include <linux/config.h>
@@ -94,8 +84,8 @@
 #include "e100_vendor.h"
 
 #ifdef CONFIG_PROC_FS
-extern int e100_create_proc_subdir(struct e100_private *);
-extern void e100_remove_proc_subdir(struct e100_private *);
+extern int e100_create_proc_subdir(struct e100_private *, char *);
+extern void e100_remove_proc_subdir(struct e100_private *, char *);
 #else
 #define e100_create_proc_subdir(X) 0
 #define e100_remove_proc_subdir(X) do {} while(0)
@@ -145,7 +135,7 @@
 
 /* Global Data structures and variables */
 char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation";
-char e100_driver_version[]="2.1.15-k1";
+char e100_driver_version[]="2.1.24-k1";
 const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
 char e100_short_driver_name[] = "e100";
 static int e100nics = 0;
@@ -154,12 +144,19 @@
 static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
 static int e100_suspend(struct pci_dev *pcid, u32 state);
 static int e100_resume(struct pci_dev *pcid);
-struct notifier_block e100_notifier = {
+struct notifier_block e100_notifier_reboot = {
         notifier_call:  e100_notify_reboot,
         next:           NULL,
         priority:       0
 };
 #endif
+static int e100_notify_netdev(struct notifier_block *, unsigned long event, void *ptr);
+ 
+struct notifier_block e100_notifier_netdev = {
+	notifier_call:  e100_notify_netdev,
+	next:           NULL,
+	priority:       0
+};
 
 static void e100_get_mdix_status(struct e100_private *bdp);
 
@@ -349,9 +346,7 @@
 }
 
 void e100_tx_srv(struct e100_private *);
-u32 e100_rx_srv(struct e100_private *, u32, int *);
-
-void e100_polling_tasklet(unsigned long);
+u32 e100_rx_srv(struct e100_private *);
 
 void e100_watchdog(struct net_device *);
 static void e100_do_hwi(struct net_device *);
@@ -379,9 +374,6 @@
 E100_PARAM(BundleSmallFr, "Disable or enable interrupt bundling of small frames");
 E100_PARAM(BundleMax, "Maximum number for CPU saver's packet bundling");
 E100_PARAM(IFS, "Disable or enable the adaptive IFS algorithm");
-E100_PARAM(RxCongestionControl, "Disable or enable switch to polling mode");
-E100_PARAM(PollingMaxWork, "Max number of receive packets processed on single "
-	   "polling call");
 
 /**
  * e100_exec_cmd - issue a comand
@@ -656,6 +648,8 @@
 	if ((rc = register_netdev(dev)) != 0) {
 		goto err_pci;
 	}
+        memcpy(bdp->ifname, dev->name, IFNAMSIZ);
+        bdp->ifname[IFNAMSIZ-1] = 0;	
 
 	bdp->device_type = ent->driver_data;
 	printk(KERN_NOTICE
@@ -674,7 +668,7 @@
 			bdp->cable_status = "Not available";
 	}
 
-	if (e100_create_proc_subdir(bdp) < 0) {
+	if (e100_create_proc_subdir(bdp, bdp->ifname) < 0) {
 		printk(KERN_ERR "e100: Failed to create proc dir for %s\n",
 		       bdp->device->name);
 	}
@@ -738,7 +732,7 @@
 
 	unregister_netdev(dev);
 
-	e100_remove_proc_subdir(bdp);
+	e100_remove_proc_subdir(bdp, bdp->ifname);
 
 	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
 
@@ -772,10 +766,12 @@
 	int ret;
         ret = pci_module_init(&e100_driver);
 
-#ifdef CONFIG_PM	
-	if(ret >= 0)
-		register_reboot_notifier(&e100_notifier);
-#endif	
+	if(ret >= 0) {
+#ifdef CONFIG_PM
+		register_reboot_notifier(&e100_notifier_reboot);
+#endif 
+		register_netdevice_notifier(&e100_notifier_netdev);
+	}
 
 	return ret;
 }
@@ -784,8 +780,9 @@
 e100_cleanup_module(void)
 {
 #ifdef CONFIG_PM	
-	unregister_reboot_notifier(&e100_notifier);
-#endif	
+	unregister_reboot_notifier(&e100_notifier_reboot);
+#endif 
+	unregister_netdevice_notifier(&e100_notifier_netdev);
 
 	pci_unregister_driver(&e100_driver);
 }
@@ -856,14 +853,6 @@
 			    0xFFFF, E100_DEFAULT_CPUSAVER_BUNDLE_MAX,
 			    "CPU saver bundle max value");
 
-	e100_set_bool_option(bdp, RxCongestionControl[board], PRM_RX_CONG,
-			     E100_DEFAULT_RX_CONGESTION_CONTROL,
-			     "Rx Congestion Control value");
-
-	e100_set_int_option(&(bdp->params.PollingMaxWork),
-			    PollingMaxWork[board], 1, E100_MAX_RFD,
-			    bdp->params.RxDescriptors,
-			    "Polling Max Work value");
 }
 
 /**
@@ -991,11 +980,6 @@
 		del_timer_sync(&bdp->watchdog_timer);
 		goto err_exit;
 	}
-	if (bdp->params.b_params & PRM_RX_CONG) {
-		DECLARE_TASKLET(polling_tasklet,
-				e100_polling_tasklet, (unsigned long) bdp);
-		bdp->polling_tasklet = polling_tasklet;
-	}
 	bdp->intr_mask = 0;
 	e100_set_intr_mask(bdp);
 
@@ -1024,10 +1008,6 @@
 	free_irq(dev->irq, dev);
 	e100_clear_pools(bdp);
 
-	if (bdp->params.b_params & PRM_RX_CONG) {
-		tasklet_kill(&(bdp->polling_tasklet));
-	}
-
 	/* set the isolate flag to false, so e100_open can be called */
 	bdp->driver_isolated = false;
 
@@ -1263,12 +1243,21 @@
 static unsigned char __devinit
 e100_init(struct e100_private *bdp)
 {
+	u32 st_timeout = 0;
+	u32 st_result = 0;
 	e100_sw_init(bdp);
 
-	if (!e100_selftest(bdp, NULL, NULL)) {
-		printk(KERN_ERR "e100: selftest failed\n");
+	if (!e100_selftest(bdp, &st_timeout, &st_result)) {
+        	if (st_timeout) {
+			printk(KERN_ERR "e100: selftest timeout\n");
+		} else {
+			printk(KERN_ERR "e100: selftest failed. Results: %x\n",
+					st_result);
+		}
 		return false;
 	}
+	else
+		printk(KERN_DEBUG "e100: selftest OK.\n");
 
 	/* read the MAC address from the eprom */
 	e100_rd_eaddr(bdp);
@@ -1802,47 +1791,6 @@
 	}
 }
 
-void
-e100_polling_tasklet(unsigned long ptr)
-{
-	struct e100_private *bdp = (struct e100_private *) ptr;
-	unsigned int rx_congestion = 0;
-	u32 skb_cnt;
-
-	/* the device is closed, don't continue or else bad things may happen. */
-	if (!netif_running(bdp->device)) {
-		return;
-	}
-
-	read_lock(&(bdp->isolate_lock));
-	if (bdp->driver_isolated) {
-		tasklet_schedule(&(bdp->polling_tasklet));
-		goto exit;
-	}
-
-	e100_alloc_skbs(bdp);
-
-	skb_cnt = e100_rx_srv(bdp, bdp->params.PollingMaxWork, &rx_congestion);
-
-	bdp->drv_stats.rx_tasklet_pkts += skb_cnt;
-
-	if (rx_congestion || skb_cnt) {
-		tasklet_schedule(&(bdp->polling_tasklet));
-	} else {
-		bdp->intr_mask &= ~SCB_INT_MASK;
-
-		bdp->drv_stats.poll_intr_switch++;
-	}
-
-	bdp->tx_count = 0;	/* restart tx interrupt batch count */
-	e100_tx_srv(bdp);
-
-	e100_set_intr_mask(bdp);
-
-exit:
-	read_unlock(&(bdp->isolate_lock));
-}
-
 /**
  * e100intr - interrupt handler
  * @irq: the IRQ number
@@ -1892,18 +1840,8 @@
 
 	/* do recv work if any */
 	if (intr_status &
-	    (SCB_STATUS_ACK_FR | SCB_STATUS_ACK_RNR | SCB_STATUS_ACK_SWI)) {
-		int rx_congestion;
-
-		bdp->drv_stats.rx_intr_pkts +=
-			e100_rx_srv(bdp, 0, &rx_congestion);
-		if ((bdp->params.b_params & PRM_RX_CONG) && rx_congestion) {
-			bdp->intr_mask |= SCB_INT_MASK;
-			tasklet_schedule(&(bdp->polling_tasklet));
-
-			bdp->drv_stats.poll_intr_switch++;
-		}
-	}
+	    (SCB_STATUS_ACK_FR | SCB_STATUS_ACK_RNR | SCB_STATUS_ACK_SWI)) 
+		bdp->drv_stats.rx_intr_pkts += e100_rx_srv(bdp);
 
 	/* clean up after tx'ed packets */
 	if (intr_status & (SCB_STATUS_ACK_CNA | SCB_STATUS_ACK_CX)) {
@@ -1997,8 +1935,7 @@
  * It returns the number of serviced RFDs.
  */
 u32
-e100_rx_srv(struct e100_private *bdp, u32 max_number_of_rfds,
-	    int *rx_congestion)
+e100_rx_srv(struct e100_private *bdp)
 {
 	rfd_t *rfd;		/* new rfd, received rfd */
 	int i;
@@ -2009,10 +1946,6 @@
 	struct rx_list_elem *rx_struct;
 	u32 rfd_cnt = 0;
 
-	if (rx_congestion) {
-		*rx_congestion = 0;
-	}
-
 	dev = bdp->device;
 
 	/* current design of rx is as following:
@@ -2027,9 +1960,6 @@
 	 *    (watchdog trigger SWI intr and isr should allocate new skbs)
 	 */
 	for (i = 0; i < bdp->params.RxDescriptors; i++) {
-		if (max_number_of_rfds && (rfd_cnt >= max_number_of_rfds)) {
-			break;
-		}
 		if (list_empty(&(bdp->active_rx_list))) {
 			break;
 		}
@@ -2094,20 +2024,12 @@
 		} else {
 			skb->ip_summed = CHECKSUM_NONE;
 		}
-
 		switch (netif_rx(skb)) {
 		case NET_RX_BAD:
-			break;
-
 		case NET_RX_DROP:
 		case NET_RX_CN_MOD:
 		case NET_RX_CN_HIGH:
-			if (bdp->params.b_params & PRM_RX_CONG) {
-				if (rx_congestion) {
-					*rx_congestion = 1;
-				}
-			}
-			/* FALL THROUGH TO STATISTICS UPDATE */
+			break;
 		default:
 			bdp->drv_stats.net_stats.rx_bytes += skb->len;
 			break;
@@ -3032,11 +2954,6 @@
 		       "  Mem:0x%08lx  IRQ:%d  Speed:%d Mbps  Dx:%s\n",
 		       (unsigned long) bdp->device->mem_start,
 		       bdp->device->irq, 0, "N/A");
-
-		/* Auto negotiation failed so we should display an error */
-		printk(KERN_NOTICE "  Failed to detect cable link\n");
-		printk(KERN_NOTICE "  Speed and duplex will be determined "
-		       "at time of connection\n");
 	}
 
 	/* Print the string if checksum Offloading was enabled */
@@ -4176,11 +4093,34 @@
 	spin_unlock_bh(&(bdp->bd_non_tx_lock));
 }
 
+int e100_notify_netdev(struct notifier_block *nb, unsigned long event, void *p)
+{
+	struct e100_private *bdp;
+	struct net_device *netdev = p;
+	
+	if(netdev == NULL)
+		return NOTIFY_DONE;
+	
+	switch(event) {
+	case NETDEV_CHANGENAME:
+		if(netdev->open == e100_open) {
+			bdp = netdev->priv;
+			/* rename the proc nodes the easy way */
+			e100_remove_proc_subdir(bdp, bdp->ifname);
+			memcpy(bdp->ifname, netdev->name, IFNAMSIZ);
+			bdp->ifname[IFNAMSIZ-1] = 0;
+			e100_create_proc_subdir(bdp, bdp->ifname);
+		}
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
 #ifdef CONFIG_PM
 static int
 e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
 {
-        struct pci_dev *pdev = NULL;
+        struct pci_dev *pdev;
 	
         switch(event) {
         case SYS_DOWN:
diff -Nru a/drivers/net/e100/e100_proc.c b/drivers/net/e100/e100_proc.c
--- a/drivers/net/e100/e100_proc.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/net/e100/e100_proc.c	Fri Oct 18 21:03:04 2002
@@ -249,8 +249,6 @@
 	{"Rx_TCO_Packets",        read_gen_ulong, 0, bdp_drv_off(rcv_tco_pkts)},
 	{"\n",},
 	{"Rx_Interrupt_Packets",  read_gen_ulong, 0, bdp_drv_off(rx_intr_pkts)},
-	{"Rx_Polling_Packets",    read_gen_ulong, 0, bdp_drv_off(rx_tasklet_pkts)},
-	{"Polling_Interrupt_Switch", read_gen_ulong, 0, bdp_drv_off(poll_intr_switch)},
 	{"Identify_Adapter", 0, write_blink_led_timer, 0},
 	{"", 0, 0, 0}
 };
@@ -291,7 +289,7 @@
 	return generic_read(page, start, off, count, eof, len);
 }
 
-static struct proc_dir_entry * __devinit
+static struct proc_dir_entry *
 create_proc_rw(char *name, void *data, struct proc_dir_entry *parent,
 	       read_proc_t * read_proc, write_proc_t * write_proc)
 {
@@ -318,7 +316,7 @@
 }
 
 void
-e100_remove_proc_subdir(struct e100_private *bdp)
+e100_remove_proc_subdir(struct e100_private *bdp, char *name)
 {
 	e100_proc_entry *pe;
 	char info[256];
@@ -329,8 +327,8 @@
 		return;
 	}
 
-	len = strlen(bdp->device->name);
-	strncpy(info, bdp->device->name, sizeof (info));
+	len = strlen(bdp->ifname);
+	strncpy(info, bdp->ifname, sizeof (info));
 	strncat(info + len, ".info", sizeof (info) - len);
 
 	if (bdp->proc_parent) {
@@ -341,7 +339,7 @@
 			remove_proc_entry(pe->name, bdp->proc_parent);
 		}
 
-		remove_proc_entry(bdp->device->name, adapters_proc_dir);
+		remove_proc_entry(bdp->ifname, adapters_proc_dir);
 		bdp->proc_parent = NULL;
 	}
 
@@ -351,7 +349,7 @@
 	e100_proc_cleanup();
 }
 
-int __devinit
+int
 e100_create_proc_subdir(struct e100_private *bdp)
 {
 	struct proc_dir_entry *dev_dir;
@@ -366,7 +364,7 @@
 			return -ENOMEM;
 	}
 
-	strncpy(info, bdp->device->name, sizeof (info));
+	strncpy(info, bdp->ifname, sizeof (info));
 	len = strlen(info);
 	strncat(info + len, ".info", sizeof (info) - len);
 
@@ -376,12 +374,12 @@
 		return -ENOMEM;
 	}
 
-	dev_dir = create_proc_entry(bdp->device->name, S_IFDIR,
+	dev_dir = create_proc_entry(bdp->ifname, S_IFDIR,
 				    adapters_proc_dir);
 	bdp->proc_parent = dev_dir;
 
 	if (!dev_dir) {
-		e100_remove_proc_subdir(bdp);
+		e100_remove_proc_subdir(bdp, bdp->ifname);
 		return -ENOMEM;
 	}
 
@@ -396,7 +394,7 @@
 
 		if (!(create_proc_rw(pe->name, data, dev_dir,
 				     pe->read_proc, pe->write_proc))) {
-			e100_remove_proc_subdir(bdp);
+			e100_remove_proc_subdir(bdp, bdp->ifname);
 			return -ENOMEM;
 		}
 	}
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- a/drivers/net/e1000/e1000.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/net/e1000/e1000.h	Fri Oct 18 21:03:03 2002
@@ -95,6 +95,15 @@
 #define E1000_RXBUFFER_8192  8192
 #define E1000_RXBUFFER_16384 16384
 
+/* Flow Control High-Watermark: 43464 bytes */
+#define E1000_FC_HIGH_THRESH 0xA9C8
+
+/* Flow Control Low-Watermark: 43456 bytes */
+#define E1000_FC_LOW_THRESH 0xA9C0
+
+/* Flow Control Pause Time: 858 usec */
+#define E1000_FC_PAUSE_TIME 0x0680
+
 /* How many Tx Descriptors do we need to call netif_wake_queue ? */
 #define E1000_TX_QUEUE_WAKE	16
 /* How many Rx Buffers do we bundle into one write to the hardware ? */
@@ -194,5 +203,6 @@
 
 
 	uint32_t pci_state[16];
+	char ifname[IFNAMSIZ];
 };
 #endif /* _E1000_H_ */
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/net/e1000/e1000_ethtool.c	Fri Oct 18 21:03:04 2002
@@ -117,7 +117,8 @@
 
 	if(ecmd->autoneg == AUTONEG_ENABLE) {
 		hw->autoneg = 1;
-		hw->autoneg_advertised = (ecmd->advertising & 0x002F);
+		hw->autoneg_advertised = 0x002F;
+		ecmd->advertising = 0x002F;
 	} else {
 		hw->autoneg = 0;
 		switch(ecmd->speed + ecmd->duplex) {
@@ -210,7 +211,7 @@
 	struct e1000_hw *hw = &adapter->hw;
 	int i, max_len, first_word, last_word;
 
-	if(eeprom->len == 0) 
+	if(eeprom->len == 0)
 		return -EINVAL;
 
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
@@ -228,6 +229,7 @@
 
 	for(i = 0; i <= (last_word - first_word); i++)
 		e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]);
+
 	return 0;
 }
 
@@ -290,7 +292,6 @@
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
-	default:
 		wol->supported = 0;
 		wol->wolopts   = 0;
 		return;
@@ -304,14 +305,7 @@
 		}
 		/* Fall Through */
 
-	case E1000_DEV_ID_82544EI_COPPER:
-	case E1000_DEV_ID_82544GC_COPPER:
-	case E1000_DEV_ID_82544GC_LOM:
-	case E1000_DEV_ID_82540EM:
-	case E1000_DEV_ID_82540EM_LOM:
-	case E1000_DEV_ID_82545EM_COPPER:
-	case E1000_DEV_ID_82545EM_FIBER:
-	case E1000_DEV_ID_82546EB_COPPER:
+	default:
 		wol->supported = WAKE_PHY | WAKE_UCAST | 
 				 WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
 		
@@ -340,7 +334,6 @@
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
-	default:
 		return wol->wolopts ? -EOPNOTSUPP : 0;
 
 	case E1000_DEV_ID_82546EB_FIBER:
@@ -349,14 +342,7 @@
 			return wol->wolopts ? -EOPNOTSUPP : 0;
 		/* Fall Through */
 
-	case E1000_DEV_ID_82544EI_COPPER:
-	case E1000_DEV_ID_82544GC_COPPER:
-	case E1000_DEV_ID_82544GC_LOM:
-	case E1000_DEV_ID_82540EM:
-	case E1000_DEV_ID_82540EM_LOM:
-	case E1000_DEV_ID_82545EM_COPPER:
-	case E1000_DEV_ID_82545EM_FIBER:
-	case E1000_DEV_ID_82546EB_COPPER:
+	default:
 		if(wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
 			return -EOPNOTSUPP;
 
@@ -518,7 +504,8 @@
 		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
 			return -EFAULT;
 
-		if((err = e1000_ethtool_geeprom(adapter, &eeprom, eeprom_buff))<0)
+		if((err = e1000_ethtool_geeprom(adapter, 
+			&eeprom, eeprom_buff)))
 			return err;
 
 		if(copy_to_user(addr, &eeprom, sizeof(eeprom)))
diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
--- a/drivers/net/e1000/e1000_hw.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/net/e1000/e1000_hw.c	Fri Oct 18 21:03:04 2002
@@ -47,9 +47,9 @@
 static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count);
 static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw);
 static void e1000_setup_eeprom(struct e1000_hw *hw);
-static void e1000_standby_eeprom(struct e1000_hw *hw);
 static void e1000_clock_eeprom(struct e1000_hw *hw);
 static void e1000_cleanup_eeprom(struct e1000_hw *hw);
+static void e1000_standby_eeprom(struct e1000_hw *hw);
 static int32_t e1000_id_led_init(struct e1000_hw * hw);
 
 /******************************************************************************
@@ -88,6 +88,9 @@
         break;
     case E1000_DEV_ID_82540EM:
     case E1000_DEV_ID_82540EM_LOM:
+    case E1000_DEV_ID_82540EP:
+    case E1000_DEV_ID_82540EP_LOM:
+    case E1000_DEV_ID_82540EP_LP:
         hw->mac_type = e1000_82540;
         break;
     case E1000_DEV_ID_82545EM_COPPER:
@@ -655,14 +658,17 @@
         return -E1000_ERR_PHY;
     }
     phy_data |= M88E1000_EPSCR_TX_CLK_25;
-    /* Configure Master and Slave downshift values */
-    phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
-                  M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
-    phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
-                 M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
-    if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) {
-        DEBUGOUT("PHY Write Error\n");
-        return -E1000_ERR_PHY;
+
+    if (hw->phy_revision < M88E1011_I_REV_4) {
+        /* Configure Master and Slave downshift values */
+        phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
+                      M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
+        phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
+                     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
+        if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) {
+            DEBUGOUT("PHY Write Error\n");
+            return -E1000_ERR_PHY;
+        }
     }
 
     /* SW Reset the PHY so all changes take effect */
@@ -1008,7 +1014,6 @@
     /* Write the configured values back to the Device Control Reg. */
     E1000_WRITE_REG(hw, CTRL, ctrl);
 
-    /* Write the MII Control Register with the new PHY configuration. */
     if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) {
         DEBUGOUT("PHY Read Error\n");
         return -E1000_ERR_PHY;
@@ -1023,9 +1028,11 @@
         return -E1000_ERR_PHY;
     }
     DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
-    
+
     /* Need to reset the PHY or these changes will be ignored */
     mii_ctrl_reg |= MII_CR_RESET;
+
+    /* Write back the modified PHY MII control register. */
     if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) {
         DEBUGOUT("PHY Write Error\n");
         return -E1000_ERR_PHY;
@@ -2100,7 +2107,8 @@
         return -E1000_ERR_PHY;
     }
     hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
-    
+    hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
+
     switch(hw->mac_type) {
     case e1000_82543:
         if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
@@ -2242,7 +2250,7 @@
                    uint32_t *eecd)
 {
     /* Raise the clock input to the EEPROM (by setting the SK bit), and then
-     * wait 50 microseconds.
+     * wait <delay> microseconds.
      */
     *eecd = *eecd | E1000_EECD_SK;
     E1000_WRITE_REG(hw, EECD, *eecd);
@@ -2331,11 +2339,11 @@
     uint32_t i;
     uint16_t data;
 
-    /* In order to read a register from the EEPROM, we need to shift 16 bits 
-     * in from the EEPROM. Bits are "shifted in" by raising the clock input to
-     * the EEPROM (setting the SK bit), and then reading the value of the "DO"
-     * bit.  During this "shifting in" process the "DI" bit should always be 
-     * clear..
+    /* In order to read a register from the EEPROM, we need to shift 'count'
+     * bits in from the EEPROM. Bits are "shifted in" by raising the clock
+     * input to the EEPROM (setting the SK bit), and then reading the value of
+     * the "DO" bit.  During this "shifting in" process the "DI" bit should
+     * always be clear.
      */
 
     eecd = E1000_READ_REG(hw, EECD);
@@ -3140,6 +3148,9 @@
         ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT);
         E1000_WRITE_REG(hw, LEDCTL, ledctl);
         break;
+    case E1000_DEV_ID_82540EP:
+    case E1000_DEV_ID_82540EP_LOM:
+    case E1000_DEV_ID_82540EP_LP:
     case E1000_DEV_ID_82540EM:
     case E1000_DEV_ID_82540EM_LOM:
     case E1000_DEV_ID_82545EM_COPPER:
@@ -3173,6 +3184,9 @@
     case E1000_DEV_ID_82544GC_LOM:
         /* No cleanup necessary */
         break;
+    case E1000_DEV_ID_82540EP:
+    case E1000_DEV_ID_82540EP_LOM:
+    case E1000_DEV_ID_82540EP_LP:
     case E1000_DEV_ID_82540EM:
     case E1000_DEV_ID_82540EM_LOM:
     case E1000_DEV_ID_82545EM_COPPER:
@@ -3223,6 +3237,9 @@
         ctrl |= E1000_CTRL_SWDPIO0;
         E1000_WRITE_REG(hw, CTRL, ctrl);
         break;
+    case E1000_DEV_ID_82540EP:
+    case E1000_DEV_ID_82540EP_LOM:
+    case E1000_DEV_ID_82540EP_LP:
     case E1000_DEV_ID_82540EM:
     case E1000_DEV_ID_82540EM_LOM:
     case E1000_DEV_ID_82545EM_COPPER:
@@ -3270,6 +3287,9 @@
         ctrl |= E1000_CTRL_SWDPIO0;
         E1000_WRITE_REG(hw, CTRL, ctrl);
         break;
+    case E1000_DEV_ID_82540EP:
+    case E1000_DEV_ID_82540EP_LOM:
+    case E1000_DEV_ID_82540EP_LP:
     case E1000_DEV_ID_82540EM:
     case E1000_DEV_ID_82540EM_LOM:
     case E1000_DEV_ID_82545EM_COPPER:
diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
--- a/drivers/net/e1000/e1000_hw.h	Fri Oct 18 21:03:08 2002
+++ b/drivers/net/e1000/e1000_hw.h	Fri Oct 18 21:03:08 2002
@@ -237,20 +237,23 @@
     e1000_write_reg_io((a), E1000_##reg, val)
 
 /* PCI Device IDs */
-#define E1000_DEV_ID_82542          0x1000
-#define E1000_DEV_ID_82543GC_FIBER  0x1001
-#define E1000_DEV_ID_82543GC_COPPER 0x1004
-#define E1000_DEV_ID_82544EI_COPPER 0x1008
-#define E1000_DEV_ID_82544EI_FIBER  0x1009
-#define E1000_DEV_ID_82544GC_COPPER 0x100C
-#define E1000_DEV_ID_82544GC_LOM    0x100D
-#define E1000_DEV_ID_82540EM        0x100E
-#define E1000_DEV_ID_82540EM_LOM    0x1015
-#define E1000_DEV_ID_82545EM_COPPER 0x100F
-#define E1000_DEV_ID_82545EM_FIBER  0x1011
-#define E1000_DEV_ID_82546EB_COPPER 0x1010
-#define E1000_DEV_ID_82546EB_FIBER  0x1012
-#define NUM_DEV_IDS 13
+#define E1000_DEV_ID_82542               0x1000
+#define E1000_DEV_ID_82543GC_FIBER       0x1001
+#define E1000_DEV_ID_82543GC_COPPER      0x1004
+#define E1000_DEV_ID_82544EI_COPPER      0x1008
+#define E1000_DEV_ID_82544EI_FIBER       0x1009
+#define E1000_DEV_ID_82544GC_COPPER      0x100C
+#define E1000_DEV_ID_82544GC_LOM         0x100D
+#define E1000_DEV_ID_82540EM             0x100E
+#define E1000_DEV_ID_82540EM_LOM         0x1015
+#define E1000_DEV_ID_82540EP_LOM         0x1016
+#define E1000_DEV_ID_82540EP             0x1017
+#define E1000_DEV_ID_82540EP_LP          0x101E
+#define E1000_DEV_ID_82545EM_COPPER      0x100F
+#define E1000_DEV_ID_82545EM_FIBER       0x1011
+#define E1000_DEV_ID_82546EB_COPPER      0x1010
+#define E1000_DEV_ID_82546EB_FIBER       0x1012
+#define NUM_DEV_IDS 16
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -851,6 +854,7 @@
     e1000_bus_type bus_type;
     uint32_t io_base;
     uint32_t phy_id;
+    uint32_t phy_revision;
     uint32_t phy_addr;
     uint32_t original_fc;
     uint32_t txcw;
@@ -1755,6 +1759,7 @@
 #define M88E1011_I_PHY_ID  0x01410C20
 #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
 #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
+#define M88E1011_I_REV_4   0x04
 
 /* Miscellaneous PHY bit definitions. */
 #define PHY_PREAMBLE        0xFFFFFFFF
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/net/e1000/e1000_main.c	Fri Oct 18 21:03:04 2002
@@ -31,6 +31,19 @@
 
 /* Change Log
  *
+ * 4.4.12       10/15/02
+ *   o Clean up: use members of pci_device rather than direct calls to
+ *     pci_read_config_word.
+ *   o Bug fix: changed default flow control settings.
+ *   o Clean up: ethtool file now has an inclusive list for adapters in the
+ *     Wake-On-LAN capabilities instead of an exclusive list.
+ *   o Bug fix: miscellaneous WoL bug fixes.
+ *   o Added software interrupt for clearing rx ring
+ *   o Bug fix: easier to undo "forcing" of 1000/fd using ethtool.
+ *   o Now setting netdev->mem_end in e1000_probe.
+ *   o Clean up: Moved tx_timeout from interrupt context to process context
+ *     using schedule_task.
+ *
  *   o Feature: merged in modified NAPI patch from Robert Olsson
  *     <Robert.Olsson@its.uu.se> Uppsala Univeristy, Sweden.
  *
@@ -47,31 +60,13 @@
  *   o Feature: exposed two Tx and one Rx interrupt delay knobs for finer
  *     control over interurpt rate tuning.
  *   o Misc ethtool bug fixes.
- *         
- * 4.3.2       7/5/02
- *   o Bug fix: perform controller reset using I/O rather than mmio because
- *     some chipsets try to perform a 64-bit write, but the controller ignores
- *     the upper 32-bit write once the reset is intiated by the lower 32-bit
- *     write, causing a master abort.
- *   o Bug fix: fixed jumbo frames sized from 1514 to 2048.
- *   o ASF support: disable ARP when driver is loaded or resumed; enable when 
- *     driver is removed or suspended.
- *   o Bug fix: changed default setting for RxIntDelay to 0 for 82542/3/4
- *     controllers to workaround h/w errata where controller will hang when
- *     RxIntDelay <> 0 under certian network conditions.
- *   o Clean up: removed unused and undocumented user-settable settings for
- *     PHY.
- *   o Bug fix: ethtool GEEPROM was using byte address rather than word
- *     addressing.
- *   o Feature: added support for ethtool SEEPROM.
- *   o Feature: added support for entropy pool.
  *
- * 4.2.17      5/30/02
+ * 4.3.2       7/5/02
  */
  
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "4.3.15-k1";
+char e1000_driver_version[] = "4.4.12-k1";
 char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
@@ -113,6 +108,9 @@
 	{0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	/* required last entry */
 	{0,}
 };
@@ -179,17 +177,24 @@
 static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
 
 static int e1000_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
+static int e1000_notify_netdev(struct notifier_block *, unsigned long event, void *ptr);
 static int e1000_suspend(struct pci_dev *pdev, uint32_t state);
 #ifdef CONFIG_PM
 static int e1000_resume(struct pci_dev *pdev);
 #endif
 
-struct notifier_block e1000_notifier = {
+struct notifier_block e1000_notifier_reboot = {
 	.notifier_call	= e1000_notify_reboot,
 	.next		= NULL,
 	.priority	= 0
 };
 
+struct notifier_block e1000_notifier_netdev = {
+	.notifier_call	= e1000_notify_netdev,
+	.next		= NULL,
+	.priority	= 0
+};
+
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -230,8 +235,10 @@
 	printk(KERN_INFO "%s\n", e1000_copyright);
 
 	ret = pci_module_init(&e1000_driver);
-	if(ret >= 0)
-		register_reboot_notifier(&e1000_notifier);
+	if(ret >= 0) {
+		register_reboot_notifier(&e1000_notifier_reboot);
+		register_netdevice_notifier(&e1000_notifier_netdev);
+	}
 	return ret;
 }
 
@@ -247,7 +254,8 @@
 static void __exit
 e1000_exit_module(void)
 {
-	unregister_reboot_notifier(&e1000_notifier);
+	unregister_reboot_notifier(&e1000_notifier_reboot);
+	unregister_netdevice_notifier(&e1000_notifier_netdev);
 	pci_unregister_driver(&e1000_driver);
 }
 
@@ -408,6 +416,7 @@
 
 	netdev->irq = pdev->irq;
 	netdev->mem_start = mmio_start;
+	netdev->mem_end = mmio_start + mmio_len;
 	netdev->base_addr = adapter->hw.io_base;
 
 	adapter->bd_number = cards_found;
@@ -475,6 +484,8 @@
 		(void (*)(void *))e1000_tx_timeout_task, netdev);
 
 	register_netdev(netdev);
+	memcpy(adapter->ifname, netdev->name, IFNAMSIZ);
+	adapter->ifname[IFNAMSIZ-1] = 0;
 
 	/* we're going to reset, so assume we have no link for now */
 
@@ -527,7 +538,7 @@
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev->priv;
 	uint32_t manc;
-	
+
 	if(adapter->hw.mac_type >= e1000_82540) {
 		manc = E1000_READ_REG(&adapter->hw, MANC);
 		if(manc & E1000_MANC_SMBUS_EN) {
@@ -535,7 +546,7 @@
 			E1000_WRITE_REG(&adapter->hw, MANC, manc);
 		}
 	}
-		
+
 	unregister_netdev(netdev);
 
 	e1000_phy_hw_reset(&adapter->hw);
@@ -588,9 +599,9 @@
 
 	/* flow control settings */
 
-	hw->fc_high_water = FC_DEFAULT_HI_THRESH;
-	hw->fc_low_water = FC_DEFAULT_LO_THRESH;
-	hw->fc_pause_time = FC_DEFAULT_TX_TIMER;
+	hw->fc_high_water = E1000_FC_HIGH_THRESH;
+	hw->fc_low_water = E1000_FC_LOW_THRESH;
+	hw->fc_pause_time = E1000_FC_PAUSE_TIME;
 	hw->fc_send_xon = 1;
 
 	/* Media type - copper or fiber */
@@ -911,8 +922,9 @@
 
 	/* set the Receive Delay Timer Register */
 
+	E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
+
 	if(adapter->hw.mac_type >= e1000_82540) {
-		E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
 		E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
 
 		/* Set the interrupt throttling rate.  Value is calculated
@@ -920,9 +932,6 @@
 #define MAX_INTS_PER_SEC        8000
 #define DEFAULT_ITR             1000000000/(MAX_INTS_PER_SEC * 256)
 		E1000_WRITE_REG(&adapter->hw, ITR, DEFAULT_ITR);
-
-	} else {
-		E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
 	}
 
 	/* Setup the Base and Length of the Rx Descriptor Ring */
@@ -1280,6 +1289,10 @@
 	e1000_update_stats(adapter);
 	e1000_update_adaptive(&adapter->hw);
 
+
+	/* Cause software interrupt to ensure rx ring is cleaned */
+	E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
+
 	/* Early detection of hung controller */
 	i = txdr->next_to_clean;
 	if(txdr->buffer_info[i].dma &&
@@ -1497,7 +1510,6 @@
 
 	int f;
 
-
 	count = TXD_USE_COUNT(skb->len - skb->data_len,
 	                      adapter->max_data_per_txd);
 	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++)
@@ -1744,6 +1756,7 @@
 	                               adapter->stats.latecol;
 	adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
 	adapter->net_stats.tx_window_errors = adapter->stats.latecol;
+	adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
 
 	/* Tx Dropped needs to be maintained elsewhere */
 
@@ -1756,7 +1769,8 @@
 			adapter->phy_stats.idle_errors += phy_tmp;
 		}
 
-		if(!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
+		if((hw->mac_type <= e1000_82546) &&
+		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
 			adapter->phy_stats.receive_errors += phy_tmp;
 	}
 }
@@ -2164,8 +2178,7 @@
 	while(!rx_ring->buffer_info[i].skb) {
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 
-		skb = alloc_skb(adapter->rx_buffer_len + reserve_len,
-		                GFP_ATOMIC);
+		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
 
 		if(!skb) {
 			/* Better luck next round */
@@ -2397,6 +2410,29 @@
 }
 
 static int
+e1000_notify_netdev(struct notifier_block *nb, unsigned long event, void *p)
+{
+	struct e1000_adapter *adapter;
+	struct net_device *netdev = p;
+	if(netdev == NULL)
+		return NOTIFY_DONE;
+
+	switch(event) {
+	case NETDEV_CHANGENAME:
+		if(netdev->open == e1000_open) {
+			adapter = netdev->priv;
+			/* rename the proc nodes the easy way */
+			e1000_proc_dev_free(adapter);
+			memcpy(adapter->ifname, netdev->name, IFNAMSIZ);
+			adapter->ifname[IFNAMSIZ-1] = 0;
+			e1000_proc_dev_setup(adapter);
+		}
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static int
 e1000_suspend(struct pci_dev *pdev, uint32_t state)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
@@ -2412,30 +2448,40 @@
 		e1000_setup_rctl(adapter);
 		e1000_set_multi(netdev);
 
+		/* turn on all-multi mode if wake on multicast is enabled */
 		if(adapter->wol & E1000_WUFC_MC) {
 			rctl = E1000_READ_REG(&adapter->hw, RCTL);
 			rctl |= E1000_RCTL_MPE;
 			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 		}
 
-		if(adapter->hw.media_type == e1000_media_type_fiber) {
-			#define E1000_CTRL_ADVD3WUC 0x00100000
+		if(adapter->hw.mac_type >= e1000_82540) {
 			ctrl = E1000_READ_REG(&adapter->hw, CTRL);
-			ctrl |= E1000_CTRL_ADVD3WUC;
+			/* advertise wake from D3Cold */
+			#define E1000_CTRL_ADVD3WUC 0x00100000
+			/* phy power management enable */
+			#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
+			ctrl |= E1000_CTRL_ADVD3WUC |
+				E1000_CTRL_EN_PHY_PWR_MGMT;
 			E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+		}
 
+		if(adapter->hw.media_type == e1000_media_type_fiber) {
+			/* keep the laser running in D3 */
 			ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
-        		ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
+			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
 			E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
 		}
 
-		E1000_WRITE_REG(&adapter->hw, WUC, 0);
+		E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
 		E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol);
 		pci_enable_wake(pdev, 3, 1);
+		pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
 	} else {
 		E1000_WRITE_REG(&adapter->hw, WUC, 0);
 		E1000_WRITE_REG(&adapter->hw, WUFC, 0);
 		pci_enable_wake(pdev, 3, 0);
+		pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
 	}
 
 	pci_save_state(pdev, adapter->pci_state);
@@ -2445,9 +2491,12 @@
 		if(manc & E1000_MANC_SMBUS_EN) {
 			manc |= E1000_MANC_ARP_EN;
 			E1000_WRITE_REG(&adapter->hw, MANC, manc);
+			state = 0;
 		}
-	} else
-		pci_set_power_state(pdev, 3);
+	}
+
+	state = (state > 0) ? 3 : 0;
+	pci_set_power_state(pdev, state);
 
 	return 0;
 }
@@ -2462,10 +2511,11 @@
 
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, adapter->pci_state);
-	pci_enable_wake(pdev, 0, 0);
 
-	/* Clear the wakeup status bits */
+	pci_enable_wake(pdev, 3, 0);
+	pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
 
+	e1000_reset(adapter);
 	E1000_WRITE_REG(&adapter->hw, WUS, ~0);
 
 	if(netif_running(netdev))
diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
--- a/drivers/net/e1000/e1000_osdep.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/net/e1000/e1000_osdep.h	Fri Oct 18 21:03:03 2002
@@ -96,6 +96,6 @@
         readl((a)->hw_addr + E1000_##reg + ((offset) << 2)) : \
         readl((a)->hw_addr + E1000_82542_##reg + ((offset) << 2)))
 
-#define E1000_WRITE_FLUSH(a) ((void)E1000_READ_REG(a, STATUS))
+#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
 
 #endif /* _E1000_OSDEP_H_ */
diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
--- a/drivers/net/e1000/e1000_param.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/net/e1000/e1000_param.c	Fri Oct 18 21:03:07 2002
@@ -197,8 +197,7 @@
 #define MIN_RXD                       80
 #define MAX_82544_RXD               4096
 
-#define DEFAULT_RDTR                 128
-#define DEFAULT_RDTR_82544             0
+#define DEFAULT_RDTR                   0
 #define MAX_RXDELAY               0xFFFF
 #define MIN_RXDELAY                    0
 
@@ -315,7 +314,8 @@
 		};
 		struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 		e1000_mac_type mac_type = adapter->hw.mac_type;
-		opt.arg.r.max = mac_type < e1000_82544 ? MAX_TXD : MAX_82544_TXD;
+		opt.arg.r.max = mac_type < e1000_82544 ? 
+			MAX_TXD : MAX_82544_TXD;
 
 		tx_ring->count = TxDescriptors[bd];
 		e1000_validate_option(&tx_ring->count, &opt);
@@ -398,16 +398,13 @@
 	}
 	{ /* Receive Interrupt Delay */
 		char *rdtr = "using default of " __MODULE_STRING(DEFAULT_RDTR);
-		char *rdtr_82544 = "using default of "
-		       		   __MODULE_STRING(DEFAULT_RDTR_82544);
 		struct e1000_option opt = {
 			.type = range_option,
 			.name = "Receive Interrupt Delay",
 			.arg  = { r: { min: MIN_RXDELAY, max: MAX_RXDELAY }}
 		};
-		e1000_mac_type mac_type = adapter->hw.mac_type;
-		opt.def = mac_type > e1000_82544 ? DEFAULT_RDTR : 0;
-		opt.err = mac_type > e1000_82544 ? rdtr : rdtr_82544;
+		opt.def = DEFAULT_RDTR;
+		opt.err = rdtr;
 
 		adapter->rx_int_delay = RxIntDelay[bd];
 		e1000_validate_option(&adapter->rx_int_delay, &opt);
diff -Nru a/drivers/net/e1000/e1000_proc.c b/drivers/net/e1000/e1000_proc.c
--- a/drivers/net/e1000/e1000_proc.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/net/e1000/e1000_proc.c	Fri Oct 18 21:03:07 2002
@@ -132,7 +132,7 @@
 	return e1000_proc_read(page, start, off, count, eof);
 }
 
-static void __devexit
+static void
 e1000_proc_dirs_free(char *name, struct list_head *proc_list_head)
 {
 	struct proc_dir_entry *intel_proc_dir, *proc_dir;
@@ -188,7 +188,7 @@
 }
 
 
-static int __devinit
+static int
 e1000_proc_singles_create(struct proc_dir_entry *parent,
                           struct list_head *proc_list_head)
 {
@@ -215,7 +215,7 @@
 	return 1;
 }
 
-static void __devinit
+static void
 e1000_proc_dirs_create(void *data, char *name, 
                        struct list_head *proc_list_head)
 {
@@ -255,7 +255,7 @@
 	info_entry->data = proc_list_head;
 }
 
-static void __devinit
+static void
 e1000_proc_list_add(struct list_head *proc_list_head, char *tag,
                     void *data, size_t len, 
 		    char *(*func)(void *, size_t, char *))
@@ -274,7 +274,7 @@
 	list_add_tail(&new->list, proc_list_head);
 }
 
-static void __devexit
+static void
 e1000_proc_list_free(struct list_head *proc_list_head)
 {
 	struct proc_list *elem;
@@ -542,7 +542,7 @@
 #define LIST_ADD_H(T,D) LIST_ADD_F((T), (D), e1000_proc_hex)
 #define LIST_ADD_U(T,D) LIST_ADD_F((T), (D), e1000_proc_unsigned)
 
-static void __devinit
+static void
 e1000_proc_list_setup(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
@@ -572,7 +572,7 @@
 	}
 
 	LIST_ADD_U("IRQ", &adapter->pdev->irq);
-	LIST_ADD_S("System_Device_Name", adapter->netdev->name);
+	LIST_ADD_S("System_Device_Name", adapter->ifname);
 	LIST_ADD_F("Current_HWaddr",
 	            adapter->netdev->dev_addr, e1000_proc_hwaddr);
 	LIST_ADD_F("Permanent_HWaddr",
@@ -670,13 +670,13 @@
  * @adapter: board private structure
  */
 
-void __devinit
+void
 e1000_proc_dev_setup(struct e1000_adapter *adapter)
 {
 	e1000_proc_list_setup(adapter);
 
 	e1000_proc_dirs_create(adapter, 
-	                       adapter->netdev->name,
+	                       adapter->ifname,
 	                       &adapter->proc_list_head);
 }
 
@@ -685,18 +685,18 @@
  * @adapter: board private structure
  */
 
-void __devexit
+void
 e1000_proc_dev_free(struct e1000_adapter *adapter)
 {
-	e1000_proc_dirs_free(adapter->netdev->name, &adapter->proc_list_head);
+	e1000_proc_dirs_free(adapter->ifname, &adapter->proc_list_head);
 
 	e1000_proc_list_free(&adapter->proc_list_head);
 }
 
 #else /* CONFIG_PROC_FS */
 
-void __devinit e1000_proc_dev_setup(struct e1000_adapter *adapter) {}
-void __devexit e1000_proc_dev_free(struct e1000_adapter *adapter) {}
+void e1000_proc_dev_setup(struct e1000_adapter *adapter) {}
+void e1000_proc_dev_free(struct e1000_adapter *adapter) {}
 
 #endif /* CONFIG_PROC_FS */
 
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Fri Oct 18 21:03:06 2002
+++ b/drivers/net/eepro100.c	Fri Oct 18 21:03:06 2002
@@ -65,7 +65,6 @@
    e.g. "options=16" for FD, "options=32" for 100mbps-only. */
 static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int debug = -1;			/* The debug level */
 
 /* A few values that may be tweaked. */
 /* The ring sizes should be a power of two for efficiency. */
@@ -119,6 +118,16 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
+
+static int debug = -1;
+#define DEBUG_DEFAULT		(NETIF_MSG_DRV		| \
+				 NETIF_MSG_IFDOWN	| \
+				 NETIF_MSG_IFUP		| \
+				 NETIF_MSG_RX_ERR	| \
+				 NETIF_MSG_TX_ERR)
+#define DEBUG			((debug >= 0) ? (1<<debug)-1 : DEBUG_DEFAULT)
+
 
 MODULE_AUTHOR("Maintainer: Andrey V. Savochkin <saw@saw.sw.com.sg>");
 MODULE_DESCRIPTION("Intel i82557/i82558/i82559 PCI EtherExpressPro driver");
@@ -167,7 +176,6 @@
 								} while(0)
 
 
-static int speedo_debug = 1;
 
 /*
 				Theory of Operation
@@ -316,23 +324,11 @@
 #define outl writel
 #endif
 
-/* How to wait for the command unit to accept a command.
-   Typically this takes 0 ticks. */
-static inline void wait_for_cmd_done(long cmd_ioaddr)
-{
-	int wait = 1000;
-	do  udelay(1) ;
-	while(inb(cmd_ioaddr) && --wait >= 0);
-#ifndef final_version
-	if (wait < 0)
-		printk(KERN_ALERT "eepro100: wait_for_cmd_done timeout!\n");
-#endif
-}
-
 /* Offsets to the various registers.
    All accesses need not be longword aligned. */
 enum speedo_offsets {
 	SCBStatus = 0, SCBCmd = 2,	/* Rx/Command Unit command and status. */
+	SCBIntmask = 3,
 	SCBPointer = 4,				/* General purpose pointer. */
 	SCBPort = 8,				/* Misc. commands and operands.  */
 	SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
@@ -488,7 +484,6 @@
 	unsigned char acpi_pwr;
 	signed char rx_mode;			/* Current PROMISC/ALLMULTI setting. */
 	unsigned int tx_full:1;			/* The Tx queue is full. */
-	unsigned int full_duplex:1;		/* Full-duplex operation requested. */
 	unsigned int flow_ctrl:1;		/* Use 802.3x flow control. */
 	unsigned int rx_bug:1;			/* Work around receiver hang errata. */
 	unsigned char default_port:8;		/* Last dev->if_port value. */
@@ -496,6 +491,7 @@
 	unsigned short phy[2];			/* PHY media interfaces available. */
 	unsigned short partner;			/* Link partner caps. */
 	struct mii_if_info mii_if;		/* MII API hooks, info */
+	u32 msg_enable;				/* debug message level */
 #ifdef CONFIG_PM
 	u32 pm_state[16];
 #endif
@@ -559,6 +555,26 @@
 						   0x2000, 0x2100, 0x0400, 0x3100};
 #endif
 
+/* How to wait for the command unit to accept a command.
+   Typically this takes 0 ticks. */
+static inline unsigned char wait_for_cmd_done(struct net_device *dev)
+{
+	int wait = 1000;
+	long cmd_ioaddr = dev->base_addr + SCBCmd;
+	unsigned char r;
+
+	do  {
+		udelay(1);
+		r = inb(cmd_ioaddr);
+	} while(r && --wait >= 0);
+
+#ifndef final_version
+	if (wait < 0)
+		printk(KERN_ALERT "%s: wait_for_cmd_done timeout!\n", dev->name);
+#endif
+	return r;
+}
+
 static int __devinit eepro100_init_one (struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
@@ -567,9 +583,12 @@
 	int acpi_idle_state = 0, pm;
 	static int cards_found /* = 0 */;
 
-	static int did_version /* = 0 */;		/* Already printed version info. */
-	if (speedo_debug > 0  &&  did_version++ == 0)
+#ifndef MODULE
+	/* when built-in, we only print version if device is found */
+	static int did_version;
+	if (did_version++ == 0)
 		printk(version);
+#endif
 
 	/* save power state before pci_enable_device overwrites it */
 	pm = pci_find_capability(pdev, PCI_CAP_ID_PM);
@@ -598,7 +617,7 @@
 	irq = pdev->irq;
 #ifdef USE_IO
 	ioaddr = pci_resource_start(pdev, 1);
-	if (speedo_debug > 2)
+	if (DEBUG & NETIF_MSG_PROBE)
 		printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
 			   ioaddr, irq);
 #else
@@ -609,7 +628,7 @@
 				pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
 		goto err_out_free_mmio_region;
 	}
-	if (speedo_debug > 2)
+	if (DEBUG & NETIF_MSG_PROBE)
 		printk("Found Intel i82557 PCI Speedo, MMIO at %#lx, IRQ %d.\n",
 			   pci_resource_start(pdev, 0), irq);
 #endif
@@ -815,6 +834,7 @@
 
 	sp = dev->priv;
 	sp->pdev = pdev;
+	sp->msg_enable = DEBUG;
 	sp->acpi_pwr = acpi_idle_state;
 	sp->tx_ring = tx_ring_space;
 	sp->tx_ring_dma = tx_ring_dma;
@@ -960,7 +980,7 @@
 	long ioaddr = dev->base_addr;
 	int retval;
 
-	if (speedo_debug > 1)
+	if (netif_msg_ifup(sp))
 		printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
 
 	pci_set_power_state(sp->pdev, 0);
@@ -1017,12 +1037,9 @@
 	if ((sp->phy[0] & 0x8000) == 0)
 		sp->mii_if.advertising = mdio_read(dev, sp->phy[0] & 0x1f, MII_ADVERTISE);
 
-	if (mdio_read(dev, sp->phy[0] & 0x1f, MII_BMSR) & BMSR_LSTATUS)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
+	mii_check_link(&sp->mii_if);
 
-	if (speedo_debug > 2) {
+	if (netif_msg_ifup(sp)) {
 		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 	}
@@ -1054,8 +1071,7 @@
 	sp->tx_threshold = 0x01208000;
 
 	/* Set the segment registers to '0'. */
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	if (inb(ioaddr + SCBCmd)) {
+	if (wait_for_cmd_done(dev) != 0) {
 		outl(PortPartialReset, ioaddr + SCBPort);
 		udelay(10);
 	}
@@ -1074,10 +1090,10 @@
 
 	outb(CUStatsAddr, ioaddr + SCBCmd);
 	sp->lstats->done_marker = 0;
-	wait_for_cmd_done(ioaddr + SCBCmd);
+	wait_for_cmd_done(dev);
 
 	if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
-		if (speedo_debug > 2)
+		if (netif_msg_rx_err(sp))
 			printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
 					dev->name);
 	} else {
@@ -1133,8 +1149,7 @@
 	long ioaddr;
 
 	ioaddr = dev->base_addr;
-	wait_for_cmd_done(ioaddr + SCBCmd);
-	if (inb(ioaddr + SCBCmd) != 0) {
+	if (wait_for_cmd_done(dev) != 0) {
 		printk("%s: previous command stalled\n", dev->name);
 		return;
 	}
@@ -1147,9 +1162,7 @@
 
 	rfd->rx_buf_addr = 0xffffffff;
 
-	wait_for_cmd_done(ioaddr + SCBCmd);
-
-	if (inb(ioaddr + SCBCmd) != 0) {
+	if (wait_for_cmd_done(dev) != 0) {
 		printk("%s: RxAbort command stalled\n", dev->name);
 		return;
 	}
@@ -1172,7 +1185,7 @@
 		int partner = mdio_read(dev, phy_num, MII_LPA);
 		if (partner != sp->partner) {
 			int flow_ctrl = sp->mii_if.advertising & partner & 0x0400 ? 1 : 0;
-			if (speedo_debug > 2) {
+			if (netif_msg_link(sp)) {
 				printk(KERN_DEBUG "%s: Link status change.\n", dev->name);
 				printk(KERN_DEBUG "%s: Old partner %x, new %x, adv %x.\n",
 					   dev->name, sp->partner, partner, sp->mii_if.advertising);
@@ -1182,16 +1195,10 @@
 				sp->flow_ctrl = flow_ctrl;
 				sp->rx_mode = -1;	/* Trigger a reload. */
 			}
-			/* Clear sticky bit. */
-			mdio_read(dev, phy_num, MII_BMSR);
-			/* If link beat has returned... */
-			if (mdio_read(dev, phy_num, MII_BMSR) & BMSR_LSTATUS)
-				netif_carrier_on(dev);
-			else
-				netif_carrier_off(dev);
 		}
 	}
-	if (speedo_debug > 3) {
+	mii_check_link(&sp->mii_if);
+	if (netif_msg_timer(sp)) {
 		printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 	}
@@ -1200,7 +1207,7 @@
 		/* We haven't received a packet in a Long Time.  We might have been
 		   bitten by the receiver hang bug.  This can be cleared by sending
 		   a set multicast list command. */
-		if (speedo_debug > 3)
+		if (netif_msg_rx_err(sp))
 			printk(KERN_DEBUG "%s: Sending a multicast list set command"
 				   " from a timer routine,"
 				   " m=%d, j=%ld, l=%ld.\n",
@@ -1218,20 +1225,17 @@
 	int i;
 
 	/* Print a few items for debugging. */
-	if (speedo_debug > 0) {
-		int i;
-		printk(KERN_DEBUG "%s: Tx ring dump,  Tx queue %u / %u:\n", dev->name,
-			   sp->cur_tx, sp->dirty_tx);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(KERN_DEBUG "%s:  %c%c%2d %8.8x.\n", dev->name,
-				   i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ',
-				   i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ',
-				   i, sp->tx_ring[i].status);
-	}
+	printk(KERN_DEBUG "%s: Tx ring dump,  Tx queue %u / %u:\n", dev->name,
+		   sp->cur_tx, sp->dirty_tx);
+	for (i = 0; i < TX_RING_SIZE; i++)
+		printk(KERN_DEBUG "%s:  %c%c%2d %8.8x.\n", dev->name,
+			   i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ',
+			   i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ',
+			   i, sp->tx_ring[i].status);
+
 	printk(KERN_DEBUG "%s: Printing Rx ring"
 		   " (next to receive into %u, dirty index %u).\n",
 		   dev->name, sp->cur_rx, sp->dirty_rx);
-
 	for (i = 0; i < RX_RING_SIZE; i++)
 		printk(KERN_DEBUG "%s: %c%c%c%2d %8.8x.\n", dev->name,
 			   sp->rx_ringp[i] == sp->last_rxf ? 'l' : ' ',
@@ -1324,7 +1328,7 @@
 	}
 	while (sp->mc_setup_head != NULL) {
 		struct speedo_mc_block *t;
-		if (speedo_debug > 1)
+		if (netif_msg_tx_err(sp))
 			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
 		pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
 				sp->mc_setup_head->len, PCI_DMA_TODEVICE);
@@ -1367,13 +1371,15 @@
 	int status = inw(ioaddr + SCBStatus);
 	unsigned long flags;
 
-	printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
+	if (netif_msg_tx_err(sp)) {
+		printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
 		   " %4.4x at %d/%d command %8.8x.\n",
 		   dev->name, status, inw(ioaddr + SCBCmd),
 		   sp->dirty_tx, sp->cur_tx,
 		   sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
 
-	speedo_show_state(dev);
+		speedo_show_state(dev);
+	}
 #if 0
 	if ((status & 0x00C0) != 0x0080
 		&&  (status & 0x003C) == 0x0010) {
@@ -1462,13 +1468,13 @@
 	/* workaround for hardware bug on 10 mbit half duplex */
 
 	if ((sp->partner == 0) && (sp->chip_id == 1)) {
-		wait_for_cmd_done(ioaddr + SCBCmd);
+		wait_for_cmd_done(dev);
 		outb(0 , ioaddr + SCBCmd);
 		udelay(1);
 	}
 
 	/* Trigger the command unit resume. */
-	wait_for_cmd_done(ioaddr + SCBCmd);
+	wait_for_cmd_done(dev);
 	clear_suspend(sp->last_cmd);
 	/* We want the time window between clearing suspend flag on the previous
 	   command and resuming CU to be as small as possible.
@@ -1500,14 +1506,14 @@
 		int entry = dirty_tx % TX_RING_SIZE;
 		int status = le32_to_cpu(sp->tx_ring[entry].status);
 
-		if (speedo_debug > 5)
+		if (netif_msg_tx_done(sp))
 			printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
 				   entry, status);
 		if ((status & StatusComplete) == 0)
 			break;			/* It still hasn't been processed. */
 		if (status & TxUnderrun)
 			if (sp->tx_threshold < 0x01e08000) {
-				if (speedo_debug > 2)
+				if (netif_msg_tx_err(sp))
 					printk(KERN_DEBUG "%s: TX underrun, threshold adjusted.\n",
 						   dev->name);
 				sp->tx_threshold += 0x00040000;
@@ -1525,7 +1531,7 @@
 		dirty_tx++;
 	}
 
-	if (speedo_debug && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) {
+	if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) {
 		printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d,"
 			   " full=%d.\n",
 			   dirty_tx, sp->cur_tx, sp->tx_full);
@@ -1535,7 +1541,7 @@
 	while (sp->mc_setup_head != NULL
 		   && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) {
 		struct speedo_mc_block *t;
-		if (speedo_debug > 1)
+		if (netif_msg_tx_err(sp))
 			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
 		pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
 				sp->mc_setup_head->len, PCI_DMA_TODEVICE);
@@ -1585,7 +1591,7 @@
 		   FCP and ER interrupts --Dragan */
 		outw(status & 0xfc00, ioaddr + SCBStatus);
 
-		if (speedo_debug > 4)
+		if (netif_msg_intr(sp))
 			printk(KERN_DEBUG "%s: interrupt  status=%#4.4x.\n",
 				   dev->name, status);
 
@@ -1647,7 +1653,7 @@
 		}
 	} while (1);
 
-	if (speedo_debug > 3)
+	if (netif_msg_intr(sp))
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 
@@ -1708,7 +1714,7 @@
 		if (rxf == NULL) {
 			unsigned int forw;
 			int forw_entry;
-			if (speedo_debug > 2 || !(sp->rx_ring_state & RrOOMReported)) {
+			if (netif_msg_rx_err(sp) || !(sp->rx_ring_state & RrOOMReported)) {
 				printk(KERN_WARNING "%s: can't fill rx buffer (force %d)!\n",
 						dev->name, force);
 				speedo_show_state(dev);
@@ -1754,8 +1760,9 @@
 	int entry = sp->cur_rx % RX_RING_SIZE;
 	int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
 	int alloc_ok = 1;
+	int npkts = 0;
 
-	if (speedo_debug > 4)
+	if (netif_msg_intr(sp))
 		printk(KERN_DEBUG " In speedo_rx().\n");
 	/* If we own the next entry, it's a new packet. Send it up. */
 	while (sp->rx_ringp[entry] != NULL) {
@@ -1778,14 +1785,14 @@
 		if (sp->last_rxf == sp->rx_ringp[entry]) {
 			/* Postpone the packet.  It'll be reaped at an interrupt when this
 			   packet is no longer the last packet in the ring. */
-			if (speedo_debug > 2)
+			if (netif_msg_rx_err(sp))
 				printk(KERN_DEBUG "%s: RX packet postponed!\n",
 					   dev->name);
 			sp->rx_ring_state |= RrPostponed;
 			break;
 		}
 
-		if (speedo_debug > 4)
+		if (netif_msg_intr(sp))
 			printk(KERN_DEBUG "  speedo_rx() status %8.8x len %d.\n", status,
 				   pkt_len);
 		if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) {
@@ -1820,6 +1827,7 @@
 				memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail,
 					   pkt_len);
 #endif
+				npkts++;
 			} else {
 				/* Pass up the already-filled skbuff. */
 				skb = sp->rx_skbuff[entry];
@@ -1830,6 +1838,7 @@
 				}
 				sp->rx_skbuff[entry] = NULL;
 				skb_put(skb, pkt_len);
+				npkts++;
 				sp->rx_ringp[entry] = NULL;
 				pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
 						PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
@@ -1851,7 +1860,8 @@
 	/* Try hard to refill the recently taken buffers. */
 	speedo_refill_rx_buffers(dev, 1);
 
-	sp->last_rx_time = jiffies;
+	if (npkts)
+		sp->last_rx_time = jiffies;
 
 	return 0;
 }
@@ -1866,20 +1876,27 @@
 	netdevice_stop(dev);
 	netif_stop_queue(dev);
 
-	if (speedo_debug > 1)
+	if (netif_msg_ifdown(sp))
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 
 	/* Shut off the media monitoring timer. */
 	del_timer_sync(&sp->timer);
 
+	outw(SCBMaskAll, ioaddr + SCBCmd);
+
 	/* Shutting down the chip nicely fails to disable flow control. So.. */
 	outl(PortPartialReset, ioaddr + SCBPort);
+	inl(ioaddr + SCBPort); /* flush posted write */
+	/*
+	 * The chip requires a 10 microsecond quiet period.  Wait here!
+	 */
+	udelay(10);
 
 	free_irq(dev->irq, dev);
 
 	/* Print a few items for debugging. */
-	if (speedo_debug > 3)
+	if (netif_msg_ifdown(sp))
 		speedo_show_state(dev);
 
     /* Free all the skbuffs in the Rx and Tx queues. */
@@ -1915,7 +1932,7 @@
 		sp->mc_setup_head = t;
 	}
 	sp->mc_setup_tail = NULL;
-	if (speedo_debug > 0)
+	if (netif_msg_ifdown(sp))
 		printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i);
 
 	pci_set_power_state(sp->pdev, 2);
@@ -1956,7 +1973,7 @@
 			/* Take a spinlock to make wait_for_cmd_done and sending the
 			   command atomic.  --SAW */
 			spin_lock_irqsave(&sp->lock, flags);
-			wait_for_cmd_done(ioaddr + SCBCmd);
+			wait_for_cmd_done(dev);
 			outb(CUDumpStats, ioaddr + SCBCmd);
 			spin_unlock_irqrestore(&sp->lock, flags);
 		}
@@ -2018,6 +2035,22 @@
 			return -EFAULT;
 		return 0;
 	}
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = sp->msg_enable;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		sp->msg_enable = edata.data;
+		return 0;
+	}
 
         }
 	
@@ -2092,7 +2125,7 @@
 	} else
 		new_rx_mode = 0;
 
-	if (speedo_debug > 3)
+	if (netif_msg_rx_status(sp))
 		printk(KERN_DEBUG "%s: set_rx_mode %d -> %d\n", dev->name,
 				sp->rx_mode, new_rx_mode);
 
@@ -2133,7 +2166,7 @@
 			config_cmd_data[8] = 0;
 		}
 		/* Trigger the command unit resume. */
-		wait_for_cmd_done(ioaddr + SCBCmd);
+		wait_for_cmd_done(dev);
 		clear_suspend(last_cmd);
 		outb(CUResume, ioaddr + SCBCmd);
 		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
@@ -2170,7 +2203,7 @@
 			*setup_params++ = *eaddrs++;
 		}
 
-		wait_for_cmd_done(ioaddr + SCBCmd);
+		wait_for_cmd_done(dev);
 		clear_suspend(last_cmd);
 		/* Immediately trigger the command unit resume. */
 		outb(CUResume, ioaddr + SCBCmd);
@@ -2203,7 +2236,7 @@
 		mc_setup_frm = &mc_blk->frame;
 
 		/* Fill the setup frame. */
-		if (speedo_debug > 1)
+		if (netif_msg_ifup(sp))
 			printk(KERN_DEBUG "%s: Constructing a setup frame at %p.\n",
 				   dev->name, mc_setup_frm);
 		mc_setup_frm->cmd_status =
@@ -2246,7 +2279,7 @@
 		pci_dma_sync_single(sp->pdev, mc_blk->frame_dma,
 				mc_blk->len, PCI_DMA_TODEVICE);
 
-		wait_for_cmd_done(ioaddr + SCBCmd);
+		wait_for_cmd_done(dev);
 		clear_suspend(last_cmd);
 		/* Immediately trigger the command unit resume. */
 		outb(CUResume, ioaddr + SCBCmd);
@@ -2257,7 +2290,7 @@
 		}
 		spin_unlock_irqrestore(&sp->lock, flags);
 
-		if (speedo_debug > 5)
+		if (netif_msg_rx_status(sp))
 			printk(" CmdMCSetup frame length %d in entry %d.\n",
 				   dev->mc_count, entry);
 	}
@@ -2400,11 +2433,9 @@
 
 static int __init eepro100_init_module(void)
 {
-	if (debug >= 0 && speedo_debug != debug)
-		printk(KERN_INFO "eepro100.c: Debug level is %d.\n", debug);
-	if (debug >= 0)
-		speedo_debug = debug;
-
+#ifdef MODULE
+	printk(version);
+#endif
 	return pci_module_init(&eepro100_driver);
 }
 
diff -Nru a/drivers/net/hamradio/soundmodem/Makefile b/drivers/net/hamradio/soundmodem/Makefile
--- a/drivers/net/hamradio/soundmodem/Makefile	Fri Oct 18 21:03:03 2002
+++ b/drivers/net/hamradio/soundmodem/Makefile	Fri Oct 18 21:03:03 2002
@@ -19,6 +19,12 @@
 host-progs := gentbl
 HOST_LOADLIBES := -lm
 
+# Files generated that shall be removed upon make clean
+clean-files  :=	sm_tbl_afsk1200.h   sm_tbl_afsk2400_7.h	\
+		sm_tbl_afsk2400_8.h sm_tbl_afsk2666.h	\
+		sm_tbl_psk4800.h    sm_tbl_hapn4800.h	\
+		sm_tbl_fsk9600.h
+
 include $(TOPDIR)/Rules.make
 
 # Dependencies on generates files need to be listed explicitly
diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c
--- a/drivers/net/mii.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/net/mii.c	Fri Oct 18 21:03:04 2002
@@ -192,9 +192,12 @@
 
 void mii_check_link (struct mii_if_info *mii)
 {
-	if (mii_link_ok(mii))
+	int cur_link = mii_link_ok(mii);
+	int prev_link = netif_carrier_ok(mii->dev);
+
+	if (cur_link && !prev_link)
 		netif_carrier_on(mii->dev);
-	else
+	else if (prev_link && !cur_link)
 		netif_carrier_off(mii->dev);
 }
 
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/net/natsemi.c	Fri Oct 18 21:03:03 2002
@@ -184,7 +184,7 @@
 				 NETIF_MSG_WOL		| \
 				 NETIF_MSG_RX_ERR	| \
 				 NETIF_MSG_TX_ERR)
-static int debug = NATSEMI_DEF_MSG;
+static int debug = -1;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 20;
@@ -256,7 +256,7 @@
 MODULE_PARM_DESC(max_interrupt_work, 
 	"DP8381x maximum events handled per interrupt");
 MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");
-MODULE_PARM_DESC(debug, "DP8381x default debug bitmask");
+MODULE_PARM_DESC(debug, "DP8381x default debug level");
 MODULE_PARM_DESC(rx_copybreak, 
 	"DP8381x copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(options, 
@@ -796,7 +796,7 @@
 	pci_set_drvdata(pdev, dev);
 	np->iosize = iosize;
 	spin_lock_init(&np->lock);
-	np->msg_enable = debug;
+	np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG;
 	np->hands_off = 0;
 
 	/* Reset the chip to erase previous misconfiguration. */
diff -Nru a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
--- a/drivers/nubus/nubus.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/nubus/nubus.c	Fri Oct 18 21:03:03 2002
@@ -72,7 +72,7 @@
    Etcetera, etcetera.  Hopefully this clears up some confusion over
    what the following code actually does.  */
  
-extern inline int not_useful(void *p, int map)
+static inline int not_useful(void *p, int map)
 {
 	unsigned long pv=(unsigned long)p;
 	pv &= 3;
@@ -148,14 +148,14 @@
    have to expand it from a 24-bit signed number to a 32-bit signed
    number. */
 
-extern inline long nubus_expand32(long foo)
+static inline long nubus_expand32(long foo)
 {
 	if(foo & 0x00800000)	/* 24bit negative */
 		foo |= 0xFF000000;
 	return foo;
 }
 
-extern inline void *nubus_rom_addr(int slot)
+static inline void *nubus_rom_addr(int slot)
 {	
 	/*
 	 *	Returns the first byte after the card. We then walk
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/parport/parport_pc.c	Fri Oct 18 21:03:04 2002
@@ -52,6 +52,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/pnp.h>
 #include <linux/sysctl.h>
 
 #include <asm/io.h>
@@ -2939,9 +2940,9 @@
 }
 
 static struct pci_driver parport_pc_pci_driver = {
-	name:		"parport_pc",
-	id_table:	parport_pc_pci_tbl,
-	probe:		parport_pc_pci_probe,
+	.name		= "parport_pc",
+	.id_table	= parport_pc_pci_tbl,
+	.probe		= parport_pc_pci_probe,
 };
 
 static int __init parport_pc_init_superio (int autoirq, int autodma)
@@ -2968,6 +2969,25 @@
 static int __init parport_pc_init_superio(int autoirq, int autodma) {return 0;}
 #endif /* CONFIG_PCI */
 
+#ifdef CONFIG_PNP
+static const struct pnp_id pnp_dev_table[] = {
+	/* Standard LPT Printer Port */
+	{.id = "PNP0400", .driver_data = 0},
+	/* ECP Printer Port */
+	{.id = "PNP0401", .driver_data = 0},
+	{.id = ""}
+};
+
+/* we only need the pnp layer to activate the device, at least for now */
+static struct pnp_driver parport_pc_pnp_driver = {
+	.name		= "parport_pc",
+	.card_id_table	= NULL,
+	.id_table	= pnp_dev_table,
+};
+#else
+static const struct pnp_driver parport_pc_pnp_driver;
+#endif
+
 /* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */
 static int __init __attribute__((unused))
 parport_pc_find_isa_ports (int autoirq, int autodma)
@@ -3021,6 +3041,8 @@
 int __init parport_pc_init (int *io, int *io_hi, int *irq, int *dma)
 {
 	int count = 0, i = 0;
+	/* try to activate any PnP parports first */
+	pnp_register_driver(&parport_pc_pnp_driver);
 
 	if (io && *io) {
 		/* Only probe the ports we were given. */
@@ -3133,5 +3155,6 @@
 
 		p = tmp;
 	}
+	pnp_unregister_driver (&parport_pc_pnp_driver);
 }
 #endif
diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile	Fri Oct 18 21:03:08 2002
+++ b/drivers/pci/Makefile	Fri Oct 18 21:03:08 2002
@@ -31,6 +31,9 @@
 
 host-progs := gen-devlist
 
+# Files generated that shall be removed upon make clean
+clean-files := devlist.h classlist.h
+
 include $(TOPDIR)/Rules.make
 
 # Dependencies on generated files need to be listed explicitly
diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
--- a/drivers/pci/pci-driver.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/pci/pci-driver.c	Fri Oct 18 21:03:07 2002
@@ -141,7 +141,7 @@
 void
 pci_unregister_driver(struct pci_driver *drv)
 {
-	remove_driver(&drv->driver);
+	driver_unregister(&drv->driver);
 }
 
 static struct pci_driver pci_compat_driver = {
diff -Nru a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
--- a/drivers/pcmcia/sa1111_generic.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/pcmcia/sa1111_generic.c	Fri Oct 18 21:03:04 2002
@@ -297,7 +297,7 @@
 
 static void __exit sa1111_drv_pcmcia_exit(void)
 {
-	remove_driver(&pcmcia_driver.drv);
+	driver_unregister(&pcmcia_driver.drv);
 }
 
 module_init(sa1111_drv_pcmcia_init);
diff -Nru a/drivers/pnp/Config.help b/drivers/pnp/Config.help
--- a/drivers/pnp/Config.help	Fri Oct 18 21:03:03 2002
+++ b/drivers/pnp/Config.help	Fri Oct 18 21:03:03 2002
@@ -6,15 +6,22 @@
   or using a user-space utility.
 
   Say Y here if you would like Linux to configure your Plug and Play
-  devices. You should then also say Y to "ISA Plug and Play support",
-  below. Alternatively, you can say N here and configure your PnP
-  devices using the user space utilities contained in the isapnptools
-  package.
-
-  This support is also available 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>.
+  devices. You should then also say Y to all of the protocols below.
+  Alternatively, you can say N here and configure your PnP devices
+  using user space utilities such as the isapnptools package.
+
+  If unsure, say Y.
+
+CONFIG_PNP_NAMES
+  Select Y if you want the Plug and Play Layer to keep a database of
+  human readable names for your PnP devices.  It will increase the size
+  of the kernel image by around 5 KB and use 16 KB of system memory.
+
+  If unsure, say Y.
+
+CONFIG_PNP_DEBUG
+  Say Y if you want the Plug and Play Layer to print debug messages.  
+  This is useful if you are developing a PnP driver or troubleshooting.
 
 CONFIG_ISAPNP
   Say Y here if you would like support for ISA Plug and Play devices.
@@ -32,8 +39,8 @@
   Specification Version 1.0A May 5, 1994" to autodetect built-in
   mainboard resources (e.g. parallel port resources).
 
-  Other features (e.g. change resources, ESCD, event notification,
-  Docking station information, ISAPNP services) are not used.
+  Some features (e.g. event notification, docking station information,
+  ISAPNP services) are not used.
 
   Note: ACPI is expected to supersede PNPBIOS some day, currently it
   co-exists nicely.
diff -Nru a/drivers/pnp/Config.in b/drivers/pnp/Config.in
--- a/drivers/pnp/Config.in	Fri Oct 18 21:03:03 2002
+++ b/drivers/pnp/Config.in	Fri Oct 18 21:03:03 2002
@@ -4,12 +4,15 @@
 mainmenu_option next_comment
 comment 'Plug and Play configuration'
 
-tristate 'Plug and Play support' CONFIG_PNP
+dep_bool 'Plug and Play support' CONFIG_PNP
 
-dep_tristate '  ISA Plug and Play support' CONFIG_ISAPNP $CONFIG_PNP
+   dep_bool '  Plug and Play device name database' CONFIG_PNP_NAMES $CONFIG_PNP
+   dep_bool '  PnP Debug Messages' CONFIG_PNP_DEBUG $CONFIG_PNP
+
+comment 'Protocols' $CONFIG_PNP
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   dep_bool '  PNPBIOS support (EXPERIMENTAL)' CONFIG_PNPBIOS $CONFIG_PNP
+   dep_bool '  ISA Plug and Play support (EXPERIMENTAL)' CONFIG_ISAPNP $CONFIG_PNP
+   dep_bool '  Plug and Play BIOS support (EXPERIMENTAL)' CONFIG_PNPBIOS $CONFIG_PNP
 fi
-
 endmenu
diff -Nru a/drivers/pnp/Makefile b/drivers/pnp/Makefile
--- a/drivers/pnp/Makefile	Fri Oct 18 21:03:03 2002
+++ b/drivers/pnp/Makefile	Fri Oct 18 21:03:03 2002
@@ -1,16 +1,12 @@
 #
-# Makefile for the kernel Plug-and-Play device drivers.
+# Makefile for the Linux Plug-and-Play Support.
 #
 
-export-objs := isapnp.o pnpbios_core.o
+obj-y		:= core.o driver.o resource.o interface.o quirks.o names.o compat.o system.o
 
-isa-pnp-proc-$(CONFIG_PROC_FS) = isapnp_proc.o
-pnpbios-proc-$(CONFIG_PROC_FS) = pnpbios_proc.o
+obj-$(CONFIG_PNPBIOS)		+= pnpbios/
+obj-$(CONFIG_ISAPNP)		+= isapnp/
 
-isa-pnp-objs := isapnp.o quirks.o $(isa-pnp-proc-y)
-pnpbios-objs := pnpbios_core.o $(pnpbios-proc-y)
-
-obj-$(CONFIG_ISAPNP) += isa-pnp.o
-obj-$(CONFIG_PNPBIOS) += pnpbios.o
+export-objs	:= core.o driver.o resource.o compat.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/pnp/base.h b/drivers/pnp/base.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/base.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,11 @@
+extern struct bus_type pnp_bus_type;
+extern spinlock_t pnp_lock;
+extern void *pnp_alloc(long size);
+extern int pnp_interface_attach_device(struct pnp_dev *dev);
+extern void pnp_name_device(struct pnp_dev *dev);
+extern void pnp_fixup_device(struct pnp_dev *dev);
+extern int compare_pnp_id(struct list_head * id_list, char * id);
+extern void pnp_free_ids(struct pnp_dev *dev);
+extern void pnp_free_resources(struct pnp_resources *resources);
+
+
diff -Nru a/drivers/pnp/compat.c b/drivers/pnp/compat.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/compat.c	Fri Oct 18 21:03:09 2002
@@ -0,0 +1,94 @@
+/*
+ * compat.c - A series of functions to make it easier to convert drivers that use
+ *            the old isapnp APIs. If possible use the new APIs instead.
+ *
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+ 
+/* TODO: see if more isapnp functions are needed here */
+
+#include <linux/pnp.h>
+#include <linux/isapnp.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include "base.h"
+
+static void pnp_convert_id(char *buf, unsigned short vendor, unsigned short device)
+{
+	sprintf(buf, "%c%c%c%x%x%x%x",
+			'A' + ((vendor >> 2) & 0x3f) - 1,
+			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+			'A' + ((vendor >> 8) & 0x1f) - 1,
+			(device >> 4) & 0x0f,
+			device & 0x0f,
+			(device >> 12) & 0x0f,
+			(device >> 8) & 0x0f);
+	return;
+}
+
+struct pnp_card *pnp_find_card(unsigned short vendor,
+				 unsigned short device,
+				 struct pnp_card *from)
+{
+	char id[7];
+	char any[7];
+	struct list_head *list;
+	pnp_convert_id(id, vendor, device);
+	pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID);
+	list = isapnp_cards.next;
+	if (from)
+		list = from->node.next;
+
+	while (list != &isapnp_cards) {
+		struct pnp_card *card = to_pnp_card(list);
+		if (compare_pnp_id(&card->ids,id) || (memcmp(id,any,7)==0))
+			return card;
+		list = list->next;
+	}
+	return NULL;
+}
+
+struct pnp_dev *pnp_find_dev(struct pnp_card *card,
+				unsigned short vendor,
+				unsigned short function,
+				struct pnp_dev *from)
+{
+	char id[7];
+	char any[7];
+	pnp_convert_id(id, vendor, function);
+	pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID);
+	if (card == NULL) {	/* look for a logical device from all cards */
+		struct list_head *list;
+
+		list = pnp_global.next;
+		if (from)
+			list = from->global_list.next;
+
+		while (list != &pnp_global) {
+			struct pnp_dev *dev = global_to_pnp_dev(list);
+			if (compare_pnp_id(&dev->ids,id) || (memcmp(id,any,7)==0))
+				return dev;
+			list = list->next;
+		}
+	} else {
+		struct list_head *list;
+
+		list = card->devices.next;
+		if (from) {
+			list = from->card_list.next;
+			if (from->card != card)	/* something is wrong */
+				return NULL;
+		}
+		while (list != &card->devices) {
+			struct pnp_dev *dev = card_to_pnp_dev(list);
+			if (compare_pnp_id(&dev->ids,id))
+				return dev;
+			list = list->next;
+		}
+	}
+	return NULL;
+}
+
+EXPORT_SYMBOL(pnp_find_card);
+EXPORT_SYMBOL(pnp_find_dev);
diff -Nru a/drivers/pnp/core.c b/drivers/pnp/core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/core.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,176 @@
+/*
+ * core.c - contains all core device and protocol registration functions
+ *
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+#include <linux/pnp.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "base.h"
+
+
+LIST_HEAD(pnp_protocols);
+LIST_HEAD(pnp_global);
+spinlock_t pnp_lock = SPIN_LOCK_UNLOCKED;
+
+void *pnp_alloc(long size)
+{
+	void *result;
+
+	result = kmalloc(size, GFP_KERNEL);
+	if (!result){
+		printk(KERN_ERR "pnp: Out of Memory\n");
+		return NULL;
+	}
+	memset(result, 0, size);
+	return result;
+}
+
+/**
+ * pnp_protocol_register - adds a pnp protocol to the pnp layer
+ * @protocol: pointer to the corresponding pnp_protocol structure
+ *
+ *  Ex protocols: ISAPNP, PNPBIOS, etc
+ */
+
+int pnp_protocol_register(struct pnp_protocol *protocol)
+{
+	int nodenum;
+	struct list_head * pos;
+
+	if (!protocol)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&protocol->devices);
+	nodenum = 0;
+	spin_lock(&pnp_lock);
+
+	/* assign the lowest unused number */
+	list_for_each(pos,&pnp_protocols) {
+		struct pnp_protocol * cur = to_pnp_protocol(pos);
+		if (cur->number == nodenum){
+			pos = &pnp_protocols;
+			nodenum++;
+		}
+	}
+
+	list_add_tail(&protocol->protocol_list, &pnp_protocols);
+	spin_unlock(&pnp_lock);
+
+	protocol->number = nodenum;
+	sprintf(protocol->dev.bus_id, "pnp%d", nodenum);
+	strncpy(protocol->dev.name,protocol->name,DEVICE_NAME_SIZE);
+	return device_register(&protocol->dev);
+}
+
+/**
+ * pnp_protocol_unregister - removes a pnp protocol from the pnp layer
+ * @protocol: pointer to the corresponding pnp_protocol structure
+ *
+ */
+void pnp_protocol_unregister(struct pnp_protocol *protocol)
+{
+	spin_lock(&pnp_lock);
+	list_del_init(&protocol->protocol_list);
+	spin_unlock(&pnp_lock);
+	device_unregister(&protocol->dev);
+	return;
+}
+
+/**
+ * pnp_init_device - pnp protocols should call this before adding a PnP device
+ * @dev: pointer to dev to init
+ *
+ *  for now it only inits dev->ids, more later?
+ */
+
+int pnp_init_device(struct pnp_dev *dev)
+{
+	INIT_LIST_HEAD(&dev->ids);
+	return 0;
+}
+
+static void pnp_release_device(struct device *dmdev)
+{
+	struct pnp_dev * dev = to_pnp_dev(dmdev);
+	if (dev->res)
+		pnp_free_resources(dev->res);
+	pnp_free_ids(dev);
+	kfree(dev);
+	return;
+}
+
+/**
+ * pnp_add_device - adds a pnp device to the pnp layer
+ * @dev: pointer to dev to add
+ *
+ *  adds to driver model, name database, fixups, interface, etc.
+ */
+
+int pnp_add_device(struct pnp_dev *dev)
+{
+	int error = 0;
+	if (!dev && !dev->protocol)
+		return -EINVAL;
+	if (dev->card)
+		sprintf(dev->dev.bus_id, "%02x:%02x.%02x", dev->protocol->number,
+		  dev->card->number,dev->number);
+	else
+		sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
+		  dev->number);
+	pnp_name_device(dev);
+	pnp_fixup_device(dev);
+	strcpy(dev->dev.name,dev->name);
+	dev->dev.parent = &dev->protocol->dev;
+	dev->dev.bus = &pnp_bus_type;
+	dev->dev.release = &pnp_release_device;
+	error = device_register(&dev->dev);
+	if (error == 0){
+		spin_lock(&pnp_lock);
+		list_add_tail(&dev->global_list, &pnp_global);
+		list_add_tail(&dev->dev_list, &dev->protocol->devices);
+		spin_unlock(&pnp_lock);
+		pnp_interface_attach_device(dev);
+	}
+	return error;
+}
+
+/**
+ * pnp_remove_device - removes a pnp device from the pnp layer
+ * @dev: pointer to dev to add
+ *
+ * this function will free all mem used by dev
+ */
+void pnp_remove_device(struct pnp_dev *dev)
+{
+	if (!dev)
+		return;
+	device_unregister(&dev->dev);
+	spin_lock(&pnp_lock);
+	list_del_init(&dev->global_list);
+	list_del_init(&dev->dev_list);
+	spin_unlock(&pnp_lock);
+	return;
+}
+
+static int __init pnp_init(void)
+{
+	printk(KERN_INFO "Linux Plug and Play Support v0.9 (c) Adam Belay\n");
+	return bus_register(&pnp_bus_type);
+}
+
+core_initcall(pnp_init);
+
+EXPORT_SYMBOL(pnp_protocol_register);
+EXPORT_SYMBOL(pnp_protocol_unregister);
+EXPORT_SYMBOL(pnp_add_device);
+EXPORT_SYMBOL(pnp_remove_device);
+EXPORT_SYMBOL(pnp_init_device);
diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/driver.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,202 @@
+/*
+ * driver.c - device id matching, driver model, etc.
+ *
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_PNP_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+
+#include <linux/pnp.h>
+
+static int compare_func(const char *ida, const char *idb)
+{
+	int i;
+	/* we only need to compare the last 4 chars */
+	for (i=3; i<7; i++)
+	{
+		if (ida[i] != 'X' &&
+		    idb[i] != 'X' &&
+		    toupper(ida[i]) != toupper(idb[i]))
+			return 0;
+	}
+	return 1;
+}
+
+int compare_pnp_id(struct list_head *id_list, const char *id)
+{
+	struct list_head *pos;
+	if (!id_list || !id || (strlen(id) != 7))
+		return 0;
+	if (memcmp(id,"ANYDEVS",7)==0)
+		return 1;
+	list_for_each(pos,id_list){
+		struct pnp_id *pnp_id = to_pnp_id(pos);
+		if (memcmp(pnp_id->id,id,3)==0)
+			if (compare_func(pnp_id->id,id)==1)
+				return 1;
+	}
+	return 0;
+}
+
+static const struct pnp_id * match_card(struct pnp_driver *drv, struct pnp_card *card)
+{
+	const struct pnp_id *drv_card_id = drv->card_id_table;
+	if (!drv)
+		return NULL;
+	if (!card)
+		return NULL;
+	while (*drv_card_id->id){
+		if (compare_pnp_id(&card->ids,drv_card_id->id))
+			return drv_card_id;
+		drv_card_id++;
+	}
+	return NULL;
+}
+
+static const struct pnp_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev)
+{
+	const struct pnp_id *drv_id = drv->id_table;
+	if (!drv)
+		return NULL;
+	if (!dev)
+		return NULL;
+	while (*drv_id->id){
+		if (compare_pnp_id(&dev->ids,drv_id->id))
+			return drv_id;
+		drv_id++;
+	}
+	return NULL;
+}
+
+static int pnp_device_probe(struct device *dev)
+{
+	int error = 0;
+	struct pnp_driver *pnp_drv;
+	struct pnp_dev *pnp_dev;
+	const struct pnp_id *card_id = NULL;
+	const struct pnp_id *dev_id = NULL;
+	pnp_dev = to_pnp_dev(dev);
+	pnp_drv = to_pnp_driver(dev->driver);
+	pnp_dbg("pnp: match found with the PnP device '%s' and the driver '%s'", dev->bus_id,pnp_drv->name);
+
+	if (pnp_dev->active == 0)
+		if(pnp_activate_dev(pnp_dev)<0)
+			return 0;
+	if (pnp_drv->probe && pnp_dev->active) {
+		if (pnp_dev->card && pnp_drv->card_id_table){
+			card_id = match_card(pnp_drv, pnp_dev->card);
+			if (card_id != NULL)
+				dev_id = match_device(pnp_drv, pnp_dev);
+			if (dev_id != NULL)
+				error = pnp_drv->probe(pnp_dev, card_id, dev_id);
+		}
+		else{
+			dev_id = match_device(pnp_drv, pnp_dev);
+			if (dev_id != NULL)
+				error = pnp_drv->probe(pnp_dev, card_id, dev_id);
+		}
+		if (error >= 0){
+			pnp_dev->driver = pnp_drv;
+			error = 0;
+		}
+	}
+	return error;
+}
+
+static int pnp_device_remove(struct device *dev)
+{
+	struct pnp_dev * pnp_dev = to_pnp_dev(dev);
+	struct pnp_driver * drv = pnp_dev->driver;
+
+	if (drv) {
+		if (drv->remove)
+			drv->remove(pnp_dev);
+		pnp_dev->driver = NULL;
+	}
+	pnp_disable_dev(pnp_dev);
+	return 0;
+}
+
+static int pnp_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct pnp_dev * pnp_dev = to_pnp_dev(dev);
+	struct pnp_driver * pnp_drv = to_pnp_driver(drv);
+	if (pnp_dev->card && pnp_drv->card_id_table
+	    && match_card(pnp_drv, pnp_dev->card) == NULL)
+		return 0;
+	if (match_device(pnp_drv, pnp_dev) == NULL)
+		return 0;
+	return 1;
+}
+
+
+struct bus_type pnp_bus_type = {
+	name:	"pnp",
+	match:	pnp_bus_match,
+};
+
+
+int pnp_register_driver(struct pnp_driver *drv)
+{
+	int count = 0;
+	pnp_dbg("the driver '%s' has been registered", drv->name);
+
+	drv->driver.name = drv->name;
+	drv->driver.bus = &pnp_bus_type;
+	drv->driver.probe = pnp_device_probe;
+	drv->driver.remove = pnp_device_remove;
+
+	count = driver_register(&drv->driver);
+	return count ? count : 1;
+}
+
+void pnp_unregister_driver(struct pnp_driver *drv)
+{
+	pnp_dbg("the driver '%s' has been unregistered", drv->name);
+	remove_driver(&drv->driver);
+}
+
+/**
+ * pnp_add_id - adds an EISA id to the specified device
+ * @id: pointer to a pnp_id structure
+ * @dev: pointer to the desired device
+ *
+ */
+
+int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev)
+{
+	if (!id)
+		return -EINVAL;
+	if (!dev)
+		return -EINVAL;
+	list_add_tail(&id->id_list,&dev->ids);
+	return 0;
+}
+
+void pnp_free_ids(struct pnp_dev *dev)
+{
+	struct list_head *pos;
+	if (!dev)
+		return;
+	list_for_each(pos,&dev->ids){
+		struct pnp_id *pnp_id = to_pnp_id(pos);
+		kfree(pnp_id);
+	}
+	return;
+}
+
+EXPORT_SYMBOL(pnp_register_driver);
+EXPORT_SYMBOL(pnp_unregister_driver);
+EXPORT_SYMBOL(pnp_add_id);
diff -Nru a/drivers/pnp/idlist.h b/drivers/pnp/idlist.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/idlist.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,321 @@
+ID("CSC0000", "Crystal Semiconductor CS423x sound -- SB/WSS/OPL3 emulation")
+ID("CSC0010", "Crystal Semiconductor CS423x sound -- control")
+ID("CSC0001", "Crystal Semiconductor CS423x sound -- joystick")
+ID("CSC0003", "Crystal Semiconductor CS423x sound -- MPU401")
+ID("IBM3780", "IBM pointing device")
+ID("IBM0071", "IBM infrared communications device")
+ID("IBM3760", "IBM DSP")
+ID("PNP0000", "AT Interrupt Controller")
+ID("PNP0001", "EISA Interrupt Controller")
+ID("PNP0002", "MCA Interrupt Controller")
+ID("PNP0003", "APIC")
+ID("PNP0004", "Cyrix SLiC MP Interrupt Controller")
+ID("PNP0100", "AT Timer")
+ID("PNP0101", "EISA Timer")
+ID("PNP0102", "MCA Timer")
+ID("PNP0200", "AT DMA Controller")
+ID("PNP0201", "EISA DMA Controller")
+ID("PNP0202", "MCA DMA Controller")
+ID("PNP0300", "IBM PC/XT keyboard controller (83-key)")
+ID("PNP0301", "IBM PC/AT keyboard controller (86-key)")
+ID("PNP0302", "IBM PC/XT keyboard controller (84-key)")
+ID("PNP0303", "IBM Enhanced (101/102-key, PS/2 mouse support)")
+ID("PNP0304", "Olivetti Keyboard (83-key)")
+ID("PNP0305", "Olivetti Keyboard (102-key)")
+ID("PNP0306", "Olivetti Keyboard (86-key)")
+ID("PNP0307", "Microsoft Windows(R) Keyboard")
+ID("PNP0308", "General Input Device Emulation Interface (GIDEI) legacy")
+ID("PNP0309", "Olivetti Keyboard (A101/102 key)")
+ID("PNP030a", "AT&T 302 Keyboard")
+ID("PNP0320", "Japanese 106-key keyboard A01")
+ID("PNP0321", "Japanese 101-key keyboard")
+ID("PNP0322", "Japanese AX keyboard")
+ID("PNP0323", "Japanese 106-key keyboard 002/003")
+ID("PNP0324", "Japanese 106-key keyboard 001")
+ID("PNP0325", "Japanese Toshiba Desktop keyboard")
+ID("PNP0326", "Japanese Toshiba Laptop keyboard")
+ID("PNP0327", "Japanese Toshiba Notebook keyboard")
+ID("PNP0340", "Korean 84-key keyboard")
+ID("PNP0341", "Korean 86-key keyboard")
+ID("PNP0342", "Korean Enhanced keyboard")
+ID("PNP0343", "Korean Enhanced keyboard 101b")
+ID("PNP0343", "Korean Enhanced keyboard 101c")
+ID("PNP0344", "Korean Enhanced keyboard 103")
+ID("PNP0400", "Standard LPT printer port")
+ID("PNP0401", "ECP printer port")
+ID("PNP0500", "Standard PC COM port")
+ID("PNP0501", "16550A-compatible COM port")
+ID("PNP0502", "Multiport serial device (non-intelligent 16550)")
+ID("PNP0510", "Generic IRDA-compatible device")
+ID("PNP0511", "Generic IRDA-compatible device")
+ID("PNP0600", "Generic ESDI/IDE/ATA compatible hard disk controller")
+ID("PNP0601", "Plus Hardcard II")
+ID("PNP0602", "Plus Hardcard IIXL/EZ")
+ID("PNP0603", "Generic IDE supporting Microsoft Device Bay Specification")
+ID("PNP0700", "PC standard floppy disk controller")
+ID("PNP0701", "Standard floppy controller supporting MS Device Bay Spec")
+ID("PNP0900", "VGA Compatible")
+ID("PNP0901", "Video Seven VRAM/VRAM II/1024i")
+ID("PNP0902", "8514/A Compatible")
+ID("PNP0903", "Trident VGA")
+ID("PNP0904", "Cirrus Logic Laptop VGA")
+ID("PNP0905", "Cirrus Logic VGA")
+ID("PNP0906", "Tseng ET4000")
+ID("PNP0907", "Western Digital VGA")
+ID("PNP0908", "Western Digital Laptop VGA")
+ID("PNP0909", "S3 Inc. 911/924")
+ID("PNP090a", "ATI Ultra Pro/Plus (Mach 32)")
+ID("PNP090b", "ATI Ultra (Mach 8)")
+ID("PNP090c", "XGA Compatible")
+ID("PNP090d", "ATI VGA Wonder")
+ID("PNP090e", "Weitek P9000 Graphics Adapter")
+ID("PNP090f", "Oak Technology VGA")
+ID("PNP0910", "Compaq QVision")
+ID("PNP0911", "XGA/2")
+ID("PNP0912", "Tseng Labs W32/W32i/W32p")
+ID("PNP0913", "S3 Inc. 801/928/964")
+ID("PNP0914", "Cirrus Logic 5429/5434 (memory mapped)")
+ID("PNP0915", "Compaq Advanced VGA (AVGA)")
+ID("PNP0916", "ATI Ultra Pro Turbo (Mach64)")
+ID("PNP0917", "Reserved by Microsoft")
+ID("PNP0918", "Matrox MGA")
+ID("PNP0919", "Compaq QVision 2000")
+ID("PNP091a", "Tseng W128")
+ID("PNP0930", "Chips & Technologies Super VGA")
+ID("PNP0931", "Chips & Technologies Accelerator")
+ID("PNP0940", "NCR 77c22e Super VGA")
+ID("PNP0941", "NCR 77c32blt")
+ID("PNP09ff", "Plug and Play Monitors (VESA DDC)")
+ID("PNP0a00", "ISA Bus")
+ID("PNP0a01", "EISA Bus")
+ID("PNP0a02", "MCA Bus")
+ID("PNP0a03", "PCI Bus")
+ID("PNP0a04", "VESA/VL Bus")
+ID("PNP0a05", "Generic ACPI Bus")
+ID("PNP0a06", "Generic ACPI Extended-IO Bus (EIO bus)")
+ID("PNP0800", "AT-style speaker sound")
+ID("PNP0b00", "AT Real-Time Clock")
+ID("PNP0c00", "Plug and Play BIOS (only created by the root enumerator)")
+ID("PNP0c01", "System Board")
+ID("PNP0c02", "Reserved Motherboard Resources")
+ID("PNP0c03", "Plug and Play BIOS Event Notification Interrupt")
+ID("PNP0c04", "Math Coprocessor")
+ID("PNP0c05", "APM BIOS (Version independent)")
+ID("PNP0c06", "Reserved for identification of early Plug and Play BIOS implementation.")
+ID("PNP0c07", "Reserved for identification of early Plug and Play BIOS implementation.")
+ID("PNP0c08", "ACPI system board hardware")
+ID("PNP0c09", "ACPI Embedded Controller")
+ID("PNP0c0a", "ACPI Control Method Battery")
+ID("PNP0c0b", "ACPI Fan")
+ID("PNP0c0c", "ACPI power button device")
+ID("PNP0c0d", "ACPI lid device")
+ID("PNP0c0e", "ACPI sleep button device")
+ID("PNP0c0f", "PCI interrupt link device")
+ID("PNP0c10", "ACPI system indicator device")
+ID("PNP0c11", "ACPI thermal zone")
+ID("PNP0c12", "Device Bay Controller")
+ID("PNP0c13", "Plug and Play BIOS (used when ACPI mode cannot be used)")
+ID("PNP0e00", "Intel 82365-Compatible PCMCIA Controller")
+ID("PNP0e01", "Cirrus Logic CL-PD6720 PCMCIA Controller")
+ID("PNP0e02", "VLSI VL82C146 PCMCIA Controller")
+ID("PNP0e03", "Intel 82365-compatible CardBus controller")
+ID("PNP0f00", "Microsoft Bus Mouse")
+ID("PNP0f01", "Microsoft Serial Mouse")
+ID("PNP0f02", "Microsoft InPort Mouse")
+ID("PNP0f03", "Microsoft PS/2-style Mouse")
+ID("PNP0f04", "Mouse Systems Mouse")
+ID("PNP0f05", "Mouse Systems 3-Button Mouse (COM2)")
+ID("PNP0f06", "Genius Mouse (COM1)")
+ID("PNP0f07", "Genius Mouse (COM2)")
+ID("PNP0f08", "Logitech Serial Mouse")
+ID("PNP0f09", "Microsoft BallPoint Serial Mouse")
+ID("PNP0f0a", "Microsoft Plug and Play Mouse")
+ID("PNP0f0b", "Microsoft Plug and Play BallPoint Mouse")
+ID("PNP0f0c", "Microsoft-compatible Serial Mouse")
+ID("PNP0f0d", "Microsoft-compatible InPort-compatible Mouse")
+ID("PNP0f0e", "Microsoft-compatible PS/2-style Mouse")
+ID("PNP0f0f", "Microsoft-compatible Serial BallPoint-compatible Mouse")
+ID("PNP0f10", "Texas Instruments QuickPort Mouse")
+ID("PNP0f11", "Microsoft-compatible Bus Mouse")
+ID("PNP0f12", "Logitech PS/2-style Mouse")
+ID("PNP0f13", "PS/2 Port for PS/2-style Mice")
+ID("PNP0f14", "Microsoft Kids Mouse")
+ID("PNP0f15", "Logitech bus mouse")
+ID("PNP0f16", "Logitech SWIFT device")
+ID("PNP0f17", "Logitech-compatible serial mouse")
+ID("PNP0f18", "Logitech-compatible bus mouse")
+ID("PNP0f19", "Logitech-compatible PS/2-style Mouse")
+ID("PNP0f1a", "Logitech-compatible SWIFT Device")
+ID("PNP0f1b", "HP Omnibook Mouse")
+ID("PNP0f1c", "Compaq LTE Trackball PS/2-style Mouse")
+ID("PNP0f1d", "Compaq LTE Trackball Serial Mouse")
+ID("PNP0f1e", "Microsoft Kids Trackball Mouse")
+ID("PNP8001", "Novell/Anthem NE3200")
+ID("PNP0802", "Microsoft Sound System or Compatible Device (obsolete)")
+ID("PNP8004", "Compaq NE3200")
+ID("PNP8006", "Intel EtherExpress/32")
+ID("PNP8008", "HP EtherTwist EISA LAN Adapter/32 (HP27248A)")
+ID("PNP8065", "Ungermann-Bass NIUps or NIUps/EOTP")
+ID("PNP8072", "DEC (DE211) EtherWorks MC/TP")
+ID("PNP8073", "DEC (DE212) EtherWorks MC/TP_BNC")
+ID("PNP8078", "DCA 10 Mb MCA")
+ID("PNP8074", "HP MC LAN Adapter/16 TP (PC27246)")
+ID("PNP80c9", "IBM Token Ring")
+ID("PNP80ca", "IBM Token Ring II")
+ID("PNP80cb", "IBM Token Ring II/Short")
+ID("PNP80cc", "IBM Token Ring 4/16Mbs")
+ID("PNP80d3", "Novell/Anthem NE1000")
+ID("PNP80d4", "Novell/Anthem NE2000")
+ID("PNP80d5", "NE1000 Compatible")
+ID("PNP80d6", "NE2000 Compatible")
+ID("PNP80d7", "Novell/Anthem NE1500T")
+ID("PNP80d8", "Novell/Anthem NE2100")
+ID("PNP80dd", "SMC ARCNETPC")
+ID("PNP80de", "SMC ARCNET PC100, PC200")
+ID("PNP80df", "SMC ARCNET PC110, PC210, PC250")
+ID("PNP80e0", "SMC ARCNET PC130/E")
+ID("PNP80e1", "SMC ARCNET PC120, PC220, PC260")
+ID("PNP80e2", "SMC ARCNET PC270/E")
+ID("PNP80e5", "SMC ARCNET PC600W, PC650W")
+ID("PNP80e7", "DEC DEPCA")
+ID("PNP80e8", "DEC (DE100) EtherWorks LC")
+ID("PNP80e9", "DEC (DE200) EtherWorks Turbo")
+ID("PNP80ea", "DEC (DE101) EtherWorks LC/TP")
+ID("PNP80eb", "DEC (DE201) EtherWorks Turbo/TP")
+ID("PNP80ec", "DEC (DE202) EtherWorks Turbo/TP_BNC")
+ID("PNP80ed", "DEC (DE102) EtherWorks LC/TP_BNC")
+ID("PNP80ee", "DEC EE101 (Built-In)")
+ID("PNP80ef", "DECpc 433 WS (Built-In)")
+ID("PNP80f1", "3Com EtherLink Plus")
+ID("PNP80f3", "3Com EtherLink II or IITP (8 or 16-bit)")
+ID("PNP80f4", "3Com TokenLink")
+ID("PNP80f6", "3Com EtherLink 16")
+ID("PNP80f7", "3Com EtherLink III")
+ID("PNP80f8", "3Com Generic Etherlink Plug and Play Device")
+ID("PNP80fb", "Thomas Conrad TC6045")
+ID("PNP80fc", "Thomas Conrad TC6042")
+ID("PNP80fd", "Thomas Conrad TC6142")
+ID("PNP80fe", "Thomas Conrad TC6145")
+ID("PNP80ff", "Thomas Conrad TC6242")
+ID("PNP8100", "Thomas Conrad TC6245")
+ID("PNP8105", "DCA 10 MB")
+ID("PNP8106", "DCA 10 MB Fiber Optic")
+ID("PNP8107", "DCA 10 MB Twisted Pair")
+ID("PNP8113", "Racal NI6510")
+ID("PNP811c", "Ungermann-Bass NIUpc")
+ID("PNP8120", "Ungermann-Bass NIUpc/EOTP")
+ID("PNP8123", "SMC StarCard PLUS (WD/8003S)")
+ID("PNP8124", "SMC StarCard PLUS With On Board Hub (WD/8003SH)")
+ID("PNP8125", "SMC EtherCard PLUS (WD/8003E)")
+ID("PNP8126", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EBT)")
+ID("PNP8127", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EB)")
+ID("PNP8128", "SMC EtherCard PLUS TP (WD/8003WT)")
+ID("PNP812a", "SMC EtherCard PLUS 16 With Boot ROM Socket (WD/8013EBT)")
+ID("PNP812d", "Intel EtherExpress 16 or 16TP")
+ID("PNP812f", "Intel TokenExpress 16/4")
+ID("PNP8130", "Intel TokenExpress MCA 16/4")
+ID("PNP8132", "Intel EtherExpress 16 (MCA)")
+ID("PNP8137", "Artisoft AE-1")
+ID("PNP8138", "Artisoft AE-2 or AE-3")
+ID("PNP8141", "Amplicard AC 210/XT")
+ID("PNP8142", "Amplicard AC 210/AT")
+ID("PNP814b", "Everex SpeedLink /PC16 (EV2027)")
+ID("PNP8155", "HP PC LAN Adapter/8 TP (HP27245)")
+ID("PNP8156", "HP PC LAN Adapter/16 TP (HP27247A)")
+ID("PNP8157", "HP PC LAN Adapter/8 TL (HP27250)")
+ID("PNP8158", "HP PC LAN Adapter/16 TP Plus (HP27247B)")
+ID("PNP8159", "HP PC LAN Adapter/16 TL Plus (HP27252)")
+ID("PNP815f", "National Semiconductor Ethernode *16AT")
+ID("PNP8160", "National Semiconductor AT/LANTIC EtherNODE 16-AT3")
+ID("PNP816a", "NCR Token-Ring 4 Mbs ISA")
+ID("PNP816d", "NCR Token-Ring 16/4 Mbs ISA")
+ID("PNP8191", "Olicom 16/4 Token-Ring Adapter")
+ID("PNP81c3", "SMC EtherCard PLUS Elite (WD/8003EP)")
+ID("PNP81c4", "SMC EtherCard PLUS 10T (WD/8003W)")
+ID("PNP81c5", "SMC EtherCard PLUS Elite 16 (WD/8013EP)")
+ID("PNP81c6", "SMC EtherCard PLUS Elite 16T (WD/8013W)")
+ID("PNP81c7", "SMC EtherCard PLUS Elite 16 Combo (WD/8013EW or 8013EWC)")
+ID("PNP81c8", "SMC EtherElite Ultra 16")
+ID("PNP81e4", "Pure Data PDI9025-32 (Token Ring)")
+ID("PNP81e6", "Pure Data PDI508+ (ArcNet)")
+ID("PNP81e7", "Pure Data PDI516+ (ArcNet)")
+ID("PNP81eb", "Proteon Token Ring (P1390)")
+ID("PNP81ec", "Proteon Token Ring (P1392)")
+ID("PNP81ed", "Proteon ISA Token Ring (1340)")
+ID("PNP81ee", "Proteon ISA Token Ring (1342)")
+ID("PNP81ef", "Proteon ISA Token Ring (1346)")
+ID("PNP81f0", "Proteon ISA Token Ring (1347)")
+ID("PNP81ff", "Cabletron E2000 Series DNI")
+ID("PNP8200", "Cabletron E2100 Series DNI")
+ID("PNP8209", "Zenith Data Systems Z-Note")
+ID("PNP820a", "Zenith Data Systems NE2000-Compatible")
+ID("PNP8213", "Xircom Pocket Ethernet II")
+ID("PNP8214", "Xircom Pocket Ethernet I")
+ID("PNP821d", "RadiSys EXM-10")
+ID("PNP8227", "SMC 3000 Series")
+ID("PNP8228", "SMC 91C2 controller")
+ID("PNP8231", "Advanced Micro Devices AM2100/AM1500T")
+ID("PNP8263", "Tulip NCC-16")
+ID("PNP8277", "Exos 105")
+ID("PNP828a", "Intel '595 based Ethernet")
+ID("PNP828b", "TI2000-style Token Ring")
+ID("PNP828c", "AMD PCNet Family cards")
+ID("PNP828d", "AMD PCNet32 (VL version)")
+ID("PNP8294", "IrDA Infrared NDIS driver (Microsoft-supplied)")
+ID("PNP82bd", "IBM PCMCIA-NIC")
+ID("PNP82c2", "Xircom CE10")
+ID("PNP82c3", "Xircom CEM2")
+ID("PNP8321", "DEC Ethernet (All Types)")
+ID("PNP8323", "SMC EtherCard (All Types except 8013/A)")
+ID("PNP8324", "ARCNET Compatible")
+ID("PNP8326", "Thomas Conrad (All Arcnet Types)")
+ID("PNP8327", "IBM Token Ring (All Types)")
+ID("PNP8385", "Remote Network Access Driver")
+ID("PNP8387", "RNA Point-to-point Protocol Driver")
+ID("PNP8388", "Reserved for Microsoft Networking components")
+ID("PNP8389", "Peer IrLAN infrared driver (Microsoft-supplied)")
+ID("PNP8390", "Generic network adapter")
+ID("PNPa002", "Future Domain 16-700 compatible controller")
+ID("PNPa003", "Panasonic proprietary CD-ROM adapter (SBPro/SB16)")
+ID("PNPa01b", "Trantor 128 SCSI Controller")
+ID("PNPa01d", "Trantor T160 SCSI Controller")
+ID("PNPa01e", "Trantor T338 Parallel SCSI controller")
+ID("PNPa01f", "Trantor T348 Parallel SCSI controller")
+ID("PNPa020", "Trantor Media Vision SCSI controller")
+ID("PNPa022", "Always IN-2000 SCSI controller")
+ID("PNPa02b", "Sony proprietary CD-ROM controller")
+ID("PNPa02d", "Trantor T13b 8-bit SCSI controller")
+ID("PNPa02f", "Trantor T358 Parallel SCSI controller")
+ID("PNPa030", "Mitsumi LU-005 Single Speed CD-ROM controller + drive")
+ID("PNPa031", "Mitsumi FX-001 Single Speed CD-ROM controller + drive")
+ID("PNPa032", "Mitsumi FX-001 Double Speed CD-ROM controller + drive")
+ID("PNPb000", "Sound Blaster 1.5 sound device")
+ID("PNPb001", "Sound Blaster 2.0 sound device")
+ID("PNPb002", "Sound Blaster Pro sound device")
+ID("PNPb003", "Sound Blaster 16 sound device")
+ID("PNPb004", "Thunderboard-compatible sound device")
+ID("PNPb005", "Adlib-compatible FM synthesizer device")
+ID("PNPb006", "MPU401 compatible")
+ID("PNPb007", "Microsoft Windows Sound System-compatible sound device")
+ID("PNPb008", "Compaq Business Audio")
+ID("PNPb009", "Plug and Play Microsoft Windows Sound System Device")
+ID("PNPb00a", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Disabled)")
+ID("PNPb00b", "MediaVision Pro Audio 3D")
+ID("PNPb00c", "MusicQuest MQX-32M")
+ID("PNPb00d", "MediaVision Pro Audio Spectrum Basic (No Trantor SCSI, Thunder Chip Enabled)")
+ID("PNPb00e", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Enabled)")
+ID("PNPb00f", "MediaVision Jazz-16 chipset (OEM Versions)")
+ID("PNPb010", "Auravision VxP500 chipset - Orchid Videola")
+ID("PNPb018", "MediaVision Pro Audio Spectrum 8-bit")
+ID("PNPb019", "MediaVision Pro Audio Spectrum Basic (no Trantor SCSI, Thunder chip Disabled)")
+ID("PNPb020", "Yamaha OPL3-compatible FM synthesizer device")
+ID("PNPb02f", "Joystick/Game port")
+ID("PNPb000", "Compaq 14400 Modem (TBD)")
+ID("PNPc001", "Compaq 2400/9600 Modem (TBD)")
+ID("PNP0XXX", "Unknown System Device")
+ID("PNP8XXX", "Unknown Network Adapter")
+ID("PNPaXXX", "Unknown SCSI, Proprietary CD Adapter")
+ID("PNPbXXX", "Unknown Multimedia Device")
+ID("PNPcXXX", "Unknown Modem")
+
+#undef ID
diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/interface.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,342 @@
+/*
+ * interface.c - contains everything related to the user interface
+ *
+ * Some code is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz>
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+#include <linux/pnp.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+#include "base.h"
+
+struct pnp_info_buffer {
+	char *buffer;		/* pointer to begin of buffer */
+	char *curr;		/* current position in buffer */
+	unsigned long size;	/* current size */
+	unsigned long len;	/* total length of buffer */
+	int stop;		/* stop flag */
+	int error;		/* error code */
+};
+
+typedef struct pnp_info_buffer pnp_info_buffer_t;
+
+int pnp_printf(pnp_info_buffer_t * buffer, char *fmt,...)
+{
+	va_list args;
+	int res;
+	char sbuffer[512];
+
+	if (buffer->stop || buffer->error)
+		return 0;
+	va_start(args, fmt);
+	res = vsprintf(sbuffer, fmt, args);
+	va_end(args);
+	if (buffer->size + res >= buffer->len) {
+		buffer->stop = 1;
+		return 0;
+	}
+	strcpy(buffer->curr, sbuffer);
+	buffer->curr += res;
+	buffer->size += res;
+	return res;
+}
+
+static void pnp_print_port(pnp_info_buffer_t *buffer, char *space, struct pnp_port *port)
+{
+	pnp_printf(buffer, "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
+			space, port->min, port->max, port->align ? (port->align-1) : 0, port->size,
+			port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10);
+}
+
+static void pnp_print_irq(pnp_info_buffer_t *buffer, char *space, struct pnp_irq *irq)
+{
+	int first = 1, i;
+
+	pnp_printf(buffer, "%sirq ", space);
+	for (i = 0; i < 16; i++)
+		if (irq->map & (1<<i)) {
+			if (!first) {
+				pnp_printf(buffer, ",");
+			} else {
+				first = 0;
+			}
+			if (i == 2 || i == 9)
+				pnp_printf(buffer, "2/9");
+			else
+				pnp_printf(buffer, "%i", i);
+		}
+	if (!irq->map)
+		pnp_printf(buffer, "<none>");
+	if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
+		pnp_printf(buffer, " High-Edge");
+	if (irq->flags & IORESOURCE_IRQ_LOWEDGE)
+		pnp_printf(buffer, " Low-Edge");
+	if (irq->flags & IORESOURCE_IRQ_HIGHLEVEL)
+		pnp_printf(buffer, " High-Level");
+	if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
+		pnp_printf(buffer, " Low-Level");
+	pnp_printf(buffer, "\n");
+}
+
+static void pnp_print_dma(pnp_info_buffer_t *buffer, char *space, struct pnp_dma *dma)
+{
+	int first = 1, i;
+	char *s;
+
+	pnp_printf(buffer, "%sdma ", space);
+	for (i = 0; i < 8; i++)
+		if (dma->map & (1<<i)) {
+			if (!first) {
+				pnp_printf(buffer, ",");
+			} else {
+				first = 0;
+			}
+			pnp_printf(buffer, "%i", i);
+		}
+	if (!dma->map)
+		pnp_printf(buffer, "<none>");
+	switch (dma->flags & IORESOURCE_DMA_TYPE_MASK) {
+	case IORESOURCE_DMA_8BIT:
+		s = "8-bit";
+		break;
+	case IORESOURCE_DMA_8AND16BIT:
+		s = "8-bit&16-bit";
+		break;
+	default:
+		s = "16-bit";
+	}
+	pnp_printf(buffer, " %s", s);
+	if (dma->flags & IORESOURCE_DMA_MASTER)
+		pnp_printf(buffer, " master");
+	if (dma->flags & IORESOURCE_DMA_BYTE)
+		pnp_printf(buffer, " byte-count");
+	if (dma->flags & IORESOURCE_DMA_WORD)
+		pnp_printf(buffer, " word-count");
+	switch (dma->flags & IORESOURCE_DMA_SPEED_MASK) {
+	case IORESOURCE_DMA_TYPEA:
+		s = "type-A";
+		break;
+	case IORESOURCE_DMA_TYPEB:
+		s = "type-B";
+		break;
+	case IORESOURCE_DMA_TYPEF:
+		s = "type-F";
+		break;
+	default:
+		s = "compatible";
+		break;
+	}
+	pnp_printf(buffer, " %s\n", s);
+}
+
+static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem *mem)
+{
+	char *s;
+
+	pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
+			space, mem->min, mem->max, mem->align, mem->size);
+	if (mem->flags & IORESOURCE_MEM_WRITEABLE)
+		pnp_printf(buffer, ", writeable");
+	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
+		pnp_printf(buffer, ", cacheable");
+	if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
+		pnp_printf(buffer, ", range-length");
+	if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
+		pnp_printf(buffer, ", shadowable");
+	if (mem->flags & IORESOURCE_MEM_EXPANSIONROM)
+		pnp_printf(buffer, ", expansion ROM");
+	switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
+	case IORESOURCE_MEM_8BIT:
+		s = "8-bit";
+		break;
+	case IORESOURCE_MEM_8AND16BIT:
+		s = "8-bit&16-bit";
+		break;
+	default:
+		s = "16-bit";
+	}
+	pnp_printf(buffer, ", %s\n", s);
+}
+
+static void pnp_print_mem32(pnp_info_buffer_t *buffer, char *space, struct pnp_mem32 *mem32)
+{
+	int first = 1, i;
+
+	pnp_printf(buffer, "%s32-bit memory ", space);
+	for (i = 0; i < 17; i++) {
+		if (first) {
+			first = 0;
+		} else {
+			pnp_printf(buffer, ":");
+		}
+		pnp_printf(buffer, "%02x", mem32->data[i]);
+	}
+}
+
+static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct pnp_resources *res, int dep)
+{
+	char *s;
+	struct pnp_port *port;
+	struct pnp_irq *irq;
+	struct pnp_dma *dma;
+	struct pnp_mem *mem;
+	struct pnp_mem32 *mem32;
+
+	switch (res->priority) {
+	case PNP_RES_PRIORITY_PREFERRED:
+		s = "preferred";
+		break;
+	case PNP_RES_PRIORITY_ACCEPTABLE:
+		s = "acceptable";
+		break;
+	case PNP_RES_PRIORITY_FUNCTIONAL:
+		s = "functional";
+		break;
+	default:
+		s = "invalid";
+	}
+	if (dep > 0)
+		pnp_printf(buffer, "Dependent: %02i - Priority %s\n",dep, s);
+	for (port = res->port; port; port = port->next)
+		pnp_print_port(buffer, space, port);
+	for (irq = res->irq; irq; irq = irq->next)
+		pnp_print_irq(buffer, space, irq);
+	for (dma = res->dma; dma; dma = dma->next)
+		pnp_print_dma(buffer, space, dma);
+	for (mem = res->mem; mem; mem = mem->next)
+		pnp_print_mem(buffer, space, mem);
+	for (mem32 = res->mem32; mem32; mem32 = mem32->next)
+		pnp_print_mem32(buffer, space, mem32);
+}
+
+static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf, size_t count, loff_t off)
+{
+	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	struct pnp_resources * res = dev->res;
+	int dep = 0;
+	pnp_info_buffer_t *buffer;
+	if (off)
+		return 0;
+	buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
+	if (!buffer)
+		return -ENOMEM;
+	buffer->len = PAGE_SIZE;
+	buffer->buffer = buf;
+	buffer->curr = buffer->buffer;
+	while (res){
+		if (dep == 0)
+			pnp_print_resources(buffer, "", res, dep);
+		else
+			pnp_print_resources(buffer, "   ", res, dep);
+		res = res->dep;
+		dep++;
+	}
+	return (buffer->curr - buf);
+}
+
+static DEVICE_ATTR(possible,S_IRUGO,pnp_show_possible_resources,NULL);
+
+static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf, size_t count, loff_t off)
+{
+	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	char *str = buf;
+	int i;
+	if (off)
+		return 0;
+	if (!dev->active){
+		str += sprintf(str,"DISABLED\n");
+		goto done;
+	}
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+			if (dev->resource[i].flags & IORESOURCE_IO){
+				str += sprintf(str,"io");
+				str += sprintf(str," 0x%lx-0x%lx \n",
+					       dev->resource[i].start,
+					       dev->resource[i].end);
+			}
+			if (dev->resource[i].flags & IORESOURCE_MEM){
+				str += sprintf(str,"mem");
+				str += sprintf(str," 0x%lx-0x%lx \n",
+					       dev->resource[i].start,
+					       dev->resource[i].end);
+			}
+	}
+	for (i = 0; i < DEVICE_COUNT_IRQ && dev->irq_resource[i].flags
+			 & IORESOURCE_IRQ; i++) {
+			str += sprintf(str,"irq");
+			str += sprintf(str," %ld \n", dev->irq_resource[i].start);
+	}
+	for (i = 0; i < DEVICE_COUNT_DMA && dev->dma_resource[i].flags
+			 & IORESOURCE_DMA; i++) {
+			str += sprintf(str,"dma");
+			str += sprintf(str," %ld \n", dev->dma_resource[i].start);
+	}
+	done:
+	return (str - buf);
+}
+
+static ssize_t
+pnp_set_current_resources(struct device * dmdev, const char * buf, size_t count, loff_t off)
+{
+	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	char	command[20];
+	char	type[20];
+	int	num_args;
+	int	error = 0;
+	int	depnum, mode = 0;
+	if (off)
+		return 0;
+	num_args = sscanf(buf,"%10s %i %10s",command,&depnum,type);
+	if (!num_args)
+		goto done;
+	if (!strnicmp(command,"disable",7)) {
+		error = pnp_disable_dev(dev);
+		goto done;
+	}
+	if (!strnicmp(command,"auto",4)) {
+		error = pnp_activate_dev(dev);
+		goto done;
+	}
+	if (!strnicmp(command,"manual",6)) {
+		if (num_args != 3)
+			goto done;
+		if (!strnicmp(type,"static",6))
+			mode = PNP_STATIC;
+		error = pnp_raw_set_dev(dev,depnum,mode);
+		goto done;
+	}
+ done:
+	return error < 0 ? error : count;
+}
+
+static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR,
+		   pnp_show_current_resources,pnp_set_current_resources);
+
+static ssize_t pnp_show_current_ids(struct device *dmdev, char *buf, size_t count, loff_t off)
+{
+	char *str = buf;
+	struct list_head * pos;
+	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	if (off)
+		return 0;
+	list_for_each(pos,&dev->ids) {
+		struct pnp_id * cur = to_pnp_id(pos);
+		str += sprintf(str,"%s\n", cur->id);
+	}
+	return (str - buf);
+}
+
+static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL);
+
+int pnp_interface_attach_device(struct pnp_dev *dev)
+{
+	device_create_file(&dev->dev,&dev_attr_possible);
+	device_create_file(&dev->dev,&dev_attr_resources);
+	device_create_file(&dev->dev,&dev_attr_id);
+	return 0;
+}
diff -Nru a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/isapnp/Makefile	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel ISAPNP driver.
+#
+
+export-objs := core.o
+
+isapnp-proc-$(CONFIG_PROC_FS) = proc.o
+
+obj-y := core.o $(isapnp-proc-y)
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/isapnp/core.c	Fri Oct 18 21:03:04 2002
@@ -0,0 +1,1193 @@
+/*
+ *  ISA Plug & Play support
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ *   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.
+ *
+ *  Changelog:
+ *  2000-01-01	Added quirks handling for buggy hardware
+ *		Peter Denison <peterd@pnd-pc.demon.co.uk>
+ *  2000-06-14	Added isapnp_probe_devs() and isapnp_activate_dev()
+ *		Christoph Hellwig <hch@infradead.org>
+ *  2001-06-03  Added release_region calls to correspond with
+ *		request_region calls when a failure occurs.  Also
+ *		added KERN_* constants to printk() calls.
+ *  2001-11-07  Added isapnp_{,un}register_driver calls along the lines
+ *              of the pci driver interface
+ *              Kai Germaschewski <kai.germaschewski@gmx.de>
+ *  2002-06-06  Made the use of dma channel 0 configurable
+ *              Gerald Teschl <gerald.teschl@univie.ac.at>
+ *  2002-10-06  Ported to PnP Layer - Adam Belay <ambx1@neo.rr.com>
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/isapnp.h>
+#include <linux/pnp.h>
+
+LIST_HEAD(isapnp_cards);
+LIST_HEAD(isapnp_devices);
+
+#if 0
+#define ISAPNP_REGION_OK
+#endif
+#if 0
+#define ISAPNP_DEBUG
+#endif
+
+int isapnp_disable;			/* Disable ISA PnP */
+int isapnp_rdp;				/* Read Data Port */
+int isapnp_reset = 1;			/* reset all PnP cards (deactivate) */
+int isapnp_skip_pci_scan;		/* skip PCI resource scanning */
+int isapnp_verbose = 1;			/* verbose mode */
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_DESCRIPTION("Generic ISA Plug & Play support");
+MODULE_PARM(isapnp_disable, "i");
+MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");
+MODULE_PARM(isapnp_rdp, "i");
+MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
+MODULE_PARM(isapnp_reset, "i");
+MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
+MODULE_PARM(isapnp_allow_dma0, "i");
+MODULE_PARM(isapnp_skip_pci_scan, "i");
+MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
+MODULE_PARM(isapnp_verbose, "i");
+MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
+MODULE_LICENSE("GPL");
+
+#define _PIDXR		0x279
+#define _PNPWRP		0xa79
+
+/* short tags */
+#define _STAG_PNPVERNO		0x01
+#define _STAG_LOGDEVID		0x02
+#define _STAG_COMPATDEVID	0x03
+#define _STAG_IRQ		0x04
+#define _STAG_DMA		0x05
+#define _STAG_STARTDEP		0x06
+#define _STAG_ENDDEP		0x07
+#define _STAG_IOPORT		0x08
+#define _STAG_FIXEDIO		0x09
+#define _STAG_VENDOR		0x0e
+#define _STAG_END		0x0f
+/* long tags */
+#define _LTAG_MEMRANGE		0x81
+#define _LTAG_ANSISTR		0x82
+#define _LTAG_UNICODESTR	0x83
+#define _LTAG_VENDOR		0x84
+#define _LTAG_MEM32RANGE	0x85
+#define _LTAG_FIXEDMEM32RANGE	0x86
+
+static unsigned char isapnp_checksum_value;
+static DECLARE_MUTEX(isapnp_cfg_mutex);
+static int isapnp_detected;
+
+/* some prototypes */
+
+static int isapnp_config_prepare(struct pnp_dev *dev);
+
+static inline void write_data(unsigned char x)
+{
+	outb(x, _PNPWRP);
+}
+
+static inline void write_address(unsigned char x)
+{
+	outb(x, _PIDXR);
+	udelay(20);
+}
+
+static inline unsigned char read_data(void)
+{
+	unsigned char val = inb(isapnp_rdp);
+	return val;
+}
+
+unsigned char isapnp_read_byte(unsigned char idx)
+{
+	write_address(idx);
+	return read_data();
+}
+
+unsigned short isapnp_read_word(unsigned char idx)
+{
+	unsigned short val;
+
+	val = isapnp_read_byte(idx);
+	val = (val << 8) + isapnp_read_byte(idx+1);
+	return val;
+}
+
+unsigned int isapnp_read_dword(unsigned char idx)
+{
+	unsigned int val;
+
+	val = isapnp_read_byte(idx);
+	val = (val << 8) + isapnp_read_byte(idx+1);
+	val = (val << 8) + isapnp_read_byte(idx+2);
+	val = (val << 8) + isapnp_read_byte(idx+3);
+	return val;
+}
+
+void isapnp_write_byte(unsigned char idx, unsigned char val)
+{
+	write_address(idx);
+	write_data(val);
+}
+
+void isapnp_write_word(unsigned char idx, unsigned short val)
+{
+	isapnp_write_byte(idx, val >> 8);
+	isapnp_write_byte(idx+1, val);
+}
+
+void isapnp_write_dword(unsigned char idx, unsigned int val)
+{
+	isapnp_write_byte(idx, val >> 24);
+	isapnp_write_byte(idx+1, val >> 16);
+	isapnp_write_byte(idx+2, val >> 8);
+	isapnp_write_byte(idx+3, val);
+}
+
+void *isapnp_alloc(long size)
+{
+	void *result;
+
+	result = kmalloc(size, GFP_KERNEL);
+	if (!result)
+		return NULL;
+	memset(result, 0, size);
+	return result;
+}
+
+static void isapnp_key(void)
+{
+	unsigned char code = 0x6a, msb;
+	int i;
+
+	mdelay(1);
+	write_address(0x00);
+	write_address(0x00);
+
+	write_address(code);
+
+	for (i = 1; i < 32; i++) {
+		msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
+		code = (code >> 1) | msb;
+		write_address(code);
+	}
+}
+
+/* place all pnp cards in wait-for-key state */
+static void isapnp_wait(void)
+{
+	isapnp_write_byte(0x02, 0x02);
+}
+
+void isapnp_wake(unsigned char csn)
+{
+	isapnp_write_byte(0x03, csn);
+}
+
+void isapnp_device(unsigned char logdev)
+{
+	isapnp_write_byte(0x07, logdev);
+}
+
+void isapnp_activate(unsigned char logdev)
+{
+	isapnp_device(logdev);
+	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1);
+	udelay(250);
+}
+
+void isapnp_deactivate(unsigned char logdev)
+{
+	isapnp_device(logdev);
+	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0);
+	udelay(500);
+}
+
+static void __init isapnp_peek(unsigned char *data, int bytes)
+{
+	int i, j;
+	unsigned char d=0;
+
+	for (i = 1; i <= bytes; i++) {
+		for (j = 0; j < 20; j++) {
+			d = isapnp_read_byte(0x05);
+			if (d & 1)
+				break;
+			udelay(100);
+		}
+		if (!(d & 1)) {
+			if (data != NULL)
+				*data++ = 0xff;
+			continue;
+		}
+		d = isapnp_read_byte(0x04);	/* PRESDI */
+		isapnp_checksum_value += d;
+		if (data != NULL)
+			*data++ = d;
+	}
+}
+
+#define RDP_STEP	32	/* minimum is 4 */
+
+static int isapnp_next_rdp(void)
+{
+	int rdp = isapnp_rdp;
+	while (rdp <= 0x3ff) {
+		/*
+		 *	We cannot use NE2000 probe spaces for ISAPnP or we
+		 *	will lock up machines.
+		 */
+		if ((rdp < 0x280 || rdp >  0x380) && !check_region(rdp, 1)) 
+		{
+			isapnp_rdp = rdp;
+			return 0;
+		}
+		rdp += RDP_STEP;
+	}
+	return -1;
+}
+
+/* Set read port address */
+static inline void isapnp_set_rdp(void)
+{
+	isapnp_write_byte(0x00, isapnp_rdp >> 2);
+	udelay(100);
+}
+
+/*
+ *	Perform an isolation. The port selection code now tries to avoid
+ *	"dangerous to read" ports.
+ */
+
+static int __init isapnp_isolate_rdp_select(void)
+{
+	isapnp_wait();
+	isapnp_key();
+
+	/* Control: reset CSN and conditionally everything else too */
+	isapnp_write_byte(0x02, isapnp_reset ? 0x05 : 0x04);
+	mdelay(2);
+
+	isapnp_wait();
+	isapnp_key();
+	isapnp_wake(0x00);
+
+	if (isapnp_next_rdp() < 0) {
+		isapnp_wait();
+		return -1;
+	}
+
+	isapnp_set_rdp();
+	udelay(1000);
+	write_address(0x01);
+	udelay(1000);
+	return 0;
+}
+
+/*
+ *  Isolate (assign uniqued CSN) to all ISA PnP devices.
+ */
+
+static int __init isapnp_isolate(void)
+{
+	unsigned char checksum = 0x6a;
+	unsigned char chksum = 0x00;
+	unsigned char bit = 0x00;
+	int data;
+	int csn = 0;
+	int i;
+	int iteration = 1;
+
+	isapnp_rdp = 0x213;
+	if (isapnp_isolate_rdp_select() < 0)
+		return -1;
+
+	while (1) {
+		for (i = 1; i <= 64; i++) {
+			data = read_data() << 8;
+			udelay(250);
+			data = data | read_data();
+			udelay(250);
+			if (data == 0x55aa)
+				bit = 0x01;
+			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
+			bit = 0x00;
+		}
+		for (i = 65; i <= 72; i++) {
+			data = read_data() << 8;
+			udelay(250);
+			data = data | read_data();
+			udelay(250);
+			if (data == 0x55aa)
+				chksum |= (1 << (i - 65));
+		}
+		if (checksum != 0x00 && checksum == chksum) {
+			csn++;
+
+			isapnp_write_byte(0x06, csn);
+			udelay(250);
+			iteration++;
+			isapnp_wake(0x00);
+			isapnp_set_rdp();
+			udelay(1000);
+			write_address(0x01);
+			udelay(1000);
+			goto __next;
+		}
+		if (iteration == 1) {
+			isapnp_rdp += RDP_STEP;
+			if (isapnp_isolate_rdp_select() < 0)
+				return -1;
+		} else if (iteration > 1) {
+			break;
+		}
+	      __next:
+		checksum = 0x6a;
+		chksum = 0x00;
+		bit = 0x00;
+	}
+	isapnp_wait();
+	return csn;
+}
+
+/*
+ *  Read one tag from stream.
+ */
+
+static int __init isapnp_read_tag(unsigned char *type, unsigned short *size)
+{
+	unsigned char tag, tmp[2];
+
+	isapnp_peek(&tag, 1);
+	if (tag == 0)				/* invalid tag */
+		return -1;
+	if (tag & 0x80) {	/* large item */
+		*type = tag;
+		isapnp_peek(tmp, 2);
+		*size = (tmp[1] << 8) | tmp[0];
+	} else {
+		*type = (tag >> 3) & 0x0f;
+		*size = tag & 0x07;
+	}
+#if 0
+	printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
+#endif
+	if (type == 0)				/* wrong type */
+		return -1;
+	if (*type == 0xff && *size == 0xffff)	/* probably invalid data */
+		return -1;
+	return 0;
+}
+
+/*
+ *  Skip specified number of bytes from stream.
+ */
+
+static void __init isapnp_skip_bytes(int count)
+{
+	isapnp_peek(NULL, count);
+}
+
+/*
+ *  Parse EISA id.
+ */
+
+static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigned short device)
+{
+	struct pnp_id * id = isapnp_alloc(sizeof(struct pnp_id));
+	if (!id)
+		return;
+	if (!dev)
+		return;
+	sprintf(id->id, "%c%c%c%x%x%x%x",
+			'A' + ((vendor >> 2) & 0x3f) - 1,
+			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+			'A' + ((vendor >> 8) & 0x1f) - 1,
+			(device >> 4) & 0x0f,
+			device & 0x0f,
+			(device >> 12) & 0x0f,
+			(device >> 8) & 0x0f);
+	pnp_add_id(id, dev);
+}
+
+/*
+ *  Parse logical device tag.
+ */
+
+static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int size, int number)
+{
+	unsigned char tmp[6];
+	struct pnp_dev *dev;
+
+	isapnp_peek(tmp, size);
+	dev = isapnp_alloc(sizeof(struct pnp_dev));
+	if (!dev)
+		return NULL;
+	pnp_init_device(dev);
+	dev->number = number;
+	isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]);
+	dev->regs = tmp[4];
+	dev->card = card;
+	if (size > 5)
+		dev->regs |= tmp[5] << 8;
+	return dev;
+}
+
+
+/*
+ *  Add IRQ resource to resources list.
+ */
+
+static void __init isapnp_add_irq_resource(struct pnp_dev *dev,
+                                               int depnum, int size)
+{
+	unsigned char tmp[3];
+	struct pnp_irq *irq;
+
+	isapnp_peek(tmp, size);
+	irq = isapnp_alloc(sizeof(struct pnp_irq));
+	if (!irq)
+		return;
+	irq->map = (tmp[1] << 8) | tmp[0];
+	if (size > 2)
+		irq->flags = tmp[2];
+	else
+		irq->flags = IORESOURCE_IRQ_HIGHEDGE;
+	pnp_add_irq_resource(dev, depnum, irq);
+	return;
+}
+
+/*
+ *  Add DMA resource to resources list.
+ */
+
+static void __init isapnp_add_dma_resource(struct pnp_dev *dev,
+                                    	       int depnum, int size)
+{
+	unsigned char tmp[2];
+	struct pnp_dma *dma;
+
+	isapnp_peek(tmp, size);
+	dma = isapnp_alloc(sizeof(struct pnp_dma));
+	if (!dma)
+		return;
+	dma->map = tmp[0];
+	dma->flags = tmp[1];
+	pnp_add_dma_resource(dev, depnum, dma);
+	return;
+}
+
+/*
+ *  Add port resource to resources list.
+ */
+
+static void __init isapnp_add_port_resource(struct pnp_dev *dev,
+						int depnum, int size)
+{
+	unsigned char tmp[7];
+	struct pnp_port *port;
+
+	isapnp_peek(tmp, size);
+	port = isapnp_alloc(sizeof(struct pnp_port));
+	if (!port)
+		return;
+	port->min = (tmp[2] << 8) | tmp[1];
+	port->max = (tmp[4] << 8) | tmp[3];
+	port->align = tmp[5];
+	port->size = tmp[6];
+	port->flags = tmp[0] ? ISAPNP_PORT_FLAG_16BITADDR : 0;
+	pnp_add_port_resource(dev,depnum,port);
+	return;
+}
+
+/*
+ *  Add fixed port resource to resources list.
+ */
+
+static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev,
+						      int depnum, int size)
+{
+	unsigned char tmp[3];
+	struct pnp_port *port;
+
+	isapnp_peek(tmp, size);
+	port = isapnp_alloc(sizeof(struct pnp_port));
+	if (!port)
+		return;
+	port->min = port->max = (tmp[1] << 8) | tmp[0];
+	port->size = tmp[2];
+	port->align = 0;
+	port->flags = ISAPNP_PORT_FLAG_FIXED;
+	pnp_add_port_resource(dev,depnum,port);
+	return;
+}
+
+/*
+ *  Add memory resource to resources list.
+ */
+
+static void __init isapnp_add_mem_resource(struct pnp_dev *dev,
+					       int depnum, int size)
+{
+	unsigned char tmp[9];
+	struct pnp_mem *mem;
+
+	isapnp_peek(tmp, size);
+	mem = isapnp_alloc(sizeof(struct pnp_mem));
+	if (!mem)
+		return;
+	mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
+	mem->max = ((tmp[4] << 8) | tmp[3]) << 8;
+	mem->align = (tmp[6] << 8) | tmp[5];
+	mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
+	mem->flags = tmp[0];
+	pnp_add_mem_resource(dev,depnum,mem);
+	return;
+}
+
+/*
+ *  Add 32-bit memory resource to resources list.
+ */
+
+static void __init isapnp_add_mem32_resource(struct pnp_dev *dev,
+						 int depnum, int size)
+{
+	unsigned char tmp[17];
+	struct pnp_mem32 *mem32;
+
+	isapnp_peek(tmp, size);
+	mem32 = isapnp_alloc(sizeof(struct pnp_mem32));
+	if (!mem32)
+		return;
+	memcpy(mem32->data, tmp, 17);
+	pnp_add_mem32_resource(dev,depnum,mem32);
+}
+
+/*
+ *  Add 32-bit fixed memory resource to resources list.
+ */
+
+static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev,
+						       int depnum, int size)
+{
+	unsigned char tmp[17];
+	struct pnp_mem32 *mem32;
+
+	isapnp_peek(tmp, size);
+	mem32 = isapnp_alloc(sizeof(struct pnp_mem32));
+	if (!mem32)
+		return;
+	memcpy(mem32->data, tmp, 17);
+	pnp_add_mem32_resource(dev,depnum,mem32);
+}
+
+/*
+ *  Parse card name for ISA PnP device.
+ */ 
+ 
+static void __init 
+isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
+{
+	if (name[0] == '\0') {
+		unsigned short size1 = *size >= name_max ? (name_max - 1) : *size;
+		isapnp_peek(name, size1);
+		name[size1] = '\0';
+		*size -= size1;
+		
+		/* clean whitespace from end of string */
+		while (size1 > 0  &&  name[--size1] == ' ')
+			name[size1] = '\0';
+	}	
+}
+
+/*
+ *  Parse resource map for logical device.
+ */
+
+static int __init isapnp_create_device(struct pnp_card *card,
+					   unsigned short size)
+{
+	int number = 0, skip = 0, depnum = 0, dependent = 0, compat = 0;
+	unsigned char type, tmp[17];
+	struct pnp_dev *dev;
+	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
+		return 1;
+	if (pnp_build_resource(dev, 0) == NULL)
+		return 1;
+	list_add_tail(&dev->card_list, &card->devices);
+	while (1) {
+		if (isapnp_read_tag(&type, &size)<0)
+			return 1;
+		if (skip && type != _STAG_LOGDEVID && type != _STAG_END)
+			goto __skip;
+		switch (type) {
+		case _STAG_LOGDEVID:
+			if (size >= 5 && size <= 6) {
+				isapnp_config_prepare(dev);
+				if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
+					return 1;
+				pnp_build_resource(dev,0);
+				list_add_tail(&dev->card_list, &card->devices);
+				size = 0;
+				skip = 0;
+			} else {
+				skip = 1;
+			}
+			dependent = 0;
+			depnum = 0;
+			compat = 0;
+			break;
+		case _STAG_COMPATDEVID:
+			if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
+				isapnp_peek(tmp, 4);
+				isapnp_parse_id(dev,(tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]);
+				compat++;
+				size = 0;
+			}
+			break;
+		case _STAG_IRQ:
+			if (size < 2 || size > 3)
+				goto __skip;
+			isapnp_add_irq_resource(dev, depnum, size);
+			size = 0;
+			break;
+		case _STAG_DMA:
+			if (size != 2)
+				goto __skip;
+			isapnp_add_dma_resource(dev, depnum, size);
+			size = 0;
+			break;
+		case _STAG_STARTDEP:
+			if (size > 1)
+				goto __skip;
+			dependent = 0x100 | ISAPNP_RES_PRIORITY_ACCEPTABLE;
+			if (size > 0) {
+				isapnp_peek(tmp, size);
+				dependent = 0x100 | tmp[0];
+				size = 0;
+			}
+			pnp_build_resource(dev,dependent);
+			depnum = pnp_get_max_depnum(dev);
+			break;
+		case _STAG_ENDDEP:
+			if (size != 0)
+				goto __skip;
+			dependent = 0;
+			depnum = 0;
+			break;
+		case _STAG_IOPORT:
+			if (size != 7)
+				goto __skip;
+			isapnp_add_port_resource(dev, depnum, size);
+			size = 0;
+			break;
+		case _STAG_FIXEDIO:
+			if (size != 3)
+				goto __skip;
+			isapnp_add_fixed_port_resource(dev, depnum, size);
+			size = 0;
+			break;
+		case _STAG_VENDOR:
+			break;
+		case _LTAG_MEMRANGE:
+			if (size != 9)
+				goto __skip;
+			isapnp_add_mem_resource(dev, depnum, size);
+			size = 0;
+			break;
+		case _LTAG_ANSISTR:
+			isapnp_parse_name(dev->name, sizeof(dev->name), &size);
+			break;
+		case _LTAG_UNICODESTR:
+			/* silently ignore */
+			/* who use unicode for hardware identification? */
+			break;
+		case _LTAG_VENDOR:
+			break;
+		case _LTAG_MEM32RANGE:
+			if (size != 17)
+				goto __skip;
+			isapnp_add_mem32_resource(dev, depnum, size);
+			size = 0;
+			break;
+		case _LTAG_FIXEDMEM32RANGE:
+			if (size != 17)
+				goto __skip;
+			isapnp_add_fixed_mem32_resource(dev, depnum, size);
+			size = 0;
+			break;
+		case _STAG_END:
+			if (size > 0)
+				isapnp_skip_bytes(size);
+			isapnp_config_prepare(dev);
+			return 1;
+		default:
+			printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->number, card->number);
+		}
+	      __skip:
+	      	if (size > 0)
+		      	isapnp_skip_bytes(size);
+	}
+	isapnp_config_prepare(dev);
+	return 0;
+}
+
+/*
+ *  Parse resource map for ISA PnP card.
+ */
+ 
+static void __init isapnp_parse_resource_map(struct pnp_card *card)
+{
+	unsigned char type, tmp[17];
+	unsigned short size;
+
+	while (1) {
+		if (isapnp_read_tag(&type, &size)<0)
+			return;
+		switch (type) {
+		case _STAG_PNPVERNO:
+			if (size != 2)
+				goto __skip;
+			isapnp_peek(tmp, 2);
+			card->pnpver = tmp[0];
+			card->productver = tmp[1];
+			size = 0;
+			break;
+		case _STAG_LOGDEVID:
+			if (size >= 5 && size <= 6) {
+				if (isapnp_create_device(card, size)==1)
+					return;
+				size = 0;
+			}
+			break;
+		case _STAG_VENDOR:
+			break;
+		case _LTAG_ANSISTR:
+			isapnp_parse_name(card->name, sizeof(card->name), &size);
+			break;
+		case _LTAG_UNICODESTR:
+			/* silently ignore */
+			/* who use unicode for hardware identification? */
+			break;
+		case _LTAG_VENDOR:
+			break;
+		case _STAG_END:
+			if (size > 0)
+				isapnp_skip_bytes(size);
+			return;
+		default:
+			printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type, card->number);
+		}
+	      __skip:
+	      	if (size > 0)
+		      	isapnp_skip_bytes(size);
+	}
+}
+
+/*
+ *  Compute ISA PnP checksum for first eight bytes.
+ */
+
+static unsigned char __init isapnp_checksum(unsigned char *data)
+{
+	int i, j;
+	unsigned char checksum = 0x6a, bit, b;
+	
+	for (i = 0; i < 8; i++) {
+		b = data[i];
+		for (j = 0; j < 8; j++) {
+			bit = 0;
+			if (b & (1 << j))
+				bit = 1;
+			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
+		}
+	}
+	return checksum;
+}
+
+/*
+ *  Parse EISA id for ISA PnP card.
+ */
+
+static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device)
+{
+	struct pnp_id * id = isapnp_alloc(sizeof(struct pnp_id));
+	if (!id)
+		return;
+	sprintf(id->id, "%c%c%c%x%x%x%x",
+			'A' + ((vendor >> 2) & 0x3f) - 1,
+			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+			'A' + ((vendor >> 8) & 0x1f) - 1,
+			(device >> 4) & 0x0f,
+			device & 0x0f,
+			(device >> 12) & 0x0f,
+			(device >> 8) & 0x0f);
+	list_add_tail(&id->id_list,&card->ids);
+}
+
+/*
+ *  Build device list for all present ISA PnP devices.
+ */
+
+static int __init isapnp_build_device_list(void)
+{
+	int csn;
+	unsigned char header[9], checksum;
+	struct pnp_card *card;
+
+	isapnp_wait();
+	isapnp_key();
+	for (csn = 1; csn <= 10; csn++) {
+		isapnp_wake(csn);
+		isapnp_peek(header, 9);
+		checksum = isapnp_checksum(header);
+#if 0
+		printk(KERN_DEBUG "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			header[0], header[1], header[2], header[3],
+			header[4], header[5], header[6], header[7], header[8]);
+		printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
+#endif
+		/* Don't be strict on the checksum, here !
+                   e.g. 'SCM SwapBox Plug and Play' has header[8]==0 (should be: b7)*/
+		if (header[8] == 0)
+			;
+		else if (checksum == 0x00 || checksum != header[8])	/* not valid CSN */
+			continue;
+		if ((card = isapnp_alloc(sizeof(struct pci_bus))) == NULL)
+			continue;
+
+		card->number = csn;
+		INIT_LIST_HEAD(&card->devices);
+		INIT_LIST_HEAD(&card->ids);
+		isapnp_parse_card_id(card, (header[1] << 8) | header[0], (header[3] << 8) | header[2]);
+		card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
+		isapnp_checksum_value = 0x00;
+		isapnp_parse_resource_map(card);
+		if (isapnp_checksum_value != 0x00)
+			printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
+		card->checksum = isapnp_checksum_value;
+
+		list_add_tail(&card->node, &isapnp_cards);
+	}
+	return 0;
+}
+
+/*
+ *  Basic configuration routines.
+ */
+
+int isapnp_present(void)
+{
+	return !list_empty(&isapnp_devices);
+}
+
+int isapnp_cfg_begin(int csn, int logdev)
+{
+	if (csn < 1 || csn > 10 || logdev > 10)
+		return -EINVAL;
+	MOD_INC_USE_COUNT;
+	down(&isapnp_cfg_mutex);
+	isapnp_wait();
+	isapnp_key();
+	isapnp_wake(csn);
+#if 0
+	/* to avoid malfunction when the isapnptools package is used */
+	/* we must set RDP to our value again */
+	/* it is possible to set RDP only in the isolation phase */
+	/*   Jens Thoms Toerring <Jens.Toerring@physik.fu-berlin.de> */
+	isapnp_write_byte(0x02, 0x04);	/* clear CSN of card */
+	mdelay(2);			/* is this necessary? */
+	isapnp_wake(csn);		/* bring card into sleep state */
+	isapnp_wake(0);			/* bring card into isolation state */
+	isapnp_set_rdp();		/* reset the RDP port */
+	udelay(1000);			/* delay 1000us */
+	isapnp_write_byte(0x06, csn);	/* reset CSN to previous value */
+	udelay(250);			/* is this necessary? */
+#endif
+	if (logdev >= 0)
+		isapnp_device(logdev);
+	return 0;
+}
+
+int isapnp_cfg_end(void)
+{
+	isapnp_wait();
+	up(&isapnp_cfg_mutex);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int isapnp_config_prepare(struct pnp_dev *dev)
+{
+	int idx;
+	if (dev == NULL)
+		return -EINVAL;
+	if (dev->active || dev->ro)
+		return -EBUSY;
+	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
+		dev->irq_resource[idx].name = NULL;
+		dev->irq_resource[idx].start = -1;
+		dev->irq_resource[idx].end = -1;
+		dev->irq_resource[idx].flags = 0;
+	}
+	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
+		dev->dma_resource[idx].name = NULL;
+		dev->dma_resource[idx].start = -1;
+		dev->dma_resource[idx].end = -1;
+		dev->dma_resource[idx].flags = 0;
+	}
+	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
+		dev->resource[idx].name = NULL;
+		dev->resource[idx].start = 0;
+		dev->resource[idx].end = 0;
+		dev->resource[idx].flags = 0;
+	}
+	return 0;
+}
+
+void isapnp_resource_change(struct resource *resource,
+			    unsigned long start,
+			    unsigned long size)
+{
+	if (resource == NULL)
+		return;
+	resource->flags &= ~IORESOURCE_AUTO;
+	resource->start = start;
+	resource->end = start + size - 1;
+}
+
+/*
+ *  Inititialization.
+ */
+
+
+EXPORT_SYMBOL(isapnp_cards);
+EXPORT_SYMBOL(isapnp_devices);
+EXPORT_SYMBOL(isapnp_present);
+EXPORT_SYMBOL(isapnp_cfg_begin);
+EXPORT_SYMBOL(isapnp_cfg_end);
+EXPORT_SYMBOL(isapnp_read_byte);
+EXPORT_SYMBOL(isapnp_read_word);
+EXPORT_SYMBOL(isapnp_read_dword);
+EXPORT_SYMBOL(isapnp_write_byte);
+EXPORT_SYMBOL(isapnp_write_word);
+EXPORT_SYMBOL(isapnp_write_dword);
+EXPORT_SYMBOL(isapnp_wake);
+EXPORT_SYMBOL(isapnp_device);
+EXPORT_SYMBOL(isapnp_resource_change);
+
+static int isapnp_get_resources(struct pnp_dev *dev)
+{
+	/* We don't need to do anything but this, the rest is taken care of */
+	if ((dev->resource[0].start == 0) &&
+	    (dev->irq_resource[0].start == -1) &&
+	    (dev->dma_resource[0].start == -1))
+		dev->active = 0;
+	else
+		dev->active = 1;
+	return 0;
+}
+
+static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_cfg *cfg, char flags)
+{
+	int tmp;
+      	isapnp_cfg_begin(dev->card->number, dev->number);
+	dev->active = 1;
+	dev->irq_resource[0] = cfg->request.irq_resource[0];
+	dev->irq_resource[1] = cfg->request.irq_resource[1];
+	dev->dma_resource[0] = cfg->request.dma_resource[0];
+	dev->dma_resource[1] = cfg->request.dma_resource[1];
+	for (tmp = 0; tmp < 12; tmp++) {
+		dev->resource[tmp] = cfg->request.resource[tmp];
+	}
+	for (tmp = 0; tmp < 8 && dev->resource[tmp].flags; tmp++)
+		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start);
+	for (tmp = 0; tmp < 2 && dev->irq_resource[tmp].flags; tmp++) {
+		int irq = dev->irq_resource[tmp].start;
+		if (irq == 2)
+			irq = 9;
+		isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
+	}
+	for (tmp = 0; tmp < 2 && dev->dma_resource[tmp].flags; tmp++)
+		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma_resource[tmp].start);
+	for (tmp = 0; tmp < 4 && dev->resource[tmp+8].flags; tmp++)
+		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff);
+	isapnp_activate(dev->number);
+	isapnp_cfg_end();
+	return 0;
+}
+
+static int isapnp_disable_resources(struct pnp_dev *dev)
+{
+	if (!dev || !dev->active)
+		return -EINVAL;
+      	isapnp_cfg_begin(dev->card->number, dev->number);
+	isapnp_deactivate(dev->number);
+	dev->active = 0;
+	isapnp_cfg_end();
+	return 0;
+}
+
+struct pnp_protocol isapnp_protocol = {
+	name:	"ISA Plug and Play",
+	get:	isapnp_get_resources,
+	set:	isapnp_set_resources,
+	disable:isapnp_disable_resources,
+};
+
+static inline int isapnp_init_device_tree(void)
+{
+
+	struct pnp_card *card;
+
+	isapnp_for_each_card(card) {
+		struct list_head *devlist;
+		for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
+			struct pnp_dev *dev = card_to_pnp_dev(devlist);
+			snprintf(dev->dev.name, sizeof(dev->dev.name), "%s", dev->name);
+			dev->card = card;
+			dev->protocol = &isapnp_protocol;
+			pnp_add_device(dev);
+		}
+	}
+
+	return 0;
+}
+
+int __init isapnp_init(void)
+{
+	int cards;
+	struct pnp_card *card;
+
+	if (isapnp_disable) {
+		isapnp_detected = 0;
+		printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
+		return 0;
+	}
+#ifdef ISAPNP_REGION_OK
+	if (!request_region(_PIDXR, 1, "isapnp index")) {
+		printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR);
+		return -EBUSY;
+	}
+#endif
+	if (!request_region(_PNPWRP, 1, "isapnp write")) {
+		printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP);
+#ifdef ISAPNP_REGION_OK
+		release_region(_PIDXR, 1);
+#endif
+		return -EBUSY;
+	}
+
+	if(pnp_protocol_register(&isapnp_protocol)<0)
+		return -EBUSY;
+
+	/*
+	 *	Print a message. The existing ISAPnP code is hanging machines
+	 *	so let the user know where.
+	 */
+	 
+	printk(KERN_INFO "isapnp: Scanning for PnP cards...\n");
+	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {
+		isapnp_rdp |= 3;
+		if (!request_region(isapnp_rdp, 1, "isapnp read")) {
+			printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);
+#ifdef ISAPNP_REGION_OK
+			release_region(_PIDXR, 1);
+#endif
+			release_region(_PNPWRP, 1);
+			return -EBUSY;
+		}
+		isapnp_set_rdp();
+	}
+	isapnp_detected = 1;
+	if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) {
+		cards = isapnp_isolate();
+		if (cards < 0 || 
+		    (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {
+#ifdef ISAPNP_REGION_OK
+			release_region(_PIDXR, 1);
+#endif
+			release_region(_PNPWRP, 1);
+			isapnp_detected = 0;
+			printk(KERN_INFO "isapnp: No Plug & Play device found\n");
+			return 0;
+		}
+		request_region(isapnp_rdp, 1, "isapnp read");
+	}
+	isapnp_build_device_list();
+	cards = 0;
+
+	isapnp_for_each_card(card) {
+		cards++;
+		if (isapnp_verbose) {
+			struct list_head *devlist;
+			printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
+			if (isapnp_verbose < 2)
+				continue;
+			for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
+				struct pci_dev *dev = pci_dev_b(devlist);
+				printk(KERN_INFO "isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
+			}
+		}
+	}
+	if (cards) {
+		printk(KERN_INFO "isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":"");
+	} else {
+		printk(KERN_INFO "isapnp: No Plug & Play card found\n");
+	}
+
+	isapnp_init_device_tree();
+	isapnp_proc_init();
+	return 0;
+}
+
+subsys_initcall(isapnp_init);
+
+/* format is: noisapnp */
+
+static int __init isapnp_setup_disable(char *str)
+{
+	isapnp_disable = 1;
+	return 1;
+}
+
+__setup("noisapnp", isapnp_setup_disable);
+
+/* format is: isapnp=rdp,reset,skip_pci_scan,verbose */
+
+static int __init isapnp_setup_isapnp(char *str)
+{
+	(void)((get_option(&str,&isapnp_rdp) == 2) &&
+	       (get_option(&str,&isapnp_reset) == 2) &&
+	       (get_option(&str,&isapnp_skip_pci_scan) == 2) &&
+	       (get_option(&str,&isapnp_verbose) == 2));
+	return 1;
+}
+
+__setup("isapnp=", isapnp_setup_isapnp);
+
diff -Nru a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/isapnp/proc.c	Fri Oct 18 21:03:04 2002
@@ -0,0 +1,171 @@
+/*
+ *  ISA Plug & Play support
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ *   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.
+ *
+ */
+
+
+#include <linux/isapnp.h>
+#include <linux/pnp.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+
+
+static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
+
+static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
+{
+	loff_t new = -1;
+
+	lock_kernel();
+	switch (whence) {
+	case 0:
+		new = off;
+		break;
+	case 1:
+		new = file->f_pos + off;
+		break;
+	case 2:
+		new = 256 + off;
+		break;
+	}
+	if (new < 0 || new > 256) {
+		unlock_kernel();
+		return -EINVAL;
+	}
+	unlock_kernel();
+	return (file->f_pos = new);
+}
+
+static ssize_t isapnp_proc_bus_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+	struct inode *ino = file->f_dentry->d_inode;
+	struct proc_dir_entry *dp = PDE(ino);
+	struct pnp_dev *dev = dp->data;
+	int pos = *ppos;
+	int cnt, size = 256;
+
+	if (pos >= size)
+		return 0;
+	if (nbytes >= size)
+		nbytes = size;
+	if (pos + nbytes > size)
+		nbytes = size - pos;
+	cnt = nbytes;
+
+	if (!access_ok(VERIFY_WRITE, buf, cnt))
+		return -EINVAL;
+
+	isapnp_cfg_begin(dev->card->number, dev->number);
+	for ( ; pos < 256 && cnt > 0; pos++, buf++, cnt--) {
+		unsigned char val;
+		val = isapnp_read_byte(pos);
+		__put_user(val, buf);
+	}
+	isapnp_cfg_end();
+
+	*ppos = pos;
+	return nbytes;
+}
+
+static struct file_operations isapnp_proc_bus_file_operations =
+{
+	llseek:		isapnp_proc_bus_lseek,
+	read:		isapnp_proc_bus_read,
+};
+
+static int isapnp_proc_attach_device(struct pnp_dev *dev)
+{
+	struct pnp_card *bus = dev->card;
+	struct proc_dir_entry *de, *e;
+	char name[16];
+
+	if (!(de = bus->procdir)) {
+		sprintf(name, "%02x", bus->number);
+		de = bus->procdir = proc_mkdir(name, isapnp_proc_bus_dir);
+		if (!de)
+			return -ENOMEM;
+	}
+	sprintf(name, "%02x", dev->number);
+	e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO, de);
+	if (!e)
+		return -ENOMEM;
+	e->proc_fops = &isapnp_proc_bus_file_operations;
+	e->owner = THIS_MODULE;
+	e->data = dev;
+	e->size = 256;
+	return 0;
+}
+
+#ifdef MODULE
+static int __exit isapnp_proc_detach_device(struct pnp_dev *dev)
+{
+	struct pnp_card *bus = dev->card;
+	struct proc_dir_entry *de;
+	char name[16];
+
+	if (!(de = bus->procdir))
+		return -EINVAL;
+	sprintf(name, "%02x", dev->number);
+	remove_proc_entry(name, de);
+	return 0;
+}
+
+static int __exit isapnp_proc_detach_bus(struct pnp_card *bus)
+{
+	struct proc_dir_entry *de;
+	char name[16];
+
+	if (!(de = bus->procdir))
+		return -EINVAL;
+	sprintf(name, "%02x", bus->number);
+	remove_proc_entry(name, isapnp_proc_bus_dir);
+	return 0;
+}
+#endif /* MODULE */
+
+int __init isapnp_proc_init(void)
+{
+	struct pnp_dev *dev;
+	isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
+	isapnp_for_each_dev(dev) {
+		isapnp_proc_attach_device(dev);
+	}
+	return 0;
+}
+
+#ifdef MODULE
+int __exit isapnp_proc_done(void)
+{
+	struct pnp_dev *dev;
+	struct pnp_bus *card;
+
+	isapnp_for_each_dev(dev) {
+		isapnp_proc_detach_device(dev);
+	}
+	isapnp_for_each_card(card) {
+		isapnp_proc_detach_bus(card);
+	}
+	if (isapnp_proc_bus_dir)
+		remove_proc_entry("isapnp", proc_bus);
+	return 0;
+}
+#endif /* MODULE */
diff -Nru a/drivers/pnp/isapnp.c b/drivers/pnp/isapnp.c
--- a/drivers/pnp/isapnp.c	Fri Oct 18 21:03:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2514 +0,0 @@
-/*
- *  ISA Plug & Play support
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *
- *
- *   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.
- *
- *  Changelog:
- *  2000-01-01	Added quirks handling for buggy hardware
- *		Peter Denison <peterd@pnd-pc.demon.co.uk>
- *  2000-06-14	Added isapnp_probe_devs() and isapnp_activate_dev()
- *		Christoph Hellwig <hch@infradead.org>
- *  2001-06-03  Added release_region calls to correspond with
- *		request_region calls when a failure occurs.  Also
- *		added KERN_* constants to printk() calls.
- *  2001-11-07  Added isapnp_{,un}register_driver calls along the lines
- *              of the pci driver interface
- *              Kai Germaschewski <kai.germaschewski@gmx.de>
- *  2002-06-06  Made the use of dma channel 0 configurable 
- *              Gerald Teschl <gerald.teschl@univie.ac.at>
- */
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/irq.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/isapnp.h>
-
-LIST_HEAD(isapnp_cards);
-LIST_HEAD(isapnp_devices);
-
-#if 0
-#define ISAPNP_REGION_OK
-#endif
-#if 0
-#define ISAPNP_DEBUG
-#endif
-
-int isapnp_disable;			/* Disable ISA PnP */
-int isapnp_rdp;				/* Read Data Port */
-int isapnp_reset = 1;			/* reset all PnP cards (deactivate) */
-int isapnp_allow_dma0 = -1;		/* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */
-int isapnp_skip_pci_scan;		/* skip PCI resource scanning */
-int isapnp_verbose = 1;			/* verbose mode */
-int isapnp_reserve_irq[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some IRQ */
-int isapnp_reserve_dma[8] = { [0 ... 7] = -1 };		/* reserve (don't use) some DMA */
-int isapnp_reserve_io[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some I/O region */
-int isapnp_reserve_mem[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some memory region */
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Generic ISA Plug & Play support");
-MODULE_PARM(isapnp_disable, "i");
-MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");
-MODULE_PARM(isapnp_rdp, "i");
-MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
-MODULE_PARM(isapnp_reset, "i");
-MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
-MODULE_PARM(isapnp_allow_dma0, "i");
-MODULE_PARM_DESC(isapnp_allow_dma0, "Allow dma value 0 during auto activation");
-MODULE_PARM(isapnp_skip_pci_scan, "i");
-MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
-MODULE_PARM(isapnp_verbose, "i");
-MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
-MODULE_PARM(isapnp_reserve_irq, "1-16i");
-MODULE_PARM_DESC(isapnp_reserve_irq, "ISA Plug & Play - reserve IRQ line(s)");
-MODULE_PARM(isapnp_reserve_dma, "1-8i");
-MODULE_PARM_DESC(isapnp_reserve_dma, "ISA Plug & Play - reserve DMA channel(s)");
-MODULE_PARM(isapnp_reserve_io, "1-16i");
-MODULE_PARM_DESC(isapnp_reserve_io, "ISA Plug & Play - reserve I/O region(s) - port,size");
-MODULE_PARM(isapnp_reserve_mem, "1-16i");
-MODULE_PARM_DESC(isapnp_reserve_mem, "ISA Plug & Play - reserve memory region(s) - address,size");
-MODULE_LICENSE("GPL");
-
-#define _PIDXR		0x279
-#define _PNPWRP		0xa79
-
-/* short tags */
-#define _STAG_PNPVERNO		0x01
-#define _STAG_LOGDEVID		0x02
-#define _STAG_COMPATDEVID	0x03
-#define _STAG_IRQ		0x04
-#define _STAG_DMA		0x05
-#define _STAG_STARTDEP		0x06
-#define _STAG_ENDDEP		0x07
-#define _STAG_IOPORT		0x08
-#define _STAG_FIXEDIO		0x09
-#define _STAG_VENDOR		0x0e
-#define _STAG_END		0x0f
-/* long tags */
-#define _LTAG_MEMRANGE		0x81
-#define _LTAG_ANSISTR		0x82
-#define _LTAG_UNICODESTR	0x83
-#define _LTAG_VENDOR		0x84
-#define _LTAG_MEM32RANGE	0x85
-#define _LTAG_FIXEDMEM32RANGE	0x86
-
-static unsigned char isapnp_checksum_value;
-static DECLARE_MUTEX(isapnp_cfg_mutex);
-static int isapnp_detected;
-
-/* some prototypes */
-
-static int isapnp_config_prepare(struct pci_dev *dev);
-static int isapnp_config_activate(struct pci_dev *dev);
-static int isapnp_config_deactivate(struct pci_dev *dev);
-
-static inline void write_data(unsigned char x)
-{
-	outb(x, _PNPWRP);
-}
-
-static inline void write_address(unsigned char x)
-{
-	outb(x, _PIDXR);
-	udelay(20);
-}
-
-static inline unsigned char read_data(void)
-{
-	unsigned char val = inb(isapnp_rdp);
-	return val;
-}
-
-unsigned char isapnp_read_byte(unsigned char idx)
-{
-	write_address(idx);
-	return read_data();
-}
-
-unsigned short isapnp_read_word(unsigned char idx)
-{
-	unsigned short val;
-
-	val = isapnp_read_byte(idx);
-	val = (val << 8) + isapnp_read_byte(idx+1);
-	return val;
-}
-
-unsigned int isapnp_read_dword(unsigned char idx)
-{
-	unsigned int val;
-
-	val = isapnp_read_byte(idx);
-	val = (val << 8) + isapnp_read_byte(idx+1);
-	val = (val << 8) + isapnp_read_byte(idx+2);
-	val = (val << 8) + isapnp_read_byte(idx+3);
-	return val;
-}
-
-void isapnp_write_byte(unsigned char idx, unsigned char val)
-{
-	write_address(idx);
-	write_data(val);
-}
-
-void isapnp_write_word(unsigned char idx, unsigned short val)
-{
-	isapnp_write_byte(idx, val >> 8);
-	isapnp_write_byte(idx+1, val);
-}
-
-void isapnp_write_dword(unsigned char idx, unsigned int val)
-{
-	isapnp_write_byte(idx, val >> 24);
-	isapnp_write_byte(idx+1, val >> 16);
-	isapnp_write_byte(idx+2, val >> 8);
-	isapnp_write_byte(idx+3, val);
-}
-
-void *isapnp_alloc(long size)
-{
-	void *result;
-
-	result = kmalloc(size, GFP_KERNEL);
-	if (!result)
-		return NULL;
-	memset(result, 0, size);
-	return result;
-}
-
-static void isapnp_key(void)
-{
-	unsigned char code = 0x6a, msb;
-	int i;
-
-	mdelay(1);
-	write_address(0x00);
-	write_address(0x00);
-
-	write_address(code);
-
-	for (i = 1; i < 32; i++) {
-		msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
-		code = (code >> 1) | msb;
-		write_address(code);
-	}
-}
-
-/* place all pnp cards in wait-for-key state */
-static void isapnp_wait(void)
-{
-	isapnp_write_byte(0x02, 0x02);
-}
-
-void isapnp_wake(unsigned char csn)
-{
-	isapnp_write_byte(0x03, csn);
-}
-
-void isapnp_device(unsigned char logdev)
-{
-	isapnp_write_byte(0x07, logdev);
-}
-
-void isapnp_activate(unsigned char logdev)
-{
-	isapnp_device(logdev);
-	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1);
-	udelay(250);
-}
-
-void isapnp_deactivate(unsigned char logdev)
-{
-	isapnp_device(logdev);
-	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0);
-	udelay(500);
-}
-
-static void __init isapnp_peek(unsigned char *data, int bytes)
-{
-	int i, j;
-	unsigned char d=0;
-
-	for (i = 1; i <= bytes; i++) {
-		for (j = 0; j < 20; j++) {
-			d = isapnp_read_byte(0x05);
-			if (d & 1)
-				break;
-			udelay(100);
-		}
-		if (!(d & 1)) {
-			if (data != NULL)
-				*data++ = 0xff;
-			continue;
-		}
-		d = isapnp_read_byte(0x04);	/* PRESDI */
-		isapnp_checksum_value += d;
-		if (data != NULL)
-			*data++ = d;
-	}
-}
-
-#define RDP_STEP	32	/* minimum is 4 */
-
-static int isapnp_next_rdp(void)
-{
-	int rdp = isapnp_rdp;
-	while (rdp <= 0x3ff) {
-		/*
-		 *	We cannot use NE2000 probe spaces for ISAPnP or we
-		 *	will lock up machines.
-		 */
-		if ((rdp < 0x280 || rdp >  0x380) && !check_region(rdp, 1)) 
-		{
-			isapnp_rdp = rdp;
-			return 0;
-		}
-		rdp += RDP_STEP;
-	}
-	return -1;
-}
-
-/* Set read port address */
-static inline void isapnp_set_rdp(void)
-{
-	isapnp_write_byte(0x00, isapnp_rdp >> 2);
-	udelay(100);
-}
-
-/*
- *	Perform an isolation. The port selection code now tries to avoid
- *	"dangerous to read" ports.
- */
-
-static int __init isapnp_isolate_rdp_select(void)
-{
-	isapnp_wait();
-	isapnp_key();
-
-	/* Control: reset CSN and conditionally everything else too */
-	isapnp_write_byte(0x02, isapnp_reset ? 0x05 : 0x04);
-	mdelay(2);
-
-	isapnp_wait();
-	isapnp_key();
-	isapnp_wake(0x00);
-
-	if (isapnp_next_rdp() < 0) {
-		isapnp_wait();
-		return -1;
-	}
-
-	isapnp_set_rdp();
-	udelay(1000);
-	write_address(0x01);
-	udelay(1000);
-	return 0;
-}
-
-/*
- *  Isolate (assign uniqued CSN) to all ISA PnP devices.
- */
-
-static int __init isapnp_isolate(void)
-{
-	unsigned char checksum = 0x6a;
-	unsigned char chksum = 0x00;
-	unsigned char bit = 0x00;
-	int data;
-	int csn = 0;
-	int i;
-	int iteration = 1;
-
-	isapnp_rdp = 0x213;
-	if (isapnp_isolate_rdp_select() < 0)
-		return -1;
-
-	while (1) {
-		for (i = 1; i <= 64; i++) {
-			data = read_data() << 8;
-			udelay(250);
-			data = data | read_data();
-			udelay(250);
-			if (data == 0x55aa)
-				bit = 0x01;
-			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
-			bit = 0x00;
-		}
-		for (i = 65; i <= 72; i++) {
-			data = read_data() << 8;
-			udelay(250);
-			data = data | read_data();
-			udelay(250);
-			if (data == 0x55aa)
-				chksum |= (1 << (i - 65));
-		}
-		if (checksum != 0x00 && checksum == chksum) {
-			csn++;
-
-			isapnp_write_byte(0x06, csn);
-			udelay(250);
-			iteration++;
-			isapnp_wake(0x00);
-			isapnp_set_rdp();
-			udelay(1000);
-			write_address(0x01);
-			udelay(1000);
-			goto __next;
-		}
-		if (iteration == 1) {
-			isapnp_rdp += RDP_STEP;
-			if (isapnp_isolate_rdp_select() < 0)
-				return -1;
-		} else if (iteration > 1) {
-			break;
-		}
-	      __next:
-		checksum = 0x6a;
-		chksum = 0x00;
-		bit = 0x00;
-	}
-	isapnp_wait();
-	return csn;
-}
-
-/*
- *  Read one tag from stream.
- */
-
-static int __init isapnp_read_tag(unsigned char *type, unsigned short *size)
-{
-	unsigned char tag, tmp[2];
-
-	isapnp_peek(&tag, 1);
-	if (tag == 0)				/* invalid tag */
-		return -1;
-	if (tag & 0x80) {	/* large item */
-		*type = tag;
-		isapnp_peek(tmp, 2);
-		*size = (tmp[1] << 8) | tmp[0];
-	} else {
-		*type = (tag >> 3) & 0x0f;
-		*size = tag & 0x07;
-	}
-#if 0
-	printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
-#endif
-	if (type == 0)				/* wrong type */
-		return -1;
-	if (*type == 0xff && *size == 0xffff)	/* probably invalid data */
-		return -1;
-	return 0;
-}
-
-/*
- *  Skip specified number of bytes from stream.
- */
- 
-static void __init isapnp_skip_bytes(int count)
-{
-	isapnp_peek(NULL, count);
-}
-
-/*
- *  Parse logical device tag.
- */
-
-static struct pci_dev * __init isapnp_parse_device(struct pci_bus *card, int size, int number)
-{
-	unsigned char tmp[6];
-	struct pci_dev *dev;
-
-	isapnp_peek(tmp, size);
-	dev = isapnp_alloc(sizeof(struct pci_dev));
-	if (!dev)
-		return NULL;
-	dev->dma_mask = 0x00ffffff;
-	dev->devfn = number;
-	dev->vendor = (tmp[1] << 8) | tmp[0];
-	dev->device = (tmp[3] << 8) | tmp[2];
-	dev->regs = tmp[4];
-	dev->bus = card;
-	if (size > 5)
-		dev->regs |= tmp[5] << 8;
-	dev->prepare = isapnp_config_prepare;
-	dev->activate = isapnp_config_activate;
-	dev->deactivate = isapnp_config_deactivate;
-	return dev;
-}
-
-/*
- *  Build new resources structure
- */
-
-static struct isapnp_resources * __init isapnp_build_resources(struct pci_dev *dev, int dependent)
-{
-	struct isapnp_resources *res, *ptr, *ptra;
-	
-	res = isapnp_alloc(sizeof(struct isapnp_resources));
-	if (!res)
-		return NULL;
-	res->dev = dev;
-	ptr = (struct isapnp_resources *)dev->sysdata;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr && ptr->dependent && dependent) { /* add to another list */
-		ptra = ptr->alt;
-		while (ptra && ptra->alt)
-			ptra = ptra->alt;
-		if (!ptra)
-			ptr->alt = res;
-		else
-			ptra->alt = res;
-	} else {
-		if (!ptr)
-			dev->sysdata = res;
-		else
-			ptr->next = res;
-	}
-	if (dependent) {
-		res->priority = dependent & 0xff;
-		if (res->priority > ISAPNP_RES_PRIORITY_FUNCTIONAL)
-			res->priority = ISAPNP_RES_PRIORITY_INVALID;
-		res->dependent = 1;
-	} else {
-		res->priority = ISAPNP_RES_PRIORITY_PREFERRED;
-		res->dependent = 0;
-	}
-	return res;
-}
-
-/*
- *  Add IRQ resource to resources list.
- */
-
-static void __init isapnp_add_irq_resource(struct pci_dev *dev,
-                                    	       struct isapnp_resources **res,
-                                               int dependent, int size)
-{
-	unsigned char tmp[3];
-	int i;
-	struct isapnp_irq *irq, *ptr;
-
-	isapnp_peek(tmp, size);
-	irq = isapnp_alloc(sizeof(struct isapnp_irq));
-	if (!irq)
-		return;
-	if (*res == NULL) {
-		*res = isapnp_build_resources(dev, dependent);
-		if (*res == NULL) {
-			kfree(irq);
-			return;
-		}
-	}
-	irq->map = (tmp[1] << 8) | tmp[0];
-	if (size > 2)
-		irq->flags = tmp[2];
-	else
-		irq->flags = IORESOURCE_IRQ_HIGHEDGE;
-	irq->res = *res;
-	ptr = (*res)->irq;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = irq;
-	else
-		(*res)->irq = irq;
-#ifdef CONFIG_PCI
-	for (i=0; i<16; i++)
-		if (irq->map & (1<<i))
-			pcibios_penalize_isa_irq(i);
-#endif
-}
-
-/*
- *  Add DMA resource to resources list.
- */
-
-static void __init isapnp_add_dma_resource(struct pci_dev *dev,
-                                    	       struct isapnp_resources **res,
-                                    	       int dependent, int size)
-{
-	unsigned char tmp[2];
-	struct isapnp_dma *dma, *ptr;
-
-	isapnp_peek(tmp, size);
-	dma = isapnp_alloc(sizeof(struct isapnp_dma));
-	if (!dma)
-		return;
-	if (*res == NULL) {
-		*res = isapnp_build_resources(dev, dependent);
-		if (*res == NULL) {
-			kfree(dma);
-			return;
-		}
-	}
-	dma->map = tmp[0];
-	dma->flags = tmp[1];
-	dma->res = *res;
-	ptr = (*res)->dma;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = dma;
-	else
-		(*res)->dma = dma;
-}
-
-/*
- *  Add port resource to resources list.
- */
-
-static void __init isapnp_add_port_resource(struct pci_dev *dev,
-						struct isapnp_resources **res,
-						int dependent, int size)
-{
-	unsigned char tmp[7];
-	struct isapnp_port *port, *ptr;
-
-	isapnp_peek(tmp, size);
-	port = isapnp_alloc(sizeof(struct isapnp_port));
-	if (!port)
-		return;
-	if (*res == NULL) {
-		*res = isapnp_build_resources(dev, dependent);
-		if (*res == NULL) {
-			kfree(port);
-			return;
-		}
-	}
-	port->min = (tmp[2] << 8) | tmp[1];
-	port->max = (tmp[4] << 8) | tmp[3];
-	port->align = tmp[5];
-	port->size = tmp[6];
-	port->flags = tmp[0] ? ISAPNP_PORT_FLAG_16BITADDR : 0;
-	port->res = *res;
-	ptr = (*res)->port;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = port;
-	else
-		(*res)->port = port;
-}
-
-/*
- *  Add fixed port resource to resources list.
- */
-
-static void __init isapnp_add_fixed_port_resource(struct pci_dev *dev,
-						      struct isapnp_resources **res,
-						      int dependent, int size)
-{
-	unsigned char tmp[3];
-	struct isapnp_port *port, *ptr;
-
-	isapnp_peek(tmp, size);
-	port = isapnp_alloc(sizeof(struct isapnp_port));
-	if (!port)
-		return;
-	if (*res == NULL) {
-		*res = isapnp_build_resources(dev, dependent);
-		if (*res == NULL) {
-			kfree(port);
-			return;
-		}
-	}
-	port->min = port->max = (tmp[1] << 8) | tmp[0];
-	port->size = tmp[2];
-	port->align = 0;
-	port->flags = ISAPNP_PORT_FLAG_FIXED;
-	port->res = *res;
-	ptr = (*res)->port;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = port;
-	else
-		(*res)->port = port;
-}
-
-/*
- *  Add memory resource to resources list.
- */
-
-static void __init isapnp_add_mem_resource(struct pci_dev *dev,
-					       struct isapnp_resources **res,
-					       int dependent, int size)
-{
-	unsigned char tmp[9];
-	struct isapnp_mem *mem, *ptr;
-
-	isapnp_peek(tmp, size);
-	mem = isapnp_alloc(sizeof(struct isapnp_mem));
-	if (!mem)
-		return;
-	if (*res == NULL) {
-		*res = isapnp_build_resources(dev, dependent);
-		if (*res == NULL) {
-			kfree(mem);
-			return;
-		}
-	}
-	mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
-	mem->max = ((tmp[4] << 8) | tmp[3]) << 8;
-	mem->align = (tmp[6] << 8) | tmp[5];
-	mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
-	mem->flags = tmp[0];
-	mem->res = *res;
-	ptr = (*res)->mem;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = mem;
-	else
-		(*res)->mem = mem;
-}
-
-/*
- *  Add 32-bit memory resource to resources list.
- */
-
-static void __init isapnp_add_mem32_resource(struct pci_dev *dev,
-						 struct isapnp_resources **res,
-						 int dependent, int size)
-{
-	unsigned char tmp[17];
-	struct isapnp_mem32 *mem32, *ptr;
-
-	isapnp_peek(tmp, size);
-	mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
-	if (!mem32)
-		return;
-	if (*res == NULL) {
-		*res = isapnp_build_resources(dev, dependent);
-		if (*res == NULL) {
-			kfree(mem32);
-			return;
-		}
-	}
-	memcpy(mem32->data, tmp, 17);
-	mem32->res = *res;
-	ptr = (*res)->mem32;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = mem32;
-	else
-		(*res)->mem32 = mem32;
-}
-
-/*
- *  Add 32-bit fixed memory resource to resources list.
- */
-
-static void __init isapnp_add_fixed_mem32_resource(struct pci_dev *dev,
-						       struct isapnp_resources **res,
-						       int dependent, int size)
-{
-	unsigned char tmp[17];
-	struct isapnp_mem32 *mem32, *ptr;
-
-	isapnp_peek(tmp, size);
-	mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
-	if (!mem32)
-		return;
-	if (*res == NULL) {
-		*res = isapnp_build_resources(dev, dependent);
-		if (*res == NULL) {
-			kfree(mem32);
-			return;
-		}
-	}
-	memcpy(mem32->data, tmp, 17);
-	mem32->res = *res;
-	ptr = (*res)->mem32;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = mem32;
-	else
-		(*res)->mem32 = mem32;
-}
-
-/*
- *  Parse card name for ISA PnP device.
- */ 
- 
-static void __init 
-isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
-{
-	if (name[0] == '\0') {
-		unsigned short size1 = *size >= name_max ? (name_max - 1) : *size;
-		isapnp_peek(name, size1);
-		name[size1] = '\0';
-		*size -= size1;
-		
-		/* clean whitespace from end of string */
-		while (size1 > 0  &&  name[--size1] == ' ') 
-			name[size1] = '\0';
-	}	
-}
-
-/*
- *  Parse resource map for logical device.
- */
-
-static int __init isapnp_create_device(struct pci_bus *card,
-					   unsigned short size)
-{
-	int number = 0, skip = 0, dependent = 0, compat = 0;
-	unsigned char type, tmp[17];
-	struct pci_dev *dev;
-	struct isapnp_resources *res = NULL;
-	
-	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
-		return 1;
-	list_add(&dev->bus_list, &card->devices);
-	list_add_tail(&dev->global_list, &isapnp_devices);
-	while (1) {
-		if (isapnp_read_tag(&type, &size)<0)
-			return 1;
-		if (skip && type != _STAG_LOGDEVID && type != _STAG_END)
-			goto __skip;
-		switch (type) {
-		case _STAG_LOGDEVID:
-			if (size >= 5 && size <= 6) {
-				isapnp_config_prepare(dev);
-				if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
-					return 1;
-				list_add_tail(&dev->bus_list, &card->devices);
-				list_add_tail(&dev->global_list, &isapnp_devices);
-				size = 0;
-				skip = 0;
-			} else {
-				skip = 1;
-			}
-			res = NULL;
-			dependent = 0;
-			compat = 0;
-			break;
-		case _STAG_COMPATDEVID:
-			if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
-				isapnp_peek(tmp, 4);
-				dev->vendor_compatible[compat] = (tmp[1] << 8) | tmp[0];
-				dev->device_compatible[compat] = (tmp[3] << 8) | tmp[2];
-				compat++;
-				size = 0;
-			}
-			break;
-		case _STAG_IRQ:
-			if (size < 2 || size > 3)
-				goto __skip;
-			isapnp_add_irq_resource(dev, &res, dependent, size);
-			size = 0;
-			break;
-		case _STAG_DMA:
-			if (size != 2)
-				goto __skip;
-			isapnp_add_dma_resource(dev, &res, dependent, size);
-			size = 0;
-			break;
-		case _STAG_STARTDEP:
-			if (size > 1)
-				goto __skip;
-			res = NULL;
-			dependent = 0x100 | ISAPNP_RES_PRIORITY_ACCEPTABLE;
-			if (size > 0) {
-				isapnp_peek(tmp, size);
-				dependent = 0x100 | tmp[0];
-				size = 0;
-			}
-			break;
-		case _STAG_ENDDEP:
-			if (size != 0)
-				goto __skip;
-			res = NULL;
-			dependent = 0;
-			break;
-		case _STAG_IOPORT:
-			if (size != 7)
-				goto __skip;
-			isapnp_add_port_resource(dev, &res, dependent, size);
-			size = 0;
-			break;
-		case _STAG_FIXEDIO:
-			if (size != 3)
-				goto __skip;
-			isapnp_add_fixed_port_resource(dev, &res, dependent, size);
-			size = 0;
-			break;
-		case _STAG_VENDOR:
-			break;
-		case _LTAG_MEMRANGE:
-			if (size != 9)
-				goto __skip;
-			isapnp_add_mem_resource(dev, &res, dependent, size);
-			size = 0;
-			break;
-		case _LTAG_ANSISTR:
-			isapnp_parse_name(dev->name, sizeof(dev->name), &size);
-			break;
-		case _LTAG_UNICODESTR:
-			/* silently ignore */
-			/* who use unicode for hardware identification? */
-			break;
-		case _LTAG_VENDOR:
-			break;
-		case _LTAG_MEM32RANGE:
-			if (size != 17)
-				goto __skip;
-			isapnp_add_mem32_resource(dev, &res, dependent, size);
-			size = 0;
-			break;
-		case _LTAG_FIXEDMEM32RANGE:
-			if (size != 17)
-				goto __skip;
-			isapnp_add_fixed_mem32_resource(dev, &res, dependent, size);
-			size = 0;
-			break;
-		case _STAG_END:
-			if (size > 0)
-				isapnp_skip_bytes(size);
-			isapnp_config_prepare(dev);
-			return 1;
-		default:
-			printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->devfn, card->number);
-		}
-	      __skip:
-	      	if (size > 0)
-		      	isapnp_skip_bytes(size);
-	}
-	isapnp_config_prepare(dev);
-	return 0;
-}
-
-/*
- *  Parse resource map for ISA PnP card.
- */
- 
-static void __init isapnp_parse_resource_map(struct pci_bus *card)
-{
-	unsigned char type, tmp[17];
-	unsigned short size;
-	
-	while (1) {
-		if (isapnp_read_tag(&type, &size)<0)
-			return;
-		switch (type) {
-		case _STAG_PNPVERNO:
-			if (size != 2)
-				goto __skip;
-			isapnp_peek(tmp, 2);
-			card->pnpver = tmp[0];
-			card->productver = tmp[1];
-			size = 0;
-			break;
-		case _STAG_LOGDEVID:
-			if (size >= 5 && size <= 6) {
-				if (isapnp_create_device(card, size)==1)
-					return;
-				size = 0;
-			}
-			break;
-		case _STAG_VENDOR:
-			break;
-		case _LTAG_ANSISTR:
-			isapnp_parse_name(card->name, sizeof(card->name), &size);
-			break;
-		case _LTAG_UNICODESTR:
-			/* silently ignore */
-			/* who use unicode for hardware identification? */
-			break;
-		case _LTAG_VENDOR:
-			break;
-		case _STAG_END:
-			if (size > 0)
-				isapnp_skip_bytes(size);
-			return;
-		default:
-			printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type, card->number);
-		}
-	      __skip:
-	      	if (size > 0)
-		      	isapnp_skip_bytes(size);
-	}
-}
-
-/*
- *  Compute ISA PnP checksum for first eight bytes.
- */
-
-static unsigned char __init isapnp_checksum(unsigned char *data)
-{
-	int i, j;
-	unsigned char checksum = 0x6a, bit, b;
-	
-	for (i = 0; i < 8; i++) {
-		b = data[i];
-		for (j = 0; j < 8; j++) {
-			bit = 0;
-			if (b & (1 << j))
-				bit = 1;
-			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
-		}
-	}
-	return checksum;
-}
-
-/*
- *  Build device list for all present ISA PnP devices.
- */
-
-static int __init isapnp_build_device_list(void)
-{
-	int csn;
-	unsigned char header[9], checksum;
-	struct pci_bus *card;
-	struct pci_dev *dev;
-
-	isapnp_wait();
-	isapnp_key();
-	for (csn = 1; csn <= 10; csn++) {
-		isapnp_wake(csn);
-		isapnp_peek(header, 9);
-		checksum = isapnp_checksum(header);
-#if 0
-		printk(KERN_DEBUG "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
-			header[0], header[1], header[2], header[3],
-			header[4], header[5], header[6], header[7], header[8]);
-		printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
-#endif
-		/* Don't be strict on the checksum, here !
-                   e.g. 'SCM SwapBox Plug and Play' has header[8]==0 (should be: b7)*/
-		if (header[8] == 0)
-			;
-		else if (checksum == 0x00 || checksum != header[8])	/* not valid CSN */
-			continue;
-		if ((card = isapnp_alloc(sizeof(struct pci_bus))) == NULL)
-			continue;
-
-		card->number = csn;
-		card->vendor = (header[1] << 8) | header[0];
-		card->device = (header[3] << 8) | header[2];
-		card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
-		isapnp_checksum_value = 0x00;
-		INIT_LIST_HEAD(&card->children);
-		INIT_LIST_HEAD(&card->devices);
-		isapnp_parse_resource_map(card);
-		if (isapnp_checksum_value != 0x00)
-			printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
-		card->checksum = isapnp_checksum_value;
-
-		list_add_tail(&card->node, &isapnp_cards);
-	}
-	isapnp_for_each_dev(dev) {
-		isapnp_fixup_device(dev);
-	}
-	return 0;
-}
-
-/*
- *  Basic configuration routines.
- */
-
-int isapnp_present(void)
-{
-	return !list_empty(&isapnp_devices);
-}
-
-int isapnp_cfg_begin(int csn, int logdev)
-{
-	if (csn < 1 || csn > 10 || logdev > 10)
-		return -EINVAL;
-	MOD_INC_USE_COUNT;
-	down(&isapnp_cfg_mutex);
-	isapnp_wait();
-	isapnp_key();
-	isapnp_wake(csn);
-#if 0
-	/* to avoid malfunction when the isapnptools package is used */
-	/* we must set RDP to our value again */
-	/* it is possible to set RDP only in the isolation phase */ 
-	/*   Jens Thoms Toerring <Jens.Toerring@physik.fu-berlin.de> */
-	isapnp_write_byte(0x02, 0x04);	/* clear CSN of card */
-	mdelay(2);			/* is this necessary? */
-	isapnp_wake(csn);		/* bring card into sleep state */
-	isapnp_wake(0);			/* bring card into isolation state */
-	isapnp_set_rdp();		/* reset the RDP port */
-	udelay(1000);			/* delay 1000us */
-	isapnp_write_byte(0x06, csn);	/* reset CSN to previous value */
-	udelay(250);			/* is this necessary? */
-#endif
-	if (logdev >= 0)
-		isapnp_device(logdev);
-	return 0;
-}
-
-int isapnp_cfg_end(void)
-{
-	isapnp_wait();
-	up(&isapnp_cfg_mutex);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-/*
- *  Resource manager.
- */
-
-static struct isapnp_port *isapnp_find_port(struct pci_dev *dev, int index)
-{
-	struct isapnp_resources *res;
-	struct isapnp_port *port;
-	
-	if (!dev || index < 0 || index > 7)
-		return NULL;
-	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
-		for (port = res->port; port; port = port->next) {
-			if (!index)
-				return port;
-			index--;
-		}
-	}
-	return NULL;
-}
-
-struct isapnp_irq *isapnp_find_irq(struct pci_dev *dev, int index)
-{
-	struct isapnp_resources *res, *resa;
-	struct isapnp_irq *irq;
-	int index1, index2, index3;
-	
-	if (!dev || index < 0 || index > 7)
-		return NULL;
-	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
-		index3 = 0;
-		for (resa = res; resa; resa = resa->alt) {
-			index1 = index;
-			index2 = 0;
-			for (irq = resa->irq; irq; irq = irq->next) {
-				if (!index1)
-					return irq;
-				index1--;
-				index2++;
-			}
-			if (index3 < index2)
-				index3 = index2;
-		}
-		index -= index3;
-	}
-	return NULL;
-}
-
-struct isapnp_dma *isapnp_find_dma(struct pci_dev *dev, int index)
-{
-	struct isapnp_resources *res;
-	struct isapnp_dma *dma;
-	
-	if (!dev || index < 0 || index > 7)
-		return NULL;
-	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
-		for (dma = res->dma; dma; dma = dma->next) {
-			if (!index)
-				return dma;
-			index--;
-		}
-	}
-	return NULL;
-}
-
-struct isapnp_mem *isapnp_find_mem(struct pci_dev *dev, int index)
-{
-	struct isapnp_resources *res;
-	struct isapnp_mem *mem;
-	
-	if (!dev || index < 0 || index > 7)
-		return NULL;
-	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
-		for (mem = res->mem; mem; mem = mem->next) {
-			if (!index)
-				return mem;
-			index--;
-		}
-	}
-	return NULL;
-}
-
-struct isapnp_mem32 *isapnp_find_mem32(struct pci_dev *dev, int index)
-{
-	struct isapnp_resources *res;
-	struct isapnp_mem32 *mem32;
-	
-	if (!dev || index < 0 || index > 7)
-		return NULL;
-	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
-		for (mem32 = res->mem32; mem32; mem32 = mem32->next) {
-			if (!index)
-				return mem32;
-			index--;
-		}
-	}
-	return NULL;
-}
-
-/*
- *  Device manager.
- */
-
-struct pci_bus *isapnp_find_card(unsigned short vendor,
-				 unsigned short device,
-				 struct pci_bus *from)
-{
-	struct list_head *list;
-
-	list = isapnp_cards.next;
-	if (from)
-		list = from->node.next;
-
-	while (list != &isapnp_cards) {
-		struct pci_bus *card = pci_bus_b(list);
-		if (card->vendor == vendor && card->device == device)
-			return card;
-		list = list->next;
-	}
-	return NULL;
-}
-
-struct pci_dev *isapnp_find_dev(struct pci_bus *card,
-				unsigned short vendor,
-				unsigned short function,
-				struct pci_dev *from)
-{
-	if (card == NULL) {	/* look for a logical device from all cards */
-		struct list_head *list;
-
-		list = isapnp_devices.next;
-		if (from)
-			list = from->global_list.next;
-
-		while (list != &isapnp_devices) {
-			int idx;
-			struct pci_dev *dev = pci_dev_g(list);
-
-			if (dev->vendor == vendor && dev->device == function)
-				return dev;
-			for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
-				if (dev->vendor_compatible[idx] == vendor &&
-				    dev->device_compatible[idx] == function)
-					return dev;
-			list = list->next;
-		}
-	} else {
-		struct list_head *list;
-
-		list = card->devices.next;
-		if (from) {
-			list = from->bus_list.next;
-			if (from->bus != card)	/* something is wrong */
-				return NULL;
-		}
-		while (list != &card->devices) {
-			int idx;
-			struct pci_dev *dev = pci_dev_b(list);
-
-			if (dev->vendor == vendor && dev->device == function)
-				return dev;
-			for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
-				if (dev->vendor_compatible[idx] == vendor &&
-				    dev->device_compatible[idx] == function)
-					return dev;
-			list = list->next;
-		}
-	}
-	return NULL;
-}
-
-static const struct isapnp_card_id *
-isapnp_match_card(const struct isapnp_card_id *ids, struct pci_bus *card)
-{
-	int idx;
-
-	while (ids->card_vendor || ids->card_device) {
-		if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == card->vendor) &&
-		    (ids->card_device == ISAPNP_ANY_ID || ids->card_device == card->device)) {
-			for (idx = 0; idx < ISAPNP_CARD_DEVS; idx++) {
-				if (ids->devs[idx].vendor == 0 &&
-				    ids->devs[idx].function == 0)
-					return ids;
-				if (isapnp_find_dev(card,
-						    ids->devs[idx].vendor,
-						    ids->devs[idx].function,
-						    NULL) == NULL)
-					goto __next;
-			}
-			return ids;
-		}
-	      __next:
-		ids++;
-	}
-	return NULL;
-}
-
-int isapnp_probe_cards(const struct isapnp_card_id *ids,
-		       int (*probe)(struct pci_bus *_card,
-		       		    const struct isapnp_card_id *_id))
-{
-	struct pci_bus *card;	
-	const struct isapnp_card_id *id;
-	int count = 0;
-
-	if (ids == NULL || probe == NULL)
-		return -EINVAL;
-	isapnp_for_each_card(card) {
-		id = isapnp_match_card(ids, card);
-		if (id != NULL && probe(card, id) >= 0)
-			count++;
-	}
-	return count;
-}
-
-static const struct isapnp_device_id *
-isapnp_match_dev(const struct isapnp_device_id *ids, struct pci_dev *dev)
-{
-	while (ids->card_vendor || ids->card_device) {
-		if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == dev->bus->vendor) &&
-		    (ids->card_device == ISAPNP_ANY_ID || ids->card_device == dev->bus->device) &&
-                    (ids->vendor == ISAPNP_ANY_ID || ids->vendor == dev->vendor) &&
-                    (ids->function == ISAPNP_ANY_ID || ids->function == dev->device))
-			return ids;
-		ids++;
-	}
-	return NULL;
-}
-
-int isapnp_probe_devs(const struct isapnp_device_id *ids,
-		      int (*probe)(struct pci_dev *dev,
-		                   const struct isapnp_device_id *id))
-{
-	
-	struct pci_dev *dev;
-	const struct isapnp_device_id *id;
-	int count = 0;
-
-	if (ids == NULL || probe == NULL)
-		return -EINVAL;
-	isapnp_for_each_dev(dev) {
-		id = isapnp_match_dev(ids, dev);
-		if (id != NULL && probe(dev, id) >= 0)
-			count++;
-	}
-	return count;
-}
-
-int isapnp_activate_dev(struct pci_dev *dev, const char *name)
-{
-	int err;
-	
-	/* Device already active? Let's use it and inform the caller */
-	if (dev->active)
-		return -EBUSY;
-
-	if ((err = dev->activate(dev)) < 0) {
-		printk(KERN_ERR "isapnp: config of %s failed (out of resources?)[%d]\n", name, err);
-		dev->deactivate(dev);
-		return err;
-	}
-
-	return 0;
-}
-
-static unsigned int isapnp_dma_resource_flags(struct isapnp_dma *dma)
-{
-	return dma->flags | IORESOURCE_DMA | IORESOURCE_AUTO;
-}
-
-static unsigned int isapnp_mem_resource_flags(struct isapnp_mem *mem)
-{
-	unsigned int result;
-
-	result = mem->flags | IORESOURCE_MEM | IORESOURCE_AUTO;
-	if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))
-		result |= IORESOURCE_READONLY;
-	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
-		result |= IORESOURCE_CACHEABLE;
-	if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
-		result |= IORESOURCE_RANGELENGTH;
-	if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
-		result |= IORESOURCE_SHADOWABLE;
-	return result;
-}
-
-static unsigned int isapnp_irq_resource_flags(struct isapnp_irq *irq)
-{
-	return irq->flags | IORESOURCE_IRQ | IORESOURCE_AUTO;
-}
-
-static unsigned int isapnp_port_resource_flags(struct isapnp_port *port)
-{
-	return port->flags | IORESOURCE_IO | IORESOURCE_AUTO;
-}
-
-static int isapnp_config_prepare(struct pci_dev *dev)
-{
-	struct isapnp_resources *res, *resa;
-	struct isapnp_port *port;
-	struct isapnp_irq *irq;
-	struct isapnp_dma *dma;
-	struct isapnp_mem *mem;
-	int port_count, port_count1;
-	int irq_count, irq_count1;
-	int dma_count, dma_count1;
-	int mem_count, mem_count1;
-	int idx;
-
-	if (dev == NULL)
-		return -EINVAL;
-	if (dev->active || dev->ro)
-		return -EBUSY;
-	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
-		dev->irq_resource[idx].name = NULL;
-		dev->irq_resource[idx].start = 0;
-		dev->irq_resource[idx].end = 0;
-		dev->irq_resource[idx].flags = 0;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
-		dev->dma_resource[idx].name = NULL;
-		dev->dma_resource[idx].start = 0;
-		dev->dma_resource[idx].end = 0;
-		dev->dma_resource[idx].flags = 0;
-	}
-	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
-		dev->resource[idx].name = NULL;
-		dev->resource[idx].start = 0;
-		dev->resource[idx].end = 0;
-		dev->resource[idx].flags = 0;
-	}
-	port_count = irq_count = dma_count = mem_count = 0;
-	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
-		port_count1 = irq_count1 = dma_count1 = mem_count1 = 0;
-		for (resa = res; resa; resa = resa->alt) {
-			for (port = resa->port, idx = 0; port; port = port->next, idx++) {
-				if (dev->resource[port_count + idx].flags == 0) {
-					dev->resource[port_count + idx].flags = isapnp_port_resource_flags(port);
-					dev->resource[port_count + idx].end = port->size;
-				}
-			}
-			if (port_count1 < idx)
-				port_count1 = idx;
-			for (irq = resa->irq, idx = 0; irq; irq = irq->next, idx++) {
-				int count = irq_count + idx;
-				if (count < DEVICE_COUNT_IRQ) {
-					if (dev->irq_resource[count].flags == 0) {
-						dev->irq_resource[count].flags = isapnp_irq_resource_flags(irq);
-					}
-				}
-				
-			}
-			if (irq_count1 < idx)
-				irq_count1 = idx;
-			for (dma = resa->dma, idx = 0; dma; dma = dma->next, idx++)
-				if (dev->dma_resource[idx].flags == 0) {
-					dev->dma_resource[idx].flags = isapnp_dma_resource_flags(dma);
-				}
-			if (dma_count1 < idx)
-				dma_count1 = idx;
-			for (mem = resa->mem, idx = 0; mem; mem = mem->next, idx++)
-				if (dev->resource[mem_count + idx + 8].flags == 0) {
-					dev->resource[mem_count + idx + 8].flags = isapnp_mem_resource_flags(mem);
-				}
-			if (mem_count1 < idx)
-				mem_count1 = idx;
-		}
-		port_count += port_count1;
-		irq_count += irq_count1;
-		dma_count += dma_count1;
-		mem_count += mem_count1;
-	}
-	return 0;
-}
-
-struct isapnp_cfgtmp {
-	struct isapnp_port *port[8];
-	struct isapnp_irq *irq[2];
-	struct isapnp_dma *dma[2];
-	struct isapnp_mem *mem[4];
-	struct pci_dev *request;
-	struct pci_dev result;
-};
-
-static int isapnp_alternative_switch(struct isapnp_cfgtmp *cfg,
-				     struct isapnp_resources *from,
-				     struct isapnp_resources *to)
-{
-	int tmp, tmp1;
-	struct isapnp_port *port;
-	struct isapnp_irq *irq;
-	struct isapnp_dma *dma;
-	struct isapnp_mem *mem;
-
-	if (!cfg)
-		return -EINVAL;
-	/* process port settings */
-	for (tmp = 0; tmp < 8; tmp++) {
-		if (!(cfg->request->resource[tmp].flags & IORESOURCE_AUTO))
-			continue;		/* don't touch */
-		port = cfg->port[tmp];
-		if (!port) {
-			cfg->port[tmp] = port = isapnp_find_port(cfg->request, tmp);
-			if (!port)
-				return -EINVAL;
-		}
-		if (from && port->res == from) {
-			while (port->res != to) {
-				if (!port->res->alt)
-					return -EINVAL;
-				port = port->res->alt->port;
-				for (tmp1 = tmp; tmp1 > 0 && port; tmp1--)
-					port = port->next;
-				cfg->port[tmp] = port;
-				if (!port)
-					return -ENOENT;
-				cfg->result.resource[tmp].flags = isapnp_port_resource_flags(port);
-			}
-		}
-	}
-	/* process irq settings */
-	for (tmp = 0; tmp < 2; tmp++) {
-		if (!(cfg->request->irq_resource[tmp].flags & IORESOURCE_AUTO))
-			continue;		/* don't touch */
-		irq = cfg->irq[tmp];
-		if (!irq) {
-			cfg->irq[tmp] = irq = isapnp_find_irq(cfg->request, tmp);
-			if (!irq)
-				return -EINVAL;
-		}
-		if (from && irq->res == from) {
-			while (irq->res != to) {
-				if (!irq->res->alt)
-					return -EINVAL;
-				irq = irq->res->alt->irq;
-				for (tmp1 = tmp; tmp1 > 0 && irq; tmp1--)
-					irq = irq->next;
-				cfg->irq[tmp] = irq;
-				if (!irq)
-					return -ENOENT;
-				cfg->result.irq_resource[tmp].flags = isapnp_irq_resource_flags(irq);
-			}
-		}
-	}
-	/* process dma settings */
-	for (tmp = 0; tmp < 2; tmp++) {
-		if (!(cfg->request->dma_resource[tmp].flags & IORESOURCE_AUTO))
-			continue;		/* don't touch */
-		dma = cfg->dma[tmp];
-		if (!dma) {
-			cfg->dma[tmp] = dma = isapnp_find_dma(cfg->request, tmp);
-			if (!dma)
-				return -EINVAL;
-		}
-		if (from && dma->res == from) {
-			while (dma->res != to) {
-				if (!dma->res->alt)
-					return -EINVAL;
-				dma = dma->res->alt->dma;
-				for (tmp1 = tmp; tmp1 > 0 && dma; tmp1--)
-					dma = dma->next;
-				cfg->dma[tmp] = dma;
-				if (!dma)
-					return -ENOENT;
-				cfg->result.dma_resource[tmp].flags = isapnp_dma_resource_flags(dma);
-			}
-		}
-	}
-	/* process memory settings */
-	for (tmp = 0; tmp < 4; tmp++) {
-		if (!(cfg->request->resource[tmp + 8].flags & IORESOURCE_AUTO))
-			continue;		/* don't touch */
-		mem = cfg->mem[tmp];
-		if (!mem) {
-			cfg->mem[tmp] = mem = isapnp_find_mem(cfg->request, tmp);
-			if (!mem)
-				return -EINVAL;
-		}
-		if (from && mem->res == from) {
-			while (mem->res != to) {
-				if (!mem->res->alt)
-					return -EINVAL;
-				mem = mem->res->alt->mem;
-				for (tmp1 = tmp; tmp1 > 0 && mem; tmp1--)
-					mem = mem->next;
-				cfg->mem[tmp] = mem;
-				if (!mem)
-					return -ENOENT;
-				cfg->result.resource[tmp + 8].flags = isapnp_mem_resource_flags(mem);
-			}
-		}
-	}
-	return 0;
-}
-
-static int isapnp_check_port(struct isapnp_cfgtmp *cfg, int port, int size, int idx)
-{
-	int i, tmp, rport, rsize;
-	struct isapnp_port *xport;
-	struct pci_dev *dev;
-
-	if (check_region(port, size))
-		return 1;
-	for (i = 0; i < 8; i++) {
-		rport = isapnp_reserve_io[i << 1];
-		rsize = isapnp_reserve_io[(i << 1) + 1];
-		if (port >= rport && port < rport + rsize)
-			return 1;
-		if (port + size > rport && port + size < (rport + rsize) - 1)
-			return 1;
-	}
-
-	isapnp_for_each_dev(dev) {
-		if (dev->active) {
-			for (tmp = 0; tmp < 8; tmp++) {
-				if (dev->resource[tmp].flags) {
-					rport = dev->resource[tmp].start;
-					rsize = (dev->resource[tmp].end - rport) + 1;
-					if (port >= rport && port < rport + rsize)
-						return 1;
-					if (port + size > rport && port + size < (rport + rsize) - 1)
-						return 1;
-				}
-			}
-		}
-	}
-	for (i = 0; i < 8; i++) {
-		unsigned int flags;
-		if (i == idx)
-			continue;
-		flags = cfg->request->resource[i].flags;
-		if (!flags)
-			continue;
-		tmp = cfg->request->resource[i].start;
-		if (flags & IORESOURCE_AUTO) {		/* auto */
-			xport = cfg->port[i];
-			if (!xport)
-				return 1;
-			if (cfg->result.resource[i].flags & IORESOURCE_AUTO)
-				continue;
-			tmp = cfg->result.resource[i].start;
-			if (tmp + xport->size >= port && tmp <= port + xport->size)
-				return 1;
-			continue;
-		}
-		if (port == tmp)
-			return 1;
-		xport = isapnp_find_port(cfg->request, i);
-		if (!xport)
-			return 1;
-		if (tmp + xport->size >= port && tmp <= port + xport->size)
-			return 1;
-	}
-	return 0;
-}
-
-static int isapnp_valid_port(struct isapnp_cfgtmp *cfg, int idx)
-{
-	int err;
-	unsigned long *value1, *value2;
-	struct isapnp_port *port;
-
-	if (!cfg || idx < 0 || idx > 7)
-		return -EINVAL;
-	if (!(cfg->result.resource[idx].flags & IORESOURCE_AUTO)) /* don't touch */
-		return 0;
-      __again:
-      	port = cfg->port[idx];
-      	if (!port)
-      		return -EINVAL;
-      	value1 = &cfg->result.resource[idx].start;
-      	value2 = &cfg->result.resource[idx].end;
-	if (cfg->result.resource[idx].flags & IORESOURCE_AUTO) {
-		cfg->result.resource[idx].flags &= ~IORESOURCE_AUTO;
-		*value1 = port->min;
-		*value2 = port->min + port->size - 1;
-		if (!isapnp_check_port(cfg, *value1, port->size, idx))
-			return 0;
-	}
-	do {
-		*value1 += port->align;
-		*value2 = *value1 + port->size - 1;
-		if (*value1 > port->max || !port->align) {
-			if (port->res && port->res->alt) {
-				if ((err = isapnp_alternative_switch(cfg, port->res, port->res->alt))<0)
-					return err;
-				goto __again;
-			}
-			return -ENOENT;
-		}
-	} while (isapnp_check_port(cfg, *value1, port->size, idx));
-	return 0;
-}
-
-static void isapnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-}
-
-static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx)
-{
-	int i;
-	struct pci_dev *dev;
-
-	if (irq < 0 || irq > 15)
-		return 1;
-	for (i = 0; i < 16; i++) {
-		if (isapnp_reserve_irq[i] == irq)
-			return 1;
-	}
-	isapnp_for_each_dev(dev) {
-		if (dev->active) {
-			if ((dev->irq_resource[0].flags && dev->irq_resource[0].start == irq) ||
-			    (dev->irq_resource[1].flags && dev->irq_resource[1].start == irq))
-				return 1;
-		}
-	}
-#ifdef CONFIG_PCI
-	if (!isapnp_skip_pci_scan) {
-		pci_for_each_dev(dev) {
-			if (dev->irq == irq)
-				return 1;
-		}
-	}
-#endif
-	if (request_irq(irq, isapnp_test_handler, SA_INTERRUPT, "isapnp", NULL))
-		return 1;
-	free_irq(irq, NULL);
-	for (i = 0; i < DEVICE_COUNT_IRQ; i++) {
-		if (i == idx)
-			continue;
-		if (!cfg->result.irq_resource[i].flags)
-			continue;
-		if (cfg->result.irq_resource[i].flags & IORESOURCE_AUTO)
-			continue;
-		if (cfg->result.irq_resource[i].start == irq)
-			return 1;
-	}
-	return 0;
-}
-
-static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx)
-{
-	/* IRQ priority: this table is good for i386 */
-	static unsigned short xtab[16] = {
-		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
-	};
-	int err, i;
-	unsigned long *value1, *value2;
-	struct isapnp_irq *irq;
-
-	if (!cfg || idx < 0 || idx > 1)
-		return -EINVAL;
-	if (!(cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO))
-		return 0;
-      __again:
-      	irq = cfg->irq[idx];
-      	if (!irq)
-      		return -EINVAL;
-      	value1 = &cfg->result.irq_resource[idx].start;
-      	value2 = &cfg->result.irq_resource[idx].end;
-	if (cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO) {
-		for (i = 0; i < 16 && !(irq->map & (1<<xtab[i])); i++);
-		if (i >= 16)
-			return -ENOENT;
-		cfg->result.irq_resource[idx].flags &= ~IORESOURCE_AUTO;
-		if (!isapnp_check_interrupt(cfg, *value1 = *value2 = xtab[i], idx))
-			return 0;
-	}
-	do {
-		for (i = 0; i < 16 && xtab[i] != *value1; i++);
-		for (i++; i < 16 && !(irq->map & (1<<xtab[i])); i++);
-		if (i >= 16) {
-			if (irq->res && irq->res->alt) {
-				if ((err = isapnp_alternative_switch(cfg, irq->res, irq->res->alt))<0)
-					return err;
-				goto __again;
-			}
-			return -ENOENT;
-		} else {
-			*value1 = *value2 = xtab[i];
-		}
-	} while (isapnp_check_interrupt(cfg, *value1, idx));
-	return 0;
-}
-
-static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
-{
-	int i, mindma =1;
-	struct pci_dev *dev;
-
-	/* Some machines allow DMA 0, but others don't. In fact on some 
-	   boxes DMA 0 is the memory refresh. Play safe */
-	if (isapnp_allow_dma0 == 1)
-		mindma = 0;
-	if (dma < mindma || dma == 4 || dma > 7)
-		return 1;
-	for (i = 0; i < 8; i++) {
-		if (isapnp_reserve_dma[i] == dma)
-			return 1;
-	}
-	isapnp_for_each_dev(dev) {
-		if (dev->active) {
-			if ((dev->dma_resource[0].flags && dev->dma_resource[0].start == dma) ||
-			    (dev->dma_resource[1].flags && dev->dma_resource[1].start == dma))
-				return 1;
-		}
-	}
-	if (request_dma(dma, "isapnp"))
-		return 1;
-	free_dma(dma);
-	for (i = 0; i < 2; i++) {
-		if (i == idx)
-			continue;
-		if (!cfg->result.dma_resource[i].flags ||
-		    (cfg->result.dma_resource[i].flags & IORESOURCE_AUTO))
-			continue;
-		if (cfg->result.dma_resource[i].start == dma)
-			return 1;
-	}
-	return 0;
-}
-
-static int isapnp_valid_dma(struct isapnp_cfgtmp *cfg, int idx)
-{
-	/* DMA priority: this table is good for i386 */
-	static unsigned short xtab[16] = {
-		1, 3, 5, 6, 7, 0, 2, 4
-	};
-	int err, i;
-	unsigned long *value1, *value2;
-	struct isapnp_dma *dma;
-
-	if (!cfg || idx < 0 || idx > 1)
-		return -EINVAL;
-	if (!(cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO))	/* don't touch */
-		return 0;
-      __again:
-      	dma = cfg->dma[idx];
-      	if (!dma)
-      		return -EINVAL;
-      	value1 = &cfg->result.dma_resource[idx].start;
-      	value2 = &cfg->result.dma_resource[idx].end;
-	if (cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO) {
-		for (i = 0; i < 8 && !(dma->map & (1<<xtab[i])); i++);
-		if (i >= 8)
-			return -ENOENT;
-		cfg->result.dma_resource[idx].flags &= ~IORESOURCE_AUTO;
-		if (!isapnp_check_dma(cfg, *value1 = *value2 = xtab[i], idx))
-			return 0;
-	}
-	do {
-		for (i = 0; i < 8 && xtab[i] != *value1; i++);
-		for (i++; i < 8 && !(dma->map & (1<<xtab[i])); i++);
-		if (i >= 8) {
-			if (dma->res && dma->res->alt) {
-				if ((err = isapnp_alternative_switch(cfg, dma->res, dma->res->alt))<0)
-					return err;
-				goto __again;
-			}
-			return -ENOENT;
-		} else {
-			*value1 = *value2 = xtab[i];
-		}
-	} while (isapnp_check_dma(cfg, *value1, idx));
-	return 0;
-}
-
-static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsigned int size, int idx)
-{
-	int i, tmp;
-	unsigned int raddr, rsize;
-	struct isapnp_mem *xmem;
-	struct pci_dev *dev;
-
-	for (i = 0; i < 8; i++) {
-		raddr = (unsigned int)isapnp_reserve_mem[i << 1];
-		rsize = (unsigned int)isapnp_reserve_mem[(i << 1) + 1];
-		if (addr >= raddr && addr < raddr + rsize)
-			return 1;
-		if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
-			return 1;
-		if (__check_region(&iomem_resource, addr, size))
-			return 1;
-	}
-	isapnp_for_each_dev(dev) {
-		if (dev->active) {
-			for (tmp = 0; tmp < 4; tmp++) {
-				if (dev->resource[tmp].flags) {
-					raddr = dev->resource[tmp + 8].start;
-					rsize = (dev->resource[tmp + 8].end - raddr) + 1;
-					if (addr >= raddr && addr < raddr + rsize)
-						return 1;
-					if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
-						return 1;
-				}
-			}
-		}
-	}
-	for (i = 0; i < 4; i++) {
-		unsigned int flags = cfg->request->resource[i + 8].flags;
-		if (i == idx)
-			continue;
-		if (!flags)
-			continue;
-		tmp = cfg->result.resource[i + 8].start;
-		if (flags & IORESOURCE_AUTO) {		/* auto */
-			xmem = cfg->mem[i];
-			if (!xmem)
-				return 1;
-			if (cfg->result.resource[i + 8].flags & IORESOURCE_AUTO)
-				continue;
-			if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
-				return 1;
-			continue;
-		}
-		if (addr == tmp)
-			return 1;
-		xmem = isapnp_find_mem(cfg->request, i);
-		if (!xmem)
-			return 1;
-		if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
-			return 1;
-	}
-	return 0;
-}
-
-static int isapnp_valid_mem(struct isapnp_cfgtmp *cfg, int idx)
-{
-	int err;
-	unsigned long *value1, *value2;
-	struct isapnp_mem *mem;
-
-	if (!cfg || idx < 0 || idx > 3)
-		return -EINVAL;
-	if (!(cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO)) /* don't touch */
-		return 0;
-      __again:
-      	mem = cfg->mem[idx];
-      	if (!mem)
-      		return -EINVAL;
-      	value1 = &cfg->result.resource[idx + 8].start;
-      	value2 = &cfg->result.resource[idx + 8].end;
-	if (cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO) {
-		cfg->result.resource[idx + 8].flags &= ~IORESOURCE_AUTO;
-		*value1 = mem->min;
-		*value2 = mem->min + mem->size - 1;
-		if (!isapnp_check_mem(cfg, *value1, mem->size, idx))
-			return 0;
-	}
-	do {
-		*value1 += mem->align;
-		*value2 = *value1 + mem->size - 1;
-		if (*value1 > mem->max || !mem->align) {
-			if (mem->res && mem->res->alt) {
-				if ((err = isapnp_alternative_switch(cfg, mem->res, mem->res->alt))<0)
-					return err;
-				goto __again;
-			}
-			return -ENOENT;
-		}
-	} while (isapnp_check_mem(cfg, *value1, mem->size, idx));
-	return 0;
-}
-
-static int isapnp_check_valid(struct isapnp_cfgtmp *cfg)
-{
-	int tmp;
-	
-	for (tmp = 0; tmp < 8; tmp++)
-		if (cfg->result.resource[tmp].flags & IORESOURCE_AUTO)
-			return -EAGAIN;
-	for (tmp = 0; tmp < 2; tmp++)
-		if (cfg->result.irq_resource[tmp].flags & IORESOURCE_AUTO)
-			return -EAGAIN;
-	for (tmp = 0; tmp < 2; tmp++)
-		if (cfg->result.dma_resource[tmp].flags & IORESOURCE_AUTO)
-			return -EAGAIN;
-	for (tmp = 0; tmp < 4; tmp++)
-		if (cfg->result.resource[tmp + 8].flags & IORESOURCE_AUTO)
-			return -EAGAIN;
-	return 0;
-}
-
-static int isapnp_config_activate(struct pci_dev *dev)
-{
-	struct isapnp_cfgtmp cfg;
-	int tmp, fauto, err;
-	
-	if (!dev)
-		return -EINVAL;
-	if (dev->active)
-		return -EBUSY;
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.request = dev;
-	memcpy(&cfg.result, dev, sizeof(struct pci_dev));
-	/* check if all values are set, otherwise try auto-configuration */
-	for (tmp = fauto = 0; !fauto && tmp < 8; tmp++) {
-		if (dev->resource[tmp].flags & IORESOURCE_AUTO)
-			fauto++;
-	}
-	for (tmp = 0; !fauto && tmp < 2; tmp++) {
-		if (dev->irq_resource[tmp].flags & IORESOURCE_AUTO)
-			fauto++;
-	}
-	for (tmp = 0; !fauto && tmp < 2; tmp++) {
-		if (dev->dma_resource[tmp].flags & IORESOURCE_AUTO)
-			fauto++;
-	}
-	for (tmp = 0; !fauto && tmp < 4; tmp++) {
-		if (dev->resource[tmp + 8].flags & IORESOURCE_AUTO)
-			fauto++;
-	}
-	if (!fauto)
-		goto __skip_auto;
-	/* set variables to initial values */
-	if ((err = isapnp_alternative_switch(&cfg, NULL, NULL))<0)
-		return err;
-	/* find first valid configuration */
-	fauto = 0;
-	do {
-		for (tmp = 0; tmp < 8 && cfg.result.resource[tmp].flags; tmp++)
-			if ((err = isapnp_valid_port(&cfg, tmp))<0)
-				return err;
-		for (tmp = 0; tmp < 2 && cfg.result.irq_resource[tmp].flags; tmp++)
-			if ((err = isapnp_valid_irq(&cfg, tmp))<0)
-				return err;
-		for (tmp = 0; tmp < 2 && cfg.result.dma_resource[tmp].flags; tmp++)
-			if ((err = isapnp_valid_dma(&cfg, tmp))<0)
-				return err;
-		for (tmp = 0; tmp < 4 && cfg.result.resource[tmp + 8].flags; tmp++)
-			if ((err = isapnp_valid_mem(&cfg, tmp))<0)
-				return err;
-	} while (isapnp_check_valid(&cfg)<0 && fauto++ < 20);
-	if (fauto >= 20)
-		return -EAGAIN;
-      __skip_auto:
-      	/* we have valid configuration, try configure hardware */
-      	isapnp_cfg_begin(dev->bus->number, dev->devfn);
-	dev->active = 1;
-	dev->irq_resource[0] = cfg.result.irq_resource[0];
-	dev->irq_resource[1] = cfg.result.irq_resource[1];
-	dev->dma_resource[0] = cfg.result.dma_resource[0];
-	dev->dma_resource[1] = cfg.result.dma_resource[1];
-	for (tmp = 0; tmp < 12; tmp++) {
-		dev->resource[tmp] = cfg.result.resource[tmp];
-	}	
-	for (tmp = 0; tmp < 8 && dev->resource[tmp].flags; tmp++)
-		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start);
-	for (tmp = 0; tmp < 2 && dev->irq_resource[tmp].flags; tmp++) {
-		int irq = dev->irq_resource[tmp].start;
-		if (irq == 2)
-			irq = 9;
-		isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
-	}
-	for (tmp = 0; tmp < 2 && dev->dma_resource[tmp].flags; tmp++)
-		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma_resource[tmp].start);
-	for (tmp = 0; tmp < 4 && dev->resource[tmp+8].flags; tmp++)
-		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff);
-	isapnp_activate(dev->devfn);
-	isapnp_cfg_end();
-	return 0;
-}
-
-static int isapnp_config_deactivate(struct pci_dev *dev)
-{
-	if (!dev || !dev->active)
-		return -EINVAL;
-      	isapnp_cfg_begin(dev->bus->number, dev->devfn);
-	isapnp_deactivate(dev->devfn);
-	dev->active = 0;
-	isapnp_cfg_end();
-	return 0;
-}
-
-void isapnp_resource_change(struct resource *resource,
-			    unsigned long start,
-			    unsigned long size)
-{
-	if (resource == NULL)
-		return;
-	resource->flags &= ~IORESOURCE_AUTO;
-	resource->start = start;
-	resource->end = start + size - 1;
-}
-
-/*
- *  Inititialization.
- */
-
-#ifdef MODULE
-
-static void isapnp_free_port(struct isapnp_port *port)
-{
-	struct isapnp_port *next;
-
-	while (port) {
-		next = port->next;
-		kfree(port);
-		port = next;
-	}
-}
-
-static void isapnp_free_irq(struct isapnp_irq *irq)
-{
-	struct isapnp_irq *next;
-
-	while (irq) {
-		next = irq->next;
-		kfree(irq);
-		irq = next;
-	}
-}
-
-static void isapnp_free_dma(struct isapnp_dma *dma)
-{
-	struct isapnp_dma *next;
-
-	while (dma) {
-		next = dma->next;
-		kfree(dma);
-		dma = next;
-	}
-}
-
-static void isapnp_free_mem(struct isapnp_mem *mem)
-{
-	struct isapnp_mem *next;
-
-	while (mem) {
-		next = mem->next;
-		kfree(mem);
-		mem = next;
-	}
-}
-
-static void isapnp_free_mem32(struct isapnp_mem32 *mem32)
-{
-	struct isapnp_mem32 *next;
-
-	while (mem32) {
-		next = mem32->next;
-		kfree(mem32);
-		mem32 = next;
-	}
-}
-
-static void isapnp_free_resources(struct isapnp_resources *resources, int alt)
-{
-	struct isapnp_resources *next;
-
-	while (resources) {
-		next = alt ? resources->alt : resources->next;
-		isapnp_free_port(resources->port);
-		isapnp_free_irq(resources->irq);
-		isapnp_free_dma(resources->dma);
-		isapnp_free_mem(resources->mem);
-		isapnp_free_mem32(resources->mem32);
-		if (!alt && resources->alt)
-			isapnp_free_resources(resources->alt, 1);
-		kfree(resources);
-		resources = next;
-	}
-}
-
-static void isapnp_free_card(struct pci_bus *card)
-{
-	while (!list_empty(&card->devices)) {
-		struct list_head *list = card->devices.next;
-		struct pci_dev *dev = pci_dev_b(list);
-		list_del(list);
-		isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0);
-		kfree(dev);
-	}
-	kfree(card);
-}
-
-static void isapnp_free_all_resources(void)
-{
-#ifdef ISAPNP_REGION_OK
-	release_region(_PIDXR, 1);
-#endif
-	release_region(_PNPWRP, 1);
-	release_region(isapnp_rdp, 1);
-#ifdef CONFIG_PROC_FS
-	isapnp_proc_done();
-#endif
-	while (!list_empty(&isapnp_cards)) {
-		struct list_head *list = isapnp_cards.next;
-		list_del(list);
-		isapnp_free_card(pci_bus_b(list));
-	}
-}
-
-#endif /* MODULE */
-
-static int isapnp_announce_device(struct isapnp_driver *drv, 
-				  struct pci_dev *dev)
-{
-	const struct isapnp_device_id *id;
-	int ret = 0;
-
-	if (drv->id_table) {
-		id = isapnp_match_dev(drv->id_table, dev);
-		if (!id) {
-			ret = 0;
-			goto out;
-		}
-	} else
-		id = NULL;
-
-	if (drv->probe(dev, id) >= 0) {
-		dev->driver = (struct pci_driver *) drv;
-		ret = 1;
-	}
-out:
-	return ret;
-}
-
-/**
- * isapnp_dev_driver - get the isapnp_driver of a device
- * @dev: the device to query
- *
- * Returns the appropriate isapnp_driver structure or %NULL if there is no 
- * registered driver for the device.
- */
-static struct isapnp_driver *isapnp_dev_driver(const struct pci_dev *dev)
-{
-	return (struct isapnp_driver *) dev->driver;
-}
-
-static LIST_HEAD(isapnp_drivers);
-
-/**
- * isapnp_register_driver - register a new ISAPnP driver
- * @drv: the driver structure to register
- * 
- * Adds the driver structure to the list of registered ISAPnP drivers
- * Returns the number of isapnp devices which were claimed by the driver
- * during registration.  The driver remains registered even if the
- * return value is zero.
- */
-int isapnp_register_driver(struct isapnp_driver *drv)
-{
-	struct pci_dev *dev;
-	int count = 0;
-
-	list_add_tail(&drv->node, &isapnp_drivers);
-
-	isapnp_for_each_dev(dev) {
-		if (!isapnp_dev_driver(dev))
-			count += isapnp_announce_device(drv, dev);
-	}
-	return count;
-}
-
-/**
- * isapnp_unregister_driver - unregister an isapnp driver
- * @drv: the driver structure to unregister
- * 
- * Deletes the driver structure from the list of registered ISAPnP drivers,
- * gives it a chance to clean up by calling its remove() function for
- * each device it was responsible for, and marks those devices as
- * driverless.
- */
-void isapnp_unregister_driver(struct isapnp_driver *drv)
-{
-	struct pci_dev *dev;
-
-	list_del(&drv->node);
-	isapnp_for_each_dev(dev) {
-		if (dev->driver == (struct pci_driver *) drv) {
-			if (drv->remove)
-				drv->remove(dev);
-			dev->driver = NULL;
-		}
-	}
-}
-
-EXPORT_SYMBOL(isapnp_cards);
-EXPORT_SYMBOL(isapnp_devices);
-EXPORT_SYMBOL(isapnp_present);
-EXPORT_SYMBOL(isapnp_cfg_begin);
-EXPORT_SYMBOL(isapnp_cfg_end);
-EXPORT_SYMBOL(isapnp_read_byte);
-EXPORT_SYMBOL(isapnp_read_word);
-EXPORT_SYMBOL(isapnp_read_dword);
-EXPORT_SYMBOL(isapnp_write_byte);
-EXPORT_SYMBOL(isapnp_write_word);
-EXPORT_SYMBOL(isapnp_write_dword);
-EXPORT_SYMBOL(isapnp_wake);
-EXPORT_SYMBOL(isapnp_device);
-EXPORT_SYMBOL(isapnp_activate);
-EXPORT_SYMBOL(isapnp_deactivate);
-EXPORT_SYMBOL(isapnp_find_card);
-EXPORT_SYMBOL(isapnp_find_dev);
-EXPORT_SYMBOL(isapnp_probe_cards);
-EXPORT_SYMBOL(isapnp_probe_devs);
-EXPORT_SYMBOL(isapnp_activate_dev);
-EXPORT_SYMBOL(isapnp_resource_change);
-EXPORT_SYMBOL(isapnp_register_driver);
-EXPORT_SYMBOL(isapnp_unregister_driver);
-
-static struct device_driver isapnp_device_driver = {
-	.devices = LIST_HEAD_INIT(isapnp_device_driver.devices),
-};
-
-static inline int isapnp_init_device_tree(void)
-{
-	struct pci_bus *card;
-	struct pci_dev *parent = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-
-	INIT_LIST_HEAD(&isapnp_device_driver.devices);
-
-	isapnp_for_each_card(card) {
-		struct list_head *devlist;
-
-		card->dev = isapnp_alloc(sizeof(*card->dev));
-		if (!card->dev)
-			break;
-		snprintf(card->dev->name, sizeof(card->dev->name), "%s", card->name);
-		sprintf(card->dev->bus_id, "isapnp%d", card->number);
-		card->dev->parent = parent ? &parent->dev : NULL;
-		card->dev->driver = &isapnp_device_driver;
-		device_register(card->dev);
-
-		for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
-			struct pci_dev *dev = pci_dev_b(devlist);
-
-			snprintf(dev->dev.name, sizeof(dev->dev.name), "%s", dev->name);
-			sprintf(dev->dev.bus_id, "%d", dev->devfn);
-			dev->dev.parent = card->dev;
-			dev->dev.driver = &isapnp_device_driver;
-			device_register(&dev->dev);
-		}
-	}
-
-	return 0;
-}
-
-int __init isapnp_init(void)
-{
-	int cards;
-	struct pci_bus *card;
-
-	if (isapnp_disable) {
-		isapnp_detected = 0;
-		printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
-		return 0;
-	}
-#ifdef ISAPNP_REGION_OK
-	if (!request_region(_PIDXR, 1, "isapnp index")) {
-		printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR);
-		return -EBUSY;
-	}
-#endif
-	if (!request_region(_PNPWRP, 1, "isapnp write")) {
-		printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP);
-#ifdef ISAPNP_REGION_OK
-		release_region(_PIDXR, 1);
-#endif
-		return -EBUSY;
-	}
-	
-	/*
-	 *	Print a message. The existing ISAPnP code is hanging machines
-	 *	so let the user know where.
-	 */
-	 
-	printk(KERN_INFO "isapnp: Scanning for PnP cards...\n");
-	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {
-		isapnp_rdp |= 3;
-		if (!request_region(isapnp_rdp, 1, "isapnp read")) {
-			printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);
-#ifdef ISAPNP_REGION_OK
-			release_region(_PIDXR, 1);
-#endif
-			release_region(_PNPWRP, 1);
-			return -EBUSY;
-		}
-		isapnp_set_rdp();
-	}
-	isapnp_detected = 1;
-	if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) {
-		cards = isapnp_isolate();
-		if (cards < 0 || 
-		    (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {
-#ifdef ISAPNP_REGION_OK
-			release_region(_PIDXR, 1);
-#endif
-			release_region(_PNPWRP, 1);
-			isapnp_detected = 0;
-			printk(KERN_INFO "isapnp: No Plug & Play device found\n");
-			return 0;
-		}
-		request_region(isapnp_rdp, 1, "isapnp read");
-	}
-	isapnp_build_device_list();
-	cards = 0;
-
-	isapnp_for_each_card(card) {
-		cards++;
-		if (isapnp_verbose) {
-			struct list_head *devlist;
-			printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
-			if (isapnp_verbose < 2)
-				continue;
-			for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
-				struct pci_dev *dev = pci_dev_b(devlist);
-				printk(KERN_INFO "isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
-			}
-		}
-	}
-	if (cards) {
-		printk(KERN_INFO "isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":"");
-	} else {
-		printk(KERN_INFO "isapnp: No Plug & Play card found\n");
-	}
-
-	isapnp_init_device_tree();
-
-#ifdef CONFIG_PROC_FS
-	isapnp_proc_init();
-#endif
-	return 0;
-}
-
-subsys_initcall(isapnp_init);
-
-#ifdef MODULE
-
-static inline void isapnp_cleanup_device_tree(void)
-{
-	struct pci_bus *card;
-
-	isapnp_for_each_card(card) {
-		struct list_head *devlist;
-
-		for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
-			struct pci_dev *dev = pci_dev_b(devlist);
-
-			put_device(&dev->dev);
-		}
-		put_device(card->dev);
-	}
-}
-
-void cleanup_module(void)
-{
-	if (isapnp_detected) {
-		isapnp_cleanup_device_tree();
-		isapnp_free_all_resources();
-	}
-}
-
-#else
-
-/* format is: noisapnp */
-
-static int __init isapnp_setup_disable(char *str)
-{
-	isapnp_disable = 1;
-	return 1;
-}
-
-__setup("noisapnp", isapnp_setup_disable);
-
-/* format is: isapnp=rdp,reset,skip_pci_scan,verbose */
-
-static int __init isapnp_setup_isapnp(char *str)
-{
-	(void)((get_option(&str,&isapnp_rdp) == 2) &&
-	       (get_option(&str,&isapnp_reset) == 2) &&
-	       (get_option(&str,&isapnp_skip_pci_scan) == 2) &&
-	       (get_option(&str,&isapnp_verbose) == 2));
-	return 1;
-}
-
-__setup("isapnp=", isapnp_setup_isapnp);
-
-/* format is: isapnp_reserve_irq=irq1[,irq2] .... */
-
-static int __init isapnp_setup_reserve_irq(char *str)
-{
-	int i;
-
-	for (i = 0; i < 16; i++)
-		if (get_option(&str,&isapnp_reserve_irq[i]) != 2)
-			break;
-	return 1;
-}
-
-__setup("isapnp_reserve_irq=", isapnp_setup_reserve_irq);
-
-/* format is: isapnp_reserve_dma=dma1[,dma2] .... */
-
-static int __init isapnp_setup_reserve_dma(char *str)
-{
-	int i;
-
-	for (i = 0; i < 8; i++)
-		if (get_option(&str,&isapnp_reserve_dma[i]) != 2)
-			break;
-	return 1;
-}
-
-__setup("isapnp_reserve_dma=", isapnp_setup_reserve_dma);
-
-/* format is: isapnp_reserve_io=io1,size1[,io2,size2] .... */
-
-static int __init isapnp_setup_reserve_io(char *str)
-{
-	int i;
-
-	for (i = 0; i < 16; i++)
-		if (get_option(&str,&isapnp_reserve_io[i]) != 2)
-			break;
-	return 1;
-}
-
-__setup("isapnp_reserve_io=", isapnp_setup_reserve_io);
-
-/* format is: isapnp_reserve_mem=mem1,size1[,mem2,size2] .... */
-
-static int __init isapnp_setup_reserve_mem(char *str)
-{
-	int i;
-
-	for (i = 0; i < 16; i++)
-		if (get_option(&str,&isapnp_reserve_mem[i]) != 2)
-			break;
-	return 1;
-}
-
-__setup("isapnp_reserve_mem=", isapnp_setup_reserve_mem);
-
-#endif
diff -Nru a/drivers/pnp/isapnp_proc.c b/drivers/pnp/isapnp_proc.c
--- a/drivers/pnp/isapnp_proc.c	Fri Oct 18 21:03:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1134 +0,0 @@
-/*
- *  ISA Plug & Play support
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *
- *
- *   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.
- *
- */
-
-#define __NO_VERSION__
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/poll.h>
-#include <linux/vmalloc.h>
-#include <asm/uaccess.h>
-#include <linux/smp_lock.h>
-#include <linux/isapnp.h>
-
-struct isapnp_info_buffer {
-	char *buffer;		/* pointer to begin of buffer */
-	char *curr;		/* current position in buffer */
-	unsigned long size;	/* current size */
-	unsigned long len;	/* total length of buffer */
-	int stop;		/* stop flag */
-	int error;		/* error code */
-};
-
-typedef struct isapnp_info_buffer isapnp_info_buffer_t;
-
-static struct proc_dir_entry *isapnp_proc_entry = NULL;
-static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
-static struct proc_dir_entry *isapnp_proc_devices_entry = NULL;
-
-static void isapnp_info_read(isapnp_info_buffer_t *buffer);
-static void isapnp_info_write(isapnp_info_buffer_t *buffer);
-
-int isapnp_printf(isapnp_info_buffer_t * buffer, char *fmt,...)
-{
-	va_list args;
-	int res;
-	char sbuffer[512];
-
-	if (buffer->stop || buffer->error)
-		return 0;
-	va_start(args, fmt);
-	res = vsprintf(sbuffer, fmt, args);
-	va_end(args);
-	if (buffer->size + res >= buffer->len) {
-		buffer->stop = 1;
-		return 0;
-	}
-	strcpy(buffer->curr, sbuffer);
-	buffer->curr += res;
-	buffer->size += res;
-	return res;
-}
-
-static void isapnp_devid(char *str, unsigned short vendor, unsigned short device)
-{
-	sprintf(str, "%c%c%c%x%x%x%x",
-			'A' + ((vendor >> 2) & 0x3f) - 1,
-			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
-			'A' + ((vendor >> 8) & 0x1f) - 1,
-			(device >> 4) & 0x0f,
-			device & 0x0f,
-			(device >> 12) & 0x0f,
-			(device >> 8) & 0x0f);
-}
-
-static loff_t isapnp_info_entry_lseek(struct file *file, loff_t offset, int orig)
-{
-	loff_t ret;
-
-	lock_kernel();
-
-	switch (orig) {
-	case 0:	/* SEEK_SET */
-		file->f_pos = offset;
-		ret = file->f_pos;
-		break;
-	case 1:	/* SEEK_CUR */
-		file->f_pos += offset;
-		ret = file->f_pos;
-		break;
-	case 2:	/* SEEK_END */
-	default:
-		ret = -EINVAL;
-	}
-
-	unlock_kernel();
-	return ret;
-}
-
-static ssize_t isapnp_info_entry_read(struct file *file, char *buffer,
-				      size_t count, loff_t * offset)
-{
-	isapnp_info_buffer_t *buf;
-	long size = 0, size1;
-	int mode;
-
-	mode = file->f_flags & O_ACCMODE;
-	if (mode != O_RDONLY)
-		return -EINVAL;
-	buf = (isapnp_info_buffer_t *) file->private_data;
-	if (!buf)
-		return -EIO;
-	if (file->f_pos >= buf->size)
-		return 0;
-	size = buf->size < count ? buf->size : count;
-	size1 = buf->size - file->f_pos;
-	if (size1 < size)
-		size = size1;
-	if (copy_to_user(buffer, buf->buffer + file->f_pos, size))
-		return -EFAULT;
-	file->f_pos += size;
-	return size;
-}
-
-static ssize_t isapnp_info_entry_write(struct file *file, const char *buffer,
-				       size_t count, loff_t * offset)
-{
-	isapnp_info_buffer_t *buf;
-	long size = 0, size1;
-	int mode;
-
-	mode = file->f_flags & O_ACCMODE;
-	if (mode != O_WRONLY)
-		return -EINVAL;
-	buf = (isapnp_info_buffer_t *) file->private_data;
-	if (!buf)
-		return -EIO;
-	if (file->f_pos < 0)
-		return -EINVAL;
-	if (file->f_pos >= buf->len)
-		return -ENOMEM;
-	size = buf->len < count ? buf->len : count;
-	size1 = buf->len - file->f_pos;
-	if (size1 < size)
-		size = size1;
-	if (copy_from_user(buf->buffer + file->f_pos, buffer, size))
-		return -EFAULT;
-	if (buf->size < file->f_pos + size)
-		buf->size = file->f_pos + size;
-	file->f_pos += size;
-	return size;
-}
-
-static int isapnp_info_entry_open(struct inode *inode, struct file *file)
-{
-	isapnp_info_buffer_t *buffer;
-	int mode;
-
-	mode = file->f_flags & O_ACCMODE;
-	if (mode != O_RDONLY && mode != O_WRONLY)
-		return -EINVAL;
-	buffer = (isapnp_info_buffer_t *)
-				isapnp_alloc(sizeof(isapnp_info_buffer_t));
-	if (!buffer)
-		return -ENOMEM;
-	buffer->len = 4 * PAGE_SIZE;
-	buffer->buffer = vmalloc(buffer->len);
-	if (!buffer->buffer) {
-		kfree(buffer);
-		return -ENOMEM;
-	}
-	buffer->curr = buffer->buffer;
-	file->private_data = buffer;
-	if (mode == O_RDONLY)
-		isapnp_info_read(buffer);
-	return 0;
-}
-
-static int isapnp_info_entry_release(struct inode *inode, struct file *file)
-{
-	isapnp_info_buffer_t *buffer;
-	int mode;
-
-	if ((buffer = (isapnp_info_buffer_t *) file->private_data) == NULL)
-		return -EINVAL;
-	mode = file->f_flags & O_ACCMODE;
-	if (mode == O_WRONLY)
-		isapnp_info_write(buffer);
-	vfree(buffer->buffer);
-	kfree(buffer);
-	return 0;
-}
-
-static unsigned int isapnp_info_entry_poll(struct file *file, poll_table * wait)
-{
-	if (!file->private_data)
-		return 0;
-	return POLLIN | POLLRDNORM;
-}
-
-static struct file_operations isapnp_info_entry_operations =
-{
-	llseek:		isapnp_info_entry_lseek,
-	read:		isapnp_info_entry_read,
-	write:		isapnp_info_entry_write,
-	poll:		isapnp_info_entry_poll,
-	open:		isapnp_info_entry_open,
-	release:	isapnp_info_entry_release,
-};
-
-static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
-{
-	loff_t new = -1;
-
-	lock_kernel();
-	switch (whence) {
-	case 0:
-		new = off;
-		break;
-	case 1:
-		new = file->f_pos + off;
-		break;
-	case 2:
-		new = 256 + off;
-		break;
-	}
-	if (new < 0 || new > 256) {
-		unlock_kernel();
-		return -EINVAL;
-	}
-	unlock_kernel();
-	return (file->f_pos = new);
-}
-
-static ssize_t isapnp_proc_bus_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
-{
-	struct inode *ino = file->f_dentry->d_inode;
-	struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
-	int pos = *ppos;
-	int cnt, size = 256;
-
-	if (pos >= size)
-		return 0;
-	if (nbytes >= size)
-		nbytes = size;
-	if (pos + nbytes > size)
-		nbytes = size - pos;
-	cnt = nbytes;
-
-	if (!access_ok(VERIFY_WRITE, buf, cnt))
-		return -EINVAL;
-		
-	isapnp_cfg_begin(dev->bus->number, dev->devfn);
-	for ( ; pos < 256 && cnt > 0; pos++, buf++, cnt--) {
-		unsigned char val;
-		val = isapnp_read_byte(pos);
-		__put_user(val, buf);
-	}
-	isapnp_cfg_end();
-	
-	*ppos = pos;
-	return nbytes;
-}
-
-static struct file_operations isapnp_proc_bus_file_operations =
-{
-	llseek:		isapnp_proc_bus_lseek,
-	read:		isapnp_proc_bus_read,
-};
-
-static int isapnp_proc_attach_device(struct pci_dev *dev)
-{
-	struct pci_bus *bus = dev->bus;
-	struct proc_dir_entry *de, *e;
-	char name[16];
-
-	if (!(de = bus->procdir)) {
-		sprintf(name, "%02x", bus->number);
-		de = bus->procdir = proc_mkdir(name, isapnp_proc_bus_dir);
-		if (!de)
-			return -ENOMEM;
-	}
-	sprintf(name, "%02x", dev->devfn);
-	e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO, de);
-	if (!e)
-		return -ENOMEM;
-	e->proc_fops = &isapnp_proc_bus_file_operations;
-	e->owner = THIS_MODULE;
-	e->data = dev;
-	e->size = 256;
-	return 0;
-}
-
-#ifdef MODULE
-static int __exit isapnp_proc_detach_device(struct pci_dev *dev)
-{
-	struct pci_bus *bus = dev->bus;
-	struct proc_dir_entry *de;
-	char name[16];
-
-	if (!(de = bus->procdir))
-		return -EINVAL;
-	sprintf(name, "%02x", dev->devfn);
-	remove_proc_entry(name, de);
-	return 0;
-}
-
-static int __exit isapnp_proc_detach_bus(struct pci_bus *bus)
-{
-	struct proc_dir_entry *de;
-	char name[16];
-
-	if (!(de = bus->procdir))
-		return -EINVAL;
-	sprintf(name, "%02x", bus->number);
-	remove_proc_entry(name, isapnp_proc_bus_dir);
-	return 0;
-}
-#endif
-
-static int isapnp_proc_read_devices(char *buf, char **start, off_t pos, int count)
-{
-	struct pci_dev *dev;
-	off_t at = 0;
-	int len, cnt, i;
-	
-	cnt = 0;
-	isapnp_for_each_dev(dev) {
-		char bus_id[8], device_id[8];
-	
-		isapnp_devid(bus_id, dev->bus->vendor, dev->bus->device);
-		isapnp_devid(device_id, dev->vendor, dev->device);
-		len = sprintf(buf, "%02x%02x\t%s%s\t",
-			dev->bus->number,
-			dev->devfn,
-			bus_id,
-			device_id);
-		isapnp_cfg_begin(dev->bus->number, dev->devfn);
-		len += sprintf(buf+len, "%02x", isapnp_read_byte(ISAPNP_CFG_ACTIVATE));
-		for (i = 0; i < 8; i++)
-			len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)));
-		for (i = 0; i < 2; i++)
-			len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)));
-		for (i = 0; i < 2; i++)
-			len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_DMA + i));
-		for (i = 0; i < 4; i++)
-			len += sprintf(buf+len, "%08x", isapnp_read_dword(ISAPNP_CFG_MEM + (i << 3)));
-		isapnp_cfg_end();
-		buf[len++] = '\n';
-		at += len;
-		if (at >= pos) {
-			if (!*start) {
-				*start = buf + (pos - (at - len));
-				cnt = at - pos;
-			} else
-				cnt += len;
-			buf += len;
-		}
-	}
-	return (count > cnt) ? cnt : count;
-}
-
-int __init isapnp_proc_init(void)
-{
-	struct proc_dir_entry *p;
-	struct pci_dev *dev;
-
-	isapnp_proc_entry = NULL;
-	p = create_proc_entry("isapnp", S_IFREG | S_IRUGO | S_IWUSR, &proc_root);
-	if (p) {
-		p->proc_fops = &isapnp_info_entry_operations;
-		p->owner = THIS_MODULE;
-	}
-	isapnp_proc_entry = p;
-	isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
-	isapnp_proc_devices_entry = create_proc_info_entry("devices", 0,
-							   isapnp_proc_bus_dir,
-							   isapnp_proc_read_devices);
-	isapnp_for_each_dev(dev) {
-		isapnp_proc_attach_device(dev);
-	}
-	return 0;
-}
-
-#ifdef MODULE
-int __exit isapnp_proc_done(void)
-{
-	struct pci_dev *dev;
-	struct pci_bus *card;
-
-	isapnp_for_each_dev(dev) {
-		isapnp_proc_detach_device(dev);
-	}
-	isapnp_for_each_card(card) {
-		isapnp_proc_detach_bus(card);
-	}
-	if (isapnp_proc_devices_entry)
-		remove_proc_entry("devices", isapnp_proc_devices_entry);
-	if (isapnp_proc_bus_dir)
-		remove_proc_entry("isapnp", proc_bus);
-	if (isapnp_proc_entry)
-		remove_proc_entry("isapnp", &proc_root);
-	return 0;
-}
-#endif /* MODULE */
-
-/*
- *
- */
-
-static void isapnp_print_devid(isapnp_info_buffer_t *buffer, unsigned short vendor, unsigned short device)
-{
-	char tmp[8];
-	
-	isapnp_devid(tmp, vendor, device);
-	isapnp_printf(buffer, tmp);
-}
-
-static void isapnp_print_compatible(isapnp_info_buffer_t *buffer, struct pci_dev *dev)
-{
-	int idx;
-
-	for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++) {
-		if (dev->vendor_compatible[idx] == 0)
-			continue;
-		isapnp_printf(buffer, "    Compatible device ");
-		isapnp_print_devid(buffer,
-				   dev->vendor_compatible[idx],
-				   dev->device_compatible[idx]);
-		isapnp_printf(buffer, "\n");
-	}
-}
-
-static void isapnp_print_port(isapnp_info_buffer_t *buffer, char *space, struct isapnp_port *port)
-{
-	isapnp_printf(buffer, "%sPort 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
-			space, port->min, port->max, port->align ? (port->align-1) : 0, port->size,
-			port->flags & ISAPNP_PORT_FLAG_16BITADDR ? 16 : 10);
-}
-
-static void isapnp_print_irq(isapnp_info_buffer_t *buffer, char *space, struct isapnp_irq *irq)
-{
-	int first = 1, i;
-
-	isapnp_printf(buffer, "%sIRQ ", space);
-	for (i = 0; i < 16; i++)
-		if (irq->map & (1<<i)) {
-			if (!first) {
-				isapnp_printf(buffer, ",");
-			} else {
-				first = 0;
-			}
-			if (i == 2 || i == 9)
-				isapnp_printf(buffer, "2/9");
-			else
-				isapnp_printf(buffer, "%i", i);
-		}
-	if (!irq->map)
-		isapnp_printf(buffer, "<none>");
-	if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
-		isapnp_printf(buffer, " High-Edge");
-	if (irq->flags & IORESOURCE_IRQ_LOWEDGE)
-		isapnp_printf(buffer, " Low-Edge");
-	if (irq->flags & IORESOURCE_IRQ_HIGHLEVEL)
-		isapnp_printf(buffer, " High-Level");
-	if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
-		isapnp_printf(buffer, " Low-Level");
-	isapnp_printf(buffer, "\n");
-}
-
-static void isapnp_print_dma(isapnp_info_buffer_t *buffer, char *space, struct isapnp_dma *dma)
-{
-	int first = 1, i;
-	char *s;
-
-	isapnp_printf(buffer, "%sDMA ", space);
-	for (i = 0; i < 8; i++)
-		if (dma->map & (1<<i)) {
-			if (!first) {
-				isapnp_printf(buffer, ",");
-			} else {
-				first = 0;
-			}
-			isapnp_printf(buffer, "%i", i);
-		}
-	if (!dma->map)
-		isapnp_printf(buffer, "<none>");
-	switch (dma->flags & IORESOURCE_DMA_TYPE_MASK) {
-	case IORESOURCE_DMA_8BIT:
-		s = "8-bit";
-		break;
-	case IORESOURCE_DMA_8AND16BIT:
-		s = "8-bit&16-bit";
-		break;
-	default:
-		s = "16-bit";
-	}
-	isapnp_printf(buffer, " %s", s);
-	if (dma->flags & IORESOURCE_DMA_MASTER)
-		isapnp_printf(buffer, " master");
-	if (dma->flags & IORESOURCE_DMA_BYTE)
-		isapnp_printf(buffer, " byte-count");
-	if (dma->flags & IORESOURCE_DMA_WORD)
-		isapnp_printf(buffer, " word-count");
-	switch (dma->flags & IORESOURCE_DMA_SPEED_MASK) {
-	case IORESOURCE_DMA_TYPEA:
-		s = "type-A";
-		break;
-	case IORESOURCE_DMA_TYPEB:
-		s = "type-B";
-		break;
-	case IORESOURCE_DMA_TYPEF:
-		s = "type-F";
-		break;
-	default:
-		s = "compatible";
-		break;
-	}
-	isapnp_printf(buffer, " %s\n", s);
-}
-
-static void isapnp_print_mem(isapnp_info_buffer_t *buffer, char *space, struct isapnp_mem *mem)
-{
-	char *s;
-
-	isapnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
-			space, mem->min, mem->max, mem->align, mem->size);
-	if (mem->flags & IORESOURCE_MEM_WRITEABLE)
-		isapnp_printf(buffer, ", writeable");
-	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
-		isapnp_printf(buffer, ", cacheable");
-	if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
-		isapnp_printf(buffer, ", range-length");
-	if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
-		isapnp_printf(buffer, ", shadowable");
-	if (mem->flags & IORESOURCE_MEM_EXPANSIONROM)
-		isapnp_printf(buffer, ", expansion ROM");
-	switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
-	case IORESOURCE_MEM_8BIT:
-		s = "8-bit";
-		break;
-	case IORESOURCE_MEM_8AND16BIT:
-		s = "8-bit&16-bit";
-		break;
-	default:
-		s = "16-bit";
-	}
-	isapnp_printf(buffer, ", %s\n", s);
-}
-
-static void isapnp_print_mem32(isapnp_info_buffer_t *buffer, char *space, struct isapnp_mem32 *mem32)
-{
-	int first = 1, i;
-
-	isapnp_printf(buffer, "%s32-bit memory ", space);
-	for (i = 0; i < 17; i++) {
-		if (first) {
-			first = 0;
-		} else {
-			isapnp_printf(buffer, ":");
-		}
-		isapnp_printf(buffer, "%02x", mem32->data[i]);
-	}
-}
-
-static void isapnp_print_resources(isapnp_info_buffer_t *buffer, char *space, struct isapnp_resources *res)
-{
-	char *s;
-	struct isapnp_port *port;
-	struct isapnp_irq *irq;
-	struct isapnp_dma *dma;
-	struct isapnp_mem *mem;
-	struct isapnp_mem32 *mem32;
-
-	switch (res->priority) {
-	case ISAPNP_RES_PRIORITY_PREFERRED:
-		s = "preferred";
-		break;
-	case ISAPNP_RES_PRIORITY_ACCEPTABLE:
-		s = "acceptable";
-		break;
-	case ISAPNP_RES_PRIORITY_FUNCTIONAL:
-		s = "functional";
-		break;
-	default:
-		s = "invalid";
-	}
-	isapnp_printf(buffer, "%sPriority %s\n", space, s);
-	for (port = res->port; port; port = port->next)
-		isapnp_print_port(buffer, space, port);
-	for (irq = res->irq; irq; irq = irq->next)
-		isapnp_print_irq(buffer, space, irq);
-	for (dma = res->dma; dma; dma = dma->next)
-		isapnp_print_dma(buffer, space, dma);
-	for (mem = res->mem; mem; mem = mem->next)
-		isapnp_print_mem(buffer, space, mem);
-	for (mem32 = res->mem32; mem32; mem32 = mem32->next)
-		isapnp_print_mem32(buffer, space, mem32);
-}
-
-static void isapnp_print_configuration(isapnp_info_buffer_t *buffer, struct pci_dev *dev)
-{
-	int i, tmp, next;
-	char *space = "    ";
-
-	isapnp_cfg_begin(dev->bus->number, dev->devfn);
-	isapnp_printf(buffer, "%sDevice is %sactive\n",
-			space, isapnp_read_byte(ISAPNP_CFG_ACTIVATE)?"":"not ");
-	for (i = next = 0; i < 8; i++) {
-		tmp = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
-		if (!tmp)
-			continue;
-		if (!next) {
-			isapnp_printf(buffer, "%sActive port ", space);
-			next = 1;
-		}
-		isapnp_printf(buffer, "%s0x%x", i > 0 ? "," : "", tmp);
-	}
-	if (next)
-		isapnp_printf(buffer, "\n");
-	for (i = next = 0; i < 2; i++) {
-		tmp = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1));
-		if (!(tmp >> 8))
-			continue;
-		if (!next) {
-			isapnp_printf(buffer, "%sActive IRQ ", space);
-			next = 1;
-		}
-		isapnp_printf(buffer, "%s%i", i > 0 ? "," : "", tmp >> 8);
-		if (tmp & 0xff)
-			isapnp_printf(buffer, " [0x%x]", tmp & 0xff);
-	}
-	if (next)
-		isapnp_printf(buffer, "\n");
-	for (i = next = 0; i < 2; i++) {
-		tmp = isapnp_read_byte(ISAPNP_CFG_DMA + i);
-		if (tmp == 4)
-			continue;
-		if (!next) {
-			isapnp_printf(buffer, "%sActive DMA ", space);
-			next = 1;
-		}
-		isapnp_printf(buffer, "%s%i", i > 0 ? "," : "", tmp);
-	}
-	if (next)
-		isapnp_printf(buffer, "\n");
-	for (i = next = 0; i < 4; i++) {
-		tmp = isapnp_read_dword(ISAPNP_CFG_MEM + (i << 3));
-		if (!tmp)
-			continue;
-		if (!next) {
-			isapnp_printf(buffer, "%sActive memory ", space);
-			next = 1;
-		}
-		isapnp_printf(buffer, "%s0x%x", i > 0 ? "," : "", tmp);
-	}
-	if (next)
-		isapnp_printf(buffer, "\n");
-	isapnp_cfg_end();
-}
-
-static void isapnp_print_device(isapnp_info_buffer_t *buffer, struct pci_dev *dev)
-{
-	int block, block1;
-	char *space = "    ";
-	struct isapnp_resources *res, *resa;
-
-	if (!dev)
-		return;
-	isapnp_printf(buffer, "  Logical device %i '", dev->devfn);
-	isapnp_print_devid(buffer, dev->vendor, dev->device);
-	isapnp_printf(buffer, ":%s'", dev->name[0]?dev->name:"Unknown");
-	isapnp_printf(buffer, "\n");
-#if 0
-	isapnp_cfg_begin(dev->bus->number, dev->devfn);
-	for (block = 0; block < 128; block++)
-		if ((block % 16) == 15)
-			isapnp_printf(buffer, "%02x\n", isapnp_read_byte(block));
-		else
-			isapnp_printf(buffer, "%02x:", isapnp_read_byte(block));
-	isapnp_cfg_end();
-#endif
-	if (dev->regs)
-		isapnp_printf(buffer, "%sSupported registers 0x%x\n", space, dev->regs);
-	isapnp_print_compatible(buffer, dev);
-	isapnp_print_configuration(buffer, dev);
-	for (res = (struct isapnp_resources *)dev->sysdata, block = 0; res; res = res->next, block++) {
-		isapnp_printf(buffer, "%sResources %i\n", space, block);
-		isapnp_print_resources(buffer, "      ", res);
-		for (resa = res->alt, block1 = 1; resa; resa = resa->alt, block1++) {
-			isapnp_printf(buffer, "%s  Alternate resources %i:%i\n", space, block, block1);
-			isapnp_print_resources(buffer, "        ", resa);
-		}
-	}
-}
-
-/*
- *  Main read routine
- */
- 
-static void isapnp_info_read(isapnp_info_buffer_t *buffer)
-{
-	struct pci_bus *card;
-
-	isapnp_for_each_card(card) {
-		struct list_head *dev_list;
-
-		isapnp_printf(buffer, "Card %i '", card->number);
-		isapnp_print_devid(buffer, card->vendor, card->device);
-		isapnp_printf(buffer, ":%s'", card->name[0]?card->name:"Unknown");
-		if (card->pnpver)
-			isapnp_printf(buffer, " PnP version %x.%x", card->pnpver >> 4, card->pnpver & 0x0f);
-		if (card->productver)
-			isapnp_printf(buffer, " Product version %x.%x", card->productver >> 4, card->productver & 0x0f);
-		isapnp_printf(buffer,"\n");
-		for (dev_list = card->devices.next; dev_list != &card->devices; dev_list = dev_list->next)
-			isapnp_print_device(buffer, pci_dev_b(dev_list));
-	}
-}
-
-/*
- *
- */
-
-static struct pci_bus *isapnp_info_card;
-static struct pci_dev *isapnp_info_device;
-
-static char *isapnp_get_str(char *dest, char *src, int len)
-{
-	int c;
-
-	while (*src == ' ' || *src == '\t')
-		src++;
-	if (*src == '"' || *src == '\'') {
-		c = *src++;
-		while (--len > 0 && *src && *src != c) {
-			*dest++ = *src++;
-		}
-		if (*src == c)
-			src++;
-	} else {
-		while (--len > 0 && *src && *src != ' ' && *src != '\t') {
-			*dest++ = *src++;
-		}
-	}
-	*dest = 0;
-	while (*src == ' ' || *src == '\t')
-		src++;
-	return src;
-}
-
-static unsigned char isapnp_get_hex(unsigned char c)
-{
-	if (c >= '0' && c <= '9')
-		return c - '0';
-	if (c >= 'a' && c <= 'f')
-		return (c - 'a') + 10;
-	if (c >= 'A' && c <= 'F')
-		return (c - 'A') + 10;
-	return 0;
-}
-
-static unsigned int isapnp_parse_id(const char *id)
-{
-	if (strlen(id) != 7) {
-		printk("isapnp: wrong PnP ID\n");
-		return 0;
-	}
-	return (ISAPNP_VENDOR(id[0], id[1], id[2])<<16) |
-			(isapnp_get_hex(id[3])<<4) |
-			(isapnp_get_hex(id[4])<<0) |
-			(isapnp_get_hex(id[5])<<12) |
-			(isapnp_get_hex(id[6])<<8);
-}
-
-static int isapnp_set_card(char *line)
-{
-	int idx, idx1;
-	unsigned int id;
-	char index[16], value[32];
-
-	if (isapnp_info_card) {
-		isapnp_cfg_end();
-		isapnp_info_card = NULL;
-	}
-	line = isapnp_get_str(index, line, sizeof(index));
-	isapnp_get_str(value, line, sizeof(value));
-	idx = idx1 = simple_strtoul(index, NULL, 0);
-	id = isapnp_parse_id(value);
-	isapnp_info_card = isapnp_find_card(id >> 16, id & 0xffff, NULL);
-	while (isapnp_info_card && idx1-- > 0)
-		isapnp_info_card = isapnp_find_card(id >> 16, id & 0xffff, isapnp_info_card);
-	if (isapnp_info_card == NULL) {
-		printk("isapnp: card '%s' order %i not found\n", value, idx);
-		return 1;
-	}
-	if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
-		printk("isapnp: configuration start sequence for device '%s' failed\n", value);
-		isapnp_info_card = NULL;
-		return 1;
-	}
-	return 0;
-}
-
-static int isapnp_select_csn(char *line)
-{
-	int csn;
-	struct list_head *list;
-	char index[16], value[32];
-
-	isapnp_info_device = NULL;
-	isapnp_get_str(index, line, sizeof(index));
-	csn = simple_strtoul(index, NULL, 0);
-
-	for (list = isapnp_cards.next; list != &isapnp_cards; list = list->next) {
-		isapnp_info_card = pci_bus_b(list);
-		if (isapnp_info_card->number == csn)
-			break;
-	}
-	if (list == &isapnp_cards) {
-		printk("isapnp: cannot find CSN %i\n", csn);
-		return 1;
-	}
-	if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
-		printk("isapnp: configuration start sequence for device '%s' failed\n", value);
-		isapnp_info_card = NULL;
-		return 1;
-	}
-	return 0;
-}
-
-static int isapnp_set_device(char *line)
-{
-	int idx, idx1;
-	unsigned int id;
-	char index[16], value[32];
-
-	line = isapnp_get_str(index, line, sizeof(index));
-	isapnp_get_str(value, line, sizeof(value));
-	idx = idx1 = simple_strtoul(index, NULL, 0);
-	id = isapnp_parse_id(value);
-	isapnp_info_device = isapnp_find_dev(isapnp_info_card, id >> 16, id & 0xffff, NULL);
-	while (isapnp_info_device && idx-- > 0)
-		isapnp_info_device = isapnp_find_dev(isapnp_info_card, id >> 16, id & 0xffff, isapnp_info_device);
-	if (isapnp_info_device == NULL) {
-		printk("isapnp: device '%s' order %i not found\n", value, idx);
-		return 1;
-	}
-	isapnp_device(isapnp_info_device->devfn);
-	return 0;
-}
-
-static int isapnp_autoconfigure(void)
-{
-	isapnp_cfg_end();
-	if (isapnp_info_device->active)
-		isapnp_info_device->deactivate(isapnp_info_device);
-	if (isapnp_info_device->prepare(isapnp_info_device) < 0) {
-		printk("isapnp: cannot prepare device for the activation");
-		return 0;
-	}
-	if (isapnp_info_device->activate(isapnp_info_device) < 0) {
-		printk("isapnp: cannot activate device");
-		return 0;
-	}
-	if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
-		printk("isapnp: configuration start sequence for card %d failed\n", isapnp_info_card->number);
-		isapnp_info_card = NULL;
-		isapnp_info_device = NULL;
-		return 1;
-	}
-	isapnp_device(isapnp_info_device->devfn);
-	return 0;
-}
-
-static int isapnp_set_port(char *line)
-{
-	int idx, port;
-	char index[16], value[32];
-
-	line = isapnp_get_str(index, line, sizeof(index));
-	isapnp_get_str(value, line, sizeof(value));
-	idx = simple_strtoul(index, NULL, 0);
-	port = simple_strtoul(value, NULL, 0);
-	if (idx < 0 || idx > 7) {
-		printk("isapnp: wrong port index %i\n", idx);
-		return 1;
-	}
-	if (port < 0 || port > 0xffff) {
-		printk("isapnp: wrong port value 0x%x\n", port);
-		return 1;
-	}
-	isapnp_write_word(ISAPNP_CFG_PORT + (idx << 1), port);
-	if (!isapnp_info_device->resource[idx].flags)
-		return 0;
-	if (isapnp_info_device->resource[idx].flags & IORESOURCE_AUTO) {
-		isapnp_info_device->resource[idx].start = port;
-		isapnp_info_device->resource[idx].end += port - 1;
-		isapnp_info_device->resource[idx].flags &= ~IORESOURCE_AUTO;
-	} else {
-		isapnp_info_device->resource[idx].end -= isapnp_info_device->resource[idx].start;
-		isapnp_info_device->resource[idx].start = port;
-		isapnp_info_device->resource[idx].end += port;
-	}
-	return 0;
-}
-
-static void isapnp_set_irqresource(struct resource *res, int irq)
-{
-	res->start = res->end = irq;
-	res->flags = IORESOURCE_IRQ;
-}
- 
-static int isapnp_set_irq(char *line)
-{
-	int idx, irq;
-	char index[16], value[32];
-
-	line = isapnp_get_str(index, line, sizeof(index));
-	isapnp_get_str(value, line, sizeof(value));
-	idx = simple_strtoul(index, NULL, 0);
-	irq = simple_strtoul(value, NULL, 0);
-	if (idx < 0 || idx > 1) {
-		printk("isapnp: wrong IRQ index %i\n", idx);
-		return 1;
-	}
-	if (irq == 2)
-		irq = 9;
-	if (irq < 0 || irq > 15) {
-		printk("isapnp: wrong IRQ value %i\n", irq);
-		return 1;
-	}
-	isapnp_write_byte(ISAPNP_CFG_IRQ + (idx << 1), irq);
-	isapnp_set_irqresource(isapnp_info_device->irq_resource + idx, irq);
-	return 0;
-}
- 
-static void isapnp_set_dmaresource(struct resource *res, int dma)
-{
-	res->start = res->end = dma;
-	res->flags = IORESOURCE_DMA;
-}
-
-extern int isapnp_allow_dma0;
-static int isapnp_set_allow_dma0(char *line)
-{
-	int i;
-	char value[32];
-
-	isapnp_get_str(value, line, sizeof(value));
-	i = simple_strtoul(value, NULL, 0);
-	if (i < 0 || i > 1) {
-		printk("isapnp: wrong value %i for allow_dma0\n", i);
-		return 1;
-	}
-	isapnp_allow_dma0 = i;
-	return 0;
-}
- 
-static int isapnp_set_dma(char *line)
-{
-	int idx, dma;
-	char index[16], value[32];
-
-	line = isapnp_get_str(index, line, sizeof(index));
-	isapnp_get_str(value, line, sizeof(value));
-	idx = simple_strtoul(index, NULL, 0);
-	dma = simple_strtoul(value, NULL, 0);
-	if (idx < 0 || idx > 1) {
-		printk("isapnp: wrong DMA index %i\n", idx);
-		return 1;
-	}
-	if (dma < 0 || dma > 7) {
-		printk("isapnp: wrong DMA value %i\n", dma);
-		return 1;
-	}
-	isapnp_write_byte(ISAPNP_CFG_DMA + idx, dma);
-	isapnp_set_dmaresource(isapnp_info_device->dma_resource + idx, dma);
-	return 0;
-}
- 
-static int isapnp_set_mem(char *line)
-{
-	int idx;
-	unsigned int mem;
-	char index[16], value[32];
-
-	line = isapnp_get_str(index, line, sizeof(index));
-	isapnp_get_str(value, line, sizeof(value));
-	idx = simple_strtoul(index, NULL, 0);
-	mem = simple_strtoul(value, NULL, 0);
-	if (idx < 0 || idx > 3) {
-		printk("isapnp: wrong memory index %i\n", idx);
-		return 1;
-	}
-	mem >>= 8;
-	isapnp_write_word(ISAPNP_CFG_MEM + (idx<<2), mem & 0xffff);
-	if (!isapnp_info_device->resource[idx + 8].flags)
-		return 0;
-	if (isapnp_info_device->resource[idx + 8].flags & IORESOURCE_AUTO) {
-		isapnp_info_device->resource[idx + 8].start = mem & ~0x00ffff00;
-		isapnp_info_device->resource[idx + 8].end += (mem & ~0x00ffff00) - 1;
-		isapnp_info_device->resource[idx + 8].flags &= ~IORESOURCE_AUTO;
-	} else {
-		isapnp_info_device->resource[idx + 8].end -= isapnp_info_device->resource[idx + 8].start;
-		isapnp_info_device->resource[idx + 8].start = mem & ~0x00ffff00;
-		isapnp_info_device->resource[idx + 8].end += mem & ~0x00ffff00;
-	}
-	return 0;
-}
- 
-static int isapnp_poke(char *line, int what)
-{
-	int reg;
-	unsigned int val;
-	char index[16], value[32];
-
-	line = isapnp_get_str(index, line, sizeof(index));
-	isapnp_get_str(value, line, sizeof(value));
-	reg = simple_strtoul(index, NULL, 0);
-	val = simple_strtoul(value, NULL, 0);
-	if (reg < 0 || reg > 127) {
-		printk("isapnp: wrong register %i\n", reg);
-		return 1;
-	}
-	switch (what) {
-	case 1:
-		isapnp_write_word(reg, val);
-		break;
-	case 2:
-		isapnp_write_dword(reg, val);
-		break;
-	default:
-		isapnp_write_byte(reg, val);
-		break;
-	}
-	return 0;
-}
- 
-static int isapnp_decode_line(char *line)
-{
-	char cmd[32];
-
-	line = isapnp_get_str(cmd, line, sizeof(cmd));
-	if (!strcmp(cmd, "allow_dma0"))
-		return isapnp_set_allow_dma0(line);
-	if (!strcmp(cmd, "card"))
-		return isapnp_set_card(line);
-	if (!strcmp(cmd, "csn"))
-		return isapnp_select_csn(line);
-	if (!isapnp_info_card) {
-		printk("isapnp: card is not selected\n");
-		return 1;
-	}
-	if (!strncmp(cmd, "dev", 3))
-		return isapnp_set_device(line);
-	if (!isapnp_info_device) {
-		printk("isapnp: device is not selected\n");
-		return 1;
-	}
-	if (!strncmp(cmd, "auto", 4))
-		return isapnp_autoconfigure();
-	if (!strncmp(cmd, "act", 3)) {
-		isapnp_activate(isapnp_info_device->devfn);
-		isapnp_info_device->active = 1;
-		return 0;
-	}
-	if (!strncmp(cmd, "deact", 5)) {
-		isapnp_deactivate(isapnp_info_device->devfn);
-		isapnp_info_device->active = 0;
-		return 0;
-	}
-	if (!strcmp(cmd, "port"))
-		return isapnp_set_port(line);
-	if (!strcmp(cmd, "irq"))
-		return isapnp_set_irq(line);
-	if (!strcmp(cmd, "dma"))
-		return isapnp_set_dma(line);
-	if (!strncmp(cmd, "mem", 3))
-		return isapnp_set_mem(line);
-	if (!strcmp(cmd, "poke"))
-		return isapnp_poke(line, 0);
-	if (!strcmp(cmd, "pokew"))
-		return isapnp_poke(line, 1);
-	if (!strcmp(cmd, "poked"))
-		return isapnp_poke(line, 2);
-	printk("isapnp: wrong command '%s'\n", cmd);
-	return 1;
-}
-
-/*
- *  Main write routine
- */
-
-static void isapnp_info_write(isapnp_info_buffer_t *buffer)
-{
-	int c, idx, idx1 = 0;
-	char line[128];
-
-	if (buffer->size <= 0)
-		return;
-	isapnp_info_card = NULL;
-	isapnp_info_device = NULL;
-	for (idx = 0; idx < buffer->size; idx++) {
-		c = buffer->buffer[idx];
-		if (c == '\n') {
-			line[idx1] = '\0';
-			if (line[0] != '#') {
-				if (isapnp_decode_line(line))
-					goto __end;
-			}
-			idx1 = 0;
-			continue;
-		}
-		if (idx1 >= sizeof(line)-1) {
-			printk("isapnp: line too long, aborting\n");
-			return;
-		}
-		line[idx1++] = c;
-	}
-      __end:
-	if (isapnp_info_card)
-		isapnp_cfg_end();
-}
diff -Nru a/drivers/pnp/names.c b/drivers/pnp/names.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/names.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,51 @@
+/*
+ * names.c - a very simple name database for PnP devices
+ *
+ * Some code is based on names.c from linux pci
+ * Copyright 1993--1999 Drew Eckhardt, Frederic Potter,
+ * David Mosberger-Tang, Martin Mares
+ *
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/pnp.h>
+
+#include "base.h"
+
+#ifdef CONFIG_PNP_NAMES
+
+static char *pnp_id_eisaid[] = {
+#define ID(x,y) x,
+#include "idlist.h"
+};
+
+static char *pnp_id_names[] = {
+#define ID(x,y) y,
+#include "idlist.h"
+};
+
+void
+pnp_name_device(struct pnp_dev *dev)
+{
+	int i;
+	char *name = dev->name;
+	for(i=0; i<sizeof(pnp_id_eisaid)/sizeof(pnp_id_eisaid[0]); i++){
+		if (compare_pnp_id(&dev->ids,pnp_id_eisaid[i])){
+			sprintf(name, "%s", pnp_id_names[i]);
+			return;
+		}
+	}
+	return;
+}
+
+#else
+
+void
+pnp_name_device(struct pnp_dev *dev)
+{
+	return;
+}
+
+#endif /* CONFIG_PNP_NAMES */
diff -Nru a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/pnpbios/Makefile	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel PNPBIOS driver.
+#
+
+export-objs := core.o
+
+pnpbios-proc-$(CONFIG_PROC_FS) = proc.o
+
+obj-y := core.o $(pnpbios-proc-y)
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/pnpbios/core.c	Fri Oct 18 21:03:03 2002
@@ -0,0 +1,1572 @@
+/*
+ * pnpbios -- PnP BIOS driver
+ *
+ * This driver provides access to Plug-'n'-Play services provided by
+ * the PnP BIOS firmware, described in the following documents:
+ *   Plug and Play BIOS Specification, Version 1.0A, 5 May 1994
+ *   Plug and Play BIOS Clarification Paper, 6 October 1994
+ *     Compaq Computer Corporation, Phoenix Technologies Ltd., Intel Corp.
+ * 
+ * Originally (C) 1998 Christian Schmidt <schmidt@digadd.de>
+ * Modifications (C) 1998 Tom Lees <tom@lpsg.demon.co.uk>
+ * Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
+ * Further modifications (C) 2001, 2002 by:
+ *   Alan Cox <alan@redhat.com>
+ *   Thomas Hood <jdthood@mail.com>
+ *   Brian Gerst <bgerst@didntduck.org>
+ *
+ * Ported to the PnP Layer and several additional improvements (C) 2002
+ * by Adam Belay <ambx1@neo.rr.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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/pnpbios.h>
+#include <linux/device.h>
+#include <linux/pnp.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <asm/desc.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/kmod.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+
+
+/*
+ *
+ * PnP BIOS INTERFACE
+ *
+ */
+
+/* PnP BIOS signature: "$PnP" */
+#define PNP_SIGNATURE   (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
+
+#pragma pack(1)
+union pnp_bios_expansion_header {
+	struct {
+		u32 signature;    /* "$PnP" */
+		u8 version;	  /* in BCD */
+		u8 length;	  /* length in bytes, currently 21h */
+		u16 control;	  /* system capabilities */
+		u8 checksum;	  /* all bytes must add up to 0 */
+
+		u32 eventflag;    /* phys. address of the event flag */
+		u16 rmoffset;     /* real mode entry point */
+		u16 rmcseg;
+		u16 pm16offset;   /* 16 bit protected mode entry */
+		u32 pm16cseg;
+		u32 deviceID;	  /* EISA encoded system ID or 0 */
+		u16 rmdseg;	  /* real mode data segment */
+		u32 pm16dseg;	  /* 16 bit pm data segment base */
+	} fields;
+	char chars[0x21];	  /* To calculate the checksum */
+};
+#pragma pack()
+
+static struct {
+	u16	offset;
+	u16	segment;
+} pnp_bios_callpoint;
+
+static union pnp_bios_expansion_header * pnp_bios_hdr = NULL;
+
+/* The PnP BIOS entries in the GDT */
+#define PNP_GDT    (GDT_ENTRY_PNPBIOS_BASE * 8)
+
+#define PNP_CS32   (PNP_GDT+0x00)	/* segment for calling fn */
+#define PNP_CS16   (PNP_GDT+0x08)	/* code segment for BIOS */
+#define PNP_DS     (PNP_GDT+0x10)	/* data segment for BIOS */
+#define PNP_TS1    (PNP_GDT+0x18)	/* transfer data segment */
+#define PNP_TS2    (PNP_GDT+0x20)	/* another data segment */
+
+/* 
+ * These are some opcodes for a "static asmlinkage"
+ * As this code is *not* executed inside the linux kernel segment, but in a
+ * alias at offset 0, we need a far return that can not be compiled by
+ * default (please, prove me wrong! this is *really* ugly!) 
+ * This is the only way to get the bios to return into the kernel code,
+ * because the bios code runs in 16 bit protected mode and therefore can only
+ * return to the caller if the call is within the first 64kB, and the linux
+ * kernel begins at offset 3GB...
+ */
+
+asmlinkage void pnp_bios_callfunc(void);
+
+__asm__(
+	".text			\n"
+	__ALIGN_STR "\n"
+	"pnp_bios_callfunc:\n"
+	"	pushl %edx	\n"
+	"	pushl %ecx	\n"
+	"	pushl %ebx	\n"
+	"	pushl %eax	\n"
+	"	lcallw *pnp_bios_callpoint\n"
+	"	addl $16, %esp	\n"
+	"	lret		\n"
+	".previous		\n"
+);
+
+#define Q_SET_SEL(cpu, selname, address, size) \
+do { \
+set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
+set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+} while(0)
+
+#define Q2_SET_SEL(cpu, selname, address, size) \
+do { \
+set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
+set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+} while(0)
+
+/*
+ * At some point we want to use this stack frame pointer to unwind
+ * after PnP BIOS oopses. 
+ */
+ 
+u32 pnp_bios_fault_esp;
+u32 pnp_bios_fault_eip;
+u32 pnp_bios_is_utter_crap = 0;
+
+static spinlock_t pnp_bios_lock;
+
+static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
+				u16 arg4, u16 arg5, u16 arg6, u16 arg7,
+				void *ts1_base, u32 ts1_size,
+				void *ts2_base, u32 ts2_size)
+{
+	unsigned long flags;
+	u16 status;
+
+	/*
+	 * PnP BIOSes are generally not terribly re-entrant.
+	 * Also, don't rely on them to save everything correctly.
+	 */
+	if(pnp_bios_is_utter_crap)
+		return PNP_FUNCTION_NOT_SUPPORTED;
+
+	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
+	spin_lock_irqsave(&pnp_bios_lock, flags);
+
+	/* The lock prevents us bouncing CPU here */
+	if (ts1_size)
+		Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
+	if (ts2_size)
+		Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
+
+	__asm__ __volatile__(
+	        "pushl %%ebp\n\t"
+		"pushl %%edi\n\t"
+		"pushl %%esi\n\t"
+		"pushl %%ds\n\t"
+		"pushl %%es\n\t"
+		"pushl %%fs\n\t"
+		"pushl %%gs\n\t"
+		"pushfl\n\t"
+		"movl %%esp, pnp_bios_fault_esp\n\t"
+		"movl $1f, pnp_bios_fault_eip\n\t"
+		"lcall %5,%6\n\t"
+		"1:popfl\n\t"
+		"popl %%gs\n\t"
+		"popl %%fs\n\t"
+		"popl %%es\n\t"
+		"popl %%ds\n\t"
+	        "popl %%esi\n\t"
+		"popl %%edi\n\t"
+		"popl %%ebp\n\t"
+		: "=a" (status)
+		: "0" ((func) | (((u32)arg1) << 16)),
+		  "b" ((arg2) | (((u32)arg3) << 16)),
+		  "c" ((arg4) | (((u32)arg5) << 16)),
+		  "d" ((arg6) | (((u32)arg7) << 16)),
+		  "i" (PNP_CS32),
+		  "i" (0)
+		: "memory"
+	);
+	spin_unlock_irqrestore(&pnp_bios_lock, flags);
+	
+	/* If we get here and this is set then the PnP BIOS faulted on us. */
+	if(pnp_bios_is_utter_crap)
+	{
+		printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
+		printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"nobiospnp\" option to operate stably\n");
+		printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n");
+	}
+
+	return status;
+}
+
+
+/*
+ *
+ * UTILITY FUNCTIONS
+ *
+ */
+
+static void pnpbios_warn_unexpected_status(const char * module, u16 status)
+{
+	printk(KERN_ERR "PnPBIOS: %s: Unexpected status 0x%x\n", module, status);
+}
+
+void *pnpbios_kmalloc(size_t size, int f)
+{
+	void *p = kmalloc( size, f );
+	if ( p == NULL )
+		printk(KERN_ERR "PnPBIOS: kmalloc() failed\n");
+	return p;
+}
+
+/*
+ * Call this only after init time
+ */
+static int pnp_bios_present(void)
+{
+	return (pnp_bios_hdr != NULL);
+}
+
+
+/*
+ *
+ * PnP BIOS ACCESS FUNCTIONS
+ *
+ */
+
+#define PNP_GET_NUM_SYS_DEV_NODES       0x00
+#define PNP_GET_SYS_DEV_NODE            0x01
+#define PNP_SET_SYS_DEV_NODE            0x02
+#define PNP_GET_EVENT                   0x03
+#define PNP_SEND_MESSAGE                0x04
+#define PNP_GET_DOCKING_STATION_INFORMATION 0x05
+#define PNP_SET_STATIC_ALLOCED_RES_INFO 0x09
+#define PNP_GET_STATIC_ALLOCED_RES_INFO 0x0a
+#define PNP_GET_APM_ID_TABLE            0x0b
+#define PNP_GET_PNP_ISA_CONFIG_STRUC    0x40
+#define PNP_GET_ESCD_INFO               0x41
+#define PNP_READ_ESCD                   0x42
+#define PNP_WRITE_ESCD                  0x43
+
+/*
+ * Call PnP BIOS with function 0x00, "get number of system device nodes"
+ */
+static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0,
+			       data, sizeof(struct pnp_dev_node_info), 0, 0);
+	data->no_nodes &= 0xff;
+	return status;
+}
+
+int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
+{
+	int status = __pnp_bios_dev_node_info( data );
+	if ( status )
+		pnpbios_warn_unexpected_status( "dev_node_info", status );
+	return status;
+}
+
+/*
+ * Note that some PnP BIOSes (e.g., on Sony Vaio laptops) die a horrible
+ * death if they are asked to access the "current" configuration.
+ * Therefore, if it's a matter of indifference, it's better to call
+ * get_dev_node() and set_dev_node() with boot=1 rather than with boot=0.
+ */
+
+/* 
+ * Call PnP BIOS with function 0x01, "get system device node"
+ * Input: *nodenum = desired node, 
+ *        boot = whether to get nonvolatile boot (!=0)
+ *               or volatile current (0) config
+ * Output: *nodenum=next node or 0xff if no more nodes
+ */
+static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	if ( !boot & pnpbios_dont_use_current_config )
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
+			       nodenum, sizeof(char), data, 65536);
+	return status;
+}
+
+int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
+{
+	int status;
+	status =  __pnp_bios_get_dev_node( nodenum, boot, data );
+	if ( status )
+		pnpbios_warn_unexpected_status( "get_dev_node", status );
+	return status;
+}
+
+
+/*
+ * Call PnP BIOS with function 0x02, "set system device node"
+ * Input: *nodenum = desired node, 
+ *        boot = whether to set nonvolatile boot (!=0)
+ *               or volatile current (0) config
+ */
+static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	if ( !boot & pnpbios_dont_use_current_config )
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0,
+			       data, 65536, 0, 0);
+	return status;
+}
+
+int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
+{
+	int status;
+	status =  __pnp_bios_set_dev_node( nodenum, boot, data );
+	if ( status ) {
+		pnpbios_warn_unexpected_status( "set_dev_node", status );
+		return status;
+	}
+	if ( !boot ) { /* Update devlist */
+		status =  pnp_bios_get_dev_node( &nodenum, boot, data );
+		if ( status )
+			return status;
+	}
+	return status;
+}
+
+#if needed
+/*
+ * Call PnP BIOS with function 0x03, "get event"
+ */
+static int pnp_bios_get_event(u16 *event)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
+			       event, sizeof(u16), 0, 0);
+	return status;
+}
+#endif
+
+#if needed
+/* 
+ * Call PnP BIOS with function 0x04, "send message"
+ */
+static int pnp_bios_send_message(u16 message)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	return status;
+}
+#endif
+
+#ifdef CONFIG_HOTPLUG
+/*
+ * Call PnP BIOS with function 0x05, "get docking station information"
+ */
+static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       data, sizeof(struct pnp_docking_station_info), 0, 0);
+	return status;
+}
+#endif
+
+#if needed
+/*
+ * Call PnP BIOS with function 0x09, "set statically allocated resource
+ * information"
+ */
+static int pnp_bios_set_stat_res(char *info)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       info, *((u16 *) info), 0, 0);
+	return status;
+}
+#endif
+
+/*
+ * Call PnP BIOS with function 0x0a, "get statically allocated resource
+ * information"
+ */
+static int __pnp_bios_get_stat_res(char *info)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       info, 65536, 0, 0);
+	return status;
+}
+
+int pnp_bios_get_stat_res(char *info)
+{
+	int status;
+	status = __pnp_bios_get_stat_res( info );
+	if ( status )
+		pnpbios_warn_unexpected_status( "get_stat_res", status );
+	return status;
+}
+
+#if needed
+/*
+ * Call PnP BIOS with function 0x0b, "get APM id table"
+ */
+static int pnp_bios_apm_id_table(char *table, u16 *size)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0,
+			       table, *size, size, sizeof(u16));
+	return status;
+}
+#endif
+
+/*
+ * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
+ */
+static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       data, sizeof(struct pnp_isa_config_struc), 0, 0);
+	return status;
+}
+
+int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
+{
+	int status;
+	status = __pnp_bios_isapnp_config( data );
+	if ( status )
+		pnpbios_warn_unexpected_status( "isapnp_config", status );
+	return status;
+}
+
+/*
+ * Call PnP BIOS with function 0x41, "get ESCD info"
+ */
+static int __pnp_bios_escd_info(struct escd_info_struc *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return ESCD_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS,
+			       data, sizeof(struct escd_info_struc), 0, 0);
+	return status;
+}
+
+int pnp_bios_escd_info(struct escd_info_struc *data)
+{
+	int status;
+	status = __pnp_bios_escd_info( data );
+	if ( status )
+		pnpbios_warn_unexpected_status( "escd_info", status );
+	return status;
+}
+
+/*
+ * Call PnP BIOS function 0x42, "read ESCD"
+ * nvram_base is determined by calling escd_info
+ */
+static int __pnp_bios_read_escd(char *data, u32 nvram_base)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return ESCD_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
+			       data, 65536, (void *)nvram_base, 65536);
+	return status;
+}
+
+int pnp_bios_read_escd(char *data, u32 nvram_base)
+{
+	int status;
+	status = __pnp_bios_read_escd( data, nvram_base );
+	if ( status )
+		pnpbios_warn_unexpected_status( "read_escd", status );
+	return status;
+}
+
+#if needed
+/*
+ * Call PnP BIOS function 0x43, "write ESCD"
+ */
+static int pnp_bios_write_escd(char *data, u32 nvram_base)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return ESCD_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
+			       data, 65536, nvram_base, 65536);
+	return status;
+}
+#endif
+
+
+/*
+ *
+ * DOCKING FUNCTIONS
+ *
+ */
+
+#ifdef CONFIG_HOTPLUG
+
+static int unloading = 0;
+static struct completion unload_sem;
+
+/*
+ * (Much of this belongs in a shared routine somewhere)
+ */
+ 
+static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
+{
+	char *argv [3], **envp, *buf, *scratch;
+	int i = 0, value;
+
+	if (!hotplug_path [0])
+		return -ENOENT;
+	if (!current->fs->root) {
+		return -EAGAIN;
+	}
+	if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
+		return -ENOMEM;
+	}
+	if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) {
+		kfree (envp);
+		return -ENOMEM;
+	}
+
+	/* only one standardized param to hotplug command: type */
+	argv [0] = hotplug_path;
+	argv [1] = "dock";
+	argv [2] = 0;
+
+	/* minimal command environment */
+	envp [i++] = "HOME=/";
+	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+#ifdef	DEBUG
+	/* hint that policy agent should enter no-stdout debug mode */
+	envp [i++] = "DEBUG=kernel";
+#endif
+	/* extensible set of named bus-specific parameters,
+	 * supporting multiple driver selection algorithms.
+	 */
+	scratch = buf;
+
+	/* action:  add, remove */
+	envp [i++] = scratch;
+	scratch += sprintf (scratch, "ACTION=%s", dock?"add":"remove") + 1;
+
+	/* Report the ident for the dock */
+	envp [i++] = scratch;
+	scratch += sprintf (scratch, "DOCK=%x/%x/%x",
+		info->location_id, info->serial, info->capabilities);
+	envp[i] = 0;
+	
+	value = call_usermodehelper (argv [0], argv, envp);
+	kfree (buf);
+	kfree (envp);
+	return 0;
+}
+
+/*
+ * Poll the PnP docking at regular intervals
+ */
+static int pnp_dock_thread(void * unused)
+{
+	static struct pnp_docking_station_info now;
+	int docked = -1, d = 0;
+	daemonize();
+	strcpy(current->comm, "kpnpbiosd");
+	while(!unloading && !signal_pending(current))
+	{
+		int status;
+		
+		/*
+		 * Poll every 2 seconds
+		 */
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ*2);
+		if(signal_pending(current))
+			break;
+
+		status = pnp_bios_dock_station_info(&now);
+
+		switch(status)
+		{
+			/*
+			 * No dock to manage
+			 */
+			case PNP_FUNCTION_NOT_SUPPORTED:
+				complete_and_exit(&unload_sem, 0);
+			case PNP_SYSTEM_NOT_DOCKED:
+				d = 0;
+				break;
+			case PNP_SUCCESS:
+				d = 1;
+				break;
+			default:
+				pnpbios_warn_unexpected_status( "pnp_dock_thread", status );
+				continue;
+		}
+		if(d != docked)
+		{
+			if(pnp_dock_event(d, &now)==0)
+			{
+				docked = d;
+#if 0
+				printk(KERN_INFO "PnPBIOS: Docking station %stached\n", docked?"at":"de");
+#endif
+			}
+		}
+	}
+	complete_and_exit(&unload_sem, 0);
+}
+
+#endif   /* CONFIG_HOTPLUG */
+
+
+/* pnp current resource reading functions */
+
+
+static void add_irqresource(struct pnp_dev *dev, int irq)
+{
+	int i = 0;
+	while (!(dev->irq_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_IRQ) i++;
+	if (i < DEVICE_COUNT_IRQ) {
+		dev->irq_resource[i].start = (unsigned long) irq;
+		dev->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
+	}
+}
+
+static void add_dmaresource(struct pnp_dev *dev, int dma)
+{
+	int i = 8;
+	while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++;
+	if (i < DEVICE_COUNT_DMA) {
+		dev->dma_resource[i].start = (unsigned long) dma;
+		dev->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
+	}
+}
+
+static void add_ioresource(struct pnp_dev *dev, int io, int len)
+{
+	int i = 0;
+	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
+	if (i < DEVICE_COUNT_RESOURCE) {
+		dev->resource[i].start = (unsigned long) io;
+		dev->resource[i].end = (unsigned long)(io + len - 1);
+		dev->resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+	}
+}
+
+static void add_memresource(struct pnp_dev *dev, int mem, int len)
+{
+	int i = 0;
+	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
+	if (i < DEVICE_COUNT_RESOURCE) {
+		dev->resource[i].start = (unsigned long) mem;
+		dev->resource[i].end = (unsigned long)(mem + len - 1);
+		dev->resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
+	}
+}
+
+static unsigned char *node_current_resource_data_to_dev(struct pnp_bios_node *node, struct pnp_dev *dev)
+{
+	unsigned char *p = node->data, *lastp=NULL;
+	int i;
+
+	/*
+	 * First, set resource info to default values
+	 */
+	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
+		dev->resource[i].start = 0;  // "disabled"
+		dev->resource[i].flags = IORESOURCE_UNSET;
+	}
+	for (i=0;i<DEVICE_COUNT_IRQ;i++) {
+		dev->irq_resource[i].start = (unsigned long)-1;  // "disabled"
+		dev->irq_resource[i].flags = IORESOURCE_UNSET;
+	}
+	for (i=0;i<DEVICE_COUNT_DMA;i++) {
+		dev->dma_resource[i].start = (unsigned long)-1;  // "disabled"
+		dev->dma_resource[i].flags = IORESOURCE_UNSET;
+	}
+
+	/*
+	 * Fill in dev resource info
+	 */
+        while ( (char *)p < ((char *)node->data + node->size )) {
+        	if(p==lastp) break;
+
+                if( p[0] & 0x80 ) {// large item
+			switch (p[0] & 0x7f) {
+			case 0x01: // memory
+			{
+				int io = *(short *) &p[4];
+				int len = *(short *) &p[10];
+				add_memresource(dev, io, len);
+				break;
+			}
+			case 0x02: // device name
+			{
+				int len = *(short *) &p[1];
+				memcpy(dev->name, p + 3, len >= 80 ? 79 : len);
+				break;
+			}
+			case 0x05: // 32-bit memory
+			{
+				int io = *(int *) &p[4];
+				int len = *(int *) &p[16];
+				add_memresource(dev, io, len);
+				break;
+			}
+			case 0x06: // fixed location 32-bit memory
+			{
+				int io = *(int *) &p[4];
+				int len = *(int *) &p[8];
+				add_memresource(dev, io, len);
+				break;
+			}
+			} /* switch */
+                        lastp = p+3;
+                        p = p + p[1] + p[2]*256 + 3;
+                        continue;
+                }
+                if ((p[0]>>3) == 0x0f){ // end tag
+			p = p + 2;
+			goto end;
+                        break;
+			}
+                switch (p[0]>>3) {
+                case 0x04: // irq
+                {
+                        int i, mask, irq = -1;
+                        mask= p[1] + p[2]*256;
+                        for (i=0;i<16;i++, mask=mask>>1)
+                                if(mask & 0x01) irq=i;
+			add_irqresource(dev, irq);
+                        break;
+                }
+                case 0x05: // dma
+                {
+                        int i, mask, dma = -1;
+                        mask = p[1];
+                        for (i=0;i<8;i++, mask = mask>>1)
+                                if(mask & 0x01) dma=i;
+			add_dmaresource(dev, dma);
+                        break;
+                }
+                case 0x08: // io
+                {
+			int io= p[2] + p[3] *256;
+			int len = p[7];
+			add_ioresource(dev, io, len);
+                        break;
+                }
+		case 0x09: // fixed location io
+		{
+			int io = p[1] + p[2] * 256;
+			int len = p[3];
+			add_ioresource(dev, io, len);
+			break;
+		}
+                } /* switch */
+                lastp=p+1;
+                p = p + (p[0] & 0x07) + 1;
+
+        } /* while */
+	end:
+	if ((dev->resource[0].start == 0) &&
+	    (dev->irq_resource[0].start == -1) &&
+	    (dev->dma_resource[0].start == -1))
+		dev->active = 0;
+	else
+		dev->active = 1;
+        return (unsigned char *)p;
+}
+
+
+/* pnp possible resource reading functions */
+
+static void read_lgtag_mem(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_mem * mem;
+	mem = pnpbios_kmalloc(sizeof(struct pnp_mem),GFP_KERNEL);
+	if (!mem)
+		return;
+	memset(mem,0,sizeof(struct pnp_mem));
+	mem->min = ((p[3] << 8) | p[2]) << 8;
+	mem->max = ((p[5] << 8) | p[4]) << 8;
+	mem->align = (p[7] << 8) | p[6];
+	mem->size = ((p[9] << 8) | p[8]) << 8;
+	mem->flags = p[1];
+	pnp_add_mem_resource(dev,depnum,mem);
+	return;
+}
+
+static void read_lgtag_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_mem32 * mem;
+	mem = pnpbios_kmalloc(sizeof(struct pnp_mem32),GFP_KERNEL);
+	if (!mem)
+		return;
+	memset(mem,0,sizeof(struct pnp_mem32));
+	memcpy(mem->data, p, 17);
+	pnp_add_mem32_resource(dev,depnum,mem);
+	return;
+}
+
+static void read_lgtag_fmem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_mem32 * mem;
+	mem = pnpbios_kmalloc(sizeof(struct pnp_mem32),GFP_KERNEL);
+	if (!mem)
+		return;
+	memset(mem,0,sizeof(struct pnp_mem32));
+	memcpy(mem->data, p, 17);
+	pnp_add_mem32_resource(dev,depnum,mem);
+	return;
+}
+
+static void read_smtag_irq(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_irq * irq;
+	irq = pnpbios_kmalloc(sizeof(struct pnp_irq),GFP_KERNEL);
+	if (!irq)
+		return;
+	memset(irq,0,sizeof(struct pnp_irq));
+	irq->map = (p[2] << 8) | p[1];
+	if (size > 2)
+		irq->flags = p[3];
+	pnp_add_irq_resource(dev,depnum,irq);
+	return;
+}
+
+static void read_smtag_dma(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_dma * dma;
+	dma = pnpbios_kmalloc(sizeof(struct pnp_dma),GFP_KERNEL);
+	if (!dma)
+		return;
+	memset(dma,0,sizeof(struct pnp_dma));
+	dma->map = p[1];
+	dma->flags = p[2];
+	pnp_add_dma_resource(dev,depnum,dma);
+	return;
+}
+
+static void read_smtag_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_port * port;
+	port = pnpbios_kmalloc(sizeof(struct pnp_port),GFP_KERNEL);
+	if (!port)
+		return;
+	memset(port,0,sizeof(struct pnp_port));
+	port->min = (p[3] << 8) | p[2];
+	port->max = (p[5] << 8) | p[4];
+	port->align = p[6];
+	port->size = p[7];
+	port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
+	pnp_add_port_resource(dev,depnum,port);
+	return;
+}
+
+static void read_smtag_fport(unsigned char *p, int size, int depnum, struct pnp_dev *dev)
+{
+	struct pnp_port * port;
+	port = pnpbios_kmalloc(sizeof(struct pnp_port),GFP_KERNEL);
+	if (!port)
+		return;
+	memset(port,0,sizeof(struct pnp_port));
+	port->min = port->max = (p[2] << 8) | p[1];
+	port->size = p[3];
+	port->align = 0;
+	port->flags = PNP_PORT_FLAG_FIXED;
+	pnp_add_port_resource(dev,depnum,port);
+	return;
+}
+
+static unsigned char *node_possible_resource_data_to_dev(unsigned char *p, struct pnp_bios_node *node, struct pnp_dev *dev)
+{
+	unsigned char *lastp = NULL;
+	int len, depnum, dependent;
+
+	if ((char *)p == NULL)
+		return NULL;
+	if (pnp_build_resource(dev, 0) == NULL)
+		return NULL;
+	depnum = 0; /*this is the first so it should be 0 */
+	dependent = 0;
+        while ( (char *)p < ((char *)node->data + node->size )) {
+
+                if( p[0] & 0x80 ) {// large item
+			len = (p[2] << 8) | p[1];
+			switch (p[0] & 0x7f) {
+			case 0x01: // memory
+			{
+				if (len != 9)
+					goto __skip;
+				read_lgtag_mem(p,len,depnum,dev);
+				break;
+			}
+			case 0x05: // 32-bit memory
+			{
+				if (len != 17)
+					goto __skip;
+				read_lgtag_mem32(p,len,depnum,dev);
+				break;
+			}
+			case 0x06: // fixed location 32-bit memory
+			{
+				if (len != 17)
+					goto __skip;
+				read_lgtag_fmem32(p,len,depnum,dev);
+				break;
+			}
+			} /* switch */
+                        lastp = p+3;
+                        p = p + p[1] + p[2]*256 + 3;
+                        continue;
+                }
+		len = p[0] & 0x07;
+                switch ((p[0]>>3) & 0x0f) {
+		case 0x0f:
+		{
+			p = p + 2;
+        		return (unsigned char *)p;
+			break;
+		}
+                case 0x04: // irq
+                {
+			if (len < 2 || len > 3)
+				goto __skip;
+			read_smtag_irq(p,len,depnum,dev);
+			break;
+                }
+                case 0x05: // dma
+                {
+			if (len != 2)
+				goto __skip;
+			read_smtag_dma(p,len,depnum,dev);
+                        break;
+                }
+                case 0x06: // start dep
+                {
+			if (len > 1)
+				goto __skip;
+			dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
+			if (len > 0)
+				dependent = 0x100 | p[1];
+			pnp_build_resource(dev,dependent);
+			depnum = pnp_get_max_depnum(dev);
+                        break;
+                }
+                case 0x07: // end dep
+                {
+			if (len != 0)
+				goto __skip;
+			depnum = 0;
+                        break;
+                }
+                case 0x08: // io
+                {
+			if (len != 7)
+				goto __skip;
+			read_smtag_port(p,len,depnum,dev);
+                        break;
+                }
+		case 0x09: // fixed location io
+		{
+			if (len != 3)
+				goto __skip;
+			read_smtag_fport(p,len,depnum,dev);
+			break;
+		}
+                } /* switch */
+		__skip:
+                p += len + 1;
+
+        } /* while */
+
+        return NULL;
+}
+
+
+/* pnp resource writing functions */
+
+static void write_lgtag_mem(unsigned char *p, int size, struct pnp_mem *mem)
+{
+	if (!mem)
+		return;
+	p[2] = (mem->min >> 8) & 0xff;
+	p[3] = ((mem->min >> 8) >> 8) & 0xff;
+	p[4] = (mem->max >> 8) & 0xff;
+	p[5] = ((mem->max >> 8) >> 8) & 0xff;
+	p[6] = mem->align & 0xff;
+	p[7] = (mem->align >> 8) & 0xff;
+	p[8] = (mem->size >> 8) & 0xff;
+	p[9] = ((mem->size >> 8) >> 8) & 0xff;
+	p[1] = mem->flags & 0xff;
+	return;
+}
+
+static void write_smtag_irq(unsigned char *p, int size, struct pnp_irq *irq)
+{
+	if (!irq)
+		return;
+	p[1] = irq->map & 0xff;
+	p[2] = (irq->map >> 8) & 0xff;
+	if (size > 2)
+		p[3] = irq->flags & 0xff;
+	return;
+}
+
+static void write_smtag_dma(unsigned char *p, int size, struct pnp_dma *dma)
+{
+	if (!dma)
+		return;
+	p[1] = dma->map & 0xff;
+	p[2] = dma->flags & 0xff;
+	return;
+}
+
+static void write_smtag_port(unsigned char *p, int size, struct pnp_port *port)
+{
+	if (!port)
+		return;
+	p[2] = port->min & 0xff;
+	p[3] = (port->min >> 8) & 0xff;
+	p[4] = port->max & 0xff;
+	p[5] = (port->max >> 8) & 0xff;
+	p[6] = port->align & 0xff;
+	p[7] = port->size & 0xff;
+	p[1] = port->flags & 0xff;
+	return;
+}
+
+static void write_smtag_fport(unsigned char *p, int size, struct pnp_port *port)
+{
+	if (!port)
+		return;
+	p[1] = port->min & 0xff;
+	p[2] = (port->min >> 8) & 0xff;
+	p[3] = port->size & 0xff;
+	return;
+}
+
+static int node_set_resources(struct pnp_bios_node *node, struct pnp_cfg *config)
+{
+	int error = 0;
+	unsigned char *p = (char *)node->data, *lastp = NULL;
+	int len, port = 0, irq = 0, dma = 0, mem = 0;
+
+	if (!node)
+		return -EINVAL;
+	if ((char *)p == NULL)
+		return -EINVAL;
+        while ( (char *)p < ((char *)node->data + node->size )) {
+
+                if( p[0] & 0x80 ) {// large item
+			len = (p[2] << 8) | p[1];
+			switch (p[0] & 0x7f) {
+			case 0x01: // memory
+			{
+				if (len != 9)
+					goto __skip;
+				write_lgtag_mem(p,len,config->mem[mem]);
+				mem++;
+				break;
+			}
+			case 0x05: // 32-bit memory
+			{
+				if (len != 17)
+					goto __skip;
+				/* FIXME */
+				break;
+			}
+			case 0x06: // fixed location 32-bit memory
+			{
+				if (len != 17)
+					goto __skip;
+				/* FIXME */
+				break;
+			}
+			} /* switch */
+                        lastp = p+3;
+                        p = p + p[1] + p[2]*256 + 3;
+                        continue;
+                }
+		len = p[0] & 0x07;
+                switch ((p[0]>>3) & 0x0f) {
+		case 0x0f:
+		{
+        		goto done;
+			break;
+		}
+                case 0x04: // irq
+                {
+			if (len < 2 || len > 3)
+				goto __skip;
+			write_smtag_irq(p,len,config->irq[irq]);
+			irq++;
+			break;
+                }
+                case 0x05: // dma
+                {
+			if (len != 2)
+				goto __skip;
+			write_smtag_dma(p,len,config->dma[dma]);
+			dma++;
+                        break;
+                }
+                case 0x08: // io
+                {
+			if (len != 7)
+				goto __skip;
+			write_smtag_port(p,len,config->port[port]);
+			port++;
+                        break;
+                }
+		case 0x09: // fixed location io
+		{
+			if (len != 3)
+				goto __skip;
+			write_smtag_fport(p,len,config->port[port]);
+			port++;
+			break;
+		}
+                } /* switch */
+		__skip:
+                p += len + 1;
+
+        } /* while */
+
+	/* we never got an end tag so this data is corrupt or invalid */
+	return -EINVAL;
+
+	done:
+	error = pnp_bios_set_dev_node(node->handle, (char)0, node);
+        return error;
+}
+
+static int pnpbios_get_resources(struct pnp_dev *dev)
+{
+	struct pnp_dev_node_info node_info;
+	u8 nodenum = dev->number;
+	struct pnp_bios_node * node;
+	if (pnp_bios_dev_node_info(&node_info) != 0)
+		return -ENODEV;
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node)
+		return -1;
+	if (pnp_bios_get_dev_node(&nodenum, (char )0, node))
+		return -ENODEV;
+	node_current_resource_data_to_dev(node,dev);
+	kfree(node);
+	return 0;
+}
+
+static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config, char flags)
+{
+	struct pnp_dev_node_info node_info;
+	u8 nodenum = dev->number;
+	struct pnp_bios_node * node;
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+
+	if (pnp_bios_dev_node_info(&node_info) != 0)
+		return -ENODEV;
+	if (!node)
+		return -1;
+	if (pnp_bios_get_dev_node(&nodenum, (char )1, node))
+		return -ENODEV;
+	if(node_set_resources(node, config)<0){
+		return -1;
+	}
+	kfree(node);
+	return 0;
+}
+
+static int pnpbios_disable_resources(struct pnp_dev *dev)
+{
+	struct pnp_cfg * config = kmalloc(sizeof(struct pnp_cfg), GFP_KERNEL);
+	/* first we need to set everything to a disabled value */
+	struct pnp_port	port = {
+	max:	0,
+	min:	0,
+	align:	0,
+	size:	0,
+	flags:	0,
+	pad:	0,
+	};
+	struct pnp_mem	mem = {
+	max:	0,
+	min:	0,
+	align:	0,
+	size:	0,
+	flags:	0,
+	pad:	0,
+	};
+	struct pnp_dma	dma = {
+	map:	0,
+	flags:	0,
+	};
+	struct pnp_irq	irq = {
+	map:	0,
+	flags:	0,
+	pad:	0,
+	};
+	int i;
+	struct pnp_dev_node_info node_info;
+	u8 nodenum = dev->number;
+	struct pnp_bios_node * node;
+	if (!config)
+		return -1;
+	memset(config, 0, sizeof(struct pnp_cfg));
+	if (!dev || !dev->active)
+		return -EINVAL;
+	for (i=0; i <= 8; i++)
+		config->port[i] = &port;
+	for (i=0; i <= 4; i++)
+		config->mem[i] = &mem;
+	for (i=0; i <= 2; i++)
+		config->irq[i] = &irq;
+	for (i=0; i <= 2; i++)
+		config->dma[i] = &dma;
+	dev->active = 0;
+
+	if (pnp_bios_dev_node_info(&node_info) != 0)
+		return -ENODEV;
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node)
+		return -1;
+	if (pnp_bios_get_dev_node(&nodenum, (char )1, node))
+		goto failed;
+	if(node_set_resources(node, config)<0)
+		goto failed;
+	kfree(config);
+	kfree(node);
+	return 0;
+ failed:
+	kfree(node);
+	kfree(config);
+	return -1;
+}
+
+
+/* PnP Layer support */
+
+static struct pnp_protocol pnpbios_protocol = {
+	name:	"Plug and Play BIOS",
+	get:	pnpbios_get_resources,
+	set:	pnpbios_set_resources,
+	disable:pnpbios_disable_resources,
+};
+
+static int inline insert_device(struct pnp_dev *dev)
+{
+	struct list_head * pos;
+	struct pnp_dev * pnp_dev;
+	list_for_each (pos, &pnpbios_protocol.devices){
+		pnp_dev = list_entry(pos, struct pnp_dev, dev_list);
+		if (dev->number == pnp_dev->number)
+			return -1;
+	}
+	pnp_add_device(dev);
+	return 0;
+}
+
+#define HEX(id,a) hex[((id)>>a) & 15]
+#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
+//
+
+static void inline pnpid32_to_pnpid(u32 id, char *str)
+{
+	const char *hex = "0123456789abcdef";
+
+	id = be32_to_cpu(id);
+	str[0] = CHAR(id, 26);
+	str[1] = CHAR(id, 21);
+	str[2] = CHAR(id,16);
+	str[3] = HEX(id, 12);
+	str[4] = HEX(id, 8);
+	str[5] = HEX(id, 4);
+	str[6] = HEX(id, 0);
+	str[7] = '\0';
+
+	return;
+}
+//
+#undef CHAR
+#undef HEX
+
+
+static void __init build_devlist(void)
+{
+	u8 nodenum;
+	char id[7];
+	unsigned char *pos;
+	unsigned int nodes_got = 0;
+	unsigned int devs = 0;
+	struct pnp_bios_node *node;
+	struct pnp_dev_node_info node_info;
+	struct pnp_dev *dev;
+	struct pnp_id *dev_id;
+
+	if (!pnp_bios_present())
+		return;
+
+	if (pnp_bios_dev_node_info(&node_info) != 0)
+		return;
+
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node)
+		return;
+
+	for(nodenum=0; nodenum<0xff; ) {
+		u8 thisnodenum = nodenum;
+		/* We build the list from the "boot" config because
+		 * asking for the "current" config causes some
+		 * BIOSes to crash.
+		 */
+		if (pnp_bios_get_dev_node(&nodenum, (char )0 , node))
+			break;
+		nodes_got++;
+		dev =  pnpbios_kmalloc(sizeof (struct pnp_dev), GFP_KERNEL);
+		if (!dev)
+			break;
+		memset(dev,0,sizeof(struct pnp_dev));
+		dev_id =  pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
+		if (!dev_id)
+			break;
+		memset(dev_id,0,sizeof(struct pnp_id));
+		pnp_init_device(dev);
+		dev->number = thisnodenum;
+		memcpy(dev->name,"Unknown Device",13);
+		dev->name[14] = '\0';
+		pnpid32_to_pnpid(node->eisa_id,id);
+		memcpy(dev_id->id,id,8);
+		pnp_add_id(dev_id, dev);
+		pos = node_current_resource_data_to_dev(node,dev);
+		node_possible_resource_data_to_dev(pos,node,dev);
+
+		dev->protocol = &pnpbios_protocol;
+
+		if(insert_device(dev)<0)
+			kfree(dev);
+		else
+			devs++;
+		if (nodenum <= thisnodenum) {
+			printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum);
+			break;
+		}
+	}
+	kfree(node);
+
+	printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver\n",
+		nodes_got, nodes_got != 1 ? "s" : "", devs);
+}
+
+/*
+ *
+ * INIT AND EXIT
+ *
+ */
+
+extern int is_sony_vaio_laptop;
+
+static int pnpbios_disabled; /* = 0 */
+static int dont_reserve_resources; /* = 0 */
+int pnpbios_dont_use_current_config; /* = 0 */
+
+#ifndef MODULE
+static int __init pnpbios_setup(char *str)
+{
+	int invert;
+
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "off", 3) == 0)
+			pnpbios_disabled=1;
+		if (strncmp(str, "on", 2) == 0)
+			pnpbios_disabled=0;
+		invert = (strncmp(str, "no-", 3) == 0);
+		if (invert)
+			str += 3;
+		if (strncmp(str, "curr", 4) == 0)
+			pnpbios_dont_use_current_config = invert;
+		if (strncmp(str, "res", 3) == 0)
+			dont_reserve_resources = invert;
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+
+	return 1;
+}
+
+__setup("pnpbios=", pnpbios_setup);
+#endif
+
+subsys_initcall(pnpbios_init);
+
+int __init pnpbios_init(void)
+{
+	union pnp_bios_expansion_header *check;
+	u8 sum;
+	int i, length, r;
+
+	spin_lock_init(&pnp_bios_lock);
+
+	if(pnpbios_disabled) {
+		printk(KERN_INFO "PnPBIOS: Disabled\n");
+		return -ENODEV;
+	}
+
+	if ( is_sony_vaio_laptop )
+		pnpbios_dont_use_current_config = 1;
+
+	/*
+ 	 * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS
+	 * structure and, if one is found, sets up the selectors and
+	 * entry points
+	 */
+	for (check = (union pnp_bios_expansion_header *) __va(0xf0000);
+	     check < (union pnp_bios_expansion_header *) __va(0xffff0);
+	     ((void *) (check)) += 16) {
+		if (check->fields.signature != PNP_SIGNATURE)
+			continue;
+		length = check->fields.length;
+		if (!length)
+			continue;
+		for (sum = 0, i = 0; i < length; i++)
+			sum += check->chars[i];
+		if (sum)
+			continue;
+		if (check->fields.version < 0x10) {
+			printk(KERN_WARNING "PnPBIOS: PnP BIOS version %d.%d is not supported\n",
+			       check->fields.version >> 4,
+			       check->fields.version & 15);
+			continue;
+		}
+		printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", check);
+		printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n",
+                       check->fields.version >> 4, check->fields.version & 15,
+		       check->fields.pm16cseg, check->fields.pm16offset,
+		       check->fields.pm16dseg);
+		pnp_bios_callpoint.offset = check->fields.pm16offset;
+		pnp_bios_callpoint.segment = PNP_CS16;
+		pnp_bios_hdr = check;
+
+		for(i=0; i < NR_CPUS; i++)
+		{
+			Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
+			Q_SET_SEL(i, PNP_CS16, check->fields.pm16cseg, 64 * 1024);
+			Q_SET_SEL(i, PNP_DS, check->fields.pm16dseg, 64 * 1024);
+		}
+		break;
+	}
+	if (!pnp_bios_present())
+		return -ENODEV;
+	pnp_protocol_register(&pnpbios_protocol);
+	build_devlist();
+	/*if ( ! dont_reserve_resources )*/
+		/*reserve_resources();*/
+#ifdef CONFIG_PROC_FS
+	r = pnpbios_proc_init();
+	if (r)
+		return r;
+#endif
+	return 0;
+}
+
+static int __init pnpbios_thread_init(void)
+{
+#ifdef CONFIG_HOTPLUG
+	init_completion(&unload_sem);
+	if (kernel_thread(pnp_dock_thread, NULL, CLONE_KERNEL) > 0)
+		unloading = 0;
+#endif
+	return 0;
+}
+
+#ifndef MODULE
+
+/* init/main.c calls pnpbios_init early */
+
+/* Start the kernel thread later: */
+module_init(pnpbios_thread_init);
+
+#else
+
+/*
+ * N.B.: Building pnpbios as a module hasn't been fully implemented
+ */
+
+MODULE_LICENSE("GPL");
+
+static int __init pnpbios_init_all(void)
+{
+	int r;
+
+	r = pnpbios_init();
+	if (r)
+		return r;
+	r = pnpbios_thread_init();
+	if (r)
+		return r;
+	return 0;
+}
+
+static void __exit pnpbios_exit(void)
+{
+#ifdef CONFIG_HOTPLUG
+	unloading = 1;
+	wait_for_completion(&unload_sem);
+#endif
+	pnpbios_proc_exit();
+	/* We ought to free resources here */
+	return;
+}
+
+module_init(pnpbios_init_all);
+module_exit(pnpbios_exit);
+
+#endif
diff -Nru a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/pnpbios/proc.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,279 @@
+/*
+ * /proc/bus/pnp interface for Plug and Play devices
+ *
+ * Written by David Hinds, dahinds@users.sourceforge.net
+ * Modified by Thomas Hood, jdthood@mail.com
+ *
+ * The .../devices and .../<node> and .../boot/<node> files are
+ * utilized by the lspnp and setpnp utilities, supplied with the
+ * pcmcia-cs package.
+ *     http://pcmcia-cs.sourceforge.net
+ *
+ * The .../escd file is utilized by the lsescd utility written by
+ * Gunther Mayer.
+ *     http://home.t-online.de/home/gunther.mayer/lsescd
+ *
+ * The .../legacy_device_resources file is not used yet.
+ *
+ * The other files are human-readable.
+ */
+
+//#include <pcmcia/config.h>
+#define __NO_VERSION__
+//#include <pcmcia/k_compat.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/pnpbios.h>
+#include <linux/init.h>
+
+static struct proc_dir_entry *proc_pnp = NULL;
+static struct proc_dir_entry *proc_pnp_boot = NULL;
+static struct pnp_dev_node_info node_info;
+
+static int proc_read_pnpconfig(char *buf, char **start, off_t pos,
+                               int count, int *eof, void *data)
+{
+	struct pnp_isa_config_struc pnps;
+
+	if (pnp_bios_isapnp_config(&pnps))
+		return -EIO;
+	return snprintf(buf, count,
+		"structure_revision %d\n"
+		"number_of_CSNs %d\n"
+		"ISA_read_data_port 0x%x\n",
+		pnps.revision,
+		pnps.no_csns,
+		pnps.isa_rd_data_port
+	);
+}
+
+static int proc_read_escdinfo(char *buf, char **start, off_t pos,
+                              int count, int *eof, void *data)
+{
+	struct escd_info_struc escd;
+
+	if (pnp_bios_escd_info(&escd))
+		return -EIO;
+	return snprintf(buf, count,
+		"min_ESCD_write_size %d\n"
+		"ESCD_size %d\n"
+		"NVRAM_base 0x%x\n",
+		escd.min_escd_write_size,
+		escd.escd_size,
+		escd.nv_storage_base
+	);
+}
+
+#define MAX_SANE_ESCD_SIZE (32*1024)
+static int proc_read_escd(char *buf, char **start, off_t pos,
+                          int count, int *eof, void *data)
+{
+	struct escd_info_struc escd;
+	char *tmpbuf;
+	int escd_size, escd_left_to_read, n;
+
+	if (pnp_bios_escd_info(&escd))
+		return -EIO;
+
+	/* sanity check */
+	if (escd.escd_size > MAX_SANE_ESCD_SIZE) {
+		printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by BIOS escd_info call is too great\n");
+		return -EFBIG;
+	}
+
+	tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
+	if (!tmpbuf) return -ENOMEM;
+
+	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base))
+		return -EIO;
+
+	escd_size = (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1])*256;
+
+	/* sanity check */
+	if (escd_size > MAX_SANE_ESCD_SIZE) {
+		printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by BIOS read_escd call is too great\n");
+		return -EFBIG;
+	}
+
+	escd_left_to_read = escd_size - pos;
+	if (escd_left_to_read < 0) escd_left_to_read = 0;
+	if (escd_left_to_read == 0) *eof = 1;
+	n = min(count,escd_left_to_read);
+	memcpy(buf, tmpbuf + pos, n);
+	kfree(tmpbuf);
+	*start = buf;
+	return n;
+}
+
+static int proc_read_legacyres(char *buf, char **start, off_t pos,
+                               int count, int *eof, void *data)
+{
+	/* Assume that the following won't overflow the buffer */
+	if (pnp_bios_get_stat_res(buf)) 
+		return -EIO;
+
+	return count;  // FIXME: Return actual length
+}
+
+static int proc_read_devices(char *buf, char **start, off_t pos,
+                             int count, int *eof, void *data)
+{
+	struct pnp_bios_node *node;
+	u8 nodenum;
+	char *p = buf;
+
+	if (pos >= 0xff)
+		return 0;
+
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node) return -ENOMEM;
+
+	for (nodenum=pos; nodenum<0xff; ) {
+		u8 thisnodenum = nodenum;
+		/* 26 = the number of characters per line sprintf'ed */
+		if ((p - buf + 26) > count)
+			break;
+		if (pnp_bios_get_dev_node(&nodenum, 1, node))
+			break;
+		p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
+			     node->handle, node->eisa_id,
+			     node->type_code[0], node->type_code[1],
+			     node->type_code[2], node->flags);
+		if (nodenum <= thisnodenum) {
+			printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_read_devices:", (unsigned int)nodenum, (unsigned int)thisnodenum);
+			*eof = 1;
+			break;
+		}
+	}
+	kfree(node);
+	if (nodenum == 0xff)
+		*eof = 1;
+	*start = (char *)((off_t)nodenum - pos);
+	return p - buf;
+}
+
+static int proc_read_node(char *buf, char **start, off_t pos,
+                          int count, int *eof, void *data)
+{
+	struct pnp_bios_node *node;
+	int boot = (long)data >> 8;
+	u8 nodenum = (long)data;
+	int len;
+
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node) return -ENOMEM;
+	if (pnp_bios_get_dev_node(&nodenum, boot, node))
+		return -EIO;
+	len = node->size - sizeof(struct pnp_bios_node);
+	memcpy(buf, node->data, len);
+	kfree(node);
+	return len;
+}
+
+static int proc_write_node(struct file *file, const char *buf,
+                           unsigned long count, void *data)
+{
+	struct pnp_bios_node *node;
+	int boot = (long)data >> 8;
+	u8 nodenum = (long)data;
+
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node) return -ENOMEM;
+	if ( pnp_bios_get_dev_node(&nodenum, boot, node) )
+		return -EIO;
+	if (count != node->size - sizeof(struct pnp_bios_node))
+		return -EINVAL;
+	memcpy(node->data, buf, count);
+	if (pnp_bios_set_dev_node(node->handle, boot, node) != 0)
+	    return -EINVAL;
+	kfree(node);
+	return count;
+}
+
+/*
+ * When this is called, pnpbios functions are assumed to
+ * work and the pnpbios_dont_use_current_config flag
+ * should already have been set to the appropriate value
+ */
+int __init pnpbios_proc_init( void )
+{
+	struct pnp_bios_node *node;
+	struct proc_dir_entry *ent;
+	char name[3];
+	u8 nodenum;
+
+	if (pnp_bios_dev_node_info(&node_info))
+		return -EIO;
+	
+	proc_pnp = proc_mkdir("pnp", proc_bus);
+	if (!proc_pnp)
+		return -EIO;
+	proc_pnp_boot = proc_mkdir("boot", proc_pnp);
+	if (!proc_pnp_boot)
+		return -EIO;
+	create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL);
+	create_proc_read_entry("configuration_info", 0, proc_pnp, proc_read_pnpconfig, NULL);
+	create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, NULL);
+	create_proc_read_entry("escd", S_IRUSR, proc_pnp, proc_read_escd, NULL);
+	create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL);
+	
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node)
+		return -ENOMEM;
+
+	for (nodenum=0; nodenum<0xff; ) {
+		u8 thisnodenum = nodenum;
+		if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0)
+			break;
+		sprintf(name, "%02x", node->handle);
+		if ( !pnpbios_dont_use_current_config ) {
+			ent = create_proc_entry(name, 0, proc_pnp);
+			if (ent) {
+				ent->read_proc = proc_read_node;
+				ent->write_proc = proc_write_node;
+				ent->data = (void *)(long)(node->handle);
+			}
+		}
+		ent = create_proc_entry(name, 0, proc_pnp_boot);
+		if (ent) {
+			ent->read_proc = proc_read_node;
+			ent->write_proc = proc_write_node;
+			ent->data = (void *)(long)(node->handle+0x100);
+		}
+		if (nodenum <= thisnodenum) {
+			printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_init:", (unsigned int)nodenum, (unsigned int)thisnodenum);
+			break;
+		}
+	}
+	kfree(node);
+
+	return 0;
+}
+
+void __exit pnpbios_proc_exit(void)
+{
+	int i;
+	char name[3];
+	
+	if (!proc_pnp) return;
+
+	for (i=0; i<0xff; i++) {
+		sprintf(name, "%02x", i);
+		if ( !pnpbios_dont_use_current_config )
+			remove_proc_entry(name, proc_pnp);
+		remove_proc_entry(name, proc_pnp_boot);
+	}
+	remove_proc_entry("legacy_device_resources", proc_pnp);
+	remove_proc_entry("escd", proc_pnp);
+	remove_proc_entry("escd_info", proc_pnp);
+	remove_proc_entry("configuration_info", proc_pnp);
+	remove_proc_entry("devices", proc_pnp);
+	remove_proc_entry("boot", proc_pnp);
+	remove_proc_entry("pnp", proc_bus);
+
+	return;
+}
diff -Nru a/drivers/pnp/pnpbios_core.c b/drivers/pnp/pnpbios_core.c
--- a/drivers/pnp/pnpbios_core.c	Fri Oct 18 21:03:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1350 +0,0 @@
-/*
- * pnpbios -- PnP BIOS driver
- *
- * This driver provides access to Plug-'n'-Play services provided by
- * the PnP BIOS firmware, described in the following documents:
- *   Plug and Play BIOS Specification, Version 1.0A, 5 May 1994
- *   Plug and Play BIOS Clarification Paper, 6 October 1994
- *     Compaq Computer Corporation, Phoenix Technologies Ltd., Intel Corp.
- * 
- * Originally (C) 1998 Christian Schmidt <schmidt@digadd.de>
- * Modifications (C) 1998 Tom Lees <tom@lpsg.demon.co.uk>
- * Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
- * Further modifications (C) 2001, 2002 by:
- *   Alan Cox <alan@redhat.com>
- *   Thomas Hood <jdthood@mail.com>
- *   Brian Gerst <bgerst@didntduck.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-#include <linux/pnpbios.h>
-#include <asm/page.h>
-#include <asm/system.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <asm/desc.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/kmod.h>
-#include <linux/completion.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-
-/*
- *
- * PnP BIOS INTERFACE
- *
- */
-
-/* PnP BIOS signature: "$PnP" */
-#define PNP_SIGNATURE   (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
-
-#pragma pack(1)
-union pnp_bios_expansion_header {
-	struct {
-		u32 signature;    /* "$PnP" */
-		u8 version;	  /* in BCD */
-		u8 length;	  /* length in bytes, currently 21h */
-		u16 control;	  /* system capabilities */
-		u8 checksum;	  /* all bytes must add up to 0 */
-
-		u32 eventflag;    /* phys. address of the event flag */
-		u16 rmoffset;     /* real mode entry point */
-		u16 rmcseg;
-		u16 pm16offset;   /* 16 bit protected mode entry */
-		u32 pm16cseg;
-		u32 deviceID;	  /* EISA encoded system ID or 0 */
-		u16 rmdseg;	  /* real mode data segment */
-		u32 pm16dseg;	  /* 16 bit pm data segment base */
-	} fields;
-	char chars[0x21];	  /* To calculate the checksum */
-};
-#pragma pack()
-
-static struct {
-	u16	offset;
-	u16	segment;
-} pnp_bios_callpoint;
-
-static union pnp_bios_expansion_header * pnp_bios_hdr = NULL;
-
-/* The PnP BIOS entries in the GDT */
-#define PNP_GDT    (GDT_ENTRY_PNPBIOS_BASE * 8)
-
-#define PNP_CS32   (PNP_GDT+0x00)	/* segment for calling fn */
-#define PNP_CS16   (PNP_GDT+0x08)	/* code segment for BIOS */
-#define PNP_DS     (PNP_GDT+0x10)	/* data segment for BIOS */
-#define PNP_TS1    (PNP_GDT+0x18)	/* transfer data segment */
-#define PNP_TS2    (PNP_GDT+0x20)	/* another data segment */
-
-/* 
- * These are some opcodes for a "static asmlinkage"
- * As this code is *not* executed inside the linux kernel segment, but in a
- * alias at offset 0, we need a far return that can not be compiled by
- * default (please, prove me wrong! this is *really* ugly!) 
- * This is the only way to get the bios to return into the kernel code,
- * because the bios code runs in 16 bit protected mode and therefore can only
- * return to the caller if the call is within the first 64kB, and the linux
- * kernel begins at offset 3GB...
- */
-
-asmlinkage void pnp_bios_callfunc(void);
-
-__asm__(
-	".text			\n"
-	__ALIGN_STR "\n"
-	"pnp_bios_callfunc:\n"
-	"	pushl %edx	\n"
-	"	pushl %ecx	\n"
-	"	pushl %ebx	\n"
-	"	pushl %eax	\n"
-	"	lcallw *pnp_bios_callpoint\n"
-	"	addl $16, %esp	\n"
-	"	lret		\n"
-	".previous		\n"
-);
-
-#define Q_SET_SEL(cpu, selname, address, size) \
-do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
-} while(0)
-
-#define Q2_SET_SEL(cpu, selname, address, size) \
-do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
-} while(0)
-
-/*
- * At some point we want to use this stack frame pointer to unwind
- * after PnP BIOS oopses. 
- */
- 
-u32 pnp_bios_fault_esp;
-u32 pnp_bios_fault_eip;
-u32 pnp_bios_is_utter_crap = 0;
-
-static spinlock_t pnp_bios_lock;
-
-static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
-				u16 arg4, u16 arg5, u16 arg6, u16 arg7,
-				void *ts1_base, u32 ts1_size,
-				void *ts2_base, u32 ts2_size)
-{
-	unsigned long flags;
-	u16 status;
-
-	/*
-	 * PnP BIOSes are generally not terribly re-entrant.
-	 * Also, don't rely on them to save everything correctly.
-	 */
-	if(pnp_bios_is_utter_crap)
-		return PNP_FUNCTION_NOT_SUPPORTED;
-
-	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
-	spin_lock_irqsave(&pnp_bios_lock, flags);
-
-	/* The lock prevents us bouncing CPU here */
-	if (ts1_size)
-		Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
-	if (ts2_size)
-		Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
-
-	__asm__ __volatile__(
-	        "pushl %%ebp\n\t"
-		"pushl %%edi\n\t"
-		"pushl %%esi\n\t"
-		"pushl %%ds\n\t"
-		"pushl %%es\n\t"
-		"pushl %%fs\n\t"
-		"pushl %%gs\n\t"
-		"pushfl\n\t"
-		"movl %%esp, pnp_bios_fault_esp\n\t"
-		"movl $1f, pnp_bios_fault_eip\n\t"
-		"lcall %5,%6\n\t"
-		"1:popfl\n\t"
-		"popl %%gs\n\t"
-		"popl %%fs\n\t"
-		"popl %%es\n\t"
-		"popl %%ds\n\t"
-	        "popl %%esi\n\t"
-		"popl %%edi\n\t"
-		"popl %%ebp\n\t"
-		: "=a" (status)
-		: "0" ((func) | (((u32)arg1) << 16)),
-		  "b" ((arg2) | (((u32)arg3) << 16)),
-		  "c" ((arg4) | (((u32)arg5) << 16)),
-		  "d" ((arg6) | (((u32)arg7) << 16)),
-		  "i" (PNP_CS32),
-		  "i" (0)
-		: "memory"
-	);
-	spin_unlock_irqrestore(&pnp_bios_lock, flags);
-	
-	/* If we get here and this is set then the PnP BIOS faulted on us. */
-	if(pnp_bios_is_utter_crap)
-	{
-		printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
-		printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"nobiospnp\" option to operate stably\n");
-		printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n");
-	}
-
-	return status;
-}
-
-
-/*
- *
- * UTILITY FUNCTIONS
- *
- */
-
-static void pnpbios_warn_unexpected_status(const char * module, u16 status)
-{
-	printk(KERN_ERR "PnPBIOS: %s: Unexpected status 0x%x\n", module, status);
-}
-
-void *pnpbios_kmalloc(size_t size, int f)
-{
-	void *p = kmalloc( size, f );
-	if ( p == NULL )
-		printk(KERN_ERR "PnPBIOS: kmalloc() failed\n");
-	return p;
-}
-
-/*
- * Call this only after init time
- */
-static int pnp_bios_present(void)
-{
-	return (pnp_bios_hdr != NULL);
-}
-
-/* Forward declaration */
-static void update_devlist( u8 nodenum, struct pnp_bios_node *data );
-
-
-/*
- *
- * PnP BIOS ACCESS FUNCTIONS
- *
- */
-
-#define PNP_GET_NUM_SYS_DEV_NODES       0x00
-#define PNP_GET_SYS_DEV_NODE            0x01
-#define PNP_SET_SYS_DEV_NODE            0x02
-#define PNP_GET_EVENT                   0x03
-#define PNP_SEND_MESSAGE                0x04
-#define PNP_GET_DOCKING_STATION_INFORMATION 0x05
-#define PNP_SET_STATIC_ALLOCED_RES_INFO 0x09
-#define PNP_GET_STATIC_ALLOCED_RES_INFO 0x0a
-#define PNP_GET_APM_ID_TABLE            0x0b
-#define PNP_GET_PNP_ISA_CONFIG_STRUC    0x40
-#define PNP_GET_ESCD_INFO               0x41
-#define PNP_READ_ESCD                   0x42
-#define PNP_WRITE_ESCD                  0x43
-
-/*
- * Call PnP BIOS with function 0x00, "get number of system device nodes"
- */
-static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0,
-			       data, sizeof(struct pnp_dev_node_info), 0, 0);
-	data->no_nodes &= 0xff;
-	return status;
-}
-
-int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
-{
-	int status = __pnp_bios_dev_node_info( data );
-	if ( status )
-		pnpbios_warn_unexpected_status( "dev_node_info", status );
-	return status;
-}
-
-/*
- * Note that some PnP BIOSes (e.g., on Sony Vaio laptops) die a horrible
- * death if they are asked to access the "current" configuration.
- * Therefore, if it's a matter of indifference, it's better to call
- * get_dev_node() and set_dev_node() with boot=1 rather than with boot=0.
- */
-
-/* 
- * Call PnP BIOS with function 0x01, "get system device node"
- * Input: *nodenum = desired node, 
- *        boot = whether to get nonvolatile boot (!=0)
- *               or volatile current (0) config
- * Output: *nodenum=next node or 0xff if no more nodes
- */
-static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	if ( !boot & pnpbios_dont_use_current_config )
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
-			       nodenum, sizeof(char), data, 65536);
-	return status;
-}
-
-int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
-{
-	int status;
-	status =  __pnp_bios_get_dev_node( nodenum, boot, data );
-	if ( status )
-		pnpbios_warn_unexpected_status( "get_dev_node", status );
-	return status;
-}
-
-
-/*
- * Call PnP BIOS with function 0x02, "set system device node"
- * Input: *nodenum = desired node, 
- *        boot = whether to set nonvolatile boot (!=0)
- *               or volatile current (0) config
- */
-static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	if ( !boot & pnpbios_dont_use_current_config )
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0,
-			       data, 65536, 0, 0);
-	return status;
-}
-
-int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
-{
-	int status;
-	status =  __pnp_bios_set_dev_node( nodenum, boot, data );
-	if ( status ) {
-		pnpbios_warn_unexpected_status( "set_dev_node", status );
-		return status;
-	}
-	if ( !boot ) { /* Update devlist */
-		u8 thisnodenum = nodenum;
-		status =  pnp_bios_get_dev_node( &nodenum, boot, data );
-		if ( status )
-			return status;
-		update_devlist( thisnodenum, data );
-	}
-	return status;
-}
-
-#if needed
-/*
- * Call PnP BIOS with function 0x03, "get event"
- */
-static int pnp_bios_get_event(u16 *event)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
-			       event, sizeof(u16), 0, 0);
-	return status;
-}
-#endif
-
-#if needed
-/* 
- * Call PnP BIOS with function 0x04, "send message"
- */
-static int pnp_bios_send_message(u16 message)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-	return status;
-}
-#endif
-
-#ifdef CONFIG_HOTPLUG
-/*
- * Call PnP BIOS with function 0x05, "get docking station information"
- */
-static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       data, sizeof(struct pnp_docking_station_info), 0, 0);
-	return status;
-}
-#endif
-
-#if needed
-/*
- * Call PnP BIOS with function 0x09, "set statically allocated resource
- * information"
- */
-static int pnp_bios_set_stat_res(char *info)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       info, *((u16 *) info), 0, 0);
-	return status;
-}
-#endif
-
-/*
- * Call PnP BIOS with function 0x0a, "get statically allocated resource
- * information"
- */
-static int __pnp_bios_get_stat_res(char *info)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       info, 65536, 0, 0);
-	return status;
-}
-
-int pnp_bios_get_stat_res(char *info)
-{
-	int status;
-	status = __pnp_bios_get_stat_res( info );
-	if ( status )
-		pnpbios_warn_unexpected_status( "get_stat_res", status );
-	return status;
-}
-
-#if needed
-/*
- * Call PnP BIOS with function 0x0b, "get APM id table"
- */
-static int pnp_bios_apm_id_table(char *table, u16 *size)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0,
-			       table, *size, size, sizeof(u16));
-	return status;
-}
-#endif
-
-/*
- * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
- */
-static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       data, sizeof(struct pnp_isa_config_struc), 0, 0);
-	return status;
-}
-
-int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
-{
-	int status;
-	status = __pnp_bios_isapnp_config( data );
-	if ( status )
-		pnpbios_warn_unexpected_status( "isapnp_config", status );
-	return status;
-}
-
-/*
- * Call PnP BIOS with function 0x41, "get ESCD info"
- */
-static int __pnp_bios_escd_info(struct escd_info_struc *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return ESCD_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS,
-			       data, sizeof(struct escd_info_struc), 0, 0);
-	return status;
-}
-
-int pnp_bios_escd_info(struct escd_info_struc *data)
-{
-	int status;
-	status = __pnp_bios_escd_info( data );
-	if ( status )
-		pnpbios_warn_unexpected_status( "escd_info", status );
-	return status;
-}
-
-/*
- * Call PnP BIOS function 0x42, "read ESCD"
- * nvram_base is determined by calling escd_info
- */
-static int __pnp_bios_read_escd(char *data, u32 nvram_base)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return ESCD_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
-			       data, 65536, (void *)nvram_base, 65536);
-	return status;
-}
-
-int pnp_bios_read_escd(char *data, u32 nvram_base)
-{
-	int status;
-	status = __pnp_bios_read_escd( data, nvram_base );
-	if ( status )
-		pnpbios_warn_unexpected_status( "read_escd", status );
-	return status;
-}
-
-#if needed
-/*
- * Call PnP BIOS function 0x43, "write ESCD"
- */
-static int pnp_bios_write_escd(char *data, u32 nvram_base)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return ESCD_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
-			       data, 65536, nvram_base, 65536);
-	return status;
-}
-#endif
-
-
-/*
- *
- * DOCKING FUNCTIONS
- *
- */
-
-#ifdef CONFIG_HOTPLUG
-
-static int unloading = 0;
-static struct completion unload_sem;
-
-/*
- * (Much of this belongs in a shared routine somewhere)
- */
- 
-static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
-{
-	char *argv [3], **envp, *buf, *scratch;
-	int i = 0, value;
-
-	if (!hotplug_path [0])
-		return -ENOENT;
-	if (!current->fs->root) {
-		return -EAGAIN;
-	}
-	if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
-		return -ENOMEM;
-	}
-	if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) {
-		kfree (envp);
-		return -ENOMEM;
-	}
-
-	/* only one standardized param to hotplug command: type */
-	argv [0] = hotplug_path;
-	argv [1] = "dock";
-	argv [2] = 0;
-
-	/* minimal command environment */
-	envp [i++] = "HOME=/";
-	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
-#ifdef	DEBUG
-	/* hint that policy agent should enter no-stdout debug mode */
-	envp [i++] = "DEBUG=kernel";
-#endif
-	/* extensible set of named bus-specific parameters,
-	 * supporting multiple driver selection algorithms.
-	 */
-	scratch = buf;
-
-	/* action:  add, remove */
-	envp [i++] = scratch;
-	scratch += sprintf (scratch, "ACTION=%s", dock?"add":"remove") + 1;
-
-	/* Report the ident for the dock */
-	envp [i++] = scratch;
-	scratch += sprintf (scratch, "DOCK=%x/%x/%x",
-		info->location_id, info->serial, info->capabilities);
-	envp[i] = 0;
-	
-	value = call_usermodehelper (argv [0], argv, envp);
-	kfree (buf);
-	kfree (envp);
-	return 0;
-}
-
-/*
- * Poll the PnP docking at regular intervals
- */
-static int pnp_dock_thread(void * unused)
-{
-	static struct pnp_docking_station_info now;
-	int docked = -1, d = 0;
-	daemonize();
-	strcpy(current->comm, "kpnpbiosd");
-	while(!unloading && !signal_pending(current))
-	{
-		int status;
-		
-		/*
-		 * Poll every 2 seconds
-		 */
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ*2);
-		if(signal_pending(current))
-			break;
-
-		status = pnp_bios_dock_station_info(&now);
-
-		switch(status)
-		{
-			/*
-			 * No dock to manage
-			 */
-			case PNP_FUNCTION_NOT_SUPPORTED:
-				complete_and_exit(&unload_sem, 0);
-			case PNP_SYSTEM_NOT_DOCKED:
-				d = 0;
-				break;
-			case PNP_SUCCESS:
-				d = 1;
-				break;
-			default:
-				pnpbios_warn_unexpected_status( "pnp_dock_thread", status );
-				continue;
-		}
-		if(d != docked)
-		{
-			if(pnp_dock_event(d, &now)==0)
-			{
-				docked = d;
-#if 0
-				printk(KERN_INFO "PnPBIOS: Docking station %stached\n", docked?"at":"de");
-#endif
-			}
-		}
-	}	
-	complete_and_exit(&unload_sem, 0);
-}
-
-#endif   /* CONFIG_HOTPLUG */
-
-
-/*
- *
- * NODE DATA PARSING FUNCTIONS
- *
- */
-
-static void add_irqresource(struct pci_dev *dev, int irq)
-{
-	int i = 0;
-	while (!(dev->irq_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_IRQ) i++;
-	if (i < DEVICE_COUNT_IRQ) {
-		dev->irq_resource[i].start = (unsigned long) irq;
-		dev->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
-	}
-}
-
-static void add_dmaresource(struct pci_dev *dev, int dma)
-{
-	int i = 0;
-	while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++;
-	if (i < DEVICE_COUNT_DMA) {
-		dev->dma_resource[i].start = (unsigned long) dma;
-		dev->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
-	}
-}
-
-static void add_ioresource(struct pci_dev *dev, int io, int len)
-{
-	int i = 0;
-	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
-	if (i < DEVICE_COUNT_RESOURCE) {
-		dev->resource[i].start = (unsigned long) io;
-		dev->resource[i].end = (unsigned long)(io + len - 1);
-		dev->resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
-	}
-}
-
-static void add_memresource(struct pci_dev *dev, int mem, int len)
-{
-	int i = 0;
-	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
-	if (i < DEVICE_COUNT_RESOURCE) {
-		dev->resource[i].start = (unsigned long) mem;
-		dev->resource[i].end = (unsigned long)(mem + len - 1);
-		dev->resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
-	}
-}
-
-static void node_resource_data_to_dev(struct pnp_bios_node *node, struct pci_dev *dev)
-{
-	unsigned char *p = node->data, *lastp=NULL;
-	int i;
-
-	/*
-	 * First, set resource info to default values
-	 */
-	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
-		dev->resource[i].start = 0;  // "disabled"
-		dev->resource[i].flags = IORESOURCE_UNSET;
-	}
-	for (i=0;i<DEVICE_COUNT_IRQ;i++) {
-		dev->irq_resource[i].start = (unsigned long)-1;  // "disabled"
-		dev->irq_resource[i].flags = IORESOURCE_UNSET;
-	}
-	for (i=0;i<DEVICE_COUNT_DMA;i++) {
-		dev->dma_resource[i].start = (unsigned long)-1;  // "disabled"
-		dev->dma_resource[i].flags = IORESOURCE_UNSET;
-	}
-
-	/*
-	 * Fill in dev resource info
-	 */
-        while ( (char *)p < ((char *)node->data + node->size )) {
-        	if(p==lastp) break;
-
-                if( p[0] & 0x80 ) {// large item
-			switch (p[0] & 0x7f) {
-			case 0x01: // memory
-			{
-				int io = *(short *) &p[4];
-				int len = *(short *) &p[10];
-				add_memresource(dev, io, len);
-				break;
-			}
-			case 0x02: // device name
-			{
-				int len = *(short *) &p[1];
-				memcpy(dev->name, p + 3, len >= 80 ? 79 : len);
-				break;
-			}
-			case 0x05: // 32-bit memory
-			{
-				int io = *(int *) &p[4];
-				int len = *(int *) &p[16];
-				add_memresource(dev, io, len);
-				break;
-			}
-			case 0x06: // fixed location 32-bit memory
-			{
-				int io = *(int *) &p[4];
-				int len = *(int *) &p[8];
-				add_memresource(dev, io, len);
-				break;
-			}
-			} /* switch */
-                        lastp = p+3;
-                        p = p + p[1] + p[2]*256 + 3;
-                        continue;
-                }
-                if ((p[0]>>3) == 0x0f) // end tag
-                        break;
-                switch (p[0]>>3) {
-                case 0x04: // irq
-                {
-                        int i, mask, irq = -1;
-                        mask= p[1] + p[2]*256;
-                        for (i=0;i<16;i++, mask=mask>>1)
-                                if(mask & 0x01) irq=i;
-			add_irqresource(dev, irq);
-                        break;
-                }
-                case 0x05: // dma
-                {
-                        int i, mask, dma = -1;
-                        mask = p[1];
-                        for (i=0;i<8;i++, mask = mask>>1)
-                                if(mask & 0x01) dma=i;
-			add_dmaresource(dev, dma);
-                        break;
-                }
-                case 0x08: // io
-                {
-			int io= p[2] + p[3] *256;
-			int len = p[7];
-			add_ioresource(dev, io, len);
-                        break;
-                }
-		case 0x09: // fixed location io
-		{
-			int io = p[1] + p[2] * 256;
-			int len = p[3];
-			add_ioresource(dev, io, len);
-			break;
-		}
-                } /* switch */
-                lastp=p+1;
-                p = p + (p[0] & 0x07) + 1;
-
-        } /* while */
-
-        return;
-}
-
-
-/*
- *
- * DEVICE LIST MANAGEMENT FUNCTIONS
- *
- *
- * Some of these are exported to give public access
- *
- * Question: Why maintain a device list when the PnP BIOS can 
- * list devices for us?  Answer: Some PnP BIOSes can't report
- * the current configuration, only the boot configuration.
- * The boot configuration can be changed, so we need to keep
- * a record of what the configuration was when we booted;
- * presumably it continues to describe the current config.
- * For those BIOSes that can change the current config, we
- * keep the information in the devlist up to date.
- *
- * Note that it is currently assumed that the list does not
- * grow or shrink in size after init time, and slot_name
- * never changes.  The list is protected by a spinlock.
- */
-
-static LIST_HEAD(pnpbios_devices);
-
-static spinlock_t pnpbios_devices_lock;
-
-static int inline insert_device(struct pci_dev *dev)
-{
-
-	/*
-	 * FIXME: Check for re-add of existing node;
-	 * return -1 if node already present
-	 */
-
-	/* We don't lock because we only do this at init time */
-	list_add_tail(&dev->global_list, &pnpbios_devices);
-
-	return 0;
-}
-
-#define HEX(id,a) hex[((id)>>a) & 15]
-#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
-//
-static void inline pnpid32_to_pnpid(u32 id, char *str)
-{
-	const char *hex = "0123456789abcdef";
-
-	id = be32_to_cpu(id);
-	str[0] = CHAR(id, 26);
-	str[1] = CHAR(id, 21);
-	str[2] = CHAR(id,16);
-	str[3] = HEX(id, 12);
-	str[4] = HEX(id, 8);
-	str[5] = HEX(id, 4);
-	str[6] = HEX(id, 0);
-	str[7] = '\0';
-
-	return;
-}                                              
-//
-#undef CHAR
-#undef HEX 
-
-/*
- * Build a linked list of pci_devs in order of ascending node number
- * Called only at init time.
- */
-static void __init build_devlist(void)
-{
-	u8 nodenum;
-	unsigned int nodes_got = 0;
-	unsigned int devs = 0;
-	struct pnp_bios_node *node;
-	struct pnp_dev_node_info node_info;
-	struct pci_dev *dev;
-	
-	if (!pnp_bios_present())
-		return;
-
-	if (pnp_bios_dev_node_info(&node_info) != 0)
-		return;
-
-	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
-	if (!node)
-		return;
-
-	for(nodenum=0; nodenum<0xff; ) {
-		u8 thisnodenum = nodenum;
-		/* We build the list from the "boot" config because
-		 * asking for the "current" config causes some
-		 * BIOSes to crash.
-		 */
-		if (pnp_bios_get_dev_node(&nodenum, (char )1 , node))
-			break;
-		nodes_got++;
-		dev =  pnpbios_kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
-		if (!dev)
-			break;
-		memset(dev,0,sizeof(struct pci_dev));
-		dev->devfn = thisnodenum;
-		memcpy(dev->name,"PNPBIOS",8);
-		pnpid32_to_pnpid(node->eisa_id,dev->slot_name);
-		node_resource_data_to_dev(node,dev);
-		if(insert_device(dev)<0)
-			kfree(dev);
-		else
-			devs++;
-		if (nodenum <= thisnodenum) {
-			printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum);
-			break;
-		}
-	}
-	kfree(node);
-
-	printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver\n",
-		nodes_got, nodes_got != 1 ? "s" : "", devs);
-}
-
-static struct pci_dev *find_device_by_nodenum( u8 nodenum )
-{
-	struct pci_dev *dev;
-
-	pnpbios_for_each_dev(dev) {
-		if(dev->devfn == nodenum)
-			return dev;
-	}
-
-	return NULL;
-}
-
-static void update_devlist( u8 nodenum, struct pnp_bios_node *data )
-{
-	unsigned long flags;
-	struct pci_dev *dev;
-
-	spin_lock_irqsave(&pnpbios_devices_lock, flags);
-	dev = find_device_by_nodenum( nodenum );
-	if ( dev ) {
-		node_resource_data_to_dev(data,dev);
-	}
-	spin_unlock_irqrestore(&pnpbios_devices_lock, flags);
-
-	return;
-}
-
-
-/*
- *
- * DRIVER REGISTRATION FUNCTIONS
- *
- *
- * Exported to give public access
- *
- */
-
-static LIST_HEAD(pnpbios_drivers);
-
-static const struct pnpbios_device_id *
-match_device(const struct pnpbios_device_id *ids, const struct pci_dev *dev)
-{
-	while (*ids->id)
-	{
-		if(memcmp(ids->id, dev->slot_name, 7)==0)
-			return ids;
-		ids++;
-	}
-	return NULL;
-}
-
-static int announce_device(struct pnpbios_driver *drv, struct pci_dev *dev)
-{
-	const struct pnpbios_device_id *id;
-	struct pci_dev tmpdev;
-	int ret;
-
-	if (drv->id_table) {
-		id = match_device(drv->id_table, dev);
-		if (!id)
-			return 0;
-	} else
-		id = NULL;
-
-	memcpy( &tmpdev, dev, sizeof(struct pci_dev));
-	tmpdev.global_list.prev = NULL;
-	tmpdev.global_list.next = NULL;
-
-	dev_probe_lock();
-	/* Obviously, probe() should not call any pnpbios functions */
-	ret = drv->probe(&tmpdev, id);
-	dev_probe_unlock();
-	if (ret < 1)
-		return 0;
-
-	dev->driver = (void *)drv;
-
-	return 1;
-}
-
-/**
- * pnpbios_register_driver - register a new pci driver
- * @drv: the driver structure to register
- * 
- * Adds the driver structure to the list of registered drivers
- *
- * For each device in the pnpbios device list that matches one of
- * the ids in drv->id_table, calls the driver's "probe" function with
- * arguments (1) a pointer to a *temporary* struct pci_dev containing
- * resource info for the device, and (2) a pointer to the id string
- * of the device.  Expects the probe function to return 1 if the
- * driver claims the device (otherwise 0) in which case, marks the
- * device as having this driver.
- * 
- * Returns the number of pci devices which were claimed by the driver
- * during registration.  The driver remains registered even if the
- * return value is zero.
- */
-int pnpbios_register_driver(struct pnpbios_driver *drv)
-{
-	struct pci_dev *dev;
-	unsigned long flags;
-	int count = 0;
-
-	list_add_tail(&drv->node, &pnpbios_drivers);
-	spin_lock_irqsave(&pnpbios_devices_lock, flags);
-	pnpbios_for_each_dev(dev) {
-		if (!pnpbios_dev_driver(dev))
-			count += announce_device(drv, dev);
-	}
-	spin_unlock_irqrestore(&pnpbios_devices_lock, flags);
-	return count;
-}
-
-EXPORT_SYMBOL(pnpbios_register_driver);
-
-/**
- * pnpbios_unregister_driver - unregister a pci driver
- * @drv: the driver structure to unregister
- * 
- * Deletes the driver structure from the list of registered PnPBIOS
- * drivers, gives it a chance to clean up by calling its "remove"
- * function for each device it was responsible for, and marks those
- * devices as driverless.
- */
-void pnpbios_unregister_driver(struct pnpbios_driver *drv)
-{
-	unsigned long flags;
-	struct pci_dev *dev;
-
-	list_del(&drv->node);
-	spin_lock_irqsave(&pnpbios_devices_lock, flags);
-	pnpbios_for_each_dev(dev) {
-		if (dev->driver == (void *)drv) {
-			if (drv->remove)
-				drv->remove(dev);
-			dev->driver = NULL;
-		}
-	}
-	spin_unlock_irqrestore(&pnpbios_devices_lock, flags);
-}
-
-EXPORT_SYMBOL(pnpbios_unregister_driver);
-
-
-/*
- *
- * RESOURCE RESERVATION FUNCTIONS
- *
- *
- * Used only at init time
- *
- */
-
-static void __init reserve_ioport_range(char *pnpid, int start, int end)
-{
-	struct resource *res;
-	char *regionid;
-
-	regionid = pnpbios_kmalloc(16, GFP_KERNEL);
-	if ( regionid == NULL )
-		return;
-	snprintf(regionid, 16, "PnPBIOS %s", pnpid);
-	res = request_region(start,end-start+1,regionid);
-	if ( res == NULL )
-		kfree( regionid );
-	else
-		res->flags &= ~IORESOURCE_BUSY;
-	/*
-	 * Failures at this point are usually harmless. pci quirks for
-	 * example do reserve stuff they know about too, so we may well
-	 * have double reservations.
-	 */
-	printk(KERN_INFO
-		"PnPBIOS: %s: ioport range 0x%x-0x%x %s reserved\n",
-		pnpid, start, end,
-		NULL != res ? "has been" : "could not be"
-	);
-
-	return;
-}
-
-static void __init reserve_resources_of_dev( struct pci_dev *dev )
-{
-	int i;
-
-	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
-		if ( dev->resource[i].flags & IORESOURCE_UNSET )
-			/* end of resources */
-			break;
-		if (dev->resource[i].flags & IORESOURCE_IO) {
-			/* ioport */
-			if ( dev->resource[i].start == 0 )
-				/* disabled */
-				/* Do nothing */
-				continue;
-			if ( dev->resource[i].start < 0x100 )
-				/*
-				 * Below 0x100 is only standard PC hardware
-				 * (pics, kbd, timer, dma, ...)
-				 * We should not get resource conflicts there,
-				 * and the kernel reserves these anyway
-				 * (see arch/i386/kernel/setup.c).
-				 * So, do nothing
-				 */
-				continue;
-			if ( dev->resource[i].end < dev->resource[i].start )
-				/* invalid endpoint */
-				/* Do nothing */
-				continue;
-			reserve_ioport_range(
-				dev->slot_name,
-				dev->resource[i].start,
-				dev->resource[i].end
-			);
-		} else if (dev->resource[i].flags & IORESOURCE_MEM) {
-			/* iomem */
-			/* For now do nothing */
-			continue;
-		} else {
-			/* Neither ioport nor iomem */
-			/* Do nothing */
-			continue;
-		}
-	}
-
-	return;
-}
-
-static void __init reserve_resources( void )
-{
-	struct pci_dev *dev;
-
-	pnpbios_for_each_dev(dev) {
-		if (
-			0 != strcmp(dev->slot_name,"PNP0c01") &&  /* memory controller */
-			0 != strcmp(dev->slot_name,"PNP0c02")     /* system peripheral: other */
-		) {
-			continue;
-		}  
-		reserve_resources_of_dev(dev);
-	}
-
-	return;
-}
-
-
-/* 
- *
- * INIT AND EXIT
- *
- */
-
-extern int is_sony_vaio_laptop;
-
-static int pnpbios_disabled; /* = 0 */
-static int dont_reserve_resources; /* = 0 */
-int pnpbios_dont_use_current_config; /* = 0 */
-
-#ifndef MODULE
-static int __init pnpbios_setup(char *str)
-{
-	int invert;
-
-	while ((str != NULL) && (*str != '\0')) {
-		if (strncmp(str, "off", 3) == 0)
-			pnpbios_disabled=1;
-		if (strncmp(str, "on", 2) == 0)
-			pnpbios_disabled=0;
-		invert = (strncmp(str, "no-", 3) == 0);
-		if (invert)
-			str += 3;
-		if (strncmp(str, "curr", 4) == 0)
-			pnpbios_dont_use_current_config = invert;
-		if (strncmp(str, "res", 3) == 0)
-			dont_reserve_resources = invert;
-		str = strchr(str, ',');
-		if (str != NULL)
-			str += strspn(str, ", \t");
-	}
-
-	return 1;
-}
-
-__setup("pnpbios=", pnpbios_setup);
-#endif
-
-subsys_initcall(pnpbios_init);
-
-int __init pnpbios_init(void)
-{
-	union pnp_bios_expansion_header *check;
-	u8 sum;
-	int i, length, r;
-
-	spin_lock_init(&pnp_bios_lock);
-	spin_lock_init(&pnpbios_devices_lock);
-
-	if(pnpbios_disabled) {
-		printk(KERN_INFO "PnPBIOS: Disabled\n");
-		return -ENODEV;
-	}
-
-	if ( is_sony_vaio_laptop )
-		pnpbios_dont_use_current_config = 1;
-
-	/*
- 	 * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS
-	 * structure and, if one is found, sets up the selectors and
-	 * entry points
-	 */
-	for (check = (union pnp_bios_expansion_header *) __va(0xf0000);
-	     check < (union pnp_bios_expansion_header *) __va(0xffff0);
-	     ((void *) (check)) += 16) {
-		if (check->fields.signature != PNP_SIGNATURE)
-			continue;
-		length = check->fields.length;
-		if (!length)
-			continue;
-		for (sum = 0, i = 0; i < length; i++)
-			sum += check->chars[i];
-		if (sum)
-			continue;
-		if (check->fields.version < 0x10) {
-			printk(KERN_WARNING "PnPBIOS: PnP BIOS version %d.%d is not supported\n",
-			       check->fields.version >> 4,
-			       check->fields.version & 15);
-			continue;
-		}
-		printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", check);
-		printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n",
-                       check->fields.version >> 4, check->fields.version & 15,
-		       check->fields.pm16cseg, check->fields.pm16offset,
-		       check->fields.pm16dseg);
-		pnp_bios_callpoint.offset = check->fields.pm16offset;
-		pnp_bios_callpoint.segment = PNP_CS16;
-		pnp_bios_hdr = check;
-
-		for(i=0; i < NR_CPUS; i++)
-		{
-			Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
-			Q_SET_SEL(i, PNP_CS16, check->fields.pm16cseg, 64 * 1024);
-			Q_SET_SEL(i, PNP_DS, check->fields.pm16dseg, 64 * 1024);
-		}
-		break;
-	}
-	if (!pnp_bios_present())
-		return -ENODEV;
-	build_devlist();
-	if ( ! dont_reserve_resources )
-		reserve_resources();
-#ifdef CONFIG_PROC_FS
-	r = pnpbios_proc_init();
-	if (r)
-		return r;
-#endif
-	return 0;
-}
-
-static int __init pnpbios_thread_init(void)
-{
-#ifdef CONFIG_HOTPLUG	
-	init_completion(&unload_sem);
-	if (kernel_thread(pnp_dock_thread, NULL, CLONE_KERNEL) > 0)
-		unloading = 0;
-#endif		
-	return 0;
-}
-
-#ifndef MODULE
-
-/* init/main.c calls pnpbios_init early */
-
-/* Start the kernel thread later: */
-module_init(pnpbios_thread_init);
-
-#else
-
-/*
- * N.B.: Building pnpbios as a module hasn't been fully implemented
- */
-
-MODULE_LICENSE("GPL");
-
-static int __init pnpbios_init_all(void)
-{
-	int r;
-
-	r = pnpbios_init();
-	if (r)
-		return r;
-	r = pnpbios_thread_init();
-	if (r)
-		return r;
-	return 0;
-}
-
-static void __exit pnpbios_exit(void)
-{
-#ifdef CONFIG_HOTPLUG
-	unloading = 1;
-	wait_for_completion(&unload_sem);
-#endif
-	pnpbios_proc_exit();
-	/* We ought to free resources here */
-	return;
-}
-
-module_init(pnpbios_init_all);
-module_exit(pnpbios_exit);
-
-#endif
diff -Nru a/drivers/pnp/pnpbios_proc.c b/drivers/pnp/pnpbios_proc.c
--- a/drivers/pnp/pnpbios_proc.c	Fri Oct 18 21:03:08 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,279 +0,0 @@
-/*
- * /proc/bus/pnp interface for Plug and Play devices
- *
- * Written by David Hinds, dahinds@users.sourceforge.net
- * Modified by Thomas Hood, jdthood@mail.com
- *
- * The .../devices and .../<node> and .../boot/<node> files are
- * utilized by the lspnp and setpnp utilities, supplied with the
- * pcmcia-cs package.
- *     http://pcmcia-cs.sourceforge.net
- *
- * The .../escd file is utilized by the lsescd utility written by
- * Gunther Mayer.
- *     http://home.t-online.de/home/gunther.mayer/lsescd
- *
- * The .../legacy_device_resources file is not used yet.
- *
- * The other files are human-readable.
- */
-
-//#include <pcmcia/config.h>
-#define __NO_VERSION__
-//#include <pcmcia/k_compat.h>
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/pnpbios.h>
-#include <linux/init.h>
-
-static struct proc_dir_entry *proc_pnp = NULL;
-static struct proc_dir_entry *proc_pnp_boot = NULL;
-static struct pnp_dev_node_info node_info;
-
-static int proc_read_pnpconfig(char *buf, char **start, off_t pos,
-                               int count, int *eof, void *data)
-{
-	struct pnp_isa_config_struc pnps;
-
-	if (pnp_bios_isapnp_config(&pnps))
-		return -EIO;
-	return snprintf(buf, count,
-		"structure_revision %d\n"
-		"number_of_CSNs %d\n"
-		"ISA_read_data_port 0x%x\n",
-		pnps.revision,
-		pnps.no_csns,
-		pnps.isa_rd_data_port
-	);
-}
-
-static int proc_read_escdinfo(char *buf, char **start, off_t pos,
-                              int count, int *eof, void *data)
-{
-	struct escd_info_struc escd;
-
-	if (pnp_bios_escd_info(&escd))
-		return -EIO;
-	return snprintf(buf, count,
-		"min_ESCD_write_size %d\n"
-		"ESCD_size %d\n"
-		"NVRAM_base 0x%x\n",
-		escd.min_escd_write_size,
-		escd.escd_size,
-		escd.nv_storage_base
-	);
-}
-
-#define MAX_SANE_ESCD_SIZE (32*1024)
-static int proc_read_escd(char *buf, char **start, off_t pos,
-                          int count, int *eof, void *data)
-{
-	struct escd_info_struc escd;
-	char *tmpbuf;
-	int escd_size, escd_left_to_read, n;
-
-	if (pnp_bios_escd_info(&escd))
-		return -EIO;
-
-	/* sanity check */
-	if (escd.escd_size > MAX_SANE_ESCD_SIZE) {
-		printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by BIOS escd_info call is too great\n");
-		return -EFBIG;
-	}
-
-	tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
-	if (!tmpbuf) return -ENOMEM;
-
-	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base))
-		return -EIO;
-
-	escd_size = (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1])*256;
-
-	/* sanity check */
-	if (escd_size > MAX_SANE_ESCD_SIZE) {
-		printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by BIOS read_escd call is too great\n");
-		return -EFBIG;
-	}
-
-	escd_left_to_read = escd_size - pos;
-	if (escd_left_to_read < 0) escd_left_to_read = 0;
-	if (escd_left_to_read == 0) *eof = 1;
-	n = min(count,escd_left_to_read);
-	memcpy(buf, tmpbuf + pos, n);
-	kfree(tmpbuf);
-	*start = buf;
-	return n;
-}
-
-static int proc_read_legacyres(char *buf, char **start, off_t pos,
-                               int count, int *eof, void *data)
-{
-	/* Assume that the following won't overflow the buffer */
-	if (pnp_bios_get_stat_res(buf)) 
-		return -EIO;
-
-	return count;  // FIXME: Return actual length
-}
-
-static int proc_read_devices(char *buf, char **start, off_t pos,
-                             int count, int *eof, void *data)
-{
-	struct pnp_bios_node *node;
-	u8 nodenum;
-	char *p = buf;
-
-	if (pos >= 0xff)
-		return 0;
-
-	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
-	if (!node) return -ENOMEM;
-
-	for (nodenum=pos; nodenum<0xff; ) {
-		u8 thisnodenum = nodenum;
-		/* 26 = the number of characters per line sprintf'ed */
-		if ((p - buf + 26) > count)
-			break;
-		if (pnp_bios_get_dev_node(&nodenum, 1, node))
-			break;
-		p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
-			     node->handle, node->eisa_id,
-			     node->type_code[0], node->type_code[1],
-			     node->type_code[2], node->flags);
-		if (nodenum <= thisnodenum) {
-			printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_read_devices:", (unsigned int)nodenum, (unsigned int)thisnodenum);
-			*eof = 1;
-			break;
-		}
-	}
-	kfree(node);
-	if (nodenum == 0xff)
-		*eof = 1;
-	*start = (char *)((off_t)nodenum - pos);
-	return p - buf;
-}
-
-static int proc_read_node(char *buf, char **start, off_t pos,
-                          int count, int *eof, void *data)
-{
-	struct pnp_bios_node *node;
-	int boot = (long)data >> 8;
-	u8 nodenum = (long)data;
-	int len;
-
-	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
-	if (!node) return -ENOMEM;
-	if (pnp_bios_get_dev_node(&nodenum, boot, node))
-		return -EIO;
-	len = node->size - sizeof(struct pnp_bios_node);
-	memcpy(buf, node->data, len);
-	kfree(node);
-	return len;
-}
-
-static int proc_write_node(struct file *file, const char *buf,
-                           unsigned long count, void *data)
-{
-	struct pnp_bios_node *node;
-	int boot = (long)data >> 8;
-	u8 nodenum = (long)data;
-
-	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
-	if (!node) return -ENOMEM;
-	if ( pnp_bios_get_dev_node(&nodenum, boot, node) )
-		return -EIO;
-	if (count != node->size - sizeof(struct pnp_bios_node))
-		return -EINVAL;
-	memcpy(node->data, buf, count);
-	if (pnp_bios_set_dev_node(node->handle, boot, node) != 0)
-	    return -EINVAL;
-	kfree(node);
-	return count;
-}
-
-/*
- * When this is called, pnpbios functions are assumed to
- * work and the pnpbios_dont_use_current_config flag
- * should already have been set to the appropriate value
- */
-int __init pnpbios_proc_init( void )
-{
-	struct pnp_bios_node *node;
-	struct proc_dir_entry *ent;
-	char name[3];
-	u8 nodenum;
-
-	if (pnp_bios_dev_node_info(&node_info))
-		return -EIO;
-	
-	proc_pnp = proc_mkdir("pnp", proc_bus);
-	if (!proc_pnp)
-		return -EIO;
-	proc_pnp_boot = proc_mkdir("boot", proc_pnp);
-	if (!proc_pnp_boot)
-		return -EIO;
-	create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL);
-	create_proc_read_entry("configuration_info", 0, proc_pnp, proc_read_pnpconfig, NULL);
-	create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, NULL);
-	create_proc_read_entry("escd", S_IRUSR, proc_pnp, proc_read_escd, NULL);
-	create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL);
-	
-	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
-	if (!node)
-		return -ENOMEM;
-
-	for (nodenum=0; nodenum<0xff; ) {
-		u8 thisnodenum = nodenum;
-		if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0)
-			break;
-		sprintf(name, "%02x", node->handle);
-		if ( !pnpbios_dont_use_current_config ) {
-			ent = create_proc_entry(name, 0, proc_pnp);
-			if (ent) {
-				ent->read_proc = proc_read_node;
-				ent->write_proc = proc_write_node;
-				ent->data = (void *)(long)(node->handle);
-			}
-		}
-		ent = create_proc_entry(name, 0, proc_pnp_boot);
-		if (ent) {
-			ent->read_proc = proc_read_node;
-			ent->write_proc = proc_write_node;
-			ent->data = (void *)(long)(node->handle+0x100);
-		}
-		if (nodenum <= thisnodenum) {
-			printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_init:", (unsigned int)nodenum, (unsigned int)thisnodenum);
-			break;
-		}
-	}
-	kfree(node);
-
-	return 0;
-}
-
-void __exit pnpbios_proc_exit(void)
-{
-	int i;
-	char name[3];
-	
-	if (!proc_pnp) return;
-
-	for (i=0; i<0xff; i++) {
-		sprintf(name, "%02x", i);
-		if ( !pnpbios_dont_use_current_config )
-			remove_proc_entry(name, proc_pnp);
-		remove_proc_entry(name, proc_pnp_boot);
-	}
-	remove_proc_entry("legacy_device_resources", proc_pnp);
-	remove_proc_entry("escd", proc_pnp);
-	remove_proc_entry("escd_info", proc_pnp);
-	remove_proc_entry("configuration_info", proc_pnp);
-	remove_proc_entry("devices", proc_pnp);
-	remove_proc_entry("boot", proc_pnp);
-	remove_proc_entry("pnp", proc_bus);
-
-	return;
-}
diff -Nru a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
--- a/drivers/pnp/quirks.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/pnp/quirks.c	Fri Oct 18 21:03:08 2002
@@ -1,5 +1,5 @@
 /*
- *  This file contains quirk handling code for ISAPnP devices
+ *  This file contains quirk handling code for PnP devices
  *  Some devices do not report all their resources, and need to have extra
  *  resources added. This is most easily accomplished at initialisation time
  *  when building up the resource structure for the first time.
@@ -11,21 +11,25 @@
  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/isapnp.h>
 #include <linux/string.h>
 
-#if 0
-#define ISAPNP_DEBUG
+#ifdef CONFIG_PNP_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
 #endif
 
-static void __init quirk_awe32_resources(struct pci_dev *dev)
+#include <linux/pnp.h>
+#include "base.h"
+
+
+static void quirk_awe32_resources(struct pnp_dev *dev)
 {
-	struct isapnp_port *port, *port2, *port3;
-	struct isapnp_resources *res = dev->sysdata;
+	struct pnp_port *port, *port2, *port3;
+	struct pnp_resources *res = dev->res->dep;
 
 	/*
 	 * Unfortunately the isapnp_add_port_resource is too tightly bound
@@ -33,14 +37,14 @@
 	 * two extra ports (at offset 0x400 and 0x800 from the one given) by
 	 * hand.
 	 */
-	for ( ; res ; res = res->alt ) {
-		port2 = isapnp_alloc(sizeof(struct isapnp_port));
-		port3 = isapnp_alloc(sizeof(struct isapnp_port));
+	for ( ; res ; res = res->dep ) {
+		port2 = pnp_alloc(sizeof(struct pnp_port));
+		port3 = pnp_alloc(sizeof(struct pnp_port));
 		if (!port2 || !port3)
 			return;
 		port = res->port;
-		memcpy(port2, port, sizeof(struct isapnp_port));
-		memcpy(port3, port, sizeof(struct isapnp_port));
+		memcpy(port2, port, sizeof(struct pnp_port));
+		memcpy(port3, port, sizeof(struct pnp_port));
 		port->next = port2;
 		port2->next = port3;
 		port2->min += 0x400;
@@ -48,18 +52,18 @@
 		port3->min += 0x800;
 		port3->max += 0x800;
 	}
-	printk(KERN_INFO "isapnp: AWE32 quirk - adding two ports\n");
+	printk(KERN_INFO "pnp: AWE32 quirk - adding two ports\n");
 }
 
-static void __init quirk_cmi8330_resources(struct pci_dev *dev)
+static void quirk_cmi8330_resources(struct pnp_dev *dev)
 {
-	struct isapnp_resources *res = dev->sysdata;
+	struct pnp_resources *res = dev->res->dep;
 
-	for ( ; res ; res = res->alt ) {
+	for ( ; res ; res = res->dep ) {
+
+		struct pnp_irq *irq;
+		struct pnp_dma *dma;
 
-		struct isapnp_irq *irq;
-		struct isapnp_dma *dma;
-	
 		for( irq = res->irq; irq; irq = irq->next )	// Valid irqs are 5, 7, 10
 			irq->map = 0x04A0;						// 0000 0100 1010 0000
 
@@ -67,22 +71,22 @@
 			if( ( dma->flags & IORESOURCE_DMA_TYPE_MASK ) == IORESOURCE_DMA_8BIT )
 				dma->map = 0x000A;
 	}
-	printk(KERN_INFO "isapnp: CMI8330 quirk - fixing interrupts and dma\n");
+	printk(KERN_INFO "pnp: CMI8330 quirk - fixing interrupts and dma\n");
 }
 
-static void __init quirk_sb16audio_resources(struct pci_dev *dev)
+static void quirk_sb16audio_resources(struct pnp_dev *dev)
 {
-	struct isapnp_port *port;
-	struct isapnp_resources *res = dev->sysdata;
+	struct pnp_port *port;
+	struct pnp_resources *res = dev->res->dep;
 	int    changed = 0;
 
-	/* 
+	/*
 	 * The default range on the mpu port for these devices is 0x388-0x388.
 	 * Here we increase that range so that two such cards can be
 	 * auto-configured.
 	 */
-	
-	for( ; res ; res = res->alt ) {
+
+	for( ; res ; res = res->dep ) {
 		port = res->port;
 		if(!port)
 			continue;
@@ -98,82 +102,68 @@
 		changed = 1;
 	}
 	if(changed)
-		printk(KERN_INFO "isapnp: SB audio device quirk - increasing port range\n");
+		printk(KERN_INFO "pnp: SB audio device quirk - increasing port range\n");
 	return;
 }
 
-extern int isapnp_allow_dma0;
-static void __init quirk_opl3sax_resources(struct pci_dev *dev)
+extern int pnp_allow_dma0;
+static void quirk_opl3sax_resources(struct pnp_dev *dev)
 {
 	/* This really isn't a device quirk but isapnp core code
 	 * doesn't allow a DMA channel of 0, afflicted card is an
 	 * OPL3Sax where x=4.
 	 */
-	struct isapnp_resources *res;
+	struct pnp_resources *res;
 	int max;
-	res = (struct isapnp_resources *)dev->sysdata;
-	max = res->dma->map;
-	for (res = res->alt; res; res = res->alt) {
+	res = dev->res;
+	max = 0;
+	for (res = res->dep; res; res = res->dep) {
 		if (res->dma->map > max)
 			max = res->dma->map;
 	}
-	if (max == 1 && isapnp_allow_dma0 == -1) {
-		printk(KERN_INFO "isapnp: opl3sa4 quirk: Allowing dma 0.\n");
-		isapnp_allow_dma0 = 1;
+	if (max == 1 && pnp_allow_dma0 == -1) {
+		printk(KERN_INFO "pnp: opl3sa4 quirk: Allowing dma 0.\n");
+		pnp_allow_dma0 = 1;
 	}
 	return;
 }
 
 /*
- *  ISAPnP Quirks
- *  Cards or devices that need some tweaking due to broken hardware
+ *  PnP Quirks
+ *  Cards or devices that need some tweaking due to incomplete resource info
  */
 
-static struct isapnp_fixup isapnp_fixups[] __initdata = {
+static struct pnp_fixup pnp_fixups[] = {
 	/* Soundblaster awe io port quirk */
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021),
-		quirk_awe32_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0022),
-		quirk_awe32_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0023),
-		quirk_awe32_resources },
+	{ "CTL0021", quirk_awe32_resources },
+	{ "CTL0022", quirk_awe32_resources },
+	{ "CTL0023", quirk_awe32_resources },
 	/* CMI 8330 interrupt and dma fix */
-	{ ISAPNP_VENDOR('@','X','@'), ISAPNP_DEVICE(0x0001),
-		quirk_cmi8330_resources },
+	{ "@X@0001", quirk_cmi8330_resources },
 	/* Soundblaster audio device io port range quirk */
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0001),
-		quirk_sb16audio_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0031),
-		quirk_sb16audio_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0041),
-		quirk_sb16audio_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042),
-		quirk_sb16audio_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043),
-		quirk_sb16audio_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
-		quirk_sb16audio_resources },
-	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
-		quirk_sb16audio_resources },
-	{ ISAPNP_VENDOR('Y','M','H'), ISAPNP_DEVICE(0x0021),
-		quirk_opl3sax_resources },
-	{ 0 }
+	{ "CTL0001", quirk_sb16audio_resources },
+	{ "CTL0031", quirk_sb16audio_resources },
+	{ "CTL0041", quirk_sb16audio_resources },
+	{ "CTL0042", quirk_sb16audio_resources },
+	{ "CTL0043", quirk_sb16audio_resources },
+	{ "CTL0044", quirk_sb16audio_resources },
+	{ "CTL0045", quirk_sb16audio_resources },
+	{ "YMH0021", quirk_opl3sax_resources },
+	{ "" }
 };
 
-void isapnp_fixup_device(struct pci_dev *dev)
+void pnp_fixup_device(struct pnp_dev *dev)
 {
 	int i = 0;
 
-	while (isapnp_fixups[i].vendor != 0) {
-		if ((isapnp_fixups[i].vendor == dev->vendor) &&
-		    (isapnp_fixups[i].device == dev->device)) {
-#ifdef ISAPNP_DEBUG
-			printk(KERN_DEBUG "isapnp: Calling quirk for %02x:%02x\n",
-			       dev->bus->number, dev->devfn);
-#endif
-			isapnp_fixups[i].quirk_function(dev);
+	while (*pnp_fixups[i].id) {
+		if (compare_pnp_id(&dev->ids,pnp_fixups[i].id)) {
+			pnp_dbg("Calling quirk for %s",
+		                  dev->dev.bus_id);
+			pnp_fixups[i].quirk_function(dev);
 		}
 		i++;
 	}
+	return;
 }
 
diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/resource.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,880 @@
+/*
+ * resource.c - contains resource management algorithms
+ *
+ * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_PNP_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+
+#include <linux/pnp.h>
+#include "base.h"
+
+int pnp_allow_dma0 = -1;		        /* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */
+int pnp_skip_pci_scan;				/* skip PCI resource scanning */
+int pnp_reserve_irq[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some IRQ */
+int pnp_reserve_dma[8] = { [0 ... 7] = -1 };	/* reserve (don't use) some DMA */
+int pnp_reserve_io[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some I/O region */
+int pnp_reserve_mem[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some memory region */
+
+
+/* resource information adding functions */
+
+struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent)
+{
+	struct pnp_resources *res, *ptr, *ptra;
+
+	res = pnp_alloc(sizeof(struct pnp_resources));
+	if (!res)
+		return NULL;
+	ptr = dev->res;
+	if (ptr && ptr->dependent && dependent) { /* add to another list */
+		ptra = ptr->dep;
+		while (ptra && ptra->dep)
+			ptra = ptra->dep;
+		if (!ptra)
+			ptr->dep = res;
+		else
+			ptra->dep = res;
+	} else {
+		if (!ptr){
+			dev->res = res;
+		}
+		else{
+			kfree(res);
+			return NULL;
+		}
+	}
+	if (dependent) {
+		res->priority = dependent & 0xff;
+		if (res->priority > PNP_RES_PRIORITY_FUNCTIONAL)
+			res->priority = PNP_RES_PRIORITY_INVALID;
+		res->dependent = 1;
+	} else {
+		res->priority = PNP_RES_PRIORITY_PREFERRED;
+		res->dependent = 1;
+	}
+	return res;
+}
+
+struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum)
+{
+	int i;
+	struct pnp_resources *res;
+	if (!dev)
+		return NULL;
+	res = dev->res;
+	if (!res)
+		return NULL;
+	for (i = 0; i < depnum; i++)
+	{
+		if (res->dep)
+			res = res->dep;
+		else
+			return NULL;
+	}
+	return res;
+}
+
+int pnp_get_max_depnum(struct pnp_dev *dev)
+{
+	int num = 0;
+	struct pnp_resources *res;
+	if (!dev)
+		return -EINVAL;
+	res = dev->res;
+	if (!res)
+		return -EINVAL;
+	while (res->dep){
+		res = res->dep;
+		num++;
+	}
+	return num;
+}
+
+/*
+ *  Add IRQ resource to resources list.
+ */
+
+int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data)
+{
+	int i;
+	struct pnp_resources *res;
+	struct pnp_irq *ptr;
+	res = pnp_find_resources(dev,depnum);
+	if (!res)
+		return -EINVAL;
+	if (!data)
+		return -EINVAL;
+	ptr = res->irq;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = data;
+	else
+		res->irq = data;
+#ifdef CONFIG_PCI
+	for (i=0; i<16; i++)
+		if (data->map & (1<<i))
+			pcibios_penalize_isa_irq(i);
+#endif
+	return 0;
+}
+
+/*
+ *  Add DMA resource to resources list.
+ */
+
+int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data)
+{
+	struct pnp_resources *res;
+	struct pnp_dma *ptr;
+	res = pnp_find_resources(dev,depnum);
+	if (!res)
+		return -EINVAL;
+	if (!data)
+		return -EINVAL;
+	ptr = res->dma;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = data;
+	else
+		res->dma = data;
+	return 0;
+}
+
+/*
+ *  Add port resource to resources list.
+ */
+
+int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data)
+{
+	struct pnp_resources *res;
+	struct pnp_port *ptr;
+	res = pnp_find_resources(dev,depnum);
+	if (res==NULL)
+		return -EINVAL;
+	if (!data)
+		return -EINVAL;
+	data->res = res;
+	ptr = res->port;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = data;
+	else
+		res->port = data;
+	return 0;
+}
+
+/*
+ *  Add memory resource to resources list.
+ */
+
+int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data)
+{
+	struct pnp_resources *res;
+	struct pnp_mem *ptr;
+	res = pnp_find_resources(dev,depnum);
+	if (!res)
+		return -EINVAL;
+	if (!data)
+		return -EINVAL;
+	ptr = res->mem;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = data;
+	else
+		res->mem = data;
+	return 0;
+}
+
+/*
+ *  Add 32-bit memory resource to resources list.
+ */
+
+int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_mem32 *data)
+{
+	struct pnp_resources *res;
+	struct pnp_mem32 *ptr;
+	res = pnp_find_resources(dev,depnum);
+	if (!res)
+		return -EINVAL;
+	if (!data)
+		return -EINVAL;
+	ptr = res->mem32;
+	while (ptr && ptr->next)
+		ptr = ptr->next;
+	if (ptr)
+		ptr->next = data;
+	else
+		res->mem32 = data;
+	return 0;
+}
+
+
+/* resource removing functions */
+
+static void pnp_free_port(struct pnp_port *port)
+{
+	struct pnp_port *next;
+
+	while (port) {
+		next = port->next;
+		kfree(port);
+		port = next;
+	}
+}
+
+static void pnp_free_irq(struct pnp_irq *irq)
+{
+	struct pnp_irq *next;
+
+	while (irq) {
+		next = irq->next;
+		kfree(irq);
+		irq = next;
+	}
+}
+
+static void pnp_free_dma(struct pnp_dma *dma)
+{
+	struct pnp_dma *next;
+
+	while (dma) {
+		next = dma->next;
+		kfree(dma);
+		dma = next;
+	}
+}
+
+static void pnp_free_mem(struct pnp_mem *mem)
+{
+	struct pnp_mem *next;
+
+	while (mem) {
+		next = mem->next;
+		kfree(mem);
+		mem = next;
+	}
+}
+
+static void pnp_free_mem32(struct pnp_mem32 *mem32)
+{
+	struct pnp_mem32 *next;
+
+	while (mem32) {
+		next = mem32->next;
+		kfree(mem32);
+		mem32 = next;
+	}
+}
+
+void pnp_free_resources(struct pnp_resources *resources)
+{
+	struct pnp_resources *next;
+
+	while (resources) {
+		next = resources->dep;
+		pnp_free_port(resources->port);
+		pnp_free_irq(resources->irq);
+		pnp_free_dma(resources->dma);
+		pnp_free_mem(resources->mem);
+		pnp_free_mem32(resources->mem32);
+		kfree(resources);
+		resources = next;
+	}
+}
+
+
+/* resource validity checking functions */
+
+static int pnp_check_port(int port, int size)
+{
+	int i, tmp, rport, rsize;
+	struct pnp_dev *dev;
+
+	if (check_region(port, size))
+		return 1;
+	for (i = 0; i < 8; i++) {
+		rport = pnp_reserve_io[i << 1];
+		rsize = pnp_reserve_io[(i << 1) + 1];
+		if (port >= rport && port < rport + rsize)
+			return 1;
+		if (port + size > rport && port + size < (rport + rsize) - 1)
+			return 1;
+	}
+
+	pnp_for_each_dev(dev) {
+		if (dev->active) {
+			for (tmp = 0; tmp < 8; tmp++) {
+				if (dev->resource[tmp].flags) {
+					rport = dev->resource[tmp].start;
+					rsize = (dev->resource[tmp].end - rport) + 1;
+					if (port >= rport && port < rport + rsize)
+						return 1;
+					if (port + size > rport && port + size < (rport + rsize) - 1)
+						return 1;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+static int pnp_check_mem(unsigned int addr, unsigned int size)
+{
+	int i, tmp;
+	unsigned int raddr, rsize;
+	struct pnp_dev *dev;
+
+	for (i = 0; i < 8; i++) {
+		raddr = (unsigned int)pnp_reserve_mem[i << 1];
+		rsize = (unsigned int)pnp_reserve_mem[(i << 1) + 1];
+		if (addr >= raddr && addr < raddr + rsize)
+			return 1;
+		if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
+			return 1;
+		if (__check_region(&iomem_resource, addr, size))
+			return 1;
+	}
+	pnp_for_each_dev(dev) {
+		if (dev->active) {
+			for (tmp = 0; tmp < 4; tmp++) {
+				if (dev->resource[tmp].flags) {
+					raddr = dev->resource[tmp + 8].start;
+					rsize = (dev->resource[tmp + 8].end - raddr) + 1;
+					if (addr >= raddr && addr < raddr + rsize)
+						return 1;
+					if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
+						return 1;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+static void pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+static int pnp_check_interrupt(int irq, struct pnp_cfg *config)
+{
+	int i;
+#ifdef CONFIG_PCI
+	struct pci_dev *pci;
+#endif
+	struct pnp_dev *dev;
+	if (!config)
+		return 1;
+
+	if (irq < 0 || irq > 15)
+		return 1;
+	for (i = 0; i < 16; i++) {
+		if (pnp_reserve_irq[i] == irq)
+			return 1;
+	}
+	pnp_for_each_dev(dev) {
+		if (dev->active) {
+			if ((dev->irq_resource[0].flags && dev->irq_resource[0].start == irq) ||
+			    (dev->irq_resource[1].flags && dev->irq_resource[1].start == irq))
+				return 1;
+		}
+	}
+	if (config->request.irq_resource[0].flags && config->request.irq_resource[1].flags &&
+	   (config->request.irq_resource[0].start == irq))
+		return 1;
+#ifdef CONFIG_PCI
+	if (!pnp_skip_pci_scan) {
+		pci_for_each_dev(pci) {
+			if (pci->irq == irq)
+				return 1;
+		}
+	}
+#endif
+	if (request_irq(irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL))
+		return 1;
+	free_irq(irq, NULL);
+	return 0;
+}
+
+static int pnp_check_dma(int dma, struct pnp_cfg *config)
+{
+	int i, mindma = 1;
+	struct pnp_dev *dev;
+	if (!config)
+		return 1;
+
+	if (pnp_allow_dma0 == 1)
+		mindma = 0;
+	if (dma < mindma || dma == 4 || dma > 7)
+		return 1;
+	for (i = 0; i < 8; i++) {
+		if (pnp_reserve_dma[i] == dma)
+			return 1;
+	}
+	pnp_for_each_dev(dev) {
+		if (dev->active) {
+			if ((dev->dma_resource[0].flags && dev->dma_resource[0].start == dma) ||
+			    (dev->dma_resource[1].flags && dev->dma_resource[1].start == dma))
+				return 1;
+		}
+	}
+	if (config->request.dma_resource[0].flags && config->request.dma_resource[1].flags &&
+	   (config->request.dma_resource[0].start == dma))
+		return 1;
+	if (request_dma(dma, "pnp"))
+		return 1;
+	free_dma(dma);
+	return 0;
+}
+
+
+/* config generation functions */
+static int pnp_generate_port(struct pnp_cfg *config, int num)
+{
+	struct pnp_port *port = config->port[num];
+	unsigned long *value1, *value2, *value3;
+	if (!config || num < 0 || num > 7)
+		return -EINVAL;
+	if (!port)
+		return 0;
+	value1 = &config->request.resource[num].start;
+	value2 = &config->request.resource[num].end;
+	value3 = &config->request.resource[num].flags;
+	*value1 = port->min;
+	*value2 = *value1 + port->size -1;
+	*value3 = port->flags | IORESOURCE_IO;
+	while (pnp_check_port(*value1, port->size)) {
+		*value1 += port->align;
+		*value2 = *value1 + port->size - 1;
+		if (*value1 > port->max || !port->align)
+			return -ENOENT;
+	}
+	return 0;
+}
+
+static int pnp_generate_mem(struct pnp_cfg *config, int num)
+{
+	struct pnp_mem *mem = config->mem[num];
+	unsigned long *value1, *value2, *value3;
+	if (!config || num < 0 || num > 3)
+		return -EINVAL;
+	if (!mem)
+		return 0;
+	value1 = &config->request.resource[num + 8].start;
+	value2 = &config->request.resource[num + 8].end;
+	value3 = &config->request.resource[num].flags;
+	*value1 = mem->min;
+	*value2 = *value1 + mem->size -1;
+	*value3 = mem->flags | IORESOURCE_MEM;
+	if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))
+		*value3 |= IORESOURCE_READONLY;
+	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
+		*value3 |= IORESOURCE_CACHEABLE;
+	if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
+		*value3 |= IORESOURCE_RANGELENGTH;
+	if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
+		*value3 |= IORESOURCE_SHADOWABLE;
+	while (pnp_check_mem(*value1, mem->size)) {
+		*value1 += mem->align;
+		*value2 = *value1 + mem->size - 1;
+		if (*value1 > mem->max || !mem->align)
+			return -ENOENT;
+	}
+	return 0;
+}
+
+static int pnp_generate_irq(struct pnp_cfg *config, int num)
+{
+	struct pnp_irq *irq = config->irq[num];
+	unsigned long *value1, *value2, *value3;
+	/* IRQ priority: this table is good for i386 */
+	static unsigned short xtab[16] = {
+		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
+	};
+	int i;
+	if (!config || num < 0 || num > 1)
+		return -EINVAL;
+	if (!irq)
+		return 0;
+	value1 = &config->request.irq_resource[num].start;
+	value2 = &config->request.irq_resource[num].end;
+	value3 = &config->request.irq_resource[num].flags;
+	*value3 = irq->flags | IORESOURCE_IRQ;
+
+	for (i=0; i < 16; i++)
+	{
+		if(irq->map & (1<<xtab[i])) {
+		*value1 = *value2 = xtab[i];
+		if(pnp_check_interrupt(*value1,config)==0)
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+static int pnp_generate_dma(struct pnp_cfg *config, int num)
+{
+	struct pnp_dma *dma = config->dma[num];
+	unsigned long *value1, *value2, *value3;
+	/* DMA priority: this table is good for i386 */
+	static unsigned short xtab[16] = {
+		1, 3, 5, 6, 7, 0, 2, 4
+	};
+	int i;
+
+	if (!config || num < 0 || num > 1)
+		return -EINVAL;
+	if (!dma)
+		return 0;
+	value1 = &config->request.dma_resource[num].start;
+	value2 = &config->request.dma_resource[num].end;
+	value3 = &config->request.dma_resource[num].flags;
+	*value3 = dma->flags | IORESOURCE_DMA;
+
+	for (i=0; i < 8; i++)
+	{
+		if(dma->map & (1<<xtab[i])) {
+		*value1 = *value2 = xtab[i];
+		if(pnp_check_dma(*value1,config)==0)
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+static int pnp_prepare_request(struct pnp_cfg *config)
+{
+	struct pnp_dev *dev = &config->request;
+	int idx;
+	if (!config)
+		return -EINVAL;
+	if (dev == NULL)
+		return -EINVAL;
+	if (dev->active || dev->ro)
+		return -EBUSY;
+	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
+		dev->irq_resource[idx].name = NULL;
+		dev->irq_resource[idx].start = -1;
+		dev->irq_resource[idx].end = -1;
+		dev->irq_resource[idx].flags = 0;
+	}
+	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
+		dev->dma_resource[idx].name = NULL;
+		dev->dma_resource[idx].start = -1;
+		dev->dma_resource[idx].end = -1;
+		dev->dma_resource[idx].flags = 0;
+	}
+	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
+		dev->resource[idx].name = NULL;
+		dev->resource[idx].start = 0;
+		dev->resource[idx].end = 0;
+		dev->resource[idx].flags = 0;
+	}
+	return 0;
+}
+
+static int pnp_generate_request(struct pnp_cfg *config)
+{
+	int i;
+	if (!config)
+		return -EINVAL;
+	if (pnp_prepare_request<0)
+		return -ENOENT;
+	for (i=0; i<=7; i++)
+	{
+		if(pnp_generate_port(config,i)<0)
+			return -ENOENT;
+	}
+	for (i=0; i<=3; i++)
+	{
+		if(pnp_generate_mem(config,i)<0)
+			return -ENOENT;
+	}
+	for (i=0; i<=1; i++)
+	{
+		if(pnp_generate_irq(config,i)<0)
+			return -ENOENT;
+	}
+	for (i=0; i<=1; i++)
+	{
+		if(pnp_generate_dma(config,i)<0)
+			return -ENOENT;
+	}
+	return 0;
+}
+
+
+
+static struct pnp_cfg * pnp_generate_config(struct pnp_dev *dev, int depnum)
+{
+	struct pnp_cfg * config = pnp_alloc(sizeof(struct pnp_cfg));
+	int nport = 0, nirq = 0, ndma = 0, nmem = 0;
+	struct pnp_resources * res = dev->res;
+	struct pnp_port * port = res->port;
+	struct pnp_mem * mem = res->mem;
+	struct pnp_irq * irq = res->irq;
+	struct pnp_dma * dma = res->dma;
+	if (!dev)
+		return NULL;
+	if (depnum < 0)
+		return NULL;
+	if (!config)
+		return NULL;
+
+	/* independent */
+	while (port){
+		config->port[nport] = port;
+		nport++;
+		port = port->next;
+	}
+	while (mem){
+		config->mem[nmem] = mem;
+		nmem++;
+		mem = mem->next;
+	}
+	while (irq){
+		config->irq[nirq] = irq;
+		nirq++;
+		irq = irq->next;
+	}
+	while (dma){
+		config->dma[ndma] = dma;
+		ndma++;
+		dma = dma->next;
+	}
+
+	/* dependent */
+	if (depnum == 0)
+		return config;
+	res = pnp_find_resources(dev, depnum);
+	port = res->port;
+	mem = res->mem;
+	irq = res->irq;
+	dma = res->dma;
+	while (port){
+		config->port[nport] = port;
+		nport++;
+		port = port->next;
+	}
+	while (mem){
+		config->mem[nmem] = mem;
+		nmem++;
+		mem = mem->next;
+	}
+
+	while (irq){
+		config->irq[nirq] = irq;
+		nirq++;
+		irq = irq->next;
+	}
+	while (dma){
+		config->dma[ndma] = dma;
+		ndma++;
+		dma = dma->next;
+	}
+	return config;
+}
+
+/* PnP Device Resource Management */
+
+/**
+ * pnp_activate_dev - activates a PnP device for use
+ * @dev: pointer to the desired device
+ *
+ * finds the best resource configuration and then informs the correct pnp protocol
+ */
+
+int pnp_activate_dev(struct pnp_dev *dev)
+{
+	int depnum, max;
+	struct pnp_cfg *config;
+	if (!dev)
+		return -EINVAL;
+        max = pnp_get_max_depnum(dev);
+	if (dev->active)
+		return -EBUSY;
+	if (dev->driver){
+		printk(KERN_INFO "pnp: Automatic configuration failed because the PnP device '%s' is busy\n", dev->dev.bus_id);
+		return -EINVAL;
+	}
+	if (!dev->protocol->get || !dev->protocol->set)
+		return -EINVAL;
+	if (max == 0)
+		return 0;
+	for (depnum=1; depnum <= max; depnum++)
+	{
+		config = pnp_generate_config(dev,depnum);
+		if (!config)
+			return -EINVAL;
+		if (pnp_generate_request(config)==0)
+			goto done;
+		kfree(config);
+	}
+	printk(KERN_ERR "pnp: Automatic configuration failed for device '%s' due to resource conflicts\n", dev->dev.bus_id);
+	return -ENOENT;
+
+	done:
+	pnp_dbg("the device '%s' has been activated", dev->dev.bus_id);
+	dev->protocol->set(dev,config,0);
+	if (dev->protocol->get)
+		dev->protocol->get(dev);
+	kfree(config);
+	return 0;
+}
+
+/**
+ * pnp_disable_dev - disables device
+ * @dev: pointer to the desired device
+ *
+ * inform the correct pnp protocol so that resources can be used by other devices
+ */
+
+int pnp_disable_dev(struct pnp_dev *dev)
+{
+        if (!dev)
+                return -EINVAL;
+	if (dev->driver){
+		printk(KERN_INFO "pnp: Disable failed becuase the PnP device '%s' is busy\n", dev->dev.bus_id);
+		return -EINVAL;
+	}
+	if (!dev->protocol->disable || !dev->active)
+		return -EINVAL;
+	pnp_dbg("the device '%s' has been disabled", dev->dev.bus_id);
+	return dev->protocol->disable(dev);
+}
+
+/**
+ * pnp_raw_set_dev - same as pnp_activate_dev except the resource config can be specified
+ * @dev: pointer to the desired device
+ * @depnum: resource dependent function
+ * @mode: static or dynamic
+ *
+ */
+
+int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, int mode)
+{
+	struct pnp_cfg *config;
+	if (!dev)
+		return -EINVAL;
+        config = pnp_generate_config(dev,depnum);
+	if (dev->driver){
+		printk(KERN_INFO "pnp: Unable to set resources becuase the PnP device '%s' is busy\n", dev->dev.bus_id);
+		return -EINVAL;
+	}
+	if (!dev->protocol->get || !dev->protocol->set)
+		return -EINVAL;
+	if (!config)
+		return -EINVAL;
+	if (pnp_generate_request(config)==0)
+		goto done;
+	kfree(config);
+	printk(KERN_ERR "pnp: Manual configuration failed for device '%s' due to resource conflicts\n", dev->dev.bus_id);
+	return -ENOENT;
+
+	done:
+	dev->protocol->set(dev,config,mode);
+	if (dev->protocol->get)
+		dev->protocol->get(dev);
+	kfree(config);
+	return 0;
+}
+
+EXPORT_SYMBOL(pnp_build_resource);
+EXPORT_SYMBOL(pnp_find_resources);
+EXPORT_SYMBOL(pnp_get_max_depnum);
+EXPORT_SYMBOL(pnp_add_irq_resource);
+EXPORT_SYMBOL(pnp_add_dma_resource);
+EXPORT_SYMBOL(pnp_add_port_resource);
+EXPORT_SYMBOL(pnp_add_mem_resource);
+EXPORT_SYMBOL(pnp_add_mem32_resource);
+EXPORT_SYMBOL(pnp_activate_dev);
+EXPORT_SYMBOL(pnp_disable_dev);
+EXPORT_SYMBOL(pnp_raw_set_dev);
+
+/* format is: allowdma0 */
+
+static int __init pnp_allowdma0(char *str)
+{
+        pnp_allow_dma0 = 1;
+	return 1;
+}
+
+__setup("allowdma0", pnp_allowdma0);
+
+/* format is: pnp_reserve_irq=irq1[,irq2] .... */
+
+static int __init pnp_setup_reserve_irq(char *str)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		if (get_option(&str,&pnp_reserve_irq[i]) != 2)
+			break;
+	return 1;
+}
+
+__setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
+
+/* format is: pnp_reserve_dma=dma1[,dma2] .... */
+
+static int __init pnp_setup_reserve_dma(char *str)
+{
+	int i;
+
+	for (i = 0; i < 8; i++)
+		if (get_option(&str,&pnp_reserve_dma[i]) != 2)
+			break;
+	return 1;
+}
+
+__setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
+
+/* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
+
+static int __init pnp_setup_reserve_io(char *str)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		if (get_option(&str,&pnp_reserve_io[i]) != 2)
+			break;
+	return 1;
+}
+
+__setup("pnp_reserve_io=", pnp_setup_reserve_io);
+
+/* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
+
+static int __init pnp_setup_reserve_mem(char *str)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		if (get_option(&str,&pnp_reserve_mem[i]) != 2)
+			break;
+	return 1;
+}
+
+__setup("pnp_reserve_mem=", pnp_setup_reserve_mem);
diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/system.c	Fri Oct 18 21:03:09 2002
@@ -0,0 +1,123 @@
+/*
+ * system.c - a driver for reserving pnp system resources
+ *
+ * Some code is based on pnpbios_core.c
+ * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+#include <linux/pnp.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+
+static const struct pnp_id pnp_card_table[] = {
+	{	"ANYDEVS",		0	},
+	{	"",			0	}
+};
+
+static const struct pnp_id pnp_dev_table[] = {
+	/* General ID for reserving resources */
+	{	"PNP0c02",		0	},
+	/* memory controller */
+	{	"PNP0c01",		0	},
+	{	"",			0	}
+};
+
+static void __init reserve_ioport_range(char *pnpid, int start, int end)
+{
+	struct resource *res;
+	char *regionid;
+
+	regionid = kmalloc(16, GFP_KERNEL);
+	if ( regionid == NULL )
+		return;
+	snprintf(regionid, 16, "pnp %s", pnpid);
+	res = request_region(start,end-start+1,regionid);
+	if ( res == NULL )
+		kfree( regionid );
+	else
+		res->flags &= ~IORESOURCE_BUSY;
+	/*
+	 * Failures at this point are usually harmless. pci quirks for
+	 * example do reserve stuff they know about too, so we may well
+	 * have double reservations.
+	 */
+	printk(KERN_INFO
+		"pnp: %s: ioport range 0x%x-0x%x %s reserved\n",
+		pnpid, start, end,
+		NULL != res ? "has been" : "could not be"
+	);
+
+	return;
+}
+
+static void __init reserve_resources_of_dev( struct pnp_dev *dev )
+{
+	int i;
+
+	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
+		if ( dev->resource[i].flags & IORESOURCE_UNSET )
+			/* end of resources */
+			break;
+		if (dev->resource[i].flags & IORESOURCE_IO) {
+			/* ioport */
+			if ( dev->resource[i].start == 0 )
+				/* disabled */
+				/* Do nothing */
+				continue;
+			if ( dev->resource[i].start < 0x100 )
+				/*
+				 * Below 0x100 is only standard PC hardware
+				 * (pics, kbd, timer, dma, ...)
+				 * We should not get resource conflicts there,
+				 * and the kernel reserves these anyway
+				 * (see arch/i386/kernel/setup.c).
+				 * So, do nothing
+				 */
+				continue;
+			if ( dev->resource[i].end < dev->resource[i].start )
+				/* invalid endpoint */
+				/* Do nothing */
+				continue;
+			reserve_ioport_range(
+				dev->dev.bus_id,
+				dev->resource[i].start,
+				dev->resource[i].end
+			);
+		} else if (dev->resource[i].flags & IORESOURCE_MEM) {
+			/* iomem */
+			/* For now do nothing */
+			continue;
+		} else {
+			/* Neither ioport nor iomem */
+			/* Do nothing */
+			continue;
+		}
+	}
+
+	return;
+}
+
+static int system_pnp_probe(struct pnp_dev * dev, const struct pnp_id *card_id, const struct pnp_id *dev_id)
+{
+	reserve_resources_of_dev(dev);
+	return 0;
+}
+
+static struct pnp_driver system_pnp_driver = {
+	.name		= "system",
+	.card_id_table	= pnp_card_table,
+	.id_table	= pnp_dev_table,
+	.probe		= system_pnp_probe,
+	.remove		= NULL,
+};
+
+static int __init pnp_system_init(void)
+{
+	return pnp_register_driver(&system_pnp_driver);
+}
+
+core_initcall(pnp_system_init);
diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
--- a/drivers/sbus/char/jsflash.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/sbus/char/jsflash.c	Fri Oct 18 21:03:04 2002
@@ -190,53 +190,38 @@
 
 static void jsfd_do_request(request_queue_t *q)
 {
-	struct request *req;
-	int dev;
-	struct jsfd_part *jdp;
-	unsigned long offset;
-	size_t len;
+	while (!blk_queue_empty(q)) {
+		struct request *req = elv_next_request(q);
+		struct jsfd_part *jdp = req->rq_disk->private_data;
+		unsigned long offset = req->sector << 9;
+		size_t len = req->current_nr_sectors << 9;
 
-	for (;;) {
-		if (blk_queue_empty(QUEUE))
-			return;
-
-		req = CURRENT;
-
-		dev = MINOR(req->rq_dev);
-		if (dev >= JSF_MAX || (dev & JSF_PART_MASK) >= JSF_NPART) {
-			end_request(CURRENT, 0);
-			continue;
-		}
-		jdp = &jsf0.dv[dev & JSF_PART_MASK];
-
-		offset = req->sector << 9;
-		len = req->current_nr_sectors << 9;
 		if ((offset + len) > jdp->dsize) {
-               		end_request(CURRENT, 0);
+               		end_request(req, 0);
 			continue;
 		}
 
 		if (req->cmd == WRITE) {
 			printk(KERN_ERR "jsfd: write\n");
-			end_request(CURRENT, 0);
+			end_request(req, 0);
 			continue;
 		}
 		if (req->cmd != READ) {
 			printk(KERN_ERR "jsfd: bad req->cmd %d\n", req->cmd);
-			end_request(CURRENT, 0);
+			end_request(req, 0);
 			continue;
 		}
 
 		if ((jdp->dbase & 0xff000000) != 0x20000000) {
 			printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase);
-			end_request(CURRENT, 0);
+			end_request(req, 0);
 			continue;
 		}
 
-/* printk("jsfd%d: read buf %p off %x len %x\n", dev, req->buffer, (int)offset, (int)len); */ /* P3 */
+/* printk("%s: read buf %p off %x len %x\n", req->rq_disk->disk_name, req->buffer, (int)offset, (int)len); */ /* P3 */
 		jsfd_read(req->buffer, jdp->dbase + offset, len);
 
-		end_request(CURRENT, 1);
+		end_request(req, 1);
 	}
 }
 
@@ -564,6 +549,8 @@
 	return 0;
 }
 
+static struct request_queue jsf_queue;
+
 static int jsfd_init(void)
 {
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
@@ -590,7 +577,7 @@
 		goto out;
 	}
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), jsfd_do_request, &lock);
+	blk_init_queue(&jsf_queue, jsfd_do_request, &lock);
 	for (i = 0; i < JSF_MAX; i++) {
 		struct gendisk *disk = jsfd_disk[i];
 		if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
@@ -602,6 +589,8 @@
 		sprintf(disk->disk_name, "jsfd%d", i);
 		disk->fops = &jsfd_fops;
 		set_capacity(disk, jdp->dsize >> 9);
+		disk->private_data = jdp;
+		disk->queue = &jsf_queue;
 		add_disk(disk);
 		set_device_ro(MKDEV(JSFD_MAJOR, i), 1);
 	}
@@ -641,7 +630,7 @@
 	misc_deregister(&jsf_dev);
 	if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0)
 		printk("jsfd: cleanup_module failed\n");
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	blk_cleanup_queue(&jsf_queue);
 }
 
 module_init(jsflash_init_module);
diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/53c700.c	Fri Oct 18 21:03:03 2002
@@ -170,6 +170,8 @@
 STATIC int NCR_700_proc_directory_info(char *, char **, off_t, int, int, int);
 STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
 STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
+STATIC int NCR_700_slave_attach(Scsi_Device *SDpnt);
+STATIC void NCR_700_slave_detach(Scsi_Device *SDpnt);
 
 static char *NCR_700_phase[] = {
 	"",
@@ -280,9 +282,11 @@
 	tpnt->eh_host_reset_handler = NCR_700_host_reset;
 	tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST;
 	tpnt->sg_tablesize = NCR_700_SG_SEGMENTS;
-	tpnt->cmd_per_lun = NCR_700_MAX_TAGS;
+	tpnt->cmd_per_lun = NCR_700_CMD_PER_LUN;
 	tpnt->use_clustering = DISABLE_CLUSTERING;
 	tpnt->proc_info = NCR_700_proc_directory_info;
+	tpnt->slave_attach = NCR_700_slave_attach;
+	tpnt->slave_detach = NCR_700_slave_detach;
 	tpnt->use_blk_tcq = 1;
 	tpnt->highmem_io = 1;
 	
@@ -891,8 +895,8 @@
 			printk(KERN_WARNING "scsi%d (%d:%d) Rejected first tag queue attempt, turning off tag queueing\n", host->host_no, pun, lun);
 			NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING);
 			hostdata->tag_negotiated &= ~(1<<SCp->target);
-			SCp->device->tagged_queue = 0;
 			SCp->device->tagged_supported = 0;
+			scsi_deactivate_tcq(SCp->device);
 		} else {
 			printk(KERN_WARNING "scsi%d (%d:%d) Unexpected REJECT Message %s\n",
 			       host->host_no, pun, lun,
@@ -1719,13 +1723,11 @@
 {
 	static char buf[4096];	/* 1 page should be sufficient */
 	int len = 0;
-	struct Scsi_Host *host = scsi_hostlist;
+	struct Scsi_Host *host;
 	struct NCR_700_Host_Parameters *hostdata;
 	Scsi_Device *SDp;
 
-	while(host != NULL && host->host_no != host_no)
-		host = host->next;
-
+	host = scsi_host_hn_get(host_no);
 	if(host == NULL)
 		return 0;
 
@@ -1739,7 +1741,7 @@
 Target	Depth  Active  Next Tag\n\
 ======	=====  ======  ========\n");
 	for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) {
-		len += sprintf(&buf[len]," %2d:%2d   %4d    %4d      %4d\n", SDp->id, SDp->lun, SDp->queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);
+		len += sprintf(&buf[len]," %2d:%2d   %4d    %4d      %4d\n", SDp->id, SDp->lun, SDp->current_queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);
 	}
 	if((len -= offset) <= 0)
 		return 0;
@@ -1776,13 +1778,13 @@
 		DEBUG((KERN_ERR "scsi%d (%d:%d) has non zero depth %d\n",
 		       SCp->host->host_no, SCp->target, SCp->lun,
 		       NCR_700_get_depth(SCp->device)));
-		return 1;
+		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	if(NCR_700_get_depth(SCp->device) >= NCR_700_MAX_TAGS) {
 		DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n",
 		       SCp->host->host_no, SCp->target, SCp->lun,
 		       NCR_700_get_depth(SCp->device)));
-		return 1;
+		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1);
 
@@ -1996,6 +1998,25 @@
 	NCR_700_internal_bus_reset(SCp->host);
 	NCR_700_chip_reset(SCp->host);
 	return SUCCESS;
+}
+
+STATIC int
+NCR_700_slave_attach(Scsi_Device *SDp)
+{
+	/* to do here: allocate memory; build a queue_full list */
+	if(SDp->tagged_supported) {
+		/* do TCQ stuff here */
+	} else {
+		/* initialise to default depth */
+		scsi_adjust_queue_depth(SDp, 0, SDp->host->cmd_per_lun);
+	}
+	return 0;
+}
+
+STATIC void
+NCR_700_slave_detach(Scsi_Device *SDp)
+{
+	/* to do here: deallocate memory */
 }
 
 EXPORT_SYMBOL(NCR_700_detect);
diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
--- a/drivers/scsi/53c700.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/53c700.h	Fri Oct 18 21:03:03 2002
@@ -30,6 +30,11 @@
 /* Alter this with care: too many tags won't give the elevator a chance to
  * work; too few will cause the device to operate less efficiently */
 #define NCR_700_MAX_TAGS		16
+/* This is the default number of commands per LUN in the untagged case.
+ * two is a good value because it means we can have one command active and
+ * one command fully prepared and waiting
+ */
+#define NCR_700_CMD_PER_LUN		2
 /* magic byte identifying an internally generated REQUEST_SENSE command */
 #define NCR_700_INTERNAL_SENSE_MAGIC	0x42
 
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/Makefile	Fri Oct 18 21:03:08 2002
@@ -132,6 +132,10 @@
 cpqfc-objs	:= cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \
 		   cpqfcTSworker.o cpqfcTStrigger.o
 
+# Files generated that shall be removed upon make clean
+clean-files :=	53c8xx_d.h  53c7xx_d.h sim710_d.h  53c700_d.h	\
+		53c8xx_u.h  53c7xx_u.h sim710_u.h 53c700_u.h
+
 include $(TOPDIR)/Rules.make
 
 $(obj)/53c7,8xx.o: $(obj)/53c8xx_d.h $(obj)/53c8xx_u.h
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/NCR53C9x.c	Fri Oct 18 21:03:03 2002
@@ -289,7 +289,7 @@
 #endif
 
 #ifdef DEBUG_ESP_CMDS
-extern inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
+inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
 			   unchar cmd)
 {
 	esp->espcmdlog[esp->espcmdent] = cmd;
diff -Nru a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
--- a/drivers/scsi/aacraid/aachba.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/aacraid/aachba.c	Fri Oct 18 21:03:04 2002
@@ -1060,7 +1060,8 @@
 			 */
 			 
 			spin_unlock_irq(scsicmd->host->host_lock);
-			fsa_dev_ptr->devno[cid] = DEVICE_NR(scsicmd->sc_request->sr_request->rq_dev);
+			fsa_dev_ptr->devno[cid] = 
+				DEVICE_NR(scsicmd->request->rq_dev);
 			ret = aac_read(scsicmd, cid);
 			spin_lock_irq(scsicmd->host->host_lock);
 			return ret;
diff -Nru a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile
--- a/drivers/scsi/aic7xxx/Makefile	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/aic7xxx/Makefile	Fri Oct 18 21:03:08 2002
@@ -20,6 +20,13 @@
 
 #EXTRA_CFLAGS += -g
 
+# Files generated that shall be removed upon make clean
+clean-files := aic7xxx_seq.h aic7xxx_reg.h
+
+# Command to be executed upon make clean
+# Note: Assignment without ':' to force late evaluation of $(src)
+clean-rule = @$(MAKE) -C $(src)/aicasm clean
+
 include $(TOPDIR)/Rules.make
 
 # Dependencies for generated files need to be listed explicitly
@@ -30,11 +37,12 @@
 
 ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)
 
-$(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h: $(src)/aic7xxx.seq \
-					   $(src)/aic7xxx.reg \
-					   $(obj)/aicasm/aicasm
+$(obj)/aic7xxx_seq.h: $(src)/aic7xxx.seq $(src)/aic7xxx.reg \
+		      $(obj)/aicasm/aicasm
 	$(obj)/aicasm/aicasm -I. -r $(obj)/aic7xxx_reg.h \
 				 -o $(obj)/aic7xxx_seq.h $(src)/aic7xxx.seq
+
+$(obj)/aic7xxx_reg.h: $(obj)/aix7xxx_seq.h
 
 $(obj)/aicasm/aicasm: $(src)/aicasm/*.[chyl]
 	$(MAKE) -C $(src)/aicasm
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
--- a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Fri Oct 18 21:03:04 2002
@@ -63,7 +63,6 @@
  * to do with card config are filled in after the card is detected.
  */
 #define AIC7XXX	{						\
-	next: NULL,						\
 	module: NULL,						\
 	proc_dir: NULL,						\
 	proc_info: ahc_linux_proc_info,				\
diff -Nru a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
--- a/drivers/scsi/aic7xxx/aicasm/Makefile	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile	Fri Oct 18 21:03:08 2002
@@ -43,7 +43,7 @@
 	 fi
 
 clean:
-	rm -f $(CLEANFILES) $(PROG)
+	@rm -f $(CLEANFILES) $(PROG)
 
 y.tab.h aicasm_gram.c: aicasm_gram.y
 	$(YACC) $(YFLAGS) aicasm_gram.y
diff -Nru a/drivers/scsi/aic7xxx_old/aic7xxx.h b/drivers/scsi/aic7xxx_old/aic7xxx.h
--- a/drivers/scsi/aic7xxx_old/aic7xxx.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/aic7xxx_old/aic7xxx.h	Fri Oct 18 21:03:03 2002
@@ -30,14 +30,10 @@
  * to do with card config are filled in after the card is detected.
  */
 #define AIC7XXX	{						\
-	next: NULL,						\
-	module: NULL,						\
 	proc_info: aic7xxx_proc_info,				\
-	name: NULL,						\
 	detect: aic7xxx_detect,					\
 	release: aic7xxx_release,				\
 	info: aic7xxx_info,					\
-	command: NULL,						\
 	queuecommand: aic7xxx_queue,				\
 	eh_strategy_handler: NULL,				\
 	eh_abort_handler: NULL,					\
diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
--- a/drivers/scsi/cpqfcTSinit.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/cpqfcTSinit.c	Fri Oct 18 21:03:03 2002
@@ -938,9 +938,7 @@
   char buf[81];
 
   // Search the Scsi host list for our controller
-  for (host=scsi_hostlist; host; host=host->next)
-    if (host->host_no == hostno)
-      break;
+  host = scsi_host_hn_get(hostno);
 
   if (!host) return -ESRCH;
 
diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c
--- a/drivers/scsi/esp.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/esp.c	Fri Oct 18 21:03:08 2002
@@ -378,7 +378,7 @@
 #endif
 
 #ifdef DEBUG_ESP_CMDS
-extern inline void esp_cmd(struct esp *esp, u8 cmd)
+static inline void esp_cmd(struct esp *esp, u8 cmd)
 {
 	esp->espcmdlog[esp->espcmdent] = cmd;
 	esp->espcmdent = (esp->espcmdent + 1) & 31;
diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
--- a/drivers/scsi/fcal.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/fcal.c	Fri Oct 18 21:03:03 2002
@@ -213,9 +213,7 @@
 	char *pos = buffer;
 	int i, j;
 
-	for (host=scsi_hostlist; host; host=host->next)
-		if (host->host_no == hostno)
-                      break;
+	host = scsi_host_hn_get(hostno);
 
 	if (!host) return -ESRCH;
 
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/hosts.c	Fri Oct 18 21:03:03 2002
@@ -15,12 +15,15 @@
  *  Updated to reflect the new initialization scheme for the higher 
  *  level of scsi drivers (sd/sr/st)
  *  September 17, 2000 Torben Mathiasen <tmm@image.dk>
+ *
+ *  Restructured scsi_host lists and associated functions.
+ *  September 04, 2002 Mike Anderson (andmike@us.ibm.com)
  */
 
 
 /*
  *  This file contains the medium level SCSI
- *  host interface initialization, as well as the scsi_hosts array of SCSI
+ *  host interface initialization, as well as the scsi_hosts list of SCSI
  *  hosts currently present in the system.
  */
 
@@ -31,232 +34,713 @@
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
 
 #define __KERNEL_SYSCALLS__
 
 #include <linux/unistd.h>
+#include <asm/dma.h>
 
 #include "scsi.h"
 #include "hosts.h"
 
-/*
-static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.c,v 1.20 1996/12/12 19:18:32 davem Exp $";
-*/
+LIST_HEAD(scsi_host_tmpl_list);
+LIST_HEAD(scsi_host_hn_list);
 
-/*
- *  The scsi host entries should be in the order you wish the
- *  cards to be detected.  A driver may appear more than once IFF
- *  it can deal with being detected (and therefore initialized)
- *  with more than one simultaneous host number, can handle being
- *  reentrant, etc.
+LIST_HEAD(scsi_host_list);
+spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
+
+struct Scsi_Device_Template * scsi_devicelist;
+
+static int scsi_host_next_hn;		/* host_no for next new host */
+static int scsi_hosts_registered;	/* cnt of registered scsi hosts */
+
+/**
+ * scsi_tp_for_each_host - call function for each scsi host off a template
+ * @shost_tp:	a pointer to a scsi host template
+ * @callback:	a pointer to callback function
  *
- *  They may appear in any order, as each SCSI host is told which host 
- *  number it is during detection.
- */
+ * Return value:
+ * 	0 on Success / 1 on Failure
+ **/
+int scsi_tp_for_each_host(Scsi_Host_Template *shost_tp, int
+			    (*callback)(struct Scsi_Host *shost))
+{
+	struct list_head *lh, *lh_sf;
+	struct Scsi_Host *shost;
 
-/*
- *  When figure is run, we don't want to link to any object code.  Since
- *  the macro for each host will contain function pointers, we cannot
- *  use it and instead must use a "blank" that does no such
- *  idiocy.
- */
+	spin_lock(&scsi_host_list_lock);
 
-Scsi_Host_Template * scsi_hosts;
+	list_for_each_safe(lh, lh_sf, &scsi_host_list) {
+		shost = list_entry(lh, struct Scsi_Host, sh_list);
+		if (shost->hostt == shost_tp) {
+			spin_unlock(&scsi_host_list_lock);
+			callback(shost);
+			spin_lock(&scsi_host_list_lock);
+		}
+	}
 
+	spin_unlock(&scsi_host_list_lock);
 
-/*
- *  Our semaphores and timeout counters, where size depends on 
- *      MAX_SCSI_HOSTS here.
- */
+	return 0;
+}
 
-Scsi_Host_Name * scsi_host_no_list;
-struct Scsi_Host * scsi_hostlist;
-struct Scsi_Device_Template * scsi_devicelist;
+/**
+ * scsi_host_generic_release - default release function for hosts
+ * @shost: 
+ * 
+ * Description:
+ * 	This is the default case for the release function.  It should do
+ * 	the right thing for most correctly written host adapters.
+ **/
+static void scsi_host_generic_release(struct Scsi_Host *shost)
+{
+	if (shost->irq)
+		free_irq(shost->irq, NULL);
+	if (shost->dma_channel != 0xff)
+		free_dma(shost->dma_channel);
+	if (shost->io_port && shost->n_io_port)
+		release_region(shost->io_port, shost->n_io_port);
+}
 
-int max_scsi_hosts;
-int next_scsi_host;
+/**
+ * scsi_host_chk_and_release - check a scsi host for release and release
+ * @shost:	a pointer to a scsi host to release
+ *
+ * Return value:
+ * 	0 on Success / 1 on Failure
+ **/
+int scsi_host_chk_and_release(struct Scsi_Host *shost)
+{
+	int pcount;
+	Scsi_Device *sdev;
+	struct Scsi_Device_Template *sdev_tp;
+	Scsi_Cmnd *scmd;
+
+	/*
+	 * Current policy is all shosts go away on unregister.
+	 */
+	if (shost->hostt->module && GET_USE_COUNT(shost->hostt->module))
+		return 1;
+
+	/*
+	 * FIXME Do ref counting.  We force all of the devices offline to
+	 * help prevent race conditions where other hosts/processors could
+	 * try and get in and queue a command.
+	 */
+	for (sdev = shost->host_queue; sdev; sdev = sdev->next) 
+		sdev->online = FALSE;
+
+	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+		/*
+		 * Loop over all of the commands associated with the
+		 * device.  If any of them are busy, then set the state
+		 * back to inactive and bail.
+		 */
+		for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
+			if (scmd->request && scmd->request->rq_status !=
+			    RQ_INACTIVE) {
+				printk(KERN_ERR "SCSI device not inactive"
+				       "- rq_status=%d, target=%d, pid=%ld,"
+				       "state=%d, owner=%d.\n",
+				       scmd->request->rq_status,
+				       scmd->target, scmd->pid,
+				       scmd->state, scmd->owner);
+				for (sdev = shost->host_queue; sdev;
+				     sdev = sdev->next) {
+					for (scmd = sdev->device_queue; scmd;
+					     scmd = scmd->next)
+						if (scmd->request->rq_status ==
+						    RQ_SCSI_DISCONNECTING)
+							scmd->request->rq_status = RQ_INACTIVE;
+				}
+				printk(KERN_ERR "Device busy???\n");
+				return 1;
+			}
+			/*
+			 * No, this device is really free.  Mark it as such, and
+			 * continue on.
+			 */
+			scmd->state = SCSI_STATE_DISCONNECTING;
+			if (scmd->request)
+				scmd->request->rq_status =
+					RQ_SCSI_DISCONNECTING;	/* Mark as
+								   busy */
+		}
+	}
 
-void
-scsi_unregister(struct Scsi_Host * sh){
-    struct Scsi_Host * shpnt;
-    Scsi_Host_Name *shn;
-        
-    if(scsi_hostlist == sh)
-	scsi_hostlist = sh->next;
-    else {
-	shpnt = scsi_hostlist;
-	while(shpnt->next != sh) shpnt = shpnt->next;
-	shpnt->next = shpnt->next->next;
-    }
-
-    /*
-     * We have to unregister the host from the scsi_host_no_list as well.
-     * Decide by the host_no not by the name because most host drivers are
-     * able to handle more than one adapters from the same kind (or family).
-     */
-    for ( shn=scsi_host_no_list; shn && (sh->host_no != shn->host_no);
-	  shn=shn->next);
-    if (shn) shn->host_registered = 0;
-    /* else {} : This should not happen, we should panic here... */
-    
-    /* If we are removing the last host registered, it is safe to reuse
-     * its host number (this avoids "holes" at boot time) (DB) 
-     * It is also safe to reuse those of numbers directly below which have
-     * been released earlier (to avoid some holes in numbering).
-     */
-    if(sh->host_no == max_scsi_hosts - 1) {
-	while(--max_scsi_hosts >= next_scsi_host) {
-	    shpnt = scsi_hostlist;
-	    while(shpnt && shpnt->host_no != max_scsi_hosts - 1)
-		shpnt = shpnt->next;
-	    if(shpnt)
-		break;
-	}
-    }
-    next_scsi_host--;
-    kfree((char *) sh);
-}
-
-/* We call this when we come across a new host adapter. We only do this
- * once we are 100% sure that we want to use this host adapter -  it is a
- * pain to reverse this, so we try to avoid it 
- */
+	/*
+	 * Next we detach the high level drivers from the Scsi_Device
+	 * structures
+	 */
+	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+		for (sdev_tp = scsi_devicelist; sdev_tp;
+		     sdev_tp = sdev_tp->next)
+			if (sdev_tp->detach)
+				(*sdev_tp->detach) (sdev);
+
+		/* If something still attached, punt */
+		if (sdev->attached) {
+			printk(KERN_ERR "Attached usage count = %d\n",
+			       sdev->attached);
+			return 1;
+		}
+
+		if (shost->hostt->slave_detach)
+			(*shost->hostt->slave_detach) (sdev);
+
+		devfs_unregister(sdev->de);
+		device_unregister(&sdev->sdev_driverfs_dev);
+	}
+
+	/* Next we free up the Scsi_Cmnd structures for this host */
+
+	for (sdev = shost->host_queue; sdev;
+	     sdev = shost->host_queue) {
+		scsi_release_commandblocks(sdev);
+		blk_cleanup_queue(&sdev->request_queue);
+		/* Next free up the Scsi_Device structures for this host */
+		shost->host_queue = sdev->next;
+		if (sdev->inquiry)
+			kfree(sdev->inquiry);
+		kfree(sdev);
+	}
+
+	/* Remove the instance of the individual hosts */
+	pcount = scsi_hosts_registered;
+	if (shost->hostt->release)
+		(*shost->hostt->release) (shost);
+	else {
+		scsi_host_generic_release(shost);
+	}
+
+	if (pcount == scsi_hosts_registered)
+		scsi_unregister(shost);
+
+	return 0;
+}
+
+/**
+ * scsi_unregister - unregister a scsi host
+ * @shost:	scsi host to be unregistered
+ **/
+void scsi_unregister(struct Scsi_Host *shost)
+{
+	struct list_head *lh;
+	Scsi_Host_Name *shost_name;
+
+	/* Remove shost from scsi_host_list */
+	spin_lock(&scsi_host_list_lock);
+	list_del(&shost->sh_list);
+	spin_unlock(&scsi_host_list_lock);
+
+	/* Unregister from scsi_host_hn_list */
+	list_for_each(lh, &scsi_host_hn_list) {
+		shost_name = list_entry(lh, Scsi_Host_Name, shn_list);
+		if (shost->host_no == shost_name->host_no)
+			shost_name->host_registered = 0;
+	}
+
+	/*
+	 * Next, kill the kernel error recovery thread for this host.
+	 */
+	if (shost->ehandler) {
+		DECLARE_MUTEX_LOCKED(sem);
+		shost->eh_notify = &sem;
+		send_sig(SIGHUP, shost->ehandler, 1);
+		down(&sem);
+		shost->eh_notify = NULL;
+	}
+
+	scsi_hosts_registered--;
+	shost->hostt->present--;
+
+	/* Cleanup proc and driverfs */
+#ifdef CONFIG_PROC_FS
+	scsi_proc_host_rm(shost);
+	if (!shost->hostt->present)
+		remove_proc_entry(shost->hostt->proc_name, proc_scsi);
+#endif
+	device_unregister(&shost->host_driverfs_dev);
+
+	kfree(shost);
+}
+
+/**
+ * scsi_host_hn_add - allocate and add new Scsi_Host_Name
+ * @name:	String to store in name field
+ *
+ * Return value:
+ * 	Pointer to a new Scsi_Host_Name
+ **/
+Scsi_Host_Name *scsi_host_hn_add(char *name)
+{
+	Scsi_Host_Name *shost_name;
+	int len;
+
+	len = strlen(name);
+	shost_name =  kmalloc(sizeof(*shost_name), GFP_KERNEL);
+	if (!shost_name) {
+		printk(KERN_ERR "%s: out of memory at line %d.\n",
+		       __FUNCTION__, __LINE__);
+		return NULL;
+	}
+	shost_name->name = kmalloc(len + 1, GFP_KERNEL);
+	if (!shost_name->name) {
+		kfree(shost_name);
+		printk(KERN_ERR "%s: out of memory at line %d.\n",
+		       __FUNCTION__, __LINE__);
+		return NULL;
+	}
+
+	if (len)
+		strncpy(shost_name->name, name, len);
+	shost_name->name[len] = 0;
+	shost_name->host_no = scsi_host_next_hn++;
+	shost_name->host_registered = 0;
+	list_add_tail(&shost_name->shn_list, &scsi_host_hn_list);
+
+	return shost_name;
+}
+
+/**
+ * scsi_register - register a scsi host adapter instance.
+ * @shost_tp:	pointer to scsi host template
+ * @xtr_bytes:	extra bytes to allocate for driver
+ *
+ * Note:
+ * 	We call this when we come across a new host adapter. We only do
+ * 	this once we are 100% sure that we want to use this host adapter -
+ * 	it is a pain to reverse this, so we try to avoid it 
+ *
+ * Return value:
+ * 	Pointer to a new Scsi_Host
+ **/
 extern int blk_nohighio;
-struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
+struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
 {
-    struct Scsi_Host * retval, *shpnt, *o_shp;
-    Scsi_Host_Name *shn, *shn2;
-    int flag_new = 1;
-    const char * hname;
-    size_t hname_len;
-    retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j,
-					 (tpnt->unchecked_isa_dma && j ? 
-					  GFP_DMA : 0) | GFP_ATOMIC);
-    if(retval == NULL)
-    {
-        printk("scsi: out of memory in scsi_register.\n");
-    	return NULL;
-    }
-    	
-    memset(retval, 0, sizeof(struct Scsi_Host) + j);
-
-    /* trying to find a reserved entry (host_no) */
-    hname = (tpnt->proc_name) ?  tpnt->proc_name : "";
-    hname_len = strlen(hname);
-    for (shn = scsi_host_no_list;shn;shn = shn->next) {
-	if (!(shn->host_registered) && 
-	    (hname_len > 0) && (0 == strncmp(hname, shn->name, hname_len))) {
-	    flag_new = 0;
-	    retval->host_no = shn->host_no;
-	    shn->host_registered = 1;
-	    break;
-	}
-    }
-    spin_lock_init(&retval->default_lock);
-    scsi_assign_lock(retval, &retval->default_lock);
-    atomic_set(&retval->host_active,0);
-    retval->host_busy = 0;
-    retval->host_failed = 0;
-    if (flag_new) {
-	shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC);
-        if (!shn) {
-                kfree(retval);
-                printk(KERN_ERR "scsi: out of memory(2) in scsi_register.\n");
-                return NULL;
-        }
-	shn->name = kmalloc(hname_len + 1, GFP_ATOMIC);
-	if (hname_len > 0)
-	    strncpy(shn->name, hname, hname_len);
-	shn->name[hname_len] = 0;
-	shn->host_no = max_scsi_hosts++;
-	shn->host_registered = 1;
-	shn->next = NULL;
-	if (scsi_host_no_list) {
-	    for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next)
-		;
-	    shn2->next = shn;
-	}
-	else
-	    scsi_host_no_list = shn;
-	retval->host_no = shn->host_no;
-    }
-    next_scsi_host++;
-    retval->host_queue = NULL;
-    init_waitqueue_head(&retval->host_wait);
-    retval->resetting = 0;
-    retval->last_reset = 0;
-    retval->irq = 0;
-    retval->dma_channel = 0xff;
-
-    /* These three are default values which can be overridden */
-    retval->max_channel = 0; 
-    retval->max_id = 8;      
-    retval->max_lun = 8;
-
-    /*
-     * All drivers right now should be able to handle 12 byte commands.
-     * Every so often there are requests for 16 byte commands, but individual
-     * low-level drivers need to certify that they actually do something
-     * sensible with such commands.
-     */
-    retval->max_cmd_len = 12;
-
-    retval->unique_id = 0;
-    retval->io_port = 0;
-    retval->hostt = tpnt;
-    retval->next = NULL;
-    retval->in_recovery = 0;
-    retval->ehandler = NULL;    /* Initial value until the thing starts up. */
-    retval->eh_notify   = NULL;    /* Who we notify when we exit. */
+	struct Scsi_Host *shost, *shost_scr;
+	Scsi_Host_Name *shost_name = NULL;
+	Scsi_Host_Name *shn = NULL;
+	char *hname;
+	size_t hname_len;
+	struct list_head *lh;
+	int gfp_mask;
+	DECLARE_MUTEX_LOCKED(sem);
+
+	gfp_mask = GFP_KERNEL;
+	if (shost_tp->unchecked_isa_dma && xtr_bytes)
+		gfp_mask |= __GFP_DMA;
+
+	shost = kmalloc(sizeof(struct Scsi_Host) + xtr_bytes, gfp_mask);
+	if (!shost) {
+		printk(KERN_ERR "%s: out of memory.\n", __FUNCTION__);
+		return NULL;
+	}
 
-    retval->max_host_blocked = tpnt->max_host_blocked ? tpnt->max_host_blocked : SCSI_DEFAULT_HOST_BLOCKED;
+	memset(shost, 0, sizeof(struct Scsi_Host) + xtr_bytes);
 
-    retval->host_blocked = 0;
-    retval->host_self_blocked = FALSE;
+	/*
+	 * Determine host number. Check reserved first before allocating
+	 * new one
+	 */
+	hname = (shost_tp->proc_name) ?  shost_tp->proc_name : "";
+	hname_len = strlen(hname);
+
+	if (hname_len)
+		list_for_each(lh, &scsi_host_hn_list) {
+			shn = list_entry(lh, Scsi_Host_Name, shn_list);
+			if (!(shn->host_registered) &&
+			    !strncmp(hname, shn->name, hname_len)) {
+				shost_name = shn;
+				break;
+			}
+		}
+
+	if (!shost_name) {
+		shost_name = scsi_host_hn_add(hname);
+		if (!shost_name) {
+			kfree(shost);
+			return NULL;
+		}
+	}
+
+	shost->host_no = shost_name->host_no;
+	shost_name->host_registered = 1;
+	scsi_hosts_registered++;
+
+	spin_lock_init(&shost->default_lock);
+	scsi_assign_lock(shost, &shost->default_lock);
+	atomic_set(&shost->host_active,0);
+
+	init_waitqueue_head(&shost->host_wait);
+	shost->dma_channel = 0xff;
+
+	/* These three are default values which can be overridden */
+	shost->max_channel = 0;
+	shost->max_id = 8;
+	shost->max_lun = 8;
+
+	/*
+	 * All drivers right now should be able to handle 12 byte
+	 * commands.  Every so often there are requests for 16 byte
+	 * commands, but individual low-level drivers need to certify that
+	 * they actually do something sensible with such commands.
+	 */
+	shost->max_cmd_len = 12;
+	shost->hostt = shost_tp;
+	shost->host_blocked = FALSE;
+	shost->host_self_blocked = FALSE;
 
 #ifdef DEBUG
-    printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j);
+	printk("%s: %x %x: %d\n", __FUNCTION_ (int)shost,
+	       (int)shost->hostt, xtr_bytes);
 #endif
 
-    /* The next six are the default values which can be overridden
-     * if need be */
-    retval->this_id = tpnt->this_id;
-    retval->can_queue = tpnt->can_queue;
-    retval->sg_tablesize = tpnt->sg_tablesize;
-    retval->cmd_per_lun = tpnt->cmd_per_lun;
-    retval->unchecked_isa_dma = tpnt->unchecked_isa_dma;
-    retval->use_clustering = tpnt->use_clustering;   
-    if (!blk_nohighio)
-	retval->highmem_io = tpnt->highmem_io;
-
-    retval->max_sectors = tpnt->max_sectors;
-    retval->use_blk_tcq = tpnt->use_blk_tcq;
-
-    if(!scsi_hostlist)
-	scsi_hostlist = retval;
-    else {
-	shpnt = scsi_hostlist;
-	if (retval->host_no < shpnt->host_no) {
-	    retval->next = shpnt;
-	    wmb(); /* want all to see these writes in this order */
-	    scsi_hostlist = retval;
+	/*
+	 * The next six are the default values which can be overridden if
+	 * need be
+	 */
+	shost->this_id = shost_tp->this_id;
+	shost->can_queue = shost_tp->can_queue;
+	shost->sg_tablesize = shost_tp->sg_tablesize;
+	shost->cmd_per_lun = shost_tp->cmd_per_lun;
+	shost->unchecked_isa_dma = shost_tp->unchecked_isa_dma;
+	shost->use_clustering = shost_tp->use_clustering;
+	if (!blk_nohighio)
+	shost->highmem_io = shost_tp->highmem_io;
+
+	shost->max_sectors = shost_tp->max_sectors;
+	shost->use_blk_tcq = shost_tp->use_blk_tcq;
+
+	spin_lock(&scsi_host_list_lock);
+	/*
+	 * FIXME When device naming is complete remove this step that
+	 * orders the scsi_host_list by host number and just do a
+	 * list_add_tail.
+	 */
+	list_for_each(lh, &scsi_host_list) {
+		shost_scr = list_entry(lh, struct Scsi_Host, sh_list);
+		if (shost->host_no < shost_scr->host_no) {
+			__list_add(&shost->sh_list, shost_scr->sh_list.prev,
+				   &shost_scr->sh_list);
+			goto found;
+		}
+	}
+	list_add_tail(&shost->sh_list, &scsi_host_list);
+found:
+	spin_unlock(&scsi_host_list_lock);
+
+#ifdef CONFIG_PROC_FS
+	/* Add the new driver to /proc/scsi if not already there */
+	if (!shost_tp->proc_dir)
+		scsi_proc_host_mkdir(shost_tp);
+	scsi_proc_host_add(shost);
+#endif
+
+	strncpy(shost->host_driverfs_dev.name, shost_tp->proc_name,
+		DEVICE_NAME_SIZE-1);
+	sprintf(shost->host_driverfs_dev.bus_id, "scsi%d",
+		shost->host_no);
+
+	shost->eh_notify = &sem;
+	kernel_thread((int (*)(void *)) scsi_error_handler, (void *) shost, 0);
+	/*
+	 * Now wait for the kernel error thread to initialize itself
+	 * as it might be needed when we scan the bus.
+	 */
+	down(&sem);
+	shost->eh_notify = NULL;
+
+	shost->hostt->present++;
+
+	return shost;
+}
+
+
+/**
+ * scsi_register_host - register a low level host driver
+ * @shost_tp:	pointer to a scsi host driver template
+ *
+ * Return value:
+ * 	0 on Success / 1 on Failure.
+ **/
+int scsi_register_host(Scsi_Host_Template *shost_tp)
+{
+	int cur_cnt;
+	Scsi_Device *sdev;
+	struct Scsi_Device_Template *sdev_tp;
+	struct list_head *lh;
+	struct Scsi_Host *shost;
+
+	INIT_LIST_HEAD(&shost_tp->shtp_list);
+
+	/*
+	 * Check no detect routine.
+	 */
+	if (!shost_tp->detect)
+		return 1;
+
+	/* If max_sectors isn't set, default to max */
+	if (!shost_tp->max_sectors)
+		shost_tp->max_sectors = 1024;
+
+	cur_cnt = scsi_hosts_registered;
+
+	MOD_INC_USE_COUNT;
+
+	/*
+	 * The detect routine must carefully spinunlock/spinlock if it
+	 * enables interrupts, since all interrupt handlers do spinlock as
+	 * well.
+	 */
+
+	/*
+	 * detect should do its own locking
+	 * FIXME present is now set is scsi_register which breaks manual
+	 * registration code below.
+	 */
+	shost_tp->detect(shost_tp);
+
+	if (shost_tp->present) {
+			/*
+			 * FIXME Who needs manual registration and why???
+			 */
+		if (cur_cnt == scsi_hosts_registered) {
+			if (shost_tp->present > 1) {
+				printk(KERN_ERR "scsi: Failure to register"
+				       "low-level scsi driver");
+				scsi_unregister_host(shost_tp);
+				return 1;
+			}
+			/*
+			 * The low-level driver failed to register a driver.
+			 * We can do this now.
+			 */
+			if(scsi_register(shost_tp, 0)==NULL) {
+				printk(KERN_ERR "scsi: register failed.\n");
+				scsi_unregister_host(shost_tp);
+				return 1;
+			}
+		}
+
+		list_add_tail(&shost_tp->shtp_list, &scsi_host_tmpl_list);
+
+		/* The next step is to call scan_scsis here.  This generates the
+		 * Scsi_Devices entries
+		 */
+		list_for_each(lh, &scsi_host_list) {
+			shost = list_entry(lh, struct Scsi_Host, sh_list);
+			if (shost->hostt == shost_tp) {
+				const char *dm_name;
+				if (shost_tp->info) {
+					dm_name = shost_tp->info(shost);
+				} else {
+					dm_name = shost_tp->name;
+				}
+				printk(KERN_INFO "scsi%d : %s\n",
+				       shost->host_no, dm_name);
+
+				/* first register parent with driverfs */
+				device_register(&shost->host_driverfs_dev);
+				scan_scsis(shost, 0, 0, 0, 0);
+			}
+		}
+
+		for (sdev_tp = scsi_devicelist; sdev_tp;
+		     sdev_tp = sdev_tp->next) {
+			if (sdev_tp->init && sdev_tp->dev_noticed)
+				(*sdev_tp->init) ();
+		}
+
+		/*
+		 * Next we create the Scsi_Cmnd structures for this host 
+		 */
+		list_for_each(lh, &scsi_host_list) {
+			shost = list_entry(lh, struct Scsi_Host, sh_list);
+			for (sdev = shost->host_queue; sdev; sdev = sdev->next)
+				if (sdev->host->hostt == shost_tp) {
+					for (sdev_tp = scsi_devicelist;
+					     sdev_tp;
+					     sdev_tp = sdev_tp->next)
+						if (sdev_tp->attach)
+							(*sdev_tp->attach) (sdev);
+					if (sdev->attached) {
+						scsi_build_commandblocks(sdev);
+						if (sdev->current_queue_depth == 0)
+							goto out_of_space;
+					}
+				}
+		}
+
+		/* This does any final handling that is required. */
+		for (sdev_tp = scsi_devicelist; sdev_tp;
+		     sdev_tp = sdev_tp->next) {
+			if (sdev_tp->finish && sdev_tp->nr_dev) {
+				(*sdev_tp->finish) ();
+			}
+		}
+	}
+
+	return 0;
+
+out_of_space:
+	scsi_unregister_host(shost_tp); /* easiest way to clean up?? */
+	return 1;
+}
+
+/**
+ * scsi_unregister_host - unregister a low level host adapter driver
+ * @shost_tp:	scsi host template to unregister.
+ *
+ * Description:
+ * 	Similarly, this entry point should be called by a loadable module
+ * 	if it is trying to remove a low level scsi driver from the system.
+ *
+ * Return value:
+ * 	0 on Success / 1 on Failure
+ *
+ * Notes:
+ * 	rmmod does not care what we return here the module will be
+ * 	removed.
+ **/
+int scsi_unregister_host(Scsi_Host_Template *shost_tp)
+{
+	int pcount;
+
+	/* get the big kernel lock, so we don't race with open() */
+	lock_kernel();
+
+	pcount = scsi_hosts_registered;
+
+	scsi_tp_for_each_host(shost_tp, scsi_host_chk_and_release);
+
+	if (pcount != scsi_hosts_registered)
+		printk(KERN_INFO "scsi : %d host%s left.\n", scsi_hosts_registered,
+		       (scsi_hosts_registered == 1) ? "" : "s");
+
+	/*
+	 * Remove it from the list if all
+	 * hosts were successfully removed (ie preset == 0)
+	 */
+	if (!shost_tp->present) {
+		list_del(&shost_tp->shtp_list);
+	}
+
+	MOD_DEC_USE_COUNT;
+
+	unlock_kernel();
+	return 0;
+
+}
+
+/**
+ * *scsi_host_get_next - get scsi host and inc ref count
+ * @shost:	pointer to a Scsi_Host or NULL to start.
+ *
+ * Return value:
+ * 	A pointer to next Scsi_Host in list or NULL.
+ **/
+struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *shost)
+{
+	struct list_head *lh = NULL;
+
+	spin_lock(&scsi_host_list_lock);
+	if (shost) {
+		/* XXX Dec ref on cur shost */
+		lh = shost->sh_list.next;
+	} else {
+		lh = scsi_host_list.next;
+	}
+
+	if (lh == &scsi_host_list) {
+		shost = (struct Scsi_Host *)NULL;
+		goto done;
+	}
+
+	shost = list_entry(lh, struct Scsi_Host, sh_list);
+	/* XXX Inc ref count */
+
+done:
+	spin_unlock(&scsi_host_list_lock);
+	return shost;
+}
+
+/**
+ * scsi_host_hn_get - get a Scsi_Host by host no and inc ref count
+ * @host_no:	host number to locate
+ *
+ * Return value:
+ * 	A pointer to located Scsi_Host or NULL.
+ **/
+struct Scsi_Host *scsi_host_hn_get(unsigned short host_no)
+{
+	struct list_head *lh;
+	struct Scsi_Host *shost;
+
+	spin_lock(&scsi_host_list_lock);
+	list_for_each(lh, &scsi_host_list) {
+		shost = list_entry(lh, struct Scsi_Host, sh_list);
+		if (shost->host_no == host_no) {
+			/* XXX Inc ref count */
+			goto done;
+		}
+	}
+
+	shost = (struct Scsi_Host *)NULL;
+done:
+	spin_unlock(&scsi_host_list_lock);
+	return shost;
+}
+
+/**
+ * *scsi_host_put - dec a Scsi_Host ref count
+ * @shost:	Pointer to Scsi_Host to dec.
+ **/
+void scsi_host_put(struct Scsi_Host *shost)
+{
+
+	/* XXX Get list lock */
+	/* XXX dec ref count */
+	/* XXX Release list lock */
+	return;
+}
+
+/**
+ * scsi_host_hn_init - init scsi host number list from string
+ * @shost_hn:	string of scsi host driver names.
+ **/
+void __init scsi_host_hn_init(char *shost_hn)
+{
+	char *temp = shost_hn;
+
+	while (temp) {
+		while (*temp && (*temp != ':') && (*temp != ','))
+			temp++;
+		if (!*temp)
+			temp = NULL;
+		else
+			*temp++ = 0;
+		(void)scsi_host_hn_add(shost_hn);
+		shost_hn = temp;
+	}
+}
+
+/**
+ * scsi_host_no_release - free all entries in scsi host number list
+ **/
+void __exit scsi_host_hn_release()
+{
+	struct list_head *lh, *next;
+	Scsi_Host_Name *shn;
+
+	list_for_each_safe(lh, next, &scsi_host_hn_list) {
+		shn = list_entry(lh, Scsi_Host_Name, shn_list);
+		if (shn->name)
+			kfree(shn->name);
+		kfree(shn);
 	}
-	else {
-	    for (o_shp = shpnt, shpnt = shpnt->next; shpnt; 
-		 o_shp = shpnt, shpnt = shpnt->next) {
-		if (retval->host_no < shpnt->host_no) {
-		    retval->next = shpnt;
-		    wmb();
-		    o_shp->next = retval;
-		    break;
-		}
-	    }
-	    if (! shpnt)
-		o_shp->next = retval;
-        }
-    }
-    
-    return retval;
 }
 
 void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev)
@@ -279,8 +763,7 @@
 	if (shost->in_recovery && (shost->host_busy == shost->host_failed)) {
 		up(shost->eh_wait);
 		SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler"
-					  "thread (%d)\n",
-					  atomic_read(&shost->eh_wait->count)));
+					  " thread\n"));
 	}
 	spin_unlock_irqrestore(shost->host_lock, flags);
 }
@@ -295,8 +778,7 @@
 	if (shost->host_busy == shost->host_failed) {
 		up(shost->eh_wait);
 		SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler"
-					  "thread (%d)\n",
-					  atomic_read(&shost->eh_wait->count)));
+					  " thread\n"));
 	}
 	spin_unlock_irqrestore(shost->host_lock, flags);
 }
diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
--- a/drivers/scsi/hosts.h	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/hosts.h	Fri Oct 18 21:03:04 2002
@@ -16,15 +16,14 @@
  *  of the same type.
  *
  *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
+ *
+ *  Restructured scsi_host lists and associated functions.
+ *  September 04, 2002 Mike Anderson (andmike@us.ibm.com)
  */
 
 #ifndef _HOSTS_H
 #define _HOSTS_H
 
-/*
-    $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $
-*/
-
 #include <linux/config.h>
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
@@ -58,8 +57,7 @@
 typedef struct	SHT
 {
 
-    /* Used with loadable modules so we can construct a linked list. */
-    struct SHT * next;
+    struct list_head	shtp_list;
 
     /* Used with loadable modules so that we know when it is safe to unload */
     struct module * module;
@@ -374,7 +372,7 @@
      * This information is private to the scsi mid-layer.  Wrapping it in a
      * struct private is a way of marking it in a sort of C++ type of way.
      */
-    struct Scsi_Host      * next;
+    struct list_head      sh_list;
     Scsi_Device           * host_queue;
     struct list_head	  all_scsi_hosts;
     struct list_head	  my_devices;
@@ -510,28 +508,26 @@
  * thing.  This physical pseudo-device isn't real and won't be available
  * from any high-level drivers.
  */
-extern void scsi_free_host_dev(Scsi_Device * SDpnt);
-extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt);
+extern void scsi_free_host_dev(Scsi_Device *);
+extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host *);
 
-extern void scsi_unblock_requests(struct Scsi_Host * SHpnt);
-extern void scsi_block_requests(struct Scsi_Host * SHpnt);
-extern void scsi_report_bus_reset(struct Scsi_Host * SHpnt, int channel);
+extern void scsi_unblock_requests(struct Scsi_Host *);
+extern void scsi_block_requests(struct Scsi_Host *);
+extern void scsi_report_bus_reset(struct Scsi_Host *, int);
 
 typedef struct SHN
-    {
-    struct SHN * next;
-    char * name;
-    unsigned short host_no;
-    unsigned short host_registered;
-    } Scsi_Host_Name;
+{
+	struct list_head shn_list;
+	char *name;
+	unsigned short host_no;
+	unsigned short host_registered;
+} Scsi_Host_Name;
 	
-extern Scsi_Host_Name * scsi_host_no_list;
-extern struct Scsi_Host * scsi_hostlist;
 extern struct Scsi_Device_Template * scsi_devicelist;
 
-extern Scsi_Host_Template * scsi_hosts;
-
-extern void build_proc_dir_entries(Scsi_Host_Template  *);
+extern void scsi_proc_host_mkdir(Scsi_Host_Template *);
+extern void scsi_proc_host_add(struct Scsi_Host *);
+extern void scsi_proc_host_rm(struct Scsi_Host *);
 
 /*
  *  scsi_init initializes the scsi hosts.
@@ -540,34 +536,33 @@
 extern int next_scsi_host;
 
 unsigned int scsi_init(void);
-extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j);
-extern void scsi_unregister(struct Scsi_Host * i);
-extern void scsi_register_blocked_host(struct Scsi_Host * SHpnt);
-extern void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt);
+extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int);
+extern void scsi_unregister(struct Scsi_Host *);
+extern void scsi_register_blocked_host(struct Scsi_Host *);
+extern void scsi_deregister_blocked_host(struct Scsi_Host *);
 
-static inline void scsi_assign_lock(struct Scsi_Host *host, spinlock_t *lock)
+static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
 {
-	host->host_lock = lock;
+	shost->host_lock = lock;
 }
 
-static inline void scsi_set_pci_device(struct Scsi_Host *SHpnt,
+static inline void scsi_set_pci_device(struct Scsi_Host *shost,
                                        struct pci_dev *pdev)
 {
-	SHpnt->pci_dev = pdev;
-	SHpnt->host_driverfs_dev.parent=&pdev->dev;
+	shost->pci_dev = pdev;
+	shost->host_driverfs_dev.parent=&pdev->dev;
+
+	/* register parent with driverfs */
+	device_register(&shost->host_driverfs_dev);
 }
 
 
 /*
  * Prototypes for functions/data in scsi_scan.c
  */
-extern void scan_scsis(struct Scsi_Host *shpnt,
-		       uint hardcoded,
-		       uint hchannel,
-		       uint hid,
-                       uint hlun);
+extern void scan_scsis(struct Scsi_Host *, uint, uint, uint, uint);
 
-extern void scsi_mark_host_reset(struct Scsi_Host *Host);
+extern void scsi_mark_host_reset(struct Scsi_Host *);
 
 #define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 
@@ -596,7 +591,7 @@
     struct device_driver scsi_driverfs_driver;
 };
 
-void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
+void  scsi_initialize_queue(Scsi_Device *, struct Scsi_Host *);
 
 
 /*
@@ -607,6 +602,12 @@
 extern int scsi_register_host(Scsi_Host_Template *);
 extern int scsi_unregister_host(Scsi_Host_Template *);
 
+extern struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *);
+extern struct Scsi_Host *scsi_host_hn_get(unsigned short);
+extern void scsi_host_put(struct Scsi_Host *);
+extern void scsi_host_hn_init(char *);
+extern void scsi_host_hn_release(void);
+
 /*
  * host_busy inc/dec/test functions
  */
@@ -614,7 +615,6 @@
 extern void scsi_host_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *);
 extern void scsi_host_failed_inc_and_test(struct Scsi_Host *);
 
-
 /*
  * This is an ugly hack.  If we expect to be able to load devices at run time,
  * we need to leave extra room in some of the data structures.	Doing a
@@ -643,21 +643,22 @@
 
 /**
  * scsi_find_device - find a device given the host
+ * @shost:	SCSI host pointer
  * @channel:	SCSI channel (zero if only one channel)
  * @pun:	SCSI target number (physical unit number)
  * @lun:	SCSI Logical Unit Number
  **/
-static inline Scsi_Device *scsi_find_device(struct Scsi_Host *host,
+static inline Scsi_Device *scsi_find_device(struct Scsi_Host *shost,
                                             int channel, int pun, int lun) {
-        Scsi_Device *SDpnt;
+        Scsi_Device *sdev;
 
-        for(SDpnt = host->host_queue;
-            SDpnt != NULL;
-            SDpnt = SDpnt->next)
-                if(SDpnt->channel == channel && SDpnt->id == pun
-                   && SDpnt->lun ==lun)
+        for (sdev = shost->host_queue;
+            sdev != NULL;
+            sdev = sdev->next)
+                if (sdev->channel == channel && sdev->id == pun
+                   && sdev->lun ==lun)
                         break;
-        return SDpnt;
+        return sdev;
 }
     
 #endif
diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h
--- a/drivers/scsi/ips.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/ips.h	Fri Oct 18 21:03:03 2002
@@ -407,7 +407,6 @@
     */
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
  #define IPS {                            \
-    next : NULL,                          \
     module : NULL,                        \
     proc_info : NULL,                     \
     proc_dir : NULL,                      \
@@ -437,7 +436,6 @@
 }
 #elif LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
  #define IPS {                            \
-    next : NULL,                          \
     module : NULL,                        \
     proc_info : NULL,                     \
     name : NULL,                          \
@@ -466,7 +464,6 @@
 }
 #else
  #define IPS {                            \
-    next : NULL,                          \
     module : NULL,                        \
     proc_info : NULL,                     \
     name : NULL,                          \
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/osst.c	Fri Oct 18 21:03:04 2002
@@ -322,8 +322,6 @@
 		}
 	}
 
-        if (SRpnt->sr_device->scsi_level <= SCSI_2)
-                cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
         init_completion(&STp->wait);
 	SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
 				    (STp->buffer)->use_sg : 0;
diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
--- a/drivers/scsi/pcmcia/aha152x_stub.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/pcmcia/aha152x_stub.c	Fri Oct 18 21:03:08 2002
@@ -294,7 +294,8 @@
 
     tail = &link->dev;
     info->ndev = 0;
-    for (host = scsi_hostlist; host; host = host->next)
+    for (host = scsi_host_get_next(NULL); host;
+	 host = scsi_host_get_next(host))
 	if (host->hostt == &driver_template)
 	    for (dev = host->host_queue; dev; dev = dev->next) {
 	    u_long arg[2], id;
diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
--- a/drivers/scsi/pcmcia/fdomain_stub.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/scsi/pcmcia/fdomain_stub.c	Fri Oct 18 21:03:05 2002
@@ -258,7 +258,8 @@
 
     tail = &link->dev;
     info->ndev = 0;
-    for (host = scsi_hostlist; host; host = host->next)
+    for (host = scsi_host_get_next(NULL); host;
+	 host = scsi_host_get_next(host))
 	if (host->hostt == &driver_template)
 	    for (dev = host->host_queue; dev; dev = dev->next) {
 	    u_long arg[2], id;
diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
--- a/drivers/scsi/pcmcia/nsp_cs.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/pcmcia/nsp_cs.c	Fri Oct 18 21:03:08 2002
@@ -1520,7 +1520,8 @@
 	DEBUG(0, "GET_SCSI_INFO\n");
 	tail = &link->dev;
 	info->ndev = 0;
-	for (host = scsi_hostlist; host != NULL; host = host->next) {
+	for (host = scsi_host_get_next(NULL); host;
+	     host = scsi_host_get_next(host))
 		if (host->hostt == &driver_template) {
 			for (dev = host->host_queue; dev != NULL; dev = dev->next) {
 				u_long arg[2], id;
diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
--- a/drivers/scsi/pcmcia/qlogic_stub.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/pcmcia/qlogic_stub.c	Fri Oct 18 21:03:04 2002
@@ -281,7 +281,8 @@
 
     tail = &link->dev;
     info->ndev = 0;
-    for (host = scsi_hostlist; host; host = host->next)
+	for (host = scsi_host_get_next(NULL); host;
+	     host = scsi_host_get_next(host))
 	if (host->hostt == &driver_template)
 	    for (dev = host->host_queue; dev; dev = dev->next) {
 	    u_long arg[2], id;
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/scsi.c	Fri Oct 18 21:03:04 2002
@@ -798,6 +798,12 @@
 		serial_number = 1;
 	SCpnt->serial_number = serial_number;
 	SCpnt->pid = scsi_pid++;
+	/* 
+	 * If SCSI-2 or lower, store the LUN value in cmnd.
+	 */
+	if (SCpnt->device->scsi_level <= SCSI_2)
+		SCpnt->cmnd[1] = (SCpnt->cmnd[1] & 0x1f) |
+			(SCpnt->lun << 5 & 0xe0);
 
 	/*
 	 * We will wait MIN_RESET_DELAY clock ticks after the last reset so
@@ -1659,33 +1665,6 @@
 	}
 }
 
-void __init scsi_host_no_insert(char *str, int n)
-{
-    Scsi_Host_Name *shn, *shn2;
-    int len;
-    
-    len = strlen(str);
-    if (len && (shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC))) {
-	if ((shn->name = kmalloc(len+1, GFP_ATOMIC))) {
-	    strncpy(shn->name, str, len);
-	    shn->name[len] = 0;
-	    shn->host_no = n;
-	    shn->host_registered = 0;
-	    shn->next = NULL;
-	    if (scsi_host_no_list) {
-		for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next)
-		    ;
-		shn2->next = shn;
-	    }
-	    else
-		scsi_host_no_list = shn;
-	    max_scsi_hosts = n+1;
-	}
-	else
-	    kfree((char *) shn);
-    }
-}
-
 #ifdef CONFIG_PROC_FS
 static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
 {
@@ -1698,7 +1677,8 @@
 	/*
 	 * First, see if there are any attached devices or not.
 	 */
-	for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+	for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+	     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
 		if (HBA_ptr->host_queue != NULL) {
 			break;
 		}
@@ -1706,7 +1686,8 @@
 	size = sprintf(buffer + len, "Attached devices: %s\n", (HBA_ptr) ? "" : "none");
 	len += size;
 	pos = begin + len;
-	for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+	for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+	     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
 #if 0
 		size += sprintf(buffer + len, "scsi%2d: %s\n", (int) HBA_ptr->host_no,
 				HBA_ptr->hostt->procname);
@@ -1873,7 +1854,8 @@
 		printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel,
 		       id, lun);
 
-		for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+		for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+		     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
 			if (HBA_ptr->host_no == host) {
 				break;
 			}
@@ -1918,7 +1900,8 @@
 		lun = simple_strtoul(p + 1, &p, 0);
 
 
-		for (HBA_ptr = scsi_hostlist; HBA_ptr; HBA_ptr = HBA_ptr->next) {
+		for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
+		     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
 			if (HBA_ptr->host_no == host) {
 				break;
 			}
@@ -1988,369 +1971,6 @@
 #endif
 
 /*
- * This entry point should be called by a driver if it is trying
- * to add a low level scsi driver to the system.
- */
-int scsi_register_host(Scsi_Host_Template * tpnt)
-{
-	int pcount;
-	struct Scsi_Host *shpnt;
-	Scsi_Device *SDpnt;
-	struct Scsi_Device_Template *sdtpnt;
-	const char *name;
-	int out_of_space = 0;
-
-	if (tpnt->next || !tpnt->detect)
-		return 1;	/* Must be already loaded, or
-				 * no detect routine available
-				 */
-
-	/* If max_sectors isn't set, default to max */
-	if (!tpnt->max_sectors)
-		tpnt->max_sectors = 1024;
-
-	pcount = next_scsi_host;
-
-	MOD_INC_USE_COUNT;
-
-	/* The detect routine must carefully spinunlock/spinlock if 
-	   it enables interrupts, since all interrupt handlers do 
-	   spinlock as well.  */
-
-	/*
-	 * detect should do its own locking
-	 */
-	tpnt->present = tpnt->detect(tpnt);
-
-	if (tpnt->present) {
-		if (pcount == next_scsi_host) {
-			if (tpnt->present > 1) {
-				printk(KERN_ERR "scsi: Failure to register low-level scsi driver");
-				scsi_unregister_host(tpnt);
-				return 1;
-			}
-			/* 
-			 * The low-level driver failed to register a driver.
-			 * We can do this now.
-			 */
-			if(scsi_register(tpnt, 0)==NULL)
-			{
-				printk(KERN_ERR "scsi: register failed.\n");
-				scsi_unregister_host(tpnt);
-				return 1;
-			}
-		}
-		tpnt->next = scsi_hosts;	/* Add to the linked list */
-		scsi_hosts = tpnt;
-
-		/* Add the new driver to /proc/scsi */
-#ifdef CONFIG_PROC_FS
-		build_proc_dir_entries(tpnt);
-#endif
-
-
-		/*
-		 * Add the kernel threads for each host adapter that will
-		 * handle error correction.
-		 */
-		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-			if (shpnt->hostt == tpnt) {
-				DECLARE_MUTEX_LOCKED(sem);
-
-				shpnt->eh_notify = &sem;
-				kernel_thread((int (*)(void *)) scsi_error_handler,
-					      (void *) shpnt, 0);
-
-				/*
-				 * Now wait for the kernel error thread to initialize itself
-				 * as it might be needed when we scan the bus.
-				 */
-				down(&sem);
-				shpnt->eh_notify = NULL;
-			}
-		}
-
-		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-			if (shpnt->hostt == tpnt) {
-				if (tpnt->info) {
-					name = tpnt->info(shpnt);
-				} else {
-					name = tpnt->name;
-				}
-				printk(KERN_INFO "scsi%d : %s\n",		/* And print a little message */
-				       shpnt->host_no, name);
-				strncpy(shpnt->host_driverfs_dev.name,name,
-					DEVICE_NAME_SIZE-1);
-				sprintf(shpnt->host_driverfs_dev.bus_id,
-					"scsi%d",
-					shpnt->host_no);
-			}
-		}
-
-		/* The next step is to call scan_scsis here.  This generates the
-		 * Scsi_Devices entries
-		 */
-		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-			if (shpnt->hostt == tpnt) {
-				/* first register parent with driverfs */
-				device_register(&shpnt->host_driverfs_dev);
-				scan_scsis(shpnt, 0, 0, 0, 0);
-			}
-		}
-
-		for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
-			if (sdtpnt->init && sdtpnt->dev_noticed)
-				(*sdtpnt->init) ();
-		}
-
-		/*
-		 * Next we create the Scsi_Cmnd structures for this host 
-		 */
-		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-			for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next)
-				if (SDpnt->host->hostt == tpnt) {
-					for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-						if (sdtpnt->attach)
-							(*sdtpnt->attach) (SDpnt);
-					if (SDpnt->attached) {
-						scsi_build_commandblocks(SDpnt);
-						if (SDpnt->current_queue_depth == 0)
-							out_of_space = 1;
-					}
-				}
-		}
-
-		/* This does any final handling that is required. */
-		for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
-			if (sdtpnt->finish && sdtpnt->nr_dev) {
-				(*sdtpnt->finish) ();
-			}
-		}
-	}
-
-	if (out_of_space) {
-		scsi_unregister_host(tpnt);	/* easiest way to clean up?? */
-		return 1;
-	} else
-		return 0;
-}
-
-/*
- * Similarly, this entry point should be called by a loadable module if it
- * is trying to remove a low level scsi driver from the system.
- */
-int scsi_unregister_host(Scsi_Host_Template * tpnt)
-{
-	int online_status;
-	int pcount0, pcount;
-	Scsi_Cmnd *SCpnt;
-	Scsi_Device *SDpnt;
-	Scsi_Device *SDpnt1;
-	struct Scsi_Device_Template *sdtpnt;
-	struct Scsi_Host *sh1;
-	struct Scsi_Host *shpnt;
-	char name[10];	/* host_no>=10^9? I don't think so. */
-
-	/* get the big kernel lock, so we don't race with open() */
-	lock_kernel();
-
-	/*
-	 * First verify that this host adapter is completely free with no pending
-	 * commands 
-	 */
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = SDpnt->next) {
-			if (SDpnt->host->hostt == tpnt
-			    && SDpnt->host->hostt->module
-			    && GET_USE_COUNT(SDpnt->host->hostt->module))
-				goto err_out;
-			/* 
-			 * FIXME(eric) - We need to find a way to notify the
-			 * low level driver that we are shutting down - via the
-			 * special device entry that still needs to get added. 
-			 *
-			 * Is detach interface below good enough for this?
-			 */
-		}
-	}
-
-	/*
-	 * FIXME(eric) put a spinlock on this.  We force all of the devices offline
-	 * to help prevent race conditions where other hosts/processors could try and
-	 * get in and queue a command.
-	 */
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = SDpnt->next) {
-			if (SDpnt->host->hostt == tpnt)
-				SDpnt->online = FALSE;
-
-		}
-	}
-
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		if (shpnt->hostt != tpnt) {
-			continue;
-		}
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = SDpnt->next) {
-			/*
-			 * Loop over all of the commands associated with the device.  If any of
-			 * them are busy, then set the state back to inactive and bail.
-			 */
-			for (SCpnt = SDpnt->device_queue; SCpnt;
-			     SCpnt = SCpnt->next) {
-				online_status = SDpnt->online;
-				SDpnt->online = FALSE;
-				if (SCpnt->request && SCpnt->request->rq_status != RQ_INACTIVE) {
-					printk(KERN_ERR "SCSI device not inactive - rq_status=%d, target=%d, pid=%ld, state=%d, owner=%d.\n",
-					       SCpnt->request->rq_status, SCpnt->target, SCpnt->pid,
-					     SCpnt->state, SCpnt->owner);
-					for (SDpnt1 = shpnt->host_queue; SDpnt1;
-					     SDpnt1 = SDpnt1->next) {
-						for (SCpnt = SDpnt1->device_queue; SCpnt;
-						     SCpnt = SCpnt->next)
-							if (SCpnt->request->rq_status == RQ_SCSI_DISCONNECTING)
-								SCpnt->request->rq_status = RQ_INACTIVE;
-					}
-					SDpnt->online = online_status;
-					printk(KERN_ERR "Device busy???\n");
-					goto err_out;
-				}
-				/*
-				 * No, this device is really free.  Mark it as such, and
-				 * continue on.
-				 */
-				SCpnt->state = SCSI_STATE_DISCONNECTING;
-                                if(SCpnt->request)
-                                        SCpnt->request->rq_status = RQ_SCSI_DISCONNECTING;	/* Mark as busy */
-			}
-		}
-	}
-	/* Next we detach the high level drivers from the Scsi_Device structures */
-
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		if (shpnt->hostt != tpnt) {
-			continue;
-		}
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = SDpnt->next) {
-			for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-				if (sdtpnt->detach)
-					(*sdtpnt->detach) (SDpnt);
-
-			/* If something still attached, punt */
-			if (SDpnt->attached) {
-				printk(KERN_ERR "Attached usage count = %d\n", SDpnt->attached);
-				goto err_out;
-			}
-			if (shpnt->hostt->slave_detach)
-				(*shpnt->hostt->slave_detach) (SDpnt);
-			devfs_unregister (SDpnt->de);
-			put_device(&SDpnt->sdev_driverfs_dev);
-		}
-	}
-
-	/*
-	 * Next, kill the kernel error recovery thread for this host.
-	 */
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		if (shpnt->hostt == tpnt
-		    && shpnt->ehandler != NULL) {
-			DECLARE_MUTEX_LOCKED(sem);
-
-			shpnt->eh_notify = &sem;
-			send_sig(SIGHUP, shpnt->ehandler, 1);
-			down(&sem);
-			shpnt->eh_notify = NULL;
-		}
-	}
-
-	/* Next we free up the Scsi_Cmnd structures for this host */
-
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		if (shpnt->hostt != tpnt) {
-			continue;
-		}
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = shpnt->host_queue) {
-			scsi_release_commandblocks(SDpnt);
-
-			blk_cleanup_queue(&SDpnt->request_queue);
-			/* Next free up the Scsi_Device structures for this host */
-			shpnt->host_queue = SDpnt->next;
-			if (SDpnt->inquiry)
-				kfree(SDpnt->inquiry);
-			kfree((char *) SDpnt);
-
-		}
-	}
-
-	/* Next we go through and remove the instances of the individual hosts
-	 * that were detected */
-
-	pcount0 = next_scsi_host;
-	for (shpnt = scsi_hostlist; shpnt; shpnt = sh1) {
-		sh1 = shpnt->next;
-		if (shpnt->hostt != tpnt)
-			continue;
-		pcount = next_scsi_host;
-		/* Remove the /proc/scsi directory entry */
-		sprintf(name,"%d",shpnt->host_no);
-		remove_proc_entry(name, tpnt->proc_dir);
-		put_device(&shpnt->host_driverfs_dev);
-		if (tpnt->release)
-			(*tpnt->release) (shpnt);
-		else {
-			/* This is the default case for the release function.
-			 * It should do the right thing for most correctly
-			 * written host adapters.
-			 */
-			if (shpnt->irq)
-				free_irq(shpnt->irq, NULL);
-			if (shpnt->dma_channel != 0xff)
-				free_dma(shpnt->dma_channel);
-			if (shpnt->io_port && shpnt->n_io_port)
-				release_region(shpnt->io_port, shpnt->n_io_port);
-		}
-		if (pcount == next_scsi_host)
-			scsi_unregister(shpnt);
-		tpnt->present--;
-	}
-
-	if (pcount0 != next_scsi_host)
-		printk(KERN_INFO "scsi : %d host%s left.\n", next_scsi_host,
-		       (next_scsi_host == 1) ? "" : "s");
-
-	/*
-	 * Remove it from the linked list and /proc if all
-	 * hosts were successfully removed (ie preset == 0)
-	 */
-	if (!tpnt->present) {
-		Scsi_Host_Template **SHTp = &scsi_hosts;
-		Scsi_Host_Template *SHT;
-
-		while ((SHT = *SHTp) != NULL) {
-			if (SHT == tpnt) {
-				*SHTp = SHT->next;
-				remove_proc_entry(tpnt->proc_name, proc_scsi);
-				break;
-			}
-			SHTp = &SHT->next;
-		}
-	}
-	MOD_DEC_USE_COUNT;
-
-	unlock_kernel();
-	return 0;
-
-err_out:
-	unlock_kernel();
-	return -1;
-}
-
-/*
  * This entry point should be called by a loadable module if it is trying
  * add a high level scsi driver to the system.
  */
@@ -2361,7 +1981,7 @@
 	int out_of_space = 0;
 
 #ifdef CONFIG_KMOD
-	if (scsi_hosts == NULL)
+	if (scsi_host_get_next(NULL) == NULL)
 		request_module("scsi_hostadapter");
 #endif
 
@@ -2375,7 +1995,8 @@
 	 * First scan the devices that we know about, and see if we notice them.
 	 */
 
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+	for (shpnt = scsi_host_get_next(NULL); shpnt;
+	     shpnt = scsi_host_get_next(shpnt)) {
 		for (SDpnt = shpnt->host_queue; SDpnt;
 		     SDpnt = SDpnt->next) {
 			if (tpnt->detect)
@@ -2394,7 +2015,8 @@
 	/*
 	 * Now actually connect the devices to the new driver.
 	 */
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+	for (shpnt = scsi_host_get_next(NULL); shpnt;
+	     shpnt = scsi_host_get_next(shpnt)) {
 		for (SDpnt = shpnt->host_queue; SDpnt;
 		     SDpnt = SDpnt->next) {
 			if (tpnt->attach)
@@ -2444,7 +2066,8 @@
 	 * Next, detach the devices from the driver.
 	 */
 
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+	for (shpnt = scsi_host_get_next(NULL); shpnt;
+	     shpnt = scsi_host_get_next(shpnt)) {
 		for (SDpnt = shpnt->host_queue; SDpnt;
 		     SDpnt = SDpnt->next) {
 			if (tpnt->detach)
@@ -2516,7 +2139,8 @@
 	Scsi_Device *SDpnt;
 	printk(KERN_INFO "Dump of scsi host parameters:\n");
 	i = 0;
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+	for (shpnt = scsi_host_get_next(NULL); shpnt;
+	     shpnt = scsi_host_get_next(shpnt)) {
 		printk(KERN_INFO " %d %d %d : %d %d\n",
 		       shpnt->host_failed,
 		       shpnt->host_busy,
@@ -2527,7 +2151,8 @@
 
 	printk(KERN_INFO "\n\n");
 	printk(KERN_INFO "Dump of scsi command parameters:\n");
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+	for (shpnt = scsi_host_get_next(NULL); shpnt;
+	     shpnt = scsi_host_get_next(shpnt)) {
 		printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result\n");
 		for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
 			for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
@@ -2565,26 +2190,6 @@
 }
 #endif				/* CONFIG_PROC_FS */
 
-static int __init scsi_host_no_init (char *str)
-{
-    static int next_no = 0;
-    char *temp;
-
-    while (str) {
-	temp = str;
-	while (*temp && (*temp != ':') && (*temp != ','))
-	    temp++;
-	if (!*temp)
-	    temp = NULL;
-	else
-	    *temp++ = 0;
-	scsi_host_no_insert(str, next_no);
-	str = temp;
-	next_no++;
-    }
-    return 1;
-}
-
 static char *scsihosts;
 
 MODULE_PARM(scsihosts, "s");
@@ -2724,9 +2329,8 @@
 #endif
 
         scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
-        if (scsihosts)
-		printk(KERN_INFO "scsi: host order: %s\n", scsihosts);	
-	scsi_host_no_init (scsihosts);
+
+	scsi_host_hn_init(scsihosts);
 
 	bus_register(&scsi_driverfs_bus_type);
 
@@ -2738,19 +2342,11 @@
 
 static void __exit exit_scsi(void)
 {
-	Scsi_Host_Name *shn, *shn2 = NULL;
 	int i;
 
         devfs_unregister (scsi_devfs_handle);
-        for (shn = scsi_host_no_list;shn;shn = shn->next) {
-		if (shn->name)
-			kfree(shn->name);
-                if (shn2)
-			kfree (shn2);
-                shn2 = shn;
-        }
-        if (shn2)
-		kfree (shn2);
+
+	scsi_host_hn_release();
 
 #ifdef CONFIG_PROC_FS
 	/* No, we're not here anymore. Don't show the /proc/scsi files. */
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/scsi.h	Fri Oct 18 21:03:03 2002
@@ -877,6 +877,12 @@
 
 extern int scsi_reset_provider(Scsi_Device *, int);
 
+#define MSG_SIMPLE_TAG	0x20
+#define MSG_HEAD_TAG	0x21
+#define MSG_ORDERED_TAG	0x22
+
+#define SCSI_NO_TAG	(-1)    /* identify no tag in use */
+
 /**
  * scsi_activate_tcq - turn on tag command queueing
  * @SDpnt:	device to turn on TCQ for
@@ -892,7 +898,7 @@
 
         if(SDpnt->tagged_supported && !blk_queue_tagged(q)) {
                 blk_queue_init_tags(q, depth);
-                SDpnt->tagged_queue = 1;
+		scsi_adjust_queue_depth(SDpnt, MSG_ORDERED_TAG, depth);
         }
 }
 
@@ -902,13 +908,8 @@
  **/
 static inline void scsi_deactivate_tcq(Scsi_Device *SDpnt) {
         blk_queue_free_tags(&SDpnt->request_queue);
-        SDpnt->tagged_queue = 0;
+	scsi_adjust_queue_depth(SDpnt, 0, 2);
 }
-#define MSG_SIMPLE_TAG	0x20
-#define MSG_HEAD_TAG	0x21
-#define MSG_ORDERED_TAG	0x22
-
-#define SCSI_NO_TAG	(-1)    /* identify no tag in use */
 
 /**
  * scsi_populate_tag_msg - place a tag message in a buffer
diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
--- a/drivers/scsi/scsi_debug.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/scsi/scsi_debug.c	Fri Oct 18 21:03:05 2002
@@ -108,9 +108,13 @@
 #define SDEBUG_SENSE_LEN 32
 
 struct sdebug_dev_info {
-	Scsi_Device * sdp;
 	unsigned char sense_buff[SDEBUG_SENSE_LEN];	/* weak nexus */
+	unsigned int channel;
+	unsigned int target;
+	unsigned int lun;
+	struct Scsi_Host *host;
 	char reset;
+	char used;
 };
 static struct sdebug_dev_info * devInfop;
 
@@ -154,7 +158,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(Scsi_Device * sdp);
+static struct sdebug_dev_info * devInfoReg(Scsi_Cmnd *scmd);
 static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, 
 			    int asc, int asq, int inbandLen);
 static int check_reset(Scsi_Cmnd * SCpnt, struct sdebug_dev_info * devip);
@@ -222,7 +226,7 @@
 		return schedule_resp(SCpnt, NULL, done, 0, 0);
         }
 
-	if ((target > driver_template.this_id) || (SCpnt->lun != 0))
+	if (SCpnt->lun != 0)
 		return schedule_resp(SCpnt, NULL, done, 
 				     DID_NO_CONNECT << 16, 0);
 #if 0
@@ -230,14 +234,10 @@
 	       (int)SCpnt->device->host->host_no, (int)SCpnt->device->id,
 	       SCpnt->device, (int)*cmd);
 #endif
-	if (NULL == SCpnt->device->hostdata) {
-		devip = devInfoReg(SCpnt->device);
-		if (NULL == devip)
-			return schedule_resp(SCpnt, NULL, done, 
-					     DID_NO_CONNECT << 16, 0);
-		SCpnt->device->hostdata = devip;
-	}
-	devip = SCpnt->device->hostdata;
+	devip = devInfoReg(SCpnt);
+	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) &&
@@ -474,8 +474,8 @@
 		int dev_id_num, len;
 		char dev_id_str[6];
 		
-		dev_id_num = ((devip->sdp->host->host_no + 1) * 1000) + 
-			      devip->sdp->id;
+		dev_id_num = ((devip->host->host_no + 1) * 1000) + 
+			      devip->target;
 		len = snprintf(dev_id_str, 6, "%d", dev_id_num);
 		len = (len > 6) ? 6 : len;
 		if (0 == cmd[2]) { /* supported vital product data pages */
@@ -861,8 +861,7 @@
 	if (++num_releases == num_present) {
 #ifdef DRIVERFS_SUPPORT
 		do_remove_driverfs_files();
-		remove_driver(&sdebug_driverfs_driver);
-		// driver_unregister(&sdebug_driverfs_driver);
+		driver_unregister(&sdebug_driverfs_driver);
 #endif
 		vfree(fake_storep);
 		vfree(devInfop);
@@ -870,21 +869,28 @@
 	return 0;
 }
 
-static struct sdebug_dev_info * devInfoReg(Scsi_Device * sdp)
+static struct sdebug_dev_info * devInfoReg(Scsi_Cmnd *scmd)
 {
 	int k;
 	struct sdebug_dev_info * devip;
 
 	for (k = 0; k < scsi_debug_num_devs; ++k) {
 		devip = &devInfop[k];
-		if (devip->sdp == sdp)
+		if ((devip->channel == scmd->channel) &&
+		    (devip->target == scmd->target) &&
+		    (devip->lun == scmd->lun) &&
+		    (devip->host == scmd->host))
 			return devip;
 	}
 	for (k = 0; k < scsi_debug_num_devs; ++k) {
 		devip = &devInfop[k];
-		if (NULL == devip->sdp) {
-			devip->sdp = sdp;
+		if (!devip->used) {
+			devip->channel = scmd->channel;
+			devip->target = scmd->target;
+			devip->lun = scmd->lun;
+			devip->host = scmd->host;
 			devip->reset = 1;
+			devip->used = 1;
 			memset(devip->sense_buff, 0, SDEBUG_SENSE_LEN);
 			devip->sense_buff[0] = 0x70;
 			return devip;
@@ -934,19 +940,15 @@
 
 static int scsi_debug_device_reset(Scsi_Cmnd * SCpnt)
 {
-	Scsi_Device * sdp;
-	int k;
+	struct sdebug_dev_info * devip;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 		printk(KERN_INFO "scsi_debug: device_reset\n");
 	++num_dev_resets;
-	if (SCpnt && ((sdp = SCpnt->device))) {
-		for (k = 0; k < scsi_debug_num_devs; ++k) {
-			if (sdp->hostdata == (devInfop + k))
-				break;
-		}
-		if (k < scsi_debug_num_devs)
-			devInfop[k].reset = 1;
+	if (SCpnt) {
+		devip = devInfoReg(SCpnt);
+		if (devip)
+			devip->reset = 1;
 	}
 	return SUCCESS;
 }
@@ -960,9 +962,9 @@
 	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 = sdp->host))) {
+	if (SCpnt && ((sdp = SCpnt->device)) && ((hp = SCpnt->host))) {
 		for (k = 0; k < scsi_debug_num_devs; ++k) {
-			if (hp == devInfop[k].sdp->host)
+			if (hp == devInfop[k].host)
 				devInfop[k].reset = 1;
 		}
 	}
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/scsi_error.c	Fri Oct 18 21:03:03 2002
@@ -502,6 +502,10 @@
 	 */
 	scmd->owner = SCSI_OWNER_LOWLEVEL;
 
+	if (scmd->device->scsi_level <= SCSI_2)
+		scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
+			(scmd->lun << 5 & 0xe0);
+
 	if (host->can_queue) {
 		DECLARE_MUTEX_LOCKED(sem);
 
@@ -610,9 +614,6 @@
 	memcpy((void *) scmd->cmnd, (void *) generic_sense,
 	       sizeof(generic_sense));
 
-	if (scmd->device->scsi_level <= SCSI_2)
-		scmd->cmnd[1] = scmd->lun << 5;
-
 	scsi_result = (!scmd->host->hostt->unchecked_isa_dma)
 	    ? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA);
 
@@ -839,9 +840,6 @@
 	memcpy((void *) scmd->cmnd, (void *) tur_command,
 	       sizeof(tur_command));
 
-	if (scmd->device->scsi_level <= SCSI_2)
-		scmd->cmnd[1] = scmd->lun << 5;
-
 	/*
 	 * zero the sense buffer.  the scsi spec mandates that any
 	 * untransferred sense data should be interpreted as being zero.
@@ -1419,7 +1417,7 @@
 	}
 
 	sreq->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
-	sreq->sr_cmnd[1] = (sdev->scsi_level <= SCSI_2) ? (sdev->lun << 5) : 0;
+	sreq->sr_cmnd[1] = 0;
 	sreq->sr_cmnd[2] = 0;
 	sreq->sr_cmnd[3] = 0;
 	sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
--- a/drivers/scsi/scsi_ioctl.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/scsi_ioctl.c	Fri Oct 18 21:03:08 2002
@@ -160,7 +160,7 @@
 	       return 0;
 
 	scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-	scsi_cmd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
+	scsi_cmd[1] = 0;
 	scsi_cmd[2] = 0;
 	scsi_cmd[3] = 0;
 	scsi_cmd[4] = state;
@@ -297,12 +297,6 @@
 	if(copy_from_user(buf, cmd_in + cmdlen, inlen))
 		goto error;
 
-	/*
-	 * Set the lun field to the correct value.
-	 */
-	if (dev->scsi_level <= SCSI_2)
-		cmd[1] = (cmd[1] & 0x1f) | (dev->lun << 5);
-
 	switch (opcode) {
 	case FORMAT_UNIT:
 		timeout = FORMAT_UNIT_TIMEOUT;
@@ -416,7 +410,6 @@
 int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
 {
 	char scsi_cmd[MAX_COMMAND_SIZE];
-	char cmd_byte1;
 
 	/* No idea how this happens.... */
 	if (!dev)
@@ -431,7 +424,6 @@
 	if (!scsi_block_when_processing_errors(dev)) {
 		return -ENODEV;
 	}
-	cmd_byte1 = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
 
 	switch (cmd) {
 	case SCSI_IOCTL_GET_IDLUN:
@@ -484,7 +476,7 @@
 		return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW);
 	case SCSI_IOCTL_TEST_UNIT_READY:
 		scsi_cmd[0] = TEST_UNIT_READY;
-		scsi_cmd[1] = cmd_byte1;
+		scsi_cmd[1] = 0;
 		scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
 		scsi_cmd[4] = 0;
 		return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
@@ -492,7 +484,7 @@
 		break;
 	case SCSI_IOCTL_START_UNIT:
 		scsi_cmd[0] = START_STOP;
-		scsi_cmd[1] = cmd_byte1;
+		scsi_cmd[1] = 0;
 		scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
 		scsi_cmd[4] = 1;
 		return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
@@ -500,7 +492,7 @@
 		break;
 	case SCSI_IOCTL_STOP_UNIT:
 		scsi_cmd[0] = START_STOP;
-		scsi_cmd[1] = cmd_byte1;
+		scsi_cmd[1] = 0;
 		scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
 		scsi_cmd[4] = 0;
 		return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/scsi_lib.c	Fri Oct 18 21:03:04 2002
@@ -857,7 +857,7 @@
 				scsi_init_cmd_from_req(SCpnt, SRpnt);
 			}
 
-		} else if (req->flags & REQ_CMD) {
+		} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
 			SRpnt = NULL;
 			STpnt = scsi_get_request_dev(req);
 			if (!STpnt) {
@@ -919,7 +919,7 @@
 		req = NULL;
 		spin_unlock_irq(q->queue_lock);
 
-		if (SCpnt->request->flags & REQ_CMD) {
+		if (SCpnt->request->flags & (REQ_CMD | REQ_BLOCK_PC)) {
 			/*
 			 * This will do a couple of things:
 			 *  1) Fill in the actual SCSI command.
diff -Nru a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c
--- a/drivers/scsi/scsi_merge.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/scsi_merge.c	Fri Oct 18 21:03:08 2002
@@ -62,16 +62,28 @@
 	int count, gfp_mask;
 
 	/*
-	 * First we need to know how many scatter gather segments are needed.
+	 * non-sg block request. FIXME: check bouncing for isa hosts!
 	 */
-	count = req->nr_phys_segments;
+	if ((req->flags & REQ_BLOCK_PC) && !req->bio) {
+		/*
+		 * FIXME: isa bouncing
+		 */
+		if (SCpnt->host->unchecked_isa_dma)
+			goto fail;
+
+		SCpnt->request_bufflen = req->data_len;
+		SCpnt->request_buffer = req->data;
+		req->buffer = req->data;
+		SCpnt->use_sg = 0;
+		return 1;
+	}
 
 	/*
 	 * we used to not use scatter-gather for single segment request,
 	 * but now we do (it makes highmem I/O easier to support without
 	 * kmapping pages)
 	 */
-	SCpnt->use_sg = count;
+	SCpnt->use_sg = req->nr_phys_segments;
 
 	gfp_mask = GFP_NOIO;
 	if (in_interrupt()) {
@@ -111,6 +123,7 @@
 	/*
 	 * kill it. there should be no leftover blocks in this request
 	 */
+fail:
 	SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
 	BUG_ON(SCpnt);
 	return 0;
diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
--- a/drivers/scsi/scsi_proc.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/scsi_proc.c	Fri Oct 18 21:03:03 2002
@@ -119,35 +119,44 @@
 	return(ret);
 }
 
-void build_proc_dir_entries(Scsi_Host_Template * tpnt)
+void scsi_proc_host_mkdir(Scsi_Host_Template *shost_tp)
 {
-	struct Scsi_Host *hpnt;
-	char name[10];	/* see scsi_unregister_host() */
-
-	tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi);
-        if (!tpnt->proc_dir) {
-                printk(KERN_ERR "Unable to proc_mkdir in scsi.c/build_proc_dir_entries");
+	shost_tp->proc_dir = proc_mkdir(shost_tp->proc_name, proc_scsi);
+        if (!shost_tp->proc_dir) {
+		printk(KERN_ERR "%s: proc_mkdir failed for %s\n",
+		       __FUNCTION__, shost_tp->proc_name);
                 return;
         }
-	tpnt->proc_dir->owner = tpnt->module;
+	shost_tp->proc_dir->owner = shost_tp->module;
+}
+
+void scsi_proc_host_add(struct Scsi_Host *shost)
+{
+	char name[10];
+	struct proc_dir_entry *p;
 
-	hpnt = scsi_hostlist;
-	while (hpnt) {
-		if (tpnt == hpnt->hostt) {
-			struct proc_dir_entry *p;
-			sprintf(name,"%d",hpnt->host_no);
-			p = create_proc_read_entry(name,
-					S_IFREG | S_IRUGO | S_IWUSR,
-					tpnt->proc_dir,
-					proc_scsi_read,
-					(void *)hpnt);
-			if (!p)
-				panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");
-			p->write_proc=proc_scsi_write;
-			p->owner = tpnt->module;
-		}
-		hpnt = hpnt->next;
+	sprintf(name,"%d",shost->host_no);
+	p = create_proc_read_entry(name,
+			S_IFREG | S_IRUGO | S_IWUSR,
+			shost->hostt->proc_dir,
+			proc_scsi_read,
+			(void *)shost);
+	if (!p) {
+		printk(KERN_ERR "%s: Failed to register host %d in"
+		       "%s\n", __FUNCTION__, shost->host_no,
+		       shost->hostt->proc_name);
+	} else {
+		p->write_proc=proc_scsi_write;
+		p->owner = shost->hostt->module;
 	}
+
+}
+
+void scsi_proc_host_rm(struct Scsi_Host *shost)
+{
+	char name[10];
+	sprintf(name,"%d",shost->host_no);
+	remove_proc_entry(name, shost->hostt->proc_dir);
 }
 
 /*
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/scsi/scsi_scan.c	Fri Oct 18 21:03:07 2002
@@ -291,15 +291,11 @@
  **/
 static void scsi_unlock_floptical(Scsi_Request *sreq, unsigned char *result)
 {
-	Scsi_Device *sdscan = sreq->sr_device;
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
 
 	printk(KERN_NOTICE "scsi: unlocking floptical drive\n");
 	scsi_cmd[0] = MODE_SENSE;
-	if (sdscan->scsi_level <= SCSI_2)
-		scsi_cmd[1] = (sdscan->lun << 5) & 0xe0;
-	else
-		scsi_cmd[1] = 0;
+	scsi_cmd[1] = 0;
 	scsi_cmd[2] = 0x2e;
 	scsi_cmd[3] = 0;
 	scsi_cmd[4] = 0x2a;	/* size */
@@ -611,8 +607,6 @@
 {
 	unsigned char *evpd_page;
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
-	int lun = sdev->lun;
-	int scsi_level = sdev->scsi_level;
 	int max_lgth = 255;
 
 retry:
@@ -629,10 +623,7 @@
 
 	memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
 	scsi_cmd[0] = INQUIRY;
-	if ((lun > 0) && (scsi_level <= SCSI_2))
-		scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
-	else
-		scsi_cmd[1] = 0x01;	/* SCSI_3 and higher, don't touch */
+	scsi_cmd[1] = 0x01;
 	scsi_cmd[4] = max_lgth;
 	sreq->sr_cmd_len = 0;
 	sreq->sr_sense_buffer[0] = 0;
@@ -870,8 +861,6 @@
 	unsigned char *id_page;
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
 	int id_idx, scnt, ret;
-	int lun = sdev->lun;
-	int scsi_level = sdev->scsi_level;
 	int max_lgth = 255;
 
 retry:
@@ -888,10 +877,7 @@
 
 	memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
 	scsi_cmd[0] = INQUIRY;
-	if ((lun > 0) && (scsi_level <= SCSI_2))
-		scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
-	else
-		scsi_cmd[1] = 0x01;	/* SCSI_3 and higher, don't touch */
+	scsi_cmd[1] = 0x01;
 	scsi_cmd[2] = 0x83;
 	scsi_cmd[4] = max_lgth;
 	sreq->sr_cmd_len = 0;
@@ -977,8 +963,6 @@
 {
 	unsigned char *serialnumber_page;
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
-	int lun = sdev->lun;
-	int scsi_level = sdev->scsi_level;
 	int max_lgth = 255;
 
  retry:
@@ -995,10 +979,7 @@
 
 	memset(scsi_cmd, 0, MAX_COMMAND_SIZE);
 	scsi_cmd[0] = INQUIRY;
-	if ((lun > 0) && (scsi_level <= SCSI_2))
-		scsi_cmd[1] = ((lun << 5) & 0xe0) | 0x01;
-	else
-		scsi_cmd[1] = 0x01;	/* SCSI_3 and higher, don't touch */
+	scsi_cmd[1] = 0x01;
 	scsi_cmd[2] = 0x80;
 	scsi_cmd[4] = max_lgth;
 	sreq->sr_cmd_len = 0;
@@ -1181,8 +1162,6 @@
 
 	memset(scsi_cmd, 0, 6);
 	scsi_cmd[0] = INQUIRY;
-	if ((sdev->lun > 0) && (sdev->scsi_level <= SCSI_2))
-		scsi_cmd[1] = (sdev->lun << 5) & 0xe0;
 	scsi_cmd[4] = 36;	/* issue conservative alloc_length */
 	sreq->sr_cmd_len = 0;
 	sreq->sr_data_direction = SCSI_DATA_READ;
@@ -1230,8 +1209,6 @@
 	if (possible_inq_resp_len > 36) {	/* do additional INQUIRY */
 		memset(scsi_cmd, 0, 6);
 		scsi_cmd[0] = INQUIRY;
-		if ((sdev->lun > 0) && (sdev->scsi_level <= SCSI_2))
-			scsi_cmd[1] = (sdev->lun << 5) & 0xe0;
 		scsi_cmd[4] = (unsigned char) possible_inq_resp_len;
 		sreq->sr_cmd_len = 0;
 		sreq->sr_data_direction = SCSI_DATA_READ;
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/scsi_syms.c	Fri Oct 18 21:03:04 2002
@@ -91,8 +91,9 @@
 /*
  * These are here only while I debug the rest of the scsi stuff.
  */
-EXPORT_SYMBOL(scsi_hostlist);
-EXPORT_SYMBOL(scsi_hosts);
+EXPORT_SYMBOL(scsi_host_get_next);
+EXPORT_SYMBOL(scsi_host_hn_get);
+EXPORT_SYMBOL(scsi_host_put);
 EXPORT_SYMBOL(scsi_devicelist);
 EXPORT_SYMBOL(scsi_device_types);
 
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/scsi/sd.c	Fri Oct 18 21:03:07 2002
@@ -51,7 +51,6 @@
 
 #define MAJOR_NR SCSI_DISK0_MAJOR
 #define LOCAL_END_REQUEST
-#define DEVICE_NR(device) (((major(device) & SD_MAJOR_MASK) << (8 - 4)) + (minor(device) >> 4))
 #include <linux/blk.h>
 #include <linux/blkpg.h>
 #include "scsi.h"
@@ -87,10 +86,10 @@
 static Scsi_Disk ** sd_dsk_arr;
 static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
 
-static int check_scsidisk_media_change(kdev_t);
-static int sd_revalidate(kdev_t);
+static int check_scsidisk_media_change(struct gendisk *);
+static int sd_revalidate(struct gendisk *);
 
-static void sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr);
+static void sd_init_onedisk(Scsi_Disk * sdkp, struct gendisk *disk);
 
 static int sd_init(void);
 static void sd_finish(void);
@@ -187,17 +186,16 @@
 static int sd_ioctl(struct inode * inode, struct file * filp, 
 		    unsigned int cmd, unsigned long arg)
 {
-	kdev_t dev = inode->i_rdev;
-        Scsi_Disk * sdkp;
-	struct Scsi_Host * host;
-	Scsi_Device * sdp;
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+        Scsi_Disk *sdkp = disk->private_data;
+	Scsi_Device *sdp = sdkp->device;
+	struct Scsi_Host *host;
 	int diskinfo[4];
-	int dsk_nr = DEVICE_NR(dev);
+	int error;
     
-	SCSI_LOG_IOCTL(1, printk("sd_ioctl: dsk_nr=%d, cmd=0x%x\n",
-		       dsk_nr, cmd));
-	sdkp = sd_get_sdisk(dsk_nr);
-	if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
+	SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n",
+						disk->disk_name, cmd));
+	if (!sdp)
 		return -ENODEV;
 	/*
 	 * If we are in the middle of error recovery, don't let anyone
@@ -209,6 +207,10 @@
 	if( !scsi_block_when_processing_errors(sdp) )
 		return -ENODEV;
 
+	error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
+	if (error != -ENOTTY)
+		return error;
+
 	switch (cmd) 
 	{
 		case HDIO_GETGEO:   /* Return BIOS disk parameters */
@@ -264,29 +266,6 @@
 	}
 }
 
-/**
- *	sd_find_queue - yields queue associated with device
- *	@dev: kernel device descriptor (kdev_t)
- *
- *	Returns NULL if no match, otherwise returns pointer to associated
- *	request queue.
- *
- *	Note: this function is invoked (often) from the block subsystem
- *	and should not wait on anything (sd_get_sdisk() does have a read
- *	spinlock).
- **/
-static request_queue_t *sd_find_queue(kdev_t dev)
-{
-	Scsi_Disk *sdkp;
- 	int dsk_nr = DEVICE_NR(dev);
-
-	sdkp = sd_get_sdisk(dsk_nr);
-	if (sdkp && sdkp->device)
-		return &sdkp->device->request_queue;
-	else
-		return NULL;	/* No such device */
-}
-
 static struct gendisk **sd_disks;
 
 /**
@@ -299,33 +278,54 @@
  **/
 static int sd_init_command(Scsi_Cmnd * SCpnt)
 {
-	int dsk_nr, part_nr, this_count;
+	int this_count, timeout;
+	struct gendisk *disk;
 	sector_t block;
-	Scsi_Device *sdp;
-#if CONFIG_SCSI_LOGGING
-	char nbuff[6];
-#endif
+	Scsi_Device *sdp = SCpnt->device;
+
+	timeout = SD_TIMEOUT;
+	if (SCpnt->device->type != TYPE_DISK)
+		timeout = SD_MOD_TIMEOUT;
+
+	/*
+	 * these are already setup, just copy cdb basically
+	 */
+	if (SCpnt->request->flags & REQ_BLOCK_PC) {
+		struct request *rq = SCpnt->request;
+
+		if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
+			return 0;
+
+		memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+		if (rq_data_dir(rq) == WRITE)
+			SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+		else if (rq->data_len)
+			SCpnt->sc_data_direction = SCSI_DATA_READ;
+		else
+			SCpnt->sc_data_direction = SCSI_DATA_NONE;
+
+		this_count = rq->data_len;
+		if (rq->timeout)
+			timeout = rq->timeout;
+
+		goto queue;
+	}
+
 	/*
-	 * don't support specials for nwo
+	 * we only do REQ_CMD and REQ_BLOCK_PC
 	 */
 	if (!(SCpnt->request->flags & REQ_CMD))
 		return 0;
 
-	part_nr = SD_PARTITION(SCpnt->request->rq_dev);
-	dsk_nr = DEVICE_NR(SCpnt->request->rq_dev);
-
+	disk = SCpnt->request->rq_disk;
 	block = SCpnt->request->sector;
 	this_count = SCpnt->request_bufflen >> 9;
 
-	SCSI_LOG_HLQUEUE(1, printk("sd_command_init: dsk_nr=%d, block=%llu, "
-			    "count=%d\n", dsk_nr, (unsigned long long)block, this_count));
+	SCSI_LOG_HLQUEUE(1, printk("sd_command_init: disk=%s, block=%llu, "
+			    "count=%d\n", disk->disk_name, (unsigned long long)block, this_count));
 
-	sdp = SCpnt->device;
-	/* >>>>> the "(part_nr & 0xf)" excludes 15th partition, why?? */
-	/* >>>>> this change is not in the lk 2.5 series */
-	if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) ||
-	    !sdp || !sdp->online ||
- 	    block + SCpnt->request->nr_sectors > get_capacity(sd_disks[dsk_nr])) {
+	if (!sdp || !sdp->online ||
+ 	    block + SCpnt->request->nr_sectors > get_capacity(disk)) {
 		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", 
 				 SCpnt->request->nr_sectors));
 		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
@@ -340,9 +340,8 @@
 		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
 		return 0;
 	}
-	SCSI_LOG_HLQUEUE(2, sd_dskname(dsk_nr, nbuff));
-	SCSI_LOG_HLQUEUE(2, printk("%s : [part_nr=%d], block=%llu\n",
-				   nbuff, part_nr, (unsigned long long)block));
+	SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n",
+				   disk->disk_name, (unsigned long long)block));
 
 	/*
 	 * If we have a 1K hardware sectorsize, prevent access to single
@@ -399,11 +398,10 @@
 	}
 
 	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", 
-		nbuff, (rq_data_dir(SCpnt->request) == WRITE) ? 
+		disk->disk_name, (rq_data_dir(SCpnt->request) == WRITE) ? 
 		"writing" : "reading", this_count, SCpnt->request->nr_sectors));
 
-	SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
-			 ((SCpnt->lun << 5) & 0xe0) : 0;
+	SCpnt->cmnd[1] = 0;
 
 	if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
 		if (this_count > 0xffff)
@@ -433,12 +431,12 @@
 	 * host adapter, it's safe to assume that we can at least transfer
 	 * this many bytes between each connect / disconnect.
 	 */
+queue:
 	SCpnt->transfersize = sdp->sector_size;
 	SCpnt->underflow = this_count << 9;
 
 	SCpnt->allowed = MAX_RETRIES;
-	SCpnt->timeout_per_command = (SCpnt->device->type == TYPE_DISK ?
-				      SD_TIMEOUT : SD_MOD_TIMEOUT);
+	SCpnt->timeout_per_command = timeout;
 
 	/*
 	 * This is the completion routine we use.  This is matched in terms
@@ -468,16 +466,14 @@
  **/
 static int sd_open(struct inode *inode, struct file *filp)
 {
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	Scsi_Disk *sdkp = disk->private_data;
+	Scsi_Device * sdp = sdkp->device;
 	int retval = -ENXIO;
-	Scsi_Device * sdp;
-	Scsi_Disk * sdkp;
-	int dsk_nr = DEVICE_NR(inode->i_rdev);
 
-	SCSI_LOG_HLQUEUE(3, printk("sd_open: dsk_nr=%d, part_nr=%d\n", 
-			    dsk_nr, SD_PARTITION(inode->i_rdev)));
+	SCSI_LOG_HLQUEUE(3, printk("sd_open: disk=%s\n", disk->disk_name));
 
-	sdkp = sd_get_sdisk(dsk_nr);
-	if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
+	if (!sdkp)
 		return -ENXIO;	/* No such device */
 
 	/*
@@ -555,14 +551,12 @@
  **/
 static int sd_release(struct inode *inode, struct file *filp)
 {
-	Scsi_Disk * sdkp;
-	int dsk_nr = DEVICE_NR(inode->i_rdev);
-	Scsi_Device * sdp;
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	Scsi_Disk *sdkp = disk->private_data;
+	Scsi_Device *sdp = sdkp->device;
 
-	SCSI_LOG_HLQUEUE(3, printk("sd_release: dsk_nr=%d, part_nr=%d\n", 
-			    dsk_nr, SD_PARTITION(inode->i_rdev)));
-	sdkp = sd_get_sdisk(dsk_nr);
-	if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
+	SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name));
+	if (!sdp)
 		return -ENODEV; /* open uses ENXIO ?? */
 
 	/* ... and what if there are packets in flight and this close()
@@ -585,12 +579,12 @@
 
 static struct block_device_operations sd_fops =
 {
-	owner:			THIS_MODULE,
-	open:			sd_open,
-	release:		sd_release,
-	ioctl:			sd_ioctl,
-	check_media_change:	check_scsidisk_media_change,
-	revalidate:		sd_revalidate
+	.owner		= THIS_MODULE,
+	.open		= sd_open,
+	.release	= sd_release,
+	.ioctl		= sd_ioctl,
+	.media_changed	= check_scsidisk_media_change,
+	.revalidate_disk= sd_revalidate
 };
 
 /**
@@ -608,12 +602,8 @@
 	sector_t block_sectors = 1;
 	sector_t error_sector;
 #if CONFIG_SCSI_LOGGING
-	char nbuff[6];
-
-	SCSI_LOG_HLCOMPLETE(1, sd_dskname(DEVICE_NR(SCpnt->request->rq_dev), 
-			    nbuff));
 	SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", 
-				      nbuff, result));
+				SCpnt->request->rq_disk->disk_name, result));
 	if (0 != result) {
 		SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[0,2,asc,ascq]"
 				"=%x,%x,%x,%x\n", SCpnt->sense_buffer[0],
@@ -714,21 +704,18 @@
  *
  *	Note: this function is invoked from the block subsystem.
  **/
-static int check_scsidisk_media_change(kdev_t full_dev)
+static int check_scsidisk_media_change(struct gendisk *disk)
 {
+	Scsi_Disk *sdkp = disk->private_data;
+	Scsi_Device *sdp = sdkp->device;
 	int retval;
 	int flag = 0;	/* <<<< what is this for?? */
-	Scsi_Disk * sdkp;
-	Scsi_Device * sdp;
-	int dsk_nr = DEVICE_NR(full_dev);
-
-	sdkp = sd_get_sdisk(dsk_nr);
 
 	SCSI_LOG_HLQUEUE(3, printk("check_scsidisk_media_change: "
-			    "dsk_nr=%d\n", dsk_nr));
-	if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) {
-		printk(KERN_ERR "check_scsidisk_media_change: dsk_nr=%d, "
-		       "invalid device\n", dsk_nr);
+			    "disk=%s\n", disk->disk_name));
+	if (!sdp) {
+		printk(KERN_ERR "check_scsidisk_media_change: disk=%s, "
+		       "invalid device\n", disk->disk_name);
 		return 0;
 	}
 	if (!sdp->removable)
@@ -815,9 +802,7 @@
 
 		while (retries < 3) {
 			cmd[0] = TEST_UNIT_READY;
-			cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-				((sdp->lun << 5) & 0xe0) : 0;
-			memset((void *) &cmd[2], 0, 8);
+			memset((void *) &cmd[1], 0, 9);
 
 			SRpnt->sr_cmd_len = 0;
 			SRpnt->sr_sense_buffer[0] = 0;
@@ -851,9 +836,7 @@
 				printk(KERN_NOTICE "%s: Spinning up disk...",
 				       diskname);
 				cmd[0] = START_STOP;
-				cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-					((sdp->lun << 5) & 0xe0) : 0;
-				cmd[1] |= 1;	/* Return immediately */
+				cmd[1] = 1;	/* Return immediately */
 				memset((void *) &cmd[2], 0, 8);
 				cmd[4] = 1;	/* Start spin cycle */
 				SRpnt->sr_cmd_len = 0;
@@ -894,7 +877,6 @@
 		   Scsi_Request *SRpnt, unsigned char *buffer) {
 
 	unsigned char cmd[10];
-	Scsi_Device *sdp = sdkp->device;
 	int the_result, retries;
 
 	retries = 3;
@@ -902,9 +884,7 @@
 
 		memset((void *) &cmd[0], 0, 10);
 		cmd[0] = MODE_SENSE;
-		cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-			 ((sdp->lun << 5) & 0xe0) : 0;
-		cmd[1] |= 0x08;	/* DBD */
+		cmd[1] = 0x08;	/* DBD */
 		cmd[2] = 0x08;	/* current values, cache page */
 		cmd[4] = 128;	/* allocation length */
 
@@ -924,20 +904,29 @@
 	} while (the_result && retries);
 
 	if (the_result) {
-		printk(KERN_ERR "%s : MODE SENSE failed.\n"
-		       "%s : status = %x, message = %02x, host = %d, driver = %02x \n",
-		       diskname, diskname,
-		       status_byte(the_result),
-		       msg_byte(the_result),
-		       host_byte(the_result),
-		       driver_byte(the_result)
-		    );
-		if (driver_byte(the_result) & DRIVER_SENSE)
-			print_req_sense("sd", SRpnt);
-		else
-			printk(KERN_ERR "%s : sense not available. \n", diskname);
-
-		printk(KERN_ERR "%s : assuming drive cache: write through\n", diskname);
+		if(status_byte(the_result) == CHECK_CONDITION
+		   && (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70
+		   && (SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST
+		   /* The next are ASC 0x24 ASCQ 0x00: Invalid field in CDB */
+		   && SRpnt->sr_sense_buffer[12] == 0x24
+		   && SRpnt->sr_sense_buffer[13] == 0x00) {
+			printk(KERN_NOTICE "SCSI device %s: cache data unavailable\n", diskname);
+		} else {
+			printk(KERN_ERR "%s : MODE SENSE failed.\n"
+			       "%s : status = %x, message = %02x, host = %d, driver = %02x \n",
+			       diskname, diskname,
+			       status_byte(the_result),
+			       msg_byte(the_result),
+			       host_byte(the_result),
+			       driver_byte(the_result)
+			       );
+			if (driver_byte(the_result) & DRIVER_SENSE)
+				print_req_sense("sd", SRpnt);
+			else
+				printk(KERN_ERR "%s : sense not available. \n", diskname);
+			
+			printk(KERN_ERR "%s : assuming drive cache: write through\n", diskname);
+		}
 		sdkp->WCE = 0;
 		sdkp->RCD = 0;
 	} else {
@@ -968,9 +957,7 @@
 	retries = 3;
 	do {
 		cmd[0] = READ_CAPACITY;
-		cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-			((sdp->lun << 5) & 0xe0) : 0;
-		memset((void *) &cmd[2], 0, 8);
+		memset((void *) &cmd[1], 0, 9);
 		memset((void *) buffer, 0, 8);
 
 		SRpnt->sr_cmd_len = 0;
@@ -1090,7 +1077,6 @@
 
 	memset((void *) &cmd[0], 0, 8);
 	cmd[0] = MODE_SENSE;
-	cmd[1] = (sdp->scsi_level <= SCSI_2) ? ((sdp->lun << 5) & 0xe0) : 0;
 	cmd[2] = modepage;
 	cmd[4] = len;
 
@@ -1157,18 +1143,13 @@
  *	Note: this function is local to this driver.
  **/
 static void
-sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) {
-	char diskname[40];
+sd_init_onedisk(Scsi_Disk * sdkp, struct gendisk *disk)
+{
 	unsigned char *buffer;
 	Scsi_Device *sdp;
 	Scsi_Request *SRpnt;
 
-	SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: dsk_nr=%d\n", dsk_nr));
-
-	/*
-	 * Get the name of the disk, in case we need to log it somewhere.
-	 */
-	sd_dskname(dsk_nr, diskname);
+	SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: disk=%s\n", disk->disk_name));
 
 	/*
 	 * If the device is offline, don't try and read capacity or any
@@ -1198,14 +1179,14 @@
 	sdkp->media_present = 1;
 	sdkp->write_prot = 0;
 
-	sd_spinup_disk(sdkp, diskname, SRpnt, buffer);
-	sd_read_cache_type(sdkp, diskname, SRpnt, buffer);
+	sd_spinup_disk(sdkp, disk->disk_name, SRpnt, buffer);
+	sd_read_cache_type(sdkp, disk->disk_name, SRpnt, buffer);
 
 	if (sdkp->media_present)
-		sd_read_capacity(sdkp, diskname, SRpnt, buffer);
+		sd_read_capacity(sdkp, disk->disk_name, SRpnt, buffer);
 
 	if (sdp->removable && sdkp->media_present)
-		sd_read_write_protect_flag(sdkp, diskname, SRpnt, buffer);
+		sd_read_write_protect_flag(sdkp, disk->disk_name, SRpnt, buffer);
 
 	SRpnt->sr_device->ten = 1;
 	SRpnt->sr_device->remap = 1;
@@ -1324,18 +1305,18 @@
 	Scsi_Disk * sdkp;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n"));
-	for (k = 0; k < N_USED_SD_MAJORS; k++)
-		blk_dev[SD_MAJOR(k)].queue = sd_find_queue;
 
 	for (k = 0; k < sd_template.dev_max; ++k) {
 		sdkp = sd_get_sdisk(k);
 		if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
-			sd_init_onedisk(sdkp, k);
-			if (!sdkp->has_been_registered) {
-				set_capacity(sd_disks[k], sdkp->capacity);
-				add_disk(sd_disks[k]);
-				sdkp->has_been_registered = 1;
-			}
+			sd_init_onedisk(sdkp, sd_disks[k]);
+			if (sdkp->has_been_registered)
+				continue;
+			set_capacity(sd_disks[k], sdkp->capacity);
+			sd_disks[k]->private_data = sdkp;
+			sd_disks[k]->queue = &sdkp->device->request_queue;
+			add_disk(sd_disks[k]);
+			sdkp->has_been_registered = 1;
 		}
 	}
 	return;
@@ -1438,16 +1419,15 @@
 	return 0;
 }
 
-static int sd_revalidate(kdev_t dev)
+static int sd_revalidate(struct gendisk *disk)
 {
-	int dsk_nr = DEVICE_NR(dev);
-	Scsi_Disk * sdkp = sd_get_sdisk(dsk_nr);
+	Scsi_Disk *sdkp = disk->private_data;
 
-	if (!sdkp || !sdkp->device)
+	if (!sdkp->device)
 		return -ENODEV;
 
-	sd_init_onedisk(sdkp, dsk_nr);
-	set_capacity(sd_disks[dsk_nr], sdkp->capacity);
+	sd_init_onedisk(sdkp, disk);
+	set_capacity(disk, sdkp->capacity);
 	return 0;
 }
 
@@ -1465,7 +1445,6 @@
 static void sd_detach(Scsi_Device * sdp)
 {
 	Scsi_Disk *sdkp = NULL;
-	kdev_t dev;
 	int dsk_nr;
 	unsigned long iflags;
 
@@ -1495,7 +1474,6 @@
 
 	if (sdkp->has_been_registered) {
 		sdkp->has_been_registered = 0;
-		dev = MKDEV_SD(dsk_nr);
 		del_gendisk(sd_disks[dsk_nr]);
 	}
 	sdp->attached--;
@@ -1546,10 +1524,8 @@
 			vfree(sd_dsk_arr[k]);
 		vfree(sd_dsk_arr);
 	}
-	for (k = 0; k < N_USED_SD_MAJORS; k++)
-		blk_dev[SD_MAJOR(k)].queue = NULL;
 	sd_template.dev_max = 0;
-	remove_driver(&sd_template.scsi_driverfs_driver);
+	driver_unregister(&sd_template.scsi_driverfs_driver);
 
 	unregister_reboot_notifier(&sd_notifier_block);
 }
@@ -1611,7 +1587,6 @@
 		unsigned char cmd[10] = { 0 };
 
 		cmd[0] = SYNCHRONIZE_CACHE;
-		cmd[1] = SDpnt->scsi_level <= SCSI_2 ? (SDpnt->lun << 5) & 0xe0 : 0;
 		/* leave the rest of the command zero to indicate 
 		 * flush everything */
 		scsi_wait_req(SRpnt, (void *)cmd, NULL, 0,
diff -Nru a/drivers/scsi/sd.h b/drivers/scsi/sd.h
--- a/drivers/scsi/sd.h	Fri Oct 18 21:03:05 2002
+++ b/drivers/scsi/sd.h	Fri Oct 18 21:03:05 2002
@@ -40,6 +40,5 @@
 #define N_SD_MAJORS	8
 
 #define SD_MAJOR_MASK	(N_SD_MAJORS - 1)
-#define SD_PARTITION(i)		(((major(i) & SD_MAJOR_MASK) << 8) | (minor(i) & 255))
 
 #endif
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/sg.c	Fri Oct 18 21:03:04 2002
@@ -705,10 +705,6 @@
 	SRpnt->sr_request->rq_dev = sdp->i_rdev;
 	SRpnt->sr_sense_buffer[0] = 0;
 	SRpnt->sr_cmd_len = hp->cmd_len;
-	if (!(hp->flags & SG_FLAG_LUN_INHIBIT)) {
-		if (sdp->device->scsi_level <= SCSI_2)
-			cmnd[1] = (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
-	}
 	SRpnt->sr_use_sg = srp->data.k_use_sg;
 	SRpnt->sr_sglist_len = srp->data.sglist_len;
 	SRpnt->sr_bufflen = srp->data.bufflen;
@@ -1659,7 +1655,7 @@
 		sg_dev_arr = NULL;
 	}
 	sg_template.dev_max = 0;
-	remove_driver(&sg_template.scsi_driverfs_driver);
+	driver_unregister(&sg_template.scsi_driverfs_driver);
 }
 
 static int
@@ -3103,7 +3099,8 @@
 	struct Scsi_Host *shp;
 	int k;
 
-	for (k = 0, shp = scsi_hostlist; shp; shp = shp->next, ++k) {
+	for (k = 0, shp = scsi_host_get_next(NULL); shp;
+	     shp = scsi_host_get_next(shp), ++k) {
 		for (; k < shp->host_no; ++k)
 			PRINT_PROC("-1\t-1\t-1\t-1\t-1\t-1\n");
 		PRINT_PROC("%u\t%hu\t%hd\t%hu\t%d\t%d\n",
@@ -3147,7 +3144,8 @@
 	char buff[SG_MAX_HOST_STR_LEN];
 	char *cp;
 
-	for (k = 0, shp = scsi_hostlist; shp; shp = shp->next, ++k) {
+	for (k = 0, shp = scsi_host_get_next(NULL); shp;
+	     shp = scsi_host_get_next(shp), ++k) {
 		for (; k < shp->host_no; ++k)
 			PRINT_PROC("<no active host>\n");
 		strncpy(buff, shp->hostt->info ? shp->hostt->info(shp) :
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/scsi/sr.c	Fri Oct 18 21:03:03 2002
@@ -51,7 +51,6 @@
 
 #define MAJOR_NR SCSI_CDROM_MAJOR
 #define LOCAL_END_REQUEST
-#define DEVICE_NR(device) (minor(device))
 #include <linux/blk.h>
 #include "scsi.h"
 #include "hosts.h"
@@ -196,8 +195,7 @@
 	int this_count = SCpnt->bufflen >> 9;
 	int good_sectors = (result == 0 ? this_count : 0);
 	int block_sectors = 0;
-	int device_nr = DEVICE_NR(SCpnt->request->rq_dev);
-	Scsi_CD *cd = &scsi_CDs[device_nr];
+	Scsi_CD *cd = SCpnt->request->rq_disk->private_data;
 
 #ifdef DEBUG
 	printk("sr.c done: %x %p\n", result, SCpnt->request->bh->b_data);
@@ -247,31 +245,14 @@
 	scsi_io_completion(SCpnt, good_sectors, block_sectors);
 }
 
-
-static request_queue_t *sr_find_queue(kdev_t dev)
-{
-	Scsi_CD *cd;
-
-	if (minor(dev) >= sr_template.dev_max)
-		return NULL;
-	cd = &scsi_CDs[minor(dev)];
-	if (!cd->device)
-		return NULL;
-	return &cd->device->request_queue;
-}
-
 static int sr_init_command(Scsi_Cmnd * SCpnt)
 {
-	int dev, devm, block=0, this_count, s_size;
-	Scsi_CD *cd;
-
-	devm = minor(SCpnt->request->rq_dev);
-	dev = DEVICE_NR(SCpnt->request->rq_dev);
-	cd = &scsi_CDs[dev];
+	int block=0, this_count, s_size, timeout = SR_TIMEOUT;
+	Scsi_CD *cd = SCpnt->request->rq_disk->private_data;
 
-	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
+	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", cd->disk->disk_name, block));
 
-	if (dev >= sr_template.nr_dev || !cd->device || !cd->device->online) {
+	if (!cd->device || !cd->device->online) {
 		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request->nr_sectors));
 		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
 		return 0;
@@ -285,6 +266,30 @@
 		return 0;
 	}
 
+	/*
+	 * these are already setup, just copy cdb basically
+	 */
+	if (SCpnt->request->flags & REQ_BLOCK_PC) {
+		struct request *rq = SCpnt->request;
+
+		if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
+			return 0;
+
+		memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+		if (rq_data_dir(rq) == WRITE)
+			SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+		else if (rq->data_len)
+			SCpnt->sc_data_direction = SCSI_DATA_READ;
+		else
+			SCpnt->sc_data_direction = SCSI_DATA_NONE;
+
+		this_count = rq->data_len;
+		if (rq->timeout)
+			timeout = rq->timeout;
+
+		goto queue;
+	}
+
 	if (!(SCpnt->request->flags & REQ_CMD)) {
 		blk_dump_rq_flags(SCpnt->request, "sr unsup command");
 		return 0;
@@ -336,9 +341,7 @@
 		   (rq_data_dir(SCpnt->request) == WRITE) ? "writing" : "reading",
 				 this_count, SCpnt->request->nr_sectors));
 
-	SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
-			 ((SCpnt->lun << 5) & 0xe0) : 0;
-
+	SCpnt->cmnd[1] = 0;
 	block = (unsigned int)SCpnt->request->sector / (s_size >> 9);
 
 	if (this_count > 0xffff)
@@ -357,11 +360,12 @@
 	 * host adapter, it's safe to assume that we can at least transfer
 	 * this many bytes between each connect / disconnect.
 	 */
+queue:
 	SCpnt->transfersize = cd->device->sector_size;
 	SCpnt->underflow = this_count << 9;
 
 	SCpnt->allowed = MAX_RETRIES;
-	SCpnt->timeout_per_command = SR_TIMEOUT;
+	SCpnt->timeout_per_command = timeout;
 
 	/*
 	 * This is the completion routine we use.  This is matched in terms
@@ -388,13 +392,38 @@
 	return 1;
 }
 
+static int sr_block_open(struct inode *inode, struct file *file)
+{
+	Scsi_CD *cd = inode->i_bdev->bd_disk->private_data;
+	return cdrom_open(&cd->cdi, inode, file);
+}
+
+static int sr_block_release(struct inode *inode, struct file *file)
+{
+	Scsi_CD *cd = inode->i_bdev->bd_disk->private_data;
+	return cdrom_release(&cd->cdi, file);
+}
+
+static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+			  unsigned long arg)
+{
+	Scsi_CD *cd = inode->i_bdev->bd_disk->private_data;
+	return cdrom_ioctl(&cd->cdi, inode, cmd, arg);
+}
+
+static int sr_block_media_changed(struct gendisk *disk)
+{
+	Scsi_CD *cd = disk->private_data;
+	return cdrom_media_changed(&cd->cdi);
+}
+
 struct block_device_operations sr_bdops =
 {
-	owner:			THIS_MODULE,
-	open:			cdrom_open,
-	release:		cdrom_release,
-	ioctl:			cdrom_ioctl,
-	check_media_change:	cdrom_media_changed,
+	.owner		= THIS_MODULE,
+	.open		= sr_block_open,
+	.release	= sr_block_release,
+	.ioctl		= sr_block_ioctl,
+	.media_changed	= sr_block_media_changed,
 };
 
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
@@ -486,9 +515,7 @@
 
 	do {
 		cmd[0] = READ_CAPACITY;
-		cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-			 ((cd->device->lun << 5) & 0xe0) : 0;
-		memset((void *) &cmd[2], 0, 8);
+		memset((void *) &cmd[1], 0, 9);
 		SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;	/* Mark as really busy */
 		SRpnt->sr_cmd_len = 0;
 
@@ -599,8 +626,6 @@
 	}
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = MODE_SENSE;
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     ((cd->device->lun << 5) & 0xe0) : 0;
 	cgc.cmd[2] = 0x2a;
 	cgc.cmd[4] = 128;
 	cgc.buffer = buffer;
@@ -678,13 +703,6 @@
  */
 static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
 {
-	Scsi_CD *cd = cdi->handle;
-	Scsi_Device *device = cd->device;
-	
-	/* set the LUN */
-	if (device->scsi_level <= SCSI_2)
-		cgc->cmd[1] |= device->lun << 5;
-
 	if (cgc->timeout <= 0)
 		cgc->timeout = IOCTL_TIMEOUT;
 
@@ -730,8 +748,6 @@
 {
 	int i;
 
-	blk_dev[MAJOR_NR].queue = sr_find_queue;
-
 	for (i = 0; i < sr_template.nr_dev; ++i) {
 		struct gendisk *disk;
 		Scsi_CD *cd = &scsi_CDs[i];
@@ -770,7 +786,6 @@
 
 		cd->cdi.ops = &sr_dops;
 		cd->cdi.handle = cd;
-		cd->cdi.dev = mk_kdev(MAJOR_NR, i);
 		cd->cdi.mask = 0;
 		cd->cdi.capacity = 1;
 		/*
@@ -783,6 +798,8 @@
 		disk->driverfs_dev = &cd->device->sdev_driverfs_dev;
 		register_cdrom(&cd->cdi);
 		set_capacity(disk, cd->capacity);
+		disk->private_data = cd;
+		disk->queue = &cd->device->request_queue;
 		add_disk(disk);
 	}
 }
@@ -839,7 +856,7 @@
 		kfree(scsi_CDs);
 
 	sr_template.dev_max = 0;
-	remove_driver(&sr_template.scsi_driverfs_driver);
+	driver_unregister(&sr_template.scsi_driverfs_driver);
 }
 
 module_init(init_sr);
diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
--- a/drivers/scsi/sr_ioctl.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/scsi/sr_ioctl.c	Fri Oct 18 21:03:05 2002
@@ -200,8 +200,6 @@
 
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     ((cd->device->lun) << 5) : 0;
 	cgc.quiet = 1;
 	cgc.data_direction = SCSI_DATA_NONE;
 	cgc.timeout = IOCTL_TIMEOUT;
@@ -215,8 +213,6 @@
 
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = GPCMD_START_STOP_UNIT;
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     ((cd->device->lun) << 5) : 0;
 	cgc.cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
 	cgc.data_direction = SCSI_DATA_NONE;
 	cgc.timeout = IOCTL_TIMEOUT;
@@ -293,8 +289,6 @@
 
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     ((cd->device->lun) << 5) : 0;
 	cgc.cmd[2] = 0x40;	/* I do want the subchannel info */
 	cgc.cmd[3] = 0x02;	/* Give me medium catalog number info */
 	cgc.cmd[8] = 24;
@@ -327,8 +321,6 @@
 
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = GPCMD_SET_SPEED;	/* SET CD SPEED */
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     ((cd->device->lun) << 5) : 0;
 	cgc.cmd[2] = (speed >> 8) & 0xff;	/* MSB for speed (in kbytes/sec) */
 	cgc.cmd[3] = speed & 0xff;	/* LSB */
 	cgc.data_direction = SCSI_DATA_NONE;
@@ -361,8 +353,6 @@
 			struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
 
 			cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-			cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-				     ((cd->device->lun) << 5) : 0;
 			cgc.cmd[8] = 12;		/* LSB of length */
 			cgc.buffer = buffer;
 			cgc.buflen = 12;
@@ -382,8 +372,6 @@
 			struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
 
 			cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-			cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-				     ((cd->device->lun) << 5) : 0;
 			cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
 			cgc.cmd[6] = tocentry->cdte_track;
 			cgc.cmd[8] = 12;		/* LSB of length */
@@ -411,8 +399,6 @@
 		struct cdrom_ti* ti = (struct cdrom_ti*)arg;
 
 		cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
-		cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-			     (cd->device->lun << 5) : 0;
 		cgc.cmd[4] = ti->cdti_trk0;
 		cgc.cmd[5] = ti->cdti_ind0;
 		cgc.cmd[7] = ti->cdti_trk1;
@@ -463,9 +449,7 @@
 
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = GPCMD_READ_CD;	/* READ_CD */
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     (cd->device->lun << 5) : 0;
-	cgc.cmd[1] |= ((format & 7) << 2);
+	cgc.cmd[1] = ((format & 7) << 2);
 	cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff;
 	cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff;
 	cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff;
@@ -521,8 +505,6 @@
 
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = GPCMD_READ_10;
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     (cd->device->lun << 5) : 0;
 	cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff;
 	cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff;
 	cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff;
diff -Nru a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
--- a/drivers/scsi/sr_vendor.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/scsi/sr_vendor.c	Fri Oct 18 21:03:04 2002
@@ -124,9 +124,7 @@
 #endif
 	memset(&cgc, 0, sizeof(struct cdrom_generic_command));
 	cgc.cmd[0] = MODE_SELECT;
-	cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-		     (cd->device->lun << 5) : 0;
-	cgc.cmd[1] |= (1 << 4);
+	cgc.cmd[1] = (1 << 4);
 	cgc.cmd[4] = 12;
 	modesel = (struct ccs_modesel_head *) buffer;
 	memset(modesel, 0, sizeof(*modesel));
@@ -180,8 +178,6 @@
 
 	case VENDOR_SCSI3:
 		cgc.cmd[0] = READ_TOC;
-		cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-			     (cd->device->lun << 5) : 0;
 		cgc.cmd[8] = 12;
 		cgc.cmd[9] = 0x40;
 		cgc.buffer = buffer;
@@ -210,9 +206,7 @@
 	case VENDOR_NEC:{
 			unsigned long min, sec, frame;
 			cgc.cmd[0] = 0xde;
-			cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-				     (cd->device->lun << 5) : 0;
-			cgc.cmd[1] |= 0x03;
+			cgc.cmd[1] = 0x03;
 			cgc.cmd[2] = 0xb0;
 			cgc.buffer = buffer;
 			cgc.buflen = 0x16;
@@ -242,9 +236,7 @@
 			/* we request some disc information (is it a XA-CD ?,
 			 * where starts the last session ?) */
 			cgc.cmd[0] = 0xc7;
-			cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-				     (cd->device->lun << 5) : 0;
-			cgc.cmd[1] |= 0x03;
+			cgc.cmd[1] = 0x03;
 			cgc.buffer = buffer;
 			cgc.buflen = 4;
 			cgc.quiet = 1;
@@ -272,8 +264,6 @@
 
 	case VENDOR_WRITER:
 		cgc.cmd[0] = READ_TOC;
-		cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-			     (cd->device->lun << 5) : 0;
 		cgc.cmd[8] = 0x04;
 		cgc.cmd[9] = 0x40;
 		cgc.buffer = buffer;
@@ -291,8 +281,6 @@
 			break;
 		}
 		cgc.cmd[0] = READ_TOC;	/* Read TOC */
-		cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-			     (cd->device->lun << 5) : 0;
 		cgc.cmd[6] = rc & 0x7f;	/* number of last session */
 		cgc.cmd[8] = 0x0c;
 		cgc.cmd[9] = 0x40;
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Fri Oct 18 21:03:05 2002
+++ b/drivers/scsi/st.c	Fri Oct 18 21:03:05 2002
@@ -381,8 +381,6 @@
 		}
 	}
 
-	if (SRpnt->sr_device->scsi_level <= SCSI_2)
-		cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
 	init_completion(&STp->wait);
 	SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
 	if (SRpnt->sr_use_sg) {
@@ -3994,7 +3992,7 @@
 		kfree(scsi_tapes);
 	}
 	st_template.dev_max = 0;
-	remove_driver(&st_template.scsi_driverfs_driver);
+	driver_unregister(&st_template.scsi_driverfs_driver);
 	printk(KERN_INFO "st: Unloaded.\n");
 }
 
diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
--- a/drivers/scsi/sym53c8xx.c	Fri Oct 18 21:03:06 2002
+++ b/drivers/scsi/sym53c8xx.c	Fri Oct 18 21:03:06 2002
@@ -1279,16 +1279,6 @@
 
 #endif	/* SCSI_DATA_UNKNOWN */
 
-/*
-**	Head of list of NCR boards
-**
-**	For kernel version < 1.3.70, host is retrieved by its irq level.
-**	For later kernels, the internal host control block address 
-**	(struct ncb) is used as device id parameter of the irq stuff.
-*/
-
-static struct Scsi_Host	*first_host = NULL;
-
 
 /*
 **	/proc directory entry and proc_info function
@@ -5880,11 +5870,6 @@
 
 	/*
 	**  Done.
-	*/
-        if (!first_host)
-        	first_host = instance;
-
-	/*
 	**	Fill Linux host instance structure
 	**	and return success.
 	*/
@@ -14228,36 +14213,30 @@
 printk("sym53c8xx_proc_info: hostno=%d, func=%d\n", hostno, func);
 #endif
 
-	for (host = first_host; host; host = host->next) {
-		if (host->hostt != first_host->hostt)
-			continue;
-		if (host->host_no == hostno) {
-			host_data = (struct host_data *) host->hostdata;
-			ncb = host_data->ncb;
-			break;
-		}
-	}
+	host = scsi_host_hn_get(hostno);
+	if (!host)
+		return -EINVAL;
 
+	host_data = (struct host_data *) host->hostdata;
+	ncb = host_data->ncb;
+	retv = -EINVAL;
 	if (!ncb)
-		return -EINVAL;
+		goto out;
 
 	if (func) {
 #ifdef	SCSI_NCR_USER_COMMAND_SUPPORT
 		retv = ncr_user_command(ncb, buffer, length);
-#else
-		retv = -EINVAL;
 #endif
-	}
-	else {
+	} else {
 		if (start)
 			*start = buffer;
 #ifdef SCSI_NCR_USER_INFO_SUPPORT
 		retv = ncr_host_info(ncb, buffer, offset, length);
-#else
-		retv = -EINVAL;
 #endif
 	}
 
+out:
+	scsi_host_put(host);
 	return retv;
 }
 
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	Fri Oct 18 21:03:08 2002
@@ -1793,16 +1793,12 @@
 	hcb_p np = 0;
 	int retv;
 
-	for (host = first_host; host; host = host->next) {
-		if (host->hostt != first_host->hostt)
-			continue;
-		if (host->host_no == hostno) {
-			host_data = (struct host_data *) host->hostdata;
-			np = host_data->ncb;
-			break;
-		}
-	}
+	host = scsi_host_hn_get(hostno);
+	if (!host)
+		return -EINVAL;
 
+	host_data = (struct host_data *) host->hostdata;
+	np = host_data->ncb;
 	if (!np)
 		return -EINVAL;
 
@@ -1823,6 +1819,7 @@
 #endif
 	}
 
+	scsi_host_put(host);
 	return retv;
 }
 #endif /* SYM_LINUX_PROC_INFO_SUPPORT */
diff -Nru a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
--- a/drivers/scsi/wd33c93.c	Fri Oct 18 21:03:07 2002
+++ b/drivers/scsi/wd33c93.c	Fri Oct 18 21:03:07 2002
@@ -1871,10 +1871,7 @@
 int x,i;
 static int stop = 0;
 
-   for (instance=scsi_hostlist; instance; instance=instance->next) {
-      if (instance->host_no == hn)
-         break;
-      }
+   instance = scsi_host_hn_get(hn);
    if (!instance) {
       printk("*** Hmm... Can't find host #%d!\n",hn);
       return (-ESRCH);
diff -Nru a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
--- a/drivers/serial/8250_pnp.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/serial/8250_pnp.c	Fri Oct 18 21:03:03 2002
@@ -7,6 +7,8 @@
  *
  *  Copyright (C) 2001 Russell King, All Rights Reserved.
  *
+ *  Ported to the Linux PnP Layer - (C) Adam Belay.
+ *
  * 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.
@@ -16,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/isapnp.h>
+#include <linux/pnp.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/serial.h>
@@ -28,13 +30,15 @@
 
 #include "8250.h"
 
-struct pnpbios_device_id
-{
-	char id[8];
-	unsigned long driver_data;
+#define UNKNOWN_DEV 0x3000
+
+
+static const struct pnp_id pnp_card_table[] = {
+	{	"ANYDEVS",		0	},
+	{	"",			0	}
 };
 
-static const struct pnpbios_device_id pnp_dev_table[] = {
+static const struct pnp_id pnp_dev_table[] = {
 	/* Archtek America Corp. */
 	/* Archtek SmartLink Modem 3334BT Plug & Play */
 	{	"AAC000F",		0	},
@@ -43,6 +47,8 @@
 	{	"ADC0001",		0	},
 	/* SXPro 288 External Data Fax Modem Plug & Play */
 	{	"ADC0002",		0	},
+	/* Actiontec ISA PNP 56K X2 Fax Modem */
+	{	"AEI1240",		0	},
 	/* Rockwell 56K ACF II Fax+Data+Voice Modem */
 	{	"AKY1021",		SPCI_FL_NO_SHIRQ	},
 	/* AZT3005 PnP SOUND DEVICE */
@@ -303,18 +309,22 @@
 	{	"USR9180",		0	},
 	/* U.S. Robotics 56K Voice INT PnP*/
 	{	"USR9190",		0	},
+	/* Unkown PnP modems */
+	{	"PNPCXXX",		UNKNOWN_DEV	},
+	/* More unkown PnP modems */
+	{	"PNPDXXX",		UNKNOWN_DEV	},
 	{	"",			0	}
 };
 
-static void inline avoid_irq_share(struct pci_dev *dev)
+static void inline avoid_irq_share(struct pnp_dev *dev)
 {
 	unsigned int map = 0x1FF8;
-	struct isapnp_irq *irq;
-	struct isapnp_resources *res = dev->sysdata;
+	struct pnp_irq *irq;
+	struct pnp_resources *res = dev->res;
 
 	serial8250_get_irq_map(&map);
 
-	for ( ; res; res = res->alt)
+	for ( ; res; res = res->dep)
 		for (irq = res->irq; irq; irq = irq->next)
 			irq->map = map;
 }
@@ -337,43 +347,30 @@
 	return 0;
 }
 
-static int inline check_compatible_id(struct pci_dev *dev)
-{
-	int i;
-	for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
-		if ((dev->vendor_compatible[i] ==
-		     ISAPNP_VENDOR('P', 'N', 'P')) &&
-		    (swab16(dev->device_compatible[i]) >= 0xc000) &&
-		    (swab16(dev->device_compatible[i]) <= 0xdfff))
-			return 0;
-	return 1;
-}
-
 /*
- * Given a complete unknown ISA PnP device, try to use some heuristics to
+ * Given a complete unknown PnP device, try to use some heuristics to
  * detect modems. Currently use such heuristic set:
  *     - dev->name or dev->bus->name must contain "modem" substring;
  *     - device must have only one IO region (8 byte long) with base adress
  *       0x2e8, 0x3e8, 0x2f8 or 0x3f8.
  *
  * Such detection looks very ugly, but can detect at least some of numerous
- * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[]
+ * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
  * table.
  */
-static int serial_pnp_guess_board(struct pci_dev *dev, int *flags)
+static int serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
 {
-	struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
-	struct isapnp_resources *resa;
+	struct pnp_resources *res = dev->res;
+	struct pnp_resources *resa;
 
-	if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
-	    !(check_compatible_id(dev)))
+	if (!(check_name(dev->name) || check_name(dev->card->name)))
 		return -ENODEV;
 
-	if (!res || res->next)
+	if (!res)
 		return -ENODEV;
 
-	for (resa = res->alt; resa; resa = resa->alt) {
-		struct isapnp_port *port;
+	for (resa = res->dep; resa; resa = resa->dep) {
+		struct pnp_port *port;
 		for (port = res->port; port; port = port->next)
 			if ((port->size == 8) &&
 			    ((port->min == 0x2f8) ||
@@ -387,42 +384,19 @@
 }
 
 static int
-pnp_init_one(struct pci_dev *dev, const struct pnpbios_device_id *ent,
-	     char *slot_name)
+serial_pnp_probe(struct pnp_dev * dev, const struct pnp_id *card_id, const struct pnp_id *dev_id)
 {
 	struct serial_struct serial_req;
-	int ret, line, flags = ent ? ent->driver_data : 0;
-
-	if (!ent) {
+	int ret, line, flags = dev_id->driver_data;
+	if (flags & UNKNOWN_DEV)
 		ret = serial_pnp_guess_board(dev, &flags);
-		if (ret)
-			return ret;
-	}
-
-	if (dev->prepare(dev) < 0) {
-		printk("serial: PNP device '%s' prepare failed\n",
-			slot_name);
-		return -ENODEV;
-	}
-
-	if (dev->active)
-		return -ENODEV;
-
 	if (flags & SPCI_FL_NO_SHIRQ)
 		avoid_irq_share(dev);
-
-	if (dev->activate(dev) < 0) {
-		printk("serial: PNP device '%s' activate failed\n",
-			slot_name);
-		return -ENODEV;
-	}
-
 	memset(&serial_req, 0, sizeof(serial_req));
 	serial_req.irq = dev->irq_resource[0].start;
 	serial_req.port = pci_resource_start(dev, 0);
 	if (HIGH_BITS_OFFSET)
-		serial_req.port = pci_resource_start(dev, 0) >> HIGH_BITS_OFFSET;
-
+		serial_req.port = dev->resource[0].start >> HIGH_BITS_OFFSET;
 #ifdef SERIAL_DEBUG_PNP
 	printk("Setup PNP port: port %x, irq %d, type %d\n",
 	       serial_req.port, serial_req.irq, serial_req.io_type);
@@ -432,110 +406,33 @@
 	serial_req.baud_base = 115200;
 	line = register_serial(&serial_req);
 
-	if (line >= 0) {
-		pci_set_drvdata(dev, (void *)(line + 1));
-
-		/*
-		 * Public health warning: remove this once the 2.5
-		 * pnpbios_module_init() stuff is incorporated.
-		 */
-		dev->driver = (void *)pnp_dev_table;
-	} else
-		dev->deactivate(dev);
-
+	if (line >= 0)
+		dev->driver_data = (void *)(line + 1);
 	return line >= 0 ? 0 : -ENODEV;
-}
-
-static void pnp_remove_one(struct pci_dev *dev)
-{
-	int line = (int)pci_get_drvdata(dev);
-
-	if (line) {
-		pci_set_drvdata(dev, NULL);
 
-		unregister_serial(line - 1);
-
-		dev->deactivate(dev);
-	}
 }
 
-static char hex[] = "0123456789ABCDEF";
-
-/*
- * This function should vanish when 2.5 comes around and
- * we have pnpbios_module_init()
- */
-static int pnp_init(void)
+static void serial_pnp_remove(struct pnp_dev * dev)
 {
-	const struct pnpbios_device_id *id;
-	struct pci_dev *dev = NULL;
-	int nr = 0, rc = -ENODEV;
-
-#ifdef SERIAL_DEBUG_PNP
-	printk("Entered probe_serial_pnp()\n");
-#endif
-
-	isapnp_for_each_dev(dev) {
-		char slot_name[8];
-		u32 pnpid;
-
-		if (dev->active)
-			continue;
-
-		pnpid = dev->vendor << 16 | dev->device;
-		pnpid = cpu_to_le32(pnpid);
-
-#define HEX(id,a) hex[((id)>>a) & 15]
-#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
-		slot_name[0] = CHAR(pnpid, 26);
-		slot_name[1] = CHAR(pnpid, 21);
-		slot_name[2] = CHAR(pnpid, 16);
-		slot_name[3] = HEX(pnpid, 12);
-		slot_name[4] = HEX(pnpid, 8);
-		slot_name[5] = HEX(pnpid, 4);
-		slot_name[6] = HEX(pnpid, 0);
-		slot_name[7] = '\0';
-		
-		for (id = pnp_dev_table; id->id[0]; id++)
-			if (memcmp(id->id, slot_name, 7) == 0)
-				break;
-
-		if (id->id[0])
-			rc = pnp_init_one(dev, id, slot_name);
-		else
-			rc = pnp_init_one(dev, NULL, slot_name);
-
-		if (rc == 0)
-			nr++;
-	}
-
-#ifdef SERIAL_DEBUG_PNP
-	printk("Leaving probe_serial_pnp() (probe finished)\n");
-#endif
-
-	return nr == 0 ? rc : 0;
+	return;
 }
 
+static struct pnp_driver serial_pnp_driver = {
+	.name		= "serial",
+	.card_id_table	= pnp_card_table,
+	.id_table	= pnp_dev_table,
+	.probe		= serial_pnp_probe,
+	.remove		= serial_pnp_remove,
+};
+
 static int __init serial8250_pnp_init(void)
 {
-	if (!isapnp_present()) {
-#ifdef SERIAL_DEBUG_PNP
-		printk("Leaving probe_serial_pnp() (no isapnp)\n");
-#endif
-		return -ENODEV;
-	}
-	return pnp_init();
+	return pnp_register_driver(&serial_pnp_driver);
 }
 
 static void __exit serial8250_pnp_exit(void)
 {
-	struct pci_dev *dev = NULL;
-
-	isapnp_for_each_dev(dev) {
-		if (dev->driver != (void *)pnp_dev_table)
-			continue;
-		pnp_remove_one(dev);
-	}
+	/* FIXME */
 }
 
 module_init(serial8250_pnp_init);
@@ -544,5 +441,6 @@
 EXPORT_NO_SYMBOLS;
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
-MODULE_DEVICE_TABLE(pnpbios, pnp_dev_table);
+MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver");
+/* FIXME */
+/*MODULE_DEVICE_TABLE(pnpbios, pnp_dev_table);*/
diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile
--- a/drivers/serial/Makefile	Fri Oct 18 21:03:04 2002
+++ b/drivers/serial/Makefile	Fri Oct 18 21:03:04 2002
@@ -8,7 +8,7 @@
 
 serial-8250-y :=
 serial-8250-$(CONFIG_PCI) += 8250_pci.o
-serial-8250-$(CONFIG_ISAPNP) += 8250_pnp.o
+serial-8250-$(CONFIG_PNP) += 8250_pnp.o
 obj-$(CONFIG_SERIAL_CORE) += core.o
 obj-$(CONFIG_SERIAL_21285) += 21285.o
 obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/usb/class/audio.c	Fri Oct 18 21:03:08 2002
@@ -395,7 +395,7 @@
 
 /* prevent picking up a bogus abs macro */
 #undef abs
-extern inline int abs(int x)
+static inline int abs(int x)
 {
         if (x < 0)
 		return -x;
@@ -404,7 +404,7 @@
                                 
 /* --------------------------------------------------------------------- */
 
-extern inline unsigned ld2(unsigned int x)
+static inline unsigned ld2(unsigned int x)
 {
 	unsigned r = 0;
 	
@@ -1939,13 +1939,13 @@
 	kfree(s);
 }
 
-extern inline int prog_dmabuf_in(struct usb_audiodev *as)
+static inline int prog_dmabuf_in(struct usb_audiodev *as)
 {
 	usbin_stop(as);
 	return dmabuf_init(&as->usbin.dma);
 }
 
-extern inline int prog_dmabuf_out(struct usb_audiodev *as)
+static inline int prog_dmabuf_out(struct usb_audiodev *as)
 {
 	usbout_stop(as);
 	return dmabuf_init(&as->usbout.dma);
@@ -3253,7 +3253,7 @@
 
 static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid);
 
-extern inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
+static inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
 {
 	unsigned int idx;
 
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/usb/core/devio.c	Fri Oct 18 21:03:04 2002
@@ -1077,7 +1077,7 @@
 			     driver->name, ps->dev->devnum, ctrl.ifno);
 			usb_device_remove(&ifp->dev);
 		} else
-			retval = -EINVAL;
+			retval = -ENODATA;
 		break;
 
 	/* let kernel drivers try to (re)bind to the interface */
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/usb/core/message.c	Fri Oct 18 21:03:03 2002
@@ -847,7 +847,7 @@
 		ep &= USB_ENDPOINT_NUMBER_MASK;
 		usb_settoggle (dev, ep, out, 0);
 		(out ? dev->epmaxpacketout : dev->epmaxpacketin) [ep]
-			= iface_as->endpoint [ep].wMaxPacketSize;
+			= iface_as->endpoint [i].wMaxPacketSize;
 	}
 
 	return 0;
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/usb/core/usb.c	Fri Oct 18 21:03:04 2002
@@ -208,7 +208,7 @@
 {
 	info("deregistering driver %s", driver->name);
 
-	remove_driver (&driver->driver);
+	driver_unregister (&driver->driver);
 
 	usbfs_update_special();
 }
@@ -790,6 +790,7 @@
 			usb_disconnect(child);
 	}
 
+	dbg ("unregistering interfaces on device %d", dev->devnum);
 	if (dev->actconfig) {
 		for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
 			struct usb_interface *interface = &dev->actconfig->interface[i];
@@ -799,12 +800,13 @@
 		}
 	}
 
+	dbg ("unregistering the device %d", dev->devnum);
 	/* Free the device number and remove the /proc/bus/usb entry */
 	if (dev->devnum > 0) {
 		clear_bit(dev->devnum, dev->bus->devmap.devicemap);
 		usbfs_remove_device(dev);
-		device_unregister(&dev->dev);
 	}
+	device_unregister(&dev->dev);
 
 	/* Decrement the reference count, it'll auto free everything when */
 	/* it hits 0 which could very well be now */
@@ -1394,7 +1396,7 @@
 	if (nousb)
 		return;
 
-	remove_driver(&usb_generic_driver);
+	driver_unregister(&usb_generic_driver);
 	usb_major_cleanup();
 	usbfs_cleanup();
 	usb_hub_cleanup();
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/usb/host/ohci-sa1111.c	Fri Oct 18 21:03:04 2002
@@ -413,7 +413,7 @@
 
 static void __exit ohci_hcd_sa1111_cleanup (void)
 {
-	remove_driver(&ohci_hcd_sa1111_driver.drv);
+	driver_unregister(&ohci_hcd_sa1111_driver.drv);
 }
 
 module_init (ohci_hcd_sa1111_init);
diff -Nru a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
--- a/drivers/usb/host/uhci-debug.c	Fri Oct 18 21:03:03 2002
+++ b/drivers/usb/host/uhci-debug.c	Fri Oct 18 21:03:03 2002
@@ -34,17 +34,6 @@
 	}
 }
 
-static int inline uhci_is_skeleton_td(struct uhci_hcd *uhci, struct uhci_td *td)
-{
-	int i;
-
-	for (i = 0; i < UHCI_NUM_SKELTD; i++)
-		if (td == uhci->skeltd[i])
-			return 1;
-
-	return 0;
-}
-
 static int inline uhci_is_skeleton_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	int i;
@@ -285,13 +274,14 @@
 	return out - buf;
 }
 
-static const char *td_names[] = {"skel_int1_td", "skel_int2_td",
-				 "skel_int4_td", "skel_int8_td",
-				 "skel_int16_td", "skel_int32_td",
-				 "skel_int64_td", "skel_int128_td",
-				 "skel_int256_td", "skel_term_td" };
-static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh",
-				  "skel_bulk_qh", "skel_term_qh" };
+static const char *qh_names[] = {
+  "skel_int128_qh", "skel_int64_qh",
+  "skel_int32_qh", "skel_int16_qh",
+  "skel_int8_qh", "skel_int4_qh",
+  "skel_int2_qh", "skel_int1_qh",
+  "skel_ls_control_qh", "skel_hs_control_qh",
+  "skel_bulk_qh", "skel_term_qh"
+};
 
 #define show_frame_num()	\
 	if (!shown) {		\
@@ -299,26 +289,141 @@
 	  out += sprintf(out, "- Frame %d\n", i); \
 	}
 
-#define show_td_name()		\
-	if (!shown) {		\
-	  shown = 1;		\
-	  out += sprintf(out, "- %s\n", td_names[i]); \
-	}
-
 #define show_qh_name()		\
 	if (!shown) {		\
 	  shown = 1;		\
 	  out += sprintf(out, "- %s\n", qh_names[i]); \
 	}
 
+static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len)
+{
+	struct list_head *tmp;
+	char *out = buf;
+	int count = 0;
+
+	if (len < 200)
+		return 0;
+
+	out += sprintf(out, "urb_priv [%p] ", urbp);
+	out += sprintf(out, "urb [%p] ", urbp->urb);
+	out += sprintf(out, "qh [%p] ", urbp->qh);
+	out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
+	out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
+
+	switch (usb_pipetype(urbp->urb->pipe)) {
+	case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break;
+	case PIPE_INTERRUPT: out += sprintf(out, "INT "); break;
+	case PIPE_BULK: out += sprintf(out, "BLK "); break;
+	case PIPE_CONTROL: out += sprintf(out, "CTL "); break;
+	}
+
+	out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));
+	out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : ""));
+
+	if (urbp->status != -EINPROGRESS)
+		out += sprintf(out, "Status=%d ", urbp->status);
+	//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
+	//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
+
+	spin_lock(&urbp->urb->lock);
+	count = 0;
+	list_for_each(tmp, &urbp->td_list)
+		count++;
+	spin_unlock(&urbp->urb->lock);
+	out += sprintf(out, "TDs=%d ",count);
+
+	if (urbp->queued)
+		out += sprintf(out, "queued\n");
+	else {
+		spin_lock(&uhci->frame_list_lock);
+		count = 0;
+		list_for_each(tmp, &urbp->queue_list)
+			count++;
+		spin_unlock(&uhci->frame_list_lock);
+		out += sprintf(out, "queued URBs=%d\n", count);
+	}
+
+	return out - buf;
+}
+
+static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len)
+{
+	char *out = buf;
+	unsigned long flags;
+	struct list_head *head, *tmp;
+	int count;
+
+	out += sprintf(out, "Main list URBs:");
+	spin_lock_irqsave(&uhci->urb_list_lock, flags);
+	if (list_empty(&uhci->urb_list))
+		out += sprintf(out, " Empty\n");
+	else {
+		out += sprintf(out, "\n");
+		count = 0;
+		head = &uhci->urb_list;
+		tmp = head->next;
+		while (tmp != head) {
+			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+
+			out += sprintf(out, "  %d: ", ++count);
+			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+			tmp = tmp->next;
+		}
+	}
+	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
+	out += sprintf(out, "Remove list URBs:");
+	spin_lock_irqsave(&uhci->urb_remove_list_lock, flags);
+	if (list_empty(&uhci->urb_remove_list))
+		out += sprintf(out, " Empty\n");
+	else {
+		out += sprintf(out, "\n");
+		count = 0;
+		head = &uhci->urb_remove_list;
+		tmp = head->next;
+		while (tmp != head) {
+			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+
+			out += sprintf(out, "  %d: ", ++count);
+			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+			tmp = tmp->next;
+		}
+	}
+	spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
+
+	out += sprintf(out, "Complete list URBs:");
+	spin_lock_irqsave(&uhci->complete_list_lock, flags);
+	if (list_empty(&uhci->complete_list))
+		out += sprintf(out, " Empty\n");
+	else {
+		out += sprintf(out, "\n");
+		count = 0;
+		head = &uhci->complete_list;
+		tmp = head->next;
+		while (tmp != head) {
+			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
+
+			out += sprintf(out, "  %d: ", ++count);
+			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+			tmp = tmp->next;
+		}
+	}
+	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+
+	return out - buf;
+}
+
 static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 {
+	unsigned long flags;
 	char *out = buf;
 	int i;
 	struct uhci_qh *qh;
 	struct uhci_td *td;
 	struct list_head *tmp, *head;
 
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
 	out += sprintf(out, "HC status\n");
 	out += uhci_show_status(uhci, out, len - (out - buf));
 
@@ -333,8 +438,6 @@
 			show_frame_num();
 			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
 		}
-		if (uhci_is_skeleton_td(uhci, td))
-			continue;
 		show_frame_num();
 
 		head = &td->fl_list;
@@ -346,67 +449,6 @@
 		} while (tmp != head);
 	}
 
-	out += sprintf(out, "Skeleton TD's\n");
-	for (i = UHCI_NUM_SKELTD - 1; i >= 0; i--) {
-		int shown = 0;
-
-		td = uhci->skeltd[i];
-
-		if (debug > 1) {
-			show_td_name();
-			out += uhci_show_td(td, out, len - (out - buf), 4);
-		}
-
-		if (list_empty(&td->fl_list)) {
-			/* TD 0 is the int1 TD and links to control_ls_qh */
-			if (!i) {
-				if (td->link !=
-				    (cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH)) {
-					show_td_name();
-					out += sprintf(out, "    skeleton TD not linked to ls_control QH!\n");
-				}
-			} else if (i < 9) {
-				if (td->link != cpu_to_le32(uhci->skeltd[i - 1]->dma_handle)) {
-					show_td_name();
-					out += sprintf(out, "    skeleton TD not linked to next skeleton TD!\n");
-				}
-			} else {
-				show_td_name();
-
-				if (td->link != cpu_to_le32(td->dma_handle))
-					out += sprintf(out, "    skel_term_td does not link to self\n");
-
-				/* Don't show it twice */
-				if (debug <= 1)
-					out += uhci_show_td(td, out, len - (out - buf), 4);
-			}
-
-			continue;
-		}
-
-		show_td_name();
-
-		head = &td->fl_list;
-		tmp = head->next;
-
-		while (tmp != head) {
-			td = list_entry(tmp, struct uhci_td, fl_list);
-
-			tmp = tmp->next;
-
-			out += uhci_show_td(td, out, len - (out - buf), 4);
-		}
-
-		if (!i) {
-			if (td->link !=
-			    (cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH))
-				out += sprintf(out, "    last TD not linked to ls_control QH!\n");
-		} else if (i < 9) {
-			if (td->link != cpu_to_le32(uhci->skeltd[i - 1]->dma_handle))
-				out += sprintf(out, "    last TD not linked to next skeleton!\n");
-		}
-	}
-
 	out += sprintf(out, "Skeleton QH's\n");
 
 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
@@ -419,21 +461,19 @@
 			out += uhci_show_qh(qh, out, len - (out - buf), 4);
 		}
 
-		/* QH 3 is the Terminating QH, it's different */
-		if (i == 3) {
-			if (qh->link != UHCI_PTR_TERM) {
-				show_qh_name();
+		/* Last QH is the Terminating QH, it's different */
+		if (i == UHCI_NUM_SKELQH - 1) {
+			if (qh->link != UHCI_PTR_TERM)
 				out += sprintf(out, "    bandwidth reclamation on!\n");
-			}
 
-			if (qh->element != cpu_to_le32(uhci->skel_term_td->dma_handle)) {
-				show_qh_name();
-				out += sprintf(out, "    skel_term_qh element is not set to skel_term_td\n");
-			}
+			if (qh->element != cpu_to_le32(uhci->term_td->dma_handle))
+				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
+
+			continue;
 		}
 
 		if (list_empty(&qh->list)) {
-			if (i < 3) {
+			if (i < UHCI_NUM_SKELQH - 1) {
 				if (qh->link !=
 				    (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH)) {
 					show_qh_name();
@@ -457,18 +497,23 @@
 			out += uhci_show_qh(qh, out, len - (out - buf), 4);
 		}
 
-		if (i < 3) {
+		if (i < UHCI_NUM_SKELQH - 1) {
 			if (qh->link !=
 			    (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH))
 				out += sprintf(out, "    last QH not linked to next skeleton!\n");
 		}
 	}
 
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+
+	if (debug > 2)
+		out += uhci_show_lists(uhci, out, len - (out - buf));
+
 	return out - buf;
 }
 
 #ifdef CONFIG_PROC_FS
-#define MAX_OUTPUT	(PAGE_SIZE * 8)
+#define MAX_OUTPUT	(PAGE_SIZE * 16)
 
 static struct proc_dir_entry *uhci_proc_root = NULL;
 
@@ -483,7 +528,6 @@
 	const struct proc_dir_entry *dp = PDE(inode);
 	struct uhci_hcd *uhci = dp->data;
 	struct uhci_proc *up;
-	unsigned long flags;
 	int ret = -ENOMEM;
 
 	lock_kernel();
@@ -497,9 +541,7 @@
 		goto out;
 	}
 
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 	up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 
 	file->private_data = up;
 
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/usb/host/uhci-hcd.c	Fri Oct 18 21:03:08 2002
@@ -69,7 +69,7 @@
  * debug = 0, no debugging messages
  * debug = 1, dump failed URB's except for stalls
  * debug = 2, dump all failed URB's (including stalls)
- *            show all queues in /proc/uhci/hc*
+ *            show all queues in /proc/driver/uhci/[pci_addr]
  * debug = 3, show all TD's in URB's when dumping
  */
 #ifdef DEBUG
@@ -118,7 +118,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	uhci->skel_term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
+	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
 	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 }
 
@@ -127,7 +127,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	uhci->skel_term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
+	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
 	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 }
 
@@ -174,30 +174,8 @@
 	td->buffer = cpu_to_le32(buffer);
 }
 
-static void uhci_insert_td(struct uhci_hcd *uhci, struct uhci_td *skeltd, struct uhci_td *td)
-{
-	unsigned long flags;
-	struct uhci_td *ltd;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
-	ltd = list_entry(skeltd->fl_list.prev, struct uhci_td, fl_list);
-
-	td->link = ltd->link;
-	mb();
-	ltd->link = cpu_to_le32(td->dma_handle);
-
-	list_add_tail(&td->fl_list, &skeltd->fl_list);
-
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
 /*
- * We insert Isochronous transfers directly into the frame list at the
- * beginning
- * The layout looks as follows:
- * frame list pointer -> iso td's (if any) ->
- * periodic interrupt td (if frame 0) -> irq td's -> control qh -> bulk qh
+ * We insert Isochronous URB's directly into the frame list at the beginning
  */
 static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
 {
@@ -374,8 +352,9 @@
 	/* Grab the last QH */
 	lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
 
-	/* Patch this endpoint's URBs' QHs to point to the next skelQH:
-	 *    SkelQH --> ... lqh --> NewQH --> NextSkelQH
+	/*
+	 * Patch this endpoint's URB's QHs to point to the next skelqh:
+	 *    skelqh --> ... lqh --> newqh --> next skelqh
 	 * Do this first, so the HC always sees the right QH after this one.
 	 */
 	list_for_each (tmp, &urbp->queue_list) {
@@ -387,15 +366,16 @@
 	urbp->qh->link = lqh->link;
 	wmb();				/* Ordering is important */
 
-	/* Patch QHs for previous endpoint's queued URBs?  HC goes
-	 * here next, not to the NextSkelQH it now points to.
+	/*
+	 * Patch QHs for previous endpoint's queued URBs?  HC goes
+	 * here next, not to the next skelqh it now points to.
 	 *
 	 *    lqh --> td ... --> qh ... --> td --> qh ... --> td
 	 *     |                 |                 |
 	 *     v                 v                 v
 	 *     +<----------------+-----------------+
 	 *     v
-	 *    NewQH --> td ... --> td
+	 *    newqh --> td ... --> td
 	 *     |
 	 *     v
 	 *    ...
@@ -424,7 +404,8 @@
 	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 }
 
-/* start removal of qh from schedule; it finishes next frame.
+/*
+ * Start removal of QH from schedule; it finishes next frame.
  * TDs should be unlinked before this is called.
  */
 static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
@@ -437,7 +418,12 @@
 
 	qh->urbp = NULL;
 
-	/* Only go through the hoops if it's actually linked in */
+	/*
+	 * Only go through the hoops if it's actually linked in
+	 * Queued QHs are removed in uhci_delete_queued_urb,
+	 * since (for queued URBs) the pqh is pointed to the next
+	 * QH in the queue, not the next endpoint's QH.
+	 */
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 	if (!list_empty(&qh->list)) {
 		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
@@ -459,7 +445,9 @@
 
 		pqh->link = qh->link;
 		mb();
-		qh->element = qh->link = UHCI_PTR_TERM;
+		/* Leave qh->link in case the HC is on the QH now, it will */
+		/* continue the rest of the schedule */
+		qh->element = UHCI_PTR_TERM;
 
 		list_del_init(&qh->list);
 	}
@@ -502,8 +490,7 @@
 }
 
 /* This function will append one URB's QH to another URB's QH. This is for */
-/* queuing bulk transfers and soon implicitily for */
-/*  control transfers */
+/* queuing interrupt, control or bulk transfers */
 static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb)
 {
 	struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
@@ -545,7 +532,7 @@
 	urbp->qh->link = eurbp->qh->link;
 
 	mb();			/* Make sure we flush everything */
-	/* Only support bulk right now, so no depth */
+
 	lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
 
 	list_add_tail(&urbp->queue_list, &furbp->queue_list);
@@ -575,7 +562,7 @@
 
 	/* Fix up the toggle for the next URB's */
 	if (!urbp->queued)
-		/* We set the toggle when we unlink */
+		/* We just set the toggle in uhci_unlink_generic */
 		toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
 	else {
 		/* If we're in the middle of the queue, grab the toggle */
@@ -607,9 +594,35 @@
 		usb_pipeout(urb->pipe), toggle);
 
 	if (!urbp->queued) {
+		struct uhci_qh *pqh;
+
 		nurbp->queued = 0;
 
-		_uhci_insert_qh(uhci, uhci->skel_bulk_qh, nurbp->urb);
+		/*
+		 * Fixup the previous QH's queue to link to the new head
+		 * of this queue.
+		 */
+		pqh = list_entry(urbp->qh->list.prev, struct uhci_qh, list);
+
+		if (pqh->urbp) {
+			struct list_head *head, *tmp;
+
+			head = &pqh->urbp->queue_list;
+			tmp = head->next;
+			while (head != tmp) {
+				struct urb_priv *turbp =
+					list_entry(tmp, struct urb_priv, queue_list);
+
+				tmp = tmp->next;
+
+				turbp->qh->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+			}
+		}
+
+		pqh->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+
+		list_add_tail(&nurbp->qh->list, &urbp->qh->list);
+		list_del_init(&urbp->qh->list);
 	} else {
 		/* We're somewhere in the middle (or end). A bit trickier */
 		/*  than the head scenario */
@@ -786,11 +799,11 @@
 /*
  * Control transfers
  */
-static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb)
+static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
 {
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	struct uhci_td *td;
-	struct uhci_qh *qh;
+	struct uhci_qh *qh, *skelqh;
 	unsigned long destination, status;
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
@@ -880,19 +893,32 @@
 	urbp->qh = qh;
 	qh->urbp = urbp;
 
+	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+
 	/* Low speed transfers get a different queue, and won't hog the bus */
-	if (urb->dev->speed == USB_SPEED_LOW) {
-		uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_DEPTH);
-		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
-	} else {
-		uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
-		uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		skelqh = uhci->skel_ls_control_qh;
+	else {
+		skelqh = uhci->skel_hs_control_qh;
 		uhci_inc_fsbr(uhci, urb);
 	}
 
+	if (eurb)
+		uhci_append_queued_urb(uhci, eurb, urb);
+	else
+		uhci_insert_qh(uhci, skelqh, urb);
+
 	return -EINPROGRESS;
 }
 
+/*
+ * If control was short, then end status packet wasn't sent, so this
+ * reorganize s so it's sent to finish the transfer.  The original QH is
+ * removed from the skel and discarded; all TDs except the last (status)
+ * are deleted; the last (status) TD is put on a new QH which is reinserted
+ * into the skel.  Since the last TD and urb_priv are reused, the TD->link
+ * and urb_priv maintain any queued QHs.
+ */
 static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
 {
 	struct list_head *tmp, *head;
@@ -1047,46 +1073,109 @@
 }
 
 /*
- * Interrupt transfers
+ * Common submit for bulk and interrupt
  */
-static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb)
+static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh)
 {
 	struct uhci_td *td;
+	struct uhci_qh *qh;
 	unsigned long destination, status;
+	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	int len = urb->transfer_buffer_length;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	dma_addr_t data = urb->transfer_dma;
 
-	if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
+	if (len < 0)
 		return -EINVAL;
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
 
-	status = TD_CTRL_ACTIVE | TD_CTRL_IOC;
+	status = uhci_maxerr(3) | TD_CTRL_ACTIVE;
 	if (urb->dev->speed == USB_SPEED_LOW)
 		status |= TD_CTRL_LS;
+	if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+		status |= TD_CTRL_SPD;
 
-	td = uhci_alloc_td(uhci, urb->dev);
-	if (!td)
-		return -ENOMEM;
+	/*
+	 * Build the DATA TD's
+	 */
+	do {	/* Allow zero length packets */
+		int pktsze = len;
 
-	destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT);
-	destination |= uhci_explen(urb->transfer_buffer_length - 1);
+		if (pktsze > maxsze)
+			pktsze = maxsze;
 
-	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
 
-	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status, destination, urb->transfer_dma);
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
+			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+			data);
+
+		data += pktsze;
+		len -= maxsze;
+
+		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			usb_pipeout(urb->pipe));
+	} while (len > 0);
+
+	/*
+	 * USB_ZERO_PACKET means adding a 0-length packet, if direction
+	 * is OUT and the transfer_length was an exact multiple of maxsze,
+	 * hence (len = transfer_length - N * maxsze) == 0
+	 * however, if transfer_length == 0, the zero packet was already
+	 * prepared above.
+	 */
+	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) &&
+	    !len && urb->transfer_buffer_length) {
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
+			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+			data);
+
+		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			usb_pipeout(urb->pipe));
+	}
+
+	/* Set the flag on the last packet */
+	td->status |= cpu_to_le32(TD_CTRL_IOC);
 
-	uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td);
+	qh = uhci_alloc_qh(uhci, urb->dev);
+	if (!qh)
+		return -ENOMEM;
+
+	urbp->qh = qh;
+	qh->urbp = urbp;
+
+	/* Always breadth first */
+	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+
+	if (eurb)
+		uhci_append_queued_urb(uhci, eurb, urb);
+	else
+		uhci_insert_qh(uhci, skelqh, urb);
 
 	return -EINPROGRESS;
 }
 
-static int uhci_result_interrupt(struct uhci_hcd *uhci, struct urb *urb)
+/*
+ * Common result for bulk and interrupt
+ */
+static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 {
 	struct list_head *tmp, *head;
 	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
-	unsigned int status;
+	unsigned int status = 0;
 	int ret = 0;
 
 	urb->actual_length = 0;
@@ -1128,15 +1217,11 @@
 err:
 	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
 		/* Some debugging code */
-		dbg("uhci_result_interrupt/bulk() failed with status %x",
-			status);
+		dbg("uhci_result_common() failed with status %x", status);
 
 		if (errbuf) {
 			/* Print the chain for debugging purposes */
-			if (urbp->qh)
-				uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-			else
-				uhci_show_td(td, errbuf, ERRBUF_LEN, 0);
+			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
 
 			lprintk(errbuf);
 		}
@@ -1145,129 +1230,35 @@
 	return ret;
 }
 
-static void uhci_reset_interrupt(struct uhci_hcd *uhci, struct urb *urb)
+static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-	unsigned long flags;
-
-	spin_lock_irqsave(&urb->lock, flags);
-
-	td = list_entry(urbp->td_list.next, struct uhci_td, list);
-
-	td->status = (td->status & cpu_to_le32(0x2F000000)) | cpu_to_le32(TD_CTRL_ACTIVE | TD_CTRL_IOC);
-	td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE);
-	td->token |= cpu_to_le32(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT);
-	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
-
-	urb->status = -EINPROGRESS;
-
-	spin_unlock_irqrestore(&urb->lock, flags);
-}
-
-/*
- * Bulk transfers
- */
-static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
-{
-	struct uhci_td *td;
-	struct uhci_qh *qh;
-	unsigned long destination, status;
-	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	int len = urb->transfer_buffer_length;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	dma_addr_t data = urb->transfer_dma;
-
-	if (len < 0)
-		return -EINVAL;
+	int ret;
 
 	/* Can't have low speed bulk transfers */
 	if (urb->dev->speed == USB_SPEED_LOW)
 		return -EINVAL;
 
-	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
-	/* 3 errors */
-	status = TD_CTRL_ACTIVE | uhci_maxerr(3);
-	if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
-		status |= TD_CTRL_SPD;
-
-	/*
-	 * Build the DATA TD's
-	 */
-	do {	/* Allow zero length packets */
-		int pktsze = len;
-
-		if (pktsze > maxsze)
-			pktsze = maxsze;
-
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
-			data);
-
-		data += pktsze;
-		len -= maxsze;
-
-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			usb_pipeout(urb->pipe));
-	} while (len > 0);
-
-	/*
-	 * USB_ZERO_PACKET means adding a 0-length packet, if
-	 * direction is OUT and the transfer_length was an
-	 * exact multiple of maxsze, hence
-	 * (len = transfer_length - N * maxsze) == 0
-	 * however, if transfer_length == 0, the zero packet
-	 * was already prepared above.
-	 */
-	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) &&
-	   !len && urb->transfer_buffer_length) {
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
-			data);
-
-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			usb_pipeout(urb->pipe));
-	}
-
-	/* Set the flag on the last packet */
-	td->status |= cpu_to_le32(TD_CTRL_IOC);
-
-	qh = uhci_alloc_qh(uhci, urb->dev);
-	if (!qh)
-		return -ENOMEM;
-
-	urbp->qh = qh;
-	qh->urbp = urbp;
-
-	/* Always breadth first */
-	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+	ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh);
+	if (ret == -EINPROGRESS)
+		uhci_inc_fsbr(uhci, urb);
 
-	if (eurb)
-		uhci_append_queued_urb(uhci, eurb, urb);
-	else
-		uhci_insert_qh(uhci, uhci->skel_bulk_qh, urb);
+	return ret;
+}
 
-	uhci_inc_fsbr(uhci, urb);
+static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
+{
+	/* Interrupt-IN can't be more than 1 packet */
+	if (usb_pipein(urb->pipe) && urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
+		return -EINVAL;
 
-	return -EINPROGRESS;
+	return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]);
 }
 
-/* We can use the result interrupt since they're identical */
-#define uhci_result_bulk uhci_result_interrupt
+/*
+ * Bulk and interrupt use common result
+ */
+#define uhci_result_bulk uhci_result_common
+#define uhci_result_interrupt uhci_result_common
 
 /*
  * Isochronous transfers
@@ -1457,51 +1448,52 @@
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
-		if (eurb)
-			ret = -ENXIO;		/* no control queueing yet */
-		else
-			ret = uhci_submit_control(uhci, urb);
+		ret = uhci_submit_control(uhci, urb, eurb);
 		break;
 	case PIPE_INTERRUPT:
-		if (eurb)
-			ret = -ENXIO;		/* no interrupt queueing yet */
-		else if (urb->bandwidth == 0) {	/* not yet checked/allocated */
+		if (!eurb) {
 			bustime = usb_check_bandwidth(urb->dev, urb);
 			if (bustime < 0)
 				ret = bustime;
 			else {
-				ret = uhci_submit_interrupt(uhci, urb);
+				ret = uhci_submit_interrupt(uhci, urb, eurb);
 				if (ret == -EINPROGRESS)
 					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
 			}
-		} else		/* bandwidth is already set */
-			ret = uhci_submit_interrupt(uhci, urb);
+		} else {	/* inherit from parent */
+			urb->bandwidth = eurb->bandwidth;
+			ret = uhci_submit_interrupt(uhci, urb, eurb);
+		}
 		break;
 	case PIPE_BULK:
 		ret = uhci_submit_bulk(uhci, urb, eurb);
 		break;
 	case PIPE_ISOCHRONOUS:
-		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
-			bustime = usb_check_bandwidth(urb->dev, urb);
-			if (bustime < 0) {
-				ret = bustime;
-				break;
-			}
+		bustime = usb_check_bandwidth(urb->dev, urb);
+		if (bustime < 0) {
+			ret = bustime;
+			break;
+		}
 
-			ret = uhci_submit_isochronous(uhci, urb);
-			if (ret == -EINPROGRESS)
-				usb_claim_bandwidth(urb->dev, urb, bustime, 1);
-		} else		/* bandwidth is already set */
-			ret = uhci_submit_isochronous(uhci, urb);
+		ret = uhci_submit_isochronous(uhci, urb);
+		if (ret == -EINPROGRESS)
+			usb_claim_bandwidth(urb->dev, urb, bustime, 1);
 		break;
 	}
 
-	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
 	if (ret != -EINPROGRESS) {
+		/* Submit failed, so delete it from the urb_list */
+		struct urb_priv *urbp = urb->hcpriv;
+
+		list_del_init(&urbp->urb_list);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 		uhci_destroy_urb_priv (uhci, urb);
+
 		return ret;
 	}
+
+	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
 	return 0;
 }
 
@@ -1556,14 +1548,17 @@
 		uhci_unlink_generic(uhci, urb);
 		break;
 	case PIPE_INTERRUPT:
-		/* Interrupts are an exception */
-		if (urb->interval)
-			goto out_complete;
-
 		/* Release bandwidth for Interrupt or Isoc. transfers */
+		/* Make sure we don't release if we have a queued URB */
+		spin_lock(&uhci->frame_list_lock);
 		/* Spinlock needed ? */
-		if (urb->bandwidth)
+		if (list_empty(&urbp->queue_list) && urb->bandwidth)
 			usb_release_bandwidth(urb->dev, urb, 0);
+		else
+			/* bandwidth was passed on to queued URB, */
+			/* so don't let usb_unlink_urb() release it */
+			urb->bandwidth = 0;
+		spin_unlock(&uhci->frame_list_lock);
 		uhci_unlink_generic(uhci, urb);
 		break;
 	default:
@@ -1574,7 +1569,6 @@
 	/* Remove it from uhci->urb_list */
 	list_del_init(&urbp->urb_list);
 
-out_complete:
 	uhci_add_complete(uhci, urb);
 
 out:
@@ -1643,6 +1637,13 @@
 	unsigned long flags;
 	struct urb_priv *urbp = urb->hcpriv;
 
+	/* If this is an interrupt URB that is being killed in urb->complete, */
+	/* then just set its status and return */
+	if (!urbp) {
+	  urb->status = -ECONNRESET;
+	  return 0;
+	}
+
 	spin_lock_irqsave(&uhci->urb_list_lock, flags);
 
 	list_del_init(&urbp->urb_list);
@@ -1805,38 +1806,42 @@
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	struct usb_device *dev = urb->dev;
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	int killed, resubmit_interrupt, status;
+	int killed, resubmit_interrupt, status, ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&urb->lock, flags);
 
  	killed = (urb->status == -ENOENT || urb->status == -ECONNRESET);
 	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
-			urb->interval);
+			urb->interval && !killed);
 
 	status = urbp->status;
-	if (!resubmit_interrupt || killed)
-		/* We don't need urb_priv anymore */
-		uhci_destroy_urb_priv(uhci, urb);
+	uhci_destroy_urb_priv(uhci, urb);
 
 	if (!killed)
 		urb->status = status;
 	spin_unlock_irqrestore(&urb->lock, flags);
 
-	if (resubmit_interrupt)
+	if (resubmit_interrupt) {
 		urb->complete(urb);
-	else
-		usb_hcd_giveback_urb(hcd, urb);
 
-	if (resubmit_interrupt)
 		/* Recheck the status. The completion handler may have */
-		/*  unlinked the resubmitting interrupt URB */
-		killed = (urb->status == -ENOENT || urb->status == -ECONNRESET);
+		/* unlinked the resubmitting interrupt URB */
+		/* Note that this doesn't do what usb_hcd_giveback_urb() */
+		/* normally does, so that doesn't ever get done. */
+		if (urb->status == -ECONNRESET) {
+			usb_put_urb(urb);
+			return;
+		}
 
-	if (resubmit_interrupt && !killed) {
 		urb->dev = dev;
-		uhci_reset_interrupt(uhci, urb);
-	}
+		urb->status = -EINPROGRESS;
+		urb->actual_length = 0;
+		urb->bandwidth = 0;
+		if ((ret = uhci_urb_enqueue(&uhci->hcd, urb, 0)))
+			printk(KERN_ERR __FILE__ ": could not resubmit interrupt URB : %d\n", ret);		  
+	} else
+		usb_hcd_giveback_urb(hcd, urb);
 }
 
 static void uhci_finish_completion(struct usb_hcd *hcd)
@@ -2041,11 +2046,10 @@
 			uhci->skelqh[i] = NULL;
 		}
 
-	for (i = 0; i < UHCI_NUM_SKELTD; i++)
-		if (uhci->skeltd[i]) {
-			uhci_free_td(uhci, uhci->skeltd[i]);
-			uhci->skeltd[i] = NULL;
-		}
+	if (uhci->term_td) {
+		uhci_free_td(uhci, uhci->term_td);
+		uhci->term_td = NULL;
+	}
 
 	if (uhci->qh_pool) {
 		pci_pool_destroy(uhci->qh_pool);
@@ -2193,34 +2197,10 @@
 		goto err_alloc_root_hub;
 	}
 
-	uhci->skeltd[0] = uhci_alloc_td(uhci, udev);
-	if (!uhci->skeltd[0]) {
-		err("unable to allocate TD 0");
-		goto err_alloc_skeltd;
-	}
-
-	/*
-	 * 9 Interrupt queues; link int2 to int1, int4 to int2, etc
-	 * then link int1 to control and control to bulk
-	 */
-	for (i = 1; i < 9; i++) {
-		struct uhci_td *td;
-
-		td = uhci->skeltd[i] = uhci_alloc_td(uhci, udev);
-		if (!td) {
-			err("unable to allocate TD %d", i);
-			goto err_alloc_skeltd;
-		}
-
-		uhci_fill_td(td, 0, uhci_explen(UHCI_NULL_DATA_SIZE) |
-			(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
-		td->link = cpu_to_le32(uhci->skeltd[i - 1]->dma_handle);
-	}
-
-	uhci->skel_term_td = uhci_alloc_td(uhci, udev);
-	if (!uhci->skel_term_td) {
-		err("unable to allocate skel TD term");
-		goto err_alloc_skeltd;
+	uhci->term_td = uhci_alloc_td(uhci, udev);
+	if (!uhci->term_td) {
+		err("unable to allocate terminating TD");
+		goto err_alloc_term_td;
 	}
 
 	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
@@ -2231,26 +2211,30 @@
 		}
 	}
 
-	uhci_fill_td(uhci->skel_int1_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
-		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
-	uhci->skel_int1_td->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH;
+	/*
+	 * 8 Interrupt queues; link int2 to int1, int4 to int2, etc
+	 * then link int1 to control and control to bulk
+	 */
+	uhci->skel_int128_qh->link = cpu_to_le32(uhci->skel_int64_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int64_qh->link = cpu_to_le32(uhci->skel_int32_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int32_qh->link = cpu_to_le32(uhci->skel_int16_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int16_qh->link = cpu_to_le32(uhci->skel_int8_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int8_qh->link = cpu_to_le32(uhci->skel_int4_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int4_qh->link = cpu_to_le32(uhci->skel_int2_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int2_qh->link = cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH;
 
 	uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_hs_control_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_ls_control_qh->element = UHCI_PTR_TERM;
-
 	uhci->skel_hs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_hs_control_qh->element = UHCI_PTR_TERM;
-
 	uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_bulk_qh->element = UHCI_PTR_TERM;
 
 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
-	uhci_fill_td(uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
+	uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
 		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
-	uhci->skel_term_td->link = cpu_to_le32(uhci->skel_term_td->dma_handle);
+	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
 
 	uhci->skel_term_qh->link = UHCI_PTR_TERM;
-	uhci->skel_term_qh->element = cpu_to_le32(uhci->skel_term_td->dma_handle);
+	uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
 
 	/*
 	 * Fill the frame list: make all entries point to
@@ -2285,7 +2269,7 @@
 		}
 
 		/* Only place we don't use the frame list routines */
-		uhci->fl->frame[i] = cpu_to_le32(uhci->skeltd[irq]->dma_handle);
+		uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[7 - irq]->dma_handle);
 	}
 
 	start_hc(uhci);
@@ -2314,20 +2298,17 @@
 
 	del_timer_sync(&uhci->stall_timer);
 
+err_alloc_skelqh:
 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
 		if (uhci->skelqh[i]) {
 			uhci_free_qh(uhci, uhci->skelqh[i]);
 			uhci->skelqh[i] = NULL;
 		}
 
-err_alloc_skelqh:
-	for (i = 0; i < UHCI_NUM_SKELTD; i++)
-		if (uhci->skeltd[i]) {
-			uhci_free_td(uhci, uhci->skeltd[i]);
-			uhci->skeltd[i] = NULL;
-		}
+	uhci_free_td(uhci, uhci->term_td);
+	uhci->term_td = NULL;
 
-err_alloc_skeltd:
+err_alloc_term_td:
 	usb_free_dev(udev);
 	hcd->self.root_hub = NULL;
 
@@ -2517,7 +2498,7 @@
 up_failed:
 
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry("uhci", 0);
+	remove_proc_entry("driver/uhci", 0);
 
 proc_failed:
 #endif
@@ -2537,7 +2518,7 @@
 		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
 
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry("uhci", 0);
+	remove_proc_entry("driver/uhci", 0);
 #endif
 
 	if (errbuf)
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	Fri Oct 18 21:03:07 2002
+++ b/drivers/usb/host/uhci-hcd.h	Fri Oct 18 21:03:07 2002
@@ -81,7 +81,8 @@
 
 struct urb_priv;
 
-/* One role of a QH is to hold a queue of TDs for some endpoint.  Each QH is
+/*
+ * One role of a QH is to hold a queue of TDs for some endpoint.  Each QH is
  * used with one URB, and qh->element (updated by the HC) is either:
  *   - the next unprocessed TD for the URB, or
  *   - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or
@@ -194,85 +195,63 @@
 } __attribute__((aligned(16)));
 
 /*
- * There are various standard queues. We set up several different
- * queues for each of the three basic queue types: interrupt,
- * control, and bulk.
- *
- *  - There are various different interrupt latencies: ranging from
- *    every other USB frame (2 ms apart) to every 256 USB frames (ie
- *    256 ms apart). Make your choice according to how obnoxious you
- *    want to be on the wire, vs how critical latency is for you.
- *  - The control list is done every frame.
- *  - There are 4 bulk lists, so that up to four devices can have a
- *    bulk list of their own and when run concurrently all four lists
- *    will be be serviced.
- *
- * This is a bit misleading, there are various interrupt latencies, but they
- * vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the
- * other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor
- * problem
- *
- * In the case of the root hub, these QH's are just head's of qh's. Don't
- * be scared, it kinda makes sense. Look at this wonderful picture care of
- * Linus:
- *
- *  generic-  ->  dev1-  ->  generic-  ->  dev1-  ->  control-  ->  bulk- -> ...
- *   iso-QH      iso-QH       irq-QH      irq-QH        QH           QH
- *      |           |            |           |           |            |
- *     End     dev1-iso-TD1     End     dev1-irq-TD1    ...          ... 
- *                  |
- *             dev1-iso-TD2
- *                  |
- *                ....
- *
- * This may vary a bit (the UHCI docs don't explicitly say you can put iso
- * transfers in QH's and all of their pictures don't have that either) but
- * other than that, that is what we're doing now
- *
- * And now we don't put Iso transfers in QH's, so we don't waste one on it
- * --jerdfelt
- *
- * To keep with Linus' nomenclature, this is called the QH skeleton. These
- * labels (below) are only signficant to the root hub's QH's
- *
- *
- * NOTE:  That ASCII art doesn't match the current (August 2002) code, in
- * more ways than just not using QHs for ISO.
- *
- * NOTE:  Another way to look at the UHCI schedules is to compare them to what
- * other host controller interfaces use.  EHCI, OHCI, and UHCI all have tables
- * of transfers that the controller scans, frame by frame, and which hold the
- * scheduled periodic transfers.  The key differences are that UHCI
- *
- *   (a) puts control and bulk transfers into that same table; the others
- *       have separate data structures for non-periodic transfers.
- *   (b) lets QHs be linked from TDs, not just other QHs, since they don't
- *       hold endpoint data.  this driver chooses to use one QH per URB.
- *   (c) needs more TDs, since it uses one per packet.  the data toggle
- *       is stored in those TDs, along with all other endpoint state.
- */
-
-#define UHCI_NUM_SKELTD		10
-#define skel_int1_td		skeltd[0]
-#define skel_int2_td		skeltd[1]
-#define skel_int4_td		skeltd[2]
-#define skel_int8_td		skeltd[3]
-#define skel_int16_td		skeltd[4]
-#define skel_int32_td		skeltd[5]
-#define skel_int64_td		skeltd[6]
-#define skel_int128_td		skeltd[7]
-#define skel_int256_td		skeltd[8]
-#define skel_term_td		skeltd[9]	/* To work around PIIX UHCI bug */
-
-#define UHCI_NUM_SKELQH		4
-#define skel_ls_control_qh	skelqh[0]
-#define skel_hs_control_qh	skelqh[1]
-#define skel_bulk_qh		skelqh[2]
-#define skel_term_qh		skelqh[3]
+ * The UHCI driver places Interrupt, Control and Bulk into QH's both
+ * to group together TD's for one transfer, and also to faciliate queuing
+ * of URB's. To make it easy to insert entries into the schedule, we have
+ * a skeleton of QH's for each predefined Interrupt latency, low speed
+ * control, high speed control and terminating QH (see explanation for
+ * the terminating QH below).
+ *
+ * When we want to add a new QH, we add it to the end of the list for the
+ * skeleton QH.
+ *
+ * For instance, the queue can look like this:
+ *
+ * skel int128 QH
+ * dev 1 interrupt QH
+ * dev 5 interrupt QH
+ * skel int64 QH
+ * skel int32 QH
+ * ...
+ * skel int1 QH
+ * skel low speed control QH
+ * dev 5 control QH
+ * skel high speed control QH
+ * skel bulk QH
+ * dev 1 bulk QH
+ * dev 2 bulk QH
+ * skel terminating QH
+ *
+ * The terminating QH is used for 2 reasons:
+ * - To place a terminating TD which is used to workaround a PIIX bug
+ *   (see Intel errata for explanation)
+ * - To loop back to the high speed control queue for full speed bandwidth
+ *   reclamation
+ *
+ * Isochronous transfers are stored before the start of the skeleton
+ * schedule and don't use QH's. While the UHCI spec doesn't forbid the
+ * use of QH's for Isochronous, it doesn't use them either. Since we don't
+ * need to use them either, we follow the spec diagrams in hope that it'll
+ * be more compatible with future UHCI implementations.
+ */
+
+#define UHCI_NUM_SKELQH		12
+#define skel_int128_qh		skelqh[0]
+#define skel_int64_qh		skelqh[1]
+#define skel_int32_qh		skelqh[2]
+#define skel_int16_qh		skelqh[3]
+#define skel_int8_qh		skelqh[4]
+#define skel_int4_qh		skelqh[5]
+#define skel_int2_qh		skelqh[6]
+#define skel_int1_qh		skelqh[7]
+#define skel_ls_control_qh	skelqh[8]
+#define skel_hs_control_qh	skelqh[9]
+#define skel_bulk_qh		skelqh[10]
+#define skel_term_qh		skelqh[11]
 
 /*
- * Search tree for determining where <interval> fits in the
- * skelqh[] skeleton.
+ * Search tree for determining where <interval> fits in the skelqh[]
+ * skeleton.
  *
  * An interrupt request should be placed into the slowest skelqh[]
  * which meets the interval/period/frequency requirement.
@@ -280,32 +259,27 @@
  *
  * For a given <interval>, this function returns the appropriate/matching
  * skelqh[] index value.
- *
- * NOTE: For UHCI, we don't really need int256_qh since the maximum interval
- * is 255 ms.  However, we do need an int1_qh since 1 is a valid interval
- * and we should meet that frequency when requested to do so.
- * This will require some change(s) to the UHCI skeleton.
  */
 static inline int __interval_to_skel(int interval)
 {
 	if (interval < 16) {
 		if (interval < 4) {
 			if (interval < 2)
-				return 0;	/* int1 for 0-1 ms */
-			return 1;		/* int2 for 2-3 ms */
+				return 7;	/* int1 for 0-1 ms */
+			return 6;		/* int2 for 2-3 ms */
 		}
 		if (interval < 8)
-			return 2;		/* int4 for 4-7 ms */
-		return 3;			/* int8 for 8-15 ms */
+			return 5;		/* int4 for 4-7 ms */
+		return 4;			/* int8 for 8-15 ms */
 	}
 	if (interval < 64) {
 		if (interval < 32)
-			return 4;		/* int16 for 16-31 ms */
-		return 5;			/* int32 for 32-63 ms */
+			return 3;		/* int16 for 16-31 ms */
+		return 2;			/* int32 for 32-63 ms */
 	}
 	if (interval < 128)
-		return 6;			/* int64 for 64-127 ms */
-	return 7;				/* int128 for 128-255 ms (Max.) */
+		return 1;			/* int64 for 64-127 ms */
+	return 0;				/* int128 for 128-255 ms (Max.) */
 }
 
 #define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
@@ -332,7 +306,7 @@
 
 	struct usb_bus *bus;
 
-	struct uhci_td *skeltd[UHCI_NUM_SKELTD];	/* Skeleton TD's */
+	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
 
 	spinlock_t frame_list_lock;
diff -Nru a/drivers/usb/input/Config.help b/drivers/usb/input/Config.help
--- a/drivers/usb/input/Config.help	Fri Oct 18 21:03:06 2002
+++ b/drivers/usb/input/Config.help	Fri Oct 18 21:03:06 2002
@@ -63,7 +63,8 @@
   to use the generic HID driver for your USB keyboard and prefer
   to use the keyboard in its limited Boot Protocol mode instead.
 
-  This is almost certainly not what you want.
+  This is almost certainly not what you want.  This is mostly
+  useful for embedded applications or simple keyboards.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -77,7 +78,8 @@
   to use the generic HID driver for your USB keyboard and prefer
   to use the keyboard in its limited Boot Protocol mode instead.
 
-  This is almost certainly not what you want.
+  This is almost certainly not what you want.  This is mostly
+  useful for embedded applications or simple mice.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
diff -Nru a/drivers/usb/input/Config.in b/drivers/usb/input/Config.in
--- a/drivers/usb/input/Config.in	Fri Oct 18 21:03:07 2002
+++ b/drivers/usb/input/Config.in	Fri Oct 18 21:03:07 2002
@@ -15,8 +15,11 @@
 dep_mbool '    /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
 
 if [ "$CONFIG_USB_HID" != "y" ]; then
-   dep_tristate '  USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
-   dep_tristate '  USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
+   mainmenu_option next_comment
+   comment 'USB HID Boot Protocol drivers'
+   dep_tristate '  USB HIDBP Keyboard (simple Boot) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
+   dep_tristate '  USB HIDBP Mouse (simple Boot) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
+   endmenu
 fi
 
 dep_tristate '  Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	Fri Oct 18 21:03:08 2002
+++ b/drivers/usb/misc/usbtest.c	Fri Oct 18 21:03:08 2002
@@ -109,7 +109,7 @@
 	usb_fill_bulk_urb (urb, udev, pipe, 0, bytes, simple_callback, 0);
 	urb->interval = (udev->speed == USB_SPEED_HIGH)
 			? (INTERRUPT_RATE << 3)
-			: INTERRUPT_RATE,
+			: INTERRUPT_RATE;
 	urb->transfer_flags = URB_NO_DMA_MAP;
 	if (usb_pipein (pipe))
 		urb->transfer_flags |= URB_SHORT_NOT_OK;
@@ -142,7 +142,7 @@
 	int			retval = 0;
 
 	urb->context = &completion;
-	while (iterations-- > 0 && retval == 0) {
+	while (retval == 0 && iterations-- > 0) {
 		init_completion (&completion);
 		if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0)
 			break;
@@ -155,7 +155,7 @@
 		if (vary) {
 			int	len = urb->transfer_buffer_length;
 
-			len += max;
+			len += vary;
 			len %= max;
 			if (len == 0)
 				len = (vary < max) ? vary : max;
@@ -347,7 +347,7 @@
 		ep &= USB_ENDPOINT_NUMBER_MASK;
 		usb_settoggle (udev, ep, out, 0);
 		(out ? udev->epmaxpacketout : udev->epmaxpacketin ) [ep]
-			= iface_as->endpoint [ep].wMaxPacketSize;
+			= iface_as->endpoint [i].wMaxPacketSize;
 	}
 
 	return 0;
@@ -659,7 +659,7 @@
 			break;
 		dbg ("%s TEST 4:  read/%d 0..%d bytes %u times", dev->id,
 				param->vary, param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
+		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
@@ -907,6 +907,14 @@
 	.alt		= 1,
 };
 
+/* ezusb family device with dedicated usb test firmware*/
+static struct usbtest_info fw_info = {
+	.name		= "usb test device",
+	.ep_in		= 2,
+	.ep_out		= 2,
+	.alt		= 0,
+};
+
 #ifdef IBOT2
 /* this is a nice source of high speed bulk data;
  * uses an FX2, with firmware provided in the device
@@ -960,6 +968,11 @@
 	/* generic EZ-USB FX2 controller (or development board) */
 	{ USB_DEVICE (0x04b4, 0x8613),
 		.driver_info = (unsigned long) &ez2_info,
+		},
+
+	/* re-enumerated usb test device firmware */
+	{ USB_DEVICE (0xfff0, 0xfff0),
+		.driver_info = (unsigned long) &fw_info,
 		},
 
 #ifdef KEYSPAN_19Qi
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h	Fri Oct 18 21:03:08 2002
+++ b/drivers/usb/net/pegasus.h	Fri Oct 18 21:03:08 2002
@@ -135,6 +135,7 @@
 #define	VENDOR_SMC		0x0707
 #define	VENDOR_SOHOWARE		0x15e8
 #define	VENDOR_SIEMENS		0x067c
+#define	VENDOR_JTEC		0x11ad
 
 
 #else	/* PEGASUS_DEV */
@@ -256,6 +257,8 @@
 PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "FA8101 USB To ETHERNET", VENDOR_JTEC, 0x8101,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 
 
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Fri Oct 18 21:03:04 2002
+++ b/drivers/usb/storage/transport.c	Fri Oct 18 21:03:04 2002
@@ -647,6 +647,7 @@
 
 	/* no error code, so we must have transferred some data, 
 	 * just not all of it */
+	US_DEBUGP("-- transferred only %d bytes\n", partial);
 	return USB_STOR_XFER_SHORT;
 }
 
@@ -654,15 +655,15 @@
  * Transfer an entire SCSI command's worth of data payload over the bulk
  * pipe.
  *
- * Note that this uses usb_stor_transfer_buf to achieve its goals -- this
- * function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately.  For now, it also re-interprets the error codes.
+ * Note that this uses usb_stor_bulk_transfer_buf to achieve its goals --
+ * this function simply determines if we're going to use scatter-gather or not,
+ * and acts appropriately.
  */
 int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
 		char *buf, unsigned int length_left, int use_sg, int *residual)
 {
 	int i;
-	int result = -1;
+	int result = USB_STOR_XFER_ERROR;
 	struct scatterlist *sg;
 	unsigned int amount;
 	unsigned int partial;
@@ -1046,9 +1047,11 @@
 
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
-	if (transfer_length > 0) {
-		result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe,
-				srb, transfer_length);
+	if (transfer_length) {
+		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+				us->recv_bulk_pipe : us->send_bulk_pipe;
+		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
+					transfer_length);
 		US_DEBUGP("CBI data stage result is 0x%x\n", result);
 
 		/* report any errors */
@@ -1140,6 +1143,7 @@
 	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 		US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
 		return USB_STOR_TRANSPORT_ABORTED;
+	}
 
 	if (result != USB_STOR_XFER_GOOD) {
 		/* Uh oh... serious problem here */
@@ -1148,9 +1152,11 @@
 
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
-	if (transfer_length)
-		result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe,
-				srb, transfer_length);
+	if (transfer_length) {
+		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+				us->recv_bulk_pipe : us->send_bulk_pipe;
+		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
+					transfer_length);
 		US_DEBUGP("CB data stage result is 0x%x\n", result);
 
 		/* report any errors */
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	Fri Oct 18 21:03:03 2002
+++ b/drivers/video/Makefile	Fri Oct 18 21:03:03 2002
@@ -119,6 +119,9 @@
 obj-$(CONFIG_FBCON_STI)           += fbcon-sti.o
 obj-$(CONFIG_FBCON_ACCEL)	  += fbcon-accel.o
 
+# Files generated that shall be removed upon make clean
+clean-files := promcon_tbl.c
+
 include $(TOPDIR)/Rules.make
 
 $(obj)/promcon_tbl.c: $(src)/prom.uni
diff -Nru a/drivers/zorro/Makefile b/drivers/zorro/Makefile
--- a/drivers/zorro/Makefile	Fri Oct 18 21:03:04 2002
+++ b/drivers/zorro/Makefile	Fri Oct 18 21:03:04 2002
@@ -9,6 +9,9 @@
 
 host-progs 		:= gen-devlist
 
+# Files generated that shall be removed upon make clean
+clean-files := devlist.h
+
 include $(TOPDIR)/Rules.make
 
 # Dependencies on generated files need to be listed explicitly
diff -Nru a/fs/Makefile b/fs/Makefile
--- a/fs/Makefile	Fri Oct 18 21:03:05 2002
+++ b/fs/Makefile	Fri Oct 18 21:03:05 2002
@@ -37,7 +37,7 @@
 
 obj-$(CONFIG_PROC_FS)		+= proc/
 obj-y				+= partitions/
-obj-y				+= driverfs/
+obj-y				+= driverfs/ sysfs/
 obj-y				+= devpts/
 
 obj-$(CONFIG_PROFILING)		+= dcookies.o
diff -Nru a/fs/afs/cmservice.c b/fs/afs/cmservice.c
--- a/fs/afs/cmservice.c	Fri Oct 18 21:03:04 2002
+++ b/fs/afs/cmservice.c	Fri Oct 18 21:03:04 2002
@@ -129,11 +129,7 @@
 	/* only certain signals are of interest */
 	spin_lock_irq(&current->sig->siglock);
 	siginitsetinv(&current->blocked,0);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,3)
 	recalc_sigpending();
-#else
-	recalc_sigpending(current);
-#endif
 	spin_unlock_irq(&current->sig->siglock);
 
 	/* loop around looking for things to attend to */
@@ -360,6 +356,9 @@
 
 			rxrpc_call_abort(call,-ESRCH); /* abort, dequeue and put */
 
+			_debug("nuking active call %08x.%d",
+			       ntohl(call->conn->conn_id),ntohl(call->call_id));
+			rxrpc_put_call(call);
 			rxrpc_put_call(call);
 
 			spin_lock(&afscm_calls_lock);
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	Fri Oct 18 21:03:04 2002
+++ b/fs/aio.c	Fri Oct 18 21:03:04 2002
@@ -248,7 +248,7 @@
 	write_unlock(&mm->ioctx_list_lock);
 
 	dprintk("aio: allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
-		ctx, ctx->user_id, current->mm, ctx->ring_info.ring->nr);
+		ctx, ctx->user_id, current->mm, ctx->ring_info.nr);
 	return ctx;
 
 out_cleanup:
@@ -281,12 +281,12 @@
 		struct kiocb *iocb = list_kiocb(pos);
 		list_del_init(&iocb->ki_list);
 		cancel = iocb->ki_cancel;
-		if (cancel)
+		if (cancel) {
 			iocb->ki_users++;
-		spin_unlock_irq(&ctx->ctx_lock);
-		if (cancel)
+			spin_unlock_irq(&ctx->ctx_lock);
 			cancel(iocb, &res);
-		spin_lock_irq(&ctx->ctx_lock);
+			spin_lock_irq(&ctx->ctx_lock);
+		}
 	}
 	spin_unlock_irq(&ctx->ctx_lock);
 }
@@ -376,7 +376,7 @@
 /* aio_get_req
  *	Allocate a slot for an aio request.  Increments the users count
  * of the kioctx so that the kioctx stays around until all requests are
- * complete.  Returns -EAGAIN if no requests are free.
+ * complete.  Returns NULL if no requests are free.
  */
 static struct kiocb *FASTCALL(__aio_get_req(struct kioctx *ctx));
 static struct kiocb *__aio_get_req(struct kioctx *ctx)
@@ -409,8 +409,6 @@
 		req->ki_user_obj = NULL;
 		req->ki_ctx = ctx;
 		req->ki_users = 1;
-	} else {
-		kmem_cache_free(kiocb_cachep, req);
 		okay = 1;
 	}
 	kunmap_atomic(ring, KM_USER0);
@@ -478,7 +476,7 @@
 /* __aio_put_req
  *	Returns true if this put was the last user of the request.
  */
-static inline int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
+static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 {
 	dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n",
 		req, atomic_read(&req->ki_filp->f_count));
@@ -525,7 +523,7 @@
 /*	Lookup an ioctx id.  ioctx_list is lockless for reads.
  *	FIXME: this is O(n) and is only suitable for development.
  */
-static inline struct kioctx *lookup_ioctx(unsigned long ctx_id)
+static struct kioctx *lookup_ioctx(unsigned long ctx_id)
 {
 	struct kioctx *ioctx;
 	struct mm_struct *mm;
@@ -845,13 +843,13 @@
 
 	/* End fast path */
 
+	init_timeout(&to);
 	if (timeout) {
 		struct timespec	ts;
 		ret = -EFAULT;
 		if (unlikely(copy_from_user(&ts, timeout, sizeof(ts))))
 			goto out;
 
-		init_timeout(&to);
 		set_timeout(start_jiffies, &to, &ts);
 	}
 
@@ -1197,6 +1195,9 @@
 	if (NULL != cancel) {
 		struct io_event tmp;
 		printk("calling cancel\n");
+		memset(&tmp, 0, sizeof(tmp));
+		tmp.obj = (u64)(unsigned long)kiocb->ki_user_obj;
+		tmp.data = kiocb->ki_user_data;
 		ret = cancel(kiocb, &tmp);
 		if (!ret) {
 			/* Cancellation succeeded -- copy the result
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	Fri Oct 18 21:03:05 2002
+++ b/fs/bio.c	Fri Oct 18 21:03:05 2002
@@ -149,12 +149,13 @@
 	bio_init(bio);
 
 	if (unlikely(!nr_iovecs))
-		goto out;
+		goto noiovec;
 
 	bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
 	if (bvl) {
 		bio->bi_flags |= idx << BIO_POOL_OFFSET;
 		bio->bi_max_vecs = bvec_array[idx].nr_vecs;
+noiovec:
 		bio->bi_io_vec = bvl;
 		bio->bi_destructor = bio_destructor;
 out:
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Fri Oct 18 21:03:08 2002
+++ b/fs/block_dev.c	Fri Oct 18 21:03:08 2002
@@ -527,16 +527,16 @@
 	struct block_device_operations * bdops = bdev->bd_op;
 	kdev_t dev = to_kdev_t(bdev->bd_dev);
 
-	if (bdops->check_media_change == NULL)
+	if (!bdops->media_changed)
 		return 0;
-	if (!bdops->check_media_change(dev))
+	if (!bdops->media_changed(bdev->bd_disk))
 		return 0;
 
 	if (invalidate_device(dev, 0))
 		printk("VFS: busy inodes on changed media.\n");
 
-	if (bdops->revalidate)
-		bdops->revalidate(dev);
+	if (bdops->revalidate_disk)
+		bdops->revalidate_disk(bdev->bd_disk);
 	if (bdev->bd_disk->minors > 1)
 		bdev->bd_invalidated = 1;
 	return 1;
@@ -601,6 +601,13 @@
 		if (owner)
 			__MOD_INC_USE_COUNT(owner);
 	}
+	disk = get_gendisk(bdev->bd_dev, &part);
+	if (!disk) {
+		if (owner)
+			__MOD_DEC_USE_COUNT(owner);
+		bdput(bdev);
+		return ret;
+	}
 
 	down(&bdev->bd_sem);
 	old = bdev->bd_op;
@@ -612,9 +619,6 @@
 		if (owner)
 			__MOD_DEC_USE_COUNT(owner);
 	}
-	disk = get_gendisk(bdev->bd_dev, &part);
-	if (!disk)
-		goto out1;
 	if (!bdev->bd_contains) {
 		bdev->bd_contains = bdev;
 		if (part) {
@@ -633,10 +637,14 @@
 		if (!bdev->bd_openers)
 			bdev->bd_disk = disk;
 		if (!bdev->bd_queue) {
-			struct blk_dev_struct *p = blk_dev + major(dev);
-			bdev->bd_queue = &p->request_queue;
-			if (p->queue)
-				bdev->bd_queue =  p->queue(dev);
+			if (disk->queue)
+				bdev->bd_queue = disk->queue;
+			else {
+				struct blk_dev_struct *p = blk_dev + major(dev);
+				bdev->bd_queue = &p->request_queue;
+				if (p->queue)
+					bdev->bd_queue =  p->queue(dev);
+			}
 		}
 		if (bdev->bd_op->open) {
 			ret = bdev->bd_op->open(inode, file);
@@ -650,7 +658,6 @@
 			bdi = blk_get_backing_dev_info(bdev);
 			if (bdi == NULL)
 				bdi = &default_backing_dev_info;
-			inode->i_data.backing_dev_info = bdi;
 			bdev->bd_inode->i_data.backing_dev_info = bdi;
 		}
 		if (bdev->bd_invalidated)
@@ -661,8 +668,7 @@
 		if (!bdev->bd_openers) {
 			struct hd_struct *p;
 			p = disk->part + part - 1;
-			inode->i_data.backing_dev_info =
-			   bdev->bd_inode->i_data.backing_dev_info =
+			bdev->bd_inode->i_data.backing_dev_info =
 			   bdev->bd_contains->bd_inode->i_data.backing_dev_info;
 			if (!(disk->flags & GENHD_FL_UP) || !p->nr_sects) {
 				bdev->bd_contains->bd_part_count--;
@@ -685,6 +691,8 @@
 
 out2:
 	if (!bdev->bd_openers) {
+		bdev->bd_queue = NULL;
+		bdev->bd_disk = NULL;
 		bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
 		if (bdev != bdev->bd_contains) {
 			blkdev_put(bdev->bd_contains, BDEV_RAW);
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Fri Oct 18 21:03:05 2002
+++ b/fs/buffer.c	Fri Oct 18 21:03:05 2002
@@ -142,7 +142,7 @@
 	finish_wait(wqh, &wait);
 }
 
-static inline void
+static void
 __set_page_buffers(struct page *page, struct buffer_head *head)
 {
 	if (page_has_buffers(page))
@@ -152,7 +152,7 @@
 	page->private = (unsigned long)head;
 }
 
-static inline void
+static void
 __clear_page_buffers(struct page *page)
 {
 	ClearPagePrivate(page);
@@ -594,14 +594,14 @@
  * PageLocked prevents anyone from starting writeback of a page which is
  * under read I/O (PageWriteback is only ever set against a locked page).
  */
-inline void mark_buffer_async_read(struct buffer_head *bh)
+void mark_buffer_async_read(struct buffer_head *bh)
 {
 	bh->b_end_io = end_buffer_async_read;
 	set_buffer_async_read(bh);
 }
 EXPORT_SYMBOL(mark_buffer_async_read);
 
-inline void mark_buffer_async_write(struct buffer_head *bh)
+void mark_buffer_async_write(struct buffer_head *bh)
 {
 	bh->b_end_io = end_buffer_async_write;
 	set_buffer_async_write(bh);
@@ -960,7 +960,7 @@
 /*
  * Initialise the state of a blockdev page's buffers.
  */ 
-static /*inline*/ void
+static void
 init_page_buffers(struct page *page, struct block_device *bdev,
 			int block, int size)
 {
@@ -989,7 +989,7 @@
  *
  * This is user purely for blockdev mappings.
  */
-static /*inline*/ struct page *
+static struct page *
 grow_dev_page(struct block_device *bdev, unsigned long block,
 			unsigned long index, int size)
 {
@@ -1416,7 +1416,7 @@
 /*
  * Called when truncating a buffer on a page completely.
  */
-static /* inline */ void discard_buffer(struct buffer_head * bh)
+static inline void discard_buffer(struct buffer_head * bh)
 {
 	lock_buffer(bh);
 	clear_buffer_dirty(bh);
@@ -2451,7 +2451,7 @@
 		(bh->b_state & ((1 << BH_Dirty) | (1 << BH_Lock)));
 }
 
-static inline int
+static int
 drop_buffers(struct page *page, struct buffer_head **buffers_to_free)
 {
 	struct buffer_head *head = page_buffers(page);
diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
--- a/fs/driverfs/inode.c	Fri Oct 18 21:03:03 2002
+++ b/fs/driverfs/inode.c	Fri Oct 18 21:03:03 2002
@@ -509,10 +509,12 @@
 	DBG("driverfs: mount_count = %d\n",mount_count);
 }
 
-int __init init_driverfs_fs(void)
+static int __init driverfs_init(void)
 {
 	return register_filesystem(&driverfs_fs_type);
 }
+
+core_initcall(driverfs_init);
 
 static struct dentry * get_dentry(struct dentry * parent, const char * name)
 {
diff -Nru a/fs/libfs.c b/fs/libfs.c
--- a/fs/libfs.c	Fri Oct 18 21:03:03 2002
+++ b/fs/libfs.c	Fri Oct 18 21:03:03 2002
@@ -262,17 +262,16 @@
 
 int simple_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
 {
-	struct inode *inode;
+	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
 
 	if (!simple_empty(new_dentry))
 		return -ENOTEMPTY;
 
-	inode = new_dentry->d_inode;
-	if (inode) {
-		inode->i_nlink--;
-		dput(new_dentry);
-	}
-	if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+	if (new_dentry->d_inode) {
+		simple_unlink(new_dir, new_dentry);
+		if (they_are_dirs)
+			old_dir->i_nlink--;
+	} else if (they_are_dirs) {
 		old_dir->i_nlink--;
 		new_dir->i_nlink++;
 	}
diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c
--- a/fs/lockd/svc.c	Fri Oct 18 21:03:05 2002
+++ b/fs/lockd/svc.c	Fri Oct 18 21:03:05 2002
@@ -36,7 +36,7 @@
 #include <linux/nfs.h>
 
 #define NLMDBG_FACILITY		NLMDBG_SVC
-#define LOCKD_BUFSIZE		(1024 + NLMSSVC_XDRSIZE)
+#define LOCKD_BUFSIZE		(1024 + NLMSVC_XDRSIZE)
 #define ALLOWED_SIGS		(sigmask(SIGKILL))
 
 extern struct svc_program	nlmsvc_program;
@@ -223,7 +223,7 @@
 			"lockd_up: no pid, %d users??\n", nlmsvc_users);
 
 	error = -ENOMEM;
-	serv = svc_create(&nlmsvc_program, 0, NLMSVC_XDRSIZE);
+	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE);
 	if (!serv) {
 		printk(KERN_WARNING "lockd_up: create service failed\n");
 		goto out;
@@ -358,17 +358,20 @@
 		.vs_vers	= 1,
 		.vs_nproc	= 17,
 		.vs_proc	= nlmsvc_procedures,
+		.vs_xdrsize	= NLMSVC_XDRSIZE,
 };
 static struct svc_version	nlmsvc_version3 = {
 		.vs_vers	= 3,
 		.vs_nproc	= 24,
 		.vs_proc	= nlmsvc_procedures,
+		.vs_xdrsize	= NLMSVC_XDRSIZE,
 };
 #ifdef CONFIG_LOCKD_V4
 static struct svc_version	nlmsvc_version4 = {
 		.vs_vers	= 4,
 		.vs_nproc	= 24,
 		.vs_proc	= nlmsvc_procedures4,
+		.vs_xdrsize	= NLMSVC_XDRSIZE,
 };
 #endif
 static struct svc_version *	nlmsvc_version[] = {
@@ -384,8 +387,6 @@
 #define NLM_NRVERS	(sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
 struct svc_program	nlmsvc_program = {
 	.pg_prog	= NLM_PROGRAM,		/* program number */
-	.pg_lovers	= 1,			/* version */
-	.pg_hivers	= NLM_NRVERS-1,		/* range */
 	.pg_nvers	= NLM_NRVERS,		/* number of entries in nlmsvc_version */
 	.pg_vers	= nlmsvc_version,	/* version table */
 	.pg_name	= "lockd",		/* service name */
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Fri Oct 18 21:03:08 2002
+++ b/fs/locks.c	Fri Oct 18 21:03:08 2002
@@ -727,11 +727,15 @@
 	}
 	unlock_kernel();
 
-	if (found)
-		yield();
-
 	if (new_fl->fl_type == F_UNLCK)
 		return 0;
+
+	/*
+	 * If a higher-priority process was blocked on the old file lock,
+	 * give it the opportunity to lock the file.
+	 */
+	if (found)
+		cond_resched();
 
 	lock_kernel();
 	for_each_lock(inode, before) {
diff -Nru a/fs/mpage.c b/fs/mpage.c
--- a/fs/mpage.c	Fri Oct 18 21:03:03 2002
+++ b/fs/mpage.c	Fri Oct 18 21:03:03 2002
@@ -317,7 +317,7 @@
  * written, so it can intelligently allocate a suitably-sized BIO.  For now,
  * just allocate full-size (16-page) BIOs.
  */
-static inline struct bio *
+static struct bio *
 mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
 			sector_t *last_block_in_bio, int *ret)
 {
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	Fri Oct 18 21:03:07 2002
+++ b/fs/nfs/inode.c	Fri Oct 18 21:03:07 2002
@@ -1355,7 +1355,7 @@
 	if (data->auth_flavourlen != 0) {
 		if (data->auth_flavourlen > 1)
 			printk(KERN_INFO "NFS: cannot yet deal with multiple auth flavours.\n");
-		if (copy_from_user(authflavour, data->auth_flavours, sizeof(authflavour))) {
+		if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
 			err = -EFAULT;
 			goto out_fail;
 		}
diff -Nru a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
--- a/fs/nfs/nfs4xdr.c	Fri Oct 18 21:03:08 2002
+++ b/fs/nfs/nfs4xdr.c	Fri Oct 18 21:03:08 2002
@@ -1077,13 +1077,13 @@
                 READ_BUF(8);
                 len += 8;
                 READ64(nfp->change_attr);
-                dprintk("read_attrs: changeid=%Ld\n", (u64)nfp->change_attr);
+                dprintk("read_attrs: changeid=%Ld\n", (long long)nfp->change_attr);
         }
         if (bmval0 & FATTR4_WORD0_SIZE) {
                 READ_BUF(8);
                 len += 8;
                 READ64(nfp->size);
-                dprintk("read_attrs: size=%Ld\n", (u64)nfp->size);
+                dprintk("read_attrs: size=%Ld\n", (long long)nfp->size);
         }
         if (bmval0 & FATTR4_WORD0_FSID) {
                 READ_BUF(16);
@@ -1091,7 +1091,8 @@
                 READ64(nfp->fsid_u.nfs4.major);
                 READ64(nfp->fsid_u.nfs4.minor);
                 dprintk("read_attrs: fsid=0x%Lx/0x%Lx\n",
-			nfp->fsid_u.nfs4.major, nfp->fsid_u.nfs4.minor);
+			(long long)nfp->fsid_u.nfs4.major,
+			(long long)nfp->fsid_u.nfs4.minor);
         }
         if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
                 READ_BUF(4);
@@ -1103,31 +1104,31 @@
                 READ_BUF(8);
                 len += 8;
                 READ64(nfp->fileid);
-                dprintk("read_attrs: fileid=%Ld\n", nfp->fileid);
+                dprintk("read_attrs: fileid=%Ld\n", (long long) nfp->fileid);
         }
 	if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
 		READ_BUF(8);
 		len += 8;
 		READ64(fsstat->afiles);
-		dprintk("read_attrs: files_avail=0x%Lx\n", fsstat->afiles);
+		dprintk("read_attrs: files_avail=0x%Lx\n", (long long) fsstat->afiles);
 	}
         if (bmval0 & FATTR4_WORD0_FILES_FREE) {
                 READ_BUF(8);
                 len += 8;
                 READ64(fsstat->ffiles);
-                dprintk("read_attrs: files_free=0x%Lx\n", fsstat->ffiles);
+                dprintk("read_attrs: files_free=0x%Lx\n", (long long) fsstat->ffiles);
         }
         if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
                 READ_BUF(8);
                 len += 8;
                 READ64(fsstat->tfiles);
-                dprintk("read_attrs: files_tot=0x%Lx\n", fsstat->tfiles);
+                dprintk("read_attrs: files_tot=0x%Lx\n", (long long) fsstat->tfiles);
         }
         if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
                 READ_BUF(8);
                 len += 8;
                 READ64(fsinfo->maxfilesize);
-                dprintk("read_attrs: maxfilesize=0x%Lx\n", fsinfo->maxfilesize);
+                dprintk("read_attrs: maxfilesize=0x%Lx\n", (long long) fsinfo->maxfilesize);
         }
 	if (bmval0 & FATTR4_WORD0_MAXLINK) {
 		READ_BUF(4);
@@ -1214,25 +1215,25 @@
                 READ_BUF(8);
                 len += 8;
                 READ64(fsstat->abytes);
-                dprintk("read_attrs: savail=0x%Lx\n", fsstat->abytes);
+                dprintk("read_attrs: savail=0x%Lx\n", (long long) fsstat->abytes);
         }
 	if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
                 READ_BUF(8);
                 len += 8;
                 READ64(fsstat->fbytes);
-                dprintk("read_attrs: sfree=0x%Lx\n", fsstat->fbytes);
+                dprintk("read_attrs: sfree=0x%Lx\n", (long long) fsstat->fbytes);
         }
         if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
                 READ_BUF(8);
                 len += 8;
                 READ64(fsstat->tbytes);
-                dprintk("read_attrs: stotal=0x%Lx\n", fsstat->tbytes);
+                dprintk("read_attrs: stotal=0x%Lx\n", (long long) fsstat->tbytes);
         }
         if (bmval1 & FATTR4_WORD1_SPACE_USED) {
                 READ_BUF(8);
                 len += 8;
                 READ64(nfp->du.nfs3.used);
-                dprintk("read_attrs: sused=0x%Lx\n", nfp->du.nfs3.used);
+                dprintk("read_attrs: sused=0x%Lx\n", (long long) nfp->du.nfs3.used);
         }
         if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
                 READ_BUF(12);
diff -Nru a/fs/nfs/proc.c b/fs/nfs/proc.c
--- a/fs/nfs/proc.c	Fri Oct 18 21:03:08 2002
+++ b/fs/nfs/proc.c	Fri Oct 18 21:03:08 2002
@@ -490,7 +490,7 @@
 
 	dprintk("NFS call  fsinfo\n");
 	info->fattr->valid = 0;
-	status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &info, 0);
+	status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0);
 	dprintk("NFS reply fsinfo: %d\n", status);
 	if (status)
 		goto out;
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	Fri Oct 18 21:03:05 2002
+++ b/fs/nfsd/export.c	Fri Oct 18 21:03:05 2002
@@ -70,7 +70,8 @@
 {
 	if (cache_put(item, cd)) {
 		struct svc_expkey *key = container_of(item, struct svc_expkey, h);
-		if (key->ek_export)
+		if (test_bit(CACHE_VALID, &item->flags) &&
+		    !test_bit(CACHE_NEGATIVE, &item->flags))
 			exp_put(key->ek_export);
 		auth_domain_put(key->ek_client);
 		kfree(key);
@@ -85,10 +86,10 @@
 	struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
 	char type[5];
 
-	add_word(bpp, blen, ek->ek_client->name);
+	qword_add(bpp, blen, ek->ek_client->name);
 	snprintf(type, 5, "%d", ek->ek_fsidtype);
-	add_word(bpp, blen, type);
-	add_hex(bpp, blen, (char*)ek->ek_fsid, ek->ek_fsidtype==0?8:4);
+	qword_add(bpp, blen, type);
+	qword_addhex(bpp, blen, (char*)ek->ek_fsid, ek->ek_fsidtype==0?8:4);
 	(*bpp)[-1] = '\n';
 }
 
@@ -113,7 +114,7 @@
 	if (!buf) goto out;
 
 	err = -EINVAL;
-	if ((len=get_word(&mesg, buf, PAGE_SIZE)) <= 0)
+	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
 		goto out;
 
 	err = -ENOENT;
@@ -123,7 +124,7 @@
 	dprintk("found domain %s\n", buf);
 
 	err = -EINVAL;
-	if ((len=get_word(&mesg, buf, PAGE_SIZE)) <= 0)
+	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
 		goto out;
 	fsidtype = simple_strtoul(buf, &ep, 10);
 	if (*ep)
@@ -131,7 +132,7 @@
 	dprintk("found fsidtype %d\n", fsidtype);
 	if (fsidtype > 1)
 		goto out;
-	if ((len=get_word(&mesg, buf, PAGE_SIZE)) <= 0)
+	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
 		goto out;
 	dprintk("found fsid length %d\n", len);
 	if (len != ((fsidtype==0)?8:4))
@@ -148,7 +149,7 @@
 	memcpy(key.ek_fsid, buf, len);
 
 	/* now we want a pathname, or empty meaning NEGATIVE  */
-	if ((len=get_word(&mesg, buf, PAGE_SIZE)) < 0)
+	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
 		goto out;
 	dprintk("Path seems to be <%s>\n", buf);
 	err = 0;
@@ -268,9 +269,9 @@
 	struct svc_export *exp = container_of(h, struct svc_export, h);
 	char *pth;
 
-	add_word(bpp, blen, exp->ex_client->name);
+	qword_add(bpp, blen, exp->ex_client->name);
 	pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen);
-	add_word(bpp, blen, pth);
+	qword_add(bpp, blen, pth);
 	(*bpp)[-1] = '\n';
 }
 
@@ -297,7 +298,7 @@
 	if (!buf) goto out;
 
 	/* client */
-	len = get_word(&mesg, buf, PAGE_SIZE);
+	len = qword_get(&mesg, buf, PAGE_SIZE);
 	if (len <= 0) return -EINVAL;
 	err = -ENOENT;
 	dom = auth_domain_find(buf);
@@ -306,7 +307,7 @@
 
 	/* path */
 	err = -EINVAL;
-	if ((len=get_word(&mesg, buf, PAGE_SIZE)) <= 0)
+	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
 		goto out;
 	err = path_lookup(buf, 0, &nd);
 	if (err) goto out;
@@ -1119,10 +1120,12 @@
 	exp_writelock();
 
 	exp_unexport_all(NULL);
-	svcauth_unix_purge();
 
-	cache_unregister(&svc_export_cache);
-	cache_unregister(&svc_expkey_cache);
+	if (cache_unregister(&svc_expkey_cache))
+		printk(KERN_ERR "nfsd: failed to unregister expkey cache\n");
+	if (cache_unregister(&svc_export_cache))
+		printk(KERN_ERR "nfsd: failed to unregister export cache\n");
+	svcauth_unix_purge();
 
 	exp_writeunlock();
 	dprintk("nfsd: export shutdown complete.\n");
diff -Nru a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
--- a/fs/nfsd/nfs3proc.c	Fri Oct 18 21:03:04 2002
+++ b/fs/nfsd/nfs3proc.c	Fri Oct 18 21:03:04 2002
@@ -15,7 +15,6 @@
 #include <linux/fcntl.h>
 #include <linux/net.h>
 #include <linux/in.h>
-#include <linux/version.h>
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/major.h>
@@ -664,7 +663,7 @@
 #define pAT (1+AT)	/* post attributes - conditional */
 #define WC (7+pAT)	/* WCC attributes */
 
-struct svc_procedure		nfsd_procedures3[22] = {
+static struct svc_procedure		nfsd_procedures3[22] = {
   PROC(null,	 void,		void,		void,	  RC_NOCACHE, ST),
   PROC(getattr,	 fhandle,	attrstat,	fhandle,  RC_NOCACHE, ST+AT),
   PROC(setattr,  sattr,		wccstat,	fhandle,  RC_REPLBUFF, ST+WC),
@@ -687,4 +686,12 @@
   PROC(fsinfo,   fhandle,	fsinfo,		void,     RC_NOCACHE, ST+pAT+12),
   PROC(pathconf, fhandle,	pathconf,	void,     RC_NOCACHE, ST+pAT+6),
   PROC(commit,	 commit,	commit,		fhandle,  RC_NOCACHE, ST+WC+2),
+};
+
+struct svc_version	nfsd_version3 = {
+		.vs_vers	= 3,
+		.vs_nproc	= 22,
+		.vs_proc	= nfsd_procedures3,
+		.vs_dispatch	= nfsd_dispatch,
+		.vs_xdrsize	= NFS3_SVC_XDRSIZE,
 };
diff -Nru a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
--- a/fs/nfsd/nfs4proc.c	Fri Oct 18 21:03:08 2002
+++ b/fs/nfsd/nfs4proc.c	Fri Oct 18 21:03:08 2002
@@ -177,11 +177,12 @@
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclientid)
 {
 	memset(&setclientid->se_clientid, 0, sizeof(clientid_t));
+	memset(&setclientid->se_confirm, 0, sizeof(nfs4_verifier));
 	return nfs_ok;
 }
 
 static inline int
-nfsd4_setclientid_confirm(struct svc_rqst *rqstp, clientid_t *clientid)
+nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
 	return nfs_ok;
 }
@@ -732,9 +733,17 @@
  * XID's liberally, so I've left it unimplemented until pynfs generates
  * better XID's.
  */
-struct svc_procedure		nfsd_procedures4[2] = {
+static struct svc_procedure		nfsd_procedures4[2] = {
   PROC(null,	 void,		void,		void,	  RC_NOCACHE, 1),
   PROC(compound, compound,	compound,	compound, RC_NOCACHE, NFSD_BUFSIZE)
+};
+
+struct svc_version	nfsd_version4 = {
+		.vs_vers	= 4,
+		.vs_nproc	= 2,
+		.vs_proc	= nfsd_procedures4,
+		.vs_dispatch	= nfsd_dispatch,
+		.vs_xdrsize	= NFS4_SVC_XDRSIZE,
 };
 
 /*
diff -Nru a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
--- a/fs/nfsd/nfs4xdr.c	Fri Oct 18 21:03:04 2002
+++ b/fs/nfsd/nfs4xdr.c	Fri Oct 18 21:03:04 2002
@@ -717,12 +717,13 @@
 }
 
 static int
-nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, clientid_t *clientid)
+nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
 {
 	DECODE_HEAD;
 
-	READ_BUF(8);
-	COPYMEM(clientid, 8);
+	READ_BUF(8 + sizeof(nfs4_verifier));
+	COPYMEM(&scd_c->sc_clientid, 8);
+	COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
 
 	DECODE_TAIL;
 }
@@ -1736,8 +1737,9 @@
 	ENCODE_HEAD;
 
 	if (!nfserr) {
-		RESERVE_SPACE(8);
+		RESERVE_SPACE(8 + sizeof(nfs4_verifier));
 		WRITEMEM(&scd->se_clientid, 8);
+		WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
 		ADJUST_ARGS();
 	}
 	else if (nfserr == nfserr_clid_inuse) {
diff -Nru a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
--- a/fs/nfsd/nfsctl.c	Fri Oct 18 21:03:03 2002
+++ b/fs/nfsd/nfsctl.c	Fri Oct 18 21:03:03 2002
@@ -8,7 +8,6 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/version.h>
 
 #include <linux/linkage.h>
 #include <linux/time.h>
diff -Nru a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
--- a/fs/nfsd/nfsproc.c	Fri Oct 18 21:03:04 2002
+++ b/fs/nfsd/nfsproc.c	Fri Oct 18 21:03:04 2002
@@ -16,7 +16,6 @@
 #include <linux/net.h>
 #include <linux/in.h>
 #include <linux/namei.h>
-#include <linux/version.h>
 #include <linux/unistd.h>
 #include <linux/slab.h>
 
@@ -539,7 +538,7 @@
 #define FH 8		/* filehandle */
 #define	AT 18		/* attributes */
 
-struct svc_procedure		nfsd_procedures2[18] = {
+static struct svc_procedure		nfsd_procedures2[18] = {
   PROC(null,	 void,		void,		none,		RC_NOCACHE, ST),
   PROC(getattr,	 fhandle,	attrstat,	fhandle,	RC_NOCACHE, ST+AT),
   PROC(setattr,  sattrargs,	attrstat,	fhandle,	RC_REPLBUFF, ST+AT),
@@ -560,6 +559,14 @@
   PROC(statfs,	 fhandle,	statfsres,	none,		RC_NOCACHE, ST+5),
 };
 
+
+struct svc_version	nfsd_version2 = {
+		.vs_vers	= 2,
+		.vs_nproc	= 18,
+		.vs_proc	= nfsd_procedures2,
+		.vs_dispatch	= nfsd_dispatch,
+		.vs_xdrsize	= NFS2_SVC_XDRSIZE,
+};
 
 /*
  * Map errnos to NFS errnos.
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c	Fri Oct 18 21:03:03 2002
+++ b/fs/nfsd/nfssvc.c	Fri Oct 18 21:03:03 2002
@@ -8,7 +8,6 @@
  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 
@@ -17,7 +16,6 @@
 #include <linux/nfs.h>
 #include <linux/in.h>
 #include <linux/uio.h>
-#include <linux/version.h>
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
@@ -31,9 +29,6 @@
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/stats.h>
 #include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/nfsd/xdr3.h>
-#include <linux/nfsd/xdr4.h>
 #include <linux/lockd/bind.h>
 
 #define NFSDDBG_FACILITY	NFSDDBG_SVC
@@ -93,7 +88,7 @@
 	if (!nfsd_serv) {
 		atomic_set(&nfsd_busy, 0);
 		error = -ENOMEM;
-		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE, NFSSVC_XDRSIZE);
+		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
 		if (nfsd_serv == NULL)
 			goto out;
 		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
@@ -258,7 +253,7 @@
 	MOD_DEC_USE_COUNT;
 }
 
-static int
+int
 nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
 {
 	struct svc_procedure	*proc;
@@ -319,34 +314,12 @@
 	return 1;
 }
 
-static struct svc_version	nfsd_version2 = {
-		.vs_vers	= 2,
-		.vs_nproc	= 18,
-		.vs_proc	= nfsd_procedures2,
-		.vs_dispatch	= nfsd_dispatch
-};
-#ifdef CONFIG_NFSD_V3
-static struct svc_version	nfsd_version3 = {
-		.vs_vers	= 3,
-		.vs_nproc	= 22,
-		.vs_proc	= nfsd_procedures3,
-		.vs_dispatch	= nfsd_dispatch
-};
-#endif
-#ifdef CONFIG_NFSD_V4
-static struct svc_version	nfsd_version4 = {
-		.vs_vers	= 4,
-		.vs_nproc	= 2,
-		.vs_proc	= nfsd_procedures4,
-		.vs_dispatch	= nfsd_dispatch
-};
-#endif
+extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
+
 static struct svc_version *	nfsd_version[] = {
 	[2] = &nfsd_version2,
 #if defined(CONFIG_NFSD_V3)
 	[3] = &nfsd_version3,
-#elif defined(CONFIG_NFSD_V4)
-	[3] = NULL,
 #endif
 #if defined(CONFIG_NFSD_V4)
 	[4] = &nfsd_version4,
@@ -356,8 +329,6 @@
 #define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
 struct svc_program		nfsd_program = {
 	.pg_prog		= NFS_PROGRAM,		/* program number */
-	.pg_lovers		= 2,			// version
-	.pg_hivers		= NFSD_NRVERS-1,	// range
 	.pg_nvers		= NFSD_NRVERS,		/* nr of entries in nfsd_version */
 	.pg_vers		= nfsd_version,		/* version table */
 	.pg_name		= "nfsd",		/* program name */
diff -Nru a/fs/nfsd/stats.c b/fs/nfsd/stats.c
--- a/fs/nfsd/stats.c	Fri Oct 18 21:03:03 2002
+++ b/fs/nfsd/stats.c	Fri Oct 18 21:03:03 2002
@@ -27,7 +27,6 @@
 #include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/sunrpc/svc.h>
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Fri Oct 18 21:03:04 2002
+++ b/fs/nfsd/vfs.c	Fri Oct 18 21:03:04 2002
@@ -16,7 +16,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/time.h>
 #include <linux/errno.h>
@@ -30,7 +29,6 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/in.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/namei.h>
 
@@ -591,8 +589,6 @@
 	if (err)
 		goto out;
 	err = nfserr_perm;
-	if (!file.f_op->read)
-		goto out_close;
 	inode = file.f_dentry->d_inode;
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
@@ -604,11 +600,10 @@
 	ra = nfsd_get_raparms(inode->i_dev, inode->i_ino);
 	if (ra)
 		file.f_ra = ra->p_ra;
-	file.f_pos = offset;
 
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
-	err = file.f_op->read(&file, buf, *count, &file.f_pos);
+	err = vfs_read(&file, buf, *count, &offset);
 	set_fs(oldfs);
 
 	/* Write back readahead params */
@@ -650,8 +645,7 @@
 	if (!cnt)
 		goto out_close;
 	err = nfserr_perm;
-	if (!file.f_op->write)
-		goto out_close;
+
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		(!lock_may_write(file.f_dentry->d_inode, offset, cnt)))
@@ -681,11 +675,9 @@
 	if (stable && !EX_WGATHER(exp))
 		file.f_flags |= O_SYNC;
 
-	file.f_pos = offset;		/* set write offset */
-
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
-	err = file.f_op->write(&file, buf, cnt, &file.f_pos);
+	err = vfs_write(&file, buf, cnt, &offset);
 	if (err >= 0)
 		nfsdstats.io_write += cnt;
 	set_fs(oldfs);
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Fri Oct 18 21:03:04 2002
+++ b/fs/partitions/check.c	Fri Oct 18 21:03:04 2002
@@ -289,13 +289,13 @@
 			char *page, size_t count, loff_t off)
 {
 	struct hd_struct *p = dev->driver_data;
-	return off ? 0 : sprintf(page, "%llu\n",(u64)p->start_sect);
+	return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
 }
 static ssize_t part_size_read(struct device *dev,
 			char *page, size_t count, loff_t off)
 {
 	struct hd_struct *p = dev->driver_data;
-	return off ? 0 : sprintf(page, "%llu\n",(u64)p->nr_sects);
+	return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
 }
 static struct device_attribute part_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
@@ -375,7 +375,7 @@
 			char *page, size_t count, loff_t off)
 {
 	struct gendisk *disk = dev->driver_data;
-	return off ? 0 : sprintf(page, "%llu\n",(u64)get_capacity(disk));
+	return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
 }
 static struct device_attribute disk_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
@@ -511,8 +511,8 @@
 	bdev->bd_invalidated = 0;
 	for (p = 1; p < disk->minors; p++)
 		delete_partition(disk, p);
-	if (bdev->bd_op->revalidate)
-		bdev->bd_op->revalidate(dev);
+	if (bdev->bd_op->revalidate_disk)
+		bdev->bd_op->revalidate_disk(disk);
 	if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
 		return res;
 	for (p = 1; p < state->limit; p++) {
@@ -522,9 +522,8 @@
 			continue;
 		add_partition(disk, p, from, size);
 #if CONFIG_BLK_DEV_MD
-		if (!state->parts[j].flags)
-			continue;
-		md_autodetect_dev(bdev->bd_dev+p);
+		if (state->parts[p].flags)
+			md_autodetect_dev(bdev->bd_dev+p);
 #endif
 	}
 	kfree(state);
diff -Nru a/fs/partitions/msdos.c b/fs/partitions/msdos.c
--- a/fs/partitions/msdos.c	Fri Oct 18 21:03:05 2002
+++ b/fs/partitions/msdos.c	Fri Oct 18 21:03:05 2002
@@ -28,7 +28,7 @@
 #elif defined(CONFIG_BLK_DEV_IDE_MODULE)
 #include <linux/module.h>
 
-int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *);
+int (*ide_xlate_1024_hook)(struct block_device *, int, int, const char *);
 EXPORT_SYMBOL(ide_xlate_1024_hook);
 #define ide_xlate_1024 ide_xlate_1024_hook
 #endif
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	Fri Oct 18 21:03:05 2002
+++ b/fs/read_write.c	Fri Oct 18 21:03:05 2002
@@ -121,12 +121,6 @@
 	if (!file)
 		goto bad;
 
-	retval = security_ops->file_llseek(file);
-	if (retval) {
-		fput(file);
-		goto bad;
-	}
-
 	retval = -EINVAL;
 	if (origin <= 2) {
 		loff_t res = llseek(file, offset, origin);
@@ -152,10 +146,6 @@
 	file = fget(fd);
 	if (!file)
 		goto bad;
-
-	retval = security_ops->file_llseek(file);
-	if (retval)
-		goto out_putf;
 
 	retval = -EINVAL;
 	if (origin > 2)
diff -Nru a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
--- a/fs/reiserfs/ioctl.c	Fri Oct 18 21:03:04 2002
+++ b/fs/reiserfs/ioctl.c	Fri Oct 18 21:03:04 2002
@@ -80,7 +80,6 @@
     /* conversion can change page contents, must flush */
     flush_dcache_page(page) ;
     REISERFS_I(inode)->i_flags |= i_nopack_mask;
-    kunmap(page) ; /* mapped by prepare_write */
 
 out_unlock:
     unlock_page(page) ;
diff -Nru a/fs/sysfs/Makefile b/fs/sysfs/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/sysfs/Makefile	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,9 @@
+#
+# Makefile for the sysfs virtual filesystem
+#
+
+export-objs	:= inode.o
+
+obj-y		:= inode.o
+
+include $(TOPDIR)/Rules.make
diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/sysfs/inode.c	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,642 @@
+/*
+ * sysfs.c - The filesystem to export kernel objects.
+ *
+ * Copyright (c) 2001, 2002 Patrick Mochel
+ *
+ *  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
+ *
+ * This is a simple, ramfs-based filesystem, designed to export kernel 
+ * objects, their attributes, and the linkgaes between each other.
+ *
+ * Please see Documentation/filesystems/sysfs.txt for more information.
+ */
+
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/stat.h>
+#include <linux/fs.h>
+#include <linux/dcache.h>
+#include <linux/namei.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/backing-dev.h>
+#include <linux/sysfs.h>
+
+#include <asm/uaccess.h>
+
+/* Random magic number */
+#define SYSFS_MAGIC 0x62656572
+
+static struct super_operations sysfs_ops;
+static struct file_operations sysfs_file_operations;
+static struct inode_operations sysfs_dir_inode_operations;
+static struct address_space_operations sysfs_aops;
+
+static struct vfsmount *sysfs_mount;
+
+static struct backing_dev_info sysfs_backing_dev_info = {
+	.ra_pages	= 0,	/* No readahead */
+	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+};
+
+static int sysfs_readpage(struct file *file, struct page * page)
+{
+	if (!PageUptodate(page)) {
+		void *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
+		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
+		SetPageUptodate(page);
+	}
+	unlock_page(page);
+	return 0;
+}
+
+static int sysfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+	if (!PageUptodate(page)) {
+		void *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
+		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
+		SetPageUptodate(page);
+	}
+	return 0;
+}
+
+static int sysfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+	struct inode *inode = page->mapping->host;
+	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+
+	set_page_dirty(page);
+	if (pos > inode->i_size)
+		inode->i_size = pos;
+	return 0;
+}
+
+
+static struct inode *sysfs_get_inode(struct super_block *sb, int mode, int dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = current->fsuid;
+		inode->i_gid = current->fsgid;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_rdev = NODEV;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inode->i_mapping->a_ops = &sysfs_aops;
+		inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+		switch (mode & S_IFMT) {
+		default:
+			init_special_inode(inode, mode, dev);
+			break;
+		case S_IFREG:
+			inode->i_fop = &sysfs_file_operations;
+			break;
+		case S_IFDIR:
+			inode->i_op = &sysfs_dir_inode_operations;
+			inode->i_fop = &simple_dir_operations;
+
+			/* directory inodes start off with i_nlink == 2 (for "." entry) */
+			inode->i_nlink++;
+			break;
+		case S_IFLNK:
+			inode->i_op = &page_symlink_inode_operations;
+			break;
+		}
+	}
+	return inode;
+}
+
+static int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
+{
+	struct inode *inode;
+	int error = 0;
+
+	if (!dentry->d_inode) {
+		inode = sysfs_get_inode(dir->i_sb, mode, dev);
+		if (inode)
+			d_instantiate(dentry, inode);
+		else
+			error = -ENOSPC;
+	} else
+		error = -EEXIST;
+	return error;
+}
+
+static int sysfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int res;
+	mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
+ 	res = sysfs_mknod(dir, dentry, mode, 0);
+ 	if (!res)
+ 		dir->i_nlink++;
+	return res;
+}
+
+static int sysfs_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int res;
+	mode = (mode & S_IALLUGO) | S_IFREG;
+ 	res = sysfs_mknod(dir, dentry, mode, 0);
+	return res;
+}
+
+static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
+{
+	struct inode *inode;
+	int error = -ENOSPC;
+
+	if (dentry->d_inode)
+		return -EEXIST;
+
+	inode = sysfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+	if (inode) {
+		int l = strlen(symname)+1;
+		error = page_symlink(inode, symname, l);
+		if (!error) {
+			d_instantiate(dentry, inode);
+			dget(dentry);
+		} else
+			iput(inode);
+	}
+	return error;
+}
+
+static inline int sysfs_positive(struct dentry *dentry)
+{
+	return (dentry->d_inode && !d_unhashed(dentry));
+}
+
+static int sysfs_empty(struct dentry *dentry)
+{
+	struct list_head *list;
+
+	spin_lock(&dcache_lock);
+
+	list_for_each(list, &dentry->d_subdirs) {
+		struct dentry *de = list_entry(list, struct dentry, d_child);
+		if (sysfs_positive(de)) {
+			spin_unlock(&dcache_lock);
+			return 0;
+		}
+	}
+
+	spin_unlock(&dcache_lock);
+	return 1;
+}
+
+static int sysfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+	down(&inode->i_sem);
+	dentry->d_inode->i_nlink--;
+	up(&inode->i_sem);
+	d_invalidate(dentry);
+	dput(dentry);
+	return 0;
+}
+
+/**
+ * sysfs_read_file - "read" data from a file.
+ * @file:	file pointer
+ * @buf:	buffer to fill
+ * @count:	number of bytes to read
+ * @ppos:	starting offset in file
+ *
+ * Userspace wants data from a file. It is up to the creator of the file to
+ * provide that data.
+ * There is a struct device_attribute embedded in file->private_data. We
+ * obtain that and check if the read callback is implemented. If so, we call
+ * it, passing the data field of the file entry.
+ * Said callback is responsible for filling the buffer and returning the number
+ * of bytes it put in it. We update @ppos correctly.
+ */
+static ssize_t
+sysfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	struct attribute * attr = file->f_dentry->d_fsdata;
+	struct driver_dir_entry * dir;
+	unsigned char *page;
+	ssize_t retval = 0;
+
+	dir = file->f_dentry->d_parent->d_fsdata;
+	if (!dir->ops->show)
+		return 0;
+
+	if (count > PAGE_SIZE)
+		count = PAGE_SIZE;
+
+	page = (unsigned char*)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	while (count > 0) {
+		ssize_t len;
+
+		len = dir->ops->show(dir,attr,page,count,*ppos);
+
+		if (len <= 0) {
+			if (len < 0)
+				retval = len;
+			break;
+		} else if (len > count)
+			len = count;
+
+		if (copy_to_user(buf,page,len)) {
+			retval = -EFAULT;
+			break;
+		}
+
+		*ppos += len;
+		count -= len;
+		buf += len;
+		retval += len;
+	}
+	free_page((unsigned long)page);
+	return retval;
+}
+
+/**
+ * sysfs_write_file - "write" to a file
+ * @file:	file pointer
+ * @buf:	data to write
+ * @count:	number of bytes
+ * @ppos:	starting offset
+ *
+ * Similarly to sysfs_read_file, we act essentially as a bit pipe.
+ * We check for a "write" callback in file->private_data, and pass
+ * @buffer, @count, @ppos, and the file entry's data to the callback.
+ * The number of bytes written is returned, and we handle updating
+ * @ppos properly.
+ */
+static ssize_t
+sysfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+	struct attribute * attr = file->f_dentry->d_fsdata;
+	struct driver_dir_entry * dir;
+	ssize_t retval = 0;
+	char * page;
+
+	dir = file->f_dentry->d_parent->d_fsdata;
+
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	if (count >= PAGE_SIZE)
+		count = PAGE_SIZE - 1;
+	if (copy_from_user(page,buf,count))
+		goto done;
+	*(page + count) = '\0';
+
+	while (count > 0) {
+		ssize_t len;
+
+		len = dir->ops->store(dir,attr,page + retval,count,*ppos);
+
+		if (len <= 0) {
+			if (len < 0)
+				retval = len;
+			break;
+		}
+		retval += len;
+		count -= len;
+		*ppos += len;
+		buf += len;
+	}
+ done:
+	free_page((unsigned long)page);
+	return retval;
+}
+
+static loff_t
+sysfs_file_lseek(struct file *file, loff_t offset, int orig)
+{
+	loff_t retval = -EINVAL;
+
+	down(&file->f_dentry->d_inode->i_sem);
+	switch(orig) {
+	case 0:
+		if (offset > 0) {
+			file->f_pos = offset;
+			retval = file->f_pos;
+		}
+		break;
+	case 1:
+		if ((offset + file->f_pos) > 0) {
+			file->f_pos += offset;
+			retval = file->f_pos;
+		}
+		break;
+	default:
+		break;
+	}
+	up(&file->f_dentry->d_inode->i_sem);
+	return retval;
+}
+
+static int sysfs_open_file(struct inode * inode, struct file * filp)
+{
+	struct driver_dir_entry * dir;
+	int error = 0;
+
+	dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
+	if (dir) {
+		struct attribute * attr = filp->f_dentry->d_fsdata;
+		if (attr && dir->ops) {
+			if (dir->ops->open)
+				error = dir->ops->open(dir);
+			goto Done;
+		}
+	}
+	error = -EINVAL;
+ Done:
+	return error;
+}
+
+static int sysfs_release(struct inode * inode, struct file * filp)
+{
+	struct driver_dir_entry * dir;
+	dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
+	if (dir->ops->close)
+		dir->ops->close(dir);
+	return 0;
+}
+
+static struct file_operations sysfs_file_operations = {
+	.read		= sysfs_read_file,
+	.write		= sysfs_write_file,
+	.llseek		= sysfs_file_lseek,
+	.open		= sysfs_open_file,
+	.release	= sysfs_release,
+};
+
+static struct inode_operations sysfs_dir_inode_operations = {
+	.lookup		= simple_lookup,
+};
+
+static struct address_space_operations sysfs_aops = {
+	.readpage	= sysfs_readpage,
+	.writepage	= fail_writepage,
+	.prepare_write	= sysfs_prepare_write,
+	.commit_write	= sysfs_commit_write
+};
+
+static struct super_operations sysfs_ops = {
+	.statfs		= simple_statfs,
+	.drop_inode	= generic_delete_inode,
+};
+
+static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct inode *inode;
+	struct dentry *root;
+
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = SYSFS_MAGIC;
+	sb->s_op = &sysfs_ops;
+	inode = sysfs_get_inode(sb, S_IFDIR | 0755, 0);
+
+	if (!inode) {
+		pr_debug("%s: could not get inode!\n",__FUNCTION__);
+		return -ENOMEM;
+	}
+
+	root = d_alloc_root(inode);
+	if (!root) {
+		pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
+		iput(inode);
+		return -ENOMEM;
+	}
+	sb->s_root = root;
+	return 0;
+}
+
+static struct super_block *sysfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, sysfs_fill_super);
+}
+
+static struct file_system_type sysfs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "sysfs",
+	.get_sb		= sysfs_get_sb,
+	.kill_sb	= kill_litter_super,
+};
+
+static int __init sysfs_init(void)
+{
+	int err;
+
+	err = register_filesystem(&sysfs_fs_type);
+	if (!err) {
+		sysfs_mount = kern_mount(&sysfs_fs_type);
+		if (IS_ERR(sysfs_mount)) {
+			printk(KERN_ERR "sysfs: could not mount!\n");
+			err = PTR_ERR(sysfs_mount);
+			sysfs_mount = NULL;
+		}
+	}
+	return err;
+}
+
+core_initcall(sysfs_init);
+
+static struct dentry * get_dentry(struct dentry * parent, const char * name)
+{
+	struct qstr qstr;
+
+	qstr.name = name;
+	qstr.len = strlen(name);
+	qstr.hash = full_name_hash(name,qstr.len);
+	return lookup_hash(&qstr,parent);
+}
+
+/**
+ * sysfs_create_dir - create a directory in the filesystem
+ * @entry:	directory entry
+ * @parent:	parent directory entry
+ */
+int
+sysfs_create_dir(struct driver_dir_entry * entry,
+		    struct driver_dir_entry * parent)
+{
+	struct dentry * dentry = NULL;
+	struct dentry * parent_dentry;
+	int error = 0;
+
+	if (!entry)
+		return -EINVAL;
+
+	parent_dentry = parent ? parent->dentry : NULL;
+
+	if (!parent_dentry)
+		if (sysfs_mount && sysfs_mount->mnt_sb)
+			parent_dentry = sysfs_mount->mnt_sb->s_root;
+
+	if (!parent_dentry)
+		return -EFAULT;
+
+	down(&parent_dentry->d_inode->i_sem);
+	dentry = get_dentry(parent_dentry,entry->name);
+	if (!IS_ERR(dentry)) {
+		dentry->d_fsdata = (void *) entry;
+		entry->dentry = dentry;
+		error = sysfs_mkdir(parent_dentry->d_inode,dentry,entry->mode);
+	} else
+		error = PTR_ERR(dentry);
+	up(&parent_dentry->d_inode->i_sem);
+
+	return error;
+}
+
+/**
+ * sysfs_create_file - create a file
+ * @entry:	structure describing the file
+ * @parent:	directory to create it in
+ */
+int
+sysfs_create_file(struct attribute * entry,
+		     struct driver_dir_entry * parent)
+{
+	struct dentry * dentry;
+	int error = 0;
+
+	if (!entry || !parent)
+		return -EINVAL;
+
+	if (!parent->dentry)
+		return -EINVAL;
+
+	down(&parent->dentry->d_inode->i_sem);
+	dentry = get_dentry(parent->dentry,entry->name);
+	if (!IS_ERR(dentry)) {
+		dentry->d_fsdata = (void *)entry;
+		error = sysfs_create(parent->dentry->d_inode,dentry,entry->mode);
+	} else
+		error = PTR_ERR(dentry);
+	up(&parent->dentry->d_inode->i_sem);
+	return error;
+}
+
+/**
+ * sysfs_create_symlink - make a symlink
+ * @parent:	directory we're creating in 
+ * @entry:	entry describing link
+ * @target:	place we're symlinking to
+ * 
+ */
+int sysfs_create_symlink(struct driver_dir_entry * parent, 
+			    char * name, char * target)
+{
+	struct dentry * dentry;
+	int error = 0;
+
+	if (!parent || !parent->dentry)
+		return -EINVAL;
+
+	down(&parent->dentry->d_inode->i_sem);
+	dentry = get_dentry(parent->dentry,name);
+	if (!IS_ERR(dentry))
+		error = sysfs_symlink(parent->dentry->d_inode,dentry,target);
+	else
+		error = PTR_ERR(dentry);
+	up(&parent->dentry->d_inode->i_sem);
+	return error;
+}
+
+/**
+ * sysfs_remove_file - exported file removal
+ * @dir:	directory the file supposedly resides in
+ * @name:	name of the file
+ *
+ * Try and find the file in the dir's list.
+ * If it's there, call __remove_file() (above) for the dentry.
+ */
+void sysfs_remove_file(struct driver_dir_entry * dir, const char * name)
+{
+	struct dentry * dentry;
+
+	if (!dir->dentry)
+		return;
+
+	down(&dir->dentry->d_inode->i_sem);
+	dentry = get_dentry(dir->dentry,name);
+	if (!IS_ERR(dentry)) {
+		/* make sure dentry is really there */
+		if (dentry->d_inode && 
+		    (dentry->d_parent->d_inode == dir->dentry->d_inode)) {
+			sysfs_unlink(dir->dentry->d_inode,dentry);
+		}
+	}
+	up(&dir->dentry->d_inode->i_sem);
+}
+
+/**
+ * sysfs_remove_dir - exportable directory removal
+ * @dir:	directory to remove
+ *
+ * To make sure we don't orphan anyone, first remove
+ * all the children in the list, then do clean up the directory.
+ */
+void sysfs_remove_dir(struct driver_dir_entry * dir)
+{
+	struct list_head * node, * next;
+	struct dentry * dentry = dir->dentry;
+	struct dentry * parent;
+
+	if (!dentry)
+		return;
+
+	parent = dget(dentry->d_parent);
+	down(&parent->d_inode->i_sem);
+	down(&dentry->d_inode->i_sem);
+
+	list_for_each_safe(node,next,&dentry->d_subdirs) {
+		struct dentry * d = list_entry(node,struct dentry,d_child);
+		/* make sure dentry is still there */
+		if (d->d_inode)
+			sysfs_unlink(dentry->d_inode,d);
+	}
+
+	d_invalidate(dentry);
+	if (sysfs_empty(dentry)) {
+		dentry->d_inode->i_nlink -= 2;
+		dentry->d_inode->i_flags |= S_DEAD;
+		parent->d_inode->i_nlink--;
+	}
+	up(&dentry->d_inode->i_sem);
+	dput(dentry);
+
+	up(&parent->d_inode->i_sem);
+	dput(parent);
+}
+
+EXPORT_SYMBOL(sysfs_create_file);
+EXPORT_SYMBOL(sysfs_create_symlink);
+EXPORT_SYMBOL(sysfs_create_dir);
+EXPORT_SYMBOL(sysfs_remove_file);
+EXPORT_SYMBOL(sysfs_remove_dir);
+MODULE_LICENSE("GPL");
diff -Nru a/fs/xfs/Makefile b/fs/xfs/Makefile
--- a/fs/xfs/Makefile	Fri Oct 18 21:03:07 2002
+++ b/fs/xfs/Makefile	Fri Oct 18 21:03:07 2002
@@ -32,7 +32,8 @@
 # Makefile for XFS on Linux.
 #
 
-# This needs -I because everything does #include <xfs.h> instead of "xfs.h".
+
+# This needs -I. because everything does #include <xfs.h> instead of "xfs.h".
 # The code is wrong, local files should be included using "xfs.h", not <xfs.h>
 # but I am not going to change every file at the moment.
 EXTRA_CFLAGS +=	 -Ifs/xfs -funsigned-char
diff -Nru a/fs/xfs/linux/xfs_file.c b/fs/xfs/linux/xfs_file.c
--- a/fs/xfs/linux/xfs_file.c	Fri Oct 18 21:03:04 2002
+++ b/fs/xfs/linux/xfs_file.c	Fri Oct 18 21:03:04 2002
@@ -113,6 +113,32 @@
 }
 
 
+STATIC ssize_t
+linvfs_aio_read(
+	struct kiocb		*iocb,
+	char			*buf,
+	size_t			count,
+	loff_t			pos)
+{
+	struct iovec		iov = {buf, count};
+
+	return linvfs_readv(iocb->ki_filp, &iov, 1, &iocb->ki_pos);
+}
+
+
+STATIC ssize_t
+linvfs_aio_write(
+	struct kiocb		*iocb,
+	const char		*buf,
+	size_t			count,
+	loff_t			pos)
+{
+	struct iovec		iov = {(void *)buf, count};
+
+	return linvfs_writev(iocb->ki_filp, &iov, 1, &iocb->ki_pos);
+}
+
+
 STATIC int
 linvfs_open(
 	struct inode	*inode,
@@ -320,6 +346,8 @@
 	.write		= linvfs_write,
 	.readv		= linvfs_readv,
 	.writev		= linvfs_writev,
+	.aio_read	= linvfs_aio_read,
+	.aio_write	= linvfs_aio_write,
 	.ioctl		= linvfs_ioctl,
 	.mmap		= linvfs_file_mmap,
 	.open		= linvfs_open,
diff -Nru a/fs/xfs/linux/xfs_globals.c b/fs/xfs/linux/xfs_globals.c
--- a/fs/xfs/linux/xfs_globals.c	Fri Oct 18 21:03:05 2002
+++ b/fs/xfs/linux/xfs_globals.c	Fri Oct 18 21:03:05 2002
@@ -64,5 +64,6 @@
 EXPORT_SYMBOL(xfs_next_bit);
 EXPORT_SYMBOL(xfs_contig_bits);
 EXPORT_SYMBOL(xfs_bmbt_get_all);
+#if ARCH_CONVERT != ARCH_NOCONVERT
 EXPORT_SYMBOL(xfs_bmbt_disk_get_all);
-
+#endif
diff -Nru a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
--- a/fs/xfs/xfs_alloc.c	Fri Oct 18 21:03:03 2002
+++ b/fs/xfs/xfs_alloc.c	Fri Oct 18 21:03:04 2002
@@ -2135,19 +2135,6 @@
 		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
 		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
 			sizeof(xfs_agblock_t) - 1));
-	/*
-	 * Since blocks move to the free list without the coordination
-	 * used in xfs_bmap_finish, we can't allow block to be available
-	 * for reallocation and non-transaction writing (user data)
-	 * until we know that the transaction that moved it to the free
-	 * list is permanently on disk.	 We track the blocks by declaring
-	 * these blocks as "busy"; the busy list is maintained on a per-ag
-	 * basis and each transaction records which entries should be removed
-	 * when the iclog commits to disk.  If a busy block is allocated,
-	 * the iclog is pushed up to the LSN that freed the block.
-	 */
-	xfs_alloc_mark_busy(tp, INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
-
 	return 0;
 }
 
diff -Nru a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
--- a/fs/xfs/xfs_alloc_btree.c	Fri Oct 18 21:03:05 2002
+++ b/fs/xfs/xfs_alloc_btree.c	Fri Oct 18 21:03:05 2002
@@ -223,6 +223,23 @@
 			if ((error = xfs_alloc_put_freelist(cur->bc_tp,
 					cur->bc_private.a.agbp, NULL, bno)))
 				return error;
+			/*
+			 * Since blocks move to the free list without the
+			 * coordination used in xfs_bmap_finish, we can't allow
+			 * block to be available for reallocation and
+			 * non-transaction writing (user data) until we know
+			 * that the transaction that moved it to the free list
+			 * is permanently on disk. We track the blocks by
+			 * declaring these blocks as "busy"; the busy list is
+			 * maintained on a per-ag basis and each transaction
+			 * records which entries should be removed when the
+			 * iclog commits to disk. If a busy block is
+			 * allocated, the iclog is pushed up to the LSN
+			 * that freed the block.
+			 */
+			xfs_alloc_mark_busy(cur->bc_tp,
+				INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
+
 			xfs_trans_agbtree_delta(cur->bc_tp, -1);
 			xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
 				XFS_AGF_ROOTS | XFS_AGF_LEVELS);
@@ -528,6 +545,21 @@
 	if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
 			NULL, rbno)))
 		return error;
+	/*
+	 * Since blocks move to the free list without the coordination
+	 * used in xfs_bmap_finish, we can't allow block to be available
+	 * for reallocation and non-transaction writing (user data)
+	 * until we know that the transaction that moved it to the free
+	 * list is permanently on disk. We track the blocks by declaring
+	 * these blocks as "busy"; the busy list is maintained on a
+	 * per-ag basis and each transaction records which entries
+	 * should be removed when the iclog commits to disk. If a
+	 * busy block is allocated, the iclog is pushed up to the
+	 * LSN that freed the block.
+	 */
+	xfs_alloc_mark_busy(cur->bc_tp,
+		INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
+
 	xfs_trans_agbtree_delta(cur->bc_tp, -1);
 	/*
 	 * Adjust the current level's cursor so that we're left referring
diff -Nru a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
--- a/fs/xfs/xfs_bmap_btree.c	Fri Oct 18 21:03:04 2002
+++ b/fs/xfs/xfs_bmap_btree.c	Fri Oct 18 21:03:04 2002
@@ -253,11 +253,7 @@
 	xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
 		(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
 		cur->bc_private.b.allocated,
-#if BMBT_USE_64
 		INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
-#else
-		INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT), INT_GET(r.l2, ARCH_CONVERT), INT_GET(r.l3, ARCH_CONVERT),
-#endif
 		(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
 		(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
 		(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
diff -Nru a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
--- a/fs/xfs/xfs_bmap_btree.h	Fri Oct 18 21:03:04 2002
+++ b/fs/xfs/xfs_bmap_btree.h	Fri Oct 18 21:03:04 2002
@@ -658,8 +658,8 @@
 #else
 #define xfs_bmbt_disk_set_all(r, s) \
 	xfs_bmbt_set_all(r, s)
-#define xfs_bmbt_disk_set_allf(r, 0, b, c, v) \
-	xfs_bmbt_set_allf(r, 0, b, c, v)
+#define xfs_bmbt_disk_set_allf(r, o, b, c, v) \
+	xfs_bmbt_set_allf(r, o, b, c, v)
 #endif
 
 void
diff -Nru a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
--- a/fs/xfs/xfs_inode.c	Fri Oct 18 21:03:04 2002
+++ b/fs/xfs/xfs_inode.c	Fri Oct 18 21:03:04 2002
@@ -602,9 +602,12 @@
 	int		whichfork)
 {
 	xfs_ifork_t	*ifp;
-	int		nex, i;
+	int		nex;
 	int		real_size;
 	int		size;
+#if ARCH_CONVERT != ARCH_NOCONVERT
+	int		i;
+#endif
 	xfs_bmbt_rec_t	*ep, *dp;
 
 	ifp = XFS_IFORK_PTR(ip, whichfork);
diff -Nru a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
--- a/fs/xfs/xfs_inode_item.h	Fri Oct 18 21:03:08 2002
+++ b/fs/xfs/xfs_inode_item.h	Fri Oct 18 21:03:08 2002
@@ -126,7 +126,7 @@
 #ifdef __KERNEL__
 
 struct xfs_buf;
-struct xfs_bmbt_rec_32;
+struct xfs_bmbt_rec_64;
 struct xfs_inode;
 struct xfs_mount;
 
@@ -141,9 +141,9 @@
 	unsigned short		ili_flags;	   /* misc flags */
 	unsigned short		ili_logged;	   /* flushed logged data */
 	unsigned int		ili_last_fields;   /* fields when flushed */
-	struct xfs_bmbt_rec_32	*ili_extents_buf;  /* array of logged
+	struct xfs_bmbt_rec_64	*ili_extents_buf;  /* array of logged
 						      data exts */
-	struct xfs_bmbt_rec_32	*ili_aextents_buf; /* array of logged
+	struct xfs_bmbt_rec_64	*ili_aextents_buf; /* array of logged
 						      attr exts */
 	unsigned int		ili_pushbuf_flag;  /* one bit used in push_ail */
 
diff -Nru a/include/asm-alpha/checksum.h b/include/asm-alpha/checksum.h
--- a/include/asm-alpha/checksum.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-alpha/checksum.h	Fri Oct 18 21:03:03 2002
@@ -43,20 +43,6 @@
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
-
-/*
- * the same as csum_partial, but copies from user space (but on the alpha
- * we have just one address space, so this is identical to the above)
- *
- * this is obsolete and will go away.
- */
-#define csum_partial_copy_fromuser csum_partial_copy
-
-/*
- * this is a new version of the above that records errors it finds in *errp,
- * but continues and zeros the rest of the buffer.
- */
 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
 
 unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum);
diff -Nru a/include/asm-alpha/system.h b/include/asm-alpha/system.h
--- a/include/asm-alpha/system.h	Fri Oct 18 21:03:05 2002
+++ b/include/asm-alpha/system.h	Fri Oct 18 21:03:05 2002
@@ -151,14 +151,19 @@
 #define wmb() \
 __asm__ __volatile__("wmb": : :"memory")
 
+#define read_barrier_depends() \
+__asm__ __volatile__("mb": : :"memory")
+
 #ifdef CONFIG_SMP
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
 #else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	barrier()
 #endif
 
 #define set_mb(var, value) \
diff -Nru a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
--- a/include/asm-arm/checksum.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-arm/checksum.h	Fri Oct 18 21:03:08 2002
@@ -38,10 +38,10 @@
 csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
 
 /*
- * These are the old (and unsafe) way of doing checksums, a warning message will be
- * printed if they are used and an exception occurs.
+ * This is the old (and unsafe) way of doing checksums, a warning message will
+ * be printed if it is used and an exception occurs.
  *
- * these functions should go away after some time.
+ * this functions should go away after some time.
  */
 #define csum_partial_copy(src,dst,len,sum)	csum_partial_copy_nocheck(src,dst,len,sum)
 
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-arm/system.h	Fri Oct 18 21:03:03 2002
@@ -52,6 +52,9 @@
 #define mb() __asm__ __volatile__ ("" : : : "memory")
 #define rmb() mb()
 #define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value)  do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
 #define prepare_to_switch()    do { } while(0)
@@ -76,12 +79,14 @@
 #define smp_mb()		mb()
 #define smp_rmb()		rmb()
 #define smp_wmb()		wmb()
+#define smp_read_barrier_depends()		read_barrier_depends()
 
 #else
 
 #define smp_mb()		barrier()
 #define smp_rmb()		barrier()
 #define smp_wmb()		barrier()
+#define smp_read_barrier_depends()		do { } while(0)
 
 #define clf()			__clf()
 #define stf()			__stf()
diff -Nru a/include/asm-cris/system.h b/include/asm-cris/system.h
--- a/include/asm-cris/system.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-cris/system.h	Fri Oct 18 21:03:04 2002
@@ -150,15 +150,20 @@
 #define mb() __asm__ __volatile__ ("" : : : "memory")
 #define rmb() mb()
 #define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value)  do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 #ifdef CONFIG_SMP
 #define smp_mb()        mb()
 #define smp_rmb()       rmb()
 #define smp_wmb()       wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
 #else
 #define smp_mb()        barrier()
 #define smp_rmb()       barrier()
 #define smp_wmb()       barrier()
+#define smp_read_barrier_depends()     do { } while(0)
 #endif
 
 #define iret()
diff -Nru a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
--- a/include/asm-generic/siginfo.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-generic/siginfo.h	Fri Oct 18 21:03:04 2002
@@ -8,9 +8,21 @@
 	void *sival_ptr;
 } sigval_t;
 
+/*
+ * This is the size (including padding) of the part of the
+ * struct siginfo that is before the union.
+ */
+#ifndef __ARCH_SI_PREAMBLE_SIZE
+#define __ARCH_SI_PREAMBLE_SIZE	(3 * sizeof(int))
+#endif
+
 #define SI_MAX_SIZE	128
 #ifndef SI_PAD_SIZE
-#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+#define SI_PAD_SIZE	((SI_MAX_SIZE - __ARCH_SI_PREAMBLE_SIZE) / sizeof(int))
+#endif
+
+#ifndef __ARCH_SI_UID_T
+#define __ARCH_SI_UID_T	uid_t
 #endif
 
 #ifndef HAVE_ARCH_SIGINFO_T
@@ -26,7 +38,7 @@
 		/* kill() */
 		struct {
 			pid_t _pid;		/* sender's pid */
-			uid_t _uid;		/* sender's uid */
+			__ARCH_SI_UID_T _uid;	/* sender's uid */
 		} _kill;
 
 		/* POSIX.1b timers */
@@ -38,14 +50,14 @@
 		/* POSIX.1b signals */
 		struct {
 			pid_t _pid;		/* sender's pid */
-			uid_t _uid;		/* sender's uid */
+			__ARCH_SI_UID_T _uid;	/* sender's uid */
 			sigval_t _sigval;
 		} _rt;
 
 		/* SIGCHLD */
 		struct {
 			pid_t _pid;		/* which child */
-			uid_t _uid;		/* sender's uid */
+			__ARCH_SI_UID_T _uid;	/* sender's uid */
 			int _status;		/* exit code */
 			clock_t _utime;
 			clock_t _stime;
@@ -54,6 +66,9 @@
 		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
 		struct {
 			void *_addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+			int _trapno;	/* TRAP # which caused the signal */
+#endif
 		} _sigfault;
 
 		/* SIGPOLL */
@@ -80,6 +95,9 @@
 #define si_int		_sifields._rt._sigval.sival_int
 #define si_ptr		_sifields._rt._sigval.sival_ptr
 #define si_addr		_sifields._sigfault._addr
+#ifdef __ARCH_SI_TRAPNO
+#define si_trapno	_sifields._sigfault._trapno
+#endif
 #define si_band		_sifields._sigpoll._band
 #define si_fd		_sifields._sigpoll._fd
 
@@ -244,7 +262,7 @@
 		memcpy(to, from, sizeof(*to));
 	else
 		/* _sigchld is currently the largest know union member */
-		memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
+		memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
 }
 
 #endif
diff -Nru a/include/asm-i386/apic.h b/include/asm-i386/apic.h
--- a/include/asm-i386/apic.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-i386/apic.h	Fri Oct 18 21:03:08 2002
@@ -7,8 +7,6 @@
 #include <asm/apicdef.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_X86_LOCAL_APIC
-
 #define APIC_DEBUG 0
 
 #if APIC_DEBUG
@@ -16,6 +14,8 @@
 #else
 #define Dprintk(x...)
 #endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
 
 /*
  * Basic functions accessing APICs.
diff -Nru a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
--- a/include/asm-i386/checksum.h	Fri Oct 18 21:03:07 2002
+++ b/include/asm-i386/checksum.h	Fri Oct 18 21:03:07 2002
@@ -50,16 +50,6 @@
 }
 
 /*
- * These are the old (and unsafe) way of doing checksums, a warning message will be
- * printed if they are used and an exeption occurs.
- *
- * these functions should go away after some time.
- */
-
-#define csum_partial_copy_fromuser csum_partial_copy
-unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
-
-/*
  *	This is a version of ip_compute_csum() optimized for IP headers,
  *	which always checksum on 4 octet boundaries.
  *
diff -Nru a/include/asm-i386/edd.h b/include/asm-i386/edd.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/edd.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,168 @@
+/*
+ * linux/include/asm-i386/edd.h
+ *  Copyright (C) 2002 Dell Computer Corporation
+ *  by Matt Domsch <Matt_Domsch@dell.com>
+ *
+ * structures and definitions for the int 13h, ax={41,48}h
+ * BIOS Enhanced Disk Drive Services
+ * This is based on the T13 group document D1572 Revision 0 (August 14 2002)
+ * available at http://www.t13.org/docs2002/d1572r0.pdf.  It is
+ * very similar to D1484 Revision 3 http://www.t13.org/docs2002/d1484r3.pdf
+ *
+ * In a nutshell, arch/i386/boot/setup.S populates a scratch table
+ * in the empty_zero_block that contains a list of BIOS-enumerated
+ * boot devices.
+ * In arch/i386/kernel/setup.c, this information is
+ * transferred into the edd structure, and in arch/i386/kernel/edd.c, that
+ * information is used to identify BIOS boot disk.  The code in setup.S
+ * is very sensitive to the size of these structures.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * 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.
+ *
+ */
+#ifndef _ASM_I386_EDD_H
+#define _ASM_I386_EDD_H
+
+#define EDDNR 0x1e9		/* addr of number of edd_info structs at EDDBUF
+				   in empty_zero_block - treat this as 1 byte  */
+#define EDDBUF	0x600		/* addr of edd_info structs in empty_zero_block */
+#define EDDMAXNR 6		/* number of edd_info structs starting at EDDBUF  */
+#define EDDEXTSIZE 4		/* change these if you muck with the structures */
+#define EDDPARMSIZE 74
+
+#ifndef __ASSEMBLY__
+
+#define EDD_EXT_FIXED_DISK_ACCESS           (1 << 0)
+#define EDD_EXT_DEVICE_LOCKING_AND_EJECTING (1 << 1)
+#define EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT (1 << 2)
+#define EDD_EXT_64BIT_EXTENSIONS            (1 << 3)
+
+#define EDD_INFO_DMA_BOUNDRY_ERROR_TRANSPARENT (1 << 0)
+#define EDD_INFO_GEOMETRY_VALID                (1 << 1)
+#define EDD_INFO_REMOVABLE                     (1 << 2)
+#define EDD_INFO_WRITE_VERIFY                  (1 << 3)
+#define EDD_INFO_MEDIA_CHANGE_NOTIFICATION     (1 << 4)
+#define EDD_INFO_LOCKABLE                      (1 << 5)
+#define EDD_INFO_NO_MEDIA_PRESENT              (1 << 6)
+#define EDD_INFO_USE_INT13_FN50                (1 << 7)
+
+struct edd_device_params {
+	u16 length;
+	u16 info_flags;
+	u32 num_default_cylinders;
+	u32 num_default_heads;
+	u32 sectors_per_track;
+	u64 number_of_sectors;
+	u16 bytes_per_sector;
+	u32 dpte_ptr;		/* 0xFFFFFFFF for our purposes */
+	u16 key;		/* = 0xBEDD */
+	u8 device_path_info_length;	/* = 44 */
+	u8 reserved2;
+	u16 reserved3;
+	u8 host_bus_type[4];
+	u8 interface_type[8];
+	union {
+		struct {
+			u16 base_address;
+			u16 reserved1;
+			u32 reserved2;
+		} __attribute__ ((packed)) isa;
+		struct {
+			u8 bus;
+			u8 slot;
+			u8 function;
+			u8 channel;
+			u32 reserved;
+		} __attribute__ ((packed)) pci;
+		/* pcix is same as pci */
+		struct {
+			u64 reserved;
+		} __attribute__ ((packed)) ibnd;
+		struct {
+			u64 reserved;
+		} __attribute__ ((packed)) xprs;
+		struct {
+			u64 reserved;
+		} __attribute__ ((packed)) htpt;
+		struct {
+			u64 reserved;
+		} __attribute__ ((packed)) unknown;
+	} interface_path;
+	union {
+		struct {
+			u8 device;
+			u8 reserved1;
+			u16 reserved2;
+			u32 reserved3;
+			u64 reserved4;
+		} __attribute__ ((packed)) ata;
+		struct {
+			u8 device;
+			u8 lun;
+			u8 reserved1;
+			u8 reserved2;
+			u32 reserved3;
+			u64 reserved4;
+		} __attribute__ ((packed)) atapi;
+		struct {
+			u16 id;
+			u64 lun;
+			u16 reserved1;
+			u32 reserved2;
+		} __attribute__ ((packed)) scsi;
+		struct {
+			u64 serial_number;
+			u64 reserved;
+		} __attribute__ ((packed)) usb;
+		struct {
+			u64 eui;
+			u64 reserved;
+		} __attribute__ ((packed)) i1394;
+		struct {
+			u64 wwid;
+			u64 lun;
+		} __attribute__ ((packed)) fibre;
+		struct {
+			u64 identity_tag;
+			u64 reserved;
+		} __attribute__ ((packed)) i2o;
+		struct {
+			u32 array_number;
+			u32 reserved1;
+			u64 reserved2;
+		} __attribute((packed)) raid;
+		struct {
+			u8 device;
+			u8 reserved1;
+			u16 reserved2;
+			u32 reserved3;
+			u64 reserved4;
+		} __attribute__ ((packed)) sata;
+		struct {
+			u64 reserved1;
+			u64 reserved2;
+		} __attribute__ ((packed)) unknown;
+	} device_path;
+	u8 reserved4;
+	u8 checksum;
+} __attribute__ ((packed));
+
+struct edd_info {
+	u8 device;
+	u8 version;
+	u16 interface_support;
+	struct edd_device_params params;
+} __attribute__ ((packed));
+
+extern struct edd_info edd[EDDNR];
+extern unsigned char eddnr;
+#endif				/*!__ASSEMBLY__ */
+
+#endif				/* _ASM_I386_EDD_H */
diff -Nru a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
--- a/include/asm-i386/highmem.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-i386/highmem.h	Fri Oct 18 21:03:03 2002
@@ -52,88 +52,11 @@
 extern void * FASTCALL(kmap_high(struct page *page));
 extern void FASTCALL(kunmap_high(struct page *page));
 
-static inline void *kmap(struct page *page)
-{
-	if (in_interrupt())
-		BUG();
-	if (page < highmem_start_page)
-		return page_address(page);
-	return kmap_high(page);
-}
-
-static inline void kunmap(struct page *page)
-{
-	if (in_interrupt())
-		BUG();
-	if (page < highmem_start_page)
-		return;
-	kunmap_high(page);
-}
-
-/*
- * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
- * gives a more generic (and caching) interface. But kmap_atomic can
- * be used in IRQ contexts, so in some (very limited) cases we need
- * it.
- */
-static inline void *kmap_atomic(struct page *page, enum km_type type)
-{
-	enum fixed_addresses idx;
-	unsigned long vaddr;
-
-	inc_preempt_count();
-	if (page < highmem_start_page)
-		return page_address(page);
-
-	idx = type + KM_TYPE_NR*smp_processor_id();
-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#if CONFIG_DEBUG_HIGHMEM
-	if (!pte_none(*(kmap_pte-idx)))
-		BUG();
-#endif
-	set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
-	__flush_tlb_one(vaddr);
-
-	return (void*) vaddr;
-}
-
-static inline void kunmap_atomic(void *kvaddr, enum km_type type)
-{
-#if CONFIG_DEBUG_HIGHMEM
-	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
-
-	if (vaddr < FIXADDR_START) { // FIXME
-		dec_preempt_count();
-		return;
-	}
-
-	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
-		BUG();
-
-	/*
-	 * force other mappings to Oops if they'll try to access
-	 * this pte without first remap it
-	 */
-	pte_clear(kmap_pte-idx);
-	__flush_tlb_one(vaddr);
-#endif
-
-	dec_preempt_count();
-}
-
-static inline struct page *kmap_atomic_to_page(void *ptr)
-{
-	unsigned long idx, vaddr = (unsigned long)ptr;
-	pte_t *pte;
-
-	if (vaddr < FIXADDR_START)
-		return virt_to_page(ptr);
-
-	idx = virt_to_fix(vaddr);
-	pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
-	return pte_page(*pte);
-}
+void *kmap(struct page *page);
+void kunmap(struct page *page);
+void *kmap_atomic(struct page *page, enum km_type type);
+void kunmap_atomic(void *kvaddr, enum km_type type);
+struct page *kmap_atomic_to_page(void *ptr);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
--- a/include/asm-i386/io_apic.h	Fri Oct 18 21:03:06 2002
+++ b/include/asm-i386/io_apic.h	Fri Oct 18 21:03:06 2002
@@ -22,9 +22,12 @@
  * The structure of the IO-APIC:
  */
 struct IO_APIC_reg_00 {
-	__u32	__reserved_2	: 24,
+	__u32	__reserved_2	: 14,
+		LTS		:  1,
+		delivery_type	:  1,
+		__reserved_1	:  8,
 		ID		:  4,
-		__reserved_1	:  4;
+		__reserved_0	:  4;
 } __attribute__ ((packed));
 
 struct IO_APIC_reg_01 {
diff -Nru a/include/asm-i386/setup.h b/include/asm-i386/setup.h
--- a/include/asm-i386/setup.h	Fri Oct 18 21:03:06 2002
+++ b/include/asm-i386/setup.h	Fri Oct 18 21:03:06 2002
@@ -37,6 +37,8 @@
 #define KERNEL_START (*(unsigned long *) (PARAM+0x214))
 #define INITRD_START (*(unsigned long *) (PARAM+0x218))
 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
+#define EDD_NR     (*(unsigned char *) (PARAM+EDDNR))
+#define EDD_BUF     ((struct edd_info *) (PARAM+EDDBUF))
 #define COMMAND_LINE ((char *) (PARAM+2048))
 #define COMMAND_LINE_SIZE 256
 
diff -Nru a/include/asm-i386/smp.h b/include/asm-i386/smp.h
--- a/include/asm-i386/smp.h	Fri Oct 18 21:03:05 2002
+++ b/include/asm-i386/smp.h	Fri Oct 18 21:03:05 2002
@@ -37,6 +37,7 @@
  #endif /* CONFIG_CLUSTERED_APIC */
 #endif 
 
+#define BAD_APICID 0xFFu
 #ifdef CONFIG_SMP
 #ifndef __ASSEMBLY__
 
@@ -65,7 +66,6 @@
  * the real APIC ID <-> CPU # mapping.
  */
 #define MAX_APICID 256
-#define BAD_APICID 0xFFu
 extern volatile int cpu_to_physical_apicid[NR_CPUS];
 extern volatile int physical_apicid_to_cpu[MAX_APICID];
 extern volatile int cpu_to_logical_apicid[NR_CPUS];
diff -Nru a/include/asm-i386/system.h b/include/asm-i386/system.h
--- a/include/asm-i386/system.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-i386/system.h	Fri Oct 18 21:03:03 2002
@@ -286,6 +286,60 @@
 #define mb() 	__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
 #define rmb()	mb()
 
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	b = 2;
+ *	memory_barrier();
+ *	p = &b;				q = p;
+ *					read_barrier_depends();
+ *					d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	a = 2;
+ *	memory_barrier();
+ *	b = 3;				y = b;
+ *					read_barrier_depends();
+ *					x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like thiswhere there are no data dependencies.
+ **/
+
+#define read_barrier_depends()	do { } while(0)
+
 #ifdef CONFIG_X86_OOSTORE
 #define wmb() 	__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
 #else
@@ -296,13 +350,16 @@
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
+#define set_mb(var, value) do { xchg(&var, value); } while (0)
 #else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while(0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
 #endif
 
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 /* interrupt control.. */
diff -Nru a/include/asm-ia64/checksum.h b/include/asm-ia64/checksum.h
--- a/include/asm-ia64/checksum.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ia64/checksum.h	Fri Oct 18 21:03:03 2002
@@ -49,22 +49,6 @@
  * Here it is even more important to align src and dst on a 32-bit (or
  * even better 64-bit) boundary.
  */
-extern unsigned int csum_partial_copy (const char *src, char *dst, int len,
-				       unsigned int sum);
-
-/*
- * The same as csum_partial, but copies from user space (but on the
- * ia-64 we have just one address space, so this is identical to the
- * above).
- *
- * This is obsolete and will go away.
- */
-#define csum_partial_copy_fromuser csum_partial_copy
-
-/*
- * This is a new version of the above that records errors it finds in
- * *errp, but continues and zeros the rest of the buffer.
- */
 extern unsigned int csum_partial_copy_from_user (const char *src, char *dst,
 						 int len, unsigned int sum,
 						 int *errp);
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ia64/system.h	Fri Oct 18 21:03:04 2002
@@ -85,15 +85,18 @@
 #define mb()	__asm__ __volatile__ ("mf" ::: "memory")
 #define rmb()	mb()
 #define wmb()	mb()
+#define read_barrier_depends()	do { } while(0)
 
 #ifdef CONFIG_SMP
 # define smp_mb()	mb()
 # define smp_rmb()	rmb()
 # define smp_wmb()	wmb()
+# define smp_read_barrier_depends()	read_barrier_depends()
 #else
 # define smp_mb()	barrier()
 # define smp_rmb()	barrier()
 # define smp_wmb()	barrier()
+# define smp_read_barrier_depends()	do { } while(0)
 #endif
 
 /*
diff -Nru a/include/asm-m68k/checksum.h b/include/asm-m68k/checksum.h
--- a/include/asm-m68k/checksum.h	Fri Oct 18 21:03:05 2002
+++ b/include/asm-m68k/checksum.h	Fri Oct 18 21:03:05 2002
@@ -23,16 +23,6 @@
  * better 64-bit) boundary
  */
 
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
-
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
 extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
 						int len, int sum, int *csum_err);
 
diff -Nru a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
--- a/include/asm-mips/checksum.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-mips/checksum.h	Fri Oct 18 21:03:03 2002
@@ -28,12 +28,6 @@
  * this is a new version of the above that records errors it finds in *errp,
  * but continues and zeros the rest of the buffer.
  */
-#define csum_partial_copy_nocheck csum_partial_copy
-
-/*
- * this is a new version of the above that records errors it finds in *errp,
- * but continues and zeros the rest of the buffer.
- */
 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
                                          unsigned int sum, int *errp);
 
@@ -58,12 +52,9 @@
 /*
  * the same as csum_partial, but copies from user space (but on MIPS
  * we have just one address space, so this is identical to the above)
- *
- * this is obsolete and will go away.
  */
-#define csum_partial_copy_fromuser csum_partial_copy
-unsigned int csum_partial_copy(const char *src, char *dst, int len,
-			       unsigned int sum);
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len,
+				       unsigned int sum);
 
 /*
  *	Fold a partial checksum without adding pseudo headers
diff -Nru a/include/asm-mips/system.h b/include/asm-mips/system.h
--- a/include/asm-mips/system.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-mips/system.h	Fri Oct 18 21:03:04 2002
@@ -146,6 +146,7 @@
 #define rmb()	do { } while(0)
 #define wmb()	wbflush()
 #define mb()	wbflush()
+#define read_barrier_depends()	do { } while(0)
 
 #else /* CONFIG_CPU_HAS_WB  */
 
@@ -161,6 +162,7 @@
 	: "memory")
 #define rmb() mb()
 #define wmb() mb()
+#define read_barrier_depends()	do { } while(0)
 
 #endif /* CONFIG_CPU_HAS_WB  */
 
@@ -168,10 +170,12 @@
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
 #else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while(0)
 #endif
 
 #define set_mb(var, value) \
diff -Nru a/include/asm-mips64/checksum.h b/include/asm-mips64/checksum.h
--- a/include/asm-mips64/checksum.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-mips64/checksum.h	Fri Oct 18 21:03:04 2002
@@ -30,12 +30,6 @@
  * this is a new version of the above that records errors it finds in *errp,
  * but continues and zeros the rest of the buffer.
  */
-#define csum_partial_copy_nocheck csum_partial_copy
-
-/*
- * this is a new version of the above that records errors it finds in *errp,
- * but continues and zeros the rest of the buffer.
- */
 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
                                          unsigned int sum, int *errp);
 
@@ -60,12 +54,9 @@
 /*
  * the same as csum_partial, but copies from user space (but on MIPS
  * we have just one address space, so this is identical to the above)
- *
- * this is obsolete and will go away.
  */
-#define csum_partial_copy_fromuser csum_partial_copy
-unsigned int csum_partial_copy(const char *src, char *dst, int len,
-			       unsigned int sum);
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len,
+				       unsigned int sum);
 
 /*
  *	Fold a partial checksum without adding pseudo headers
diff -Nru a/include/asm-mips64/system.h b/include/asm-mips64/system.h
--- a/include/asm-mips64/system.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-mips64/system.h	Fri Oct 18 21:03:04 2002
@@ -142,15 +142,18 @@
 	: "memory")
 #define rmb() mb()
 #define wmb() mb()
+#define read_barrier_depends()	do { } while(0)
 
 #ifdef CONFIG_SMP
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
 #else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while(0)
 #endif
 
 #define set_mb(var, value) \
diff -Nru a/include/asm-parisc/checksum.h b/include/asm-parisc/checksum.h
--- a/include/asm-parisc/checksum.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-parisc/checksum.h	Fri Oct 18 21:03:03 2002
@@ -22,34 +22,13 @@
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-extern unsigned int csum_partial_copy(const char *, char *, int, unsigned int);
-
-/*
- * the same as csum_partial, but copies from user space
- *
- * this is obsolete and will go away.
- */
-#define csum_partial_copy_fromuser csum_partial_copy
+extern unsigned int csum_partial_copy_nocheck(const char *, char *, int, unsigned int);
 
 /*
  * this is a new version of the above that records errors it finds in *errp,
  * but continues and zeros the rest of the buffer.
  */
 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions. 
- *	
- *	If you use these functions directly please don't forget the 
- *	verify_area().
- */
-extern __inline__
-unsigned int csum_partial_copy_nocheck (const char *src, char *dst,
-					int len, int sum)
-{
-	return csum_partial_copy (src, dst, len, sum);
-}
 
 /*
  *	Optimized for IP headers, which always checksum on 4 octet boundaries.
diff -Nru a/include/asm-parisc/system.h b/include/asm-parisc/system.h
--- a/include/asm-parisc/system.h	Fri Oct 18 21:03:05 2002
+++ b/include/asm-parisc/system.h	Fri Oct 18 21:03:05 2002
@@ -51,6 +51,7 @@
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	do { } while(0)
 #else
 /* This is simply the barrier() macro from linux/kernel.h but when serial.c
  * uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
@@ -59,6 +60,7 @@
 #define smp_mb()	__asm__ __volatile__("":::"memory");
 #define smp_rmb()	__asm__ __volatile__("":::"memory");
 #define smp_wmb()	__asm__ __volatile__("":::"memory");
+#define smp_read_barrier_depends()	do { } while(0)
 #endif
 
 /* interrupt control */
@@ -120,6 +122,9 @@
 
 #define mb()  __asm__ __volatile__ ("sync" : : :"memory")
 #define wmb() mb()
+#define read_barrier_depends()	do { } while(0)
+#define set_mb(var, value)  do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 extern unsigned long __xchg(unsigned long, unsigned long *, int);
 
diff -Nru a/include/asm-ppc/checksum.h b/include/asm-ppc/checksum.h
--- a/include/asm-ppc/checksum.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc/checksum.h	Fri Oct 18 21:03:04 2002
@@ -38,14 +38,6 @@
 /* FIXME: this needs to be written to really do no check -- Cort */
 #define csum_partial_copy_nocheck(src, dst, len, sum)	\
 	csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)     
-/*
- * Old versions which ignore errors.
- */
-#define csum_partial_copy(src, dst, len, sum)	\
-	csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
-#define csum_partial_copy_fromuser(src, dst, len, sum)	\
-	csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
-
 
 /*
  * turns a 32-bit partial checksum (e.g. from csum_partial) into a
diff -Nru a/include/asm-ppc/div64.h b/include/asm-ppc/div64.h
--- a/include/asm-ppc/div64.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-ppc/div64.h	Fri Oct 18 21:03:08 2002
@@ -1,10 +1,23 @@
 #ifndef __PPC_DIV64
 #define __PPC_DIV64
 
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
+#include <linux/types.h>
+
+extern u32 __div64_32(u64 *dividend, u32 div);
+
+#define do_div(n, div)	({			\
+	u64 __n = (n);				\
+	u32 __d = (div);			\
+	u32 __q, __r;				\
+	if ((__n >> 32) == 0) {			\
+		__q = (u32)__n / __d;		\
+		__r = (u32)__n - __q * __d;	\
+		(n) = __q;			\
+	} else {				\
+		__r = __div64_32(&__n, __d);	\
+		(n) = __n;			\
+	}					\
+	__r;					\
+})
 
 #endif
diff -Nru a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
--- a/include/asm-ppc/pci-bridge.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc/pci-bridge.h	Fri Oct 18 21:03:03 2002
@@ -68,6 +68,11 @@
 	struct pci_ops *ops;
 	volatile unsigned int *cfg_addr;
 	volatile unsigned char *cfg_data;
+	/*
+	 * If set, indirect method will set the cfg_type bit as
+	 * needed to generate type 1 configuration transactions.
+	 */
+	int set_cfg_type;
 
 	/* Currently, we limit ourselves to 1 IO range and 3 mem
 	 * ranges since the common pci_bus structure can't handle more
diff -Nru a/include/asm-ppc/sections.h b/include/asm-ppc/sections.h
--- a/include/asm-ppc/sections.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-ppc/sections.h	Fri Oct 18 21:03:08 2002
@@ -2,27 +2,27 @@
 #ifndef _PPC_SECTIONS_H
 #define _PPC_SECTIONS_H
 
-#define __pmac __attribute__ ((__section__ (".text.pmac")))
-#define __pmacdata __attribute__ ((__section__ (".data.pmac")))
+#define __pmac __attribute__ ((__section__ (".pmac.text")))
+#define __pmacdata __attribute__ ((__section__ (".pmac.data")))
 #define __pmacfunc(__argpmac) \
 	__argpmac __pmac; \
 	__argpmac
 	
-#define __prep __attribute__ ((__section__ (".text.prep")))
-#define __prepdata __attribute__ ((__section__ (".data.prep")))
+#define __prep __attribute__ ((__section__ (".prep.text")))
+#define __prepdata __attribute__ ((__section__ (".prep.data")))
 #define __prepfunc(__argprep) \
 	__argprep __prep; \
 	__argprep
 
-#define __chrp __attribute__ ((__section__ (".text.chrp")))
-#define __chrpdata __attribute__ ((__section__ (".data.chrp")))
+#define __chrp __attribute__ ((__section__ (".chrp.text")))
+#define __chrpdata __attribute__ ((__section__ (".chrp.data")))
 #define __chrpfunc(__argchrp) \
 	__argchrp __chrp; \
 	__argchrp
 
 /* this is actually just common chrp/pmac code, not OF code -- Cort */
-#define __openfirmware __attribute__ ((__section__ (".text.openfirmware")))
-#define __openfirmwaredata __attribute__ ((__section__ (".data.openfirmware")))
+#define __openfirmware __attribute__ ((__section__ (".openfirmware.text")))
+#define __openfirmwaredata __attribute__ ((__section__ (".openfirmware.data")))
 #define __openfirmwarefunc(__argopenfirmware) \
 	__argopenfirmware __openfirmware; \
 	__argopenfirmware
diff -Nru a/include/asm-ppc/system.h b/include/asm-ppc/system.h
--- a/include/asm-ppc/system.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc/system.h	Fri Oct 18 21:03:04 2002
@@ -22,6 +22,8 @@
  * mb() prevents loads and stores being reordered across this point.
  * rmb() prevents loads being reordered across this point.
  * wmb() prevents stores being reordered across this point.
+ * read_barrier_depends() prevents data-dependant loads being reordered
+ *	across this point (nop on PPC).
  *
  * We can use the eieio instruction for wmb, but since it doesn't
  * give any ordering guarantees about loads, we have to use the
@@ -30,6 +32,7 @@
 #define mb()  __asm__ __volatile__ ("sync" : : : "memory")
 #define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
 #define wmb()  __asm__ __volatile__ ("eieio" : : : "memory")
+#define read_barrier_depends()  do { } while(0)
 
 #define set_mb(var, value)	do { var = value; mb(); } while (0)
 #define set_wmb(var, value)	do { var = value; wmb(); } while (0)
@@ -38,10 +41,12 @@
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
 #else
 #define smp_mb()	__asm__ __volatile__("": : :"memory")
 #define smp_rmb()	__asm__ __volatile__("": : :"memory")
 #define smp_wmb()	__asm__ __volatile__("": : :"memory")
+#define smp_read_barrier_depends()	do { } while(0)
 #endif /* CONFIG_SMP */
 
 #ifdef __KERNEL__
@@ -119,14 +124,14 @@
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 #define tas(ptr) (xchg((ptr),1))
 
-static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 {
 	switch (size) {
 	case 4:
-		return (unsigned long )xchg_u32(ptr, x);
+		return (unsigned long) xchg_u32(ptr, x);
 #if 0	/* xchg_u64 doesn't exist on 32-bit PPC */
 	case 8:
-		return (unsigned long )xchg_u64(ptr, x);
+		return (unsigned long) xchg_u64(ptr, x);
 #endif /* 0 */
 	}
 	__xchg_called_with_bad_pointer();
diff -Nru a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h
--- a/include/asm-ppc64/a.out.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/a.out.h	Fri Oct 18 21:03:03 2002
@@ -30,8 +30,7 @@
 
 #ifdef __KERNEL__
 
-/* 64-bit user address space is less PGDIR_SIZE due to pgd_index() bug. */
-#define STACK_TOP_USER64 (TASK_SIZE_USER64 - PGDIR_SIZE)
+#define STACK_TOP_USER64 (TASK_SIZE_USER64)
 
 /* Give 32-bit user space a full 4G address space to live in. */
 #define STACK_TOP_USER32 (TASK_SIZE_USER32)
diff -Nru a/include/asm-ppc64/checksum.h b/include/asm-ppc64/checksum.h
--- a/include/asm-ppc64/checksum.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc64/checksum.h	Fri Oct 18 21:03:04 2002
@@ -44,21 +44,13 @@
  * the same as csum_partial, but copies from src to dst while it
  * checksums
  */
-unsigned int csum_partial_copy(const char *src, char *dst, 
-			       int len, unsigned int sum);
-
 extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
 					      int len, unsigned int sum,
 					      int *src_err, int *dst_err);
 /*
- * the same as csum_partial, but copies from user space.
+ * the same as csum_partial, but copies from src to dst while it
+ * checksums.
  */
-
-unsigned int csum_partial_copy_fromuser(const char *src, 
-					char *dst, 
-					int len, 
-					unsigned int sum,
-					int *src_err);
 
 unsigned int csum_partial_copy_nocheck(const char *src, 
 				       char *dst, 
diff -Nru a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h
--- a/include/asm-ppc64/hardirq.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/hardirq.h	Fri Oct 18 21:03:03 2002
@@ -82,7 +82,7 @@
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
 #if CONFIG_PREEMPT
-# define in_atomic()	(preempt_count() != kernel_locked())
+# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
 # define in_atomic()	(preempt_count() != 0)
@@ -111,7 +111,5 @@
 	else					\
 		print_backtrace(_get_SP());	\
 } while (0)
-
-#define dump_stack()	show_stack()
 
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-ppc64/hw_irq.h b/include/asm-ppc64/hw_irq.h
--- a/include/asm-ppc64/hw_irq.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc64/hw_irq.h	Fri Oct 18 21:03:04 2002
@@ -36,7 +36,10 @@
 #else
 
 #define local_save_flags(flags)	((flags) = mfmsr())
-#define local_irq_restore(flags)	__mtmsrd((flags), 1)
+#define local_irq_restore(flags) do { \
+	__asm__ __volatile__("": : :"memory"); \
+	__mtmsrd((flags), 1); \
+} while(0)
 
 static inline void local_irq_disable(void)
 {
diff -Nru a/include/asm-ppc64/ipc.h b/include/asm-ppc64/ipc.h
--- a/include/asm-ppc64/ipc.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-ppc64/ipc.h	Fri Oct 18 21:03:08 2002
@@ -4,7 +4,7 @@
 /* 
  * These are used to wrap system calls on PowerPC.
  *
- * See arch/ppc/kernel/syscalls.c for ugly details..
+ * See arch/ppc64/kernel/syscalls.c for ugly details..
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -12,8 +12,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 struct ipc_kludge {
-	u32 msgp;
-	s32 msgtyp;
+	struct msgbuf *msgp;
+	long msgtyp;
 };
 
 #define SEMOP		 1
diff -Nru a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
--- a/include/asm-ppc64/machdep.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc64/machdep.h	Fri Oct 18 21:03:04 2002
@@ -119,5 +119,20 @@
 extern struct machdep_calls ppc_md;
 extern char cmd_line[512];
 
+/* Functions to produce codes on the leds.
+ * The SRC code should be unique for the message category and should
+ * be limited to the lower 24 bits (the upper 8 are set by these funcs),
+ * and (for boot & dump) should be sorted numerically in the order
+ * the events occur.
+ */
+/* Print a boot progress message. */
+void ppc64_boot_msg(unsigned int src, const char *msg);
+/* Print a termination message (print only -- does not stop the kernel) */
+void ppc64_terminate_msg(unsigned int src, const char *msg);
+/* Print something that needs attention (device error, etc) */
+void ppc64_attention_msg(unsigned int src, const char *msg);
+/* Print a dump progress message. */
+void ppc64_dump_msg(unsigned int src, const char *msg);
+
 #endif /* _PPC64_MACHDEP_H */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
--- a/include/asm-ppc64/pci-bridge.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/pci-bridge.h	Fri Oct 18 21:03:03 2002
@@ -79,5 +79,23 @@
 int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
 		   unsigned char *devfn_ptr);
 
+struct device_node *fetch_dev_dn(struct pci_dev *dev);
+
+/* Get a device_node from a pci_dev.  This code must be fast except in the case
+ * where the sysdata is incorrect and needs to be fixed up (hopefully just once)
+ */
+static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
+{
+	struct device_node *dn = (struct device_node *)(dev->sysdata);
+	if (dn->devfn == dev->devfn && dn->busno == dev->bus->number)
+		return dn;	/* fast path.  sysdata is good */
+	else
+		return fetch_dev_dn(dev);
+}
+/* Use this macro after the PCI bus walk for max performance when it
+ * is known that sysdata is correct.
+ */
+#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
+
 #endif
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
--- a/include/asm-ppc64/pgtable.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-ppc64/pgtable.h	Fri Oct 18 21:03:08 2002
@@ -35,7 +35,7 @@
 #define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
 #define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
 
-#define USER_PTRS_PER_PGD	(TASK_SIZE_USER64 / PGDIR_SIZE)
+#define USER_PTRS_PER_PGD	(1024)
 #define FIRST_USER_PGD_NR	0
 
 #define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
@@ -198,7 +198,8 @@
  * Find an entry in a page-table-directory.  We combine the address region 
  * (the high order N bits) and the pgd portion of the address.
  */
-#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD -1))
+/* to avoid overflow in free_pgtables we dont use PTRS_PER_PGD here */
+#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & 0x7ff)
 
 #define pgd_offset(mm, address)	 ((mm)->pgd + pgd_index(address))
 
diff -Nru a/include/asm-ppc64/posix_types.h b/include/asm-ppc64/posix_types.h
--- a/include/asm-ppc64/posix_types.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc64/posix_types.h	Fri Oct 18 21:03:04 2002
@@ -11,19 +11,10 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#if 0
-# define DRENG_TYPES
-#endif
 
-#ifdef DRENG_TYPES
 typedef unsigned long	__kernel_dev_t;
 typedef unsigned long	__kernel_ino_t;
 typedef unsigned long  	__kernel_nlink_t;
-#else
-typedef unsigned int	__kernel_dev_t;
-typedef unsigned int	__kernel_ino_t;
-typedef unsigned int  	__kernel_nlink_t;
-#endif
 typedef unsigned int	__kernel_mode_t;
 typedef long		__kernel_off_t;
 typedef long long	__kernel_loff_t;
diff -Nru a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
--- a/include/asm-ppc64/ppc32.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc64/ppc32.h	Fri Oct 18 21:03:04 2002
@@ -43,25 +43,24 @@
 })
 
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
-typedef unsigned int           __kernel_size_t32;
-typedef int                    __kernel_ssize_t32;
-typedef int                    __kernel_ptrdiff_t32;
-typedef int                    __kernel_time_t32;
-typedef int                    __kernel_clock_t32;
-typedef int                    __kernel_pid_t32;
-typedef unsigned short         __kernel_ipc_pid_t32;
-typedef unsigned int           __kernel_uid_t32;
-typedef unsigned int           __kernel_gid_t32;
-typedef unsigned int           __kernel_dev_t32;
-typedef unsigned int           __kernel_ino_t32;
-typedef unsigned int           __kernel_mode_t32;
-typedef unsigned int           __kernel_umode_t32;
-typedef short                  __kernel_nlink_t32;
-typedef int                    __kernel_daddr_t32;
-typedef int                    __kernel_off_t32;
-typedef unsigned int           __kernel_caddr_t32;
-typedef int 		       __kernel_loff_t32;
-/* typedef __kernel_fsid_t        __kernel_fsid_t32; */
+typedef unsigned int	__kernel_size_t32;
+typedef int		__kernel_ssize_t32;
+typedef int		__kernel_ptrdiff_t32;
+typedef int		__kernel_time_t32;
+typedef int		__kernel_clock_t32;
+typedef int		__kernel_pid_t32;
+typedef unsigned short	__kernel_ipc_pid_t32;
+typedef unsigned int	__kernel_uid_t32;
+typedef unsigned int	__kernel_gid_t32;
+typedef unsigned int	__kernel_dev_t32;
+typedef unsigned int	__kernel_ino_t32;
+typedef unsigned int	__kernel_mode_t32;
+typedef unsigned int	__kernel_umode_t32;
+typedef short		__kernel_nlink_t32;
+typedef int		__kernel_daddr_t32;
+typedef int		__kernel_off_t32;
+typedef unsigned int	__kernel_caddr_t32;
+typedef int		__kernel_loff_t32;
 
 struct statfs32 {
 	int f_type;
@@ -87,12 +86,12 @@
 	int si_code;
 
 	union {
-		int _pad[SI_PAD_SIZE];
+		int _pad[SI_PAD_SIZE32];
 
 		/* kill() */
 		struct {
 			__kernel_pid_t32 _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
+			__kernel_uid_t32 _uid;		/* sender's uid */
 		} _kill;
 
 		/* POSIX.1b timers */
@@ -104,14 +103,14 @@
 		/* POSIX.1b signals */
 		struct {
 			__kernel_pid_t32 _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
+			__kernel_uid_t32 _uid;		/* sender's uid */
 			sigval_t32 _sigval;
 		} _rt;
 
 		/* SIGCHLD */
 		struct {
 			__kernel_pid_t32 _pid;		/* which child */
-			unsigned int _uid;		/* sender's uid */
+			__kernel_uid_t32 _uid;		/* sender's uid */
 			int _status;			/* exit code */
 			__kernel_clock_t32 _utime;
 			__kernel_clock_t32 _stime;
@@ -119,8 +118,7 @@
 
 		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
 		struct {
-			u32 _addr; /* faulting insn/memory ref. */
-			int _trapno;
+			unsigned int _addr; /* faulting insn/memory ref. */
 		} _sigfault;
 
 		/* SIGPOLL */
@@ -153,8 +151,7 @@
 } sigset32_t;
 
 struct sigaction32 {
-       unsigned int  sa_handler;	/* Really a pointer, but need to deal 
-					     with 32 bits */
+       unsigned int  sa_handler;	/* Really a pointer, but need to deal with 32 bits */
        unsigned int sa_flags;
        unsigned int sa_restorer;	/* Another 32 bit pointer */
        sigset32_t sa_mask;		/* A 32 bit mask */
@@ -212,7 +209,7 @@
 	unsigned int   st_ctime;
 };
 
-struct sigcontext32_struct {
+struct sigcontext32 {
 	unsigned int	_unused[4];
 	int		signal;
 	unsigned int	handler;
@@ -224,9 +221,13 @@
 	unsigned int	  uc_flags;
 	unsigned int 	  uc_link;
 	stack_32_t	  uc_stack;
-	struct sigcontext32_struct uc_mcontext;
+	struct sigcontext32 uc_mcontext;
 	sigset_t	  uc_sigmask;	/* mask last for extensibility */
 };
 
+struct ipc_kludge_32 {
+	unsigned int msgp;
+	int msgtyp;
+};
 
 #endif  /* _PPC64_PPC32_H */
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/processor.h	Fri Oct 18 21:03:03 2002
@@ -477,7 +477,7 @@
 #define	PVR_REV(pvr)  (((pvr) >>   0) & 0xFFFF)	/* Revison field */
 
 /* Processor Version Numbers */
-#define PV_NORTHSTAR	0x0033
+#define	PV_NORTHSTAR	0x0033
 #define	PV_PULSAR	0x0034
 #define	PV_POWER4	0x0035
 #define	PV_ICESTAR	0x0036
diff -Nru a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h
--- a/include/asm-ppc64/semaphore.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-ppc64/semaphore.h	Fri Oct 18 21:03:04 2002
@@ -77,6 +77,7 @@
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
+	might_sleep();
 
 	/*
 	 * Try to get the semaphore, take the slow path if we fail.
@@ -93,6 +94,7 @@
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
+	might_sleep();
 
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
diff -Nru a/include/asm-ppc64/sigcontext.h b/include/asm-ppc64/sigcontext.h
--- a/include/asm-ppc64/sigcontext.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/sigcontext.h	Fri Oct 18 21:03:03 2002
@@ -10,9 +10,10 @@
 
 #include <asm/ptrace.h>
 
-struct sigcontext_struct {
+struct sigcontext {
 	unsigned long	_unused[4];
 	int		signal;
+	int		_pad0;
 	unsigned long	handler;
 	unsigned long	oldmask;
 	struct pt_regs 	*regs;
diff -Nru a/include/asm-ppc64/siginfo.h b/include/asm-ppc64/siginfo.h
--- a/include/asm-ppc64/siginfo.h	Fri Oct 18 21:03:07 2002
+++ b/include/asm-ppc64/siginfo.h	Fri Oct 18 21:03:07 2002
@@ -8,6 +8,9 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define SI_PAD_SIZE    ((SI_MAX_SIZE/sizeof(int)) - 4)
+#define SI_PAD_SIZE32  ((SI_MAX_SIZE/sizeof(int)) - 3)
+
 #include <asm-generic/siginfo.h>
 
 #endif /* _PPC64_SIGINFO_H */
diff -Nru a/include/asm-ppc64/stat.h b/include/asm-ppc64/stat.h
--- a/include/asm-ppc64/stat.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-ppc64/stat.h	Fri Oct 18 21:03:08 2002
@@ -27,8 +27,8 @@
 struct stat {
 	dev_t		st_dev;
 	ino_t		st_ino;
-	mode_t		st_mode;
 	nlink_t		st_nlink;
+	mode_t		st_mode;
 	uid_t 		st_uid;
 	gid_t 		st_gid;
 	dev_t		st_rdev;
@@ -43,6 +43,7 @@
 	unsigned long  	__unused3;
 	unsigned long  	__unused4;
 	unsigned long  	__unused5;
+	unsigned long  	__unused6;
 };
 
 /* This matches struct stat64 in glibc2.1. */
diff -Nru a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
--- a/include/asm-ppc64/system.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-ppc64/system.h	Fri Oct 18 21:03:08 2002
@@ -25,6 +25,8 @@
  * mb() prevents loads and stores being reordered across this point.
  * rmb() prevents loads being reordered across this point.
  * wmb() prevents stores being reordered across this point.
+ * read_barrier_depends() prevents data-dependant loads being reordered
+ *	across this point (nop on PPC).
  *
  * We can use the eieio instruction for wmb, but since it doesn't
  * give any ordering guarantees about loads, we have to use the
@@ -33,6 +35,7 @@
 #define mb()   __asm__ __volatile__ ("sync" : : : "memory")
 #define rmb()  __asm__ __volatile__ ("lwsync" : : : "memory")
 #define wmb()  __asm__ __volatile__ ("eieio" : : : "memory")
+#define read_barrier_depends()  do { } while(0)
 
 #define set_mb(var, value)	do { var = value; mb(); } while (0)
 #define set_wmb(var, value)	do { var = value; wmb(); } while (0)
@@ -41,10 +44,12 @@
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()  read_barrier_depends()
 #else
 #define smp_mb()	__asm__ __volatile__("": : :"memory")
 #define smp_rmb()	__asm__ __volatile__("": : :"memory")
 #define smp_wmb()	__asm__ __volatile__("": : :"memory")
+#define smp_read_barrier_depends()  do { } while(0)
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_DEBUG_KERNEL
diff -Nru a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
--- a/include/asm-ppc64/thread_info.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/thread_info.h	Fri Oct 18 21:03:03 2002
@@ -32,11 +32,11 @@
  */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
-	task:		&tsk,			\
-	exec_domain:	&default_exec_domain,	\
-	flags:		0,			\
-	cpu:		0,			\
-	preempt_count:	1,			\
+	.task =		&tsk,			\
+	.exec_domain =	&default_exec_domain,	\
+	.flags =	0,			\
+	.cpu =		0,			\
+	.preempt_count = 1,			\
 }
 
 #define init_thread_info	(init_thread_union.thread_info)
diff -Nru a/include/asm-ppc64/ucontext.h b/include/asm-ppc64/ucontext.h
--- a/include/asm-ppc64/ucontext.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/ucontext.h	Fri Oct 18 21:03:03 2002
@@ -13,7 +13,7 @@
 	unsigned long	  uc_flags;
 	struct ucontext  *uc_link;
 	stack_t		  uc_stack;
-	struct sigcontext_struct uc_mcontext;
+	struct sigcontext uc_mcontext;
 	sigset_t	  uc_sigmask;	/* mask last for extensibility */
 };
 
diff -Nru a/include/asm-ppc64/udbg.h b/include/asm-ppc64/udbg.h
--- a/include/asm-ppc64/udbg.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-ppc64/udbg.h	Fri Oct 18 21:03:03 2002
@@ -17,6 +17,8 @@
 void udbg_puts(const char *s);
 int udbg_write(const char *s, int n);
 int udbg_read(char *buf, int buflen);
+struct console;
+void udbg_console_write(struct console *con, const char *s, unsigned int n);
 void udbg_puthex(unsigned long val);
 void udbg_printSP(const char *s);
 void udbg_printf(const char *fmt, ...);
diff -Nru a/include/asm-s390/checksum.h b/include/asm-s390/checksum.h
--- a/include/asm-s390/checksum.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-s390/checksum.h	Fri Oct 18 21:03:03 2002
@@ -62,21 +62,6 @@
 }
 
 /*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-static inline unsigned int 
-csum_partial_copy(const char *src, char *dst, int len,unsigned int sum)
-{
-	memcpy(dst,src,len);
-        return csum_partial_inline(dst, len, sum);
-}
-
-/*
  * the same as csum_partial_copy, but copies from user space.
  *
  * here even more important to align src and dst on a 32-bit (or even
diff -Nru a/include/asm-s390/system.h b/include/asm-s390/system.h
--- a/include/asm-s390/system.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-s390/system.h	Fri Oct 18 21:03:08 2002
@@ -227,9 +227,11 @@
 #define mb()    eieio()
 #define rmb()   eieio()
 #define wmb()   eieio()
+#define read_barrier_depends() do { } while(0)
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
+#define smp_read_barrier_depends()    read_barrier_depends()
 #define smp_mb__before_clear_bit()     smp_mb()
 #define smp_mb__after_clear_bit()      smp_mb()
 
diff -Nru a/include/asm-s390x/checksum.h b/include/asm-s390x/checksum.h
--- a/include/asm-s390x/checksum.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-s390x/checksum.h	Fri Oct 18 21:03:08 2002
@@ -64,21 +64,6 @@
 }
 
 /*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-static inline unsigned int 
-csum_partial_copy(const char *src, char *dst, int len,unsigned int sum)
-{
-	memcpy(dst,src,len);
-        return csum_partial_inline(dst, len, sum);
-}
-
-/*
  * the same as csum_partial_copy, but copies from user space.
  *
  * here even more important to align src and dst on a 32-bit (or even
diff -Nru a/include/asm-s390x/system.h b/include/asm-s390x/system.h
--- a/include/asm-s390x/system.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-s390x/system.h	Fri Oct 18 21:03:08 2002
@@ -238,9 +238,11 @@
 #define mb()    eieio()
 #define rmb()   eieio()
 #define wmb()   eieio()
+#define read_barrier_depends()	do { } while(0)
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
+#define smp_read_barrier_depends()    read_barrier_depends()
 #define smp_mb__before_clear_bit()     smp_mb()
 #define smp_mb__after_clear_bit()      smp_mb()
 
diff -Nru a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
--- a/include/asm-sh/checksum.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-sh/checksum.h	Fri Oct 18 21:03:03 2002
@@ -58,16 +58,6 @@
 }
 
 /*
- * These are the old (and unsafe) way of doing checksums, a warning message will be
- * printed if they are used and an exeption occurs.
- *
- * these functions should go away after some time.
- */
-
-#define csum_partial_copy_fromuser csum_partial_copy
-unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
-
-/*
  *	Fold a partial checksum
  */
 
diff -Nru a/include/asm-sh/system.h b/include/asm-sh/system.h
--- a/include/asm-sh/system.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-sh/system.h	Fri Oct 18 21:03:08 2002
@@ -89,15 +89,18 @@
 #define mb()	__asm__ __volatile__ ("": : :"memory")
 #define rmb()	mb()
 #define wmb()	__asm__ __volatile__ ("": : :"memory")
+#define read_barrier_depends()	do { } while(0)
 
 #ifdef CONFIG_SMP
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
 #else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while(0)
 #endif
 
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
diff -Nru a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
--- a/include/asm-sparc/checksum.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-sparc/checksum.h	Fri Oct 18 21:03:03 2002
@@ -40,12 +40,6 @@
  * better 64-bit) boundary
  */
 
-/* FIXME: Remove these two macros ASAP */
-#define csum_partial_copy(src, dst, len, sum) \
- 		       csum_partial_copy_nocheck(src,dst,len,sum)
-#define csum_partial_copy_fromuser(s, d, l, w)  \
-                         csum_partial_copy((char *) (s), (d), (l), (w))
-  
 extern unsigned int __csum_partial_copy_sparc_generic (const char *, char *);
 
 extern __inline__ unsigned int 
diff -Nru a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h
--- a/include/asm-sparc/ptrace.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-sparc/ptrace.h	Fri Oct 18 21:03:08 2002
@@ -73,7 +73,12 @@
 #define REGWIN_SZ         0x40
 #endif
 
-#include <asm/asm_offsets.h>
+/*
+ * The asm_offsets.h is a generated file, so we cannot include it.
+ * It may be OK for glibc headers, but it's utterly pointless for C code.
+ * The assembly code using those offsets has to include it explicitly.
+ */
+/* #include <asm/asm_offsets.h> */
 
 /* These are for pt_regs. */
 #define PT_PSR    0x0
diff -Nru a/include/asm-sparc/siginfo.h b/include/asm-sparc/siginfo.h
--- a/include/asm-sparc/siginfo.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-sparc/siginfo.h	Fri Oct 18 21:03:03 2002
@@ -5,64 +5,11 @@
 #ifndef _SPARC_SIGINFO_H
 #define _SPARC_SIGINFO_H
 
-#define HAVE_ARCH_SIGINFO_T
-#define HAVE_ARCH_COPY_SIGINFO
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER
+#define __ARCH_SI_UID_T		unsigned int
+#define __ARCH_SI_TRAPNO
 
 #include <asm-generic/siginfo.h>
 
-typedef struct siginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[SI_PAD_SIZE];
-
-		/* kill() */
-		struct {
-			pid_t _pid;		/* sender's pid */
-			unsigned int _uid;	/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			pid_t _pid;		/* sender's pid */
-			unsigned int _uid;	/* sender's uid */
-			sigval_t _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			pid_t _pid;		/* which child */
-			unsigned int _uid;	/* sender's uid */
-			int _status;		/* exit code */
-			clock_t _utime;
-			clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-		struct {
-			void *_addr;	/* faulting insn/memory ref. */
-			int  _trapno;	/* TRAP # which caused the signal */
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-} siginfo_t;
-
-#define si_trapno	_sifields._sigfault._trapno
-
 #define SI_NOINFO	32767		/* no information in siginfo_t */
 
 /*
@@ -70,20 +17,5 @@
  */
 #define EMT_TAGOVF	(__SI_FAULT|1)	/* tag overflow */
 #define NSIGEMT		1
-
-#ifdef __KERNEL__
-
-#include <linux/string.h>
-
-extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from)
-{
-	if (from->si_code < 0)
-		*to = *from;
-	else
-		/* _sigchld is currently the largest know union member */
-		memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
-}
-
-#endif /* __KERNEL__ */
 
 #endif /* !(_SPARC_SIGINFO_H) */
diff -Nru a/include/asm-sparc/system.h b/include/asm-sparc/system.h
--- a/include/asm-sparc/system.h	Fri Oct 18 21:03:07 2002
+++ b/include/asm-sparc/system.h	Fri Oct 18 21:03:07 2002
@@ -310,11 +310,13 @@
 #define mb()	__asm__ __volatile__ ("" : : : "memory")
 #define rmb()	mb()
 #define wmb()	mb()
+#define read_barrier_depends()	do { } while(0)
 #define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
 #define set_wmb(__var, __value) set_mb(__var, __value)
 #define smp_mb()	__asm__ __volatile__("":::"memory");
 #define smp_rmb()	__asm__ __volatile__("":::"memory");
 #define smp_wmb()	__asm__ __volatile__("":::"memory");
+#define smp_read_barrier_depends()	do { } while(0)
 
 #define nop() __asm__ __volatile__ ("nop");
 
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-sparc/unistd.h	Fri Oct 18 21:03:03 2002
@@ -223,7 +223,7 @@
 #define __NR_readahead          205 /* Linux Specific                              */
 #define __NR_socketcall         206 /* Linux Specific                              */
 #define __NR_syslog             207 /* Linux Specific                              */
-/* #define __NR_olduname        208    Linux Specific                              */
+#define __NR_lookup_dcookie     208 /* Linux Specific                              */
 /* #define __NR_iopl            209    Linux Specific - i386 specific, unused      */
 /* #define __NR_idle            210    Linux Specific - was sys_idle, now unused   */
 /* #define __NR_vm86            211    Linux Specific - i386 specific, unused      */
diff -Nru a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
--- a/include/asm-sparc64/siginfo.h	Fri Oct 18 21:03:07 2002
+++ b/include/asm-sparc64/siginfo.h	Fri Oct 18 21:03:07 2002
@@ -1,15 +1,13 @@
 #ifndef _SPARC64_SIGINFO_H
 #define _SPARC64_SIGINFO_H
 
-#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 4)
 #define SI_PAD_SIZE32	((SI_MAX_SIZE/sizeof(int)) - 3)
 
 #define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 4)
 #define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
 
-#define HAVE_ARCH_SIGINFO_T
-#define HAVE_ARCH_COPY_SIGINFO
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER
+#define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
+#define __ARCH_SI_TRAPNO
 
 #include <asm-generic/siginfo.h>
 
@@ -20,60 +18,6 @@
 	u32 sival_ptr;
 } sigval_t32;
 
-#endif /* __KERNEL__ */
-
-typedef struct siginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[SI_PAD_SIZE];
-
-		/* kill() */
-		struct {
-			pid_t _pid;		/* sender's pid */
-			uid_t _uid;		/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			pid_t _pid;		/* sender's pid */
-			uid_t _uid;		/* sender's uid */
-			sigval_t _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			pid_t _pid;		/* which child */
-			uid_t _uid;		/* sender's uid */
-			int _status;		/* exit code */
-			clock_t _utime;
-			clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-		struct {
-			void *_addr; /* faulting insn/memory ref. */
-			int  _trapno; /* TRAP # which caused the signal */
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			long _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-} siginfo_t;
-
-#ifdef __KERNEL__
-
 typedef struct siginfo32 {
 	int si_signo;
 	int si_errno;
@@ -126,8 +70,6 @@
 
 #endif /* __KERNEL__ */
 
-#define si_trapno	_sifields._sigfault._trapno
-
 #define SI_NOINFO	32767		/* no information in siginfo_t */
 
 /*
@@ -151,17 +93,6 @@
 		} _sigev_thread;
 	} _sigev_un;
 } sigevent_t32;
-
-#include <linux/string.h>
-
-static inline void copy_siginfo(siginfo_t *to, siginfo_t *from)
-{
-	if (from->si_code < 0)
-		*to = *from;
-	else
-		/* _sigchld is currently the largest know union member */
-		memcpy(to, from, 4*sizeof(int) + sizeof(from->_sifields._sigchld));
-}
 
 extern int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);
 
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-sparc64/unistd.h	Fri Oct 18 21:03:03 2002
@@ -223,7 +223,7 @@
 #define __NR_readahead          205 /* Linux Specific                              */
 #define __NR_socketcall         206 /* Linux Specific                              */
 #define __NR_syslog             207 /* Linux Specific                              */
-/* #define __NR_olduname        208    Linux Specific                              */
+#define __NR_lookup_dcookie     208 /* Linux Specific                              */
 /* #define __NR_iopl            209    Linux Specific - i386 specific, unused      */
 /* #define __NR_idle            210    Linux Specific - was sys_idle, now unused   */
 /* #define __NR_vm86            211    Linux Specific - i386 specific, unused      */
diff -Nru a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
--- a/include/asm-x86_64/hw_irq.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-x86_64/hw_irq.h	Fri Oct 18 21:03:04 2002
@@ -20,6 +20,10 @@
 #include <linux/config.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
+#include <linux/profile.h>
+#include <linux/smp.h>
+
+struct hw_interrupt_type;
 #endif
 
 /*
@@ -126,20 +130,23 @@
 	"push $" #nr "-256 ; " \
 	"jmp common_interrupt");
 
-extern unsigned long prof_cpu_mask;
-extern unsigned int * prof_buffer;
-extern unsigned long prof_len;
-extern unsigned long prof_shift;
-
-/*
- * x86 profiling function, SMP safe. We might want to do this in
- * assembly totally?
- */
-static inline void x86_do_profile (unsigned long rip)
+static inline void x86_do_profile (struct pt_regs *regs) 
 {
+	unsigned long rip;
+	extern unsigned long prof_cpu_mask;
+	extern char _stext;
+#ifdef CONFIG_PROFILING
+	extern void x86_profile_hook(struct pt_regs *);
+ 
+	x86_profile_hook(regs);
+#endif
+	if (user_mode(regs))
+		return;
 	if (!prof_buffer)
 		return;
 
+	rip = regs->rip;
+
 	/*
 	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
 	 * (default is all CPUs.)
@@ -158,6 +165,11 @@
 		rip = prof_len-1;
 	atomic_inc((atomic_t *)&prof_buffer[rip]);
 }
+
+struct notifier_block;
+ 
+int register_profile_notifier(struct notifier_block * nb);
+int unregister_profile_notifier(struct notifier_block * nb);
 
 #ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
diff -Nru a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
--- a/include/asm-x86_64/ia32.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-x86_64/ia32.h	Fri Oct 18 21:03:08 2002
@@ -235,11 +235,6 @@
 };
 
 
-#ifdef __KERNEL__
-struct iovec *get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type);
-#endif
-
-
 #endif /* !CONFIG_IA32_SUPPORT */
  
 #endif 
diff -Nru a/include/asm-x86_64/ide.h b/include/asm-x86_64/ide.h
--- a/include/asm-x86_64/ide.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-x86_64/ide.h	Fri Oct 18 21:03:04 2002
@@ -5,7 +5,7 @@
  */
 
 /*
- *  This file contains the i386 architecture specific IDE code.
+ *  This file contains the x86_64 architecture specific IDE code.
  */
 
 #ifndef __ASMx86_64_IDE_H
diff -Nru a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
--- a/include/asm-x86_64/io_apic.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-x86_64/io_apic.h	Fri Oct 18 21:03:03 2002
@@ -148,9 +148,18 @@
 extern int io_apic_set_pci_routing (int ioapic, int pin, int irq);
 #endif
 
+#ifdef CONFIG_ACPI_BOOT
+extern int io_apic_get_unique_id (int ioapic, int apic_id);
+extern int io_apic_get_version (int ioapic);
+extern int io_apic_get_redir_entries (int ioapic);
+extern int io_apic_set_pci_routing (int ioapic, int pin, int irq);
+#endif
+
 
 #else  /* !CONFIG_X86_IO_APIC */
 #define io_apic_assign_pci_irqs 0
 #endif
+
+void enable_NMI_through_LVT0 (void * dummy);
 
 #endif
diff -Nru a/include/asm-x86_64/ioctl32.h b/include/asm-x86_64/ioctl32.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-x86_64/ioctl32.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1 @@
+#include <linux/ioctl32.h>
diff -Nru a/include/asm-x86_64/ipc.h b/include/asm-x86_64/ipc.h
--- a/include/asm-x86_64/ipc.h	Fri Oct 18 21:03:05 2002
+++ b/include/asm-x86_64/ipc.h	Fri Oct 18 21:03:05 2002
@@ -1,5 +1,5 @@
-#ifndef __x86_64_IPC_H__
-#define __x86_64_IPC_H__
+#ifndef __x8664_IPC_H__
+#define __x8664_IPC_H__
 
 /* dummy */
 
diff -Nru a/include/asm-x86_64/ipcbuf.h b/include/asm-x86_64/ipcbuf.h
--- a/include/asm-x86_64/ipcbuf.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-x86_64/ipcbuf.h	Fri Oct 18 21:03:08 2002
@@ -1,8 +1,8 @@
-#ifndef __i386_IPCBUF_H__
-#define __i386_IPCBUF_H__
+#ifndef __x86_64_IPCBUF_H__
+#define __x86_64_IPCBUF_H__
 
 /*
- * The ipc64_perm structure for i386 architecture.
+ * The ipc64_perm structure for x86_64 architecture.
  * Note extra padding because this structure is passed back and forth
  * between kernel and user space.
  *
@@ -26,4 +26,4 @@
 	unsigned long		__unused2;
 };
 
-#endif /* __i386_IPCBUF_H__ */
+#endif /* __x86_64_IPCBUF_H__ */
diff -Nru a/include/asm-x86_64/namei.h b/include/asm-x86_64/namei.h
--- a/include/asm-x86_64/namei.h	Fri Oct 18 21:03:03 2002
+++ b/include/asm-x86_64/namei.h	Fri Oct 18 21:03:03 2002
@@ -1,9 +1,3 @@
-/* $Id: namei.h,v 1.2 2001/07/04 09:08:13 ak Exp $
- * linux/include/asm-i386/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
 #ifndef __X8664_NAMEI_H
 #define __X8664_NAMEI_H
 
diff -Nru a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-x86_64/nmi.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,49 @@
+/*
+ *  linux/include/asm-i386/nmi.h
+ */
+#ifndef ASM_NMI_H
+#define ASM_NMI_H
+
+#include <linux/pm.h>
+ 
+struct pt_regs;
+ 
+typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu);
+ 
+/** 
+ * set_nmi_callback
+ *
+ * Set a handler for an NMI. Only one handler may be
+ * set. Return 1 if the NMI was handled.
+ */
+void set_nmi_callback(nmi_callback_t callback);
+ 
+/** 
+ * unset_nmi_callback
+ *
+ * Remove the handler previously set.
+ */
+void unset_nmi_callback(void);
+ 
+#ifdef CONFIG_PM
+ 
+/** Replace the PM callback routine for NMI. */
+struct pm_dev * set_nmi_pm_callback(pm_callback callback);
+
+/** Unset the PM callback routine back to the default. */
+void unset_nmi_pm_callback(struct pm_dev * dev);
+
+#else
+
+static inline struct pm_dev * set_nmi_pm_callback(pm_callback callback)
+{
+	return 0;
+} 
+ 
+static inline void unset_nmi_pm_callback(struct pm_dev * dev)
+{
+}
+
+#endif /* CONFIG_PM */
+ 
+#endif /* ASM_NMI_H */
diff -Nru a/include/asm-x86_64/param.h b/include/asm-x86_64/param.h
--- a/include/asm-x86_64/param.h	Fri Oct 18 21:03:05 2002
+++ b/include/asm-x86_64/param.h	Fri Oct 18 21:03:05 2002
@@ -2,7 +2,7 @@
 #define _ASMx86_64_PARAM_H
 
 #ifdef __KERNEL__
-# define HZ            100            /* Internal kernel timer frequency */
+# define HZ            1000            /* Internal kernel timer frequency */
 # define USER_HZ       100          /* .. some user interfaces are in "ticks */
 #define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
 #endif
diff -Nru a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
--- a/include/asm-x86_64/proto.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-x86_64/proto.h	Fri Oct 18 21:03:08 2002
@@ -42,6 +42,7 @@
 
 extern void acpi_boot_init(char *);
 
+int iommu_setup(char *opt);
 
 #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/socket32.h b/include/asm-x86_64/socket32.h
--- a/include/asm-x86_64/socket32.h	Fri Oct 18 21:03:04 2002
+++ b/include/asm-x86_64/socket32.h	Fri Oct 18 21:03:04 2002
@@ -7,14 +7,6 @@
 					   24 for IPv6,
 					   about 80 for AX.25 */
 
-extern struct socket *sockfd_lookup(int fd, int *err);
-
-/* XXX This as well... */
-extern __inline__ void sockfd_put(struct socket *sock)
-{
-	fput(sock->file);
-}
-
 struct msghdr32 {
         u32               msg_name;
         int               msg_namelen;
diff -Nru a/include/asm-x86_64/softirq.h b/include/asm-x86_64/softirq.h
--- a/include/asm-x86_64/softirq.h	Fri Oct 18 21:03:07 2002
+++ b/include/asm-x86_64/softirq.h	Fri Oct 18 21:03:07 2002
@@ -9,6 +9,8 @@
 #define __local_bh_enable() \
 		do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0)
 
+void do_softirq(void);
+
 #define local_bh_enable()						\
 do {									\
 	__local_bh_enable();						\
diff -Nru a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
--- a/include/asm-x86_64/system.h	Fri Oct 18 21:03:08 2002
+++ b/include/asm-x86_64/system.h	Fri Oct 18 21:03:08 2002
@@ -215,10 +215,12 @@
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	do {} while(0)
 #else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do {} while(0)
 #endif
 
     
@@ -230,6 +232,7 @@
 #define mb() 	asm volatile("mfence":::"memory")
 #define rmb()	asm volatile("lfence":::"memory")
 #define wmb()	asm volatile("sfence":::"memory")
+#define read_barrier_depends()	do {} while(0)
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	Fri Oct 18 21:03:07 2002
+++ b/include/asm-x86_64/unistd.h	Fri Oct 18 21:03:07 2002
@@ -482,8 +482,10 @@
 __SYSCALL(__NR_io_cancel, sys_io_cancel)
 #define __NR_get_thread_area	211
 __SYSCALL(__NR_get_thread_area, sys_get_thread_area)
+#define __NR_lookup_dcookie	212
+__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie)
 
-#define __NR_syscall_max __NR_get_thread_area
+#define __NR_syscall_max __NR_lookup_dcookie
 #ifndef __NO_STUBS
 
 /* user-visible error numbers are in the range -1 - -4095 */
@@ -503,7 +505,6 @@
 
 #define __syscall "syscall"
 
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
 #define _syscall0(type,name) \
 type name(void) \
 { \
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/blkdev.h	Fri Oct 18 21:03:03 2002
@@ -235,6 +235,7 @@
 #define blk_queue_tagged(q)	test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
 #define blk_queue_empty(q)	elv_queue_empty(q)
 #define blk_fs_request(rq)	((rq)->flags & REQ_CMD)
+#define blk_pc_request(rq)	((rq)->flags & REQ_BLOCK_PC)
 #define list_entry_rq(ptr)	list_entry((ptr), struct request, queuelist)
 
 #define rq_data_dir(rq)		((rq)->flags & 1)
diff -Nru a/include/linux/cdrom.h b/include/linux/cdrom.h
--- a/include/linux/cdrom.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/cdrom.h	Fri Oct 18 21:03:03 2002
@@ -731,7 +731,6 @@
 	struct cdrom_device_info *next; /* next device_info for this major */
 	void *handle;		        /* driver-dependent data */
 /* specifications */
-        kdev_t dev;	                /* device number */
 	int mask;                       /* mask of capability: disables them */
 	int speed;			/* maximum speed for reading data */
 	int capacity;			/* number of discs in jukebox */
@@ -776,10 +775,10 @@
 };
 
 /* the general block_device operations structure: */
-extern int cdrom_open(struct inode *, struct file *);
-extern int cdrom_release(struct inode *, struct file *);
-extern int cdrom_ioctl(struct inode *, struct file *, unsigned, unsigned long);
-extern int cdrom_media_changed(kdev_t);
+extern int cdrom_open(struct cdrom_device_info *, struct inode *, struct file *);
+extern int cdrom_release(struct cdrom_device_info *, struct file *);
+extern int cdrom_ioctl(struct cdrom_device_info *, struct inode *, unsigned, unsigned long);
+extern int cdrom_media_changed(struct cdrom_device_info *);
 
 extern int register_cdrom(struct cdrom_device_info *cdi);
 extern int unregister_cdrom(struct cdrom_device_info *cdi);
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Fri Oct 18 21:03:08 2002
+++ b/include/linux/device.h	Fri Oct 18 21:03:08 2002
@@ -48,14 +48,22 @@
 	RESUME_ENABLE,
 };
 
+enum device_state {
+	DEVICE_UNINITIALIZED	= 0,
+	DEVICE_INITIALIZED	= 1,
+	DEVICE_REGISTERED	= 2,
+	DEVICE_GONE		= 3,
+};
+
 struct device;
 struct device_driver;
 struct device_class;
 
 struct bus_type {
 	char			* name;
-	rwlock_t		lock;
+	struct rw_semaphore	rwsem;
 	atomic_t		refcount;
+	u32			present;
 
 	struct list_head	node;
 	struct list_head	devices;
@@ -73,14 +81,9 @@
 
 
 extern int bus_register(struct bus_type * bus);
+extern void bus_unregister(struct bus_type * bus);
 
-static inline struct bus_type * get_bus(struct bus_type * bus)
-{
-	BUG_ON(!atomic_read(&bus->refcount));
-	atomic_inc(&bus->refcount);
-	return bus;
-}
-
+extern struct bus_type * get_bus(struct bus_type * bus);
 extern void put_bus(struct bus_type * bus);
 
 extern int bus_for_each_dev(struct bus_type * bus, void * data, 
@@ -114,6 +117,7 @@
 
 	rwlock_t		lock;
 	atomic_t		refcount;
+	u32			present;
 
 	struct list_head	bus_list;
 	struct list_head	class_list;
@@ -123,7 +127,7 @@
 
 	int	(*probe)	(struct device * dev);
 	int 	(*remove)	(struct device * dev);
-
+	void	(*shutdown)	(struct device * dev);
 	int	(*suspend)	(struct device * dev, u32 state, u32 level);
 	int	(*resume)	(struct device * dev, u32 level);
 
@@ -131,16 +135,10 @@
 };
 
 
-
 extern int driver_register(struct device_driver * drv);
+extern void driver_unregister(struct device_driver * drv);
 
-static inline struct device_driver * get_driver(struct device_driver * drv)
-{
-	BUG_ON(!atomic_read(&drv->refcount));
-	atomic_inc(&drv->refcount);
-	return drv;
-}
-
+extern struct device_driver * get_driver(struct device_driver * drv);
 extern void put_driver(struct device_driver * drv);
 extern void remove_driver(struct device_driver * drv);
 
@@ -172,6 +170,11 @@
  */
 struct device_class {
 	char			* name;
+	struct rw_semaphore	rwsem;
+
+	atomic_t		refcount;
+	u32			present;
+
 	u32			devnum;
 
 	struct list_head	node;
@@ -189,6 +192,9 @@
 extern int devclass_register(struct device_class *);
 extern void devclass_unregister(struct device_class *);
 
+extern struct device_class * get_devclass(struct device_class *);
+extern void put_devclass(struct device_class *);
+
 
 struct devclass_attribute {
 	struct attribute	attr;
@@ -289,8 +295,8 @@
 	void		*platform_data;	/* Platform specific data (e.g. ACPI,
 					   BIOS data relevant to device) */
 
-	u32		present;
-	u32		current_state;  /* Current operating state. In
+	enum device_state state;
+	u32		power_state;  /* Current operating state. In
 					   ACPI-speak, this is D0-D3, D0
 					   being fully functional, and D3
 					   being off. */
@@ -361,6 +367,11 @@
 extern int (*platform_notify)(struct device * dev);
 
 extern int (*platform_notify_remove)(struct device * dev);
+
+static inline int device_present(struct device * dev)
+{
+	return (dev && (dev->state == DEVICE_INITIALIZED || dev->state == DEVICE_REGISTERED));
+}
 
 /* device and bus locking helpers.
  *
diff -Nru a/include/linux/driverfs_fs.h b/include/linux/driverfs_fs.h
--- a/include/linux/driverfs_fs.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/driverfs_fs.h	Fri Oct 18 21:03:04 2002
@@ -65,6 +65,4 @@
 extern void
 driverfs_remove_file(struct driver_dir_entry *, const char * name);
 
-extern int init_driverfs_fs(void);
-
 #endif /* _DDFS_H_ */
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/fs.h	Fri Oct 18 21:03:03 2002
@@ -730,8 +730,8 @@
 	int (*open) (struct inode *, struct file *);
 	int (*release) (struct inode *, struct file *);
 	int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
-	int (*check_media_change) (kdev_t);
-	int (*revalidate) (kdev_t);
+	int (*media_changed) (struct gendisk *);
+	int (*revalidate_disk) (struct gendisk *);
 	struct module *owner;
 };
 
@@ -1251,7 +1251,8 @@
 ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
 				unsigned long nr_segs, loff_t *ppos);
 extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t);
-extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
+extern void do_generic_mapping_read(struct address_space *, struct file_ra_state *, struct file *,
+				    loff_t *, read_descriptor_t *, read_actor_t);
 extern ssize_t generic_file_direct_IO(int rw, struct file *file,
 	const struct iovec *iov, loff_t offset, unsigned long nr_segs);
 extern int generic_direct_IO(int rw, struct inode *inode, const struct iovec 
@@ -1267,6 +1268,18 @@
 
 extern int generic_vm_writeback(struct page *page,
 				struct writeback_control *wbc);
+
+static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
+					read_descriptor_t * desc,
+					read_actor_t actor)
+{
+	do_generic_mapping_read(filp->f_dentry->d_inode->i_mapping,
+				&filp->f_ra,
+				filp,
+				ppos,
+				desc,
+				actor);
+}
 
 extern struct file_operations generic_ro_fops;
 
diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h
--- a/include/linux/genhd.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/genhd.h	Fri Oct 18 21:03:03 2002
@@ -80,6 +80,8 @@
 	char disk_name[16];		/* name of major driver */
 	struct hd_struct *part;		/* [indexed by minor] */
 	struct block_device_operations *fops;
+	struct request_queue *queue;
+	void *private_data;
 	sector_t capacity;
 	struct list_head list;
 	struct list_head full_list;
@@ -273,8 +275,12 @@
 extern struct gendisk *get_disk(struct gendisk *disk);
 extern void put_disk(struct gendisk *disk);
 
-/* will go away */
-extern void blk_set_probe(int major, struct gendisk *(p)(int));
+extern void blk_register_region(dev_t dev, unsigned long range,
+			struct module *module,
+			struct gendisk *(*probe)(dev_t, int *, void *),
+			void (*lock)(dev_t, void *),
+			void *data);
+extern void blk_unregister_region(dev_t dev, unsigned long range);
 
 #endif
 
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/ide.h	Fri Oct 18 21:03:04 2002
@@ -1256,7 +1256,6 @@
  */
 #define IDE_DRIVER		/* Toggle some magic bits in blk.h */
 #define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
-#define DEVICE_NR(device)	(minor(device) >> PARTN_BITS)
 #include <linux/blk.h>
 
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
@@ -1316,12 +1315,7 @@
  * This routine is called from the partition-table code in genhd.c
  * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
  */
-extern int ide_xlate_1024 (kdev_t, int, int, const char *);
-
-/*
- * Convert kdev_t structure into ide_drive_t * one.
- */
-extern ide_drive_t *get_info_ptr (kdev_t i_rdev);
+extern int ide_xlate_1024(struct block_device *, int, int, const char *);
 
 /*
  * Return the current idea about the total capacity of this drive.
@@ -1575,11 +1569,6 @@
  * to the hwgroup by sleeping for timeout jiffies.
  */
 extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
-
-/*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-extern request_queue_t *ide_get_queue (kdev_t dev);
 
 /*
  * CompactFlash cards and their brethern pretend to be removable hard disks,
diff -Nru a/include/linux/init.h b/include/linux/init.h
--- a/include/linux/init.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/init.h	Fri Oct 18 21:03:03 2002
@@ -93,18 +93,18 @@
  * Mark functions and data as being only used at initialization
  * or exit time.
  */
-#define __init		__attribute__ ((__section__ (".text.init")))
-#define __exit		__attribute__ ((unused, __section__(".text.exit")))
-#define __initdata	__attribute__ ((__section__ (".data.init")))
-#define __exitdata	__attribute__ ((unused, __section__ (".data.exit")))
-#define __initsetup	__attribute__ ((unused,__section__ (".setup.init")))
+#define __init		__attribute__ ((__section__ (".init.text")))
+#define __exit		__attribute__ ((unused, __section__(".exit.text")))
+#define __initdata	__attribute__ ((__section__ (".init.data")))
+#define __exitdata	__attribute__ ((unused, __section__ (".exit.data")))
+#define __initsetup	__attribute__ ((unused,__section__ (".init.setup")))
 #define __init_call(level)  __attribute__ ((unused,__section__ (".initcall" level ".init")))
 #define __exit_call	__attribute__ ((unused,__section__ (".exitcall.exit")))
 
 /* For assembly routines */
-#define __INIT		.section	".text.init","ax"
+#define __INIT		.section	".init.text","ax"
 #define __FINIT		.previous
-#define __INITDATA	.section	".data.init","aw"
+#define __INITDATA	.section	".init.data","aw"
 
 /**
  * module_init() - driver initialization entry point
diff -Nru a/include/linux/ioctl32.h b/include/linux/ioctl32.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/ioctl32.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,23 @@
+#ifndef IOCTL32_H
+#define IOCTL32_H 1
+
+struct file;
+
+int sys_ioctl(unsigned int, unsigned int, unsigned long);
+
+/* 
+ * Register an 32bit ioctl translation handler for ioctl cmd.
+ *
+ * handler == NULL: use 64bit ioctl handler.
+ * arguments to handler:  fd: file descriptor
+ *                        cmd: ioctl command.
+ *                        arg: ioctl argument
+ *                        struct file *file: file descriptor pointer.
+ */ 
+
+extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
+
+extern int unregister_ioctl32_conversion(unsigned int cmd);
+
+
+#endif
diff -Nru a/include/linux/ip.h b/include/linux/ip.h
--- a/include/linux/ip.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/ip.h	Fri Oct 18 21:03:04 2002
@@ -137,7 +137,23 @@
 	int			mc_index;	/* Multicast device index */
 	__u32			mc_addr;
 	struct ip_mc_socklist	*mc_list;	/* Group array */
+	struct page		*sndmsg_page;	/* Cached page for sendmsg */
+	u32			sndmsg_off;	/* Cached offset for sendmsg */
+	/*
+	 * Following members are used to retain the infomation to build
+	 * an ip header on each ip fragmentation while the socket is corked.
+	 */
+	struct {
+		unsigned int		flags;
+		unsigned int		fragsize;
+		struct ip_options	*opt;
+		struct rtable		*rt;
+		int			length; /* Total length of all frames */
+		u32			addr;
+	} cork;
 };
+
+#define IPCORK_OPT	1	/* ip-options has been held in ipcork.opt */
 
 struct ipv6_pinfo;
 
diff -Nru a/include/linux/isapnp.h b/include/linux/isapnp.h
--- a/include/linux/isapnp.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/isapnp.h	Fri Oct 18 21:03:04 2002
@@ -190,40 +190,49 @@
 void isapnp_deactivate(unsigned char device);
 void isapnp_fixup_device(struct pci_dev *dev);
 void *isapnp_alloc(long size);
+
+#ifdef CONFIG_PROC_FS
 int isapnp_proc_init(void);
 int isapnp_proc_done(void);
-/* manager */
-struct pci_bus *isapnp_find_card(unsigned short vendor,
-				 unsigned short device,
-				 struct pci_bus *from);
-struct pci_dev *isapnp_find_dev(struct pci_bus *card,
-				unsigned short vendor,
-				unsigned short function,
-				struct pci_dev *from);
-int isapnp_probe_cards(const struct isapnp_card_id *ids,
-		       int (*probe)(struct pci_bus *card,
-				    const struct isapnp_card_id *id));
-int isapnp_probe_devs(const struct isapnp_device_id *ids,
-			int (*probe)(struct pci_dev *dev,
-				     const struct isapnp_device_id *id));
+#else
+static inline isapnp_proc_init(void) { return 0; }
+static inline isapnp_proc_done(void) { return 0; )
+#endif
+
 /* misc */
 void isapnp_resource_change(struct resource *resource,
 			    unsigned long start,
 			    unsigned long size);
-int isapnp_activate_dev(struct pci_dev *dev, const char *name);
 /* init/main.c */
 int isapnp_init(void);
+/* manager */
+static inline struct pci_bus *isapnp_find_card(unsigned short vendor,
+					       unsigned short device,
+					       struct pci_bus *from) { return NULL; }
+static inline struct pci_dev *isapnp_find_dev(struct pci_bus *card,
+					      unsigned short vendor,
+					      unsigned short function,
+					      struct pci_dev *from) { return NULL; }
+static inline int isapnp_probe_cards(const struct isapnp_card_id *ids,
+				     int (*probe)(struct pci_bus *card,
+						  const struct isapnp_card_id *id)) { return -ENODEV; }
+static inline int isapnp_probe_devs(const struct isapnp_device_id *ids,
+				    int (*probe)(struct pci_dev *dev,
+						 const struct isapnp_device_id *id)) { return -ENODEV; }
+static inline int isapnp_activate_dev(struct pci_dev *dev, const char *name) { return -ENODEV; }
+
+static inline int isapnp_register_driver(struct isapnp_driver *drv) { return 0; }
+
+static inline void isapnp_unregister_driver(struct isapnp_driver *drv) { }
 
 extern struct list_head isapnp_cards;
 extern struct list_head isapnp_devices;
+extern struct pnp_protocol isapnp_protocol;
 
 #define isapnp_for_each_card(card) \
-	for(card = pci_bus_b(isapnp_cards.next); card != pci_bus_b(&isapnp_cards); card = pci_bus_b(card->node.next))
+	for(card = to_pnp_card(isapnp_cards.next); card != to_pnp_card(&isapnp_cards); card = to_pnp_card(card->node.next))
 #define isapnp_for_each_dev(dev) \
-	for(dev = pci_dev_g(isapnp_devices.next); dev != pci_dev_g(&isapnp_devices); dev = pci_dev_g(dev->global_list.next))
-
-int isapnp_register_driver(struct isapnp_driver *drv);
-void isapnp_unregister_driver(struct isapnp_driver *drv);
+	for(dev = protocol_to_pnp_dev(isapnp_protocol.devices.next); dev != protocol_to_pnp_dev(&isapnp_protocol.devices); dev = protocol_to_pnp_dev(dev->dev_list.next))
 
 #else /* !CONFIG_ISAPNP */
 
diff -Nru a/include/linux/isdn.h b/include/linux/isdn.h
--- a/include/linux/isdn.h	Fri Oct 18 21:03:08 2002
+++ b/include/linux/isdn.h	Fri Oct 18 21:03:08 2002
@@ -338,16 +338,35 @@
 				       /* phone[0] = Incoming Numbers      */
 				       /* phone[1] = Outgoing Numbers      */
 
-  struct list_head       slaves;       /* list of all bundled channels     */
-  struct list_head       online;       /* list of all bundled channels, 
-					  which are currently online       */
-  spinlock_t             online_lock;  /* lock to protect online list      */
+  struct list_head       slaves;       /* list of all bundled channels    
+					  protected by serializing config
+					  ioctls / no change allowed when
+					  interface is running             */
+  struct list_head       online;       /* list of all bundled channels 
+					  which can be used for actual
+					  data (IP) transfer              
+					  protected by xmit_lock           */
+
+  spinlock_t             xmit_lock;    /* used to protect the xmit path of 
+					  a net_device, including all
+					  associated channels's frame_cnt  */
   struct list_head       running_devs; /* member of global running_devs    */
   atomic_t               refcnt;       /* references held by ISDN code     */
 
 #ifdef CONFIG_ISDN_X25
   struct concap_device_ops *dops;      /* callbacks used by encapsulator   */
 #endif
+#ifdef CONFIG_ISDN_PPP
+  unsigned int           mpppcfg;
+  long                   mp_seqno;
+  struct ippp_ccp        *ccp;
+  unsigned long          debug;
+#ifdef CONFIG_ISDN_PPP_VJ
+  unsigned char         *cbuf;
+  struct slcompress     *slcomp;
+#endif
+#endif
+
   /* use an own struct for that in later versions */
   ulong cisco_myseq;                   /* Local keepalive seq. for Cisco   */
   ulong cisco_mineseen;                /* returned keepalive seq. from remote */
@@ -391,14 +410,11 @@
   int                    chargeint;    /* Interval between charge-infos    */
 
   int                    pppbind;      /* ippp device for bindings         */
-  int			 ppp_slot;     /* PPPD device slot number          */
+  struct ipppd          *ipppd;        /* /dev/ipppX which controls us     */
 
-  spinlock_t             xmit_lock;    /* used to protect the xmit path of */
-                                       /* a particular channel (including  */
-                                       /* the frame_cnt                    */
   struct sk_buff_head    super_tx_queue; /* List of supervisory frames to  */
 	                               /* be transmitted asap              */
-  atomic_t               frame_cnt;    /* number of frames currently       */
+  int                    frame_cnt;    /* number of frames currently       */
                         	       /* queued in HL driver              */
   struct tasklet_struct  tlet;
 
@@ -410,6 +426,11 @@
   char                   name[10];     /* Name of device                   */
   struct list_head       global_list;  /* global list of all isdn_net_devs */
 #ifdef CONFIG_ISDN_PPP
+  unsigned int           pppcfg;
+  unsigned int           pppseq;       /* last seq no seen                 */
+  struct ippp_ccp        *ccp;
+  unsigned long          debug;
+
   ippp_bundle * pb;		/* pointer to the common bundle structure
    			         * with the per-bundle data */
 #endif
diff -Nru a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
--- a/include/linux/isdn_ppp.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/isdn_ppp.h	Fri Oct 18 21:03:03 2002
@@ -8,7 +8,6 @@
 #ifndef _LINUX_ISDN_PPP_H
 #define _LINUX_ISDN_PPP_H
 
-
 #define CALLTYPE_INCOMING 0x1
 #define CALLTYPE_OUTGOING 0x2
 #define CALLTYPE_CALLBACK 0x4
@@ -39,15 +38,6 @@
 #define SC_OUT_SHORT_SEQ 0x00000800
 #define SC_IN_SHORT_SEQ  0x00004000
 
-#define SC_DECOMP_ON		0x01
-#define SC_COMP_ON		0x02
-#define SC_DECOMP_DISCARD	0x04
-#define SC_COMP_DISCARD		0x08
-#define SC_LINK_DECOMP_ON	0x10
-#define SC_LINK_COMP_ON		0x20
-#define SC_LINK_DECOMP_DISCARD	0x40
-#define SC_LINK_COMP_DISCARD	0x80
-
 #define ISDN_PPP_COMP_MAX_OPTIONS 16
 
 #define IPPP_COMP_FLAG_XMIT 0x1
@@ -64,7 +54,8 @@
 
 
 #include <linux/config.h>
-
+#include <linux/skbuff.h>
+#include <linux/ppp_defs.h>
 
 #define DECOMP_ERR_NOMEM	(-10)
 
@@ -172,8 +163,8 @@
 
 struct ippp_ccp_reset_state {
   enum ippp_ccp_reset_states state;	/* State of this transaction */
-  struct ippp_struct *is;		/* Backlink to device stuff */
-  unsigned char id;			/* Backlink id index */
+  struct ippp_ccp *ccp;                 /* Backlink */
+  unsigned char id;			/* id index */
   unsigned char ta:1;			/* The timer is active (flag) */
   unsigned char expra:1;		/* We expect a ResetAck at all */
   int dlen;				/* Databytes stored in data */
@@ -189,35 +180,6 @@
 struct ippp_ccp_reset {
   struct ippp_ccp_reset_state *rs[256];	/* One per possible id */
   unsigned char lastid;			/* Last id allocated by the engine */
-};
-
-struct ippp_struct {
-  struct ippp_struct *next_link;
-  int state;
-  struct sk_buff_head rq;
-  wait_queue_head_t wq;
-  struct task_struct *tk;
-  unsigned int mpppcfg;
-  unsigned int pppcfg;
-  unsigned int mru;
-  unsigned int mpmru;
-  unsigned int mpmtu;
-  unsigned int maxcid;
-  struct isdn_net_dev_s *idev;
-  int unit;
-  int minor;
-  unsigned int last_link_seqno;
-  long mp_seqno;
-#ifdef CONFIG_ISDN_PPP_VJ
-  unsigned char *cbuf;
-  struct slcompress *slcomp;
-#endif
-  unsigned long debug;
-  struct isdn_ppp_compressor *compressor,*decompressor;
-  struct isdn_ppp_compressor *link_compressor,*link_decompressor;
-  void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
-  struct ippp_ccp_reset *reset;	/* Allocated on demand, may never be needed */
-  unsigned long compflags;
 };
 
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/kernel.h	Fri Oct 18 21:03:03 2002
@@ -200,6 +200,12 @@
 };
 
 #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
 
 extern void BUILD_BUG(void);
 #define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/list.h	Fri Oct 18 21:03:03 2002
@@ -4,6 +4,7 @@
 #if defined(__KERNEL__) || defined(_LVM_H_INCLUDE)
 
 #include <linux/prefetch.h>
+#include <asm/system.h>
 
 /*
  * Simple doubly linked list implementation.
@@ -71,6 +72,49 @@
 }
 
 /*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add_rcu(struct list_head * new,
+	struct list_head * prev,
+	struct list_head * next)
+{
+	new->next = next;
+	new->prev = prev;
+	wmb();
+	next->prev = new;
+	prev->next = new;
+}
+
+/**
+ * list_add_rcu - add a new entry to rcu-protected list
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static __inline__ void list_add_rcu(struct list_head *new, struct list_head *head)
+{
+	__list_add_rcu(new, head, head->next);
+}
+
+/**
+ * list_add_tail_rcu - add a new entry to rcu-protected list
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static __inline__ void list_add_tail_rcu(struct list_head *new, struct list_head *head)
+{
+	__list_add_rcu(new, head->prev, head);
+}
+
+/*
  * Delete a list entry by making the prev/next entries
  * point to each other.
  *
@@ -93,6 +137,17 @@
 {
 	__list_del(entry->prev, entry->next);
 }
+/**
+ * list_del_rcu - deletes entry from list without re-initialization
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, 
+ * the entry is in an undefined state. It is useful for RCU based
+ * lockfree traversal.
+ */
+static inline void list_del_rcu(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
 
 /**
  * list_del_init - deletes entry from list and reinitialize it.
@@ -239,6 +294,30 @@
 	     &pos->member != (head); 					\
 	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
 		     prefetch(pos->member.next))
+
+/**
+ * list_for_each_rcu	-	iterate over an rcu-protected list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each_rcu(pos, head) \
+	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+        	pos = pos->next, ({ read_barrier_depends(); 0;}), prefetch(pos->next))
+        	
+#define __list_for_each_rcu(pos, head) \
+	for (pos = (head)->next; pos != (head); \
+        	pos = pos->next, ({ read_barrier_depends(); 0;}))
+        	
+/**
+ * list_for_each_safe_rcu	-	iterate over an rcu-protected list safe
+ *					against removal of list entry
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_safe_rcu(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, ({ read_barrier_depends(); 0;}), n = pos->next)
 
 #endif /* __KERNEL__ || _LVM_H_INCLUDE */
 
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/mm.h	Fri Oct 18 21:03:03 2002
@@ -504,7 +504,6 @@
 extern void truncate_inode_pages(struct address_space *, loff_t);
 
 /* generic vm_area_ops exported for stackable file systems */
-extern int filemap_sync(struct vm_area_struct *, unsigned long,	size_t, unsigned int);
 extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int);
 
 /* mm/page-writeback.c */
@@ -513,11 +512,18 @@
 /* readahead.c */
 #define VM_MAX_READAHEAD	128	/* kbytes */
 #define VM_MIN_READAHEAD	16	/* kbytes (includes current page) */
-int do_page_cache_readahead(struct file *file,
+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 file *file, unsigned long offset);
-void page_cache_readaround(struct file *file, unsigned long offset);
-void handle_ra_miss(struct file *file);
+void page_cache_readahead(struct address_space *mapping, 
+			  struct file_ra_state *ra,
+			  struct file *filp,
+			  unsigned long offset);
+void page_cache_readaround(struct address_space *mapping, 
+			   struct file_ra_state *ra,
+			   struct file *filp,
+			   unsigned long offset);
+void handle_ra_miss(struct address_space *mapping, 
+		    struct file_ra_state *ra);
 
 /* Do stack extension */
 extern int expand_stack(struct vm_area_struct * vma, unsigned long address);
diff -Nru a/include/linux/nbd.h b/include/linux/nbd.h
--- a/include/linux/nbd.h	Fri Oct 18 21:03:08 2002
+++ b/include/linux/nbd.h	Fri Oct 18 21:03:08 2002
@@ -74,12 +74,15 @@
 #define NBD_READ_ONLY 0x0001
 #define NBD_WRITE_NOCHK 0x0002
 	struct socket * sock;
-	struct file * file; 		/* If == NULL, device is not ready, yet	*/
-	int magic;			/* FIXME: not if debugging is off	*/
+	struct file * file; 	/* If == NULL, device is not ready, yet	*/
+	int magic;		/* FIXME: not if debugging is off	*/
 	spinlock_t queue_lock;
-	struct list_head queue_head;	/* Requests are added here...			*/
+	struct list_head queue_head;/* Requests are added here...	*/
 	struct semaphore tx_lock;
 	struct gendisk *disk;
+	int blksize;
+	int blksize_bits;
+	u64 bytesize;
 };
 #endif
 
diff -Nru a/include/linux/net.h b/include/linux/net.h
--- a/include/linux/net.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/net.h	Fri Oct 18 21:03:04 2002
@@ -144,6 +144,9 @@
 				  const struct iovec * iov, long count, long size);
 extern int 	sock_map_fd(struct socket *sock);
 
+extern struct socket *sockfd_lookup(int fd, int *err);
+#define         sockfd_put(sock) fput(sock->file)
+
 extern int	net_ratelimit(void);
 extern unsigned long net_random(void);
 extern void net_srandom(unsigned long);
diff -Nru a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
--- a/include/linux/nfsd/nfsd.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/nfsd/nfsd.h	Fri Oct 18 21:03:04 2002
@@ -63,22 +63,15 @@
 						int, loff_t, ino_t, unsigned int);
 typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
 
-/*
- * Procedure table for NFSv2
- */
-extern struct svc_procedure	nfsd_procedures2[];
-#ifdef CONFIG_NFSD_V3
-extern struct svc_procedure	nfsd_procedures3[];
-#endif /* CONFIG_NFSD_V3 */
-#ifdef CONFIG_NFSD_V4
-extern struct svc_procedure	nfsd_procedures4[];
-#endif /* CONFIG_NFSD_V4 */
 extern struct svc_program	nfsd_program;
+extern struct svc_version	nfsd_version2, nfsd_version3,
+				nfsd_version4;
 
 /*
  * Function prototypes.
  */
 int		nfsd_svc(unsigned short port, int nrservs);
+int		nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp);
 
 /* nfsd/vfs.c */
 int		fh_lock_parent(struct svc_fh *, struct dentry *);
diff -Nru a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
--- a/include/linux/nfsd/xdr4.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/nfsd/xdr4.h	Fri Oct 18 21:03:03 2002
@@ -224,6 +224,12 @@
 	char *		se_callback_addr_val;   /* request */
 	u32		se_callback_ident;  /* request */
 	clientid_t	se_clientid;        /* response */
+	nfs4_verifier	se_confirm;         /* response */
+};
+
+struct nfsd4_setclientid_confirm {
+	clientid_t	sc_clientid;
+	nfs4_verifier	sc_confirm;
 };
 
 /* also used for NVERIFY */
@@ -267,7 +273,7 @@
 		clientid_t			renew;
 		struct nfsd4_setattr		setattr;
 		struct nfsd4_setclientid	setclientid;
-		clientid_t			setclientid_confirm;
+		struct nfsd4_setclientid_confirm setclientid_confirm;
 		struct nfsd4_verify		verify;
 		struct nfsd4_write		write;
 	} u;
@@ -298,7 +304,6 @@
 
 #define NFS4_SVC_XDRSIZE		sizeof(struct nfsd4_compoundargs)
 
-#if CONFIG_NFSD_V3
 static inline void
 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
@@ -309,7 +314,6 @@
 	cinfo->after_size = fhp->fh_post_size;
 	cinfo->after_ctime = fhp->fh_post_ctime;
 }
-#endif
 
 int nfs4svc_encode_voidres(struct svc_rqst *, u32 *, void *);
 int nfs4svc_decode_compoundargs(struct svc_rqst *, u32 *, struct nfsd4_compoundargs *);
diff -Nru a/include/linux/pnp.h b/include/linux/pnp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/pnp.h	Fri Oct 18 21:03:09 2002
@@ -0,0 +1,285 @@
+#ifndef _LINUX_PNP_H
+#define _LINUX_PNP_H
+
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/list.h>
+
+
+/* Device Managemnt */
+
+#define DEVICE_COUNT_IRQ	2
+#define DEVICE_COUNT_DMA	2
+#define DEVICE_COUNT_RESOURCE	12
+
+struct pnp_resource;
+struct pnp_protocol;
+
+struct pnp_card {			/* this is for ISAPNP */ 
+	struct list_head node;		/* node in list of cards */
+	char name[80];
+	unsigned char number;		/* card number */
+	struct list_head ids;		/* stores all supported dev ids */
+	struct list_head devices;	/* devices attached to the card */
+	unsigned char	pnpver;		/* Plug & Play version */
+	unsigned char	productver;	/* product version */
+	unsigned int	serial;		/* serial number */
+	unsigned char	checksum;	/* if zero - checksum passed */
+	struct proc_dir_entry *procdir;	/* directory entry in /proc/bus/isapnp */
+};
+
+#define to_pnp_card(n) list_entry(n, struct pnp_card, node)
+
+struct pnp_dev {
+	char name[80];			/* device name */
+	int active;			/* status of the device */
+	int ro;				/* read only */
+	struct list_head dev_list;	/* node in list of device's protocol */
+	struct list_head global_list;
+	struct list_head card_list;
+	struct pnp_protocol * protocol;
+	struct pnp_card *card;
+
+	unsigned char number;		/* must be unique */
+	unsigned short	regs;		/* ISAPnP: supported registers */
+	struct list_head ids;		/* stores all supported dev ids */
+	struct pnp_resources *res;	/* possible resource information */
+	struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
+	struct resource dma_resource[DEVICE_COUNT_DMA];
+	struct resource irq_resource[DEVICE_COUNT_IRQ];
+
+	struct pnp_driver * driver;	/* which driver has allocated this device */
+	struct	device	    dev;	/* Driver Model device interface */
+	void  		  * driver_data;/* data private to the driver */
+	void		  * protocol_data;
+	struct proc_dir_entry *procent;	/* device entry in /proc/bus/isapnp */
+};
+
+#define global_to_pnp_dev(n) list_entry(n, struct pnp_dev, global_list)
+#define card_to_pnp_dev(n) list_entry(n, struct pnp_dev, card_list)
+#define protocol_to_pnp_dev(n) list_entry(n, struct pnp_dev, dev_list)
+#define	to_pnp_dev(n) container_of(n, struct pnp_dev, dev)
+#define pnp_for_each_dev(dev) \
+	for(dev = global_to_pnp_dev(pnp_global.next); \
+	dev != global_to_pnp_dev(&pnp_global); \
+	dev = global_to_pnp_dev(dev->global_list.next))
+
+struct pnp_fixup {
+	char id[7];
+	void (*quirk_function)(struct pnp_dev *dev);	/* fixup function */
+};
+
+/*
+ * Linux Plug and Play Support
+ * Copyright by Adam Belay <ambx1@neo.rr.com>
+ *
+ */
+
+/* Driver Management */
+
+struct pnp_id {
+	char id[7];
+	unsigned long driver_data;	/* data private to the driver */
+	struct list_head id_list;	/* node in card's or device's list */
+};
+
+#define to_pnp_id(n) list_entry(n, struct pnp_id, id_list)
+
+struct pnp_driver {
+	struct list_head node;
+	char *name;
+	const struct pnp_id *card_id_table;
+	const struct pnp_id *id_table;
+	int  (*probe)  (struct pnp_dev *dev, const struct pnp_id *card_id,
+		 	const struct pnp_id *dev_id);
+	void (*remove) (struct pnp_dev *dev);
+	struct device * (*legacy) (void);
+	struct device_driver	driver;
+};
+
+#define	to_pnp_driver(drv) container_of(drv,struct pnp_driver, driver)
+
+
+/* Resource Management */
+
+#define DEV_IO(dev, index) (dev->resource[index].start)
+#define DEV_MEM(dev, index) (dev->resource[index+8].start)
+#define DEV_IRQ(dev, index) (dev->irq_resource[index].start)
+#define DEV_DMA(dev, index) (dev->dma_resource[index].start)
+
+#define PNP_PORT_FLAG_16BITADDR	(1<<0)
+#define PNP_PORT_FLAG_FIXED		(1<<1)
+
+struct pnp_port {
+	unsigned short min;		/* min base number */
+	unsigned short max;		/* max base number */
+	unsigned char align;		/* align boundary */
+	unsigned char size;		/* size of range */
+	unsigned char flags;		/* port flags */
+	unsigned char pad;		/* pad */
+	struct pnp_resources *res;	/* parent */
+	struct pnp_port *next;		/* next port */
+};
+
+struct pnp_irq {
+	unsigned short map;		/* bitmaks for IRQ lines */
+	unsigned char flags;		/* IRQ flags */
+	unsigned char pad;		/* pad */
+	struct pnp_resources *res;	/* parent */
+	struct pnp_irq *next;		/* next IRQ */
+};
+
+struct pnp_dma {
+	unsigned char map;		/* bitmask for DMA channels */
+	unsigned char flags;		/* DMA flags */
+	struct pnp_resources *res;	/* parent */
+	struct pnp_dma *next;		/* next port */
+};
+
+struct pnp_mem {
+	unsigned int min;		/* min base number */
+	unsigned int max;		/* max base number */
+	unsigned int align;		/* align boundary */
+	unsigned int size;		/* size of range */
+	unsigned char flags;		/* memory flags */
+	unsigned char pad;		/* pad */
+	struct pnp_resources *res;	/* parent */
+	struct pnp_mem *next;		/* next memory resource */
+};
+
+struct pnp_mem32 {
+	unsigned char data[17];
+	struct pnp_resources *res;	/* parent */
+	struct pnp_mem32 *next;		/* next 32-bit memory resource */
+};
+
+#define PNP_RES_PRIORITY_PREFERRED	0
+#define PNP_RES_PRIORITY_ACCEPTABLE	1
+#define PNP_RES_PRIORITY_FUNCTIONAL	2
+#define PNP_RES_PRIORITY_INVALID	65535
+
+struct pnp_resources {
+	unsigned short priority;	/* priority */
+	unsigned short dependent;	/* dependent resources */
+	struct pnp_port *port;		/* first port */
+	struct pnp_irq *irq;		/* first IRQ */
+	struct pnp_dma *dma;		/* first DMA */
+	struct pnp_mem *mem;		/* first memory resource */
+	struct pnp_mem32 *mem32;	/* first 32-bit memory */
+	struct pnp_dev *dev;		/* parent */
+	struct pnp_resources *dep;	/* dependent resources */
+};
+
+#define PNP_DYNAMIC		0	/* get or set current resource */
+#define PNP_STATIC		1	/* get or set resource for next boot */
+
+struct pnp_cfg {
+	struct pnp_port *port[8];
+	struct pnp_irq *irq[2];
+	struct pnp_dma *dma[2];
+	struct pnp_mem *mem[4];
+	struct pnp_dev request;
+};
+
+
+/* Protocol Management */
+
+struct pnp_protocol {
+	struct list_head	protocol_list;
+	char			name[DEVICE_NAME_SIZE];
+
+	/* functions */
+	int (*get)(struct pnp_dev *dev);
+	int (*set)(struct pnp_dev *dev, struct pnp_cfg *config, char flags);
+	int (*disable)(struct pnp_dev *dev);
+
+	/* used by pnp layer only (look but don't touch) */
+	unsigned char		number;		/* protocol number*/
+	struct device		dev;		/* link to driver model */
+	struct list_head	devices;
+};
+
+#define to_pnp_protocol(n) list_entry(n, struct pnp_protocol, protocol_list)
+
+
+#if defined(CONFIG_PNP)
+
+/* core */
+int pnp_protocol_register(struct pnp_protocol *protocol);
+void pnp_protocol_unregister(struct pnp_protocol *protocol);
+int pnp_init_device(struct pnp_dev *dev);
+int pnp_add_device(struct pnp_dev *dev);
+void pnp_remove_device(struct pnp_dev *dev);
+extern struct list_head pnp_global;
+
+/* resource */
+struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent);
+struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum);
+int pnp_get_max_depnum(struct pnp_dev *dev);
+int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data);
+int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data);
+int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data);
+int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data);
+int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_mem32 *data);
+int pnp_activate_dev(struct pnp_dev *dev);
+int pnp_disable_dev(struct pnp_dev *dev);
+int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, int mode);
+
+/* driver */
+int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev);
+int pnp_register_driver(struct pnp_driver *drv);
+void pnp_unregister_driver(struct pnp_driver *drv);
+
+/* compat */
+struct pnp_card *pnp_find_card(unsigned short vendor,
+				 unsigned short device,
+				 struct pnp_card *from);
+struct pnp_dev *pnp_find_dev(struct pnp_card *card,
+				unsigned short vendor,
+				unsigned short function,
+				struct pnp_dev *from);
+
+
+#else
+
+/* just in case anyone decides to call these without PnP Support Enabled */
+static inline int pnp_protocol_register(struct pnp_protocol *protocol) { return -ENODEV; }
+static inline void pnp_protocol_unregister(struct pnp_protocol *protocol) { ; )
+static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; }
+static inline void pnp_remove_device(struct pnp_dev *dev) { ; }
+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; }
+static inline int pnp_get_max_depnum(struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
+static inline int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
+static inline int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
+static inline int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
+static inline int pnp_add_mem32_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; }
+static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, int mode) { return -ENODEV; }
+static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; }
+static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; }
+static inline struct pnp_card *pnp_find_card(unsigned short vendor,
+				 unsigned short device,
+				 struct pnp_card *from) { return NULL; }
+static inline struct pnp_dev *pnp_find_dev(struct pnp_card *card,
+				unsigned short vendor,
+				unsigned short function,
+				struct pnp_dev *from) { return NULL; }
+
+#endif /* CONFIG_PNP */
+
+
+#ifdef DEBUG
+#define pnp_dbg(format, arg...) printk(KERN_DEBUG "pnp: " format "\n" , ## arg)
+#else
+#define pnp_dbg(format, arg...) do {} while (0)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_PNP_H */
diff -Nru a/include/linux/pnpbios.h b/include/linux/pnpbios.h
--- a/include/linux/pnpbios.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/pnpbios.h	Fri Oct 18 21:03:04 2002
@@ -108,38 +108,9 @@
 };
 #pragma pack()
 
-struct pnpbios_device_id
-{
-	char id[8];
-	unsigned long driver_data;
-};
-
-struct pnpbios_driver {
-	struct list_head node;
-	char *name;
-	const struct pnpbios_device_id *id_table;	/* NULL if wants all devices */
-	int  (*probe)  (struct pci_dev *dev, const struct pnpbios_device_id *id);	/* New device inserted */
-	void (*remove) (struct pci_dev *dev);		/* Device removed, either due to hotplug remove or module remove */
-};
-
 #ifdef CONFIG_PNPBIOS
 
-/* exported */
-extern int  pnpbios_register_driver(struct pnpbios_driver *drv);
-extern void pnpbios_unregister_driver(struct pnpbios_driver *drv);
-
 /* non-exported */
-#define pnpbios_for_each_dev(dev) \
-	for(dev = pnpbios_dev_g(pnpbios_devices.next); dev != pnpbios_dev_g(&pnpbios_devices); dev = pnpbios_dev_g(dev->global_list.next))
-
-
-#define pnpbios_dev_g(n) list_entry(n, struct pci_dev, global_list)
-
-static __inline struct pnpbios_driver *pnpbios_dev_driver(const struct pci_dev *dev)
-{
-	return (struct pnpbios_driver *)dev->driver;
-}
-
 extern int  pnpbios_dont_use_current_config;
 extern void *pnpbios_kmalloc(size_t size, int f);
 extern int pnpbios_init (void);
@@ -161,52 +132,8 @@
 extern int pnp_bios_write_escd (char *data, u32 nvram_base);
 #endif
 
-/*
- * a helper function which helps ensure correct pnpbios_driver
- * setup and cleanup for commonly-encountered hotplug/modular cases
- *
- * This MUST stay in a header, as it checks for -DMODULE
- */
- 
-static inline int pnpbios_module_init(struct pnpbios_driver *drv)
-{
-	int rc = pnpbios_register_driver (drv);
-
-	if (rc > 0)
-		return 0;
-
-	/* iff CONFIG_HOTPLUG and built into kernel, we should
-	 * leave the driver around for future hotplug events.
-	 * For the module case, a hotplug daemon of some sort
-	 * should load a module in response to an insert event. */
-#if defined(CONFIG_HOTPLUG) && !defined(MODULE)
-	if (rc == 0)
-		return 0;
-#else
-	if (rc == 0)
-		rc = -ENODEV;		
-#endif
-
-	/* if we get here, we need to clean up pci driver instance
-	 * and return some sort of error */
-	pnpbios_unregister_driver (drv);
-	
-	return rc;
-}
-
-#else /* CONFIG_PNPBIOS */
-
-static __inline__ int pnpbios_register_driver(struct pnpbios_driver *drv)
-{
-	return 0;
-}
-
-static __inline__ void pnpbios_unregister_driver(struct pnpbios_driver *drv)
-{
-	return;
-}
-
 #endif /* CONFIG_PNPBIOS */
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_PNPBIOS_H */
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/sched.h	Fri Oct 18 21:03:03 2002
@@ -106,23 +106,13 @@
 
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
-#ifdef CONFIG_SMP
 #define set_task_state(tsk, state_value)		\
 	set_mb((tsk)->state, (state_value))
-#else
-#define set_task_state(tsk, state_value)		\
-	__set_task_state((tsk), (state_value))
-#endif
 
 #define __set_current_state(state_value)			\
 	do { current->state = (state_value); } while (0)
-#ifdef CONFIG_SMP
 #define set_current_state(state_value)		\
 	set_mb(current->state, (state_value))
-#else
-#define set_current_state(state_value)		\
-	__set_current_state(state_value)
-#endif
 
 /*
  * Scheduling policies
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/security.h	Fri Oct 18 21:03:03 2002
@@ -376,10 +376,6 @@
  * @file_free_security:
  *	Deallocate and free any security structures stored in file->f_security.
  *	@file contains the file structure being modified.
- * @file_llseek:
- *	Check permission before re-positioning the file offset in @file.
- *	@file contains the file structure being modified.
- *	Return 0 if permission is granted.
  * @file_ioctl:
  *	@file contains the file structure.
  *	@cmd contains the operation to perform.
@@ -790,7 +786,6 @@
 	int (*file_permission) (struct file * file, int mask);
 	int (*file_alloc_security) (struct file * file);
 	void (*file_free_security) (struct file * file);
-	int (*file_llseek) (struct file * file);
 	int (*file_ioctl) (struct file * file, unsigned int cmd,
 			   unsigned long arg);
 	int (*file_mmap) (struct file * file,
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/serial_core.h	Fri Oct 18 21:03:03 2002
@@ -396,6 +396,6 @@
  */
 #define UART_ENABLE_MS(port,cflag)	((port)->flags & UPF_HARDPPS_CD || \
 					 (cflag) & CRTSCTS || \
-					 !(cflag) & CLOCAL)
+					 !((cflag) & CLOCAL))
 
 #endif
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	Fri Oct 18 21:03:05 2002
+++ b/include/linux/skbuff.h	Fri Oct 18 21:03:05 2002
@@ -765,6 +765,15 @@
 	return skb->len - skb->data_len;
 }
 
+static inline int skb_pagelen(const struct sk_buff *skb)
+{
+	int i, len = 0;
+
+	for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)
+		len += skb_shinfo(skb)->frags[i].size;
+	return len + skb_headlen(skb);
+}
+
 #define SKB_PAGE_ASSERT(skb) do { if (skb_shinfo(skb)->nr_frags) \
 					BUG(); } while (0)
 #define SKB_FRAG_ASSERT(skb) do { if (skb_shinfo(skb)->frag_list) \
diff -Nru a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
--- a/include/linux/sunrpc/cache.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/sunrpc/cache.h	Fri Oct 18 21:03:04 2002
@@ -271,16 +271,16 @@
 extern struct cache_detail *cache_find(char *name);
 extern void cache_drop(struct cache_detail *detail);
 
-extern void add_word(char **bpp, int *lp, char *str);
-extern void add_hex(char **bpp, int *lp, char *buf, int blen);
-extern int get_word(char **bpp, char *dest, int bufsize);
+extern void qword_add(char **bpp, int *lp, char *str);
+extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
+extern int qword_get(char **bpp, char *dest, int bufsize);
 
 static inline int get_int(char **bpp, int *anint)
 {
 	char buf[50];
 	char *ep;
 	int rv;
-	int len = get_word(bpp, buf, 50);
+	int len = qword_get(bpp, buf, 50);
 	if (len < 0) return -EINVAL;
 	if (len ==0) return -ENOENT;
 	rv = simple_strtol(buf, &ep, 0);
diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
--- a/include/linux/sunrpc/svc.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/sunrpc/svc.h	Fri Oct 18 21:03:04 2002
@@ -167,6 +167,7 @@
 	u32			vs_vers;	/* version number */
 	u32			vs_nproc;	/* number of procedures */
 	struct svc_procedure *	vs_proc;	/* per-procedure info */
+	u32			vs_xdrsize;	/* xdrsize needed for this version */
 
 	/* Override dispatch function (e.g. when caching replies).
 	 * A return value of 0 means drop the request. 
@@ -199,7 +200,7 @@
 /*
  * Function prototypes.
  */
-struct svc_serv *  svc_create(struct svc_program *, unsigned int, unsigned int);
+struct svc_serv *  svc_create(struct svc_program *, unsigned int);
 int		   svc_create_thread(svc_thread_fn, struct svc_serv *);
 void		   svc_exit_thread(struct svc_rqst *);
 void		   svc_destroy(struct svc_serv *);
diff -Nru a/include/linux/sysfs.h b/include/linux/sysfs.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/sysfs.h	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,51 @@
+/*
+ * sysfs.h - definitions for the device driver filesystem
+ *
+ * Copyright (c) 2001,2002 Patrick Mochel
+ *
+ * Please see Documentation/filesystems/sysfs.txt for more information.
+ */
+
+#ifndef _SYSFS_H_
+#define _SYSFS_H_
+
+struct driver_dir_entry;
+struct attribute;
+
+struct sysfs_ops {
+	int	(*open)(struct driver_dir_entry *);
+	int	(*close)(struct driver_dir_entry *);
+	ssize_t	(*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
+	ssize_t	(*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
+};
+
+struct driver_dir_entry {
+	char			* name;
+	struct dentry		* dentry;
+	mode_t			mode;
+	struct sysfs_ops	* ops;
+};
+
+struct attribute {
+	char			* name;
+	mode_t			mode;
+};
+
+extern int
+sysfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
+
+extern void
+sysfs_remove_dir(struct driver_dir_entry * entry);
+
+extern int
+sysfs_create_file(struct attribute * attr,
+		     struct driver_dir_entry * parent);
+
+extern int 
+sysfs_create_symlink(struct driver_dir_entry * parent, 
+			char * name, char * target);
+
+extern void
+sysfs_remove_file(struct driver_dir_entry *, const char * name);
+
+#endif /* _SYSFS_H_ */
diff -Nru a/include/linux/tcp.h b/include/linux/tcp.h
--- a/include/linux/tcp.h	Fri Oct 18 21:03:04 2002
+++ b/include/linux/tcp.h	Fri Oct 18 21:03:04 2002
@@ -285,8 +285,6 @@
 
 	struct tcp_func		*af_specific;	/* Operations which are AF_INET{4,6} specific	*/
 	struct sk_buff		*send_head;	/* Front of stuff to transmit			*/
-	struct page		*sndmsg_page;	/* Cached page for sendmsg			*/
-	u32			sndmsg_off;	/* Cached offset for sendmsg			*/
 
  	__u32	rcv_wnd;	/* Current receiver window		*/
 	__u32	rcv_wup;	/* rcv_nxt on last window update sent	*/
diff -Nru a/include/linux/udp.h b/include/linux/udp.h
--- a/include/linux/udp.h	Fri Oct 18 21:03:03 2002
+++ b/include/linux/udp.h	Fri Oct 18 21:03:03 2002
@@ -17,6 +17,9 @@
 #ifndef _LINUX_UDP_H
 #define _LINUX_UDP_H
 
+#include <asm/byteorder.h>
+#include <net/sock.h>
+#include <linux/ip.h>
 
 struct udphdr {
 	__u16	source;
@@ -25,5 +28,33 @@
 	__u16	check;
 };
 
+/* UDP socket options */
+#define UDP_CORK	1	/* Never send partially complete segments */
+
+struct udp_opt {
+	int		pending;	/* Any pending frames ? */
+	unsigned int	corkflag;	/* Cork is required */
+	/*
+	 * Following members retains the infomation to create a UDP header
+	 * when the socket is uncorked.
+	 */
+	u32		saddr;		/* source address */
+	u32		daddr;		/* destination address */
+	__u16		sport;		/* source port */
+	__u16		dport;		/* destination port */
+	__u16		len;		/* total length of pending frames */
+};
+
+/* WARNING: don't change the layout of the members in udp_sock! */
+struct udp_sock {
+	struct sock	  sk;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct ipv6_pinfo *pinet6;
+#endif
+	struct inet_opt	  inet;
+	struct udp_opt	  udp;
+};
+
+#define udp_sk(__sk) (&((struct udp_sock *)__sk)->udp)
 
 #endif	/* _LINUX_UDP_H */
diff -Nru a/include/net/addrconf.h b/include/net/addrconf.h
--- a/include/net/addrconf.h	Fri Oct 18 21:03:03 2002
+++ b/include/net/addrconf.h	Fri Oct 18 21:03:03 2002
@@ -191,5 +191,21 @@
 	return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000);
 }
 
+static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
+{
+	return (addr->s6_addr32[0] == htonl(0xff020000) &&
+		addr->s6_addr32[1] == 0 &&
+		addr->s6_addr32[2] == 0 &&
+		addr->s6_addr32[3] == htonl(0x00000001));
+}
+
+static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
+{
+	return (addr->s6_addr32[0] == htonl(0xff020000) &&
+		addr->s6_addr32[1] == 0 &&
+		addr->s6_addr32[2] == 0 &&
+		addr->s6_addr32[3] == htonl(0x00000002));
+}
+
 #endif
 #endif
diff -Nru a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
--- a/include/net/bluetooth/hci.h	Fri Oct 18 21:03:08 2002
+++ b/include/net/bluetooth/hci.h	Fri Oct 18 21:03:08 2002
@@ -160,43 +160,42 @@
 #define HCI_LM_ENCRYPT	0x0004
 #define HCI_LM_TRUSTED	0x0008
 
-/* -----  HCI Commands ----- */
+/* -----  HCI Commands ---- */
 /* OGF & OCF values */
 
 /* Informational Parameters */
 #define OGF_INFO_PARAM	0x04
 
 #define OCF_READ_LOCAL_VERSION	0x0001
-typedef struct {
-	__u8  status;
-	__u8  hci_ver;
-	__u16 hci_rev;
-	__u8  lmp_ver;
-	__u16 manufacturer;
-	__u16 lmp_subver;
-} __attribute__ ((packed)) read_local_version_rp;
-#define READ_LOCAL_VERSION_RP_SIZE 9
+struct hci_rp_read_loc_version {
+	__u8     status;
+	__u8     hci_ver;
+	__u16    hci_rev;
+	__u8     lmp_ver;
+	__u16    manufacturer;
+	__u16    lmp_subver;
+} __attribute__ ((packed));
 
 #define OCF_READ_LOCAL_FEATURES	0x0003
-typedef struct {
+struct hci_rp_read_loc_features {
 	__u8 status;
 	__u8 features[8];
-} __attribute__ ((packed)) read_local_features_rp;
+} __attribute__ ((packed));
 
 #define OCF_READ_BUFFER_SIZE	0x0005
-typedef struct {
-	__u8 	status;
-	__u16 	acl_mtu;
-	__u8 	sco_mtu;
-	__u16 	acl_max_pkt;
-	__u16	sco_max_pkt;
-} __attribute__ ((packed)) read_buffer_size_rp;
+struct hci_rp_read_buffer_size {
+	__u8     status;
+	__u16    acl_mtu;
+	__u8     sco_mtu;
+	__u16    acl_max_pkt;
+	__u16    sco_max_pkt;
+} __attribute__ ((packed));
 
 #define OCF_READ_BD_ADDR	0x0009
-typedef struct {
-	__u8 status;
+struct hci_rp_read_bd_addr {
+	__u8     status;
 	bdaddr_t bdaddr;
-} __attribute__ ((packed)) read_bd_addr_rp;
+} __attribute__ ((packed));
 
 /* Host Controller and Baseband */
 #define OGF_HOST_CTL	0x03
@@ -221,435 +220,358 @@
 	#define SCAN_PAGE		0x02
 
 #define OCF_SET_EVENT_FLT	0x0005
-typedef struct {
-	__u8 	flt_type;
-	__u8 	cond_type;
-	__u8 	condition[0];
-} __attribute__ ((packed)) set_event_flt_cp;
-#define SET_EVENT_FLT_CP_SIZE 2
+struct hci_cp_set_event_flt {
+	__u8     flt_type;
+	__u8     cond_type;
+	__u8     condition[0];
+} __attribute__ ((packed));
 
 /* Filter types */
-#define FLT_CLEAR_ALL	0x00
-#define FLT_INQ_RESULT	0x01
-#define FLT_CONN_SETUP	0x02
+#define HCI_FLT_CLEAR_ALL	0x00
+#define HCI_FLT_INQ_RESULT	0x01
+#define HCI_FLT_CONN_SETUP	0x02
 
 /* CONN_SETUP Condition types */
-#define CONN_SETUP_ALLOW_ALL	0x00
-#define CONN_SETUP_ALLOW_CLASS	0x01
-#define CONN_SETUP_ALLOW_BDADDR	0x02
+#define HCI_CONN_SETUP_ALLOW_ALL	0x00
+#define HCI_CONN_SETUP_ALLOW_CLASS	0x01
+#define HCI_CONN_SETUP_ALLOW_BDADDR	0x02
 
 /* CONN_SETUP Conditions */
-#define CONN_SETUP_AUTO_OFF	0x01
-#define CONN_SETUP_AUTO_ON	0x02
-
-#define OCF_CHANGE_LOCAL_NAME	0x0013
-typedef struct {
-	__u8 	name[248];
-} __attribute__ ((packed)) change_local_name_cp;
-#define CHANGE_LOCAL_NAME_CP_SIZE 248 
-
-#define OCF_READ_LOCAL_NAME	0x0014
-typedef struct {
-	__u8	status;
-	__u8 	name[248];
-} __attribute__ ((packed)) read_local_name_rp;
-#define READ_LOCAL_NAME_RP_SIZE 249 
+#define HCI_CONN_SETUP_AUTO_OFF	0x01
+#define HCI_CONN_SETUP_AUTO_ON	0x02
 
 #define OCF_READ_CLASS_OF_DEV	0x0023
-typedef struct {
-	__u8	status;
-	__u8 	dev_class[3];
-} __attribute__ ((packed)) read_class_of_dev_rp;
-#define READ_CLASS_OF_DEV_RP_SIZE 4 
+struct hci_rp_read_dev_class {
+	__u8     status;
+	__u8     dev_class[3];
+} __attribute__ ((packed));
 
 #define OCF_WRITE_CLASS_OF_DEV	0x0024
-typedef struct {
-	__u8 	dev_class[3];
-} __attribute__ ((packed)) write_class_of_dev_cp;
-#define WRITE_CLASS_OF_DEV_CP_SIZE 3
+struct hci_cp_write_dev_class {
+	__u8     dev_class[3];
+} __attribute__ ((packed));
 
 #define OCF_HOST_BUFFER_SIZE	0x0033
-typedef struct {
-	__u16 	acl_mtu;
-	__u8 	sco_mtu;
-	__u16 	acl_max_pkt;
-	__u16	sco_max_pkt;
-} __attribute__ ((packed)) host_buffer_size_cp;
-#define HOST_BUFFER_SIZE_CP_SIZE 7
+struct hci_cp_host_buffer_size {
+	__u16    acl_mtu;
+	__u8     sco_mtu;
+	__u16    acl_max_pkt;
+	__u16    sco_max_pkt;
+} __attribute__ ((packed));
 
 /* Link Control */
 #define OGF_LINK_CTL	0x01 
 #define OCF_CREATE_CONN		0x0005
-typedef struct {
+struct hci_cp_create_conn {
 	bdaddr_t bdaddr;
-	__u16 	pkt_type;
-	__u8 	pscan_rep_mode;
-	__u8 	pscan_mode;
-	__u16 	clock_offset;
-	__u8 	role_switch;
-} __attribute__ ((packed)) create_conn_cp;
-#define CREATE_CONN_CP_SIZE 13
+	__u16    pkt_type;
+	__u8     pscan_rep_mode;
+	__u8     pscan_mode;
+	__u16    clock_offset;
+	__u8     role_switch;
+} __attribute__ ((packed));
 
 #define OCF_ACCEPT_CONN_REQ	0x0009
-typedef struct {
+struct hci_cp_accept_conn_req {
 	bdaddr_t bdaddr;
-	__u8 	role;
-} __attribute__ ((packed)) accept_conn_req_cp;
-#define ACCEPT_CONN_REQ_CP_SIZE	7
+	__u8     role;
+} __attribute__ ((packed));
 
 #define OCF_REJECT_CONN_REQ	0x000a
-typedef struct {
+struct hci_cp_reject_conn_req {
 	bdaddr_t bdaddr;
-	__u8 	reason;
-} __attribute__ ((packed)) reject_conn_req_cp;
-#define REJECT_CONN_REQ_CP_SIZE	7
+	__u8     reason;
+} __attribute__ ((packed));
 
 #define OCF_DISCONNECT	0x0006
-typedef struct {
-	__u16 	handle;
-	__u8 	reason;
-} __attribute__ ((packed)) disconnect_cp;
-#define DISCONNECT_CP_SIZE 3
+struct hci_cp_disconnect {
+	__u16    handle;
+	__u8     reason;
+} __attribute__ ((packed));
 
 #define OCF_ADD_SCO	0x0007
-typedef struct {
-	__u16 	handle;
-	__u16 	pkt_type;
-} __attribute__ ((packed)) add_sco_cp;
-#define ADD_SCO_CP_SIZE 4
+struct hci_cp_add_sco {
+	__u16    handle;
+	__u16    pkt_type;
+} __attribute__ ((packed));
 
 #define OCF_INQUIRY		0x0001
-typedef struct {
-	__u8 	lap[3];
-	__u8 	length;
-	__u8	num_rsp;
-} __attribute__ ((packed)) inquiry_cp;
-#define INQUIRY_CP_SIZE 5
-
-typedef struct {
-	__u8     status;
-	bdaddr_t bdaddr;
-} __attribute__ ((packed)) status_bdaddr_rp;
-#define STATUS_BDADDR_RP_SIZE 7
+struct hci_cp_inquiry {
+	__u8     lap[3];
+	__u8     length;
+	__u8     num_rsp;
+} __attribute__ ((packed));
 
 #define OCF_LINK_KEY_REPLY	0x000B
 #define OCF_LINK_KEY_NEG_REPLY	0x000C
-typedef struct {
+struct hci_cp_link_key_reply {
 	bdaddr_t bdaddr;
 	__u8     link_key[16];
-} __attribute__ ((packed)) link_key_reply_cp;
-#define LINK_KEY_REPLY_CP_SIZE 22
+} __attribute__ ((packed));
 
 #define OCF_PIN_CODE_REPLY	0x000D
 #define OCF_PIN_CODE_NEG_REPLY	0x000E
-typedef struct {
+struct hci_cp_pin_code_reply {
 	bdaddr_t bdaddr;
-	__u8	 pin_len;
-	__u8	 pin_code[16];
-} __attribute__ ((packed)) pin_code_reply_cp;
-#define PIN_CODE_REPLY_CP_SIZE 23
+	__u8     pin_len;
+	__u8     pin_code[16];
+} __attribute__ ((packed));
 
 #define OCF_CHANGE_CONN_PTYPE	0x000F
-typedef struct {
-	__u16	 handle;
-	__u16	 pkt_type;
-} __attribute__ ((packed)) change_conn_ptype_cp;
-#define CHANGE_CONN_PTYPE_CP_SIZE 4
+struct hci_cp_change_conn_ptype {
+	__u16    handle;
+	__u16    pkt_type;
+} __attribute__ ((packed));
 
 #define OCF_AUTH_REQUESTED	0x0011
-typedef struct {
-	__u16	 handle;
-} __attribute__ ((packed)) auth_requested_cp;
-#define AUTH_REQUESTED_CP_SIZE 2
+struct hci_cp_auth_requested {
+	__u16    handle;
+} __attribute__ ((packed));
 
 #define OCF_SET_CONN_ENCRYPT	0x0013
-typedef struct {
-	__u16	 handle;
-	__u8	 encrypt;
-} __attribute__ ((packed)) set_conn_encrypt_cp;
-#define SET_CONN_ENCRYPT_CP_SIZE 3
-
-#define OCF_REMOTE_NAME_REQ	0x0019
-typedef struct {
-	bdaddr_t bdaddr;
-	__u8     pscan_rep_mode;
-	__u8     pscan_mode;
-	__u16    clock_offset;
-} __attribute__ ((packed)) remote_name_req_cp;
-#define REMOTE_NAME_REQ_CP_SIZE 10
+struct hci_cp_set_conn_encrypt {
+	__u16    handle;
+	__u8     encrypt;
+} __attribute__ ((packed));
 
 #define OCF_READ_REMOTE_FEATURES 0x001B
-typedef struct {
-	__u16   handle;
-} __attribute__ ((packed)) read_remote_features_cp;
-#define READ_REMOTE_FEATURES_CP_SIZE 2
+struct hci_cp_read_rmt_features {
+	__u16    handle;
+} __attribute__ ((packed));
 
 #define OCF_READ_REMOTE_VERSION 0x001D
-typedef struct {
-	__u16   handle;
-} __attribute__ ((packed)) read_remote_version_cp;
-#define READ_REMOTE_VERSION_CP_SIZE 2
+struct hci_cp_read_rmt_version {
+	__u16    handle;
+} __attribute__ ((packed));
 
 /* Link Policy */
 #define OGF_LINK_POLICY	 0x02   
 #define OCF_ROLE_DISCOVERY	0x0009
-typedef struct {
-	__u16	handle;
-} __attribute__ ((packed)) role_discovery_cp;
-#define ROLE_DISCOVERY_CP_SIZE 2
-typedef struct {
-	__u8    status;
-	__u16	handle;
-	__u8    role;
-} __attribute__ ((packed)) role_discovery_rp;
-#define ROLE_DISCOVERY_RP_SIZE 4
+struct hci_cp_role_discovery {
+	__u16    handle;
+} __attribute__ ((packed));
+struct hci_rp_role_discovery {
+	__u8     status;
+	__u16    handle;
+	__u8     role;
+} __attribute__ ((packed));
 
 #define OCF_READ_LINK_POLICY	0x000C
-typedef struct {
-	__u16	handle;
-} __attribute__ ((packed)) read_link_policy_cp;
-#define READ_LINK_POLICY_CP_SIZE 2
-typedef struct {
-	__u8    status;
-	__u16	handle;
-	__u16   policy;
-} __attribute__ ((packed)) read_link_policy_rp;
-#define READ_LINK_POLICY_RP_SIZE 5
+struct hci_cp_read_link_policy {
+	__u16    handle;
+} __attribute__ ((packed));
+struct hci_rp_read_link_policy {
+	__u8     status;
+	__u16    handle;
+	__u16    policy;
+} __attribute__ ((packed));
 
 #define OCF_SWITCH_ROLE	0x000B
-typedef struct {
+struct hci_cp_switch_role {
 	bdaddr_t bdaddr;
 	__u8     role;
-} __attribute__ ((packed)) switch_role_cp;
-#define SWITCH_ROLE_CP_SIZE 7
+} __attribute__ ((packed));
 
 #define OCF_WRITE_LINK_POLICY	0x000D
-typedef struct {
-	__u16	handle;
-	__u16   policy;
-} __attribute__ ((packed)) write_link_policy_cp;
-#define WRITE_LINK_POLICY_CP_SIZE 4
-typedef struct {
-	__u8    status;
-	__u16	handle;
-} __attribute__ ((packed)) write_link_policy_rp;
-#define WRITE_LINK_POLICY_RP_SIZE 3
+struct hci_cp_write_link_policy {
+	__u16    handle;
+	__u16    policy;
+} __attribute__ ((packed));
+struct hci_rp_write_link_policy {
+	__u8     status;
+	__u16    handle;
+} __attribute__ ((packed));
 
 /* Status params */
 #define OGF_STATUS_PARAM 	0x05
 
 /* ---- HCI Events ---- */
-#define EVT_INQUIRY_COMPLETE 	0x01
+#define HCI_EV_INQUIRY_COMPLETE	0x01
 
-#define EVT_INQUIRY_RESULT 	0x02
-typedef struct {
-	bdaddr_t	bdaddr;
-	__u8	pscan_rep_mode;
-	__u8	pscan_period_mode;
-	__u8	pscan_mode;
-	__u8	dev_class[3];
-	__u16	clock_offset;
-} __attribute__ ((packed)) inquiry_info;
-#define INQUIRY_INFO_SIZE 14
-
-#define EVT_CONN_COMPLETE 	0x03
-typedef struct {
-	__u8	status;
-	__u16	handle;
-	bdaddr_t	bdaddr;
-	__u8	link_type;
-	__u8	encr_mode;
-} __attribute__ ((packed)) evt_conn_complete;
-#define EVT_CONN_COMPLETE_SIZE 13
-
-#define EVT_CONN_REQUEST	0x04
-typedef struct {
-	bdaddr_t 	bdaddr;
-	__u8 		dev_class[3];
-	__u8		link_type;
-} __attribute__ ((packed)) evt_conn_request;
-#define EVT_CONN_REQUEST_SIZE 10
-
-#define EVT_DISCONN_COMPLETE	0x05
-typedef struct {
-	__u8 	status;
-	__u16 	handle;
-	__u8 	reason;
-} __attribute__ ((packed)) evt_disconn_complete;
-#define EVT_DISCONN_COMPLETE_SIZE 4
-
-#define EVT_AUTH_COMPLETE	0x06
-typedef struct {
-	__u8 	status;
-	__u16 	handle;
-} __attribute__ ((packed)) evt_auth_complete;
-#define EVT_AUTH_COMPLETE_SIZE 3
+#define HCI_EV_INQUIRY_RESULT	0x02
+struct inquiry_info {
+	bdaddr_t bdaddr;
+	__u8     pscan_rep_mode;
+	__u8     pscan_period_mode;
+	__u8     pscan_mode;
+	__u8     dev_class[3];
+	__u16    clock_offset;
+} __attribute__ ((packed));
 
-#define EVT_REMOTE_NAME_REQ_COMPLETE	0x07
-typedef struct {
-	__u8 	 status;
-	bdaddr_t bdaddr;
-	__u8 	 name[248];
-} __attribute__ ((packed)) evt_remote_name_req_complete;
-#define EVT_REMOTE_NAME_REQ_COMPLETE_SIZE 255
-
-#define EVT_ENCRYPT_CHANGE	0x08
-typedef struct {
-	__u8 	status;
-	__u16 	handle;
-	__u8	encrypt;
-} __attribute__ ((packed)) evt_encrypt_change;
-#define EVT_ENCRYPT_CHANGE_SIZE 5
-
-#define EVT_QOS_SETUP_COMPLETE 0x0D
-typedef struct {
-	__u8	service_type;
-	__u32	token_rate;
-	__u32	peak_bandwidth;
-	__u32	latency;
-	__u32	delay_variation;
-} __attribute__ ((packed)) hci_qos;
-typedef struct {
-	__u8	status;
-	__u16	handle;
-	hci_qos qos;
-} __attribute__ ((packed)) evt_qos_setup_complete;
-#define EVT_QOS_SETUP_COMPLETE_SIZE 20
-
-#define EVT_CMD_COMPLETE 	0x0e
-typedef struct {
-	__u8 	ncmd;
-	__u16 	opcode;
-} __attribute__ ((packed)) evt_cmd_complete;
-#define EVT_CMD_COMPLETE_SIZE 3
-
-#define EVT_CMD_STATUS 		0x0f
-typedef struct {
-	__u8 	status;
-	__u8 	ncmd;
-	__u16 	opcode;
-} __attribute__ ((packed)) evt_cmd_status;
-#define EVT_CMD_STATUS_SIZE 4
-
-#define EVT_NUM_COMP_PKTS	0x13
-typedef struct {
-	__u8 	num_hndl;
+#define HCI_EV_CONN_COMPLETE 	0x03
+struct hci_ev_conn_complete {
+	__u8     status;
+	__u16    handle;
+	bdaddr_t bdaddr;
+	__u8     link_type;
+	__u8     encr_mode;
+} __attribute__ ((packed));
+
+#define HCI_EV_CONN_REQUEST	0x04
+struct hci_ev_conn_request {
+	bdaddr_t bdaddr;
+	__u8     dev_class[3];
+	__u8     link_type;
+} __attribute__ ((packed));
+
+#define HCI_EV_DISCONN_COMPLETE	0x05
+struct hci_ev_disconn_complete {
+	__u8     status;
+	__u16    handle;
+	__u8     reason;
+} __attribute__ ((packed));
+
+#define HCI_EV_AUTH_COMPLETE	0x06
+struct hci_ev_auth_complete {
+	__u8     status;
+	__u16    handle;
+} __attribute__ ((packed));
+
+#define HCI_EV_ENCRYPT_CHANGE	0x08
+struct hci_ev_encrypt_change {
+	__u8     status;
+	__u16    handle;
+	__u8     encrypt;
+} __attribute__ ((packed));
+
+#define HCI_EV_QOS_SETUP_COMPLETE	0x0D
+struct hci_qos {
+	__u8     service_type;
+	__u32    token_rate;
+	__u32    peak_bandwidth;
+	__u32    latency;
+	__u32    delay_variation;
+} __attribute__ ((packed));
+struct hci_ev_qos_setup_complete {
+	__u8     status;
+	__u16    handle;
+	struct   hci_qos qos;
+} __attribute__ ((packed));
+
+#define HCI_EV_CMD_COMPLETE 	0x0E
+struct hci_ev_cmd_complete {
+	__u8     ncmd;
+	__u16    opcode;
+} __attribute__ ((packed));
+
+#define HCI_EV_CMD_STATUS 	0x0F
+struct hci_ev_cmd_status {
+	__u8     status;
+	__u8     ncmd;
+	__u16    opcode;
+} __attribute__ ((packed));
+
+#define HCI_EV_NUM_COMP_PKTS	0x13
+struct hci_ev_num_comp_pkts {
+	__u8     num_hndl;
 	/* variable length part */
-} __attribute__ ((packed)) evt_num_comp_pkts;
-#define EVT_NUM_COMP_PKTS_SIZE 1
+} __attribute__ ((packed));
 
-#define EVT_ROLE_CHANGE		0x12
-typedef struct {
-	__u8 	 status;
+#define HCI_EV_ROLE_CHANGE	0x12
+struct hci_ev_role_change {
+	__u8     status;
 	bdaddr_t bdaddr;
 	__u8     role;
-} __attribute__ ((packed)) evt_role_change;
-#define EVT_ROLE_CHANGE_SIZE 8
+} __attribute__ ((packed));
 
-#define EVT_PIN_CODE_REQ        0x16
-typedef struct {
+#define HCI_EV_PIN_CODE_REQ	0x16
+struct hci_ev_pin_code_req {
 	bdaddr_t bdaddr;
-} __attribute__ ((packed)) evt_pin_code_req;
-#define EVT_PIN_CODE_REQ_SIZE 6
+} __attribute__ ((packed));
 
-#define EVT_LINK_KEY_REQ        0x17
-typedef struct {
+#define HCI_EV_LINK_KEY_REQ	0x17
+struct hci_ev_link_key_req {
 	bdaddr_t bdaddr;
-} __attribute__ ((packed)) evt_link_key_req;
-#define EVT_LINK_KEY_REQ_SIZE 6
+} __attribute__ ((packed));
 
-#define EVT_LINK_KEY_NOTIFY	0x18
-typedef struct {
+#define HCI_EV_LINK_KEY_NOTIFY	0x18
+struct hci_ev_link_key_notify {
 	bdaddr_t bdaddr;
 	__u8	 link_key[16];
 	__u8	 key_type;
-} __attribute__ ((packed)) evt_link_key_notify;
-#define EVT_LINK_KEY_NOTIFY_SIZE 23
+} __attribute__ ((packed));
 
-#define EVT_READ_REMOTE_FEATURES_COMPLETE 0x0B
-typedef struct {
-	__u8    status;
-	__u16   handle;
-	__u8    features[8];
-} __attribute__ ((packed)) evt_read_remote_features_complete;
-#define EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE 11
-
-#define EVT_READ_REMOTE_VERSION_COMPLETE 0x0C
-typedef struct {
-	__u8    status;
-	__u16   handle;
-	__u8    lmp_ver;
-	__u16   manufacturer;
-	__u16   lmp_subver;
-} __attribute__ ((packed)) evt_read_remote_version_complete;
-#define EVT_READ_REMOTE_VERSION_COMPLETE_SIZE 8
+#define HCI_EV_RMT_FEATURES	0x0B
+struct hci_ev_rmt_features {
+	__u8     status;
+	__u16    handle;
+	__u8     features[8];
+} __attribute__ ((packed));
 
-/* Internal events generated by Bluetooth stack */
-#define EVT_STACK_INTERNAL	0xfd
-typedef struct {
-	__u16   type;
-	__u8 	data[0];
-} __attribute__ ((packed)) evt_stack_internal;
-#define EVT_STACK_INTERNAL_SIZE 2
-
-#define EVT_SI_DEVICE  	0x01
-typedef struct {
-	__u16   event;
-	__u16 	dev_id;
-} __attribute__ ((packed)) evt_si_device;
-#define EVT_SI_DEVICE_SIZE 4
-
-#define EVT_SI_SECURITY	0x02
-typedef struct {
-	__u16 	event;
-	__u16   proto;
-	__u16   subproto;
-	__u8    incomming;
-} __attribute__ ((packed)) evt_si_security;
+#define HCI_EV_RMT_VERSION	0x0C
+struct hci_ev_rmt_version {
+	__u8     status;
+	__u16    handle;
+	__u8     lmp_ver;
+	__u16    manufacturer;
+	__u16    lmp_subver;
+} __attribute__ ((packed));
 
-/* --------  HCI Packet structures  -------- */
-#define HCI_TYPE_LEN	1
+/* Internal events generated by Bluetooth stack */
+#define HCI_EV_STACK_INTERNAL	0xFD
+struct hci_ev_stack_internal {
+	__u16    type;
+	__u8     data[0];
+} __attribute__ ((packed));
+
+#define HCI_EV_SI_DEVICE  	0x01
+struct hci_ev_si_device {
+	__u16    event;
+	__u16    dev_id;
+} __attribute__ ((packed));
+
+#define HCI_EV_SI_SECURITY	0x02
+struct hci_ev_si_security {
+	__u16    event;
+	__u16    proto;
+	__u16    subproto;
+	__u8     incoming;
+} __attribute__ ((packed));
+
+/* ---- HCI Packet structures ---- */
+#define HCI_COMMAND_HDR_SIZE 3
+#define HCI_EVENT_HDR_SIZE   2
+#define HCI_ACL_HDR_SIZE     4
+#define HCI_SCO_HDR_SIZE     3
 
-typedef struct {
+struct hci_command_hdr {
 	__u16 	opcode;		/* OCF & OGF */
 	__u8 	plen;
-} __attribute__ ((packed))	hci_command_hdr;
-#define HCI_COMMAND_HDR_SIZE 	3
+} __attribute__ ((packed));
 
-typedef struct {
+struct hci_event_hdr {
 	__u8 	evt;
 	__u8 	plen;
-} __attribute__ ((packed))	hci_event_hdr;
-#define HCI_EVENT_HDR_SIZE 	2
+} __attribute__ ((packed));
 
-typedef struct {
+struct hci_acl_hdr {
 	__u16 	handle;		/* Handle & Flags(PB, BC) */
 	__u16 	dlen;
-} __attribute__ ((packed))	hci_acl_hdr;
-#define HCI_ACL_HDR_SIZE 	4
+} __attribute__ ((packed));
 
-typedef struct {
+struct hci_sco_hdr {
 	__u16 	handle;
 	__u8 	dlen;
-} __attribute__ ((packed))	hci_sco_hdr;
-#define HCI_SCO_HDR_SIZE 	3
+} __attribute__ ((packed));
 
 /* Command opcode pack/unpack */
-#define cmd_opcode_pack(ogf, ocf)	(__u16)((ocf & 0x03ff)|(ogf << 10))
-#define cmd_opcode_ogf(op)		(op >> 10)
-#define cmd_opcode_ocf(op)		(op & 0x03ff)
+#define hci_opcode_pack(ogf, ocf)	(__u16)((ocf & 0x03ff)|(ogf << 10))
+#define hci_opcode_ogf(op)		(op >> 10)
+#define hci_opcode_ocf(op)		(op & 0x03ff)
 
 /* ACL handle and flags pack/unpack */
-#define acl_handle_pack(h, f)	(__u16)((h & 0x0fff)|(f << 12))
-#define acl_handle(h)		(h & 0x0fff)
-#define acl_flags(h)		(h >> 12)
+#define hci_handle_pack(h, f)	(__u16)((h & 0x0fff)|(f << 12))
+#define hci_handle(h)		(h & 0x0fff)
+#define hci_flags(h)		(h >> 12)
 
-/* HCI Socket options */
+/* ---- HCI Sockets ---- */
+
+/* Socket options */
 #define HCI_DATA_DIR	1
 #define HCI_FILTER	2
 #define HCI_TIME_STAMP	3
 
-/* HCI CMSG flags */
+/* CMSG flags */
 #define HCI_CMSG_DIR	0x0001
 #define HCI_CMSG_TSTAMP	0x0002
 
@@ -676,7 +598,7 @@
 #define HCI_FLT_OGF_BITS	63
 #define HCI_FLT_OCF_BITS	127
 
-/* Ioctl requests structures */
+/* ---- HCI Ioctl requests structures ---- */
 struct hci_dev_stats {
 	__u32 err_rx;
 	__u32 err_tx;
@@ -752,12 +674,5 @@
 	__u8  num_rsp;
 };
 #define IREQ_CACHE_FLUSH 0x0001
-
-struct hci_remotename_req {
-	__u16 dev_id;
-	__u16 flags;
-	bdaddr_t bdaddr;
-	__u8  name[248];
-};
 
 #endif /* __HCI_H */
diff -Nru a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
--- a/include/net/bluetooth/hci_core.h	Fri Oct 18 21:03:04 2002
+++ b/include/net/bluetooth/hci_core.h	Fri Oct 18 21:03:04 2002
@@ -42,7 +42,7 @@
 struct inquiry_entry {
 	struct inquiry_entry 	*next;
 	__u32			timestamp;
-	inquiry_info		info;
+	struct inquiry_info	info;
 };
 
 struct inquiry_cache {
@@ -51,7 +51,7 @@
 	struct inquiry_entry 	*list;
 };
 
-struct conn_hash {
+struct hci_conn_hash {
 	struct list_head list;
 	spinlock_t       lock;
 	unsigned int     num;
@@ -102,7 +102,7 @@
 	__u32			req_result;
 
 	struct inquiry_cache 	inq_cache;
-	struct conn_hash 	conn_hash;
+	struct hci_conn_hash 	conn_hash;
 
 	struct hci_dev_stats 	stat;
 
@@ -179,7 +179,7 @@
 }
 
 struct inquiry_entry *inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
-void inquiry_cache_update(struct hci_dev *hdev, inquiry_info *info);
+void inquiry_cache_update(struct hci_dev *hdev, struct inquiry_info *info);
 void inquiry_cache_flush(struct hci_dev *hdev);
 int  inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf);
 
@@ -189,44 +189,34 @@
 	HCI_CONN_ENCRYPT_PEND
 };
 
-#define hci_conn_lock(c)	spin_lock(&c->lock)
-#define hci_conn_unlock(c)	spin_unlock(&c->lock)
-#define hci_conn_lock_bh(c)	spin_lock_bh(&c->lock)
-#define hci_conn_unlock_bh(c)	spin_unlock_bh(&c->lock)
-
-#define conn_hash_lock(d)	spin_lock(&d->conn_hash->lock)
-#define conn_hash_unlock(d)	spin_unlock(&d->conn_hash->lock)
-#define conn_hash_lock_bh(d)	spin_lock_bh(&d->conn_hash->lock)
-#define conn_hash_unlock_bh(d)	spin_unlock_bh(&d->conn_hash->lock)
-
-static inline void conn_hash_init(struct hci_dev *hdev)
+static inline void hci_conn_hash_init(struct hci_dev *hdev)
 {
-	struct conn_hash *h = &hdev->conn_hash;
+	struct hci_conn_hash *h = &hdev->conn_hash;
 	INIT_LIST_HEAD(&h->list);
 	spin_lock_init(&h->lock);
 	h->num = 0;	
 }
 
-static inline void conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
+static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 {
-	struct conn_hash *h = &hdev->conn_hash;
+	struct hci_conn_hash *h = &hdev->conn_hash;
 	list_add(&c->list, &h->list);
 	h->num++;
 }
 
-static inline void conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
+static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
 {
-	struct conn_hash *h = &hdev->conn_hash;
+	struct hci_conn_hash *h = &hdev->conn_hash;
 	list_del(&c->list);
 	h->num--;
 }
 
-static inline struct hci_conn *conn_hash_lookup_handle(struct hci_dev *hdev,
+static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
 	       				__u16 handle)
 {
-	register struct conn_hash *h = &hdev->conn_hash;
-	register struct list_head *p;
-	register struct hci_conn  *c;
+	struct hci_conn_hash *h = &hdev->conn_hash;
+	struct list_head *p;
+	struct hci_conn  *c;
 
 	list_for_each(p, &h->list) {
 		c = list_entry(p, struct hci_conn, list);
@@ -236,12 +226,12 @@
         return NULL;
 }
 
-static inline struct hci_conn *conn_hash_lookup_ba(struct hci_dev *hdev,
+static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
 					__u8 type, bdaddr_t *ba)
 {
-	register struct conn_hash *h = &hdev->conn_hash;
-	register struct list_head *p;
-	register struct hci_conn  *c;
+	struct hci_conn_hash *h = &hdev->conn_hash;
+	struct list_head *p;
+	struct hci_conn  *c;
 
 	list_for_each(p, &h->list) {
 		c = list_entry(p, struct hci_conn, list);
@@ -285,6 +275,22 @@
 		hci_conn_set_timer(conn, HCI_DISCONN_TIMEOUT);
 }
 
+/* ----- HCI tasks ----- */
+static inline void hci_sched_cmd(struct hci_dev *hdev)
+{
+	tasklet_schedule(&hdev->cmd_task);
+}
+
+static inline void hci_sched_rx(struct hci_dev *hdev)
+{
+	tasklet_schedule(&hdev->rx_task);
+}
+
+static inline void hci_sched_tx(struct hci_dev *hdev)
+{
+	tasklet_schedule(&hdev->tx_task);
+}
+
 /* ----- HCI Devices ----- */
 static inline void hci_dev_put(struct hci_dev *d)
 { 
@@ -315,28 +321,33 @@
 int hci_get_conn_info(struct hci_dev *hdev, unsigned long arg);
 int hci_inquiry(unsigned long arg);
 
-int  hci_recv_frame(struct sk_buff *skb);
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
-/* ----- LMP capabilities ----- */
-#define lmp_rswitch_capable(dev) (dev->features[0] & LMP_RSWITCH)
-#define lmp_encrypt_capable(dev) (dev->features[0] & LMP_ENCRYPT)
-
-/* ----- HCI tasks ----- */
-static inline void hci_sched_cmd(struct hci_dev *hdev)
+/* Receive frame from HCI drivers */
+static inline int hci_recv_frame(struct sk_buff *skb)
 {
-	tasklet_schedule(&hdev->cmd_task);
-}
+	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+	if (!hdev || (!test_bit(HCI_UP, &hdev->flags) 
+			&& !test_bit(HCI_INIT, &hdev->flags))) {
+		kfree_skb(skb);
+		return -ENXIO;
+	}
 
-static inline void hci_sched_rx(struct hci_dev *hdev)
-{
-	tasklet_schedule(&hdev->rx_task);
-}
+	/* Incomming skb */
+	bt_cb(skb)->incoming = 1;
 
-static inline void hci_sched_tx(struct hci_dev *hdev)
-{
-	tasklet_schedule(&hdev->tx_task);
+	/* Time stamp */
+	do_gettimeofday(&skb->stamp);
+
+	/* Queue frame for rx task */
+	skb_queue_tail(&hdev->rx_q, skb);
+	hci_sched_rx(hdev);
+	return 0;
 }
+
+/* ----- LMP capabilities ----- */
+#define lmp_rswitch_capable(dev) (dev->features[0] & LMP_RSWITCH)
+#define lmp_encrypt_capable(dev) (dev->features[0] & LMP_ENCRYPT)
 
 /* ----- HCI protocols ----- */
 struct hci_proto {
diff -Nru a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
--- a/include/net/bluetooth/l2cap.h	Fri Oct 18 21:03:03 2002
+++ b/include/net/bluetooth/l2cap.h	Fri Oct 18 21:03:03 2002
@@ -89,37 +89,34 @@
 #define L2CAP_INFO_RSP    0x0b
 
 /* L2CAP structures */
-typedef struct {
+struct l2cap_hdr {
 	__u16      len;
 	__u16      cid;
-} __attribute__ ((packed)) 	l2cap_hdr;
+} __attribute__ ((packed));
 #define L2CAP_HDR_SIZE		4
 
-typedef struct {
+struct l2cap_cmd_hdr {
 	__u8       code;
 	__u8       ident;
 	__u16      len;
-} __attribute__ ((packed))	l2cap_cmd_hdr;
+} __attribute__ ((packed));
 #define L2CAP_CMD_HDR_SIZE	4
 
-typedef struct {
+struct l2cap_cmd_rej {
 	__u16      reason;
-} __attribute__ ((packed))	l2cap_cmd_rej;
-#define L2CAP_CMD_REJ_SIZE	2
+} __attribute__ ((packed));
 
-typedef struct {
+struct l2cap_conn_req {
 	__u16      psm;
 	__u16      scid;
-} __attribute__ ((packed))	l2cap_conn_req;
-#define L2CAP_CONN_REQ_SIZE	4
+} __attribute__ ((packed));
 
-typedef struct {
+struct l2cap_conn_rsp {
 	__u16      dcid;
 	__u16      scid;
 	__u16      result;
 	__u16      status;
-} __attribute__ ((packed))	l2cap_conn_rsp;
-#define L2CAP_CONN_RSP_SIZE	8
+} __attribute__ ((packed));
 
 /* connect result */
 #define L2CAP_CR_SUCCESS    0x0000
@@ -133,29 +130,27 @@
 #define L2CAP_CS_AUTHEN_PEND  0x0001
 #define L2CAP_CS_AUTHOR_PEND  0x0002
 
-typedef struct {
+struct l2cap_conf_req {
 	__u16      dcid;
 	__u16      flags;
 	__u8       data[0];
-} __attribute__ ((packed))	l2cap_conf_req;
-#define L2CAP_CONF_REQ_SIZE	4
+} __attribute__ ((packed));
 
-typedef struct {
+struct l2cap_conf_rsp {
 	__u16      scid;
 	__u16      flags;
 	__u16      result;
 	__u8       data[0];
-} __attribute__ ((packed))	l2cap_conf_rsp;
-#define L2CAP_CONF_RSP_SIZE   	6
+} __attribute__ ((packed));
 
 #define L2CAP_CONF_SUCCESS	0x00
 #define L2CAP_CONF_UNACCEPT	0x01
 
-typedef struct {
+struct l2cap_conf_opt {
 	__u8       type;
 	__u8       len;
 	__u8       val[0];
-} __attribute__ ((packed))	l2cap_conf_opt;
+} __attribute__ ((packed));
 #define L2CAP_CONF_OPT_SIZE	2
 
 #define L2CAP_CONF_MTU		0x01
@@ -164,30 +159,26 @@
 
 #define L2CAP_CONF_MAX_SIZE	22
 
-typedef struct {
+struct l2cap_disconn_req {
 	__u16      dcid;
 	__u16      scid;
-} __attribute__ ((packed)) 	l2cap_disconn_req;
-#define L2CAP_DISCONN_REQ_SIZE	4
+} __attribute__ ((packed));
 
-typedef struct {
+struct l2cap_disconn_rsp {
 	__u16      dcid;
 	__u16      scid;
-} __attribute__ ((packed)) 	l2cap_disconn_rsp;
-#define L2CAP_DISCONN_RSP_SIZE	4
+} __attribute__ ((packed));
 
-typedef struct {
+struct l2cap_info_req {
 	__u16       type;
 	__u8        data[0];
-} __attribute__ ((packed))	l2cap_info_req;
-#define L2CAP_INFO_REQ_SIZE	2
+} __attribute__ ((packed));
 
-typedef struct {
+struct l2cap_info_rsp {
 	__u16       type;
 	__u16       result;
 	__u8        data[0];
-} __attribute__ ((packed))	l2cap_info_rsp;
-#define L2CAP_INFO_RSP_SIZE	4
+} __attribute__ ((packed));
 
 /* ----- L2CAP connections ----- */
 struct l2cap_chan_list {
diff -Nru a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
--- a/include/net/bluetooth/rfcomm.h	Fri Oct 18 21:03:03 2002
+++ b/include/net/bluetooth/rfcomm.h	Fri Oct 18 21:03:03 2002
@@ -192,7 +192,7 @@
 
 	void (*data_ready)(struct rfcomm_dlc *d, struct sk_buff *skb);
 	void (*state_change)(struct rfcomm_dlc *d, int err);
-	void (*modem_status)(struct rfcomm_dlc *d, int v24_sig);
+	void (*modem_status)(struct rfcomm_dlc *d, u8 v24_sig);
 };
 
 /* DLC and session flags */
@@ -231,7 +231,8 @@
 int  rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel);
 int  rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
 int  rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
-int  rfcomm_dlc_modem_status(struct rfcomm_dlc *d, int v24_sig);
+int  rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
+int  rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
 
 #define rfcomm_dlc_lock(d)     spin_lock(&d->lock)
 #define rfcomm_dlc_unlock(d)   spin_unlock(&d->lock)
diff -Nru a/include/net/dst.h b/include/net/dst.h
--- a/include/net/dst.h	Fri Oct 18 21:03:08 2002
+++ b/include/net/dst.h	Fri Oct 18 21:03:08 2002
@@ -29,6 +29,7 @@
 	struct dst_entry        *next;
 	atomic_t		__refcnt;	/* client references	*/
 	int			__use;
+	struct dst_entry	*child;
 	struct net_device       *dev;
 	int			obsolete;
 	int			flags;
@@ -36,6 +37,8 @@
 	unsigned long		lastuse;
 	unsigned long		expires;
 
+	unsigned		header_len;	/* more space at head required */
+
 	unsigned		mxlock;
 	unsigned		pmtu;
 	unsigned		window;
@@ -108,18 +111,30 @@
 		atomic_dec(&dst->__refcnt);
 }
 
+/* Children define the path of the packet through the
+ * Linux networking.  Thus, destinations are stackable.
+ */
+
+static inline struct dst_entry *dst_pop(struct dst_entry *dst)
+{
+	struct dst_entry *child = dst_clone(dst->child);
+
+	dst_release(dst);
+	return child;
+}
+
 extern void * dst_alloc(struct dst_ops * ops);
 extern void __dst_free(struct dst_entry * dst);
-extern void dst_destroy(struct dst_entry * dst);
+extern struct dst_entry *dst_destroy(struct dst_entry * dst);
 
-static inline
-void dst_free(struct dst_entry * dst)
+static inline void dst_free(struct dst_entry * dst)
 {
 	if (dst->obsolete > 1)
 		return;
 	if (!atomic_read(&dst->__refcnt)) {
-		dst_destroy(dst);
-		return;
+		dst = dst_destroy(dst);
+		if (!dst)
+			return;
 	}
 	__dst_free(dst);
 }
@@ -153,6 +168,37 @@
 
 	if (dst->expires == 0 || (long)(dst->expires - expires) > 0)
 		dst->expires = expires;
+}
+
+/* Output packet to network from transport.  */
+static inline int dst_output(struct sk_buff *skb)
+{
+	int err;
+
+	for (;;) {
+		err = skb->dst->output(skb);
+
+		if (likely(err == 0))
+			return err;
+		if (unlikely(err != NET_XMIT_BYPASS))
+			return err;
+	}
+}
+
+/* Input packet from network to transport.  */
+static inline int dst_input(struct sk_buff *skb)
+{
+	int err;
+
+	for (;;) {
+		err = skb->dst->input(skb);
+
+		if (likely(err == 0))
+			return err;
+		/* Oh, Jamal... Seems, I will not forgive you this mess. :-) */
+		if (unlikely(err != NET_XMIT_BYPASS))
+			return err;
+	}
 }
 
 extern void		dst_init(void);
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h	Fri Oct 18 21:03:07 2002
+++ b/include/net/ip.h	Fri Oct 18 21:03:07 2002
@@ -98,16 +98,19 @@
 extern void		ip_send_check(struct iphdr *ip);
 extern int		ip_queue_xmit(struct sk_buff *skb);
 extern void		ip_init(void);
-extern int		ip_build_xmit(struct sock *sk,
-				      int getfrag (const void *,
-						   char *,
-						   unsigned int,
-						   unsigned int),
-				      const void *frag,
-				      unsigned length,
-				      struct ipcm_cookie *ipc,
-				      struct rtable *rt,
-				      int flags);
+extern int		ip_append_data(struct sock *sk,
+				       int getfrag(void *from, char *to, int offset, int len,
+						   int odd, struct sk_buff *skb),
+				void *from, int len, int protolen,
+				struct ipcm_cookie *ipc,
+				struct rtable *rt,
+				unsigned int flags);
+extern int		ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb);
+extern ssize_t		ip_append_page(struct sock *sk, struct page *page,
+				int offset, size_t size, int flags);
+extern int		ip_push_pending_frames(struct sock *sk);
+extern void		ip_flush_pending_frames(struct sock *sk);
+
 
 /*
  *	Map a multicast IP onto multicast MAC for type Token Ring.
@@ -127,8 +130,7 @@
 }
 
 struct ip_reply_arg {
-	struct iovec iov[2];   
-	int          n_iov;    /* redundant */
+	struct iovec iov[1];   
 	u32 	     csum; 
 	int	     csumoffset; /* u16 offset of csum in iov[0].iov_base */
 				 /* -1 if not needed */ 
diff -Nru a/include/net/ipv6.h b/include/net/ipv6.h
--- a/include/net/ipv6.h	Fri Oct 18 21:03:08 2002
+++ b/include/net/ipv6.h	Fri Oct 18 21:03:08 2002
@@ -74,6 +74,20 @@
 #define IPV6_ADDR_RESERVED	0x2000U	/* reserved address space */
 
 /*
+ *	Addr scopes
+ */
+#ifdef __KERNEL__
+#define IPV6_ADDR_MC_SCOPE(a)	\
+	((a)->s6_addr[1] & 0x0f)	/* nonstandard */
+#define __IPV6_ADDR_SCOPE_INVALID	-1
+#endif
+#define IPV6_ADDR_SCOPE_NODELOCAL	0x01
+#define IPV6_ADDR_SCOPE_LINKLOCAL	0x02
+#define IPV6_ADDR_SCOPE_SITELOCAL	0x05
+#define IPV6_ADDR_SCOPE_ORGLOCAL	0x08
+#define IPV6_ADDR_SCOPE_GLOBAL		0x0e
+
+/*
  *	fragmentation header
  */
 
diff -Nru a/include/net/sctp/sm.h b/include/net/sctp/sm.h
--- a/include/net/sctp/sm.h	Fri Oct 18 21:03:04 2002
+++ b/include/net/sctp/sm.h	Fri Oct 18 21:03:04 2002
@@ -139,6 +139,7 @@
 sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
 sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
 sctp_state_fn_t sctp_sf_unk_chunk;
+sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
 
 /* Prototypes for primitive event state functions.  */
 sctp_state_fn_t sctp_sf_do_prm_asoc;
@@ -329,10 +330,10 @@
 __u32 sctp_generate_tsn(const sctp_endpoint_t *);
 
 /* 4th level prototypes */
-void sctp_param2sockaddr(sockaddr_storage_t *addr, const sctpParam_t param,
+void sctp_param2sockaddr(sockaddr_storage_t *addr, sctp_addr_param_t *,
 			 __u16 port);
 int sctp_addr2sockaddr(const sctpParam_t, sockaddr_storage_t *);
-int sockaddr2sctp_addr(const sockaddr_storage_t *, sctpParam_t);
+int sockaddr2sctp_addr(const sockaddr_storage_t *, sctp_addr_param_t *);
 
 /* Extern declarations for major data structures.  */
 sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
@@ -430,6 +431,38 @@
 {
 	if (unlikely(!sctp_add_cmd(seq, verb, obj)))
 		BUG();
+}
+
+/* Check VTAG of the packet matches the sender's own tag OR its peer's
+ * tag and the T bit is set in the Chunk Flags.
+ */
+static inline int
+sctp_vtag_verify_either(const sctp_chunk_t *chunk,
+			const sctp_association_t *asoc)
+{
+        /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2
+	 *
+	 * B) The receiver of a ABORT shall accept the packet if the
+	 * Verification Tag field of the packet matches its own tag OR it
+	 * is set to its peer's tag and the T bit is set in the Chunk
+	 * Flags. Otherwise, the receiver MUST silently discard the packet
+	 * and take no further action.
+	 *
+	 * (C) The receiver of a SHUTDOWN COMPLETE shall accept the
+	 * packet if the Verification Tag field of the packet
+	 * matches its own tag OR it is set to its peer's tag and
+	 * the T bit is set in the Chunk Flags.  Otherwise, the
+	 * receiver MUST silently discard the packet and take no
+	 * further action....
+	 *
+	 */
+        if ((ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag) ||
+	    (sctp_test_T_bit(chunk) && (ntohl(chunk->sctp_hdr->vtag)
+	    == asoc->c.peer_vtag))) {
+                return 1;
+	}
+
+	return 0;
 }
 
 #endif /* __sctp_sm_h__ */
diff -Nru a/include/net/sctp/structs.h b/include/net/sctp/structs.h
--- a/include/net/sctp/structs.h	Fri Oct 18 21:03:08 2002
+++ b/include/net/sctp/structs.h	Fri Oct 18 21:03:08 2002
@@ -378,7 +378,7 @@
 typedef union {
 	sctp_ipv4addr_param_t v4;
 	sctp_ipv6addr_param_t v6;
-} sctpIpAddress_t;
+} sctp_addr_param_t;
 
 /* RFC 2960.  Section 3.3.5 Heartbeat.
  *    Heartbeat Information: variable length
@@ -1044,6 +1044,9 @@
 sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *,
 					const sockaddr_storage_t *);
 
+int sctp_has_association(const sockaddr_storage_t *laddr,
+			 const sockaddr_storage_t *paddr);
+
 int sctp_verify_init(const sctp_association_t *asoc,
 		     sctp_cid_t cid,
 		     sctp_init_chunk_t *peer_init,
@@ -1311,6 +1314,9 @@
 	 */
 
 	__u32 ctsn_ack_point;
+
+	/* Highest TSN that is acknowledged by incoming SACKs. */
+	__u32 highest_sacked;
 
 	/* The number of unacknowledged data chunks.  Reported through
 	 * the SCTP_STATUS sockopt.
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	Fri Oct 18 21:03:07 2002
+++ b/include/net/sock.h	Fri Oct 18 21:03:07 2002
@@ -249,6 +249,8 @@
 					   struct msghdr *msg,
 					int len, int noblock, int flags, 
 					int *addr_len);
+	int			(*sendpage)(struct sock *sk, struct page *page,
+					int offset, size_t size, int flags);
 	int			(*bind)(struct sock *sk, 
 					struct sockaddr *uaddr, int addr_len);
 
@@ -436,10 +438,6 @@
 
 /* Initialise core socket variables */
 extern void sock_init_data(struct socket *sock, struct sock *sk);
-
-extern void sklist_remove_socket(struct sock **list, struct sock *sk);
-extern void sklist_insert_socket(struct sock **list, struct sock *sk);
-extern void sklist_destroy_socket(struct sock **list, struct sock *sk);
 
 #ifdef CONFIG_FILTER
 
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	Fri Oct 18 21:03:03 2002
+++ b/include/net/tcp.h	Fri Oct 18 21:03:03 2002
@@ -1851,7 +1851,7 @@
 {
 	sk->route_caps = dst->dev->features;
 	if (sk->route_caps & NETIF_F_TSO) {
-		if (sk->no_largesend)
+		if (sk->no_largesend || dst->header_len)
 			sk->route_caps &= ~NETIF_F_TSO;
 	}
 }
diff -Nru a/include/net/udp.h b/include/net/udp.h
--- a/include/net/udp.h	Fri Oct 18 21:03:07 2002
+++ b/include/net/udp.h	Fri Oct 18 21:03:07 2002
@@ -76,6 +76,4 @@
 #define UDP_INC_STATS_BH(field)		SNMP_INC_STATS_BH(udp_statistics, field)
 #define UDP_INC_STATS_USER(field) 	SNMP_INC_STATS_USER(udp_statistics, field)
 
-#define udp_sock inet_sock
-
 #endif	/* _UDP_H */
diff -Nru a/include/scsi/sg.h b/include/scsi/sg.h
--- a/include/scsi/sg.h	Fri Oct 18 21:03:04 2002
+++ b/include/scsi/sg.h	Fri Oct 18 21:03:04 2002
@@ -130,7 +130,7 @@
 
 /* following flag values can be "or"-ed together */
 #define SG_FLAG_DIRECT_IO 1     /* default is indirect IO */
-#define SG_FLAG_LUN_INHIBIT 2   /* default is overwrite lun in SCSI */
+#define SG_FLAG_UNUSED_LUN_INHIBIT 2   /* default is overwrite lun in SCSI */
 				/* command block (when <= SCSI_2) */
 #define SG_FLAG_MMAP_IO 4       /* request memory mapped IO */
 #define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */
diff -Nru a/init/Makefile b/init/Makefile
--- a/init/Makefile	Fri Oct 18 21:03:04 2002
+++ b/init/Makefile	Fri Oct 18 21:03:04 2002
@@ -4,17 +4,20 @@
 
 obj-y    := main.o version.o do_mounts.o
 
+# files to be removed upon make clean
+clean-files := ../include/linux/compile.h
+
 include $(TOPDIR)/Rules.make
 
 # dependencies on generated files need to be listed explicitly
 
-$(obj)/version.o: $(objtree)/include/linux/compile.h
+$(obj)/version.o: $(obj)/../include/linux/compile.h
 
 # compile.h changes depending on hostname, generation number, etc,
 # so we regenerate it always.
 # mkcompile_h will make sure to only update the
 # actual file if its content has changed.
 
-$(objtree)/include/linux/compile.h: FORCE
-	@echo -n '  Generating $@'
+$(obj)/../include/linux/compile.h: FORCE
+	@echo -n '  Generating $(echo_target)'
 	@sh $(srctree)/scripts/mkcompile_h $@ "$(ARCH)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Fri Oct 18 21:03:03 2002
+++ b/kernel/ksyms.c	Fri Oct 18 21:03:03 2002
@@ -229,7 +229,7 @@
 EXPORT_SYMBOL(generic_block_bmap);
 EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(generic_file_sendfile);
-EXPORT_SYMBOL(do_generic_file_read);
+EXPORT_SYMBOL(do_generic_mapping_read);
 EXPORT_SYMBOL(generic_file_write);
 EXPORT_SYMBOL(generic_file_write_nolock);
 EXPORT_SYMBOL(generic_file_mmap);
@@ -326,7 +326,6 @@
 EXPORT_SYMBOL(default_llseek);
 EXPORT_SYMBOL(dentry_open);
 EXPORT_SYMBOL(filemap_nopage);
-EXPORT_SYMBOL(filemap_sync);
 EXPORT_SYMBOL(filemap_fdatawrite);
 EXPORT_SYMBOL(filemap_fdatawait);
 EXPORT_SYMBOL(lock_page);
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Fri Oct 18 21:03:04 2002
+++ b/kernel/signal.c	Fri Oct 18 21:03:04 2002
@@ -1427,6 +1427,9 @@
 		break;
 	case __SI_FAULT:
 		err |= __put_user(from->si_addr, &to->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		err |= __put_user(from->si_trapno, &to->si_trapno);
+#endif
 		break;
 	case __SI_CHLD:
 		err |= __put_user(from->si_pid, &to->si_pid);
diff -Nru a/lib/Makefile b/lib/Makefile
--- a/lib/Makefile	Fri Oct 18 21:03:03 2002
+++ b/lib/Makefile	Fri Oct 18 21:03:03 2002
@@ -29,5 +29,6 @@
 include $(TOPDIR)/drivers/net/Makefile.lib
 include $(TOPDIR)/drivers/usb/class/Makefile.lib
 include $(TOPDIR)/fs/Makefile.lib
+include $(TOPDIR)/net/bluetooth/bnep/Makefile.lib
 
 include $(TOPDIR)/Rules.make
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Fri Oct 18 21:03:04 2002
+++ b/mm/filemap.c	Fri Oct 18 21:03:04 2002
@@ -570,10 +570,15 @@
  *
  * This is really ugly. But the goto's actually try to clarify some
  * of the logic when it comes to error handling etc.
+ * - note the struct file * is only passed for the use of readpage
  */
-void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor)
+void do_generic_mapping_read(struct address_space *mapping,
+			     struct file_ra_state *ra,
+			     struct file * filp,
+			     loff_t *ppos,
+			     read_descriptor_t * desc,
+			     read_actor_t actor)
 {
-	struct address_space *mapping = filp->f_dentry->d_inode->i_mapping;
 	struct inode *inode = mapping->host;
 	unsigned long index, offset;
 	struct page *cached_page;
@@ -598,7 +603,7 @@
 				break;
 		}
 
-		page_cache_readahead(filp, index);
+		page_cache_readahead(mapping, ra, filp, index);
 
 		nr = nr - offset;
 
@@ -610,7 +615,7 @@
 		page = radix_tree_lookup(&mapping->page_tree, index);
 		if (!page) {
 			read_unlock(&mapping->page_lock);
-			handle_ra_miss(filp);
+			handle_ra_miss(mapping,ra);
 			goto no_cached_page;
 		}
 		page_cache_get(page);
@@ -891,6 +896,7 @@
 	BUG_ON(iocb->ki_pos != pos);
 	return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
 }
+EXPORT_SYMBOL(generic_file_aio_read);
 
 ssize_t
 generic_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
@@ -946,9 +952,9 @@
 }
 
 static ssize_t
-do_readahead(struct file *file, unsigned long index, unsigned long nr)
+do_readahead(struct address_space *mapping, struct file *filp,
+	     unsigned long index, unsigned long nr)
 {
-	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 	unsigned long max;
 	unsigned long active;
 	unsigned long inactive;
@@ -962,7 +968,7 @@
 	if (nr > max)
 		nr = max;
 
-	do_page_cache_readahead(file, index, nr);
+	do_page_cache_readahead(mapping, filp, index, nr);
 	return 0;
 }
 
@@ -975,10 +981,11 @@
 	file = fget(fd);
 	if (file) {
 		if (file->f_mode & FMODE_READ) {
+			struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 			unsigned long start = offset >> PAGE_CACHE_SHIFT;
 			unsigned long end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
 			unsigned long len = end - start + 1;
-			ret = do_readahead(file, start, len);
+			ret = do_readahead(mapping, file, start, len);
 		}
 		fput(file);
 	}
@@ -999,6 +1006,7 @@
 	int error;
 	struct file *file = area->vm_file;
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+	struct file_ra_state *ra = &file->f_ra;
 	struct inode *inode = mapping->host;
 	struct page *page;
 	unsigned long size, pgoff, endoff;
@@ -1031,7 +1039,7 @@
 	 */
 	if (VM_SequentialReadHint(area)) {
 		did_readahead = 1;
-		page_cache_readahead(area->vm_file, pgoff);
+		page_cache_readahead(mapping, ra, file, pgoff);
 	}
 
 	/*
@@ -1040,7 +1048,7 @@
 	 */
 	if ((pgoff < size) && !VM_RandomReadHint(area)) {
 		did_readahead = 1;
-		page_cache_readaround(file, pgoff);
+		page_cache_readaround(mapping, ra, file, pgoff);
 	}
 
 	/*
@@ -1050,7 +1058,7 @@
 	page = find_get_page(mapping, pgoff);
 	if (!page) {
 		if (did_readahead) {
-			handle_ra_miss(file);
+			handle_ra_miss(mapping,ra);
 			did_readahead = 0;
 		}
 		goto no_cached_page;
@@ -1650,6 +1658,7 @@
 {
 	return generic_file_write(iocb->ki_filp, buf, count, &iocb->ki_pos);
 }
+EXPORT_SYMBOL(generic_file_aio_write);
 
 ssize_t generic_file_write(struct file *file, const char *buf,
 			   size_t count, loff_t *ppos)
diff -Nru a/mm/madvise.c b/mm/madvise.c
--- a/mm/madvise.c	Fri Oct 18 21:03:04 2002
+++ b/mm/madvise.c	Fri Oct 18 21:03:04 2002
@@ -80,7 +80,7 @@
 	if ((vma->vm_mm->rss + (end - start)) > rlim_rss)
 		return error;
 
-	do_page_cache_readahead(file, start, end - start);
+	do_page_cache_readahead(file->f_dentry->d_inode->i_mapping, file, start, end - start);
 	return 0;
 }
 
diff -Nru a/mm/msync.c b/mm/msync.c
--- a/mm/msync.c	Fri Oct 18 21:03:04 2002
+++ b/mm/msync.c	Fri Oct 18 21:03:04 2002
@@ -94,7 +94,7 @@
 	return error;
 }
 
-int filemap_sync(struct vm_area_struct * vma, unsigned long address,
+static int filemap_sync(struct vm_area_struct * vma, unsigned long address,
 	size_t size, unsigned int flags)
 {
 	pgd_t * dir;
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	Fri Oct 18 21:03:03 2002
+++ b/mm/readahead.c	Fri Oct 18 21:03:03 2002
@@ -22,18 +22,18 @@
 /*
  * Return max readahead size for this inode in number-of-pages.
  */
-static inline unsigned long get_max_readahead(struct file *file)
+static inline unsigned long get_max_readahead(struct file_ra_state *ra)
 {
-	return file->f_ra.ra_pages;
+	return ra->ra_pages;
 }
 
-static inline unsigned long get_min_readahead(struct file *file)
+static inline unsigned long get_min_readahead(struct file_ra_state *ra)
 {
 	return (VM_MIN_READAHEAD * 1024) / PAGE_CACHE_SIZE;
 }
 
 static int
-read_pages(struct file *file, struct address_space *mapping,
+read_pages(struct address_space *mapping, struct file *filp,
 		struct list_head *pages, unsigned nr_pages)
 {
 	unsigned page_idx;
@@ -48,7 +48,7 @@
 		struct page *page = list_entry(pages->prev, struct page, list);
 		list_del(&page->list);
 		if (!add_to_page_cache(page, mapping, page->index)) {
-			mapping->a_ops->readpage(file, page);
+			mapping->a_ops->readpage(filp, page);
 			if (!pagevec_add(&lru_pvec, page))
 				__pagevec_lru_add(&lru_pvec);
 		} else {
@@ -134,10 +134,11 @@
  *
  * Returns the number of pages which actually had IO started against them.
  */
-int do_page_cache_readahead(struct file *file,
-			unsigned long offset, unsigned long nr_to_read)
+int do_page_cache_readahead(struct address_space *mapping,
+			    struct file *filp,
+			    unsigned long offset,
+			    unsigned long nr_to_read)
 {
-	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 	struct inode *inode = mapping->host;
 	struct page *page;
 	unsigned long end_index;	/* The last page we want to read */
@@ -181,7 +182,7 @@
 	 * will then handle the error.
 	 */
 	if (ret) {
-		read_pages(file, mapping, &page_pool, ret);
+		read_pages(mapping, filp, &page_pool, ret);
 		blk_run_queues();
 	}
 	BUG_ON(!list_empty(&page_pool));
@@ -216,9 +217,9 @@
  * page_cache_readahead is the main function.  If performs the adaptive
  * readahead window size management and submits the readahead I/O.
  */
-void page_cache_readahead(struct file *file, unsigned long offset)
+void page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
+			  struct file *filp, unsigned long offset)
 {
-	struct file_ra_state *ra = &file->f_ra;
 	unsigned max;
 	unsigned min;
 	unsigned orig_next_size;
@@ -239,11 +240,11 @@
 	if (ra->next_size == -1UL)
 		goto out;	/* Maximally shrunk */
 
-	max = get_max_readahead(file);
+	max = get_max_readahead(ra);
 	if (max == 0)
 		goto out;	/* No readahead */
 
-	min = get_min_readahead(file);
+	min = get_min_readahead(ra);
 	orig_next_size = ra->next_size;
 
 	if (ra->next_size == 0 && offset == 0) {
@@ -316,7 +317,8 @@
 		ra->ahead_start = 0;		/* Invalidate these */
 		ra->ahead_size = 0;
 
-		actual = do_page_cache_readahead(file, offset, ra->size);
+		actual = do_page_cache_readahead(mapping, filp, offset,
+						 ra->size);
 		check_ra_success(ra, ra->size, actual, orig_next_size);
 	} else {
 		/*
@@ -327,7 +329,7 @@
 		if (ra->ahead_start == 0) {
 			ra->ahead_start = ra->start + ra->size;
 			ra->ahead_size = ra->next_size;
-			actual = do_page_cache_readahead(file,
+			actual = do_page_cache_readahead(mapping, filp,
 					ra->ahead_start, ra->ahead_size);
 			check_ra_success(ra, ra->ahead_size,
 					actual, orig_next_size);
@@ -342,12 +344,11 @@
  * but somewhat ascending.  So readaround favours pages beyond the target one.
  * We also boost the window size, as it can easily shrink due to misses.
  */
-void page_cache_readaround(struct file *file, unsigned long offset)
+void page_cache_readaround(struct address_space *mapping, struct file_ra_state *ra,
+			   struct file *filp, unsigned long offset)
 {
-	struct file_ra_state *ra = &file->f_ra;
-
 	if (ra->next_size != -1UL) {
-		const unsigned long min = get_min_readahead(file) * 2;
+		const unsigned long min = get_min_readahead(ra) * 2;
 		unsigned long target;
 		unsigned long backward;
 
@@ -365,7 +366,7 @@
 			target = 0;
 		else
 			target -= backward;
-		page_cache_readahead(file, target);
+		page_cache_readahead(mapping, ra, filp, target);
 	}
 }
 
@@ -383,10 +384,9 @@
  * that the readahead window size will stabilise around the maximum level at
  * which there is no thrashing.
  */
-void handle_ra_miss(struct file *file)
+void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra)
 {
-	struct file_ra_state *ra = &file->f_ra;
-	const unsigned long min = get_min_readahead(file);
+	const unsigned long min = get_min_readahead(ra);
 
 	if (ra->next_size == -1UL) {
 		ra->next_size = min;
diff -Nru a/mm/vmalloc.c b/mm/vmalloc.c
--- a/mm/vmalloc.c	Fri Oct 18 21:03:05 2002
+++ b/mm/vmalloc.c	Fri Oct 18 21:03:05 2002
@@ -387,7 +387,7 @@
 	if (!area)
 		return NULL;
 
-	nr_pages = (size+PAGE_SIZE) >> PAGE_SHIFT;
+	nr_pages = size >> PAGE_SHIFT;
 	array_size = (nr_pages * sizeof(struct page *));
 
 	area->nr_pages = nr_pages;
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	Fri Oct 18 21:03:03 2002
+++ b/mm/vmscan.c	Fri Oct 18 21:03:03 2002
@@ -230,13 +230,8 @@
 		 * writes.
 		 */
 		if (PageWriteback(page)) {
-			if (may_enter_fs) {
-				if (page->pte.direct ||
-					page->mapping->backing_dev_info ==
-						current->backing_dev_info) {
-					wait_on_page_writeback(page);
-				}
-			}
+			if (may_enter_fs && page_mapped(page))
+				wait_on_page_writeback(page);
 			goto keep_locked;
 		}
 
@@ -555,10 +550,10 @@
 			/* It is currently in pagevec_release() */
 			SetPageLRU(page);
 			list_add(&page->lru, &zone->active_list);
-			continue;
+		} else {
+			page_cache_get(page);
+			list_add(&page->lru, &l_hold);
 		}
-		page_cache_get(page);
-		list_add(&page->lru, &l_hold);
 		nr_pages--;
 	}
 	spin_unlock_irq(&zone->lru_lock);
diff -Nru a/net/bluetooth/Config.in b/net/bluetooth/Config.in
--- a/net/bluetooth/Config.in	Fri Oct 18 21:03:07 2002
+++ b/net/bluetooth/Config.in	Fri Oct 18 21:03:07 2002
@@ -6,11 +6,11 @@
 
    mainmenu_option next_comment
    comment 'Bluetooth support'
-   dep_tristate 'Bluetooth subsystem support' CONFIG_BLUEZ $CONFIG_NET
+   dep_tristate 'Bluetooth subsystem support' CONFIG_BT $CONFIG_NET
 
-   if [ "$CONFIG_BLUEZ" != "n" ]; then
-      dep_tristate 'L2CAP protocol support' CONFIG_BLUEZ_L2CAP $CONFIG_BLUEZ
-      dep_tristate 'SCO links support' CONFIG_BLUEZ_SCO $CONFIG_BLUEZ
+   if [ "$CONFIG_BT" != "n" ]; then
+      dep_tristate 'L2CAP protocol support' CONFIG_BT_L2CAP $CONFIG_BT
+      dep_tristate 'SCO links support' CONFIG_BT_SCO $CONFIG_BT
       source net/bluetooth/rfcomm/Config.in
       source net/bluetooth/bnep/Config.in
       source drivers/bluetooth/Config.in
diff -Nru a/net/bluetooth/Makefile b/net/bluetooth/Makefile
--- a/net/bluetooth/Makefile	Fri Oct 18 21:03:03 2002
+++ b/net/bluetooth/Makefile	Fri Oct 18 21:03:03 2002
@@ -4,9 +4,9 @@
 
 export-objs := syms.o
 
-obj-$(CONFIG_BT)		+= bluetooth.o
+obj-$(CONFIG_BT)	+= bluetooth.o
 obj-$(CONFIG_BT_L2CAP)	+= l2cap.o
-obj-$(CONFIG_BT_SCO)		+= sco.o
+obj-$(CONFIG_BT_SCO)	+= sco.o
 obj-$(CONFIG_BT_RFCOMM)	+= rfcomm/
 obj-$(CONFIG_BT_BNEP)	+= bnep/
 
diff -Nru a/net/bluetooth/bnep/Makefile b/net/bluetooth/bnep/Makefile
--- a/net/bluetooth/bnep/Makefile	Fri Oct 18 21:03:08 2002
+++ b/net/bluetooth/bnep/Makefile	Fri Oct 18 21:03:08 2002
@@ -4,6 +4,6 @@
 
 obj-$(CONFIG_BT_BNEP) += bnep.o
 
-bnep-objs := core.o sock.o netdev.o crc32.o
+bnep-objs := core.o sock.o netdev.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/net/bluetooth/bnep/Makefile.lib b/net/bluetooth/bnep/Makefile.lib
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/bluetooth/bnep/Makefile.lib	Fri Oct 18 21:03:09 2002
@@ -0,0 +1 @@
+obj-$(CONFIG_BT_BNEP) += crc32.o
diff -Nru a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h
--- a/net/bluetooth/bnep/bnep.h	Fri Oct 18 21:03:04 2002
+++ b/net/bluetooth/bnep/bnep.h	Fri Oct 18 21:03:04 2002
@@ -24,10 +24,9 @@
 #define _BNEP_H
 
 #include <linux/types.h>
+#include <linux/crc32.h>
 #include <net/bluetooth/bluetooth.h>
 
-#include "crc32.h"
-
 // Limits
 #define BNEP_MAX_PROTO_FILTERS     5
 #define BNEP_MAX_MULTICAST_FILTERS 20
@@ -179,7 +178,7 @@
 
 static inline int bnep_mc_hash(__u8 *addr)
 {
-        return (bnep_crc32(~0, addr, ETH_ALEN) >> 26);
+        return (crc32_be(~0, addr, ETH_ALEN) >> 26);
 }
 
 #endif
diff -Nru a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
--- a/net/bluetooth/bnep/core.c	Fri Oct 18 21:03:07 2002
+++ b/net/bluetooth/bnep/core.c	Fri Oct 18 21:03:07 2002
@@ -712,16 +712,12 @@
 
 	bnep_sock_init();
 
-	bnep_crc32_init();
-
 	return 0;
 }
 
 static void __exit bnep_cleanup_module(void)
 {
 	bnep_sock_cleanup();
-
-	bnep_crc32_cleanup();
 }
 
 module_init(bnep_init_module);
diff -Nru a/net/bluetooth/bnep/crc32.c b/net/bluetooth/bnep/crc32.c
--- a/net/bluetooth/bnep/crc32.c	Fri Oct 18 21:03:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,59 +0,0 @@
-/* 
- * Based on linux-2.5/lib/crc32 by Matt Domsch <Matt_Domsch@dell.com>
- *
- * FIXME: Remove in 2.5  
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/atomic.h>
-
-#include "crc32.h"
-
-#define CRCPOLY_BE 0x04c11db7
-#define CRC_BE_BITS 8
-
-static u32 *bnep_crc32_table;
-
-/*
- * This code is in the public domain; copyright abandoned.
- * Liability for non-performance of this code is limited to the amount
- * you paid for it.  Since it is distributed for free, your refund will
- * be very very small.  If it breaks, you get to keep both pieces.
- */
-u32 bnep_crc32(u32 crc, unsigned char const *p, size_t len)
-{
-	while (len--)
-		crc = (crc << 8) ^ bnep_crc32_table[(crc >> 24) ^ *p++];
-	
-	return crc;
-}
-
-int __init bnep_crc32_init(void)
-{
-	unsigned i, j;
-	u32 crc = 0x80000000;
-
-	bnep_crc32_table = kmalloc((1 << CRC_BE_BITS) * sizeof(u32), GFP_KERNEL);
-	if (!bnep_crc32_table)
-		return -ENOMEM;
-
-	bnep_crc32_table[0] = 0;
-
-	for (i = 1; i < 1 << CRC_BE_BITS; i <<= 1) {
-		crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0);
-		for (j = 0; j < i; j++)
-			bnep_crc32_table[i + j] = crc ^ bnep_crc32_table[j];
-	}
-	return 0;
-}
-
-void __exit bnep_crc32_cleanup(void)
-{
-	if (bnep_crc32_table)
-		kfree(bnep_crc32_table);
-	bnep_crc32_table = NULL;
-}
diff -Nru a/net/bluetooth/bnep/crc32.h b/net/bluetooth/bnep/crc32.h
--- a/net/bluetooth/bnep/crc32.h	Fri Oct 18 21:03:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,10 +0,0 @@
-/*
- * crc32.h
- * See crc32.c for license and changes
- *
- * FIXME: Remove in 2.5
- */
-
-int  bnep_crc32_init(void);
-void bnep_crc32_cleanup(void);
-u32  bnep_crc32(u32 crc, unsigned char const *p, size_t len);
diff -Nru a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
--- a/net/bluetooth/bnep/sock.c	Fri Oct 18 21:03:08 2002
+++ b/net/bluetooth/bnep/sock.c	Fri Oct 18 21:03:08 2002
@@ -55,31 +55,6 @@
 #define BT_DBG( A... )
 #endif
 
-static struct socket *sockfd_lookup(int fd, int *err)
-{
-	struct file *file;
-	struct inode *inode;
-	struct socket *sock;
-
-	if (!(file = fget(fd))) {
-		*err = -EBADF;
-		return NULL;
-	}
-
-	inode = file->f_dentry->d_inode;
-	if (!inode->i_sock || !(sock = SOCKET_I(inode))) {
-		*err = -ENOTSOCK;
-		fput(file);
-		return NULL;
-	}
-
-	if (sock->file != file) {
-		printk(KERN_ERR "socki_lookup: socket file changed!\n");
-		sock->file = file;
-	}
-	return sock;
-}
- 
 static int bnep_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
diff -Nru a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
--- a/net/bluetooth/hci_conn.c	Fri Oct 18 21:03:08 2002
+++ b/net/bluetooth/hci_conn.c	Fri Oct 18 21:03:08 2002
@@ -61,7 +61,7 @@
 {
 	struct hci_dev *hdev = conn->hdev;
 	struct inquiry_entry *ie;
-	create_conn_cp cp;
+	struct hci_cp_create_conn cp;
 
 	BT_DBG("%p", conn);
 
@@ -85,13 +85,12 @@
 	else
 		cp.role_switch	= 0x00;
 		
-	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN,
-				CREATE_CONN_CP_SIZE, &cp);
+	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
 }
 
 void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
 {
-	disconnect_cp cp;
+	struct hci_cp_disconnect cp;
 
 	BT_DBG("%p", conn);
 
@@ -99,14 +98,13 @@
 
 	cp.handle = __cpu_to_le16(conn->handle);
 	cp.reason = reason;
-	hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT,
-				DISCONNECT_CP_SIZE, &cp);
+	hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT, sizeof(cp), &cp);
 }
 
 void hci_add_sco(struct hci_conn *conn, __u16 handle)
 {
 	struct hci_dev *hdev = conn->hdev;
-	add_sco_cp cp;
+	struct hci_cp_add_sco cp;
 
 	BT_DBG("%p", conn);
 
@@ -116,7 +114,7 @@
 	cp.pkt_type = __cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
 	cp.handle   = __cpu_to_le16(handle);
 
-	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, ADD_SCO_CP_SIZE, &cp);
+	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
 }
 
 static void hci_conn_timeout(unsigned long arg)
@@ -168,7 +166,7 @@
 	hci_dev_hold(hdev);
 
 	tasklet_disable(&hdev->tx_task);
-	conn_hash_add(hdev, conn);
+	hci_conn_hash_add(hdev, conn);
 	tasklet_enable(&hdev->tx_task);
 
 	return conn;
@@ -198,7 +196,7 @@
 	}
 
 	tasklet_disable(&hdev->tx_task);
-	conn_hash_del(hdev, conn);
+	hci_conn_hash_del(hdev, conn);
 	tasklet_enable(&hdev->tx_task);
 
 	skb_queue_purge(&conn->data_q);
@@ -257,7 +255,7 @@
 
 	BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
-	if (!(acl = conn_hash_lookup_ba(hdev, ACL_LINK, dst))) {
+	if (!(acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst))) {
 		if (!(acl = hci_conn_add(hdev, ACL_LINK, dst)))
 			return NULL;
 	}
@@ -270,7 +268,7 @@
 	if (type == SCO_LINK) {
 		struct hci_conn *sco;
 
-		if (!(sco = conn_hash_lookup_ba(hdev, SCO_LINK, dst))) {
+		if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) {
 			if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) {
 				hci_conn_put(acl);
 				return NULL;
@@ -300,10 +298,9 @@
 		return 1;
 	
 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
-		auth_requested_cp ar;
-		ar.handle = __cpu_to_le16(conn->handle);
-		hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_AUTH_REQUESTED,
-				AUTH_REQUESTED_CP_SIZE, &ar);
+		struct hci_cp_auth_requested cp;
+		cp.handle = __cpu_to_le16(conn->handle);
+		hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_AUTH_REQUESTED, sizeof(cp), &cp);
 	}
 	return 0;
 }
@@ -320,11 +317,10 @@
 		return 0;
 
 	if (hci_conn_auth(conn)) {
-		set_conn_encrypt_cp ce;
-		ce.handle  = __cpu_to_le16(conn->handle);
-		ce.encrypt = 1; 
-		hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT,
-				SET_CONN_ENCRYPT_CP_SIZE, &ce);
+		struct hci_cp_set_conn_encrypt cp;
+		cp.handle  = __cpu_to_le16(conn->handle);
+		cp.encrypt = 1; 
+		hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp);
 	}
 	return 0;
 }
@@ -332,7 +328,7 @@
 /* Drop all connection on the device */
 void hci_conn_hash_flush(struct hci_dev *hdev)
 {
-	struct conn_hash *h = &hdev->conn_hash;
+	struct hci_conn_hash *h = &hdev->conn_hash;
         struct list_head *p;
 
 	BT_DBG("hdev %s", hdev->name);
@@ -415,7 +411,7 @@
 		return -EFAULT;
 
 	hci_dev_lock_bh(hdev);
-	conn = conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
+	conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
 	if (conn) {
 		bacpy(&ci.bdaddr, &conn->dst);
 		ci.handle = conn->handle;
diff -Nru a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
--- a/net/bluetooth/hci_core.c	Fri Oct 18 21:03:04 2002
+++ b/net/bluetooth/hci_core.c	Fri Oct 18 21:03:04 2002
@@ -145,7 +145,8 @@
 }
 
 /* Execute request and wait for completion. */
-static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt), unsigned long opt, __u32 timeout)
+static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt), 
+				unsigned long opt, __u32 timeout)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int err = 0;
@@ -188,7 +189,7 @@
 }
 
 static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt),
-                                  unsigned long opt, __u32 timeout)
+				unsigned long opt, __u32 timeout)
 {
 	int ret;
 
@@ -210,7 +211,6 @@
 
 static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
 {
-	set_event_flt_cp ef;
 	__u16 param;
 
 	BT_DBG("%s %ld", hdev->name, opt);
@@ -226,13 +226,12 @@
 #if 0
 	/* Host buffer size */
 	{
-		host_buffer_size_cp bs;
-		bs.acl_mtu = __cpu_to_le16(HCI_MAX_ACL_SIZE);
-		bs.sco_mtu = HCI_MAX_SCO_SIZE;
-		bs.acl_max_pkt = __cpu_to_le16(0xffff);
-		bs.sco_max_pkt = __cpu_to_le16(0xffff);
-		hci_send_cmd(hdev, OGF_HOST_CTL, OCF_HOST_BUFFER_SIZE,
-				HOST_BUFFER_SIZE_CP_SIZE, &bs);
+		struct hci_cp_host_buffer_size cp;
+		cp.acl_mtu = __cpu_to_le16(HCI_MAX_ACL_SIZE);
+		cp.sco_mtu = HCI_MAX_SCO_SIZE;
+		cp.acl_max_pkt = __cpu_to_le16(0xffff);
+		cp.sco_max_pkt = __cpu_to_le16(0xffff);
+		hci_send_cmd(hdev, OGF_HOST_CTL, OCF_HOST_BUFFER_SIZE, sizeof(cp), &cp);
 	}
 #endif
 
@@ -242,8 +241,11 @@
 	/* Optional initialization */
 
 	/* Clear Event Filters */
-	ef.flt_type  = FLT_CLEAR_ALL;
-	hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, 1, &ef);
+	{
+		struct hci_cp_set_event_flt cp;
+		cp.flt_type  = HCI_FLT_CLEAR_ALL;
+		hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, sizeof(cp), &cp);
+	}
 
 	/* Page timeout ~20 secs */
 	param = __cpu_to_le16(0x8000);
@@ -338,7 +340,7 @@
 	return e;
 }
 
-void inquiry_cache_update(struct hci_dev *hdev, inquiry_info *info)
+void inquiry_cache_update(struct hci_dev *hdev, struct inquiry_info *info)
 {
 	struct inquiry_cache *cache = &hdev->inq_cache;
 	struct inquiry_entry *e;
@@ -354,7 +356,7 @@
 		cache->list = e;
 	}
 
-	memcpy(&e->info, info, sizeof(inquiry_info));
+	memcpy(&e->info, info, sizeof(*info));
 	e->timestamp = jiffies;
 	cache->timestamp = jiffies;
 }
@@ -362,12 +364,12 @@
 int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
 {
 	struct inquiry_cache *cache = &hdev->inq_cache;
-	inquiry_info *info = (inquiry_info *) buf;
+	struct inquiry_info *info = (struct inquiry_info *) buf;
 	struct inquiry_entry *e;
 	int copied = 0;
 
 	for (e = cache->list; e && copied < num; e = e->next, copied++)
-		memcpy(info++, &e->info, sizeof(inquiry_info));
+		memcpy(info++, &e->info, sizeof(*info));
 
 	BT_DBG("cache %p, copied %d", cache, copied);
 	return copied;
@@ -376,7 +378,7 @@
 static void hci_inq_req(struct hci_dev *hdev, unsigned long opt)
 {
 	struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt;
-	inquiry_cp ic;
+	struct hci_cp_inquiry cp;
 
 	BT_DBG("%s", hdev->name);
 
@@ -384,10 +386,10 @@
 		return;
 
 	/* Start Inquiry */
-	memcpy(&ic.lap, &ir->lap, 3);
-	ic.length  = ir->length;
-	ic.num_rsp = ir->num_rsp;
-	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_INQUIRY, INQUIRY_CP_SIZE, &ic);
+	memcpy(&cp.lap, &ir->lap, 3);
+	cp.length  = ir->length;
+	cp.num_rsp = ir->num_rsp;
+	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_INQUIRY, sizeof(cp), &cp);
 }
 
 int hci_inquiry(unsigned long arg)
@@ -420,7 +422,7 @@
 	/* cache_dump can't sleep. Therefore we allocate temp buffer and then
 	 * copy it to the user space.
 	 */
-	if (!(buf = kmalloc(sizeof(inquiry_info) * ir.num_rsp, GFP_KERNEL))) {
+	if (!(buf = kmalloc(sizeof(struct inquiry_info) * ir.num_rsp, GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto done;
 	}
@@ -432,10 +434,10 @@
 	BT_DBG("num_rsp %d", ir.num_rsp);
 
 	if (!verify_area(VERIFY_WRITE, ptr, sizeof(ir) + 
-				(sizeof(inquiry_info) * ir.num_rsp))) {
+			(sizeof(struct inquiry_info) * ir.num_rsp))) {
 		copy_to_user(ptr, &ir, sizeof(ir));
 		ptr += sizeof(ir);
-	        copy_to_user(ptr, buf, sizeof(inquiry_info) * ir.num_rsp);
+	        copy_to_user(ptr, buf, sizeof(struct inquiry_info) * ir.num_rsp);
 	} else 
 		err = -EFAULT;
 
@@ -780,7 +782,6 @@
 	return err;
 }
 
-
 /* ---- Interface to HCI drivers ---- */
 
 /* Register HCI device */
@@ -827,7 +828,7 @@
 
 	inquiry_cache_init(hdev);
 
-	conn_hash_init(hdev);
+	hci_conn_hash_init(hdev);
 
 	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
 
@@ -879,31 +880,6 @@
 	return 0;
 }       
 
-/* Receive frame from HCI drivers */
-int hci_recv_frame(struct sk_buff *skb)
-{
-	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
-
-	if (!hdev || (!test_bit(HCI_UP, &hdev->flags) && 
-				!test_bit(HCI_INIT, &hdev->flags)) ) {
-		kfree_skb(skb);
-		return -1;
-	}
-
-	BT_DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len);
-
-	/* Incomming skb */
-	bt_cb(skb)->incoming = 1;
-
-	/* Time stamp */
-	do_gettimeofday(&skb->stamp);
-
-	/* Queue frame for rx task */
-	skb_queue_tail(&hdev->rx_q, skb);
-	hci_sched_rx(hdev);
-	return 0;
-}
-
 /* ---- Interface to upper protocols ---- */
 
 /* Register/Unregister protocols.
@@ -1012,19 +988,20 @@
 int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param)
 {
 	int len = HCI_COMMAND_HDR_SIZE + plen;
-	hci_command_hdr *hc;
+	struct hci_command_hdr *hdr;
 	struct sk_buff *skb;
 
 	BT_DBG("%s ogf 0x%x ocf 0x%x plen %d", hdev->name, ogf, ocf, plen);
 
-	if (!(skb = bt_skb_alloc(len, GFP_ATOMIC))) {
+	skb = bt_skb_alloc(len, GFP_ATOMIC);
+	if (!skb) {
 		BT_ERR("%s Can't allocate memory for HCI command", hdev->name);
 		return -ENOMEM;
 	}
 	
-	hc = (hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE);
-	hc->opcode = __cpu_to_le16(cmd_opcode_pack(ogf, ocf));
-	hc->plen   = plen;
+	hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE);
+	hdr->opcode = __cpu_to_le16(hci_opcode_pack(ogf, ocf));
+	hdr->plen   = plen;
 
 	if (plen)
 		memcpy(skb_put(skb, plen), param, plen);
@@ -1042,14 +1019,14 @@
 /* Get data from the previously sent command */
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf)
 {
-	hci_command_hdr *hc;
+	struct hci_command_hdr *hdr;
 
 	if (!hdev->sent_cmd)
 		return NULL;
 
-	hc = (void *) hdev->sent_cmd->data;
+	hdr = (void *) hdev->sent_cmd->data;
 
-	if (hc->opcode != __cpu_to_le16(cmd_opcode_pack(ogf, ocf)))
+	if (hdr->opcode != __cpu_to_le16(hci_opcode_pack(ogf, ocf)))
 		return NULL;
 
 	BT_DBG("%s ogf 0x%x ocf 0x%x", hdev->name, ogf, ocf);
@@ -1060,14 +1037,14 @@
 /* Send ACL data */
 static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
 {
+	struct hci_acl_hdr *hdr;
 	int len = skb->len;
-	hci_acl_hdr *ah;
 
-	ah = (hci_acl_hdr *) skb_push(skb, HCI_ACL_HDR_SIZE);
-	ah->handle = __cpu_to_le16(acl_handle_pack(handle, flags));
-	ah->dlen   = __cpu_to_le16(len);
+	hdr = (struct hci_acl_hdr *) skb_push(skb, HCI_ACL_HDR_SIZE);
+	hdr->handle = __cpu_to_le16(hci_handle_pack(handle, flags));
+	hdr->dlen   = __cpu_to_le16(len);
 
-	skb->h.raw = (void *) ah;
+	skb->h.raw = (void *) hdr;
 }
 
 int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
@@ -1119,7 +1096,7 @@
 int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
 {
 	struct hci_dev *hdev = conn->hdev;
-	hci_sco_hdr hs;
+	struct hci_sco_hdr hdr;
 
 	BT_DBG("%s len %d", hdev->name, skb->len);
 
@@ -1128,11 +1105,11 @@
 		return -EINVAL;
 	}
 
-	hs.handle = __cpu_to_le16(conn->handle);
-	hs.dlen   = skb->len;
+	hdr.handle = __cpu_to_le16(conn->handle);
+	hdr.dlen   = skb->len;
 
 	skb->h.raw = skb_push(skb, HCI_SCO_HDR_SIZE);
-	memcpy(skb->h.raw, &hs, HCI_SCO_HDR_SIZE);
+	memcpy(skb->h.raw, &hdr, HCI_SCO_HDR_SIZE);
 
 	skb->dev = (void *) hdev;
 	skb->pkt_type = HCI_SCODATA_PKT;
@@ -1146,7 +1123,7 @@
 /* HCI Connection scheduler */
 static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
 {
-	struct conn_hash *h = &hdev->conn_hash;
+	struct hci_conn_hash *h = &hdev->conn_hash;
 	struct hci_conn  *conn = NULL;
 	int num = 0, min = ~0;
         struct list_head *p;
@@ -1181,7 +1158,7 @@
 
 static inline void hci_acl_tx_to(struct hci_dev *hdev)
 {
-	struct conn_hash *h = &hdev->conn_hash;
+	struct hci_conn_hash *h = &hdev->conn_hash;
         struct list_head *p;
 	struct hci_conn  *c;
 
@@ -1271,22 +1248,22 @@
 /* ACL data packet */
 static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	hci_acl_hdr *ah = (void *) skb->data;
+	struct hci_acl_hdr *hdr = (void *) skb->data;
 	struct hci_conn *conn;
 	__u16 handle, flags;
 
 	skb_pull(skb, HCI_ACL_HDR_SIZE);
 
-	handle = __le16_to_cpu(ah->handle);
-	flags  = acl_flags(handle);
-	handle = acl_handle(handle);
+	handle = __le16_to_cpu(hdr->handle);
+	flags  = hci_flags(handle);
+	handle = hci_handle(handle);
 
 	BT_DBG("%s len %d handle 0x%x flags 0x%x", hdev->name, skb->len, handle, flags);
 
 	hdev->stat.acl_rx++;
 
 	hci_dev_lock(hdev);
-	conn = conn_hash_lookup_handle(hdev, handle);
+	conn = hci_conn_hash_lookup_handle(hdev, handle);
 	hci_dev_unlock(hdev);
 	
 	if (conn) {
@@ -1308,20 +1285,20 @@
 /* SCO data packet */
 static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	hci_sco_hdr *sh = (void *) skb->data;
+	struct hci_sco_hdr *hdr = (void *) skb->data;
 	struct hci_conn *conn;
 	__u16 handle;
 
 	skb_pull(skb, HCI_SCO_HDR_SIZE);
 
-	handle = __le16_to_cpu(sh->handle);
+	handle = __le16_to_cpu(hdr->handle);
 
 	BT_DBG("%s len %d handle 0x%x", hdev->name, skb->len, handle);
 
 	hdev->stat.sco_rx++;
 
 	hci_dev_lock(hdev);
-	conn = conn_hash_lookup_handle(hdev, handle);
+	conn = hci_conn_hash_lookup_handle(hdev, handle);
 	hci_dev_unlock(hdev);
 	
 	if (conn) {
diff -Nru a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
--- a/net/bluetooth/hci_event.c	Fri Oct 18 21:03:03 2002
+++ b/net/bluetooth/hci_event.c	Fri Oct 18 21:03:03 2002
@@ -75,7 +75,7 @@
 static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
 {
 	struct hci_conn *conn;
-	role_discovery_rp *rd;
+	struct hci_rp_role_discovery *rd;
 
 	BT_DBG("%s ocf 0x%x", hdev->name, ocf);
 
@@ -88,7 +88,7 @@
 		
 		hci_dev_lock(hdev);
 	
-		conn = conn_hash_lookup_handle(hdev, __le16_to_cpu(rd->handle));
+		conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rd->handle));
 		if (conn) {
 			if (rd->role)
 				conn->link_mode &= ~HCI_LM_MASTER;
@@ -219,15 +219,15 @@
 /* Command Complete OGF INFO_PARAM  */
 static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
 {
-	read_local_features_rp *lf;
-	read_buffer_size_rp *bs;
-	read_bd_addr_rp *ba;
+	struct hci_rp_read_loc_features *lf;
+	struct hci_rp_read_buffer_size *bs;
+	struct hci_rp_read_bd_addr *ba;
 
 	BT_DBG("%s ocf 0x%x", hdev->name, ocf);
 
 	switch (ocf) {
 	case OCF_READ_LOCAL_FEATURES:
-		lf = (read_local_features_rp *) skb->data;
+		lf = (struct hci_rp_read_loc_features *) skb->data;
 
 		if (lf->status) {
 			BT_DBG("%s READ_LOCAL_FEATURES failed %d", hdev->name, lf->status);
@@ -255,7 +255,7 @@
 		break;
 
 	case OCF_READ_BUFFER_SIZE:
-		bs = (read_buffer_size_rp *) skb->data;
+		bs = (struct hci_rp_read_buffer_size *) skb->data;
 
 		if (bs->status) {
 			BT_DBG("%s READ_BUFFER_SIZE failed %d", hdev->name, bs->status);
@@ -273,7 +273,7 @@
 		break;
 
 	case OCF_READ_BD_ADDR:
-		ba = (read_bd_addr_rp *) skb->data;
+		ba = (struct hci_rp_read_bd_addr *) skb->data;
 
 		if (!ba->status) {
 			bacpy(&hdev->bdaddr, &ba->bdaddr);
@@ -294,16 +294,16 @@
 static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
 {
 	struct hci_conn *conn;
-	create_conn_cp *cc = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_CREATE_CONN);
+	struct hci_cp_create_conn *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_CREATE_CONN);
 
-	if (!cc)
+	if (!cp)
 		return;
 
 	hci_dev_lock(hdev);
 	
-	conn = conn_hash_lookup_ba(hdev, ACL_LINK, &cc->bdaddr);
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
 
-	BT_DBG("%s status 0x%x bdaddr %s conn %p", hdev->name, 
+	BT_DBG("%s status 0x%x bdaddr %s conn %p", hdev->name,
 			status, batostr(&cc->bdaddr), conn);
 
 	if (status) {
@@ -314,7 +314,7 @@
 		}
 	} else {
 		if (!conn) {
-			conn = hci_conn_add(hdev, ACL_LINK, &cc->bdaddr);
+			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
 			if (conn) {
 				conn->out = 1;
 				conn->link_mode |= HCI_LM_MASTER;
@@ -338,8 +338,7 @@
 	case OCF_ADD_SCO:
 		if (status) {
 			struct hci_conn *acl, *sco;
-			add_sco_cp *cp = hci_sent_cmd_data(hdev, 
-						OGF_LINK_CTL, OCF_ADD_SCO);
+			struct hci_cp_add_sco *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_ADD_SCO);
 			__u16 handle;
 
 			if (!cp)
@@ -351,7 +350,7 @@
 
 			hci_dev_lock(hdev);
 	
-			acl = conn_hash_lookup_handle(hdev, handle);
+			acl = hci_conn_hash_lookup_handle(hdev, handle);
 			if (acl && (sco = acl->link)) {
 				sco->state = BT_CLOSED;
 
@@ -429,7 +428,7 @@
 /* Inquiry Result */
 static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	inquiry_info *info = (inquiry_info *) (skb->data + 1);
+	struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1);
 	int num_rsp = *((__u8 *) skb->data);
 
 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
@@ -443,23 +442,23 @@
 /* Connect Request */
 static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	evt_conn_request *cr = (evt_conn_request *) skb->data;
+	struct hci_ev_conn_request *ev = (struct hci_ev_conn_request *) skb->data;
 	int mask = hdev->link_mode;
 
 	BT_DBG("%s Connection request: %s type 0x%x", hdev->name,
-			batostr(&cr->bdaddr), cr->link_type);
+			batostr(&ev->bdaddr), ev->link_type);
 
-	mask |= hci_proto_connect_ind(hdev, &cr->bdaddr, cr->link_type);
+	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
 
 	if (mask & HCI_LM_ACCEPT) {
 		/* Connection accepted */
 		struct hci_conn *conn;
-		accept_conn_req_cp ac;
+		struct hci_cp_accept_conn_req cp;
 
 		hci_dev_lock(hdev);
-		conn = conn_hash_lookup_ba(hdev, cr->link_type, &cr->bdaddr);
+		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
 		if (!conn) {
-			if (!(conn = hci_conn_add(hdev, cr->link_type, &cr->bdaddr))) {
+			if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
 				BT_ERR("No memmory for new connection");
 				hci_dev_unlock(hdev);
 				return;
@@ -468,44 +467,42 @@
 		conn->state = BT_CONNECT;
 		hci_dev_unlock(hdev);
 
-		bacpy(&ac.bdaddr, &cr->bdaddr);
+		bacpy(&cp.bdaddr, &ev->bdaddr);
 	
 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
-			ac.role = 0x00; /* Become master */
+			cp.role = 0x00; /* Become master */
 		else
-			ac.role = 0x01; /* Remain slave */
+			cp.role = 0x01; /* Remain slave */
 
-		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ, 
-				ACCEPT_CONN_REQ_CP_SIZE, &ac);
+		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp);
 	} else {
 		/* Connection rejected */
-		reject_conn_req_cp rc;
+		struct hci_cp_reject_conn_req cp;
 
-		bacpy(&rc.bdaddr, &cr->bdaddr);
-		rc.reason = 0x0f;
-		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_REJECT_CONN_REQ,
-				REJECT_CONN_REQ_CP_SIZE, &rc);
+		bacpy(&cp.bdaddr, &ev->bdaddr);
+		cp.reason = 0x0f;
+		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_REJECT_CONN_REQ, sizeof(cp), &cp);
 	}
 }
 
 /* Connect Complete */
 static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	evt_conn_complete *cc = (evt_conn_complete *) skb->data;
+	struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
 	struct hci_conn *conn = NULL;
 
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
 	
-	conn = conn_hash_lookup_ba(hdev, cc->link_type, &cc->bdaddr);
+	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
 	if (!conn) {
 		hci_dev_unlock(hdev);
 		return;
 	}
 
-	if (!cc->status) {
-		conn->handle = __le16_to_cpu(cc->handle);
+	if (!ev->status) {
+		conn->handle = __le16_to_cpu(ev->handle);
 		conn->state  = BT_CONNECTED;
 
 		if (test_bit(HCI_AUTH, &hdev->flags))
@@ -517,23 +514,21 @@
 
 		/* Set link policy */
 		if (conn->type == ACL_LINK && hdev->link_policy) {
-			write_link_policy_cp lp;
-			lp.handle = cc->handle;
-			lp.policy = __cpu_to_le16(hdev->link_policy);
-			hci_send_cmd(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY,
-				WRITE_LINK_POLICY_CP_SIZE, &lp);
+			struct hci_cp_write_link_policy cp;
+			cp.handle = ev->handle;
+			cp.policy = __cpu_to_le16(hdev->link_policy);
+			hci_send_cmd(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY, sizeof(cp), &cp);
 		}
 
 		/* Set packet type for incomming connection */
 		if (!conn->out) {
-			change_conn_ptype_cp cp;
-			cp.handle = cc->handle;
+			struct hci_cp_change_conn_ptype cp;
+			cp.handle = ev->handle;
 			cp.pkt_type = (conn->type == ACL_LINK) ? 
 				__cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK):
 				__cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
 
-			hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_PTYPE,
-				CHANGE_CONN_PTYPE_CP_SIZE, &cp);
+			hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
 		}
 	} else
 		conn->state = BT_CLOSED;
@@ -541,17 +536,17 @@
 	if (conn->type == ACL_LINK) {
 		struct hci_conn *sco = conn->link;
 		if (sco) {
-			if (!cc->status)
+			if (!ev->status)
 				hci_add_sco(sco, conn->handle);
 			else {
-				hci_proto_connect_cfm(sco, cc->status);
+				hci_proto_connect_cfm(sco, ev->status);
 				hci_conn_del(sco);
 			}
 		}
 	}
 
-	hci_proto_connect_cfm(conn, cc->status);
-	if (cc->status)
+	hci_proto_connect_cfm(conn, ev->status);
+	if (ev->status)
 		hci_conn_del(conn);
 
 	hci_dev_unlock(hdev);
@@ -560,21 +555,21 @@
 /* Disconnect Complete */
 static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	evt_disconn_complete *dc = (evt_disconn_complete *) skb->data;
+	struct hci_ev_disconn_complete *ev = (struct hci_ev_disconn_complete *) skb->data;
 	struct hci_conn *conn = NULL;
-	__u16 handle = __le16_to_cpu(dc->handle);
+	__u16 handle = __le16_to_cpu(ev->handle);
 
-	BT_DBG("%s status %d", hdev->name, dc->status);
+	BT_DBG("%s status %d", hdev->name, ev->status);
 
-	if (dc->status)
+	if (ev->status)
 		return;
 
 	hci_dev_lock(hdev);
 	
-	conn = conn_hash_lookup_handle(hdev, handle);
+	conn = hci_conn_hash_lookup_handle(hdev, handle);
 	if (conn) {
 		conn->state = BT_CLOSED;
-		hci_proto_disconn_ind(conn, dc->reason);
+		hci_proto_disconn_ind(conn, ev->reason);
 		hci_conn_del(conn);
 	}
 
@@ -584,29 +579,29 @@
 /* Number of completed packets */
 static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	evt_num_comp_pkts *nc = (evt_num_comp_pkts *) skb->data;
+	struct hci_ev_num_comp_pkts *ev = (struct hci_ev_num_comp_pkts *) skb->data;
 	__u16 *ptr;
 	int i;
 
-	skb_pull(skb, EVT_NUM_COMP_PKTS_SIZE);
+	skb_pull(skb, sizeof(*ev));
 
-	BT_DBG("%s num_hndl %d", hdev->name, nc->num_hndl);
+	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
 
-	if (skb->len < nc->num_hndl * 4) {
+	if (skb->len < ev->num_hndl * 4) {
 		BT_DBG("%s bad parameters", hdev->name);
 		return;
 	}
 
 	tasklet_disable(&hdev->tx_task);
 
-	for (i = 0, ptr = (__u16 *) skb->data; i < nc->num_hndl; i++) {
+	for (i = 0, ptr = (__u16 *) skb->data; i < ev->num_hndl; i++) {
 		struct hci_conn *conn;
 		__u16  handle, count;
 
 		handle = __le16_to_cpu(get_unaligned(ptr++));
 		count  = __le16_to_cpu(get_unaligned(ptr++));
 
-		conn = conn_hash_lookup_handle(hdev, handle);
+		conn = hci_conn_hash_lookup_handle(hdev, handle);
 		if (conn) {
 			conn->sent -= count;
 
@@ -627,19 +622,19 @@
 /* Role Change */
 static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	evt_role_change *rc = (evt_role_change *) skb->data;
+	struct hci_ev_role_change *ev = (struct hci_ev_role_change *) skb->data;
 	struct hci_conn *conn = NULL;
 
-	BT_DBG("%s status %d", hdev->name, rc->status);
+	BT_DBG("%s status %d", hdev->name, ev->status);
 
-	if (rc->status)
+	if (ev->status)
 		return;
 
 	hci_dev_lock(hdev);
 	
-	conn = conn_hash_lookup_ba(hdev, ACL_LINK, &rc->bdaddr);
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	if (conn) {
-		if (rc->role)
+		if (ev->role)
 			conn->link_mode &= ~HCI_LM_MASTER;
 		else 
 			conn->link_mode |= HCI_LM_MASTER;
@@ -651,33 +646,33 @@
 /* Authentication Complete */
 static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	evt_auth_complete *ac = (evt_auth_complete *) skb->data;
+	struct hci_ev_auth_complete *ev = (struct hci_ev_auth_complete *) skb->data;
 	struct hci_conn *conn = NULL;
-	__u16 handle = __le16_to_cpu(ac->handle);
+	__u16 handle = __le16_to_cpu(ev->handle);
 
-	BT_DBG("%s status %d", hdev->name, ac->status);
+	BT_DBG("%s status %d", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
 	
-	conn = conn_hash_lookup_handle(hdev, handle);
+	conn = hci_conn_hash_lookup_handle(hdev, handle);
 	if (conn) {
-		if (!ac->status)
+		if (!ev->status)
 			conn->link_mode |= HCI_LM_AUTH;
 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
 
-		hci_proto_auth_cfm(conn, ac->status);
+		hci_proto_auth_cfm(conn, ev->status);
 		
 		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
-			if (!ac->status) {
-				set_conn_encrypt_cp ce;
-				ce.handle  = __cpu_to_le16(conn->handle);
-				ce.encrypt = 1;
+			if (!ev->status) {
+				struct hci_cp_set_conn_encrypt cp;
+				cp.handle  = __cpu_to_le16(conn->handle);
+				cp.encrypt = 1;
 				hci_send_cmd(conn->hdev, OGF_LINK_CTL,
 						OCF_SET_CONN_ENCRYPT,
-						SET_CONN_ENCRYPT_CP_SIZE, &ce);
+						sizeof(cp), &cp);
 			} else {
 				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
-				hci_proto_encrypt_cfm(conn, ac->status);
+				hci_proto_encrypt_cfm(conn, ev->status);
 			}
 		}
 	}
@@ -688,25 +683,25 @@
 /* Encryption Change */
 static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	evt_encrypt_change *ec = (evt_encrypt_change *) skb->data;
+	struct hci_ev_encrypt_change *ev = (struct hci_ev_encrypt_change *) skb->data;
 	struct hci_conn *conn = NULL;
-	__u16 handle = __le16_to_cpu(ec->handle);
+	__u16 handle = __le16_to_cpu(ev->handle);
 
-	BT_DBG("%s status %d", hdev->name, ec->status);
+	BT_DBG("%s status %d", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
 	
-	conn = conn_hash_lookup_handle(hdev, handle);
+	conn = hci_conn_hash_lookup_handle(hdev, handle);
 	if (conn) {
-		if (!ec->status) {
-		       	if (ec->encrypt)
+		if (!ev->status) {
+		       	if (ev->encrypt)
 				conn->link_mode |= HCI_LM_ENCRYPT;
 			else
 				conn->link_mode &= ~HCI_LM_ENCRYPT;
 		}
 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
 		
-		hci_proto_encrypt_cfm(conn, ec->status);
+		hci_proto_encrypt_cfm(conn, ev->status);
 	}
 
 	hci_dev_unlock(hdev);
@@ -714,59 +709,59 @@
 
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	hci_event_hdr *he = (hci_event_hdr *) skb->data;
-	evt_cmd_status *cs;
-	evt_cmd_complete *ec;
-	__u16 opcode, ocf, ogf;
+	struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data;
+	struct hci_ev_cmd_complete *ec;
+	struct hci_ev_cmd_status *cs;
+	u16 opcode, ocf, ogf;
 
 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
 
-	BT_DBG("%s evt 0x%x", hdev->name, he->evt);
+	BT_DBG("%s evt 0x%x", hdev->name, hdr->evt);
 
-	switch (he->evt) {
-	case EVT_NUM_COMP_PKTS:
+	switch (hdr->evt) {
+	case HCI_EV_NUM_COMP_PKTS:
 		hci_num_comp_pkts_evt(hdev, skb);
 		break;
 
-	case EVT_INQUIRY_COMPLETE:
+	case HCI_EV_INQUIRY_COMPLETE:
 		hci_inquiry_complete_evt(hdev, skb);
 		break;
 
-	case EVT_INQUIRY_RESULT:
+	case HCI_EV_INQUIRY_RESULT:
 		hci_inquiry_result_evt(hdev, skb);
 		break;
 
-	case EVT_CONN_REQUEST:
+	case HCI_EV_CONN_REQUEST:
 		hci_conn_request_evt(hdev, skb);
 		break;
 
-	case EVT_CONN_COMPLETE:
+	case HCI_EV_CONN_COMPLETE:
 		hci_conn_complete_evt(hdev, skb);
 		break;
 
-	case EVT_DISCONN_COMPLETE:
+	case HCI_EV_DISCONN_COMPLETE:
 		hci_disconn_complete_evt(hdev, skb);
 		break;
 
-	case EVT_ROLE_CHANGE:
+	case HCI_EV_ROLE_CHANGE:
 		hci_role_change_evt(hdev, skb);
 		break;
 
-	case EVT_AUTH_COMPLETE:
+	case HCI_EV_AUTH_COMPLETE:
 		hci_auth_complete_evt(hdev, skb);
 		break;
 
-	case EVT_ENCRYPT_CHANGE:
+	case HCI_EV_ENCRYPT_CHANGE:
 		hci_encrypt_change_evt(hdev, skb);
 		break;
 
-	case EVT_CMD_STATUS:
-		cs = (evt_cmd_status *) skb->data;
-		skb_pull(skb, EVT_CMD_STATUS_SIZE);
+	case HCI_EV_CMD_STATUS:
+		cs = (struct hci_ev_cmd_status *) skb->data;
+		skb_pull(skb, sizeof(cs));
 				
 		opcode = __le16_to_cpu(cs->opcode);
-		ogf = cmd_opcode_ogf(opcode);
-		ocf = cmd_opcode_ocf(opcode);
+		ogf = hci_opcode_ogf(opcode);
+		ocf = hci_opcode_ocf(opcode);
 
 		switch (ogf) {
 		case OGF_INFO_PARAM:
@@ -788,7 +783,7 @@
 		default:
 			BT_DBG("%s Command Status OGF %x", hdev->name, ogf);
 			break;
-		};
+		}
 
 		if (cs->ncmd) {
 			atomic_set(&hdev->cmd_cnt, 1);
@@ -797,13 +792,13 @@
 		}
 		break;
 
-	case EVT_CMD_COMPLETE:
-		ec = (evt_cmd_complete *) skb->data;
-		skb_pull(skb, EVT_CMD_COMPLETE_SIZE);
+	case HCI_EV_CMD_COMPLETE:
+		ec = (struct hci_ev_cmd_complete *) skb->data;
+		skb_pull(skb, sizeof(*ec));
 
 		opcode = __le16_to_cpu(ec->opcode);
-		ogf = cmd_opcode_ogf(opcode);
-		ocf = cmd_opcode_ocf(opcode);
+		ogf = hci_opcode_ogf(opcode);
+		ocf = hci_opcode_ocf(opcode);
 
 		switch (ogf) {
 		case OGF_INFO_PARAM:
@@ -825,7 +820,7 @@
 		default:
 			BT_DBG("%s Command Completed OGF %x", hdev->name, ogf);
 			break;
-		};
+		}
 
 		if (ec->ncmd) {
 			atomic_set(&hdev->cmd_cnt, 1);
@@ -833,36 +828,30 @@
 				hci_sched_cmd(hdev);
 		}
 		break;
-	};
+	}
 
 	kfree_skb(skb);
 	hdev->stat.evt_rx++;
 }
 
-/* General internal stack event */
+/* Generate internal stack event */
 void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
 {
-	hci_event_hdr *eh;
-	evt_stack_internal *si;
+	struct hci_event_hdr *hdr;
+	struct hci_ev_stack_internal *ev;
 	struct sk_buff *skb;
-	int size;
-	void *ptr;
 
-	size = HCI_EVENT_HDR_SIZE + EVT_STACK_INTERNAL_SIZE + dlen;
-	skb  = bt_skb_alloc(size, GFP_ATOMIC);
+	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
 	if (!skb)
 		return;
 
-	ptr = skb_put(skb, size);
-
-	eh = ptr;
-       	eh->evt  = EVT_STACK_INTERNAL;
-	eh->plen = EVT_STACK_INTERNAL_SIZE + dlen;
-	ptr += HCI_EVENT_HDR_SIZE;
-
-	si = ptr;
-	si->type = type;
-	memcpy(si->data, data, dlen);
+	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
+       	hdr->evt  = HCI_EV_STACK_INTERNAL;
+	hdr->plen = sizeof(*ev) + dlen;
+
+	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
+	ev->type = type;
+	memcpy(ev->data, data, dlen);
 	
 	skb->pkt_type = HCI_EVENT_PKT;
 	skb->dev = (void *) hdev;
diff -Nru a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
--- a/net/bluetooth/hci_sock.c	Fri Oct 18 21:03:04 2002
+++ b/net/bluetooth/hci_sock.c	Fri Oct 18 21:03:04 2002
@@ -114,9 +114,9 @@
 			if (!test_bit(evt, flt->event_mask))
 				continue;
 
-			if (flt->opcode && ((evt == EVT_CMD_COMPLETE && 
+			if (flt->opcode && ((evt == HCI_EV_CMD_COMPLETE && 
 					flt->opcode != *(__u16 *)(skb->data + 3)) ||
-					(evt == EVT_CMD_STATUS && 
+					(evt == HCI_EV_CMD_STATUS && 
 					flt->opcode != *(__u16 *)(skb->data + 4))))
 				continue;
 		}
@@ -394,8 +394,8 @@
 
 		if (skb->pkt_type == HCI_COMMAND_PKT) {
 			u16 opcode = __le16_to_cpu(*(__u16 *)skb->data);
-			u16 ogf = cmd_opcode_ogf(opcode) - 1;
-			u16 ocf = cmd_opcode_ocf(opcode) & HCI_FLT_OCF_BITS;
+			u16 ogf = hci_opcode_ogf(opcode) - 1;
+			u16 ocf = hci_opcode_ocf(opcode) & HCI_FLT_OCF_BITS;
 
 			if (ogf > HCI_SFLT_MAX_OGF ||
 					!test_bit(ocf, hci_sec_filter.ocf_mask[ogf]))
@@ -584,14 +584,14 @@
 static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
 	struct hci_dev *hdev = (struct hci_dev *) ptr;
-	evt_si_device sd;
+	struct hci_ev_si_device ev;
 	
 	BT_DBG("hdev %s event %ld", hdev->name, event);
 
 	/* Send event to sockets */
-	sd.event  = event;
-	sd.dev_id = hdev->id;
-	hci_si_event(NULL, EVT_SI_DEVICE, EVT_SI_DEVICE_SIZE, &sd);
+	ev.event  = event;
+	ev.dev_id = hdev->id;
+	hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
 	
 	if (event == HCI_DEV_UNREG) {
 		struct sock *sk;
diff -Nru a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
--- a/net/bluetooth/l2cap.c	Fri Oct 18 21:03:07 2002
+++ b/net/bluetooth/l2cap.c	Fri Oct 18 21:03:07 2002
@@ -72,16 +72,15 @@
 
 static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent);
 static void l2cap_chan_del(struct sock *sk, int err);
-static int  l2cap_chan_send(struct sock *sk, struct msghdr *msg, int len);
 
 static void __l2cap_sock_close(struct sock *sk, int reason);
 static void l2cap_sock_close(struct sock *sk);
 static void l2cap_sock_kill(struct sock *sk);
 
-static int l2cap_send_req(struct l2cap_conn *conn, __u8 code, __u16 len, void *data);
-static int l2cap_send_rsp(struct l2cap_conn *conn, __u8 ident, __u8 code, __u16 len, void *data);
+static int l2cap_send_req(struct l2cap_conn *conn, u8 code, u16 len, void *data);
+static int l2cap_send_rsp(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
 
-/* ----- L2CAP timers ------ */
+/* ---- L2CAP timers ---- */
 static void l2cap_sock_timeout(unsigned long arg)
 {
 	struct sock *sk = (struct sock *) arg;
@@ -119,8 +118,8 @@
 	sk->timer.data = (unsigned long)sk;
 }
 
-/* -------- L2CAP connections --------- */
-static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, __u8 status)
+/* ---- L2CAP connections ---- */
+static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 {
 	struct l2cap_conn *conn;
 
@@ -226,10 +225,10 @@
 
 	if (hcon->state == BT_CONNECTED) {
 		if (sk->type == SOCK_SEQPACKET) {
-			l2cap_conn_req req;
+			struct l2cap_conn_req req;
 			req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
 			req.psm  = l2cap_pi(sk)->psm;
-			l2cap_send_req(conn, L2CAP_CONN_REQ, L2CAP_CONN_REQ_SIZE, &req);
+			l2cap_send_req(conn, L2CAP_CONN_REQ, sizeof(req), &req);
 		} else {
 			l2cap_sock_clear_timer(sk);
 			sk->state = BT_CONNECTED;
@@ -242,8 +241,8 @@
 	return err;
 }
 
-/* -------- Socket interface ---------- */
-static struct sock *__l2cap_get_sock_by_addr(__u16 psm, bdaddr_t *src)
+/* ---- Socket interface ---- */
+static struct sock *__l2cap_get_sock_by_addr(u16 psm, bdaddr_t *src)
 {
 	struct sock *sk;
 	for (sk = l2cap_sk_list.head; sk; sk = sk->next) {
@@ -257,7 +256,7 @@
 /* Find socket with psm and source bdaddr.
  * Returns closest match.
  */
-static struct sock *__l2cap_get_sock_by_psm(int state, __u16 psm, bdaddr_t *src)
+static struct sock *__l2cap_get_sock_by_psm(int state, u16 psm, bdaddr_t *src)
 {
 	struct sock *sk, *sk1 = NULL;
 
@@ -280,7 +279,7 @@
 
 /* Find socket with given address (psm, src).
  * Returns locked socket */
-static inline struct sock *l2cap_get_sock_by_psm(int state, __u16 psm, bdaddr_t *src)
+static inline struct sock *l2cap_get_sock_by_psm(int state, u16 psm, bdaddr_t *src)
 {
 	struct sock *s;
 	read_lock(&l2cap_sk_list.lock);
@@ -347,14 +346,14 @@
 	case BT_CONNECT2:
 		if (sk->type == SOCK_SEQPACKET) {
 			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-			l2cap_disconn_req req;
+			struct l2cap_disconn_req req;
 
 			sk->state = BT_DISCONN;
 			l2cap_sock_set_timer(sk, HZ * 5);
 
 			req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
 			req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
-			l2cap_send_req(conn, L2CAP_DISCONN_REQ, L2CAP_DISCONN_REQ_SIZE, &req);
+			l2cap_send_req(conn, L2CAP_DISCONN_REQ, sizeof(req), &req);
 		} else {
 			l2cap_chan_del(sk, reason);
 		}
@@ -368,7 +367,7 @@
 	default:
 		sk->zapped = 1;
 		break;
-	};
+	}
 }
 
 /* Must be called on unlocked socket. */
@@ -641,6 +640,74 @@
 	return 0;
 }
 
+static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff *skb, **frag;
+	int err, hlen, count, sent=0;
+	struct l2cap_hdr *lh;
+
+	BT_DBG("sk %p len %d", sk, len);
+
+	/* First fragment (with L2CAP header) */
+	if (sk->type == SOCK_DGRAM)
+		hlen = L2CAP_HDR_SIZE + 2;
+	else
+		hlen = L2CAP_HDR_SIZE;
+
+	count = min_t(unsigned int, (conn->mtu - hlen), len);
+
+	skb = bt_skb_send_alloc(sk, hlen + count,
+			msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return err;
+
+	/* Create L2CAP header */
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid);
+	lh->len = __cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+
+	if (sk->type == SOCK_DGRAM)
+		put_unaligned(l2cap_pi(sk)->psm, (u16 *) skb_put(skb, 2));
+
+	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
+		err = -EFAULT;
+		goto fail;
+	}
+
+	sent += count;
+	len  -= count;
+
+	/* Continuation fragments (no L2CAP header) */
+	frag = &skb_shinfo(skb)->frag_list;
+	while (len) {
+		count = min_t(unsigned int, conn->mtu, len);
+
+		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
+		if (!*frag)
+			goto fail;
+		
+		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) {
+			err = -EFAULT;
+			goto fail;
+		}
+
+		sent += count;
+		len  -= count;
+
+		frag = &(*frag)->next;
+	}
+
+	if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0)
+		goto fail;
+
+	return sent;
+
+fail:
+	kfree_skb(skb);
+	return err;
+}
+
 static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
 {
 	struct sock *sk = sock->sk;
@@ -661,7 +728,7 @@
 	lock_sock(sk);
 
 	if (sk->state == BT_CONNECTED)
-		err = l2cap_chan_send(sk, msg, len);
+		err = l2cap_do_send(sk, msg, len);
 	else
 		err = -ENOTCONN;
 
@@ -674,7 +741,7 @@
 	struct sock *sk = sock->sk;
 	struct l2cap_options opts;
 	int err = 0, len;
-	__u32 opt;
+	u32 opt;
 
 	BT_DBG("sk %p", sk);
 
@@ -692,7 +759,7 @@
 		break;
 
 	case L2CAP_LM:
-		if (get_user(opt, (__u32 *)optval)) {
+		if (get_user(opt, (u32 *)optval)) {
 			err = -EFAULT;
 			break;
 		}
@@ -734,7 +801,7 @@
 		break;
 
 	case L2CAP_LM:
-		if (put_user(l2cap_pi(sk)->link_mode, (__u32 *)optval))
+		if (put_user(l2cap_pi(sk)->link_mode, (u32 *)optval))
 			err = -EFAULT;
 		break;
 
@@ -792,8 +859,8 @@
 	return 0;
 }
 
-/* --------- L2CAP channels --------- */
-static struct sock * __l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, __u16 cid)
+/* ---- L2CAP channels ---- */
+static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
 {
 	struct sock *s;
 	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
@@ -803,7 +870,7 @@
 	return s;
 }
 
-static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, __u16 cid)
+static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
 {
 	struct sock *s;
 	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
@@ -815,7 +882,7 @@
 
 /* Find channel with given SCID.
  * Returns locked socket */
-static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, __u16 cid)
+static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
 {
 	struct sock *s;
 	read_lock(&l->lock);
@@ -825,9 +892,9 @@
 	return s;
 }
 
-static __u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
+static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
 {
-	__u16 cid = 0x0040;
+	u16 cid = 0x0040;
 
 	for (; cid < 0xffff; cid++) {
 		if(!__l2cap_get_chan_by_scid(l, cid))
@@ -940,10 +1007,10 @@
 			sk->state = BT_CONNECTED;
 			sk->state_change(sk);
 		} else if (sk->state == BT_CONNECT) {
-			l2cap_conn_req req;
+			struct l2cap_conn_req req;
 			req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
 			req.psm  = l2cap_pi(sk)->psm;
-			l2cap_send_req(conn, L2CAP_CONN_REQ, L2CAP_CONN_REQ_SIZE, &req);
+			l2cap_send_req(conn, L2CAP_CONN_REQ, sizeof(req), &req);
 		}
 
 		bh_unlock_sock(sk);
@@ -1002,78 +1069,10 @@
 	read_unlock(&l->lock);
 }
 
-static int l2cap_chan_send(struct sock *sk, struct msghdr *msg, int len)
+/* ---- L2CAP signalling commands ---- */
+static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
 {
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff *skb, **frag;
-	int err, hlen, count, sent=0;
-	l2cap_hdr *lh;
-
-	BT_DBG("sk %p len %d", sk, len);
-
-	/* First fragment (with L2CAP header) */
-	if (sk->type == SOCK_DGRAM)
-		hlen = L2CAP_HDR_SIZE + 2;
-	else
-		hlen = L2CAP_HDR_SIZE;
-
-	count = min_t(unsigned int, (conn->mtu - hlen), len);
-
-	skb = bt_skb_send_alloc(sk, hlen + count,
-			msg->msg_flags & MSG_DONTWAIT, &err);
-	if (!skb)
-		return err;
-
-	/* Create L2CAP header */
-	lh = (l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-	lh->len = __cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
-
-	if (sk->type == SOCK_DGRAM)
-		put_unaligned(l2cap_pi(sk)->psm, (__u16 *) skb_put(skb, 2));
-
-	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
-		err = -EFAULT;
-		goto fail;
-	}
-
-	sent += count;
-	len  -= count;
-
-	/* Continuation fragments (no L2CAP header) */
-	frag = &skb_shinfo(skb)->frag_list;
-	while (len) {
-		count = min_t(unsigned int, conn->mtu, len);
-
-		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
-		if (!*frag)
-			goto fail;
-		
-		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) {
-			err = -EFAULT;
-			goto fail;
-		}
-
-		sent += count;
-		len  -= count;
-
-		frag = &(*frag)->next;
-	}
-
-	if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0)
-		goto fail;
-
-	return sent;
-
-fail:
-	kfree_skb(skb);
-	return err;
-}
-
-/* --------- L2CAP signalling commands --------- */
-static inline __u8 l2cap_get_ident(struct l2cap_conn *conn)
-{
-	__u8 id;
+	u8 id;
 
 	/* Get next available identificator.
 	 *    1 - 199 are used by kernel.
@@ -1093,11 +1092,11 @@
 }
 
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
-				__u8 code, __u8 ident, __u16 dlen, void *data)
+				u8 code, u8 ident, u16 dlen, void *data)
 {
 	struct sk_buff *skb, **frag;
-	l2cap_cmd_hdr *cmd;
-	l2cap_hdr *lh;
+	struct l2cap_cmd_hdr *cmd;
+	struct l2cap_hdr *lh;
 	int len, count;
 
 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", conn, code, ident, dlen);
@@ -1109,11 +1108,11 @@
 	if (!skb)
 		return NULL;
 
-	lh = (l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
 	lh->len = __cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
 	lh->cid = __cpu_to_le16(0x0001);
 
-	cmd = (l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
+	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
 	cmd->code  = code;
 	cmd->ident = ident;
 	cmd->len   = __cpu_to_le16(dlen);
@@ -1150,9 +1149,9 @@
 	return NULL;
 }
 
-static int l2cap_send_req(struct l2cap_conn *conn, __u8 code, __u16 len, void *data)
+static int l2cap_send_req(struct l2cap_conn *conn, u8 code, u16 len, void *data)
 {
-	__u8 ident = l2cap_get_ident(conn);
+	u8 ident = l2cap_get_ident(conn);
 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
 
 	BT_DBG("code 0x%2.2x", code);
@@ -1162,7 +1161,7 @@
 	return hci_send_acl(conn->hcon, skb, 0);
 }
 
-static int l2cap_send_rsp(struct l2cap_conn *conn, __u8 ident, __u8 code, __u16 len, void *data)
+static int l2cap_send_rsp(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
 {
 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
 
@@ -1175,7 +1174,7 @@
 
 static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
 {
-	l2cap_conf_opt *opt = *ptr;
+	struct l2cap_conf_opt *opt = *ptr;
 	int len;
 
 	len = L2CAP_CONF_OPT_SIZE + opt->len;
@@ -1186,21 +1185,21 @@
 
 	switch (opt->len) {
 	case 1:
-		*val = *((__u8 *) opt->val);
+		*val = *((u8 *) opt->val);
 		break;
 
 	case 2:
-		*val = __le16_to_cpu(*((__u16 *)opt->val));
+		*val = __le16_to_cpu(*((u16 *)opt->val));
 		break;
 
 	case 4:
-		*val = __le32_to_cpu(*((__u32 *)opt->val));
+		*val = __le32_to_cpu(*((u32 *)opt->val));
 		break;
 
 	default:
 		*val = (unsigned long) opt->val;
 		break;
-	};
+	}
 
 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
 	return len;
@@ -1238,13 +1237,13 @@
 
 			/* FIXME: Reject unknown option */
 			break;
-		};
+		}
 	}
 }
 
-static void l2cap_add_conf_opt(void **ptr, __u8 type, __u8 len, unsigned long val)
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
 {
-	register l2cap_conf_opt *opt = *ptr;
+	struct l2cap_conf_opt *opt = *ptr;
 
 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
 
@@ -1253,21 +1252,21 @@
 
 	switch (len) {
 	case 1:
-		*((__u8 *) opt->val)  = val;
+		*((u8 *) opt->val)  = val;
 		break;
 
 	case 2:
-		*((__u16 *) opt->val) = __cpu_to_le16(val);
+		*((u16 *) opt->val) = __cpu_to_le16(val);
 		break;
 
 	case 4:
-		*((__u32 *) opt->val) = __cpu_to_le32(val);
+		*((u32 *) opt->val) = __cpu_to_le32(val);
 		break;
 
 	default:
 		memcpy(opt->val, (void *) val, len);
 		break;
-	};
+	}
 
 	*ptr += L2CAP_CONF_OPT_SIZE + len;
 }
@@ -1275,7 +1274,7 @@
 static int l2cap_build_conf_req(struct sock *sk, void *data)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	l2cap_conf_req *req = (l2cap_conf_req *) data;
+	struct l2cap_conf_req *req = data;
 	void *ptr = req->data;
 
 	BT_DBG("sk %p", sk);
@@ -1314,7 +1313,7 @@
 
 static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result)
 {
-	l2cap_conf_rsp *rsp = (l2cap_conf_rsp *) data;
+	struct l2cap_conf_rsp *rsp = data;
 	void *ptr = rsp->data;
 
 	BT_DBG("sk %p complete %d", sk, result ? 1 : 0);
@@ -1329,16 +1328,16 @@
 	return ptr - data;
 }
 
-static inline int l2cap_connect_req(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data)
+static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
 	struct l2cap_chan_list *list = &conn->chan_list;
-	l2cap_conn_req *req = (l2cap_conn_req *) data;
-	l2cap_conn_rsp rsp;
+	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
+	struct l2cap_conn_rsp rsp;
 	struct sock *sk, *parent;
 	int result = 0, status = 0;
 
-	__u16 dcid = 0, scid = __le16_to_cpu(req->scid);
-	__u16 psm  = req->psm;
+	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
+	u16 psm  = req->psm;
 
 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
 
@@ -1412,14 +1411,14 @@
 	rsp.dcid   = __cpu_to_le16(dcid);
 	rsp.result = __cpu_to_le16(result);
 	rsp.status = __cpu_to_le16(status);
-	l2cap_send_rsp(conn, cmd->ident, L2CAP_CONN_RSP, L2CAP_CONN_RSP_SIZE, &rsp);
+	l2cap_send_rsp(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 	return 0;
 }
 
-static inline int l2cap_connect_rsp(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data)
+static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-	l2cap_conn_rsp *rsp = (l2cap_conn_rsp *) data;
-	__u16 scid, dcid, result, status;
+	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
+	u16 scid, dcid, result, status;
 	struct sock *sk;
 	char req[128];
 
@@ -1454,11 +1453,11 @@
 	return 0;
 }
 
-static inline int l2cap_config_req(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data)
+static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-	l2cap_conf_req * req = (l2cap_conf_req *) data;
-	__u16 dcid, flags;
-	__u8 rsp[64];
+	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
+	u16 dcid, flags;
+	u8  rsp[64];
 	struct sock *sk;
 	int result;
 
@@ -1470,7 +1469,7 @@
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid)))
 		return -ENOENT;
 
-	l2cap_parse_conf_req(sk, req->data, cmd->len - L2CAP_CONF_REQ_SIZE);
+	l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req));
 
 	if (flags & 0x01) {
 		/* Incomplete config. Send empty response. */
@@ -1491,7 +1490,7 @@
 		sk->state = BT_CONNECTED;
 		l2cap_chan_ready(sk);
 	} else if (!(l2cap_pi(sk)->conf_state & CONF_REQ_SENT)) {
-		char req[64];
+		u8 req[64];
 		l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req);
 	}
 
@@ -1500,10 +1499,10 @@
 	return 0;
 }
 
-static inline int l2cap_config_rsp(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data)
+static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-	l2cap_conf_rsp *rsp = (l2cap_conf_rsp *)data;
-	__u16 scid, flags, result;
+	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
+	u16 scid, flags, result;
 	struct sock *sk;
 	int err = 0;
 
@@ -1517,7 +1516,7 @@
 		return -ENOENT;
 
 	if (result) {
-		l2cap_disconn_req req;
+		struct l2cap_disconn_req req;
 
 		/* They didn't like our options. Well... we do not negotiate.
 		 * Close channel.
@@ -1527,7 +1526,7 @@
 
 		req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
 		req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
-		l2cap_send_req(conn, L2CAP_DISCONN_REQ, L2CAP_DISCONN_REQ_SIZE, &req);
+		l2cap_send_req(conn, L2CAP_DISCONN_REQ, sizeof(req), &req);
 		goto done;
 	}
 
@@ -1547,11 +1546,11 @@
 	return err;
 }
 
-static inline int l2cap_disconnect_req(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data)
+static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-	l2cap_disconn_req *req = (l2cap_disconn_req *) data;
-	l2cap_disconn_rsp rsp;
-	__u16 dcid, scid;
+	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
+	struct l2cap_disconn_rsp rsp;
+	u16 dcid, scid;
 	struct sock *sk;
 
 	scid = __le16_to_cpu(req->scid);
@@ -1564,7 +1563,7 @@
 
 	rsp.dcid = __cpu_to_le16(l2cap_pi(sk)->scid);
 	rsp.scid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-	l2cap_send_rsp(conn, cmd->ident, L2CAP_DISCONN_RSP, L2CAP_DISCONN_RSP_SIZE, &rsp);
+	l2cap_send_rsp(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
 
 	sk->shutdown = SHUTDOWN_MASK;
 	
@@ -1575,10 +1574,10 @@
 	return 0;
 }
 
-static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data)
+static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-	l2cap_disconn_rsp *rsp = (l2cap_disconn_rsp *) data;
-	__u16 dcid, scid;
+	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
+	u16 dcid, scid;
 	struct sock *sk;
 
 	scid = __le16_to_cpu(rsp->scid);
@@ -1597,9 +1596,9 @@
 
 static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-	__u8 *data = skb->data;
+	u8 *data = skb->data;
 	int len = skb->len;
-	l2cap_cmd_hdr cmd;
+	struct l2cap_cmd_hdr cmd;
 	int err = 0;
 
 	while (len >= L2CAP_CMD_HDR_SIZE) {
@@ -1660,15 +1659,15 @@
 			BT_ERR("Uknown signaling command 0x%2.2x", cmd.code);
 			err = -EINVAL;
 			break;
-		};
+		}
 
 		if (err) {
-			l2cap_cmd_rej rej;
+			struct l2cap_cmd_rej rej;
 			BT_DBG("error %d", err);
 
 			/* FIXME: Map err to a valid reason. */
 			rej.reason = __cpu_to_le16(0);
-			l2cap_send_rsp(conn, cmd.ident, L2CAP_COMMAND_REJ, L2CAP_CMD_REJ_SIZE, &rej);
+			l2cap_send_rsp(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
 		}
 
 		data += cmd.len;
@@ -1678,7 +1677,7 @@
 	kfree_skb(skb);
 }
 
-static inline int l2cap_data_channel(struct l2cap_conn *conn, __u16 cid, struct sk_buff *skb)
+static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
 {
 	struct sock *sk;
 
@@ -1712,7 +1711,7 @@
 	return 0;
 }
 
-static inline int l2cap_conless_channel(struct l2cap_conn *conn, __u16 psm, struct sk_buff *skb)
+static inline int l2cap_conless_channel(struct l2cap_conn *conn, u16 psm, struct sk_buff *skb)
 {
 	struct sock *sk;
 
@@ -1741,8 +1740,8 @@
 
 static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-	l2cap_hdr *lh = (l2cap_hdr *) skb->data;
-	__u16 cid, psm, len;
+	struct l2cap_hdr *lh = (void *) skb->data;
+	u16 cid, psm, len;
 
 	skb_pull(skb, L2CAP_HDR_SIZE);
 	cid = __le16_to_cpu(lh->cid);
@@ -1756,7 +1755,7 @@
 		break;
 
 	case 0x0002:
-		psm = get_unaligned((__u16 *) skb->data);
+		psm = get_unaligned((u16 *) skb->data);
 		skb_pull(skb, 2);
 		l2cap_conless_channel(conn, psm, skb);
 		break;
@@ -1767,9 +1766,9 @@
 	}
 }
 
-/* ------------ L2CAP interface with lower layer (HCI) ------------- */
+/* ---- L2CAP interface with lower layer (HCI) ---- */
 
-static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
+static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 {
 	int exact = 0, lm1 = 0, lm2 = 0;
 	register struct sock *sk;
@@ -1796,7 +1795,7 @@
 	return exact ? lm1 : lm2;
 }
 
-static int l2cap_connect_cfm(struct hci_conn *hcon, __u8 status)
+static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 {
 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
 
@@ -1815,7 +1814,7 @@
 	return 0;
 }
 
-static int l2cap_disconn_ind(struct hci_conn *hcon, __u8 reason)
+static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason)
 {
 	BT_DBG("hcon %p reason %d", hcon, reason);
 
@@ -1826,11 +1825,11 @@
 	return 0;
 }
 
-static int l2cap_auth_cfm(struct hci_conn *hcon, __u8 status)
+static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
 {
 	struct l2cap_chan_list *l;
 	struct l2cap_conn *conn;
-	l2cap_conn_rsp rsp;
+	struct l2cap_conn_rsp rsp;
 	struct sock *sk;
 	int result;
 	
@@ -1864,8 +1863,7 @@
 		rsp.dcid   = __cpu_to_le16(l2cap_pi(sk)->scid);
 		rsp.result = __cpu_to_le16(result);
 		rsp.status = __cpu_to_le16(0);
-		l2cap_send_rsp(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP,
-			L2CAP_CONN_RSP_SIZE, &rsp);
+		l2cap_send_rsp(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 
 		bh_unlock_sock(sk);
 	}
@@ -1874,11 +1872,11 @@
 	return 0;
 }
 
-static int l2cap_encrypt_cfm(struct hci_conn *hcon, __u8 status)
+static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
 {
 	struct l2cap_chan_list *l;
 	struct l2cap_conn *conn;
-	l2cap_conn_rsp rsp;
+	struct l2cap_conn_rsp rsp;
 	struct sock *sk;
 	int result;
 	
@@ -1911,8 +1909,7 @@
 		rsp.dcid   = __cpu_to_le16(l2cap_pi(sk)->scid);
 		rsp.result = __cpu_to_le16(result);
 		rsp.status = __cpu_to_le16(0);
-		l2cap_send_rsp(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP, 
-			L2CAP_CONN_RSP_SIZE, &rsp);
+		l2cap_send_rsp(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 
 		bh_unlock_sock(sk);
 	}
@@ -1921,7 +1918,7 @@
 	return 0;
 }
 
-static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, __u16 flags)
+static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
 	struct l2cap_conn *conn = hcon->l2cap_data;
 
@@ -1931,7 +1928,7 @@
 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
 
 	if (flags & ACL_START) {
-		l2cap_hdr *hdr;
+		struct l2cap_hdr *hdr;
 		int len;
 
 		if (conn->rx_len) {
@@ -1946,7 +1943,7 @@
 			goto drop;
 		}
 
-		hdr = (l2cap_hdr *) skb->data;
+		hdr = (struct l2cap_hdr *) skb->data;
 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
 
 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
@@ -1995,7 +1992,7 @@
 	return 0;
 }
 
-/* ----- Proc fs support ------ */
+/* ---- Proc fs support ---- */
 static int l2cap_sock_dump(char *buf, struct bt_sock_list *list)
 {
 	struct l2cap_pinfo *pi;
diff -Nru a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
--- a/net/bluetooth/rfcomm/core.c	Fri Oct 18 21:03:03 2002
+++ b/net/bluetooth/rfcomm/core.c	Fri Oct 18 21:03:03 2002
@@ -423,7 +423,12 @@
 	rfcomm_schedule(RFCOMM_SCHED_TX);
 }
 
-int rfcomm_dlc_modem_status(struct rfcomm_dlc *d, int v24_sig)
+/* 
+   Set/get modem status functions use _local_ status i.e. what we report
+   to the other side.
+   Remote status is provided by dlc->modem_status() callback.
+ */
+int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig)
 {
 	BT_DBG("dlc %p state %ld v24_sig 0x%x", 
 			d, d->state, v24_sig);
@@ -438,6 +443,15 @@
 	if (!test_and_set_bit(RFCOMM_MSC_PENDING, &d->flags))
 		rfcomm_schedule(RFCOMM_SCHED_TX);
 
+	return 0;
+}
+
+int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig)
+{
+	BT_DBG("dlc %p state %ld v24_sig 0x%x", 
+			d, d->state, d->v24_sig);
+
+	*v24_sig = d->v24_sig;
 	return 0;
 }
 
diff -Nru a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
--- a/net/bluetooth/rfcomm/sock.c	Fri Oct 18 21:03:05 2002
+++ b/net/bluetooth/rfcomm/sock.c	Fri Oct 18 21:03:05 2002
@@ -109,12 +109,6 @@
 	bh_unlock_sock(sk);
 }
 
-static void rfcomm_sk_modem_status(struct rfcomm_dlc *d, int v24_sig)
-{
-	BT_DBG("dlc %p v24_sig 0x%02x", d, v24_sig);
-	return;
-}
-
 /* ---- Socket functions ---- */
 static struct sock *__rfcomm_get_sock_by_addr(int channel, bdaddr_t *src)
 {
@@ -276,7 +270,6 @@
 	}
 	d->data_ready   = rfcomm_sk_data_ready;
 	d->state_change = rfcomm_sk_state_change;
-	d->modem_status = rfcomm_sk_modem_status;
 
 	rfcomm_pi(sk)->dlc = d;
 	d->owner = sk;
diff -Nru a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
--- a/net/bluetooth/rfcomm/tty.c	Fri Oct 18 21:03:04 2002
+++ b/net/bluetooth/rfcomm/tty.c	Fri Oct 18 21:03:04 2002
@@ -64,6 +64,8 @@
 	bdaddr_t		dst;
 	u8 			channel;
 
+	uint 			modem_status;
+
 	struct rfcomm_dlc	*dlc;
 	struct tty_struct	*tty;
 	wait_queue_head_t       wait;
@@ -78,7 +80,7 @@
 
 static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb);
 static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err);
-static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, int v24_sig);
+static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
 
 static void rfcomm_tty_wakeup(unsigned long arg);
 
@@ -266,6 +268,9 @@
 }
 
 /* ---- Device IOCTLs ---- */
+
+#define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP))
+
 static int rfcomm_create_dev(struct sock *sk, unsigned long arg)
 {
 	struct rfcomm_dev_req req;
@@ -277,7 +282,14 @@
 
 	BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags);
 
+	if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
+		return -EPERM;
+	
 	if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
+		/* Socket must be connected */
+		if (sk->state != BT_CONNECTED)
+			return -EBADFD;
+
 		dlc = rfcomm_pi(sk)->dlc;
 		rfcomm_dlc_hold(dlc);
 	} else {
@@ -311,6 +323,9 @@
 
 	BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags);
 
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+	
 	if (!(dev = rfcomm_dev_get(req.dev_id)))
 		return -ENODEV;
 
@@ -476,11 +491,20 @@
 	}
 }
 
-static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, int v24_sig)
+static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
 {
-	BT_DBG("dlc %p v24_sig 0x%02x", dlc, v24_sig);
-}
+	struct rfcomm_dev *dev = dlc->owner;
+	if (!dev)
+		return;
+	
+	BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);
 
+	dev->modem_status = 
+		(v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0 |
+		(v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0 |
+		(v24_sig & RFCOMM_V24_IC)  ? TIOCM_RI : 0 |
+		(v24_sig & RFCOMM_V24_DV)  ? TIOCM_CD : 0;
+}
 
 /* ---- TTY functions ---- */
 static void rfcomm_tty_wakeup(unsigned long arg)
@@ -629,11 +653,38 @@
 	return dlc->mtu * (dlc->tx_credits ? : 10);
 }
 
+static int rfcomm_tty_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint status)
+{
+	u8 v24_sig, mask;
+
+	BT_DBG("dlc %p cmd 0x%02x", dlc, cmd);
+
+	if (cmd == TIOCMSET)
+		v24_sig = 0;
+	else
+		rfcomm_dlc_get_modem_status(dlc, &v24_sig);
+
+	mask =  (status & TIOCM_DSR) ? RFCOMM_V24_RTC : 0 |
+		(status & TIOCM_DTR) ? RFCOMM_V24_RTC : 0 |
+		(status & TIOCM_RTS) ? RFCOMM_V24_RTR : 0 |
+		(status & TIOCM_CTS) ? RFCOMM_V24_RTR : 0 |
+		(status & TIOCM_RI)  ? RFCOMM_V24_IC  : 0 |
+		(status & TIOCM_CD)  ? RFCOMM_V24_DV  : 0;
+
+	if (cmd == TIOCMBIC)
+		v24_sig &= ~mask;
+	else
+		v24_sig |= mask;
+
+	rfcomm_dlc_set_modem_status(dlc, v24_sig);
+	return 0;
+}
+
 static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
 	struct rfcomm_dlc *dlc = dev->dlc;
-	unsigned int modeminfo;
+	uint status;
 	int err;
 
 	BT_DBG("tty %p cmd 0x%02x", tty, cmd);
@@ -650,34 +701,14 @@
 	case TIOCMGET:
 		BT_DBG("TIOCMGET");
 
-		modeminfo = ((dlc->v24_sig & RFCOMM_V24_RTC) ? TIOCM_DSR | TIOCM_DTR : 0)
-			  | ((dlc->v24_sig & RFCOMM_V24_RTR) ? TIOCM_RTS | TIOCM_CTS : 0)
-			  | ((dlc->v24_sig & RFCOMM_V24_IC) ? TIOCM_RI : 0)
-			  | ((dlc->v24_sig & RFCOMM_V24_DV) ? TIOCM_CD : 0);
-
-		return put_user(modeminfo, (unsigned int *)arg);
+		return put_user(dev->modem_status, (unsigned int *)arg);
 
-	case TIOCMBIS:
-		BT_DBG("TIOCMBIS");
-
-		if ((err = get_user(modeminfo, (unsigned int *)arg)))
+	case TIOCMSET: /* Turns on and off the lines as specified by the mask */
+	case TIOCMBIS: /* Turns on the lines as specified by the mask */
+	case TIOCMBIC: /* Turns off the lines as specified by the mask */
+		if ((err = get_user(status, (unsigned int *)arg)))
 			return err;
-
-		dlc->v24_sig |= (modeminfo & TIOCM_DSR) ? RFCOMM_V24_RTC : 0;
-		dlc->v24_sig |= (modeminfo & TIOCM_DTR) ? RFCOMM_V24_RTC : 0;
-		dlc->v24_sig |= (modeminfo & TIOCM_RTS) ? RFCOMM_V24_RTR : 0;
-		dlc->v24_sig |= (modeminfo & TIOCM_CTS) ? RFCOMM_V24_RTR : 0;
-		dlc->v24_sig |= (modeminfo & TIOCM_RI) ? RFCOMM_V24_IC : 0;
-		dlc->v24_sig |= (modeminfo & TIOCM_CD) ? RFCOMM_V24_DV : 0;
-
-		// rfcomm_send_msc(dlc->session, dlc->dlci, 1, dlc->v24_sig);
-
-		return 0;
-
-	case TIOCMBIC:
-	case TIOCMSET:
-		BT_DBG("set modem info");
-		break;
+		return rfcomm_tty_set_modem_status(cmd, dlc, status);
 
 	case TIOCMIWAIT:
 		BT_DBG("TIOCMIWAIT");
diff -Nru a/net/bluetooth/syms.c b/net/bluetooth/syms.c
--- a/net/bluetooth/syms.c	Fri Oct 18 21:03:05 2002
+++ b/net/bluetooth/syms.c	Fri Oct 18 21:03:05 2002
@@ -56,7 +56,6 @@
 EXPORT_SYMBOL(hci_conn_auth);
 EXPORT_SYMBOL(hci_conn_encrypt);
 
-EXPORT_SYMBOL(hci_recv_frame);
 EXPORT_SYMBOL(hci_send_acl);
 EXPORT_SYMBOL(hci_send_sco);
 EXPORT_SYMBOL(hci_send_raw);
diff -Nru a/net/core/dst.c b/net/core/dst.c
--- a/net/core/dst.c	Fri Oct 18 21:03:05 2002
+++ b/net/core/dst.c	Fri Oct 18 21:03:05 2002
@@ -40,7 +40,6 @@
 static struct timer_list dst_gc_timer =
 	{ data: DST_GC_MIN, function: dst_run_gc };
 
-
 static void dst_run_gc(unsigned long dummy)
 {
 	int    delayed = 0;
@@ -60,7 +59,11 @@
 			delayed++;
 			continue;
 		}
-		*dstp = dst->next;
+		if (dst->child) {
+			dst->child->next = dst->next;
+			*dstp = dst->child;
+		} else
+			*dstp = dst->next;
 		dst_destroy(dst);
 	}
 	if (!dst_garbage_list) {
@@ -141,10 +144,16 @@
 	spin_unlock_bh(&dst_lock);
 }
 
-void dst_destroy(struct dst_entry * dst)
+struct dst_entry *dst_destroy(struct dst_entry * dst)
 {
-	struct neighbour *neigh = dst->neighbour;
-	struct hh_cache *hh = dst->hh;
+	struct dst_entry *child;
+	struct neighbour *neigh;
+	struct hh_cache *hh;
+
+again:
+	neigh = dst->neighbour;
+	hh = dst->hh;
+	child = dst->child;
 
 	dst->hh = NULL;
 	if (hh && atomic_dec_and_test(&hh->hh_refcnt))
@@ -165,6 +174,12 @@
 	atomic_dec(&dst_total);
 #endif
 	kmem_cache_free(dst->ops->kmem_cachep, dst);
+
+	dst = child;
+	if (dst && !atomic_read(&dst->__refcnt))
+		goto again;
+
+	return dst;
 }
 
 static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	Fri Oct 18 21:03:07 2002
+++ b/net/core/sock.c	Fri Oct 18 21:03:07 2002
@@ -889,94 +889,6 @@
 }
 
 /*
- *	Generic socket manager library. Most simpler socket families
- *	use this to manage their socket lists. At some point we should
- *	hash these. By making this generic we get the lot hashed for free.
- *
- *	It is broken by design. All the protocols using it must be fixed. --ANK
- */
-
-rwlock_t net_big_sklist_lock = RW_LOCK_UNLOCKED;
- 
-void sklist_remove_socket(struct sock **list, struct sock *sk)
-{
-	struct sock *s;
-
-	write_lock_bh(&net_big_sklist_lock);
-
-	while ((s = *list) != NULL) {
-		if (s == sk) {
-			*list = s->next;
-			break;
-		}
-		list = &s->next;
-	}
-
-	write_unlock_bh(&net_big_sklist_lock);
-	if (s)
-		sock_put(s);
-}
-
-void sklist_insert_socket(struct sock **list, struct sock *sk)
-{
-	write_lock_bh(&net_big_sklist_lock);
-	sk->next= *list;
-	*list=sk;
-	sock_hold(sk);
-	write_unlock_bh(&net_big_sklist_lock);
-}
-
-/*
- *	This is only called from user mode. Thus it protects itself against
- *	interrupt users but doesn't worry about being called during work.
- *	Once it is removed from the queue no interrupt or bottom half will
- *	touch it and we are (fairly 8-) ) safe.
- */
-
-void sklist_destroy_socket(struct sock **list, struct sock *sk);
-
-/*
- *	Handler for deferred kills.
- */
-
-static void sklist_destroy_timer(unsigned long data)
-{
-	struct sock *sk=(struct sock *)data;
-	sklist_destroy_socket(NULL,sk);
-}
-
-/*
- *	Destroy a socket. We pass NULL for a list if we know the
- *	socket is not on a list.
- */
- 
-void sklist_destroy_socket(struct sock **list,struct sock *sk)
-{
-	if(list)
-		sklist_remove_socket(list, sk);
-
-	skb_queue_purge(&sk->receive_queue);
-
-	if(atomic_read(&sk->wmem_alloc) == 0 &&
-	   atomic_read(&sk->rmem_alloc) == 0 &&
-	   sk->dead)
-	{
-		sock_put(sk);
-	}
-	else
-	{
-		/*
-		 *	Someone is using our buffers still.. defer
-		 */
-		init_timer(&sk->timer);
-		sk->timer.expires=jiffies+SOCK_DESTROY_TIME;
-		sk->timer.function=sklist_destroy_timer;
-		sk->timer.data = (unsigned long)sk;
-		add_timer(&sk->timer);
-	}
-}
-
-/*
  * Set of default routines for initialising struct proto_ops when
  * the protocol does not support a particular function. In certain
  * cases where it makes no sense for a protocol to have a "do nothing"
diff -Nru a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
--- a/net/decnet/af_decnet.c	Fri Oct 18 21:03:04 2002
+++ b/net/decnet/af_decnet.c	Fri Oct 18 21:03:04 2002
@@ -37,6 +37,9 @@
  *                          when required.
  *       Patrick Caulfield: /proc/net/decnet now has object name/number
  *        Steve Whitehouse: Fixed local port allocation, hashed sk list
+ *          Matthew Wilcox: Fixes for dn_ioctl()
+ *        Steve Whitehouse: New connect/accept logic to allow timeouts and
+ *                          prepare for sendpage etc.
  */
 
 
@@ -482,7 +485,7 @@
 	if (sock) {
 			sock->ops = &dn_proto_ops;
 	}
-	sock_init_data(sock,sk);
+	sock_init_data(sock, sk);
 
 	sk->backlog_rcv = dn_nsp_backlog_rcv;
 	sk->destruct    = dn_destruct;
@@ -871,95 +874,177 @@
 	return rv;
 }
 
+static int dn_confirm_accept(struct sock *sk, long *timeo, int allocation)
+{
+	struct dn_scp *scp = DN_SK(sk);
+	DECLARE_WAITQUEUE(wait, current);
+	int err;
 
-static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
+	if (scp->state != DN_CR)
+		return -EINVAL;
+
+	scp->state = DN_CC;
+	dn_send_conn_conf(sk, allocation);
+
+	add_wait_queue(sk->sleep, &wait);
+	for(;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		release_sock(sk);
+		if (scp->state == DN_CC)
+			*timeo = schedule_timeout(*timeo);
+		lock_sock(sk);
+		err = 0;
+		if (scp->state == DN_RUN)
+			break;
+		err = sock_error(sk);
+		if (err)
+			break;
+		err = sock_intr_errno(*timeo);
+		if (signal_pending(current))
+			break;
+		err = -EAGAIN;
+		if (!*timeo)
+			break;
+	}
+	remove_wait_queue(sk->sleep, &wait);
+	current->state = TASK_RUNNING;
+	return err;
+}
+
+static int dn_wait_run(struct sock *sk, long *timeo)
 {
-	struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
-	struct sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
-	int err = -EISCONN;
+	DECLARE_WAITQUEUE(wait, current);
+	int err = 0;
 
-	lock_sock(sk);
+	if (scp->state == DN_RUN)
+		goto out;
 
-	if (sock->state == SS_CONNECTED) 
+	if (!*timeo)
+		return -EALREADY;
+
+	add_wait_queue(sk->sleep, &wait);
+	for(;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		release_sock(sk);
+		if (scp->state == DN_CI || scp->state == DN_CC)
+			*timeo = schedule_timeout(*timeo);
+		lock_sock(sk);
+		err = 0;
+		if (scp->state == DN_RUN)
+			break;
+		err = sock_error(sk);
+		if (err)
+			break;
+		err = sock_intr_errno(*timeo);
+		if (signal_pending(current))
+			break;
+		err = -ETIMEDOUT;
+		if (!*timeo)
+			break;
+	}
+	remove_wait_queue(sk->sleep, &wait);
+	current->state = TASK_RUNNING;
+out:
+	if (err == 0) {
+		sk->socket->state = SS_CONNECTED;
+	}
+	return err;
+}
+
+static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen, long *timeo, int flags)
+{
+	struct socket *sock = sk->socket;
+	struct dn_scp *scp = DN_SK(sk);
+	int err = -EISCONN;
+
+	if (sock->state == SS_CONNECTED)
 		goto out;
 
 	if (sock->state == SS_CONNECTING) {
 		err = 0;
-		if (sk->state == TCP_ESTABLISHED)
+		if (scp->state == DN_RUN) {
+			sock->state = SS_CONNECTED;
 			goto out;
-
+		}
 		err = -ECONNREFUSED;
-		if (sk->state == TCP_CLOSE)
+		if (scp->state != DN_CI && scp->state != DN_CC) {
+			sock->state = SS_UNCONNECTED;
 			goto out;
+		}
+		return dn_wait_run(sk, timeo);
 	}
 
 	err = -EINVAL;
-	if (DN_SK(sk)->state != DN_O)
+	if (scp->state != DN_O)
 		goto out;
 
-	if (addr_len != sizeof(struct sockaddr_dn))
+	if (addr == NULL || addrlen != sizeof(struct sockaddr_dn))
 		goto out;
-
 	if (addr->sdn_family != AF_DECnet)
 		goto out;
-
 	if (addr->sdn_flags & SDF_WILD)
 		goto out;
 
-	err = -EADDRNOTAVAIL;
-	if (sk->zapped && (err = dn_auto_bind(sock)))
-		goto out;
+	if (sk->zapped) {
+		err = dn_auto_bind(sk->socket);
+		if (err)
+			goto out;
+	}
 
-	memcpy(&scp->peer, addr, addr_len);
+	memcpy(&scp->peer, addr, sizeof(struct sockaddr_dn));
 
 	err = -EHOSTUNREACH;
-	if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer), dn_saddr2dn(&scp->addr), 0) < 0)
+	if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer),
+			    dn_saddr2dn(&scp->addr), flags & MSG_TRYHARD) < 0)
 		goto out;
 
-	sk->state   = TCP_SYN_SENT;
 	sock->state = SS_CONNECTING;
-	DN_SK(sk)->state = DN_CI;
+	scp->state = DN_CI;
 
 	dn_nsp_send_conninit(sk, NSP_CI);
-
 	err = -EINPROGRESS;
-	if ((sk->state == TCP_SYN_SENT) && (flags & O_NONBLOCK))
-		goto out;
-
-	while(sk->state == TCP_SYN_SENT) {
-
-		err = -ERESTARTSYS;
-		if (signal_pending(current))
-			goto out;
+	if (*timeo) {
+		err = dn_wait_run(sk, timeo);
+	}
+out:
+	return err;
+}
 
-		if ((err = sock_error(sk)) != 0) {
-			sock->state = SS_UNCONNECTED;
-			goto out;
-		}
+static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addrlen, int flags)
+{
+	struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
+	struct sock *sk = sock->sk;
+	int err;
+	long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
 
-		SOCK_SLEEP_PRE(sk);
+	lock_sock(sk);
+	err = __dn_connect(sk, addr, addrlen, &timeo, 0);
+	release_sock(sk);
 
-		if (sk->state == TCP_SYN_SENT)
-			schedule();
+	return err;
+}
 
-		SOCK_SLEEP_POST(sk);
-	}
+static inline int dn_check_state(struct sock *sk, struct sockaddr_dn *addr, int addrlen, long *timeo, int flags)
+{
+	struct dn_scp *scp = DN_SK(sk);
 
-	if (sk->state != TCP_ESTABLISHED) {
-		sock->state = SS_UNCONNECTED;
-		err = sock_error(sk);
-		goto out;
+	switch(scp->state) {
+		case DN_RUN:
+			return 0;
+		case DN_CR:
+			return dn_confirm_accept(sk, timeo, sk->allocation);
+		case DN_CI:
+		case DN_CC:
+			return dn_wait_run(sk, timeo);
+		case DN_O:
+			return __dn_connect(sk, addr, addrlen, timeo, flags);
 	}
 
-	err = 0;
-	sock->state = SS_CONNECTED;
-out:
-	release_sock(sk);
-
-        return err;
+	return -EINVAL;
 }
 
+
 static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
 {
         unsigned char *ptr = skb->data;
@@ -990,42 +1075,39 @@
 
 }
 
-
-/*
- * This is here for use in the sockopt() call as well as
- * in accept(). Must be called with a locked socket.
- */
-static int dn_wait_accept(struct socket *sock, int flags)
+static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo)
 {
-        struct sock *sk = sock->sk;
-
-        while(sk->state == TCP_LISTEN) {
-                if (flags & O_NONBLOCK) {
-                        return -EAGAIN;
-                }
-
-		SOCK_SLEEP_PRE(sk)
-
-		if (sk->state == TCP_LISTEN)
-			schedule();
-
-		SOCK_SLEEP_POST(sk)
-
-                if (signal_pending(current))
-                        return -ERESTARTSYS; /* But of course you don't! */
-        }
-
-        if ((DN_SK(sk)->state != DN_RUN) && (DN_SK(sk)->state != DN_DRC)) {
-                sock->state = SS_UNCONNECTED;
-                return sock_error(sk);
-        }
-
-	sock->state = SS_CONNECTED;
+	DECLARE_WAITQUEUE(wait, current);
+	struct sk_buff *skb = NULL;
+	int err = 0;
 
-        return 0;
+	add_wait_queue_exclusive(sk->sleep, &wait);
+	for(;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		release_sock(sk);
+		skb = skb_dequeue(&sk->receive_queue);
+		if (skb == NULL) {
+			*timeo = schedule_timeout(*timeo);
+			skb = skb_dequeue(&sk->receive_queue);
+		}
+		lock_sock(sk);
+		if (skb != NULL)
+			break;
+		err = -EINVAL;
+		if (sk->state != TCP_LISTEN)
+			break;
+		err = sock_intr_errno(*timeo);
+		if (signal_pending(current))
+			break;
+		err = -EAGAIN;
+		if (!*timeo)
+			break;
+	}
+	remove_wait_queue(sk->sleep, &wait);
+	current->state = TASK_RUNNING;
+	return skb == NULL ? ERR_PTR(err) : skb;
 }
 
-
 static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	struct sock *sk = sock->sk, *newsk;
@@ -1034,52 +1116,32 @@
 	unsigned char menuver;
 	int err = 0;
 	unsigned char type;
+	long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
 	lock_sock(sk);
 
-        if (sk->state != TCP_LISTEN) {
+        if (sk->state != TCP_LISTEN || DN_SK(sk)->state != DN_O) {
 		release_sock(sk);
 		return -EINVAL;
 	}
 
-	if (DN_SK(sk)->state != DN_O) {
-		release_sock(sk);
-		return -EINVAL;
+	skb = skb_dequeue(&sk->receive_queue);
+	if (skb == NULL) {
+		skb = dn_wait_for_connect(sk, &timeo);
+		if (IS_ERR(skb)) {
+			release_sock(sk);
+			return PTR_ERR(sk);
+		}
 	}
 
-        do
-        {
-                if ((skb = skb_dequeue(&sk->receive_queue)) == NULL)
-                {
-                        if (flags & O_NONBLOCK)
-                        {
-                                release_sock(sk);
-                                return -EAGAIN;
-                        }
-
-			SOCK_SLEEP_PRE(sk);
-
-			if (!skb_peek(&sk->receive_queue))
-				schedule();
-
-			SOCK_SLEEP_POST(sk);
-
-                        if (signal_pending(current))
-                        {
-				release_sock(sk);
-                                return -ERESTARTSYS;
-                        }
-                }
-        } while (skb == NULL);
-
 	cb = DN_SKB_CB(skb);
-
-	if ((newsk = dn_alloc_sock(newsock, sk->allocation)) == NULL) {
+	sk->ack_backlog--;
+	newsk = dn_alloc_sock(newsock, sk->allocation);
+	if (newsk == NULL) {
 		release_sock(sk);
 		kfree_skb(skb);
 		return -ENOBUFS;
 	}
-	sk->ack_backlog--;
 	release_sock(sk);
 
 	dst_release(xchg(&newsk->dst_cache, skb->dst));
@@ -1099,8 +1161,6 @@
 		DN_SK(newsk)->max_window = decnet_no_fc_max_cwnd;
 
 	newsk->state  = TCP_LISTEN;
-	newsk->zapped = 0;
-
 	memcpy(&(DN_SK(newsk)->addr), &(DN_SK(sk)->addr), sizeof(struct sockaddr_dn));
 
 	/*
@@ -1137,23 +1197,18 @@
 		sizeof(struct optdata_dn));
 
 	lock_sock(newsk);
-	/*
-	 * FIXME: This can fail if we've run out of local ports....
-	 */
-	dn_hash_sock(newsk);
-
-	dn_send_conn_ack(newsk);
+	err = dn_hash_sock(newsk);
+	if (err == 0) {
+		newsk->zapped = 0;
+		dn_send_conn_ack(newsk);
 
-	/*
-	 * Here we use sk->allocation since although the conn conf is
-	 * for the newsk, the context is the old socket.
-	 */
-	if (DN_SK(newsk)->accept_mode == ACC_IMMED) {
-		DN_SK(newsk)->state = DN_CC;
-        	dn_send_conn_conf(newsk, sk->allocation);
-		err = dn_wait_accept(newsock, flags);
+		/*
+	 	 * Here we use sk->allocation since although the conn conf is
+	 	 * for the newsk, the context is the old socket.
+	 	 */
+		if (DN_SK(newsk)->accept_mode == ACC_IMMED)
+			err = dn_confirm_accept(newsk, &timeo, sk->allocation);
 	}
-
 	release_sock(newsk);
         return err;
 }
@@ -1227,30 +1282,6 @@
 		return dn_fib_ioctl(sock, cmd, arg);
 #endif /* CONFIG_DECNET_ROUTER */
 
-#if 0
-	case OSIOCSNETADDR:
-		if (!capable(CAP_NET_ADMIN)) {
-			err = -EPERM;
-			break;
-		}
-
-		dn_dev_devices_off();
-
-		decnet_address = (unsigned short)arg;
-
-		dn_dev_devices_on();
-		err = 0;
-		break;
-
-	case OSIOCGNETADDR:
-		err = put_user(decnet_address, (unsigned short *)arg);
-		break;
-#endif
-        case SIOCGIFCONF:
-        case SIOCGIFFLAGS:
-        case SIOCGIFBRDADDR:
-                return dev_ioctl(cmd,(void *)arg);
-
 	case TIOCOUTQ:
 		amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
 		if (amount < 0)
@@ -1274,6 +1305,10 @@
 		release_sock(sk);
 		err = put_user(amount, (int *)arg);
 		break;
+
+	default:
+		err = dev_ioctl(cmd, (void *)arg);
+		break;
 	}
 
 	return err;
@@ -1327,7 +1362,6 @@
 	if (how != SHUTDOWN_MASK)
 		goto out;
 
-
 	sk->shutdown = how;
 	dn_destroy_sock(sk);
 	err = 0;
@@ -1354,6 +1388,7 @@
 {
 	struct	sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
+	long timeo;
 	union {
 		struct optdata_dn opt;
 		struct accessdata_dn acc;
@@ -1439,10 +1474,8 @@
 
 			if (scp->state != DN_CR)
 				return -EINVAL;
-
-			scp->state = DN_CC;
-			dn_send_conn_conf(sk, sk->allocation);
-			err = dn_wait_accept(sock, sock->file->f_flags);
+			timeo = sock_rcvtimeo(sk, 0);
+			err = dn_confirm_accept(sk, &timeo, sk->allocation);
 			return err;
 
 		case DSO_CONREJECT:
@@ -1652,55 +1685,6 @@
 }
 
 
-/*
- * Used by send/recvmsg to wait until the socket is connected
- * before passing data.
- */
-static int dn_wait_run(struct sock *sk, int flags)
-{
-	struct dn_scp *scp = DN_SK(sk);
-	int err = 0;
-
-	switch(scp->state) {
-		case DN_RUN:
-			return 0;
-
-		case DN_CR:
-			scp->state = DN_CC;
-			dn_send_conn_conf(sk, sk->allocation);
-			return dn_wait_accept(sk->socket, (flags & MSG_DONTWAIT) ? O_NONBLOCK : 0);
-		case DN_CI:
-		case DN_CC:
-			break;
-		default:
-			return -ENOTCONN;
-	}
-
-	if (flags & MSG_DONTWAIT)
-		return -EWOULDBLOCK;
-
-	do {
-		if ((err = sock_error(sk)) != 0)
-			break;
-
-		if (signal_pending(current)) {
-			err = -ERESTARTSYS;
-			break;
-		}
-
-		SOCK_SLEEP_PRE(sk)
-
-		if (scp->state != DN_RUN)
-			schedule();
-
-		SOCK_SLEEP_POST(sk)
-
-	} while(scp->state != DN_RUN);
-
-	return 0;
-}
-
-
 static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int target)
 {
 	struct sk_buff *skb = q->next;
@@ -1745,6 +1729,7 @@
 	struct sk_buff *skb, *nskb;
 	struct dn_skb_cb *cb = NULL;
 	unsigned char eor = 0;
+	long timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 
 	lock_sock(sk);
 
@@ -1753,16 +1738,18 @@
 		goto out;
 	}
 
-	if ((rv = dn_wait_run(sk, flags)) != 0)
+	rv = dn_check_state(sk, NULL, 0, &timeo, flags);
+	if (rv)
 		goto out;
 
 	if (sk->shutdown & RCV_SHUTDOWN) {
-		send_sig(SIGPIPE, current, 0);
+		if (!(flags & MSG_NOSIGNAL))
+			send_sig(SIGPIPE, current, 0);
 		rv = -EPIPE;
 		goto out;
 	}
 
-	if (flags & ~(MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT)) {
+	if (flags & ~(MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT|MSG_NOSIGNAL)) {
 		rv = -EOPNOTSUPP;
 		goto out;
 	}
@@ -1920,35 +1907,23 @@
 	unsigned short ack;
 	int len;
 	unsigned char fctype;
+	long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
 
-	if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR))
+	if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL))
 		return -EOPNOTSUPP;
 
 	if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
 		return -EINVAL;
 
-	if (sk->zapped && dn_auto_bind(sock))  {
-		err = -EADDRNOTAVAIL;
-		goto out;
-	}
-
-	if (scp->state == DN_O) {
-		if (!addr_len || !addr) {
-			err = -ENOTCONN;
-			goto out;
-		}
-
-		if ((err = dn_connect(sock, (struct sockaddr *)addr, addr_len, (flags & MSG_DONTWAIT) ? O_NONBLOCK : 0)) < 0)
-			goto out;
-	}
-
 	lock_sock(sk);
 
-	if ((err = dn_wait_run(sk, flags)) < 0)
+	err = dn_check_state(sk, addr, addr_len, &timeo, flags);
+	if (err)
 		goto out;
 
 	if (sk->shutdown & SEND_SHUTDOWN) {
-		send_sig(SIGPIPE, current, 0);
+		if (!(flags & MSG_NOSIGNAL))
+			send_sig(SIGPIPE, current, 0);
 		err = -EPIPE;
 		goto out;
 	}
@@ -2117,7 +2092,7 @@
 }
 
 static struct notifier_block dn_dev_notifier = {
-	.notifier_call =dn_device_event,
+	.notifier_call = dn_device_event,
 };
 
 extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
diff -Nru a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
--- a/net/decnet/dn_dev.c	Fri Oct 18 21:03:04 2002
+++ b/net/decnet/dn_dev.c	Fri Oct 18 21:03:04 2002
@@ -181,30 +181,74 @@
 } dn_dev_sysctl = {
 	NULL,
 	{
-	{NET_DECNET_CONF_DEV_FORWARDING, "forwarding",
-	(void *)DN_DEV_PARMS_OFFSET(forwarding),
-	sizeof(int), 0644, NULL,
-	dn_forwarding_proc, dn_forwarding_sysctl,
-	NULL, NULL, NULL},
-	{NET_DECNET_CONF_DEV_PRIORITY, "priority",
-	(void *)DN_DEV_PARMS_OFFSET(priority),
-	sizeof(int), 0644, NULL,
-	proc_dointvec_minmax, sysctl_intvec,
-	NULL, &min_priority, &max_priority},
-	{NET_DECNET_CONF_DEV_T2, "t2", (void *)DN_DEV_PARMS_OFFSET(t2),
-	sizeof(int), 0644, NULL,
-	proc_dointvec_minmax, sysctl_intvec,
-	NULL, &min_t2, &max_t2},
-	{NET_DECNET_CONF_DEV_T3, "t3", (void *)DN_DEV_PARMS_OFFSET(t3),
-	sizeof(int), 0644, NULL,
-	proc_dointvec_minmax, sysctl_intvec,
-	NULL, &min_t3, &max_t3},
+	{
+		.ctl_name = NET_DECNET_CONF_DEV_FORWARDING,
+		.procname = "forwarding",
+		.data = (void *)DN_DEV_PARMS_OFFSET(forwarding),
+		.maxlen = sizeof(int),
+		.mode = 0644,
+		.proc_handler = dn_forwarding_proc,
+		.strategy = dn_forwarding_sysctl,
+	},
+	{
+		.ctl_name = NET_DECNET_CONF_DEV_PRIORITY,
+		.procname = "priority",
+		.data = (void *)DN_DEV_PARMS_OFFSET(priority),
+		.maxlen = sizeof(int),
+		.mode = 0644,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
+		.extra1 = &min_priority,
+		.extra2 = &max_priority
+	},
+	{
+		.ctl_name = NET_DECNET_CONF_DEV_T2,
+		.procname = "t2",
+		.data = (void *)DN_DEV_PARMS_OFFSET(t2),
+		.maxlen = sizeof(int),
+		.mode = 0644,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
+		.extra1 = &min_t2,
+		.extra2 = &max_t2
+	},
+	{
+		.ctl_name = NET_DECNET_CONF_DEV_T3,
+		.procname = "t3",
+		.data = (void *)DN_DEV_PARMS_OFFSET(t3),
+		.maxlen = sizeof(int),
+		.mode = 0644,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
+		.extra1 = &min_t3,
+		.extra2 = &max_t3
+	},
 	{0}
 	},
-	{{0, "", NULL, 0, 0555, dn_dev_sysctl.dn_dev_vars}, {0}},
-	{{NET_DECNET_CONF, "conf", NULL, 0, 0555, dn_dev_sysctl.dn_dev_dev}, {0}},
-	{{NET_DECNET, "decnet", NULL, 0, 0555, dn_dev_sysctl.dn_dev_conf_dir}, {0}},
-	{{CTL_NET, "net", NULL, 0, 0555, dn_dev_sysctl.dn_dev_proto_dir}, {0}}
+	{{
+		.ctl_name = 0, 
+		.procname = "", 
+		.mode = 0555, 
+		.child = dn_dev_sysctl.dn_dev_vars
+	}, {0}},
+	{{
+		.ctl_name = NET_DECNET_CONF,
+		.procname = "conf", 
+		.mode = 0555, 
+		.child = dn_dev_sysctl.dn_dev_dev
+	}, {0}},
+	{{
+		.ctl_name = NET_DECNET, 
+		.procname = "decnet", 
+		.mode = 0555, 
+		.child = dn_dev_sysctl.dn_dev_conf_dir
+	}, {0}},
+	{{
+		.ctl_name = CTL_NET, 
+		.procname = "net", 
+		.mode = 0555, 
+		.child = dn_dev_sysctl.dn_dev_proto_dir
+	}, {0}}
 };
 
 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
@@ -1211,8 +1255,10 @@
 {
 	struct net_device *dev;
 
+	rtnl_lock();
 	for(dev = dev_base; dev; dev = dev->next)
 		dn_dev_down(dev);
+	rtnl_unlock();
 
 }
 
@@ -1220,10 +1266,12 @@
 {
 	struct net_device *dev;
 
+	rtnl_lock();
 	for(dev = dev_base; dev; dev = dev->next) {
 		if (dev->flags & IFF_UP)
 			dn_dev_up(dev);
 	}
+	rtnl_unlock();
 }
 
 
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	Fri Oct 18 21:03:04 2002
+++ b/net/econet/af_econet.c	Fri Oct 18 21:03:04 2002
@@ -46,6 +46,7 @@
 
 static struct proto_ops econet_ops;
 static struct sock *econet_sklist;
+static rwlock_t econet_lock = RW_LOCK_UNLOCKED;
 
 /* Since there are only 256 possible network numbers (or fewer, depends
    how you count) it makes sense to use a simple lookup table. */
@@ -92,6 +93,33 @@
 #endif
 };
 
+static void econet_remove_socket(struct sock **list, struct sock *sk)
+{
+	struct sock *s;
+
+	write_lock_bh(&econet_lock);
+
+	while ((s = *list) != NULL) {
+		if (s == sk) {
+			*list = s->next;
+			break;
+		}
+		list = &s->next;
+	}
+
+	write_unlock_bh(&econet_lock);
+	if (s)
+		sock_put(s);
+}
+
+static void econet_insert_socket(struct sock **list, struct sock *sk)
+{
+	write_lock_bh(&econet_lock);
+	sk->next = *list;
+	sock_hold(sk);
+	write_unlock_bh(&econet_lock);
+}
+
 /*
  *	Pull a packet from our receive queue and hand it to the user.
  *	If necessary we block.
@@ -494,7 +522,7 @@
 	if (!sk)
 		return 0;
 
-	sklist_remove_socket(&econet_sklist, sk);
+	econet_remove_socket(&econet_sklist, sk);
 
 	/*
 	 *	Now the socket is dead. No more input will appear.
@@ -557,7 +585,7 @@
 	sk->family = PF_ECONET;
 	eo->num = protocol;
 
-	sklist_insert_socket(&econet_sklist, sk);
+	econet_insert_socket(&econet_sklist, sk);
 	return(0);
 
 out_free:
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Fri Oct 18 21:03:03 2002
+++ b/net/ipv4/af_inet.c	Fri Oct 18 21:03:03 2002
@@ -774,6 +774,21 @@
 	return sk->prot->sendmsg(iocb, sk, msg, size);
 }
 
+
+ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+
+	/* We may need to bind the socket. */
+	if (!inet_sk(sk)->num && inet_autobind(sk))
+		return -EAGAIN;
+
+	if (sk->prot->sendpage)
+		return sk->prot->sendpage(sk, page, offset, size, flags);
+	return sock_no_sendpage(sock, page, offset, size, flags);
+}
+
+
 int inet_shutdown(struct socket *sock, int how)
 {
 	struct sock *sk = sock->sk;
@@ -977,7 +992,7 @@
 	.sendmsg =	inet_sendmsg,
 	.recvmsg =	inet_recvmsg,
 	.mmap =		sock_no_mmap,
-	.sendpage =	sock_no_sendpage,
+	.sendpage =	inet_sendpage,
 };
 
 struct net_proto_family inet_family_ops = {
diff -Nru a/net/ipv4/icmp.c b/net/ipv4/icmp.c
--- a/net/ipv4/icmp.c	Fri Oct 18 21:03:08 2002
+++ b/net/ipv4/icmp.c	Fri Oct 18 21:03:08 2002
@@ -101,7 +101,6 @@
 	int offset;
 	int data_len;
 
-	unsigned int csum;
 	struct {
 		struct icmphdr icmph;
 		__u32	       times[3];
@@ -356,39 +355,47 @@
  *	Checksum each fragment, and on the first include the headers and final
  *	checksum.
  */
-static int icmp_glue_bits(const void *p, char *to, unsigned int offset,
-			  unsigned int fraglen)
+int
+icmp_glue_bits(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
 {
-	struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
-	struct icmphdr *icmph;
+	struct icmp_bxm *icmp_param = (struct icmp_bxm *)from;
 	unsigned int csum;
 
-	if (offset) {
-		icmp_param->csum =
-			skb_copy_and_csum_bits(icmp_param->skb,
-					       icmp_param->offset +
-					       (offset - icmp_param->head_len),
-						to, fraglen, icmp_param->csum);
-		goto out;
-	}
+	csum = skb_copy_and_csum_bits(icmp_param->skb,
+				      icmp_param->offset + offset,
+				      to, len, 0);
 
-	/*
-	 *	First fragment includes header. Note that we've done
-	 *	the other fragments first, so that we get the checksum
-	 *	for the whole packet here.
-	 */
-	csum = csum_partial_copy_nocheck((void *)&icmp_param->data,
-					 to, icmp_param->head_len,
-					 icmp_param->csum);
-	csum = skb_copy_and_csum_bits(icmp_param->skb, icmp_param->offset,
-				      to + icmp_param->head_len,
-				      fraglen - icmp_param->head_len, csum);
-	icmph = (struct icmphdr *)to;
-	icmph->checksum = csum_fold(csum);
-out:
+	skb->csum = csum_block_add(skb->csum, csum, odd);
 	return 0;
 }
 
+static void
+icmp_push_reply(struct icmp_bxm *icmp_param, struct ipcm_cookie *ipc, struct rtable *rt)
+{
+	struct sk_buff *skb;
+
+	ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
+		       icmp_param->data_len+icmp_param->head_len,
+		       icmp_param->head_len,
+		       ipc, rt, MSG_DONTWAIT);
+
+	if ((skb = skb_peek(&icmp_socket->sk->write_queue)) != NULL) {
+		struct icmphdr *icmph = skb->h.icmph;
+		unsigned int csum = 0;
+		struct sk_buff *skb1;
+
+		skb_queue_walk(&icmp_socket->sk->write_queue, skb1) {
+			csum = csum_add(csum, skb1->csum);
+		}
+		csum = csum_partial_copy_nocheck((void *)&icmp_param->data,
+						 (char*)icmph, icmp_param->head_len,	
+						 csum);
+		icmph->checksum = csum_fold(csum);
+		skb->ip_summed = CHECKSUM_NONE;
+		ip_push_pending_frames(icmp_socket->sk);
+	}
+}
+
 /*
  *	Driving logic for building and sending ICMP messages.
  */
@@ -406,7 +413,6 @@
 		goto out;
 
 	icmp_param->data.icmph.checksum = 0;
-	icmp_param->csum = 0;
 	icmp_out_count(icmp_param->data.icmph.type);
 
 	inet->tos = skb->nh.iph->tos;
@@ -427,11 +433,8 @@
 			goto out_unlock;
 	}
 	if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
-			       icmp_param->data.icmph.code)) {
-		ip_build_xmit(sk, icmp_glue_bits, icmp_param,
-			      icmp_param->data_len+icmp_param->head_len,
-			      &ipc, rt, MSG_DONTWAIT);
-	}
+			       icmp_param->data.icmph.code))
+		icmp_push_reply(icmp_param, &ipc, rt);
 	ip_rt_put(rt);
 out_unlock:
 	icmp_xmit_unlock_bh();
@@ -563,7 +566,6 @@
 	icmp_param.data.icmph.code	 = code;
 	icmp_param.data.icmph.un.gateway = info;
 	icmp_param.data.icmph.checksum	 = 0;
-	icmp_param.csum	  = 0;
 	icmp_param.skb	  = skb_in;
 	icmp_param.offset = skb_in->nh.raw - skb_in->data;
 	icmp_out_count(icmp_param.data.icmph.type);
@@ -597,9 +599,7 @@
 		icmp_param.data_len = room;
 	icmp_param.head_len = sizeof(struct icmphdr);
 
-	ip_build_xmit(icmp_socket->sk, icmp_glue_bits, &icmp_param,
-		      icmp_param.data_len + sizeof(struct icmphdr),
-		      &ipc, rt, MSG_DONTWAIT);
+	icmp_push_reply(&icmp_param, &ipc, rt);
 ende:
 	ip_rt_put(rt);
 out_unlock:
diff -Nru a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
--- a/net/ipv4/ip_forward.c	Fri Oct 18 21:03:03 2002
+++ b/net/ipv4/ip_forward.c	Fri Oct 18 21:03:03 2002
@@ -53,7 +53,7 @@
 
 		if (rt->rt_flags&RTCF_FAST && !netdev_fastroute_obstacles) {
 			struct dst_entry *old_dst;
-			unsigned h = ((*(u8*)&rt->key.dst)^(*(u8*)&rt->key.src))&NETDEV_FASTROUTE_HMASK;
+			unsigned h = ((*(u8*)&rt->fl.fl4_dst)^(*(u8*)&rt->fl.fl4_src))&NETDEV_FASTROUTE_HMASK;
 
 			write_lock_irq(&skb->dev->fastpath_lock);
 			old_dst = skb->dev->fastpath[h];
diff -Nru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
--- a/net/ipv4/ip_output.c	Fri Oct 18 21:03:08 2002
+++ b/net/ipv4/ip_output.c	Fri Oct 18 21:03:08 2002
@@ -15,6 +15,7 @@
  *		Stefan Becker, <stefanb@yello.ping.de>
  *		Jorge Cwik, <jorge@laser.satlink.net>
  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Hirokazu Takahashi, <taka@valinux.co.jp>
  *
  *	See ip_input.c for original log
  *
@@ -38,6 +39,9 @@
  *		Marc Boucher	:	When call_out_firewall returns FW_QUEUE,
  *					silently drop skb instead of failing with -EPERM.
  *		Detlev Wengorz	:	Copy protocol for fragments.
+ *		Hirokazu Takahashi:	HW checksumming for outgoing UDP
+ *					datagrams.
+ *		Hirokazu Takahashi:	sendfile() on UDP works now.
  */
 
 #include <asm/uaccess.h>
@@ -108,16 +112,9 @@
 	return 0;
 }
 
-/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook
-   changes route */
-static inline int
-output_maybe_reroute(struct sk_buff *skb)
-{
-	return skb->dst->output(skb);
-}
-
 /* 
  *		Add an ip header to a skbuff and send it out.
+ *
  */
 int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
 			  u32 saddr, u32 daddr, struct ip_options *opt)
@@ -153,15 +150,34 @@
 	}
 	ip_send_check(iph);
 
+	skb->priority = sk->priority;
+
 	/* Send it out. */
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		       output_maybe_reroute);
+		       dst_output);
 }
 
 static inline int ip_finish_output2(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
 	struct hh_cache *hh = dst->hh;
+	struct net_device *dev = dst->dev;
+
+	/* Be paranoid, rather than too clever. */
+	if (unlikely(skb_headroom(skb) < dev->hard_header_len
+		     && dev->hard_header)) {
+		struct sk_buff *skb2;
+
+		skb2 = skb_realloc_headroom(skb, (dev->hard_header_len&~15) + 16);
+		if (skb2 == NULL) {
+			kfree_skb(skb);
+			return -ENOMEM;
+		}
+		if (skb->sk)
+			skb_set_owner_w(skb2, skb->sk);
+		kfree_skb(skb);
+		skb = skb2;
+	}
 
 #ifdef CONFIG_NETFILTER_DEBUG
 	nf_debug_ip_finish_output2(skb);
@@ -203,10 +219,6 @@
 	 *	If the indicated interface is up and running, send the packet.
 	 */
 	IP_INC_STATS(IpOutRequests);
-#ifdef CONFIG_IP_ROUTE_NAT
-	if (rt->rt_flags & RTCF_NAT)
-		ip_do_nat(skb);
-#endif
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
@@ -251,100 +263,21 @@
 				newskb->dev, ip_dev_loopback_xmit);
 	}
 
-	return ip_finish_output(skb);
+	if (skb->len > dev->mtu || skb_shinfo(skb)->frag_list)
+		return ip_fragment(skb, ip_finish_output);
+	else
+		return ip_finish_output(skb);
 }
 
 int ip_output(struct sk_buff *skb)
 {
-#ifdef CONFIG_IP_ROUTE_NAT
-	struct rtable *rt = (struct rtable*)skb->dst;
-#endif
-
 	IP_INC_STATS(IpOutRequests);
 
-#ifdef CONFIG_IP_ROUTE_NAT
-	if (rt->rt_flags&RTCF_NAT)
-		ip_do_nat(skb);
-#endif
-
-	return ip_finish_output(skb);
-}
-
-/* Queues a packet to be sent, and starts the transmitter if necessary.  
- * This routine also needs to put in the total length and compute the 
- * checksum.  We use to do this in two stages, ip_build_header() then
- * this, but that scheme created a mess when routes disappeared etc.
- * So we do it all here, and the TCP send engine has been changed to
- * match. (No more unroutable FIN disasters, etc. wheee...)  This will
- * most likely make other reliable transport layers above IP easier
- * to implement under Linux.
- */
-static inline int ip_queue_xmit2(struct sk_buff *skb)
-{
-	struct sock *sk = skb->sk;
-	struct rtable *rt = (struct rtable *)skb->dst;
-	struct net_device *dev;
-	struct iphdr *iph = skb->nh.iph;
-
-	dev = rt->u.dst.dev;
-
-	/* This can happen when the transport layer has segments queued
-	 * with a cached route, and by the time we get here things are
-	 * re-routed to a device with a different MTU than the original
-	 * device.  Sick, but we must cover it.
-	 */
-	if (skb_headroom(skb) < dev->hard_header_len && dev->hard_header) {
-		struct sk_buff *skb2;
-
-		skb2 = skb_realloc_headroom(skb, (dev->hard_header_len + 15) & ~15);
-		kfree_skb(skb);
-		if (skb2 == NULL)
-			return -ENOMEM;
-		if (sk)
-			skb_set_owner_w(skb2, sk);
-		skb = skb2;
-		iph = skb->nh.iph;
-	}
-
-	if (skb->len > rt->u.dst.pmtu) {
-		unsigned int hlen;
-		if (!(sk->route_caps&NETIF_F_TSO))
-			goto fragment;
-
-		/* Hack zone: all this must be done by TCP. */
-		hlen = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-		skb_shinfo(skb)->tso_size = rt->u.dst.pmtu - hlen;
-		skb_shinfo(skb)->tso_segs =
-			(skb->len - hlen + skb_shinfo(skb)->tso_size - 1)/
-				skb_shinfo(skb)->tso_size - 1;
-	}
-
-	ip_select_ident_more(iph, &rt->u.dst, sk, skb_shinfo(skb)->tso_segs);
-
-	/* Add an IP checksum. */
-	ip_send_check(iph);
-
-	skb->priority = sk->priority;
-	return skb->dst->output(skb);
-
-fragment:
-	if (ip_dont_fragment(sk, &rt->u.dst)) {
-		/* Reject packet ONLY if TCP might fragment
-		 * it itself, if were careful enough.
-		 */
-		NETDEBUG(printk(KERN_DEBUG "sending pkt_too_big (len[%u] pmtu[%u]) to self\n",
-				skb->len, rt->u.dst.pmtu));
-
-		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-			  htonl(rt->u.dst.pmtu));
-		kfree_skb(skb);
-		return -EMSGSIZE;
-	}
-	ip_select_ident(iph, &rt->u.dst, sk);
-	if (skb->ip_summed == CHECKSUM_HW &&
-	    (skb = skb_checksum_help(skb)) == NULL)
-		return -ENOMEM;
-	return ip_fragment(skb, skb->dst->output);
+	if ((skb->len > skb->dst->dev->mtu || skb_shinfo(skb)->frag_list) &&
+	    !skb_shinfo(skb)->tso_size)
+		return ip_fragment(skb, ip_finish_output);
+	else
+		return ip_finish_output(skb);
 }
 
 int ip_queue_xmit(struct sk_buff *skb)
@@ -415,348 +348,58 @@
 		ip_options_build(skb, opt, inet->daddr, rt, 0);
 	}
 
-	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		       ip_queue_xmit2);
-
-no_route:
-	IP_INC_STATS(IpOutNoRoutes);
-	kfree_skb(skb);
-	return -EHOSTUNREACH;
-}
-
-/*
- *	Build and send a packet, with as little as one copy
- *
- *	Doesn't care much about ip options... option length can be
- *	different for fragment at 0 and other fragments.
- *
- *	Note that the fragment at the highest offset is sent first,
- *	so the getfrag routine can fill in the TCP/UDP checksum header
- *	field in the last fragment it sends... actually it also helps
- * 	the reassemblers, they can put most packets in at the head of
- *	the fragment queue, and they know the total size in advance. This
- *	last feature will measurably improve the Linux fragment handler one
- *	day.
- *
- *	The callback has five args, an arbitrary pointer (copy of frag),
- *	the source IP address (may depend on the routing table), the 
- *	destination address (char *), the offset to copy from, and the
- *	length to be copied.
- */
-
-static int ip_build_xmit_slow(struct sock *sk,
-		  int getfrag (const void *,
-			       char *,
-			       unsigned int,	
-			       unsigned int),
-		  const void *frag,
-		  unsigned length,
-		  struct ipcm_cookie *ipc,
-		  struct rtable *rt,
-		  int flags)
-{
-	struct inet_opt *inet = inet_sk(sk);
-	unsigned int fraglen, maxfraglen, fragheaderlen;
-	int err;
-	int offset, mf;
-	int mtu;
-	u16 id;
-
-	int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
-	int nfrags=0;
-	struct ip_options *opt = ipc->opt;
-	int df = 0;
-
-	mtu = rt->u.dst.pmtu;
-	if (ip_dont_fragment(sk, &rt->u.dst))
-		df = htons(IP_DF);
-
-	length -= sizeof(struct iphdr);
-
-	if (opt) {
-		fragheaderlen = sizeof(struct iphdr) + opt->optlen;
-		maxfraglen = ((mtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen;
-	} else {
-		fragheaderlen = sizeof(struct iphdr);
-
-		/*
-		 *	Fragheaderlen is the size of 'overhead' on each buffer. Now work
-		 *	out the size of the frames to send.
-		 */
-
-		maxfraglen = ((mtu-sizeof(struct iphdr)) & ~7) + fragheaderlen;
-	}
-
-	if (length + fragheaderlen > 0xFFFF) {
-		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu);
-		return -EMSGSIZE;
-	}
-
-	/*
-	 *	Start at the end of the frame by handling the remainder.
-	 */
-
-	offset = length - (length % (maxfraglen - fragheaderlen));
-
-	/*
-	 *	Amount of memory to allocate for final fragment.
-	 */
-
-	fraglen = length - offset + fragheaderlen;
-
-	if (length-offset==0) {
-		fraglen = maxfraglen;
-		offset -= maxfraglen-fragheaderlen;
-	}
-
-	/*
-	 *	The last fragment will not have MF (more fragments) set.
-	 */
-
-	mf = 0;
-
-	/*
-	 *	Don't fragment packets for path mtu discovery.
-	 */
+	if (skb->len > rt->u.dst.pmtu && (sk->route_caps&NETIF_F_TSO)) {
+		unsigned int hlen;
 
-	if (offset > 0 && inet->pmtudisc == IP_PMTUDISC_DO) { 
-		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu);
- 		return -EMSGSIZE;
+		/* Hack zone: all this must be done by TCP. */
+		hlen = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+		skb_shinfo(skb)->tso_size = rt->u.dst.pmtu - hlen;
+		skb_shinfo(skb)->tso_segs =
+			(skb->len - hlen + skb_shinfo(skb)->tso_size - 1)/
+				skb_shinfo(skb)->tso_size - 1;
 	}
-	if (flags&MSG_PROBE)
-		goto out;
-
-	/*
-	 *	Begin outputting the bytes.
-	 */
-
-	id = inet->id++;
-
-	do {
-		char *data;
-		struct sk_buff * skb;
-
-		/*
-		 *	Get the memory we require with some space left for alignment.
-		 */
-		if (!(flags & MSG_DONTWAIT) || nfrags == 0) {
-			skb = sock_alloc_send_skb(sk, fraglen + hh_len + 15,
-						  (flags & MSG_DONTWAIT), &err);
-		} else {
-			/* On a non-blocking write, we check for send buffer
-			 * usage on the first fragment only.
-			 */
-			skb = sock_wmalloc(sk, fraglen + hh_len + 15, 1,
-					   sk->allocation);
-			if (!skb)
-				err = -ENOBUFS;
-		}
-		if (skb == NULL)
-			goto error;
-
-		/*
-		 *	Fill in the control structures
-		 */
-
-		skb->priority = sk->priority;
-		skb->dst = dst_clone(&rt->u.dst);
-		skb_reserve(skb, hh_len);
-
-		/*
-		 *	Find where to start putting bytes.
-		 */
 
-		data = skb_put(skb, fraglen);
-		skb->nh.iph = (struct iphdr *)data;
-
-		/*
-		 *	Only write IP header onto non-raw packets 
-		 */
-
-		{
-			struct iphdr *iph = (struct iphdr *)data;
-
-			iph->version = 4;
-			iph->ihl = 5;
-			if (opt) {
-				iph->ihl += opt->optlen>>2;
-				ip_options_build(skb, opt,
-						 ipc->addr, rt, offset);
-			}
-			iph->tos = inet->tos;
-			iph->tot_len = htons(fraglen - fragheaderlen + iph->ihl*4);
-			iph->frag_off = htons(offset>>3)|mf|df;
-			iph->id = id;
-			if (!mf) {
-				if (offset || !df) {
-					/* Select an unpredictable ident only
-					 * for packets without DF or having
-					 * been fragmented.
-					 */
-					__ip_select_ident(iph, &rt->u.dst, 0);
-					id = iph->id;
-				}
-
-				/*
-				 *	Any further fragments will have MF set.
-				 */
-				mf = htons(IP_MF);
-			}
-			if (rt->rt_type == RTN_MULTICAST)
-				iph->ttl = inet->mc_ttl;
-			else
-				iph->ttl = inet->ttl;
-			iph->protocol = sk->protocol;
-			iph->check = 0;
-			iph->saddr = rt->rt_src;
-			iph->daddr = rt->rt_dst;
-			iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-			data += iph->ihl*4;
-		}
-
-		/*
-		 *	User data callback
-		 */
-
-		if (getfrag(frag, data, offset, fraglen-fragheaderlen)) {
-			err = -EFAULT;
-			kfree_skb(skb);
-			goto error;
-		}
-
-		offset -= (maxfraglen-fragheaderlen);
-		fraglen = maxfraglen;
+	ip_select_ident_more(iph, &rt->u.dst, sk, skb_shinfo(skb)->tso_segs);
 
-		nfrags++;
+	/* Add an IP checksum. */
+	ip_send_check(iph);
 
-		err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
-			      skb->dst->dev, output_maybe_reroute);
-		if (err) {
-			if (err > 0)
-				err = inet->recverr ? net_xmit_errno(err) : 0;
-			if (err)
-				goto error;
-		}
-	} while (offset >= 0);
+	skb->priority = sk->priority;
 
-	if (nfrags>1)
-		ip_statistics[smp_processor_id()*2 + !in_softirq()].IpFragCreates += nfrags;
-out:
-	return 0;
+	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+		       dst_output);
 
-error:
-	IP_INC_STATS(IpOutDiscards);
-	if (nfrags>1)
-		ip_statistics[smp_processor_id()*2 + !in_softirq()].IpFragCreates += nfrags;
-	return err; 
+no_route:
+	IP_INC_STATS(IpOutNoRoutes);
+	kfree_skb(skb);
+	return -EHOSTUNREACH;
 }
 
-/*
- *	Fast path for unfragmented packets.
- */
-int ip_build_xmit(struct sock *sk, 
-		  int getfrag (const void *,
-			       char *,
-			       unsigned int,	
-			       unsigned int),
-		  const void *frag,
-		  unsigned length,
-		  struct ipcm_cookie *ipc,
-		  struct rtable *rt,
-		  int flags)
-{
-	struct inet_opt *inet = inet_sk(sk);
-	int err;
-	struct sk_buff *skb;
-	int df;
-	struct iphdr *iph;
 
-	/*
-	 *	Try the simple case first. This leaves fragmented frames, and by
-	 *	choice RAW frames within 20 bytes of maximum size(rare) to the long path
-	 */
-
-	if (!inet->hdrincl) {
-		length += sizeof(struct iphdr);
-
-		/*
-		 * 	Check for slow path.
-		 */
-		if (length > rt->u.dst.pmtu || ipc->opt != NULL)  
-			return ip_build_xmit_slow(sk,getfrag,frag,length,ipc,rt,flags); 
-	} else {
-		if (length > rt->u.dst.dev->mtu) {
-			ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport,
-				       rt->u.dst.dev->mtu);
-			return -EMSGSIZE;
-		}
-	}
-	if (flags&MSG_PROBE)
-		goto out;
-
-	/*
-	 *	Do path mtu discovery if needed.
-	 */
-	df = 0;
-	if (ip_dont_fragment(sk, &rt->u.dst))
-		df = htons(IP_DF);
-
-	/* 
-	 *	Fast path for unfragmented frames without options. 
-	 */ 
-	{
-	int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
-
-	skb = sock_alloc_send_skb(sk, length+hh_len+15,
-				  flags&MSG_DONTWAIT, &err);
-	if(skb==NULL)
-		goto error; 
-	skb_reserve(skb, hh_len);
-	}
-
-	skb->priority = sk->priority;
-	skb->dst = dst_clone(&rt->u.dst);
-
-	skb->nh.iph = iph = (struct iphdr *)skb_put(skb, length);
-
-	if (!inet->hdrincl) {
-		iph->version=4;
-		iph->ihl=5;
-		iph->tos = inet->tos;
-		iph->tot_len = htons(length);
-		iph->frag_off = df;
-		iph->ttl = inet->mc_ttl;
-		ip_select_ident(iph, &rt->u.dst, sk);
-		if (rt->rt_type != RTN_MULTICAST)
-			iph->ttl = inet->ttl;
-		iph->protocol=sk->protocol;
-		iph->saddr=rt->rt_src;
-		iph->daddr=rt->rt_dst;
-		iph->check=0;
-		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-		err = getfrag(frag, ((char *)iph)+iph->ihl*4,0, length-iph->ihl*4);
-	}
-	else
-		err = getfrag(frag, (void *)iph, 0, length);
-
-	if (err)
-		goto error_fault;
+static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
+{
+	to->pkt_type = from->pkt_type;
+	to->priority = from->priority;
+	to->protocol = from->protocol;
+	to->security = from->security;
+	to->dst = dst_clone(from->dst);
+	to->dev = from->dev;
 
-	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		      output_maybe_reroute);
-	if (err > 0)
-		err = inet->recverr ? net_xmit_errno(err) : 0;
-	if (err)
-		goto error;
-out:
-	return 0;
+	/* Copy the flags to each fragment. */
+	IPCB(to)->flags = IPCB(from)->flags;
 
-error_fault:
-	err = -EFAULT;
-	kfree_skb(skb);
-error:
-	IP_INC_STATS(IpOutDiscards);
-	return err; 
+#ifdef CONFIG_NET_SCHED
+	to->tc_index = from->tc_index;
+#endif
+#ifdef CONFIG_NETFILTER
+	to->nfmark = from->nfmark;
+	/* Connection association is same as pre-frag packet */
+	to->nfct = from->nfct;
+	nf_conntrack_get(to->nfct);
+#ifdef CONFIG_NETFILTER_DEBUG
+	to->nf_debug = from->nf_debug;
+#endif
+#endif
 }
 
 /*
@@ -764,8 +407,6 @@
  *	smaller pieces (each of size equal to IP header plus
  *	a block of the data of the original IP data part) that will yet fit in a
  *	single device frame, and queue such a frame for sending.
- *
- *	Yes this is inefficient, feel free to submit a quicker one.
  */
 
 int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
@@ -789,13 +430,111 @@
 
 	iph = skb->nh.iph;
 
+	if (unlikely(iph->frag_off & htons(IP_DF))) {
+		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+			  htonl(rt->u.dst.pmtu));
+		kfree_skb(skb);
+		return -EMSGSIZE;
+	}
+
 	/*
 	 *	Setup starting values.
 	 */
 
 	hlen = iph->ihl * 4;
-	left = skb->len - hlen;		/* Space per frame */
 	mtu = rt->u.dst.pmtu - hlen;	/* Size of data space */
+
+	/* When frag_list is given, use it. First, check its validity:
+	 * some transformers could create wrong frag_list or break existing
+	 * one, it is not prohibited. In this case fall back to copying.
+	 *
+	 * LATER: this step can be merged to real generation of fragments,
+	 * we can switch to copy when see the first bad fragment.
+	 */
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *frag;
+		int first_len = skb_pagelen(skb);
+
+		if (first_len - hlen > mtu ||
+		    ((first_len - hlen) & 7) ||
+		    (iph->frag_off & htons(IP_MF|IP_OFFSET)) ||
+		    skb_cloned(skb))
+			goto slow_path;
+
+		for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+			/* Correct geometry. */
+			if (frag->len > mtu ||
+			    ((frag->len & 7) && frag->next) ||
+			    skb_headroom(frag) < hlen)
+			    goto slow_path;
+
+			/* Correct socket ownership. */
+			if (frag->sk == NULL)
+				goto slow_path;
+
+			/* Partially cloned skb? */
+			if (skb_shared(frag))
+				goto slow_path;
+		}
+
+		/* Everything is OK. Generate! */
+
+		err = 0;
+		offset = 0;
+		frag = skb_shinfo(skb)->frag_list;
+		skb_shinfo(skb)->frag_list = 0;
+		skb->data_len = first_len - skb_headlen(skb);
+		skb->len = first_len;
+		iph->tot_len = htons(first_len);
+		iph->frag_off |= htons(IP_MF);
+		ip_send_check(iph);
+
+		for (;;) {
+			/* Prepare header of the next frame,
+			 * before previous one went down. */
+			if (frag) {
+				frag->h.raw = frag->data;
+				frag->nh.raw = __skb_push(frag, hlen);
+				memcpy(frag->nh.raw, iph, hlen);
+				iph = frag->nh.iph;
+				iph->tot_len = htons(frag->len);
+				ip_copy_metadata(frag, skb);
+				if (offset == 0)
+					ip_options_fragment(frag);
+				offset += skb->len - hlen;
+				iph->frag_off = htons(offset>>3);
+				if (frag->next != NULL)
+					iph->frag_off |= htons(IP_MF);
+				/* Ready, complete checksum */
+				ip_send_check(iph);
+			}
+
+			err = output(skb);
+
+			if (err || !frag)
+				break;
+
+			skb = frag;
+			frag = skb->next;
+			skb->next = NULL;
+		}
+
+		if (err == 0) {
+			IP_INC_STATS(IpFragOKs);
+			return 0;
+		}
+
+		while (frag) {
+			skb = frag->next;
+			kfree_skb(frag);
+			frag = skb;
+		}
+		IP_INC_STATS(IpFragFails);
+		return err;
+	}
+
+slow_path:
+	left = skb->len - hlen;		/* Space per frame */
 	ptr = raw + hlen;		/* Where to start from */
 
 	/*
@@ -823,7 +562,7 @@
 		 *	Allocate buffer.
 		 */
 
-		if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15,GFP_ATOMIC)) == NULL) {
+		if ((skb2 = alloc_skb(len+hlen+rt->u.dst.dev->hard_header_len+16,GFP_ATOMIC)) == NULL) {
 			NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
 			err = -ENOMEM;
 			goto fail;
@@ -833,14 +572,11 @@
 		 *	Set up data on packet
 		 */
 
-		skb2->pkt_type = skb->pkt_type;
-		skb2->priority = skb->priority;
-		skb_reserve(skb2, (dev->hard_header_len+15)&~15);
+		ip_copy_metadata(skb2, skb);
+		skb_reserve(skb2, (rt->u.dst.dev->hard_header_len&~15)+16);
 		skb_put(skb2, len + hlen);
 		skb2->nh.raw = skb2->data;
 		skb2->h.raw = skb2->data + hlen;
-		skb2->protocol = skb->protocol;
-		skb2->security = skb->security;
 
 		/*
 		 *	Charge the memory for the fragment to any owner
@@ -849,8 +585,6 @@
 
 		if (skb->sk)
 			skb_set_owner_w(skb2, skb->sk);
-		skb2->dst = dst_clone(skb->dst);
-		skb2->dev = skb->dev;
 
 		/*
 		 *	Copy the packet header into the new buffer.
@@ -880,9 +614,6 @@
 		if (offset == 0)
 			ip_options_fragment(skb);
 
-		/* Copy the flags to each fragment. */
-		IPCB(skb2)->flags = IPCB(skb)->flags;
-
 		/*
 		 *	Added AC : If we are fragmenting a fragment that's not the
 		 *		   last fragment then keep MF on each bit
@@ -892,19 +623,6 @@
 		ptr += len;
 		offset += len;
 
-#ifdef CONFIG_NET_SCHED
-		skb2->tc_index = skb->tc_index;
-#endif
-#ifdef CONFIG_NETFILTER
-		skb2->nfmark = skb->nfmark;
-		/* Connection association is same as pre-frag packet */
-		skb2->nfct = skb->nfct;
-		nf_conntrack_get(skb2->nfct);
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb2->nf_debug = skb->nf_debug;
-#endif
-#endif
-
 		/*
 		 *	Put this fragment into the sending queue.
 		 */
@@ -929,40 +647,525 @@
 	return err;
 }
 
+int
+ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
+{
+	struct iovec *iov = from;
+
+	if (skb->ip_summed == CHECKSUM_HW) {
+		if (memcpy_fromiovecend(to, iov, offset, len) < 0)
+			return -EFAULT;
+	} else {
+		unsigned int csum = 0;
+		if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
+			return -EFAULT;
+		skb->csum = csum_block_add(skb->csum, csum, odd);
+	}
+	return 0;
+}
+
+static inline int
+skb_can_coalesce(struct sk_buff *skb, int i, struct page *page, int off)
+{
+	if (i) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
+		return page == frag->page &&
+			off == frag->page_offset+frag->size;
+	}
+	return 0;
+}
+
+static inline void
+skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size)
+{
+	skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+	frag->page = page;
+	frag->page_offset = off;
+	frag->size = size;
+	skb_shinfo(skb)->nr_frags = i+1;
+}
+
+static inline unsigned int
+csum_page(struct page *page, int offset, int copy)
+{
+	char *kaddr;
+	unsigned int csum;
+	kaddr = kmap(page);
+	csum = csum_partial(kaddr + offset, copy, 0);
+	kunmap(page);
+	return csum;
+}
+
 /*
- *	Fetch data from kernel space and fill in checksum if needed.
+ *	ip_append_data() and ip_append_page() can make one large IP datagram
+ *	from many pieces of data. Each pieces will be holded on the socket
+ *	until ip_push_pending_frames() is called. Eache pieces can be a page
+ *	or non-page data.
+ *	
+ *	Not only UDP, other transport protocols - e.g. raw sockets - can use
+ *	this interface potentially.
+ *
+ *	LATER: length must be adjusted by pad at tail, when it is required.
  */
-static int ip_reply_glue_bits(const void *dptr, char *to, unsigned int offset, 
-			      unsigned int fraglen)
+int ip_append_data(struct sock *sk,
+		   int getfrag(void *from, char *to, int offset, int len,
+			       int odd, struct sk_buff *skb),
+		   void *from, int length, int transhdrlen,
+		   struct ipcm_cookie *ipc, struct rtable *rt,
+		   unsigned int flags)
 {
-        struct ip_reply_arg *dp = (struct ip_reply_arg*)dptr;
-	u16 *pktp = (u16 *)to;
-	struct iovec *iov; 
-	int len; 
-	int hdrflag = 1; 
-
-	iov = &dp->iov[0]; 
-	if (offset >= iov->iov_len) { 
-		offset -= iov->iov_len;
-		iov++; 
-		hdrflag = 0; 
-	}
-	len = iov->iov_len - offset;
-	if (fraglen > len) { /* overlapping. */ 
-		dp->csum = csum_partial_copy_nocheck(iov->iov_base+offset, to, len,
-					     dp->csum);
-		offset = 0;
-		fraglen -= len; 
-		to += len; 
-		iov++;
+	struct inet_opt *inet = inet_sk(sk);
+	struct sk_buff *skb;
+
+	struct ip_options *opt = NULL;
+	int hh_len;
+	int exthdrlen;
+	int mtu;
+	int copy;
+	int err;
+	int offset = 0;
+	unsigned int maxfraglen, fragheaderlen;
+	int csummode = CHECKSUM_NONE;
+
+	if (flags&MSG_PROBE)
+		return 0;
+
+	if (skb_queue_empty(&sk->write_queue)) {
+		/*
+		 * setup for corking.
+		 */
+		opt = ipc->opt;
+		if (opt) {
+			if (inet->cork.opt == NULL)
+				inet->cork.opt = kmalloc(sizeof(struct ip_options)+40, sk->allocation);
+			memcpy(inet->cork.opt, opt, sizeof(struct ip_options)+opt->optlen);
+			inet->cork.flags |= IPCORK_OPT;
+			inet->cork.addr = ipc->addr;
+		}
+		dst_hold(&rt->u.dst);
+		inet->cork.fragsize = mtu = rt->u.dst.pmtu;
+		inet->cork.rt = rt;
+		inet->cork.length = 0;
+		inet->sndmsg_page = NULL;
+		inet->sndmsg_off = 0;
+		if ((exthdrlen = rt->u.dst.header_len) != 0) {
+			length += exthdrlen;
+			transhdrlen += exthdrlen;
+		}
+	} else {
+		rt = inet->cork.rt;
+		if (inet->cork.flags & IPCORK_OPT)
+			opt = inet->cork.opt;
+
+		transhdrlen = 0;
+		exthdrlen = 0;
+		mtu = inet->cork.fragsize;
+	}
+	hh_len = (rt->u.dst.dev->hard_header_len&~15) + 16;
+
+	fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
+	maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen;
+
+	if (inet->cork.length + length > 0xFFFF - fragheaderlen) {
+		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu-exthdrlen);
+		return -EMSGSIZE;
+	}
+
+	/*
+	 * transhdrlen > 0 means that this is the first fragment and we wish
+	 * it won't be fragmented in the future.
+	 */
+	if (transhdrlen &&
+	    length + fragheaderlen <= maxfraglen &&
+	    rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
+	    !exthdrlen)
+		csummode = CHECKSUM_HW;
+
+	inet->cork.length += length;
+
+	if ((skb = skb_peek_tail(&sk->write_queue)) == NULL)
+		goto alloc_new_skb;
+
+	while (length > 0) {
+		if ((copy = maxfraglen - skb->len) <= 0) {
+			char *data;
+			unsigned int datalen;
+			unsigned int fraglen;
+			unsigned int alloclen;
+			BUG_TRAP(copy == 0);
+
+alloc_new_skb:
+			datalen = maxfraglen - fragheaderlen;
+			if (datalen > length)
+				datalen = length;
+
+			fraglen = datalen + fragheaderlen;
+			if ((flags & MSG_MORE) && 
+			    !(rt->u.dst.dev->features&NETIF_F_SG))
+				alloclen = maxfraglen;
+			else
+				alloclen = datalen + fragheaderlen;
+			if (!(flags & MSG_DONTWAIT) || transhdrlen) {
+				skb = sock_alloc_send_skb(sk, 
+						alloclen + hh_len + 15,
+						(flags & MSG_DONTWAIT), &err);
+			} else {
+				skb = sock_wmalloc(sk, 
+						alloclen + hh_len + 15, 1,
+						sk->allocation);
+				if (unlikely(skb == NULL))
+					err = -ENOBUFS;
+			}
+			if (skb == NULL)
+				goto error;
+
+			/*
+			 *	Fill in the control structures
+			 */
+			skb->ip_summed = csummode;
+			skb->csum = 0;
+			skb_reserve(skb, hh_len);
+
+			/*
+			 *	Find where to start putting bytes.
+			 */
+			data = skb_put(skb, fraglen);
+			skb->nh.raw = __skb_pull(skb, exthdrlen);
+			data += fragheaderlen;
+			skb->h.raw = data + exthdrlen;
+
+			copy = datalen - transhdrlen;
+			if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, 0, skb) < 0) {
+				err = -EFAULT;
+				kfree_skb(skb);
+				goto error;
+			}
+
+			offset += copy;
+			length -= datalen;
+			transhdrlen = 0;
+			exthdrlen = 0;
+			csummode = CHECKSUM_NONE;
+
+			/*
+			 * Put the packet on the pending queue.
+			 */
+			__skb_queue_tail(&sk->write_queue, skb);
+			continue;
+		}
+
+		if (copy > length)
+			copy = length;
+
+		if (!(rt->u.dst.dev->features&NETIF_F_SG)) {
+			unsigned int off;
+
+			off = skb->len;
+			if (getfrag(from, skb_put(skb, copy), 
+					offset, copy, off, skb) < 0) {
+				__skb_trim(skb, off);
+				err = -EFAULT;
+				goto error;
+			}
+		} else {
+			int i = skb_shinfo(skb)->nr_frags;
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
+			struct page *page = inet->sndmsg_page;
+			int off = inet->sndmsg_off;
+			unsigned int left;
+
+			if (page && (left = PAGE_SIZE - off) > 0) {
+				if (copy >= left)
+					copy = left;
+				if (page != frag->page) {
+					if (i == MAX_SKB_FRAGS) {
+						err = -EMSGSIZE;
+						goto error;
+					}
+					get_page(page);
+	 				skb_fill_page_desc(skb, i, page, inet->sndmsg_off, 0);
+					frag = &skb_shinfo(skb)->frags[i];
+				}
+			} else if (i < MAX_SKB_FRAGS) {
+				if (copy > PAGE_SIZE)
+					copy = PAGE_SIZE;
+				page = alloc_pages(sk->allocation, 0);
+				if (page == NULL)  {
+					err = -ENOMEM;
+					goto error;
+				}
+				inet->sndmsg_page = page;
+				inet->sndmsg_off = 0;
+
+				skb_fill_page_desc(skb, i, page, 0, 0);
+				frag = &skb_shinfo(skb)->frags[i];
+				skb->truesize += PAGE_SIZE;
+				atomic_add(PAGE_SIZE, &sk->wmem_alloc);
+			} else {
+				err = -EMSGSIZE;
+				goto error;
+			}
+			if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) {
+				err = -EFAULT;
+				goto error;
+			}
+			inet->sndmsg_off += copy;
+			frag->size += copy;
+			skb->len += copy;
+			skb->data_len += copy;
+		}
+		offset += copy;
+		length -= copy;
 	}
 
-	dp->csum = csum_partial_copy_nocheck(iov->iov_base+offset, to, fraglen, 
-					     dp->csum); 
+	return 0;
 
-	if (hdrflag && dp->csumoffset)
-		*(pktp + dp->csumoffset) = csum_fold(dp->csum); /* fill in checksum */
-	return 0;	       
+error:
+	inet->cork.length -= length;
+	IP_INC_STATS(IpOutDiscards);
+	return err; 
+}
+
+ssize_t	ip_append_page(struct sock *sk, struct page *page,
+		       int offset, size_t size, int flags)
+{
+	struct inet_opt *inet = inet_sk(sk);
+	struct sk_buff *skb;
+	struct rtable *rt;
+	struct ip_options *opt = NULL;
+	int hh_len;
+	int mtu;
+	int len;
+	int err;
+	unsigned int maxfraglen, fragheaderlen;
+
+	if (inet->hdrincl)
+		return -EPERM;
+
+	if (flags&MSG_PROBE)
+		return 0;
+
+	if (skb_queue_empty(&sk->write_queue))
+		return -EINVAL;
+
+	rt = inet->cork.rt;
+	if (inet->cork.flags & IPCORK_OPT)
+		opt = inet->cork.opt;
+
+	if (!(rt->u.dst.dev->features&NETIF_F_SG))
+		return -EOPNOTSUPP;
+
+	hh_len = (rt->u.dst.dev->hard_header_len&~15)+16;
+	mtu = inet->cork.fragsize;
+
+	fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
+	maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen;
+
+	if (inet->cork.length + size > 0xFFFF - fragheaderlen) {
+		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu);
+		return -EMSGSIZE;
+	}
+
+	if ((skb = skb_peek_tail(&sk->write_queue)) == NULL)
+		return -EINVAL;
+
+	inet->cork.length += size;
+
+	while (size > 0) {
+		int i;
+		if ((len = maxfraglen - skb->len) <= 0) {
+			char *data;
+			struct iphdr *iph;
+			BUG_TRAP(len == 0);
+
+			skb = sock_wmalloc(sk, fragheaderlen + hh_len + 15, 1,
+					   sk->allocation);
+			if (unlikely(!skb)) {
+				err = -ENOBUFS;
+				goto error;
+			}
+
+			/*
+			 *	Fill in the control structures
+			 */
+			skb->ip_summed = CHECKSUM_NONE;
+			skb->csum = 0;
+			skb_reserve(skb, hh_len);
+
+			/*
+			 *	Find where to start putting bytes.
+			 */
+			data = skb_put(skb, fragheaderlen);
+			skb->nh.iph = iph = (struct iphdr *)data;
+			data += fragheaderlen;
+			skb->h.raw = data;
+
+			/*
+			 * Put the packet on the pending queue.
+			 */
+			__skb_queue_tail(&sk->write_queue, skb);
+			continue;
+		}
+
+		i = skb_shinfo(skb)->nr_frags;
+		if (len > size)
+			len = size;
+		if (skb_can_coalesce(skb, i, page, offset)) {
+			skb_shinfo(skb)->frags[i-1].size += len;
+		} else if (i < MAX_SKB_FRAGS) {
+			get_page(page);
+			skb_fill_page_desc(skb, i, page, offset, len);
+		} else {
+			err = -EMSGSIZE;
+			goto error;
+		}
+
+		if (skb->ip_summed == CHECKSUM_NONE) {
+			unsigned int csum;
+			csum = csum_page(page, offset, len);
+			skb->csum = csum_block_add(skb->csum, csum, skb->len);
+		}
+
+		skb->len += len;
+		skb->data_len += len;
+		offset += len;
+		size -= len;
+	}
+	return 0;
+
+error:
+	inet->cork.length -= size;
+	IP_INC_STATS(IpOutDiscards);
+	return err;
+}
+
+/*
+ *	Combined all pending IP fragments on the socket as one IP datagram
+ *	and push them out.
+ */
+int ip_push_pending_frames(struct sock *sk)
+{
+	struct sk_buff *skb, *tmp_skb;
+	struct sk_buff **tail_skb;
+	struct inet_opt *inet = inet_sk(sk);
+	struct ip_options *opt = NULL;
+	struct rtable *rt = inet->cork.rt;
+	struct iphdr *iph;
+	int df = 0;
+	__u8 ttl;
+	int err = 0;
+
+	if ((skb = __skb_dequeue(&sk->write_queue)) == NULL)
+		goto out;
+	tail_skb = &(skb_shinfo(skb)->frag_list);
+
+	while ((tmp_skb = __skb_dequeue(&sk->write_queue)) != NULL) {
+		__skb_pull(tmp_skb, skb->h.raw - skb->nh.raw);
+		*tail_skb = tmp_skb;
+		tail_skb = &(tmp_skb->next);
+		skb->len += tmp_skb->len;
+		skb->data_len += tmp_skb->len;
+#if 0 /* Logically correct, but useless work, ip_fragment() will have to undo */
+		skb->truesize += tmp_skb->truesize;
+		__sock_put(tmp_skb->sk);
+		tmp_skb->destructor = NULL;
+		tmp_skb->sk = NULL;
+#endif
+	}
+
+	if (inet->pmtudisc == IP_PMTUDISC_DO ||
+	    (!skb_shinfo(skb)->frag_list && ip_dont_fragment(sk, &rt->u.dst)))
+		df = htons(IP_DF);
+
+	if (inet->cork.flags & IPCORK_OPT)
+		opt = inet->cork.opt;
+
+	if (rt->rt_type == RTN_MULTICAST)
+		ttl = inet->mc_ttl;
+	else
+		ttl = inet->ttl;
+
+	iph = (struct iphdr *)skb->data;
+	iph->version = 4;
+	iph->ihl = 5;
+	if (opt) {
+		iph->ihl += opt->optlen>>2;
+		ip_options_build(skb, opt, inet->cork.addr, rt, 0);
+	}
+	iph->tos = inet->tos;
+	iph->tot_len = htons(skb->len);
+	iph->frag_off = df;
+	if (!df) {
+		__ip_select_ident(iph, &rt->u.dst, 0);
+	} else {
+		iph->id = htons(inet->id++);
+	}
+	iph->ttl = ttl;
+	iph->protocol = sk->protocol;
+	iph->saddr = rt->rt_src;
+	iph->daddr = rt->rt_dst;
+	ip_send_check(iph);
+
+	skb->priority = sk->priority;
+	skb->dst = dst_clone(&rt->u.dst);
+
+	/* Netfilter gets whole the not fragmented skb. */
+	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
+		      skb->dst->dev, dst_output);
+	if (err) {
+		if (err > 0)
+			err = inet->recverr ? net_xmit_errno(err) : 0;
+		if (err)
+			goto error;
+	}
+
+out:
+	inet->cork.flags &= ~IPCORK_OPT;
+	if (inet->cork.rt) {
+		ip_rt_put(inet->cork.rt);
+		inet->cork.rt = NULL;
+	}
+	return err;
+
+error:
+	IP_INC_STATS(IpOutDiscards);
+	goto out;
+}
+
+/*
+ *	Throw away all pending data on the socket.
+ */
+void ip_flush_pending_frames(struct sock *sk)
+{
+	struct inet_opt *inet = inet_sk(sk);
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue_tail(&sk->write_queue)) != NULL)
+		kfree_skb(skb);
+
+	inet->cork.flags &= ~IPCORK_OPT;
+	if (inet->cork.opt) {
+		kfree(inet->cork.opt);
+		inet->cork.opt = NULL;
+	}
+	if (inet->cork.rt) {
+		ip_rt_put(inet->cork.rt);
+		inet->cork.rt = NULL;
+	}
+}
+
+
+/*
+ *	Fetch data from kernel space and fill in checksum if needed.
+ */
+static int ip_reply_glue_bits(void *dptr, char *to, int offset, 
+			      int len, int odd, struct sk_buff *skb)
+{
+	unsigned int csum;
+
+	csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0);
+	skb->csum = csum_block_add(skb->csum, csum, odd);
+	return 0;  
 }
 
 /* 
@@ -971,6 +1174,8 @@
  *
  *	Should run single threaded per socket because it uses the sock 
  *     	structure to pass arguments.
+ *
+ *	LATER: switch from ip_build_xmit to ip_append_*
  */
 void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
 		   unsigned int len)
@@ -1016,7 +1221,15 @@
 	inet->tos = skb->nh.iph->tos;
 	sk->priority = skb->priority;
 	sk->protocol = skb->nh.iph->protocol;
-	ip_build_xmit(sk, ip_reply_glue_bits, arg, len, &ipc, rt, MSG_DONTWAIT);
+	ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0,
+		       &ipc, rt, MSG_DONTWAIT);
+	if ((skb = skb_peek(&sk->write_queue)) != NULL) {
+		if (arg->csumoffset >= 0)
+			*((u16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum));
+		skb->ip_summed = CHECKSUM_NONE;
+		ip_push_pending_frames(sk);
+	}
+
 	bh_unlock_sock(sk);
 
 	ip_rt_put(rt);
diff -Nru a/net/ipv4/ip_proc.c b/net/ipv4/ip_proc.c
--- a/net/ipv4/ip_proc.c	Fri Oct 18 21:03:03 2002
+++ b/net/ipv4/ip_proc.c	Fri Oct 18 21:03:03 2002
@@ -67,99 +67,183 @@
 }
 #endif /* CONFIG_AX25 */
 
+struct arp_iter_state {
+	int is_pneigh, bucket;
+};
+
+static __inline__ struct neighbour *neigh_get_bucket(struct seq_file *seq,
+						     loff_t *pos)
+{
+	struct neighbour *n = NULL;
+	struct arp_iter_state* state = seq->private;
+	loff_t l = *pos;
+	int i;
+
+	for (; state->bucket <= NEIGH_HASHMASK; ++state->bucket)
+		for (i = 0, n = arp_tbl.hash_buckets[state->bucket]; n;
+		     ++i, n = n->next)
+			/* Do not confuse users "arp -a" with magic entries */
+			if ((n->nud_state & ~NUD_NOARP) && !l--) {
+				*pos = i;
+				goto out;
+			}
+out:
+	return n;
+}
+
+static __inline__ struct pneigh_entry *pneigh_get_bucket(struct seq_file *seq,
+							 loff_t *pos)
+{
+	struct pneigh_entry *n = NULL;
+	struct arp_iter_state* state = seq->private;
+	loff_t l = *pos;
+	int i;
+
+	for (; state->bucket <= PNEIGH_HASHMASK; ++state->bucket)
+		for (i = 0, n = arp_tbl.phash_buckets[state->bucket]; n;
+		     ++i, n = n->next)
+			if (!l--) {
+				*pos = i;
+				goto out;
+			}
+out:
+	return n;
+}
+
+static __inline__ void *arp_get_bucket(struct seq_file *seq, loff_t *pos)
+{
+	void *rc = neigh_get_bucket(seq, pos);
+
+	if (!rc) {
+		struct arp_iter_state* state = seq->private;
+
+		read_unlock_bh(&arp_tbl.lock);
+		state->is_pneigh = 1;
+		state->bucket	 = 0;
+		*pos		 = 0;
+		rc = pneigh_get_bucket(seq, pos);
+	}
+	return rc;
+}
+
 static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	return (void *)(unsigned long)++*pos;
+	read_lock_bh(&arp_tbl.lock);
+	return *pos ? arp_get_bucket(seq, pos) : (void *)1;
 }
 
 static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	return (void *)(unsigned long)((++*pos) >=
-				       (NEIGH_HASHMASK +
-					PNEIGH_HASHMASK - 1) ? 0 : *pos);
+	void *rc;
+	struct arp_iter_state* state;
+
+	if (v == (void *)1) {
+		rc = arp_get_bucket(seq, pos);
+		goto out;
+	}
+
+	state = seq->private;
+	if (!state->is_pneigh) {
+		struct neighbour *n = v;
+
+		rc = n = n->next;
+		if (n)
+			goto out;
+		*pos = 0;
+		++state->bucket;
+		rc = neigh_get_bucket(seq, pos);
+		if (rc)
+			goto out;
+		read_unlock_bh(&arp_tbl.lock);
+		state->is_pneigh = 1;
+		state->bucket	 = 0;
+		*pos		 = 0;
+		rc = pneigh_get_bucket(seq, pos);
+	} else {
+		struct pneigh_entry *pn = v;
+
+		pn = pn->next;
+		if (!pn) {
+			++state->bucket;
+			*pos = 0;
+			pn   = pneigh_get_bucket(seq, pos);
+		}
+		rc = pn;
+	}
+out:
+	++*pos;
+	return rc;
 }
 
 static void arp_seq_stop(struct seq_file *seq, void *v)
 {
+	struct arp_iter_state* state = seq->private;
+
+	if (!state->is_pneigh)
+		read_unlock_bh(&arp_tbl.lock);
 }
 
 #define HBUFFERLEN 30
 
-static __inline__ void arp_format_neigh_table(struct seq_file *seq, int entry)
+static __inline__ void arp_format_neigh_entry(struct seq_file *seq,
+					      struct neighbour *n)
 {
 	char hbuffer[HBUFFERLEN];
 	const char hexbuf[] = "0123456789ABCDEF";
-	struct neighbour *n;
 	int k, j;
+	char tbuf[16];
+	struct net_device *dev = n->dev;
+	int hatype = dev->type;
 
-	read_lock_bh(&arp_tbl.lock);
-	for (n = arp_tbl.hash_buckets[entry]; n; n = n->next) {
-		char tbuf[16];
-		struct net_device *dev = n->dev;
-		int hatype = dev->type;
-
-		/* Do not confuse users "arp -a" with magic entries */
-		if (!(n->nud_state & ~NUD_NOARP))
-			continue;
-
-		read_lock(&n->lock);
-		/* Convert hardware address to XX:XX:XX:XX ... form. */
+	read_lock(&n->lock);
+	/* Convert hardware address to XX:XX:XX:XX ... form. */
 #ifdef CONFIG_AX25
-		if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
-			ax2asc2((ax25_address *)n->ha, hbuffer);
-		else {
+	if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
+		ax2asc2((ax25_address *)n->ha, hbuffer);
+	else {
 #endif
-		for (k = 0, j = 0; k < HBUFFERLEN - 3 &&
-				   j < dev->addr_len; j++) {
-			hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];
-			hbuffer[k++] = hexbuf[n->ha[j] & 15];
-			hbuffer[k++] = ':';
-		}
-		hbuffer[--k] = 0;
+	for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) {
+		hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];
+		hbuffer[k++] = hexbuf[n->ha[j] & 15];
+		hbuffer[k++] = ':';
+	}
+	hbuffer[--k] = 0;
 #ifdef CONFIG_AX25
-		}
-#endif
-		sprintf(tbuf, "%u.%u.%u.%u",
-			NIPQUAD(*(u32*)n->primary_key));
-		seq_printf(seq, "%-16s 0x%-10x0x%-10x%s"
-				"     *        %s\n",
-			   tbuf, hatype, arp_state_to_flags(n), 
-			   hbuffer, dev->name);
-		read_unlock(&n->lock);
-	}
-	read_unlock_bh(&arp_tbl.lock);
-}
-
-static __inline__ void arp_format_pneigh_table(struct seq_file *seq, int entry)
-{
-	struct pneigh_entry *n;
-
-	for (n = arp_tbl.phash_buckets[entry]; n; n = n->next) {
-		struct net_device *dev = n->dev;
-		int hatype = dev ? dev->type : 0;
-		char tbuf[16];
-
-		sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
-		seq_printf(seq, "%-16s 0x%-10x0x%-10x%s"
-				"     *        %s\n",
-			   tbuf, hatype, ATF_PUBL | ATF_PERM,
-			   "00:00:00:00:00:00",
-			   dev ? dev->name : "*");
 	}
+#endif
+	sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));
+	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
+		   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
+	read_unlock(&n->lock);
 }
 
-static int arp_seq_show(struct seq_file *seq, void *v)
+static __inline__ void arp_format_pneigh_entry(struct seq_file *seq,
+					       struct pneigh_entry *n)
 {
-	unsigned long l = (unsigned long)v - 1;
 
-	if (!l)
+	struct net_device *dev = n->dev;
+	int hatype = dev ? dev->type : 0;
+	char tbuf[16];
+
+	sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
+	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
+		   tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",
+		   dev ? dev->name : "*");
+}
+
+static int arp_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == (void *)1)
 		seq_puts(seq, "IP address       HW type     Flags       "
 			      "HW address            Mask     Device\n");
+	else {
+		struct arp_iter_state* state = seq->private;
 
-	if (l <= NEIGH_HASHMASK)
-		arp_format_neigh_table(seq, l);
-	else
-		arp_format_pneigh_table(seq, l - NEIGH_HASHMASK);
+		if (state->is_pneigh)
+			arp_format_pneigh_entry(seq, v);
+		else
+			arp_format_neigh_entry(seq, v);
+	}
 
 	return 0;
 }
@@ -198,16 +282,60 @@
 
 /* ------------------------------------------------------------------------ */
 
+struct udp_iter_state {
+	int bucket;
+};
+
+static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos)
+{
+	int i;
+	struct sock *sk = NULL;
+	loff_t l = *pos;
+	struct udp_iter_state *state = seq->private;
+
+	for (; state->bucket < UDP_HTABLE_SIZE; ++state->bucket)
+		for (i = 0, sk = udp_hash[state->bucket]; sk; ++i, sk = sk->next) {
+			if (sk->family != PF_INET)
+				continue;
+			if (l--)
+				continue;
+			*pos = i;
+			goto out;
+		}
+out:
+	return sk;
+}
+
 static void *udp_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	read_lock(&udp_hash_lock);
-	return (void *)(unsigned long)++*pos;
+	return *pos ? udp_get_bucket(seq, pos) : (void *)1;
 }
 
 static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	return (void *)(unsigned long)((++*pos) >=
-				       (UDP_HTABLE_SIZE - 1) ? 0 : *pos);
+	struct sock *sk;
+	struct udp_iter_state *state;
+
+	if (v == (void *)1) {
+		sk = udp_get_bucket(seq, pos);
+		goto out;
+	}
+
+	sk = v;
+	sk = sk->next;
+	if (sk) 
+		goto out;
+
+	state = seq->private;
+	if (++state->bucket >= UDP_HTABLE_SIZE) 
+		goto out;
+
+	*pos = 0;
+	sk = udp_get_bucket(seq, pos);
+out:
+	++*pos;
+	return sk;
 }
 
 static void udp_seq_stop(struct seq_file *seq, void *v)
@@ -215,7 +343,7 @@
 	read_unlock(&udp_hash_lock);
 }
 
-static void udp_format_sock(struct sock *sp, char *tmpbuf, int i)
+static void udp_format_sock(struct sock *sp, char *tmpbuf, int bucket)
 {
 	struct inet_opt *inet = inet_sk(sp);
 	unsigned int dest = inet->daddr;
@@ -225,7 +353,7 @@
 
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
-		i, src, srcp, dest, destp, sp->state, 
+		bucket, src, srcp, dest, destp, sp->state, 
 		atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
 		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
 		atomic_read(&sp->refcnt), sp);
@@ -233,19 +361,16 @@
 
 static int udp_seq_show(struct seq_file *seq, void *v)
 {
-	char tmpbuf[129];
-	struct sock *sk;
-	unsigned long l = (unsigned long)v - 1;
-
-	if (!l)
+	if (v == (void *)1)
 		seq_printf(seq, "%-127s\n",
 			   "  sl  local_address rem_address   st tx_queue "
-			   "rx_queue tr tm->when retrnsmt   uid  timeout inode");
+			   "rx_queue tr tm->when retrnsmt   uid  timeout "
+			   "inode");
+	else {
+		char tmpbuf[129];
+		struct udp_iter_state *state = seq->private;
 
-	for (sk = udp_hash[l]; sk; sk = sk->next) {
-		if (sk->family != PF_INET)
-			continue;
-		udp_format_sock(sk, tmpbuf, l);
+		udp_format_sock(v, tmpbuf, state->bucket);
 		seq_printf(seq, "%-127s\n", tmpbuf);
 	}
 	return 0;
@@ -275,7 +400,35 @@
 
 static int arp_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &arp_seq_ops);
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct arp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       
+	if (!s)
+		goto out;
+
+	rc = seq_open(file, &arp_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq	     = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
+
+static int arp_seq_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = (struct seq_file *)file->private_data;
+
+	kfree(seq->private);
+	seq->private = NULL;
+
+	return seq_release(inode, file);
 }
 
 static int fib_seq_open(struct inode *inode, struct file *file)
@@ -285,14 +438,42 @@
 
 static int udp_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &udp_seq_ops);
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct udp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       
+	if (!s)
+		goto out;
+
+	rc = seq_open(file, &udp_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq	     = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
+
+static int udp_seq_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = (struct seq_file *)file->private_data;
+
+	kfree(seq->private);
+	seq->private = NULL;
+
+	return seq_release(inode, file);
 }
 
 static struct file_operations arp_seq_fops = {
 	.open           = arp_seq_open,
 	.read           = seq_read,
 	.llseek         = seq_lseek,
-	.release	= seq_release,
+	.release	= arp_seq_release,
 };
 
 static struct file_operations fib_seq_fops = {
@@ -306,7 +487,7 @@
 	.open           = udp_seq_open,
 	.read           = seq_read,
 	.llseek         = seq_lseek,
-	.release	= seq_release,
+	.release	= udp_seq_release,
 };
 
 /* ------------------------------------------------------------------------ */
diff -Nru a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
--- a/net/ipv4/ip_sockglue.c	Fri Oct 18 21:03:04 2002
+++ b/net/ipv4/ip_sockglue.c	Fri Oct 18 21:03:04 2002
@@ -437,8 +437,10 @@
 				    (!((1<<sk->state)&(TCPF_LISTEN|TCPF_CLOSE))
 				     && inet->daddr != LOOPBACK4_IPV6)) {
 #endif
+					if (inet->opt)
+						tp->ext_header_len -= inet->opt->optlen;
 					if (opt)
-						tp->ext_header_len = opt->optlen;
+						tp->ext_header_len += opt->optlen;
 					tcp_sync_mss(sk, tp->pmtu_cookie);
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 				}
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	Fri Oct 18 21:03:03 2002
+++ b/net/ipv4/raw.c	Fri Oct 18 21:03:03 2002
@@ -64,6 +64,7 @@
 #include <net/raw.h>
 #include <net/inet_common.h>
 #include <net/checksum.h>
+#include <linux/netfilter.h>
 
 struct sock *raw_v4_htable[RAWV4_HTABLE_SIZE];
 rwlock_t raw_v4_lock = RW_LOCK_UNLOCKED;
@@ -243,56 +244,71 @@
 	return 0;
 }
 
-struct rawfakehdr 
+static int raw_send_hdrinc(struct sock *sk, void *from, int length,
+			struct rtable *rt, 
+			unsigned int flags)
 {
-	struct	iovec *iov;
-	u32	saddr;
-	struct	dst_entry *dst;
-};
+	struct inet_opt *inet = inet_sk(sk);
+	int hh_len;
+	struct iphdr *iph;
+	struct sk_buff *skb;
+	int err;
 
-/*
- *	Send a RAW IP packet.
- */
+	if (length > rt->u.dst.dev->mtu) {
+		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport,
+			       rt->u.dst.dev->mtu);
+		return -EMSGSIZE;
+	}
+	if (flags&MSG_PROBE)
+		goto out;
 
-/*
- *	Callback support is trivial for SOCK_RAW
- */
-  
-static int raw_getfrag(const void *p, char *to, unsigned int offset,
-			unsigned int fraglen)
-{
-	struct rawfakehdr *rfh = (struct rawfakehdr *) p;
-	return memcpy_fromiovecend(to, rfh->iov, offset, fraglen);
-}
+	hh_len = (rt->u.dst.dev->hard_header_len&~15) + 16;
 
-/*
- *	IPPROTO_RAW needs extra work.
- */
- 
-static int raw_getrawfrag(const void *p, char *to, unsigned int offset,
-				unsigned int fraglen)
-{
-	struct rawfakehdr *rfh = (struct rawfakehdr *) p;
+	skb = sock_alloc_send_skb(sk, length+hh_len+15,
+				  flags&MSG_DONTWAIT, &err);
+	if (skb == NULL)
+		goto error; 
+	skb_reserve(skb, hh_len);
+
+	skb->priority = sk->priority;
+	skb->dst = dst_clone(&rt->u.dst);
 
-	if (memcpy_fromiovecend(to, rfh->iov, offset, fraglen))
-		return -EFAULT;
+	skb->nh.iph = iph = (struct iphdr *)skb_put(skb, length);
 
-	if (!offset) {
-		struct iphdr *iph = (struct iphdr *)to;
+	skb->ip_summed = CHECKSUM_NONE;
+
+	skb->h.raw = skb->nh.raw;
+	err = memcpy_fromiovecend((void *)iph, from, 0, length);
+	if (err)
+		goto error_fault;
+
+	/* We don't modify invalid header */
+	if (length >= sizeof(*iph) && iph->ihl * 4 <= length) {
 		if (!iph->saddr)
-			iph->saddr = rfh->saddr;
+			iph->saddr = rt->rt_src;
 		iph->check   = 0;
-		iph->tot_len = htons(fraglen); /* This is right as you can't
-						  frag RAW packets */
-		/*
-	 	 *	Deliberate breach of modularity to keep 
-	 	 *	ip_build_xmit clean (well less messy).
-		 */
+		iph->tot_len = htons(length);
 		if (!iph->id)
-			ip_select_ident(iph, rfh->dst, NULL);
+			ip_select_ident(iph, &rt->u.dst, NULL);
+
 		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 	}
+
+	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+		      dst_output);
+	if (err > 0)
+		err = inet->recverr ? net_xmit_errno(err) : 0;
+	if (err)
+		goto error;
+out:
 	return 0;
+
+error_fault:
+	err = -EFAULT;
+	kfree_skb(skb);
+error:
+	IP_INC_STATS(IpOutDiscards);
+	return err; 
 }
 
 static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
@@ -300,10 +316,10 @@
 {
 	struct inet_opt *inet = inet_sk(sk);
 	struct ipcm_cookie ipc;
-	struct rawfakehdr rfh;
 	struct rtable *rt = NULL;
 	int free = 0;
 	u32 daddr;
+	u32 saddr;
 	u8  tos;
 	int err;
 
@@ -373,7 +389,7 @@
 			free = 1;
 	}
 
-	rfh.saddr = ipc.addr;
+	saddr = ipc.addr;
 	ipc.addr = daddr;
 
 	if (!ipc.opt)
@@ -399,14 +415,14 @@
 	if (MULTICAST(daddr)) {
 		if (!ipc.oif)
 			ipc.oif = inet->mc_index;
-		if (!rfh.saddr)
-			rfh.saddr = inet->mc_addr;
+		if (!saddr)
+			saddr = inet->mc_addr;
 	}
 
 	{
 		struct flowi fl = { .nl_u = { .ip4_u =
 					      { .daddr = daddr,
-						.saddr = rfh.saddr,
+						.saddr = saddr,
 						.tos = tos } },
 				    .oif = ipc.oif };
 		err = ip_route_output_key(&rt, &fl);
@@ -422,14 +438,22 @@
 		goto do_confirm;
 back_from_confirm:
 
-	rfh.iov		= msg->msg_iov;
-	rfh.saddr	= rt->rt_src;
-	rfh.dst		= &rt->u.dst;
-	if (!ipc.addr)
-		ipc.addr = rt->rt_dst;
-	err = ip_build_xmit(sk, inet->hdrincl ? raw_getrawfrag :
-		       	    raw_getfrag, &rfh, len, &ipc, rt, msg->msg_flags);
-
+	if (inet->hdrincl)
+		err = raw_send_hdrinc(sk, msg->msg_iov, len, 
+					rt, msg->msg_flags);
+	
+	 else {
+		if (!ipc.addr)
+			ipc.addr = rt->rt_dst;
+		lock_sock(sk);
+		err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0,
+					&ipc, rt, msg->msg_flags);
+		if (err)
+			ip_flush_pending_frames(sk);
+		else if (!(msg->msg_flags & MSG_MORE))
+			err = ip_push_pending_frames(sk);
+		release_sock(sk);
+	}
 done:
 	if (free)
 		kfree(ipc.opt);
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	Fri Oct 18 21:03:04 2002
+++ b/net/ipv4/tcp.c	Fri Oct 18 21:03:04 2002
@@ -204,6 +204,8 @@
  *		Andi Kleen 	:	Make poll agree with SIGIO
  *	Salvatore Sanfilippo	:	Support SO_LINGER with linger == 1 and
  *					lingertime == 0 (RFC 793 ABORT Call)
+ *	Hirokazu Takahashi	:	Use copy_from_user() instead of
+ *					csum_and_copy_from_user() if possible.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -958,8 +960,8 @@
 	return res;
 }
 
-#define TCP_PAGE(sk)	(tcp_sk(sk)->sndmsg_page)
-#define TCP_OFF(sk)	(tcp_sk(sk)->sndmsg_off)
+#define TCP_PAGE(sk)	(inet_sk(sk)->sndmsg_page)
+#define TCP_OFF(sk)	(inet_sk(sk)->sndmsg_off)
 
 static inline int tcp_copy_to_page(struct sock *sk, char *from,
 				   struct sk_buff *skb, struct page *page,
@@ -968,18 +970,22 @@
 	int err = 0;
 	unsigned int csum;
 
-	csum = csum_and_copy_from_user(from, page_address(page) + off,
+	if (skb->ip_summed == CHECKSUM_NONE) {
+		csum = csum_and_copy_from_user(from, page_address(page) + off,
 				       copy, 0, &err);
-	if (!err) {
-		if (skb->ip_summed == CHECKSUM_NONE)
-			skb->csum = csum_block_add(skb->csum, csum, skb->len);
-		skb->len += copy;
-		skb->data_len += copy;
-		skb->truesize += copy;
-		sk->wmem_queued += copy;
-		sk->forward_alloc -= copy;
+		if (err) return err;
+		skb->csum = csum_block_add(skb->csum, csum, skb->len);
+	} else {
+		if (copy_from_user(page_address(page) + off, from, copy))
+			return -EFAULT;
 	}
-	return err;
+
+	skb->len += copy;
+	skb->data_len += copy;
+	skb->truesize += copy;
+	sk->wmem_queued += copy;
+	sk->forward_alloc -= copy;
+	return 0;
 }
 
 static inline int skb_add_data(struct sk_buff *skb, char *from, int copy)
@@ -988,11 +994,16 @@
 	unsigned int csum;
 	int off = skb->len;
 
-	csum = csum_and_copy_from_user(from, skb_put(skb, copy),
+	if (skb->ip_summed == CHECKSUM_NONE) {
+		csum = csum_and_copy_from_user(from, skb_put(skb, copy),
 				       copy, 0, &err);
-	if (!err) {
-		skb->csum = csum_block_add(skb->csum, csum, off);
-		return 0;
+		if (!err) {
+			skb->csum = csum_block_add(skb->csum, csum, off);
+			return 0;
+		}
+	} else {
+		if (!copy_from_user(skb_put(skb, copy), from, copy))
+			return 0;
 	}
 
 	__skb_trim(skb, off);
@@ -1074,6 +1085,12 @@
 						     0, sk->allocation);
 				if (!skb)
 					goto wait_for_memory;
+
+				/*
+				 * Check whether we can use HW checksum.
+				 */
+				if (sk->route_caps & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM))
+					skb->ip_summed = CHECKSUM_HW;
 
 				skb_entail(sk, tp, skb);
 				copy = mss_now;
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	Fri Oct 18 21:03:04 2002
+++ b/net/ipv4/tcp_ipv4.c	Fri Oct 18 21:03:04 2002
@@ -781,6 +781,7 @@
 
 	__sk_dst_set(sk, &rt->u.dst);
 	tcp_v4_setup_caps(sk, &rt->u.dst);
+	tp->ext_header_len += rt->u.dst.header_len;
 
 	if (!inet->opt || !inet->opt->srr)
 		daddr = rt->rt_dst;
@@ -1187,7 +1188,6 @@
 	arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
 				      skb->nh.iph->saddr, /*XXX*/
 				      sizeof(struct tcphdr), IPPROTO_TCP, 0);
-	arg.n_iov = 1;
 	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
 
 	inet_sk(tcp_socket->sk)->ttl = sysctl_ip_default_ttl;
@@ -1216,7 +1216,6 @@
 
 	arg.iov[0].iov_base = (unsigned char *)&rep;
 	arg.iov[0].iov_len  = sizeof(rep.th);
-	arg.n_iov = 1;
 	if (ts) {
 		rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
 				     (TCPOPT_TIMESTAMP << 8) |
@@ -1577,6 +1576,7 @@
 	newtp->ext_header_len = 0;
 	if (newinet->opt)
 		newtp->ext_header_len = newinet->opt->optlen;
+	newtp->ext_header_len += dst->header_len;
 	newinet->id = newtp->write_seq ^ jiffies;
 
 	tcp_sync_mss(newsk, dst->pmtu);
@@ -2087,8 +2087,8 @@
 		tcp_put_port(sk);
 
 	/* If sendmsg cached page exists, toss it. */
-	if (tp->sndmsg_page)
-		__free_page(tp->sndmsg_page);
+	if (inet_sk(sk)->sndmsg_page)
+		__free_page(inet_sk(sk)->sndmsg_page);
 
 	atomic_dec(&tcp_sockets_allocated);
 
diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c	Fri Oct 18 21:03:07 2002
+++ b/net/ipv4/tcp_minisocks.c	Fri Oct 18 21:03:07 2002
@@ -902,13 +902,13 @@
 	 *                  and the incoming segment acknowledges something not yet
 	 *                  sent (the segment carries an unaccaptable ACK) ...
 	 *                  a reset is sent."
+	 *
+	 * Invalid ACK: reset will be sent by listening socket
 	 */
-	if (!(flg & TCP_FLAG_ACK))
-		return NULL;
-
-	/* Invalid ACK: reset will be sent by listening socket */
-	if (TCP_SKB_CB(skb)->ack_seq != req->snt_isn+1)
+	if ((flg & TCP_FLAG_ACK) &&
+	    (TCP_SKB_CB(skb)->ack_seq != req->snt_isn+1))
 		return sk;
+
 	/* Also, it would be not so bad idea to check rcv_tsecr, which
 	 * is essentially ACK extension and too early or too late values
 	 * should cause reset in unsynchronized states.
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	Fri Oct 18 21:03:03 2002
+++ b/net/ipv4/udp.c	Fri Oct 18 21:03:03 2002
@@ -11,6 +11,7 @@
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  *		Alan Cox, <Alan.Cox@linux.org>
+ *		Hirokazu Takahashi, <taka@valinux.co.jp>
  *
  * Fixes:
  *		Alan Cox	:	verify_area() calls
@@ -62,6 +63,9 @@
  *		Janos Farkas	:	don't deliver multi/broadcasts to a different
  *					bound-to-device socket
  *		Arnaldo C. Melo :	move proc routines to ip_proc.c.
+ *	Hirokazu Takahashi	:	HW checksumming for outgoing UDP
+ *					datagrams.
+ *	Hirokazu Takahashi	:	sendfile() on UDP works now.
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -365,82 +369,120 @@
 	sock_put(sk);
 }
 
-
-static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
-{
-	return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
-}
-
-struct udpfakehdr 
-{
-	struct udphdr uh;
-	u32 saddr;
-	u32 daddr;
-	struct iovec *iov;
-	u32 wcheck;
-};
-
 /*
- *	Copy and checksum a UDP packet from user space into a buffer.
+ * Throw away all pending data and cancel the corking. Socket is locked.
  */
- 
-static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned int fraglen) 
+static void udp_flush_pending_frames(struct sock *sk)
 {
-	struct udpfakehdr *ufh = (struct udpfakehdr *)p;
-	if (offset==0) {
-		if (csum_partial_copy_fromiovecend(to+sizeof(struct udphdr), ufh->iov, offset,
-						   fraglen-sizeof(struct udphdr), &ufh->wcheck))
-			return -EFAULT;
- 		ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
-					   ufh->wcheck);
-		ufh->uh.check = csum_tcpudp_magic(ufh->saddr, ufh->daddr, 
-					  ntohs(ufh->uh.len),
-					  IPPROTO_UDP, ufh->wcheck);
-		if (ufh->uh.check == 0)
-			ufh->uh.check = -1;
-		memcpy(to, ufh, sizeof(struct udphdr));
-		return 0;
+	struct udp_opt *up = udp_sk(sk);
+
+	if (up->pending) {
+		up->pending = 0;
+		ip_flush_pending_frames(sk);
 	}
-	if (csum_partial_copy_fromiovecend(to, ufh->iov, offset-sizeof(struct udphdr),
-					   fraglen, &ufh->wcheck))
-		return -EFAULT;
-	return 0;
 }
 
 /*
- *	Copy a UDP packet from user space into a buffer without checksumming.
+ * Push out all pending data as one UDP datagram. Socket is locked.
  */
- 
-static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset, unsigned int fraglen) 
+static int udp_push_pending_frames(struct sock *sk, struct udp_opt *up)
 {
-	struct udpfakehdr *ufh = (struct udpfakehdr *)p;
+	struct sk_buff *skb;
+	struct udphdr *uh;
+	int err = 0;
 
-	if (offset==0) {
-		memcpy(to, ufh, sizeof(struct udphdr));
-		return memcpy_fromiovecend(to+sizeof(struct udphdr), ufh->iov, offset,
-					   fraglen-sizeof(struct udphdr));
+	/* Grab the skbuff where UDP header space exists. */
+	if ((skb = skb_peek(&sk->write_queue)) == NULL)
+		goto out;
+
+	/*
+	 * Create a UDP header
+	 */
+	uh = skb->h.uh;
+	uh->source = up->sport;
+	uh->dest = up->dport;
+	uh->len = htons(up->len);
+	uh->check = 0;
+
+	if (sk->no_check == UDP_CSUM_NOXMIT) {
+		skb->ip_summed = CHECKSUM_NONE;
+		goto send;
 	}
-	return memcpy_fromiovecend(to, ufh->iov, offset-sizeof(struct udphdr),
-				   fraglen);
+
+	if (skb_queue_len(&sk->write_queue) == 1) {
+		/*
+		 * Only one fragment on the socket.
+		 */
+		if (skb->ip_summed == CHECKSUM_HW) {
+			skb->csum = offsetof(struct udphdr, check);
+			uh->check = ~csum_tcpudp_magic(up->saddr, up->daddr,
+					up->len, IPPROTO_UDP, 0);
+		} else {
+			skb->csum = csum_partial((char *)uh,
+					sizeof(struct udphdr), skb->csum);
+			uh->check = csum_tcpudp_magic(up->saddr, up->daddr,
+					up->len, IPPROTO_UDP, skb->csum);
+			if (uh->check == 0)
+				uh->check = -1;
+		}
+	} else {
+		unsigned int csum = 0;
+		/*
+		 * HW-checksum won't work as there are two or more 
+		 * fragments on the socket so that all csums of sk_buffs
+		 * should be together.
+		 */
+		if (skb->ip_summed == CHECKSUM_HW) {
+			int offset = (unsigned char *)uh - skb->data;
+			skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
+
+			skb->ip_summed = CHECKSUM_NONE;
+		} else {
+			skb->csum = csum_partial((char *)uh,
+					sizeof(struct udphdr), skb->csum);
+		}
+
+		skb_queue_walk(&sk->write_queue, skb) {
+			csum = csum_add(csum, skb->csum);
+		}
+		uh->check = csum_tcpudp_magic(up->saddr, up->daddr,
+				up->len, IPPROTO_UDP, csum);
+		if (uh->check == 0)
+			uh->check = -1;
+	}
+send:
+	err = ip_push_pending_frames(sk);
+out:
+	up->len = 0;
+	up->pending = 0;
+	return err;
+}
+
+
+static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
+{
+	return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
 }
 
 int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		int len)
 {
 	struct inet_opt *inet = inet_sk(sk);
-	int ulen = len + sizeof(struct udphdr);
+	struct udp_opt *up = udp_sk(sk);
+	int ulen = len;
 	struct ipcm_cookie ipc;
-	struct udpfakehdr ufh;
 	struct rtable *rt = NULL;
 	int free = 0;
 	int connected = 0;
-	u32 daddr;
+	u32 daddr, faddr, saddr;
+	u16 dport;
 	u8  tos;
 	int err;
+	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
 
 	/* This check is ONLY to check for arithmetic overflow
 	   on integer(!) len. Not more! Real check will be made
-	   in ip_build_xmit --ANK
+	   in ip_append_* --ANK
 
 	   BTW socket.c -> af_*.c -> ... make multiple
 	   invalid conversions size_t -> int. We MUST repair it f.e.
@@ -459,10 +501,26 @@
 	if (msg->msg_flags&MSG_OOB)	/* Mirror BSD error message compatibility */
 		return -EOPNOTSUPP;
 
+	ipc.opt = NULL;
+
+	if (up->pending) {
+		/*
+		 * There are pending frames.
+	 	 * The socket lock must be held while it's corked.
+		 */
+		lock_sock(sk);
+		if (likely(up->pending))
+ 			goto do_append_data;
+		release_sock(sk);
+
+		NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp cork app bug 1\n"));
+		return -EINVAL;
+	}
+	ulen += sizeof(struct udphdr);
+
 	/*
 	 *	Get and verify the address. 
 	 */
-	 
 	if (msg->msg_name) {
 		struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;
 		if (msg->msg_namelen < sizeof(*usin))
@@ -472,24 +530,22 @@
 				return -EINVAL;
 		}
 
-		ufh.daddr = usin->sin_addr.s_addr;
-		ufh.uh.dest = usin->sin_port;
-		if (ufh.uh.dest == 0)
+		daddr = usin->sin_addr.s_addr;
+		dport = usin->sin_port;
+		if (dport == 0)
 			return -EINVAL;
 	} else {
 		if (sk->state != TCP_ESTABLISHED)
 			return -ENOTCONN;
-		ufh.daddr   = inet->daddr;
-		ufh.uh.dest = inet->dport;
+		daddr = inet->daddr;
+		dport = inet->dport;
 		/* Open fast path for connected socket.
 		   Route will not be used, if at least one option is set.
 		 */
 		connected = 1;
   	}
 	ipc.addr = inet->saddr;
-	ufh.uh.source = inet->sport;
 
-	ipc.opt = NULL;
 	ipc.oif = sk->bound_dev_if;
 	if (msg->msg_controllen) {
 		err = ip_cmsg_send(msg, &ipc);
@@ -502,13 +558,13 @@
 	if (!ipc.opt)
 		ipc.opt = inet->opt;
 
-	ufh.saddr = ipc.addr;
-	ipc.addr = daddr = ufh.daddr;
+	saddr = ipc.addr;
+	ipc.addr = faddr = daddr;
 
 	if (ipc.opt && ipc.opt->srr) {
 		if (!daddr)
 			return -EINVAL;
-		daddr = ipc.opt->faddr;
+		faddr = ipc.opt->faddr;
 		connected = 0;
 	}
 	tos = RT_TOS(inet->tos);
@@ -521,8 +577,8 @@
 	if (MULTICAST(daddr)) {
 		if (!ipc.oif)
 			ipc.oif = inet->mc_index;
-		if (!ufh.saddr)
-			ufh.saddr = inet->mc_addr;
+		if (!saddr)
+			saddr = inet->mc_addr;
 		connected = 0;
 	}
 
@@ -531,8 +587,8 @@
 
 	if (rt == NULL) {
 		struct flowi fl = { .nl_u = { .ip4_u =
-					      { .daddr = daddr,
-						.saddr = ufh.saddr,
+					      { .daddr = faddr,
+						.saddr = saddr,
 						.tos = tos } },
 				    .oif = ipc.oif };
 		err = ip_route_output_key(&rt, &fl);
@@ -550,23 +606,39 @@
 		goto do_confirm;
 back_from_confirm:
 
-	ufh.saddr = rt->rt_src;
+	saddr = rt->rt_src;
 	if (!ipc.addr)
-		ufh.daddr = ipc.addr = rt->rt_dst;
-	ufh.uh.len = htons(ulen);
-	ufh.uh.check = 0;
-	ufh.iov = msg->msg_iov;
-	ufh.wcheck = 0;
-
-	/* RFC1122: OK.  Provides the checksumming facility (MUST) as per */
-	/* 4.1.3.4. It's configurable by the application via setsockopt() */
-	/* (MAY) and it defaults to on (MUST). */
-
-	err = ip_build_xmit(sk,
-			    (sk->no_check == UDP_CSUM_NOXMIT ?
-			     udp_getfrag_nosum :
-			     udp_getfrag),
-			    &ufh, ulen, &ipc, rt, msg->msg_flags);
+		daddr = ipc.addr = rt->rt_dst;
+
+	lock_sock(sk);
+	if (unlikely(up->pending)) {
+		/* The socket is already corked while preparing it. */
+		/* ... which is an evident application bug. --ANK */
+		release_sock(sk);
+
+		NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp cork app bug 2\n"));
+		err = -EINVAL;
+		goto out;
+	}
+	/*
+	 *	Now cork the socket to pend data.
+	 */
+	up->daddr = daddr;
+	up->dport = dport;
+	up->saddr = saddr;
+	up->sport = inet->sport;
+	up->pending = 1;
+
+do_append_data:
+	up->len += ulen;
+	err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, 
+			sizeof(struct udphdr), &ipc, rt, 
+			corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
+	if (err)
+		udp_flush_pending_frames(sk);
+	else if (!corkreq)
+		err = udp_push_pending_frames(sk, up);
+	release_sock(sk);
 
 out:
 	ip_rt_put(rt);
@@ -586,6 +658,52 @@
 	goto out;
 }
 
+int udp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags)
+{
+	struct udp_opt *up = udp_sk(sk);
+	int ret;
+
+	if (!up->pending) {
+		struct msghdr msg = {	.msg_flags = flags|MSG_MORE };
+
+		/* Call udp_sendmsg to specify destination address which
+		 * sendpage interface can't pass.
+		 * This will succeed only when the socket is connected.
+		 */
+		ret = udp_sendmsg(NULL, sk, &msg, 0);
+		if (ret < 0)
+			return ret;
+	}
+
+	lock_sock(sk);
+
+	if (unlikely(!up->pending)) {
+		release_sock(sk);
+
+		NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp cork app bug 3\n"));
+		return -EINVAL;
+	}
+
+	ret = ip_append_page(sk, page, offset, size, flags);
+	if (ret == -EOPNOTSUPP) {
+		release_sock(sk);
+		return sock_no_sendpage(sk->socket, page, offset, size, flags);
+	}
+	if (ret < 0) {
+		udp_flush_pending_frames(sk);
+		goto out;
+	}
+
+	up->len += size;
+	if (!(up->corkflag || (flags&MSG_MORE)))
+		ret = udp_push_pending_frames(sk, up);
+	if (!ret)
+		ret = size;
+out:
+	release_sock(sk);
+	return ret;
+}
+
 /*
  *	IOCTL requests applicable to the UDP protocol
  */
@@ -923,7 +1041,9 @@
 	if (!pskb_may_pull(skb, sizeof(struct udphdr)))
 		goto no_header;
 
-	ulen = ntohs(skb->h.uh->len);
+	uh = skb->h.uh;
+
+	ulen = ntohs(uh->len);
 
 	if (ulen > len || ulen < sizeof(*uh))
 		goto short_packet;
@@ -931,8 +1051,6 @@
 	if (pskb_trim(skb, ulen))
 		goto short_packet;
 
-  	uh = skb->h.uh;
-
 	if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
 		goto csum_error;
 
@@ -962,7 +1080,14 @@
 	return(0);
 
 short_packet:
-	NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "UDP: short packet: %d/%d\n", ulen, len));
+	NETDEBUG(if (net_ratelimit())
+		printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
+			NIPQUAD(saddr),
+			ntohs(uh->source),
+			ulen,
+			len,
+			NIPQUAD(daddr),
+			ntohs(uh->dest)));
 no_header:
 	UDP_INC_STATS_BH(UdpInErrors);
 	kfree_skb(skb);
@@ -985,16 +1110,99 @@
 	return(0);
 }
 
+static int udp_destroy_sock(struct sock *sk)
+{
+	lock_sock(sk);
+	udp_flush_pending_frames(sk);
+	release_sock(sk);
+	return 0;
+}
+
+/*
+ *	Socket option code for UDP
+ */
+static int udp_setsockopt(struct sock *sk, int level, int optname, 
+			  char *optval, int optlen)
+{
+	struct udp_opt *up = udp_sk(sk);
+	int val;
+	int err = 0;
+
+	if (level != SOL_UDP)
+		return ip_setsockopt(sk, level, optname, optval, optlen);
+
+	if(optlen<sizeof(int))
+		return -EINVAL;
+
+	if (get_user(val, (int *)optval))
+		return -EFAULT;
+
+	switch(optname) {
+	case UDP_CORK:
+		if (val != 0) {
+			up->corkflag = 1;
+		} else {
+			up->corkflag = 0;
+			lock_sock(sk);
+			udp_push_pending_frames(sk, up);
+			release_sock(sk);
+		}
+		break;
+		
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	};
+
+	return err;
+}
+
+static int udp_getsockopt(struct sock *sk, int level, int optname, 
+			  char *optval, int *optlen)
+{
+	struct udp_opt *up = udp_sk(sk);
+	int val, len;
+
+	if (level != SOL_UDP)
+		return ip_getsockopt(sk, level, optname, optval, optlen);
+
+	if(get_user(len,optlen))
+		return -EFAULT;
+
+	len = min_t(unsigned int, len, sizeof(int));
+	
+	if(len < 0)
+		return -EINVAL;
+
+	switch(optname) {
+	case UDP_CORK:
+		val = up->corkflag;
+		break;
+
+	default:
+		return -ENOPROTOOPT;
+	};
+
+  	if(put_user(len, optlen))
+  		return -EFAULT;
+	if(copy_to_user(optval, &val,len))
+		return -EFAULT;
+  	return 0;
+}
+
+
 struct proto udp_prot = {
  	.name =		"UDP",
 	.close =	udp_close,
 	.connect =	udp_connect,
 	.disconnect =	udp_disconnect,
 	.ioctl =	udp_ioctl,
-	.setsockopt =	ip_setsockopt,
-	.getsockopt =	ip_getsockopt,
+	.destroy =	udp_destroy_sock,
+	.setsockopt =	udp_setsockopt,
+	.getsockopt =	udp_getsockopt,
 	.sendmsg =	udp_sendmsg,
 	.recvmsg =	udp_recvmsg,
+	.sendpage =	udp_sendpage,
 	.backlog_rcv =	udp_queue_rcv_skb,
 	.hash =		udp_v4_hash,
 	.unhash =	udp_v4_unhash,
diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c
--- a/net/ipv6/mcast.c	Fri Oct 18 21:03:08 2002
+++ b/net/ipv6/mcast.c	Fri Oct 18 21:03:08 2002
@@ -18,6 +18,12 @@
 /* Changes:
  *
  *	yoshfuji	: fix format of router-alert option
+ *	YOSHIFUJI Hideaki @USAGI:
+ *		Fixed source address for MLD message based on
+ *		<draft-ietf-magma-mld-source-02.txt>.
+ *	YOSHIFUJI Hideaki @USAGI:
+ *		- Ignore Queries for invalid addresses.
+ *		- MLD for link-local addresses.
  */
 
 #define __NO_VERSION__
@@ -406,6 +412,7 @@
 	unsigned long resptime;
 	struct inet6_dev *idev;
 	struct icmp6hdr *hdr;
+	int addr_type;
 
 	if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
 		return -EINVAL;
@@ -421,6 +428,11 @@
 	resptime = (resptime<<10)/(1024000/HZ);
 
 	addrp = (struct in6_addr *) (hdr + 1);
+	addr_type = ipv6_addr_type(addrp);
+
+	if (addr_type != IPV6_ADDR_ANY &&
+	    !(addr_type&IPV6_ADDR_MULTICAST))
+		return -EINVAL;
 
 	idev = in6_dev_get(skb->dev);
 
@@ -428,7 +440,7 @@
 		return 0;
 
 	read_lock(&idev->lock);
-	if (ipv6_addr_any(addrp)) {
+	if (addr_type == IPV6_ADDR_ANY) {
 		for (ma = idev->mc_list; ma; ma=ma->next)
 			igmp6_group_queried(ma, resptime);
 	} else {
@@ -452,6 +464,7 @@
 	struct in6_addr *addrp;
 	struct inet6_dev *idev;
 	struct icmp6hdr *hdr;
+	int addr_type;
 
 	/* Our own report looped back. Ignore it. */
 	if (skb->pkt_type == PACKET_LOOPBACK)
@@ -463,7 +476,9 @@
 	hdr = (struct icmp6hdr*) skb->h.raw;
 
 	/* Drop reports with not link local source */
-	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
+	addr_type = ipv6_addr_type(&skb->nh.ipv6h->saddr);
+	if (addr_type != IPV6_ADDR_ANY && 
+	    !(addr_type&IPV6_ADDR_LINKLOCAL))
 		return -EINVAL;
 
 	addrp = (struct in6_addr *) (hdr + 1);
@@ -530,11 +545,11 @@
 	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
-#if MCAST_DEBUG >= 1
-		printk(KERN_DEBUG "igmp6: %s no linklocal address\n",
-		       dev->name);
-#endif
-		goto out;
+		/* <draft-ietf-magma-mld-source-02.txt>:
+		 * use unspecified address as the source address 
+		 * when a valid link-local address is not available.
+		 */
+		memset(&addr_buf, 0, sizeof(addr_buf));
 	}
 
 	ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
@@ -567,11 +582,9 @@
 static void igmp6_join_group(struct ifmcaddr6 *ma)
 {
 	unsigned long delay;
-	int addr_type;
-
-	addr_type = ipv6_addr_type(&ma->mca_addr);
 
-	if ((addr_type & (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_LOOPBACK)))
+	if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
+	    ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
 		return;
 
 	igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
@@ -592,11 +605,8 @@
 
 static void igmp6_leave_group(struct ifmcaddr6 *ma)
 {
-	int addr_type;
-
-	addr_type = ipv6_addr_type(&ma->mca_addr);
-
-	if ((addr_type & IPV6_ADDR_LINKLOCAL))
+	if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
+	    ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
 		return;
 
 	if (ma->mca_flags & MAF_LAST_REPORTER)
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	Fri Oct 18 21:03:05 2002
+++ b/net/ipv6/tcp_ipv6.c	Fri Oct 18 21:03:05 2002
@@ -1876,6 +1876,7 @@
 static int tcp_v6_destroy_sock(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
+	struct inet_opt *inet = inet_sk(sk);
 
 	tcp_clear_xmit_timers(sk);
 
@@ -1893,8 +1894,8 @@
 		tcp_put_port(sk);
 
 	/* If sendmsg cached page exists, toss it. */
-	if (tp->sndmsg_page != NULL)
-		__free_page(tp->sndmsg_page);
+	if (inet->sndmsg_page != NULL)
+		__free_page(inet->sndmsg_page);
 
 	atomic_dec(&tcp_sockets_allocated);
 
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Fri Oct 18 21:03:04 2002
+++ b/net/netsyms.c	Fri Oct 18 21:03:04 2002
@@ -161,6 +161,7 @@
 EXPORT_SYMBOL(sock_kmalloc);
 EXPORT_SYMBOL(sock_kfree_s);
 EXPORT_SYMBOL(sock_map_fd);
+EXPORT_SYMBOL(sockfd_lookup);
 
 #ifdef CONFIG_FILTER
 EXPORT_SYMBOL(sk_run_filter);
@@ -223,9 +224,6 @@
 EXPORT_SYMBOL(vlan_ioctl_hook);
 #endif
 
-EXPORT_SYMBOL(sklist_destroy_socket);
-EXPORT_SYMBOL(sklist_insert_socket);
-
 EXPORT_SYMBOL(scm_detach_fds);
 
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
@@ -433,7 +431,6 @@
 
 EXPORT_SYMBOL(dev_set_allmulti);
 EXPORT_SYMBOL(dev_set_promiscuity);
-EXPORT_SYMBOL(sklist_remove_socket);
 EXPORT_SYMBOL(rtnl_sem);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_unlock);
diff -Nru a/net/sctp/associola.c b/net/sctp/associola.c
--- a/net/sctp/associola.c	Fri Oct 18 21:03:03 2002
+++ b/net/sctp/associola.c	Fri Oct 18 21:03:03 2002
@@ -207,6 +207,7 @@
 	asoc->next_tsn = asoc->c.initial_tsn;
 
 	asoc->ctsn_ack_point = asoc->next_tsn - 1;
+	asoc->highest_sacked = asoc->ctsn_ack_point;
 
 	asoc->unack_data = 0;
 
@@ -472,13 +473,6 @@
 		/* Set a default msg_name for events. */
 		memcpy(&asoc->peer.primary_addr, &peer->ipaddr,
 		       sizeof(sockaddr_storage_t));
-		asoc->peer.active_path = peer;
-		asoc->peer.retran_path = peer;
-	}
-
-	/* If we do not yet have a primary path, set one.  */
-	if (NULL == asoc->peer.primary_path) {
-		asoc->peer.primary_path = peer;
 		asoc->peer.active_path = peer;
 		asoc->peer.retran_path = peer;
 	}
diff -Nru a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
--- a/net/sctp/bind_addr.c	Fri Oct 18 21:03:08 2002
+++ b/net/sctp/bind_addr.c	Fri Oct 18 21:03:08 2002
@@ -199,11 +199,10 @@
 sctpParam_t sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, int *addrs_len,
 				   int priority)
 {
-	sctpParam_t rawaddr;
 	sctpParam_t addrparms;
 	sctpParam_t retval;
 	int addrparms_len;
-	sctpIpAddress_t rawaddr_space;
+	sctp_addr_param_t rawaddr;
 	int len;
 	struct sockaddr_storage_list *addr;
 	struct list_head *pos;
@@ -214,7 +213,7 @@
 
 	/* Allocate enough memory at once. */
 	list_for_each(pos, &bp->address_list) {
-		len += sizeof(sctp_ipv6addr_param_t);
+		len += sizeof(sctp_addr_param_t);
 	}
 
 	addrparms.v = kmalloc(len, priority);
@@ -222,12 +221,11 @@
 		goto end_raw;
 
 	retval = addrparms;
-	rawaddr.v4 = &rawaddr_space.v4;
 
 	list_for_each(pos, &bp->address_list) {
 		addr = list_entry(pos, struct sockaddr_storage_list, list);
-		len = sockaddr2sctp_addr(&addr->a, rawaddr);
-		memcpy(addrparms.v, rawaddr.v, len);
+		len = sockaddr2sctp_addr(&addr->a, &rawaddr);
+		memcpy(addrparms.v, &rawaddr, len);
 		addrparms.v += len;
 		addrparms_len += len;
 	}
@@ -244,33 +242,39 @@
 int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list,
 			   int addrs_len, __u16 port, int priority)
 {
-	sctpParam_t rawaddr;
+	sctp_addr_param_t *rawaddr;
+	sctp_paramhdr_t *param;
 	sockaddr_storage_t addr;
 	int retval = 0;
 	int len;
 
 	/* Convert the raw address to standard address format */
 	while (addrs_len) {
-		rawaddr.v = raw_addr_list;
-		if (SCTP_PARAM_IPV4_ADDRESS==rawaddr.p->type
-		    || SCTP_PARAM_IPV6_ADDRESS==rawaddr.p->type) {
+		param = (sctp_paramhdr_t *)raw_addr_list;
+		rawaddr = (sctp_addr_param_t *)raw_addr_list;
+
+		switch (param->type) {
+		case SCTP_PARAM_IPV4_ADDRESS:			
+		case SCTP_PARAM_IPV6_ADDRESS:
 			sctp_param2sockaddr(&addr, rawaddr, port);
 			retval = sctp_add_bind_addr(bp, &addr, priority);
 			if (retval) {
 				/* Can't finish building the list, clean up. */
 				sctp_bind_addr_clean(bp);
-				break;
+				break;;
 			}
-
-			len = ntohs(rawaddr.p->length);
+			len = ntohs(param->length);
 			addrs_len -= len;
 			raw_addr_list += len;
-		} else {
+			break;
+		default:
 			/* Corrupted raw addr list! */
 			retval = -EINVAL;
 			sctp_bind_addr_clean(bp);
 			break;
 		}
+		if (retval)
+			break;
 	}
 
 	return retval;
diff -Nru a/net/sctp/input.c b/net/sctp/input.c
--- a/net/sctp/input.c	Fri Oct 18 21:03:03 2002
+++ b/net/sctp/input.c	Fri Oct 18 21:03:03 2002
@@ -522,9 +522,9 @@
 }
 
 /* Look up an association. */
-sctp_association_t *__sctp_rcv_lookup_association(const sockaddr_storage_t *laddr,
-						  const sockaddr_storage_t *paddr,
-						  sctp_transport_t **transportp)
+sctp_association_t *__sctp_lookup_association(const sockaddr_storage_t *laddr,
+					      const sockaddr_storage_t *paddr,
+					      sctp_transport_t **transportp)
 {
 	sctp_hashbucket_t *head;
 	sctp_endpoint_common_t *epb;
@@ -557,6 +557,36 @@
 	return asoc;
 }
 
+/* Look up an association. BH-safe. */
+sctp_association_t *sctp_lookup_association(const sockaddr_storage_t *laddr,
+					    const sockaddr_storage_t *paddr,
+					    sctp_transport_t **transportp)
+{
+	sctp_association_t *asoc;
+
+	sctp_local_bh_disable();
+	asoc = __sctp_lookup_association(laddr, paddr, transportp);
+	sctp_local_bh_enable();
+	
+	return asoc;
+}
+
+/* Is there an association matching the given local and peer addresses? */
+int sctp_has_association(const sockaddr_storage_t *laddr,
+			 const sockaddr_storage_t *paddr)
+{
+	sctp_association_t *asoc;
+	sctp_transport_t *transport;
+
+	if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
+		sock_put(asoc->base.sk);
+		sctp_association_put(asoc);
+		return 1;
+	}
+
+	return 0;
+}
+
 /*
  * SCTP Implementors Guide, 2.18 Handling of address
  * parameters within the INIT or INIT-ACK.
@@ -584,14 +614,20 @@
 	struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
 	sctp_chunkhdr_t *ch;
 	__u8 *ch_end, *data;
-	sctpParam_t parm;
+	sctp_paramhdr_t *parm;
 
 	ch = (sctp_chunkhdr_t *) skb->data;
 
 	ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
 
-	if (SCTP_CID_INIT_ACK != ch->type)
+	/* If this is INIT/INIT-ACK look inside the chunk too. */
+	switch (ch->type) {
+	case SCTP_CID_INIT:
+	case SCTP_CID_INIT_ACK:
+		break;
+	default:
 		return NULL;
+	}
 
 	/*
 	 * This code will NOT touch anything inside the chunk--it is
@@ -609,26 +645,25 @@
 	/* Find the start of the TLVs and the end of the chunk.  This is
 	 * the region we search for address parameters.
 	 */
-
 	data = skb->data + sizeof(sctp_init_chunk_t);
 
 	/* See sctp_process_init() for how to go thru TLVs. */
 	while (data < ch_end) {
-		parm.v  = data;
+		parm = (sctp_paramhdr_t *)data;
 
-		if (!parm.p->length)
+		if (!parm->length)
 			break;
 
-		data += WORD_ROUND(ntohs(parm.p->length));
+		data += WORD_ROUND(ntohs(parm->length));
 
 		/* Note: Ignoring hostname addresses. */
-		if ((SCTP_PARAM_IPV4_ADDRESS  != parm.p->type) &&
-		    (SCTP_PARAM_IPV6_ADDRESS != parm.p->type))
+		if ((SCTP_PARAM_IPV4_ADDRESS != parm->type) &&
+		    (SCTP_PARAM_IPV6_ADDRESS != parm->type))
 			continue;
 
-		sctp_param2sockaddr(paddr, parm, ntohs(sh->source));
-
-		asoc = __sctp_rcv_lookup_association(laddr, paddr, transportp);
+		sctp_param2sockaddr(paddr, (sctp_addr_param_t *)parm, 
+				    ntohs(sh->source));
+		asoc = __sctp_lookup_association(laddr, paddr, transportp);
 		if (asoc)
 			return asoc;
 	}
@@ -644,7 +679,7 @@
 {
 	sctp_association_t *asoc;
 
-	asoc = __sctp_rcv_lookup_association(laddr, paddr, transportp);
+	asoc = __sctp_lookup_association(laddr, paddr, transportp);
 
 	/* Further lookup for INIT-ACK packet.
 	 * SCTP Implementors Guide, 2.18 Handling of address
diff -Nru a/net/sctp/output.c b/net/sctp/output.c
--- a/net/sctp/output.c	Fri Oct 18 21:03:03 2002
+++ b/net/sctp/output.c	Fri Oct 18 21:03:03 2002
@@ -530,9 +530,17 @@
 	 * to a given transport address if it has cwnd or more bytes
 	 * of data outstanding to that transport address.
 	 */
-	if (transport->flight_size >= transport->cwnd) {
-		retval = SCTP_XMIT_RWND_FULL;
-		goto finish;
+	/* RFC 7.2.4 & the Implementers Guide 2.8.
+	 *
+	 * 3) ...
+	 *    When a Fast Retransmit is being performed the sender SHOULD
+	 *    ignore the value of cwnd and SHOULD NOT delay retransmission.
+	 */
+	if (!chunk->fast_retransmit) {
+		if (transport->flight_size >= transport->cwnd) {
+			retval = SCTP_XMIT_RWND_FULL;
+			goto finish;
+		}
 	}
 
 	/* Keep track of how many bytes are in flight over this transport. */
diff -Nru a/net/sctp/outqueue.c b/net/sctp/outqueue.c
--- a/net/sctp/outqueue.c	Fri Oct 18 21:03:04 2002
+++ b/net/sctp/outqueue.c	Fri Oct 18 21:03:04 2002
@@ -3,45 +3,45 @@
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001-2002 International Business Machines Corp.
- * 
+ *
  * This file is part of the SCTP kernel reference Implementation
- * 
+ *
  * These functions implement the outqueue class.   The outqueue handles
- * bundling and queueing of outgoing SCTP chunks.  
- * 
- * The SCTP reference implementation is free software; 
- * you can redistribute it and/or modify it under the terms of 
+ * bundling and queueing of outgoing SCTP chunks.
+ *
+ * The SCTP reference implementation 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.
- * 
- * The SCTP reference implementation is distributed in the hope that it 
+ *
+ * The SCTP reference implementation is distributed in the hope that it
  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
  *                 ************************
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.  
- * 
+ * Boston, MA 02111-1307, USA.
+ *
  * Please send any bug reports or fixes you make to the
  * email address(es):
  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
- * 
+ *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
  *
- * Written or modified by: 
+ * Written or modified by:
  *    La Monte H.P. Yarroll <piggy@acm.org>
- *    Karl Knutson          <karl@athena.chicago.il.us> 
+ *    Karl Knutson          <karl@athena.chicago.il.us>
  *    Perry Melange         <pmelange@null.cc.uic.edu>
  *    Xingang Guo           <xingang.guo@intel.com>
  *    Hui Huang 	    <hui.huang@nokia.com>
  *    Sridhar Samudrala     <sri@us.ibm.com>
  *    Jon Grimm             <jgrimm@us.ibm.com>
- *	
+ *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
  */
@@ -59,7 +59,8 @@
 static void sctp_check_transmitted(sctp_outqueue_t *q,
 				   struct list_head *transmitted_queue,
 				   sctp_transport_t *transport,
-				   sctp_sackhdr_t *sack);
+				   sctp_sackhdr_t *sack,
+				   __u32 highest_new_tsn);
 
 /* Generate a new outqueue.  */
 sctp_outqueue_t *sctp_outqueue_new(sctp_association_t *asoc)
@@ -163,7 +164,7 @@
 	if (SCTP_CID_DATA == chunk->chunk_hdr->type) {
 		/* Is it OK to queue data chunks?  */
 		/* From 9. Termination of Association
-		 * 
+		 *
 		 * When either endpoint performs a shutdown, the
 		 * association on each peer will stop accepting new
 		 * data from its user and only deliver data in queue
@@ -276,10 +277,10 @@
 
 }
 
-/* Mark all the eligible packets on a transport for retransmission and force 
+/* Mark all the eligible packets on a transport for retransmission and force
  * one packet out.
  */
-void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport, 
+void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport,
 		     __u8 fast_retransmit)
 {
 	int error = 0;
@@ -514,7 +515,7 @@
  * fragments.  It returns the first fragment with the frag_list field holding
  * the remaining fragments.
  */
-sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, 
+sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk,
 				  size_t max_frag_data_len)
 {
 	sctp_association_t *asoc = chunk->asoc;
@@ -549,12 +550,12 @@
 	/* Make the middle fragments. */
 	while (chunk_data_len > max_frag_data_len) {
 		frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len,
-					  data_ptr, SCTP_DATA_MIDDLE_FRAG, 
+					  data_ptr, SCTP_DATA_MIDDLE_FRAG,
 					  ssn);
 		if (!frag)
 			goto err;
 
-		/* Add the middle fragment to the first fragment's 
+		/* Add the middle fragment to the first fragment's
 		 * frag_list.
 		 */
 		list_add_tail(&frag->frag_list, frag_list);
@@ -773,6 +774,12 @@
 			 */
 			if (packet->has_cookie_echo)
 				goto sctp_flush_out;
+
+			/* Don't send new data if there is still data
+			 * waiting to retransmit.
+			 */
+			if (!list_empty(&q->retransmit))
+				goto sctp_flush_out;
 		}
 
 		/* Finally, transmit new packets.  */
@@ -849,9 +856,9 @@
 				/* We could not append this chunk, so put
 				 * the chunk back on the output queue.
 				 */
-				SCTP_DEBUG_PRINTK("sctp_flush_outqueue: could"
+				SCTP_DEBUG_PRINTK("sctp_flush_outqueue: could "
 					"not transmit TSN: 0x%x, status: %d\n",
-					ntohl(chunk->subh.data_hdr->tsn), 
+					ntohl(chunk->subh.data_hdr->tsn),
 					status);
 				skb_queue_head(queue, (struct sk_buff *)chunk);
 				goto sctp_flush_out;
@@ -911,7 +918,7 @@
 
 	default:
 		/* Do nothing.  */
-		break;		
+		break;
 	}
 
 sctp_flush_out:
@@ -932,7 +939,7 @@
 		if (packet->size != SCTP_IP_OVERHEAD)
 			error = (*q->force_output)(packet);
 	}
-	
+
 	return error;
 }
 
@@ -971,6 +978,36 @@
 	assoc->unack_data = unack_data;
 }
 
+/* Return the highest new tsn that is acknowledged by the given SACK chunk. */
+static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack,
+				  sctp_association_t *asoc)
+{
+	struct list_head *ltransport, *lchunk;
+	sctp_transport_t *transport;
+	sctp_chunk_t *chunk;
+	__u32 highest_new_tsn, tsn;
+	struct list_head *transport_list = &asoc->peer.transport_addr_list;
+
+	highest_new_tsn = ntohl(sack->cum_tsn_ack);
+
+	list_for_each(ltransport, transport_list) {
+		transport = list_entry(ltransport, sctp_transport_t,
+				       transports);
+		list_for_each(lchunk, &transport->transmitted) {
+			chunk = list_entry(lchunk, sctp_chunk_t,
+					   transmitted_list);
+			tsn = ntohl(chunk->subh.data_hdr->tsn);
+
+			if (!chunk->tsn_gap_acked &&
+			    TSN_lt(highest_new_tsn, tsn) &&
+			    sctp_acked(sack, tsn))
+				highest_new_tsn = tsn;
+		}
+	}
+
+	return highest_new_tsn;
+} 
+
 /* This is where we REALLY process a SACK.
  *
  * Process the sack against the outqueue.  Mostly, this just frees
@@ -978,22 +1015,36 @@
  */
 int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack)
 {
+	sctp_association_t *asoc = q->asoc;
+	sctp_transport_t *transport;
 	sctp_chunk_t *tchunk;
 	struct list_head *lchunk, *transport_list, *pos;
-	__u32 tsn;
-	__u32 sack_ctsn;
-	__u32 ctsn;
-	sctp_transport_t *transport;
-	int outstanding;
+	sctp_sack_variable_t *frags = sack->variable;
+	__u32 sack_ctsn, ctsn, tsn;
+	__u32 highest_tsn, highest_new_tsn;
 	__u32 sack_a_rwnd;
+	int outstanding;
 
 	/* Grab the association's destination address list. */
-	transport_list = &q->asoc->peer.transport_addr_list;
+	transport_list = &asoc->peer.transport_addr_list;
+
+	sack_ctsn = ntohl(sack->cum_tsn_ack);
+
+	/* Get the highest TSN in the sack. */
+	highest_tsn = sack_ctsn + 
+		      ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end);
+
+	if (TSN_lt(asoc->highest_sacked, highest_tsn)) {
+		highest_new_tsn = highest_tsn;
+		asoc->highest_sacked = highest_tsn;
+	} else {
+		highest_new_tsn = sctp_highest_new_tsn(sack, asoc);
+	}
 
 	/* Run through the retransmit queue.  Credit bytes received
 	 * and free those chunks that we can.
 	 */
-	sctp_check_transmitted(q, &q->retransmit, NULL, sack);
+	sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn);
 
 	/* Run through the transmitted queue.
 	 * Credit bytes received and free those chunks which we can.
@@ -1003,23 +1054,22 @@
 	list_for_each(pos, transport_list) {
 		transport  = list_entry(pos, sctp_transport_t, transports);
 		sctp_check_transmitted(q, &transport->transmitted,
-				       transport, sack);
+				       transport, sack, highest_new_tsn);
 	}
 
 	/* Move the Cumulative TSN Ack Point if appropriate.  */
-	sack_ctsn = ntohl(sack->cum_tsn_ack);
-	if (TSN_lt(q->asoc->ctsn_ack_point, sack_ctsn))
-		q->asoc->ctsn_ack_point = sack_ctsn;
+	if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn))
+		asoc->ctsn_ack_point = sack_ctsn;
 
 	/* Update unack_data field in the assoc. */
-	sctp_sack_update_unack_data(q->asoc, sack);
+	sctp_sack_update_unack_data(asoc, sack);
 
-	ctsn = q->asoc->ctsn_ack_point;
+	ctsn = asoc->ctsn_ack_point;
 
 	SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n",
 			  __FUNCTION__, sack_ctsn);
 	SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association "
-			  "%p is 0x%x.\n", __FUNCTION__, q->asoc, ctsn);
+			  "%p is 0x%x.\n", __FUNCTION__, asoc, ctsn);
 
 	/* Throw away stuff rotting on the sack queue.  */
 	list_for_each(lchunk, &q->sacked) {
@@ -1045,7 +1095,7 @@
 		sack_a_rwnd = 0;
 	}
 
-	q->asoc->peer.rwnd = sack_a_rwnd;
+	asoc->peer.rwnd = sack_a_rwnd;
 
 	/* See if all chunks are acked.
 	 * Make sure the empty queue handler will get run later.
@@ -1054,14 +1104,14 @@
 	if (!q->empty)
 		goto finish;
 
-	list_for_each(pos, transport_list) {		
+	list_for_each(pos, transport_list) {
 		transport  = list_entry(pos, sctp_transport_t, transports);
 		q->empty = q->empty && list_empty(&transport->transmitted);
 		if (!q->empty)
 			goto finish;
 	}
 
-	SCTP_DEBUG_PRINTK("sack queue is empty.\n");      
+	SCTP_DEBUG_PRINTK("sack queue is empty.\n");
 finish:
 	return q->empty;
 }
@@ -1092,7 +1142,8 @@
 static void sctp_check_transmitted(sctp_outqueue_t *q,
 				   struct list_head *transmitted_queue,
 				   sctp_transport_t *transport,
-				   sctp_sackhdr_t *sack)
+				   sctp_sackhdr_t *sack,
+				   __u32 highest_new_tsn_in_sack)
 {
 	struct list_head *lchunk;
 	sctp_chunk_t *tchunk;
@@ -1100,7 +1151,6 @@
 	__u32 tsn;
 	__u32 sack_ctsn;
 	__u32 rtt;
-	__u32 highest_new_tsn_in_sack;
 	__u8 restart_timer = 0;
 	__u8 do_fast_retransmit = 0;
 	int bytes_acked = 0;
@@ -1121,7 +1171,6 @@
 #endif /* SCTP_DEBUG */
 
 	sack_ctsn = ntohl(sack->cum_tsn_ack);
-	highest_new_tsn_in_sack = sack_ctsn;
 
 	INIT_LIST_HEAD(&tlist);
 
@@ -1144,8 +1193,8 @@
 				 * 6.3.1 C5) Karn's algorithm: RTT measurements
 				 * MUST NOT be made using packets that were
 				 * retransmitted (and thus for which it is
-				 * ambiguous whether the reply was for the 
-				 * first instance of the packet or a later 
+				 * ambiguous whether the reply was for the
+				 * first instance of the packet or a later
 				 * instance).
 				 */
 			   	if ((!tchunk->tsn_gap_acked) &&
@@ -1181,23 +1230,19 @@
 				 * 'Stray DATA chunk(s)' record the highest TSN
 				 * reported as newly acknowledged, call this
 				 * value 'HighestTSNinSack'. A newly
-				 * acknowledged DATA chunk is one not 
+				 * acknowledged DATA chunk is one not
 				 * previously acknowledged in a SACK.
 				 *
 				 * When the SCTP sender of data receives a SACK
 				 * chunk that acknowledges, for the first time,
 				 * the receipt of a DATA chunk, all the still
-				 * unacknowledged DATA chunks whose TSN is 
-				 * older than that newly acknowledged DATA 
+				 * unacknowledged DATA chunks whose TSN is
+				 * older than that newly acknowledged DATA
 				 * chunk, are qualified as 'Stray DATA chunks'.
 				 */
 				if (!tchunk->tsn_gap_acked) {
 					tchunk->tsn_gap_acked = 1;
 					bytes_acked += sctp_data_size(tchunk);
-					if (TSN_lt(highest_new_tsn_in_sack,
-						   tsn)) {
-						highest_new_tsn_in_sack = tsn;
-					}
 				}
 				list_add_tail(lchunk, &tlist);
 			}
@@ -1258,10 +1303,10 @@
 
 				/* RFC 2960 6.3.2 Retransmission Timer Rules
 				 *
-				 * R4) Whenever a SACK is received missing a 
-				 * TSN that was previously acknowledged via a 
-				 * Gap Ack Block, start T3-rtx for the 
-				 * destination address to which the DATA 
+				 * R4) Whenever a SACK is received missing a
+				 * TSN that was previously acknowledged via a
+				 * Gap Ack Block, start T3-rtx for the
+				 * destination address to which the DATA
 				 * chunk was originally
 				 * transmitted if it is not already running.
 				 */
diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c	Fri Oct 18 21:03:03 2002
+++ b/net/sctp/sm_make_chunk.c	Fri Oct 18 21:03:03 2002
@@ -1454,7 +1454,7 @@
 			return 0;
 
 	} /* for (loop through all parameters) */
-	 
+
 	return 1;
 }
 
@@ -1710,6 +1710,7 @@
 		       sctp_cid_t cid, int priority)
 {
 	sockaddr_storage_t addr;
+	sctp_addr_param_t *addrparm;
 	int j;
 	int i;
 	int retval = 1;
@@ -1721,24 +1722,23 @@
 	 */
 	switch (param.p->type) {
 	case SCTP_PARAM_IPV4_ADDRESS:
-		if (SCTP_CID_INIT != cid) {
-			sctp_param2sockaddr(&addr, param, asoc->peer.port);
-			scope = sctp_scope(peer_addr);
-			if (sctp_in_scope(&addr, scope))
-				sctp_assoc_add_peer(asoc, &addr, priority);
-		}
+		addrparm = (sctp_addr_param_t *)param.v;
+		sctp_param2sockaddr(&addr, addrparm, asoc->peer.port);
+		scope = sctp_scope(peer_addr);
+		if (sctp_in_scope(&addr, scope))
+			sctp_assoc_add_peer(asoc, &addr, priority);
 		break;
 
 	case SCTP_PARAM_IPV6_ADDRESS:
-		if (SCTP_CID_INIT != cid) {
-			if (PF_INET6 == asoc->base.sk->family) {
-				sctp_param2sockaddr(&addr, param,
-						    asoc->peer.port);
-				scope = sctp_scope(peer_addr);
-				if (sctp_in_scope(&addr, scope))
-					sctp_assoc_add_peer(asoc, &addr,
-							    priority);
-			}
+		/* Rethink this as we may need to keep for
+		 * restart considerations.
+		 */
+		if (PF_INET6 == asoc->base.sk->family) {
+			addrparm = (sctp_addr_param_t *)param.v;
+			sctp_param2sockaddr(&addr, addrparm, asoc->peer.port);
+			scope = sctp_scope(peer_addr);
+			if (sctp_in_scope(&addr, scope))
+				sctp_assoc_add_peer(asoc, &addr, priority);
 		}
 		break;
 
@@ -1833,8 +1833,7 @@
 /* Select an initial TSN to send during startup.  */
 __u32 sctp_generate_tsn(const sctp_endpoint_t *ep)
 {
-	/* I believe that this random number generator complies with RFC1750.  */
-  	__u32 retval;
+	__u32 retval;
 
 	get_random_bytes(&retval, sizeof(__u32));
 	return retval;
@@ -1845,26 +1844,27 @@
  ********************************************************************/
 
 /* Convert from an SCTP IP parameter to a sockaddr_storage_t.  */
-void sctp_param2sockaddr(sockaddr_storage_t *addr, sctpParam_t param, __u16 port)
+void sctp_param2sockaddr(sockaddr_storage_t *addr, sctp_addr_param_t *param,
+			 __u16 port)
 {
-	switch(param.p->type) {
+	switch(param->v4.param_hdr.type) {
 	case SCTP_PARAM_IPV4_ADDRESS:
 		addr->v4.sin_family = AF_INET;
 		addr->v4.sin_port = port;
-		addr->v4.sin_addr.s_addr = param.v4->addr.s_addr;
+		addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
 		break;
 
 	case SCTP_PARAM_IPV6_ADDRESS:
 		addr->v6.sin6_family = AF_INET6;
 		addr->v6.sin6_port = port;
 		addr->v6.sin6_flowinfo = 0; /* BUG */
-		addr->v6.sin6_addr = param.v6->addr;
+		addr->v6.sin6_addr = param->v6.addr;
 		addr->v6.sin6_scope_id = 0; /* BUG */
 		break;
 
 	default:
 		SCTP_DEBUG_PRINTK("Illegal address type %d\n",
-				  ntohs(param.p->type));
+				  ntohs(param->v4.param_hdr.type));
 		break;
 	};
 }
@@ -1904,11 +1904,9 @@
 	case 4:
 		family = AF_INET;
 		break;
-
 	case 6:
 		family = AF_INET6;
 		break;
-
 	default:
 		family = 0;
 		break;
@@ -1917,25 +1915,26 @@
 	return family;
 }
 
-/* Convert a sockaddr_in to  IP address in an SCTP para.  */
-/* Returns true if a valid conversion was possible.  */
-int sockaddr2sctp_addr(const sockaddr_storage_t *sa, sctpParam_t p)
+/* Convert a sockaddr_in to an IP address in an SCTP param.
+ * Returns len if a valid conversion was possible.  
+ */
+int sockaddr2sctp_addr(const sockaddr_storage_t *sa, sctp_addr_param_t *p)
 {
 	int len = 0;
 
 	switch (sa->v4.sin_family) {
 	case AF_INET:
-		p.p->type = SCTP_PARAM_IPV4_ADDRESS;
-		p.p->length = ntohs(sizeof(sctp_ipv4addr_param_t));
+		p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
+		p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t));
 		len = sizeof(sctp_ipv4addr_param_t);
-		p.v4->addr.s_addr = sa->v4.sin_addr.s_addr;
+		p->v4.addr.s_addr = sa->v4.sin_addr.s_addr;
 		break;
 
 	case AF_INET6:
-		p.p->type = SCTP_PARAM_IPV6_ADDRESS;
-		p.p->length = ntohs(sizeof(sctp_ipv6addr_param_t));
+		p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
+		p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t));
 		len = sizeof(sctp_ipv6addr_param_t);
-		p.v6->addr = *(&sa->v6.sin6_addr);
+		p->v6.addr = *(&sa->v6.sin6_addr);
 		break;
 
 	default:
diff -Nru a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
--- a/net/sctp/sm_sideeffect.c	Fri Oct 18 21:03:06 2002
+++ b/net/sctp/sm_sideeffect.c	Fri Oct 18 21:03:06 2002
@@ -1118,7 +1118,8 @@
 }
 
 /* Helper function to handle the reception of an HEARTBEAT ACK.  */
-static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, sctp_association_t *asoc,
+static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
+				  sctp_association_t *asoc,
 				  sctp_transport_t *t, sctp_chunk_t *chunk)
 {
 	sctp_sender_hb_info_t *hbinfo;
@@ -1164,7 +1165,8 @@
 }
 
 /* Helper function to process the process SACK command.  */
-static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, sctp_association_t *asoc,
+static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
+				 sctp_association_t *asoc,
 				 sctp_sackhdr_t *sackh)
 {
 	int err;
diff -Nru a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
--- a/net/sctp/sm_statefuns.c	Fri Oct 18 21:03:03 2002
+++ b/net/sctp/sm_statefuns.c	Fri Oct 18 21:03:03 2002
@@ -110,18 +110,7 @@
 	if (!chunk->singleton)
 		return SCTP_DISPOSITION_VIOLATION;
 
-	/* RFC 2960 8.5.1 Exceptions in Verification Tag Rules
-	 *
-	 * (C) The receiver of a SHUTDOWN COMPLETE shall accept the
-	 * packet if the Verification Tag field of the packet
-	 * matches its own tag OR it is set to its peer's tag and
-	 * the T bit is set in the Chunk Flags.  Otherwise, the
-	 * receiver MUST silently discard the packet and take no
-	 * further action....
-	 */
-	if ((ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) &&
-	    !(sctp_test_T_bit(chunk) ||
-	      (ntohl(chunk->sctp_hdr->vtag) != asoc->peer.i.init_tag)))
+	if (!sctp_vtag_verify_either(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	/* RFC 2960 10.2 SCTP-to-ULP
@@ -873,6 +862,105 @@
 	return SCTP_DISPOSITION_CONSUME;
 }
 
+/* Helper function to send out an abort for the restart
+ * condition.
+ */
+static int sctp_sf_send_restart_abort(sockaddr_storage_t *ssa, 
+				      sctp_chunk_t *init,
+				      sctp_cmd_seq_t *commands) 
+{
+	int len;
+	sctp_packet_t *pkt;
+	sctp_addr_param_t *addrparm;
+	sctp_errhdr_t *errhdr;
+	sctp_endpoint_t *ep;
+	char buffer[sizeof(sctp_errhdr_t) + sizeof(sctp_addr_param_t)];
+
+	/* Build the error on the stack.   We are way to malloc
+	 * malloc crazy throughout the code today.
+	 */
+	errhdr = (sctp_errhdr_t *)buffer;
+	addrparm = (sctp_addr_param_t *)errhdr->variable;
+	
+	/* Copy into a parm format. */
+	len = sockaddr2sctp_addr(ssa, addrparm);
+	len += sizeof(sctp_errhdr_t);
+
+	errhdr->cause = SCTP_ERROR_RESTART;
+	errhdr->length = htons(len);
+
+	/* Assign to the control socket. */
+	ep = sctp_sk((sctp_get_ctl_sock()))->ep;
+
+	/* Association is NULL since this may be a restart attack and we
+	 * want to send back the attacker's vtag.
+	 */
+	pkt = sctp_abort_pkt_new(ep, NULL, init, errhdr, len);
+
+	if (!pkt) 
+		goto out;
+	sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt));
+
+	/* Discard the rest of the inbound packet. */
+	sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
+
+out:
+	/* Even if there is no memory, treat as a failure so
+	 * the packet will get dropped. 
+	 */
+	return 0;
+}
+
+/* A restart is occuring, check to make sure no new addresses 
+ * are being added as we may be under a takeover attack.
+ */
+static int sctp_sf_check_restart_addrs(const sctp_association_t *new_asoc,
+				       const sctp_association_t *asoc,
+				       sctp_chunk_t *init,
+				       sctp_cmd_seq_t *commands) 
+{
+	sctp_transport_t *new_addr, *addr;
+	struct list_head *pos, *pos2;
+	int found;
+
+	/* Implementor's Guide - Sectin 5.2.2
+	 * ...
+	 * Before responding the endpoint MUST check to see if the
+	 * unexpected INIT adds new addresses to the association. If new
+	 * addresses are added to the association, the endpoint MUST respond
+	 * with an ABORT..
+	 */
+
+	/* Search through all current addresses and make sure
+	 * we aren't adding any new ones.
+	 */
+	new_addr = 0;
+	found = 0;
+
+	list_for_each(pos, &new_asoc->peer.transport_addr_list) {
+		new_addr = list_entry(pos, sctp_transport_t, transports);
+		found = 0;
+		list_for_each(pos2, &asoc->peer.transport_addr_list) {
+			addr = list_entry(pos2, sctp_transport_t, transports);
+			if (sctp_cmp_addr_exact(&new_addr->ipaddr,
+						&addr->ipaddr)) {
+				found = 1;
+				break;
+			}
+		}
+		if (!found)
+			break;
+	}
+
+	/* If a new address was added, ABORT the sender. */
+	if (!found && new_addr) {
+		sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands);
+	}
+	
+	/* Return success if all addresses were found. */   
+	return found;
+}
+
 /* Populate the verification/tie tags based on overlapping INIT
  * scenario.
  *
@@ -969,6 +1057,7 @@
 	const sctp_subtype_t type,
 	void *arg, sctp_cmd_seq_t *commands)
 {
+	sctp_disposition_t retval;
 	sctp_chunk_t *chunk = arg;
 	sctp_chunk_t *repl;
 	sctp_association_t *new_asoc;
@@ -1006,15 +1095,14 @@
 					ntohs(err_chunk->chunk_hdr->length) -
 					sizeof(sctp_chunkhdr_t));
 
-			sctp_free_chunk(err_chunk);
-
 			if (packet) {
 				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
 						SCTP_PACKET(packet));
-				return SCTP_DISPOSITION_CONSUME;
+				retval = SCTP_DISPOSITION_CONSUME;
 			} else {
-				return SCTP_DISPOSITION_NOMEM;
+				retval = SCTP_DISPOSITION_NOMEM;
 			}
+			goto cleanup;
 		} else {
 			return sctp_sf_tabort_8_4_8(ep, asoc, type, arg,
 						    commands);
@@ -1039,6 +1127,19 @@
 	sctp_process_init(new_asoc, chunk->chunk_hdr->type, sctp_source(chunk),
 			  (sctp_init_chunk_t *)chunk->chunk_hdr, GFP_ATOMIC);
 
+	/* Make sure no new addresses are being added during the
+	 * restart.   Do not do this check for COOKIE-WAIT state,
+	 * since there are no peer addresses to check against.
+	 * Upon return an ABORT will have been sent if needed.  
+	 */
+	if (asoc->state != SCTP_STATE_COOKIE_WAIT) {
+		if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, 
+						 commands)) {
+			retval = SCTP_DISPOSITION_CONSUME;
+			goto cleanup_asoc;
+		}
+	}
+
 	sctp_tietags_populate(new_asoc, asoc);
 
 	/* B) "Z" shall respond immediately with an INIT ACK chunk.  */
@@ -1086,13 +1187,18 @@
 	 * Otherwise, "Z" will be vulnerable to resource attacks.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
-	return SCTP_DISPOSITION_CONSUME;
+	retval = SCTP_DISPOSITION_CONSUME;
 
-nomem:
+cleanup:
 	if (err_chunk)
 		sctp_free_chunk(err_chunk);
-
-	return SCTP_DISPOSITION_NOMEM;
+	return retval;
+nomem:
+	retval = SCTP_DISPOSITION_NOMEM;
+	goto cleanup;
+cleanup_asoc:
+	sctp_association_free(new_asoc);
+	goto cleanup;
 }
 
 /*
@@ -1198,6 +1304,8 @@
 	return sctp_sf_do_unexpected_init(ep, asoc, type, arg, commands);
 }
 
+
+
 /* Unexpected COOKIE-ECHO handlerfor peer restart (Table 2, action 'A')
  *
  * Section 5.2.4
@@ -1212,9 +1320,6 @@
 	sctp_init_chunk_t *peer_init;
 	sctp_ulpevent_t *ev;
 	sctp_chunk_t *repl;
-	sctp_transport_t *new_addr, *addr;
-	struct list_head *pos, *pos2, *temp;
-	int found, error;
 
 	/* new_asoc is a brand-new association, so these are not yet
 	 * side effects--it is safe to run them here.
@@ -1223,57 +1328,14 @@
 	sctp_process_init(new_asoc, chunk->chunk_hdr->type,
 			  sctp_source(chunk), peer_init, GFP_ATOMIC);
 
-	/* Make sure peer is not adding new addresses.  */
-	found = 0;
-	new_addr = NULL;
-	list_for_each(pos, &new_asoc->peer.transport_addr_list) {
-		new_addr = list_entry(pos, sctp_transport_t, transports);
-		found = 1;
-		list_for_each_safe(pos2, temp, 
-				   &asoc->peer.transport_addr_list) {
-			addr = list_entry(pos2, sctp_transport_t, transports);
-			if (!sctp_cmp_addr_exact(&new_addr->ipaddr,
-						 &addr->ipaddr)) {
-				found = 0;
-				break;
-			}
-		}
-		if (!found)
-			break;
-	}
-
-	if (!found) {
-		sctp_bind_addr_t *bp;
-		sctpParam_t rawaddr;
-		int len;
-
-		bp = sctp_bind_addr_new(GFP_ATOMIC);
-		if (!bp)
-			goto nomem;
-
-		error = sctp_add_bind_addr(bp, &new_addr->ipaddr, GFP_ATOMIC);
-		if (error)
-			goto nomem_add;
-
-		rawaddr = sctp_bind_addrs_to_raw(bp, &len, GFP_ATOMIC);
-		if (!rawaddr.v)
-			goto nomem_raw;
-
-		repl = sctp_make_abort(asoc, chunk, len+sizeof(sctp_errhdr_t));
-		if (!repl)
-			goto nomem_abort;
-		sctp_init_cause(repl, SCTP_ERROR_RESTART, rawaddr.v, len);
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+	/* Make sure no new addresses are being added during the
+	 * restart.  Though this is a pretty complicated attack
+	 * since you'd have to get inside the cookie.
+	 */
+	if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) {
+		printk("cookie echo check\n"); 
 		return SCTP_DISPOSITION_CONSUME;
-
-	nomem_abort:
-		kfree(rawaddr.v);
-
-	nomem_raw:
-	nomem_add:
-		sctp_bind_addr_free(bp);
-		goto nomem;
-	}
+	}	
 
 	/* For now, fail any unsent/unacked data.  Consider the optional
 	 * choice of resending of this data.
@@ -1302,7 +1364,6 @@
 
 nomem_ev:
 	sctp_free_chunk(repl);
-
 nomem:
 	return SCTP_DISPOSITION_NOMEM;
 }
@@ -1564,6 +1625,10 @@
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
+	sctp_chunk_t *chunk = arg;
+
+	if (!sctp_vtag_verify_either(chunk, asoc))
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	/* Stop the T5-shutdown guard timer.  */
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -1583,6 +1648,10 @@
 					       void *arg,
 					       sctp_cmd_seq_t *commands)
 {
+	sctp_chunk_t *chunk = arg;
+
+	if (!sctp_vtag_verify_either(chunk, asoc))
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	/* Stop the T2-shutdown timer. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -1754,7 +1823,12 @@
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	/* ASSOC_FAILED will DELETE_TCB. */
+	sctp_chunk_t *chunk = arg;
+
+	if (!sctp_vtag_verify_either(chunk, asoc))
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ 	/* ASSOC_FAILED will DELETE_TCB. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
 
 	/* BUG?  This does not look complete... */
@@ -1772,8 +1846,10 @@
 					     void *arg,
 					     sctp_cmd_seq_t *commands)
 {
-	/* Check the verification tag.  */
-	/* BUG: WRITE ME. */
+	sctp_chunk_t *chunk = arg;
+
+	if (!sctp_vtag_verify_either(chunk, asoc))
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
 			SCTP_STATE(SCTP_STATE_CLOSED));
@@ -2526,7 +2602,7 @@
 	if (packet) {
 		/* Make an ABORT. The T bit will be set if the asoc
 		 * is NULL.
-         	 */
+		 */
         	abort = sctp_make_abort(asoc, chunk, 0);
 		if (!abort) {
 			sctp_ootb_pkt_free(packet);
@@ -2699,13 +2775,6 @@
  *   the Verification Tag received in the SHUTDOWN ACK and set the
  *   T-bit in the Chunk Flags to indicate that no TCB was found.
  *
- * Verification Tag:  8.5.1 E) Rules for packet carrying a SHUTDOWN ACK
- *   If the receiver is in COOKIE-ECHOED or COOKIE-WAIT state the
- *   procedures in section 8.4 SHOULD be followed, in other words it
- *   should be treated as an Out Of The Blue packet.
- *   [This means that we do NOT check the Verification Tag on these
- *   chunks. --piggy ]
- *
  * Inputs
  * (endpoint, asoc, type, arg, commands)
  *
@@ -2751,6 +2820,31 @@
 }
 
 /*
+ * Handle SHUTDOWN ACK in COOKIE_ECHOED or COOKIE_WAIT state.
+ *
+ * Verification Tag:  8.5.1 E) Rules for packet carrying a SHUTDOWN ACK
+ *   If the receiver is in COOKIE-ECHOED or COOKIE-WAIT state the
+ *   procedures in section 8.4 SHOULD be followed, in other words it
+ *   should be treated as an Out Of The Blue packet.
+ *   [This means that we do NOT check the Verification Tag on these
+ *   chunks. --piggy ]
+ *
+ */
+sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const sctp_endpoint_t *ep,
+				      const sctp_association_t *asoc,
+				      const sctp_subtype_t type,
+				      void *arg,
+				      sctp_cmd_seq_t *commands)
+{
+	/* Although we do have an association in this case, it corresponds
+	 * to a restarted association. So the packet is treated as an OOTB
+	 * packet and the state function that handles OOTB SHUTDOWN_ACK is
+	 * called with a NULL association.
+	 */
+	return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands);
+}
+
+/*
  * Process an unknown chunk.
  *
  * Section: 3.2. Also, 2.1 in the implementor's guide.
@@ -2881,12 +2975,11 @@
  *
  * The return value is the disposition of the chunk.
  */
-sctp_disposition_t
-sctp_sf_pdiscard(const sctp_endpoint_t *ep,
-		 const sctp_association_t *asoc,
-		 const sctp_subtype_t type,
-		 void *arg,
-		 sctp_cmd_seq_t *commands)
+sctp_disposition_t sctp_sf_pdiscard(const sctp_endpoint_t *ep,
+				    const sctp_association_t *asoc,
+				    const sctp_subtype_t type,
+				    void *arg,
+				    sctp_cmd_seq_t *commands)
 {
 	sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
 
@@ -4090,10 +4183,10 @@
  * error causes.
  */
 sctp_packet_t *sctp_abort_pkt_new(const sctp_endpoint_t *ep,
-				 const sctp_association_t *asoc,
-				 sctp_chunk_t *chunk,
-				 const void *payload,
-				 size_t paylen)
+				  const sctp_association_t *asoc,
+				  sctp_chunk_t *chunk,
+				  const void *payload,
+				  size_t paylen)
 {
 	sctp_packet_t *packet;
 	sctp_chunk_t *abort;
@@ -4126,7 +4219,7 @@
 
 /* Allocate a packet for responding in the OOTB conditions.  */
 sctp_packet_t *sctp_ootb_pkt_new(const sctp_association_t *asoc,
-					const sctp_chunk_t *chunk)
+				 const sctp_chunk_t *chunk)
 {
 	sctp_packet_t *packet;
 	sctp_transport_t *transport;
@@ -4144,7 +4237,14 @@
 	if (asoc) {
 		vtag = asoc->peer.i.init_tag;
 	} else {
-		vtag = ntohl(chunk->sctp_hdr->vtag);
+		/* Special case the INIT as there is no vtag yet. */
+		if (SCTP_CID_INIT == chunk->chunk_hdr->type) {
+			sctp_init_chunk_t *init;
+			init = (sctp_init_chunk_t *)chunk->chunk_hdr;
+			vtag = ntohl(init->init_hdr.init_tag);
+		} else {
+			vtag = ntohl(chunk->sctp_hdr->vtag);
+		}
 	}
 
 	/* Make a transport for the bucket, Eliza... */
diff -Nru a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
--- a/net/sctp/sm_statetable.c	Fri Oct 18 21:03:04 2002
+++ b/net/sctp/sm_statetable.c	Fri Oct 18 21:03:04 2002
@@ -271,9 +271,9 @@
 	/* SCTP_STATE_CLOSED */ \
 	{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
 	/* SCTP_STATE_COOKIE_WAIT */ \
-	{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+	{.fn = sctp_sf_do_8_5_1_E_sa, .name = "sctp_sf_do_8_5_1_E_sa"}, \
 	/* SCTP_STATE_COOKIE_ECHOED */ \
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	{.fn = sctp_sf_do_8_5_1_E_sa, .name = "sctp_sf_do_8_5_1_E_sa"}, \
 	/* SCTP_STATE_ESTABLISHED */ \
 	{.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
 	/* SCTP_STATE_SHUTDOWN_PENDING */ \
diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c	Fri Oct 18 21:03:08 2002
+++ b/net/sctp/socket.c	Fri Oct 18 21:03:08 2002
@@ -726,9 +726,9 @@
  *  flags   - flags sent or received with the user message, see Section
  *            5 for complete description of the flags.
  *
- * NB: The argument 'msg' is a user space address.
+ * Note:  This function could use a rewrite especially when explicit
+ * connect support comes in.
  */
-/* BUG:  We do not implement timeouts.  */
 /* BUG:  We do not implement the equivalent of wait_for_tcp_memory(). */
 
 SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *);
@@ -738,7 +738,7 @@
 {
 	sctp_opt_t *sp;
 	sctp_endpoint_t *ep;
-	sctp_association_t *asoc = NULL;
+	sctp_association_t *new_asoc=NULL, *asoc=NULL;
 	sctp_transport_t *transport;
 	sctp_chunk_t *chunk = NULL;
 	sockaddr_storage_t to;
@@ -821,7 +821,32 @@
 
 	/* If a msg_name has been specified, assume this is to be used.  */
 	if (msg_name) {
+		/* Look for a matching association on the endpoint. */
 		asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
+		if (!asoc) {
+			struct list_head *pos;
+			struct sockaddr_storage_list *addr;
+			sctp_bind_addr_t *bp = &ep->base.bind_addr;
+
+			sctp_read_lock(&ep->base.addr_lock);
+
+			/* If we could not find a matching association on
+			 * the endpoint, make sure that there is no peeled-
+			 * off association.
+			 */ 
+			list_for_each(pos, &bp->address_list) {
+				addr = list_entry(pos,
+						  struct sockaddr_storage_list,
+						  list);
+				if (sctp_has_association(&addr->a, &to)) {
+					err = -EINVAL;
+					sctp_read_unlock(&ep->base.addr_lock);
+					goto out_unlock;
+				}
+			}
+
+			sctp_read_unlock(&ep->base.addr_lock);
+		}
 	} else {
 		/* For a peeled-off socket, ignore any associd specified by
 		 * the user with SNDRCVINFO.
@@ -907,11 +932,12 @@
 		}
 
 		scope = sctp_scope(&to);
-		asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
-		if (!asoc) {
+		new_asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
+		if (!new_asoc) {
 			err = -ENOMEM;
 			goto out_unlock;
 		}
+		asoc = new_asoc;
 
 		/* If the SCTP_INIT ancillary data is specified, set all
 		 * the association init values accordingly.
@@ -946,7 +972,7 @@
 	}
 
 	/* ASSERT: we have a valid association at this point.  */
-	SCTP_DEBUG_PRINTK("We have a valid association. \n");
+	SCTP_DEBUG_PRINTK("We have a valid association.\n");
 
 	/* API 7.1.7, the sndbuf size per association bounds the
 	 * maximum size of data that can be sent in a single send call.
@@ -1054,10 +1080,16 @@
 		err = msg_len;
 		goto out_unlock;
 	}
+	/* If we are already past ASSOCIATE, the lower
+	 * layers are responsible for its cleanup.
+	 */
+	goto out_free_chunk;
 
 out_free:
-	if (SCTP_STATE_CLOSED == asoc->state)
+	if (new_asoc)
 		sctp_association_free(asoc);
+
+out_free_chunk:
 	if (chunk)
 		sctp_free_chunk(chunk);
 
@@ -1577,6 +1609,8 @@
 	sctp_endpoint_t *newep;
 	sctp_opt_t *oldsp = sctp_sk(oldsk);
 	sctp_opt_t *newsp;
+	struct sk_buff *skb, *tmp;
+	sctp_ulpevent_t *event;
 	int err = 0;
 
 	/* An association cannot be branched off from an already peeled-off
@@ -1606,6 +1640,17 @@
 	 */
 	newsp->ep = newep;
 
+	/* Move any messages in the old socket's receive queue that are for the
+	 * peeled off association to the new socket's receive queue.
+	 */
+	sctp_skb_for_each(skb, &oldsk->receive_queue, tmp) {
+		event = (sctp_ulpevent_t *)skb->cb;
+		if (event->asoc == assoc) {
+			__skb_unlink(skb, skb->list);
+			__skb_queue_tail(&newsk->receive_queue, skb);
+		}
+	}
+
 	/* Set the type of socket to indicate that it is peeled off from the
 	 * original socket.
 	 */
@@ -1623,39 +1668,46 @@
 {
 	sctp_peeloff_arg_t peeloff;
 	struct socket *newsock;
-	int err, sd;
+	int retval = 0;
 	sctp_association_t *assoc;
 
 	if (len != sizeof(sctp_peeloff_arg_t))
 		return -EINVAL;
 	if (copy_from_user(&peeloff, optval, len))
 		return -EFAULT;
+
+	sctp_lock_sock(sk);
+
 	assoc = sctp_id2assoc(sk, peeloff.associd);
-	if (NULL == assoc)
-		return -EINVAL;
+	if (NULL == assoc) {
+		retval = -EINVAL;
+		goto out_unlock;
+	}
 
 	SCTP_DEBUG_PRINTK("%s: sk: %p assoc: %p\n", __FUNCTION__, sk, assoc);
 
-	err = sctp_do_peeloff(assoc, &newsock);
-	if (err < 0)
-		return err;
+	retval = sctp_do_peeloff(assoc, &newsock);
+	if (retval < 0)
+		goto out_unlock;
 
 	/* Map the socket to an unused fd that can be returned to the user.  */
-	sd = sock_map_fd(newsock);
-	if (sd < 0) {
+	retval = sock_map_fd(newsock);
+	if (retval < 0) {
 		sock_release(newsock);
-		return sd;
+		goto out_unlock;
 	}
 
 	SCTP_DEBUG_PRINTK("%s: sk: %p assoc: %p newsk: %p sd: %d\n",
-			  __FUNCTION__, sk, assoc, newsock->sk, sd);
+			  __FUNCTION__, sk, assoc, newsock->sk, retval);
 
 	/* Return the fd mapped to the new socket.  */
-	peeloff.sd = sd;
+	peeloff.sd = retval;
 	if (copy_to_user(optval, &peeloff, len))
-		return -EFAULT;
+		retval = -EFAULT;
 
-	return 0;
+out_unlock:
+	sctp_release_sock(sk);
+	return retval;
 }
 
 SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	Fri Oct 18 21:03:04 2002
+++ b/net/socket.c	Fri Oct 18 21:03:04 2002
@@ -447,11 +447,6 @@
 	return sock;
 }
 
-extern __inline__ void sockfd_put(struct socket *sock)
-{
-	fput(sock->file);
-}
-
 /**
  *	sock_alloc	-	allocate a socket
  *	
diff -Nru a/net/sunrpc/cache.c b/net/sunrpc/cache.c
--- a/net/sunrpc/cache.c	Fri Oct 18 21:03:05 2002
+++ b/net/sunrpc/cache.c	Fri Oct 18 21:03:05 2002
@@ -750,7 +750,7 @@
  *
  */
 
-void add_word(char **bpp, int *lp, char *str)
+void qword_add(char **bpp, int *lp, char *str)
 {
 	char *bp = *bpp;
 	int len = *lp;
@@ -785,7 +785,7 @@
 	*lp = len;
 }
 
-void add_hex(char **bpp, int *lp, char *buf, int blen)
+void qword_addhex(char **bpp, int *lp, char *buf, int blen)
 {
 	char *bp = *bpp;
 	int len = *lp;
@@ -879,7 +879,7 @@
  */
 
 #define isodigit(c) (isdigit(c) && c <= '7')
-int get_word(char **bpp, char *dest, int bufsize)
+int qword_get(char **bpp, char *dest, int bufsize)
 {
 	/* return bytes copied, or -1 on error */
 	char *bp = *bpp;
diff -Nru a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
--- a/net/sunrpc/sunrpc_syms.c	Fri Oct 18 21:03:08 2002
+++ b/net/sunrpc/sunrpc_syms.c	Fri Oct 18 21:03:08 2002
@@ -92,6 +92,25 @@
 EXPORT_SYMBOL(svc_proc_read);
 #endif
 
+/* caching... */
+EXPORT_SYMBOL(auth_domain_find);
+EXPORT_SYMBOL(auth_domain_put);
+EXPORT_SYMBOL(auth_unix_add_addr);
+EXPORT_SYMBOL(auth_unix_forget_old);
+EXPORT_SYMBOL(auth_unix_lookup);
+EXPORT_SYMBOL(cache_check);
+EXPORT_SYMBOL(cache_clean);
+EXPORT_SYMBOL(cache_flush);
+EXPORT_SYMBOL(cache_fresh);
+EXPORT_SYMBOL(cache_init);
+EXPORT_SYMBOL(cache_register);
+EXPORT_SYMBOL(cache_unregister);
+EXPORT_SYMBOL(qword_add);
+EXPORT_SYMBOL(qword_addhex);
+EXPORT_SYMBOL(qword_get);
+EXPORT_SYMBOL(svcauth_unix_purge);
+EXPORT_SYMBOL(unix_domain_find);
+
 /* Generic XDR */
 EXPORT_SYMBOL(xdr_encode_array);
 EXPORT_SYMBOL(xdr_encode_string);
diff -Nru a/net/sunrpc/svc.c b/net/sunrpc/svc.c
--- a/net/sunrpc/svc.c	Fri Oct 18 21:03:08 2002
+++ b/net/sunrpc/svc.c	Fri Oct 18 21:03:08 2002
@@ -27,9 +27,11 @@
  * Create an RPC service
  */
 struct svc_serv *
-svc_create(struct svc_program *prog, unsigned int bufsize, unsigned int xdrsize)
+svc_create(struct svc_program *prog, unsigned int bufsize)
 {
 	struct svc_serv	*serv;
+	int vers;
+	unsigned int xdrsize;
 
 	if (!(serv = (struct svc_serv *) kmalloc(sizeof(*serv), GFP_KERNEL)))
 		return NULL;
@@ -39,6 +41,16 @@
 	serv->sv_nrthreads = 1;
 	serv->sv_stats     = prog->pg_stats;
 	serv->sv_bufsz	   = bufsize? bufsize : 4096;
+	prog->pg_lovers = prog->pg_nvers-1;
+	xdrsize = 0;
+	for (vers=0; vers<prog->pg_nvers ; vers++)
+		if (prog->pg_vers[vers]) {
+			prog->pg_hivers = vers;
+			if (prog->pg_lovers > vers)
+				prog->pg_lovers = vers;
+			if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
+				xdrsize = prog->pg_vers[vers]->vs_xdrsize;
+		}
 	serv->sv_xdrsize   = xdrsize;
 	INIT_LIST_HEAD(&serv->sv_threads);
 	INIT_LIST_HEAD(&serv->sv_sockets);
diff -Nru a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
--- a/net/sunrpc/svcauth_unix.c	Fri Oct 18 21:03:05 2002
+++ b/net/sunrpc/svcauth_unix.c	Fri Oct 18 21:03:05 2002
@@ -90,7 +90,9 @@
 {
 	struct ip_map *im = container_of(item, struct ip_map,h);
 	if (cache_put(item, cd)) {
-		auth_domain_put(&im->m_client->h);
+		if (test_bit(CACHE_VALID, &item->flags) &&
+		    !test_bit(CACHE_NEGATIVE, &item->flags))
+			auth_domain_put(&im->m_client->h);
 		kfree(im);
 	}
 }
@@ -130,8 +132,8 @@
 		 ntohl(addr) >>  8 & 0xff,
 		 ntohl(addr) >>  0 & 0xff);
 
-	add_word(bpp, blen, im->m_class);
-	add_word(bpp, blen, text_addr);
+	qword_add(bpp, blen, im->m_class);
+	qword_add(bpp, blen, text_addr);
 	(*bpp)[-1] = '\n';
 }
 
@@ -153,11 +155,11 @@
 	mesg[mlen-1] = 0;
 
 	/* class */
-	len = get_word(&mesg, class, 50);
+	len = qword_get(&mesg, class, 50);
 	if (len <= 0) return -EINVAL;
 
 	/* ip address */
-	len = get_word(&mesg, buf, 50);
+	len = qword_get(&mesg, buf, 50);
 	if (len <= 0) return -EINVAL;
 
 	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
@@ -168,7 +170,7 @@
 		return -EINVAL;
 
 	/* domainname, or empty for NEGATIVE */
-	len = get_word(&mesg, buf, 50);
+	len = qword_get(&mesg, buf, 50);
 	if (len < 0) return -EINVAL;
 
 	if (len) {
diff -Nru a/scripts/Makefile b/scripts/Makefile
--- a/scripts/Makefile	Fri Oct 18 21:03:04 2002
+++ b/scripts/Makefile	Fri Oct 18 21:03:04 2002
@@ -11,6 +11,8 @@
 
 EXTRA_TARGETS := fixdep split-include docproc conmakehash
 
+subdir-	:= lxdialog
+
 # Yikes. We need to build this stuff here even if the user only wants
 # modules.
 
@@ -24,6 +26,8 @@
 host-progs := fixdep split-include conmakehash docproc tkparse
 tkparse-objs := tkparse.o tkcond.o tkgen.o
 
+clean-files := kconfig.tk
+
 include $(TOPDIR)/Rules.make
 
 # In reality kconfig.tk should depend on all Config.in files,
@@ -56,8 +60,3 @@
 # fixdep is needed to compile other host programs
 $(obj)/split-include $(obj)/docproc $(addprefix $(obj)/,$(tkparse-objs)) \
 $(obj)/conmakehash lxdialog: $(obj)/fixdep
-
-mrproper:
-	@rm -f $(host-progs) $(addprefix $(obj)/,$(tkparse-objs) kconfig.tk core)
-	@$(call descend,scripts/lxdialog,mrproper)
-
diff -Nru a/scripts/Makefile.clean b/scripts/Makefile.clean
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/Makefile.clean	Fri Oct 18 21:03:08 2002
@@ -0,0 +1,42 @@
+
+src := $(obj)
+
+no-rules.make := 1
+
+.PHONY: __clean
+__clean:
+
+include $(obj)/Makefile
+
+__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))
+subdir-y	+= $(__subdir-y)
+__subdir-m	:= $(patsubst %/,%,$(filter %/, $(obj-m)))
+subdir-m	+= $(__subdir-m)
+__subdir-n	:= $(patsubst %/,%,$(filter %/, $(obj-n)))
+subdir-n	+= $(__subdir-n)
+__subdir-	:= $(patsubst %/,%,$(filter %/, $(obj-)))
+subdir-		+= $(__subdir-)
+
+subdir-ym	:= $(sort $(subdir-y) $(subdir-m))
+subdir-ymn      := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
+
+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 $(EXTRA_TARGETS) $(host-progs) $(clean-files))
+
+__clean: $(subdir-ymn)
+ifneq ($(strip $(__clean-files) $(clean-rule)),)
+	rm -f $(__clean-files)
+	$(clean-rule)
+else
+	@:
+endif
+
+.PHONY: $(subdir-ymn)
+
+$(subdir-ymn):
+	$(MAKE) -rR -f scripts/Makefile.clean obj=$@
+
diff -Nru a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
--- a/scripts/lxdialog/Makefile	Fri Oct 18 21:03:08 2002
+++ b/scripts/lxdialog/Makefile	Fri Oct 18 21:03:08 2002
@@ -42,6 +42,3 @@
 		echo ;\
 		exit 1 ;\
 	fi
-
-mrproper:
-	@rm -f $(host-progs) $(addprefix $(obj)/,$(lxdialog-objs))
diff -Nru a/security/capability.c b/security/capability.c
--- a/security/capability.c	Fri Oct 18 21:03:04 2002
+++ b/security/capability.c	Fri Oct 18 21:03:04 2002
@@ -442,11 +442,6 @@
 	return;
 }
 
-static int cap_file_llseek (struct file *file)
-{
-	return 0;
-}
-
 static int cap_file_ioctl (struct file *file, unsigned int command,
 			   unsigned long arg)
 {
@@ -787,7 +782,6 @@
 	.file_permission =		cap_file_permission,
 	.file_alloc_security =		cap_file_alloc_security,
 	.file_free_security =		cap_file_free_security,
-	.file_llseek =			cap_file_llseek,
 	.file_ioctl =			cap_file_ioctl,
 	.file_mmap =			cap_file_mmap,
 	.file_mprotect =		cap_file_mprotect,
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Fri Oct 18 21:03:03 2002
+++ b/security/dummy.c	Fri Oct 18 21:03:03 2002
@@ -344,11 +344,6 @@
 	return;
 }
 
-static int dummy_file_llseek (struct file *file)
-{
-	return 0;
-}
-
 static int dummy_file_ioctl (struct file *file, unsigned int command,
 			     unsigned long arg)
 {
@@ -602,7 +597,6 @@
 	.file_permission =		dummy_file_permission,
 	.file_alloc_security =		dummy_file_alloc_security,
 	.file_free_security =		dummy_file_free_security,
-	.file_llseek =			dummy_file_llseek,
 	.file_ioctl =			dummy_file_ioctl,
 	.file_mmap =			dummy_file_mmap,
 	.file_mprotect =		dummy_file_mprotect,
diff -Nru a/security/security.c b/security/security.c
--- a/security/security.c	Fri Oct 18 21:03:03 2002
+++ b/security/security.c	Fri Oct 18 21:03:03 2002
@@ -241,9 +241,9 @@
 	return security_ops->sys_security (id, call, args);
 }
 
-EXPORT_SYMBOL (register_security);
-EXPORT_SYMBOL (unregister_security);
-EXPORT_SYMBOL (mod_reg_security);
-EXPORT_SYMBOL (mod_unreg_security);
-EXPORT_SYMBOL (capable);
-EXPORT_SYMBOL (security_ops);
+EXPORT_SYMBOL_GPL(register_security);
+EXPORT_SYMBOL_GPL(unregister_security);
+EXPORT_SYMBOL_GPL(mod_reg_security);
+EXPORT_SYMBOL_GPL(mod_unreg_security);
+EXPORT_SYMBOL(capable);
+EXPORT_SYMBOL(security_ops);
diff -Nru a/sound/oss/Makefile b/sound/oss/Makefile
--- a/sound/oss/Makefile	Fri Oct 18 21:03:04 2002
+++ b/sound/oss/Makefile	Fri Oct 18 21:03:04 2002
@@ -96,6 +96,10 @@
 
 host-progs	:= bin2hex hex2hex
 
+# Files generated that shall be removed upon make clean
+clean-files := maui_boot.h msndperm.c msndinit.c pndsperm.c pndspini.c \
+               pss_boot.h trix_boot.h
+
 include $(TOPDIR)/Rules.make
 
 # Firmware files that need translation
diff -Nru a/sound/oss/ad1848.c b/sound/oss/ad1848.c
--- a/sound/oss/ad1848.c	Fri Oct 18 21:03:05 2002
+++ b/sound/oss/ad1848.c	Fri Oct 18 21:03:05 2002
@@ -47,6 +47,7 @@
 #include <linux/stddef.h>
 #include <linux/pm.h>
 #include <linux/isapnp.h>
+#include <linux/pnp.h>
 #include <linux/spinlock.h>
 
 #define DEB(x)
@@ -58,7 +59,7 @@
 
 typedef struct
 {
-	spinlock_t		lock;
+	spinlock_t	lock;
 	int             base;
 	int             irq;
 	int             dma1, dma2;
@@ -176,7 +177,7 @@
     ,{CAP_F_TIMER} /* MD_1845_SSCAPE */
 };
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 static int isapnp	= 1;
 static int isapnpjump	= 0;
 static int reverse	= 0;
@@ -2920,7 +2921,7 @@
 MODULE_PARM(deskpro_m, "i");            /* Special magic for Deskpro M box */
 MODULE_PARM(soundpro, "i");             /* More special magic for SoundPro chips */
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 MODULE_PARM(isapnp,	"i");
 MODULE_PARM(isapnpjump,	"i");
 MODULE_PARM(reverse,	"i");
@@ -2928,7 +2929,7 @@
 MODULE_PARM_DESC(isapnpjump,	"Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
 MODULE_PARM_DESC(reverse,	"When set to 1, will reverse ISAPnP search order");
 
-struct pci_dev	*ad1848_dev  = NULL;
+struct pnp_dev	*ad1848_dev  = NULL;
 
 /* Please add new entries at the end of the table */
 static struct {
@@ -2977,7 +2978,7 @@
 
 MODULE_DEVICE_TABLE(isapnp, id_table);
 
-static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
+static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev *dev)
 {
 	int err;
 
@@ -2985,35 +2986,26 @@
 	if(dev->active)
 		return(dev);
 
-	if((err = dev->activate(dev)) < 0) {
+	if((err = pnp_activate_dev(dev)) < 0) {
 		printk(KERN_ERR "ad1848: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
 
-		dev->deactivate(dev);
+		pnp_disable_dev(dev);
 
 		return(NULL);
 	}
+	audio_activated = 1;
 	return(dev);
 }
 
-static struct pci_dev *ad1848_init_generic(struct pci_bus *bus, struct address_info *hw_config, int slot)
+static struct pnp_dev *ad1848_init_generic(struct pnp_card *bus, struct address_info *hw_config, int slot)
 {
 
 	/* Configure Audio device */
-	if((ad1848_dev = isapnp_find_dev(bus, ad1848_isapnp_list[slot].vendor, ad1848_isapnp_list[slot].function, NULL)))
+	if((ad1848_dev = pnp_find_dev(bus, ad1848_isapnp_list[slot].vendor, ad1848_isapnp_list[slot].function, NULL)))
 	{
-		int ret;
-		ret = ad1848_dev->prepare(ad1848_dev);
-		/* If device is active, assume configured with /proc/isapnp
-		 * and use anyway. Some other way to check this? */
-		if(ret && ret != -EBUSY) {
-			printk(KERN_ERR "ad1848: ISAPnP found device that could not be autoconfigured.\n");
-			return(NULL);
-		}
-		if(ret == -EBUSY)
-			audio_activated = 1;
-
 		if((ad1848_dev = activate_dev(ad1848_isapnp_list[slot].name, "ad1848", ad1848_dev)))
 		{
+			get_device(&ad1848_dev->dev);
 			hw_config->io_base 	= ad1848_dev->resource[ad1848_isapnp_list[slot].mss_io].start;
 			hw_config->irq 		= ad1848_dev->irq_resource[ad1848_isapnp_list[slot].irq].start;
 			hw_config->dma 		= ad1848_dev->dma_resource[ad1848_isapnp_list[slot].dma].start;
@@ -3030,7 +3022,7 @@
 	return(ad1848_dev);
 }
 
-static int __init ad1848_isapnp_init(struct address_info *hw_config, struct pci_bus *bus, int slot)
+static int __init ad1848_isapnp_init(struct address_info *hw_config, struct pnp_card *bus, int slot)
 {
 	char *busname = bus->name[0] ? bus->name : ad1848_isapnp_list[slot].name;
 
@@ -3072,9 +3064,9 @@
 		i = isapnpjump;
 	first = 0;
 	while(ad1848_isapnp_list[i].card_vendor != 0) {
-		static struct pci_bus *bus = NULL;
+		static struct pnp_card *bus = NULL;
 
-		while ((bus = isapnp_find_card(
+		while ((bus = pnp_find_card(
 				ad1848_isapnp_list[i].card_vendor,
 				ad1848_isapnp_list[i].card_device,
 				bus))) {
@@ -3096,7 +3088,7 @@
 {
 	printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 	if(isapnp && (ad1848_isapnp_probe(&cfg) < 0) ) {
 		printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n");
 		isapnp = 0;
@@ -3131,10 +3123,12 @@
 	if(loaded)
 		unload_ms_sound(&cfg);
 
-#ifdef __ISAPNP__
-	if(audio_activated)
-		if(ad1848_dev)
-			ad1848_dev->deactivate(ad1848_dev);
+#ifdef CONFIG_PNP
+	if(ad1848_dev){
+		if(audio_activated)
+			pnp_disable_dev(ad1848_dev);
+		put_device(&ad1848_dev->dev);
+	}
 #endif
 }
 
@@ -3148,7 +3142,7 @@
 	int ints[6];
 	
 	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
+
 	io	= ints[1];
 	irq	= ints[2];
 	dma	= ints[3];
diff -Nru a/sound/oss/ite8172.c b/sound/oss/ite8172.c
--- a/sound/oss/ite8172.c	Fri Oct 18 21:03:03 2002
+++ b/sound/oss/ite8172.c	Fri Oct 18 21:03:03 2002
@@ -305,7 +305,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern inline unsigned ld2(unsigned int x)
+static inline unsigned ld2(unsigned int x)
 {
     unsigned r = 0;
 	
@@ -510,7 +510,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern inline void stop_adc(struct it8172_state *s)
+static inline void stop_adc(struct it8172_state *s)
 {
     struct dmabuf* db = &s->dma_adc;
     unsigned long flags;
@@ -534,7 +534,7 @@
     spin_unlock_irqrestore(&s->lock, flags);
 }	
 
-extern inline void stop_dac(struct it8172_state *s)
+static inline void stop_dac(struct it8172_state *s)
 {
     struct dmabuf* db = &s->dma_dac;
     unsigned long flags;
@@ -633,7 +633,7 @@
 #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-extern inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db)
+static inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db)
 {
     struct page *page, *pend;
 
@@ -709,7 +709,7 @@
     return 0;
 }
 
-extern inline int prog_dmabuf_adc(struct it8172_state *s)
+static inline int prog_dmabuf_adc(struct it8172_state *s)
 {
     stop_adc(s);
     return prog_dmabuf(s, &s->dma_adc, s->adcrate,
@@ -717,7 +717,7 @@
 		       IT_AC_CAPCC);
 }
 
-extern inline int prog_dmabuf_dac(struct it8172_state *s)
+static inline int prog_dmabuf_dac(struct it8172_state *s)
 {
     stop_dac(s);
     return prog_dmabuf(s, &s->dma_dac, s->dacrate,
diff -Nru a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
--- a/sound/oss/opl3sa2.c	Fri Oct 18 21:03:03 2002
+++ b/sound/oss/opl3sa2.c	Fri Oct 18 21:03:03 2002
@@ -57,12 +57,13 @@
  *                         (Jan 7, 2001)
  * Zwane Mwaikambo	   Added PM support. (Dec 4 2001)
  *
+ * Adam Belay              Converted driver to new PnP Layer (Oct 12, 2002)
  */
 
 #include <linux/config.h>
+#include <linux/pnp.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/isapnp.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include "sound_config.h"
@@ -107,7 +108,7 @@
 #define CHIPSET_OPL3SA2 0
 #define CHIPSET_OPL3SA3 1
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 #define OPL3SA2_CARDS_MAX 4
 #else
 #define OPL3SA2_CARDS_MAX 1
@@ -161,13 +162,13 @@
 static int __initdata ymode	= -1;
 static int __initdata loopback	= -1;
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 /* PnP specific parameters */
 static int __initdata isapnp = 1;
 static int __initdata multiple = 1;
 
 /* PnP devices */
-struct pci_dev* opl3sa2_dev[OPL3SA2_CARDS_MAX];
+struct pnp_dev* opl3sa2_dev[OPL3SA2_CARDS_MAX];
 
 /* Whether said devices have been activated */
 static int opl3sa2_activated[OPL3SA2_CARDS_MAX];
@@ -205,7 +206,7 @@
 MODULE_PARM(loopback, "i");
 MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 MODULE_PARM(isapnp, "i");
 MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");
 
@@ -834,89 +835,60 @@
 		sound_unload_mixerdev(opl3sa2_mixer[card]);
 }
 
-
-#ifdef __ISAPNP__
-
-struct isapnp_device_id isapnp_opl3sa2_list[] __initdata = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021),
-		0 },
-	{0}
+#ifdef CONFIG_PNP
+struct pnp_id pnp_opl3sa2_list[] = {
+	{.id = "YMH0021", .driver_data = 0},
+	{.id = ""}
 };
 
-MODULE_DEVICE_TABLE(isapnp, isapnp_opl3sa2_list);
-
-static int __init opl3sa2_isapnp_probe(struct address_info* hw_cfg,
-				       struct address_info* mss_cfg,
-				       struct address_info* mpu_cfg,
-				       int card)
-{
-	static struct pci_dev* dev;
-	int ret;
-
-	/* Find and configure device */
-	dev = isapnp_find_dev(NULL,
-			      ISAPNP_VENDOR('Y','M','H'),
-			      ISAPNP_FUNCTION(0x0021),
-			      dev);
-	if(dev == NULL) {
-		return -ENODEV;
-	}
-
-	/*
-	 * If device is active, assume configured with /proc/isapnp
-	 * and use anyway. Any other way to check this?
-	 */
-	ret = dev->prepare(dev);
-	if(ret && ret != -EBUSY) {
-		printk(KERN_ERR "opl3sa2: ISA PnP found device that could not be autoconfigured.\n");
-		return -ENODEV;
-	}
-	if(ret == -EBUSY) {
-		opl3sa2_activated[card] = 1;
-	}
-	else {
-		if(dev->activate(dev) < 0) {
-			printk(KERN_WARNING "opl3sa2: ISA PnP activate failed\n");
-			opl3sa2_activated[card] = 0;
-			return -ENODEV;
-		}
-
-		printk(KERN_DEBUG
-		       "opl3sa2: Activated ISA PnP card %d (active=%d)\n",
-		       card, dev->active);
+/*MODULE_DEVICE_TABLE(isapnp, isapnp_opl3sa2_list);*/
 
-	}
+static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_id *card_id,
+			     const struct pnp_id *dev_id)
+{
+	int card = opl3sa2_cards_num;
+	if (opl3sa2_cards_num == OPL3SA2_CARDS_MAX)
+		return 0;
+	opl3sa2_activated[card] = 1;
 
 	/* Our own config: */
-	hw_cfg->io_base = dev->resource[4].start;
-	hw_cfg->irq     = dev->irq_resource[0].start;
-	hw_cfg->dma     = dev->dma_resource[0].start;
-	hw_cfg->dma2    = dev->dma_resource[1].start;
-	
+	cfg[card].io_base = dev->resource[4].start;
+	cfg[card].irq     = dev->irq_resource[0].start;
+	cfg[card].dma     = dev->dma_resource[0].start;
+	cfg[card].dma2    = dev->dma_resource[1].start;
+
 	/* The MSS config: */
-	mss_cfg->io_base      = dev->resource[1].start;
-	mss_cfg->irq          = dev->irq_resource[0].start;
-	mss_cfg->dma          = dev->dma_resource[0].start;
-	mss_cfg->dma2         = dev->dma_resource[1].start;
-	mss_cfg->card_subtype = 1; /* No IRQ or DMA setup */
-
-	mpu_cfg->io_base       = dev->resource[3].start;
-	mpu_cfg->irq           = dev->irq_resource[0].start;
-	mpu_cfg->dma           = -1;
-	mpu_cfg->dma2          = -1;
-	mpu_cfg->always_detect = 1; /* It's there, so use shared IRQs */
+	cfg_mss[card].io_base      = dev->resource[1].start;
+	cfg_mss[card].irq          = dev->irq_resource[0].start;
+	cfg_mss[card].dma          = dev->dma_resource[0].start;
+	cfg_mss[card].dma2         = dev->dma_resource[1].start;
+	cfg_mss[card].card_subtype = 1; /* No IRQ or DMA setup */
+
+	cfg_mpu[card].io_base       = dev->resource[3].start;
+	cfg_mpu[card].irq           = dev->irq_resource[0].start;
+	cfg_mpu[card].dma           = -1;
+	cfg_mpu[card].dma2          = -1;
+	cfg_mpu[card].always_detect = 1; /* It's there, so use shared IRQs */
 
 	/* Call me paranoid: */
-	opl3sa2_clear_slots(hw_cfg);
-	opl3sa2_clear_slots(mss_cfg);
-	opl3sa2_clear_slots(mpu_cfg);
+	opl3sa2_clear_slots(&cfg[card]);
+	opl3sa2_clear_slots(&cfg_mss[card]);
+	opl3sa2_clear_slots(&cfg_mpu[card]);
 
 	opl3sa2_dev[card] = dev;
+	opl3sa2_cards_num++;
 
 	return 0;
 }
-#endif /* __ISAPNP__ */
+
+static struct pnp_driver opl3sa2_driver = {
+	.name		= "opl3sa2",
+	.card_id_table	= NULL,
+	.id_table	= pnp_opl3sa2_list,
+	.probe		= opl3sa2_pnp_probe,
+};
+
+#endif /* CONFIG_PNP */
 
 /* End of component functions */
 
@@ -1003,28 +975,21 @@
 	/* Sanitize isapnp and multiple settings */
 	isapnp = isapnp != 0 ? 1 : 0;
 	multiple = multiple != 0 ? 1 : 0;
-	
+
 	max = (multiple && isapnp) ? OPL3SA2_CARDS_MAX : 1;
-	for(card = 0; card < max; card++, opl3sa2_cards_num++) {
-#ifdef __ISAPNP__
-		/*
-		 * Please remember that even with __ISAPNP__ defined one
-		 * should still be able to disable PNP support for this 
-		 * single driver!
-		 */
-		if(isapnp && opl3sa2_isapnp_probe(&cfg[card],
-						  &cfg_mss[card],
-						  &cfg_mpu[card],
-						  card) < 0) {
-			if(!opl3sa2_cards_num)
-				printk(KERN_INFO "opl3sa2: No PnP cards found\n");
-			if(io == -1)
-				break;
-			isapnp=0;
-			printk(KERN_INFO "opl3sa2: Search for a card at 0x%d.\n", io);
-			/* Fall through */
+
+#ifdef CONFIG_PNP
+	if (isapnp){
+		pnp_register_driver(&opl3sa2_driver);
+		if(!opl3sa2_cards_num){
+			printk(KERN_INFO "opl3sa2: No PnP cards found\n");
+			isapnp = 0;
 		}
+		max = opl3sa2_cards_num;
+	}
 #endif
+
+	for(card = 0; card < max; card++) {
 		/* If a user wants an I/O then assume they meant it */
 		
 		if(!isapnp) {
@@ -1033,6 +998,7 @@
 				printk(KERN_ERR
 				       "opl3sa2: io, mss_io, irq, dma, and dma2 must be set\n");
 				return -EINVAL;
+				opl3sa2_cards_num++;
 			}
 
 			/*
@@ -1145,14 +1111,8 @@
 		unload_opl3sa2_mss(&cfg_mss[card]);
 		unload_opl3sa2(&cfg[card], card);
 
-#ifdef __ISAPNP__
-		if(opl3sa2_activated[card] && opl3sa2_dev[card]) {
-			opl3sa2_dev[card]->deactivate(opl3sa2_dev[card]);
-
-			printk(KERN_DEBUG
-			       "opl3sa2: Deactivated ISA PnP card %d (active=%d)\n",
-			       card, opl3sa2_dev[card]->active);
-		}
+#ifdef CONFIG_PNP
+		pnp_unregister_driver(&opl3sa2_driver);
 #endif
 	}
 }
@@ -1164,7 +1124,7 @@
 static int __init setup_opl3sa2(char *str)
 {
 	/* io, irq, dma, dma2,... */
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 	int ints[11];
 #else
 	int ints[9];
@@ -1179,7 +1139,7 @@
 	mpu_io   = ints[6];
 	ymode    = ints[7];
 	loopback = ints[8];
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP
 	isapnp   = ints[9];
 	multiple = ints[10];
 #endif
diff -Nru a/sound/oss/sound_config.h b/sound/oss/sound_config.h
--- a/sound/oss/sound_config.h	Fri Oct 18 21:03:03 2002
+++ b/sound/oss/sound_config.h	Fri Oct 18 21:03:03 2002
@@ -113,14 +113,14 @@
 
 #if OPEN_READ == FMODE_READ && OPEN_WRITE == FMODE_WRITE
 
-extern __inline__ int translate_mode(struct file *file)
+static inline int translate_mode(struct file *file)
 {
 	return file->f_mode;
 }
 
 #else
 
-extern __inline__ int translate_mode(struct file *file)
+static inline int translate_mode(struct file *file)
 {
 	return ((file->f_mode & FMODE_READ) ? OPEN_READ : 0) |
 		((file->f_mode & FMODE_WRITE) ? OPEN_WRITE : 0);
diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c
--- a/sound/pci/ens1370.c	Fri Oct 18 21:03:04 2002
+++ b/sound/pci/ens1370.c	Fri Oct 18 21:03:04 2002
@@ -593,7 +593,7 @@
 		}
 		spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 	}
-	snd_printk("codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
+	snd_printk("codec write timeout at 0x%lx [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
 }
 
 static unsigned short snd_es1371_codec_read(ac97_t *ac97,
@@ -641,14 +641,14 @@
 			}
 			spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 			if (++fail > 10) {
-				snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC)));
+				snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC)));
 				return 0;
 			}
 			goto __again;
 		}
 		spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 	}
-	snd_printk("es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
+	snd_printk("es1371: codec read timeout at 0x%lx [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
 	return 0;
 }
 
