diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Mon Jan 13 10:18:06 2003
+++ b/CREDITS	Mon Jan 13 10:18:06 2003
@@ -2884,8 +2884,7 @@
 S: Australia
 
 N: Stephen Smalley
-E: sds@tislabs.com
-E: ssmalley@nai.com
+E: sds@epoch.ncsc.mil
 D: portions of the Linux Security Module (LSM) framework and security modules
 
 N: Chris Smith
diff -Nru a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/arm/00-INDEX	Mon Jan 13 10:18:07 2003
@@ -0,0 +1,20 @@
+00-INDEX
+	- this file
+Booting
+	- requirements for booting
+Interrupts
+	- ARM Interrupt subsystem documentation
+Netwinder
+	- Netwinder specific documentation
+README
+	- General ARM documentation
+SA1100
+	- SA1100 documentation
+XScale
+	- XScale documentation
+empeg
+	- Empeg documentation
+mem_alignment
+	- alignment abort handler documentation
+nwfpe
+	- NWFPE floating point emulator documentation
diff -Nru a/Documentation/arm/Booting b/Documentation/arm/Booting
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/arm/Booting	Mon Jan 13 10:18:07 2003
@@ -0,0 +1,137 @@
+			Booting ARM Linux
+			=================
+
+Author:	Russell King
+Date  : 18 May 2002
+
+The following documentation is relevant to 2.4.18-rmk6 and beyond.
+
+In order to boot ARM Linux, you require a boot loader, which is a small
+program that runs before the main kernel.  The boot loader is expected
+to initialise various devices, and eventually call the Linux kernel,
+passing information to the kernel.
+
+Essentially, the boot loader should provide (as a minimum) the
+following:
+
+1. Setup and initialise the RAM.
+2. Initialise one serial port.
+3. Detect the machine type.
+4. Setup the kernel tagged list.
+5. Call the kernel image.
+
+
+1. Setup and initialise RAM
+---------------------------
+
+Existing boot loaders:		MANDATORY
+New boot loaders:		MANDATORY
+
+The boot loader is expected to find and initialise all RAM that the
+kernel will use for volatile data storage in the system.  It performs
+this in a machine dependent manner.  (It may use internal algorithms
+to automatically locate and size all RAM, or it may use knowledge of
+the RAM in the machine, or any other method the boot loader designer
+sees fit.)
+
+
+2. Initialise one serial port
+-----------------------------
+
+Existing boot loaders:		OPTIONAL, RECOMMENDED
+New boot loaders:		OPTIONAL, RECOMMENDED
+
+The boot loader should initialise and enable one serial port on the
+target.  This allows the kernel serial driver to automatically detect
+which serial port it should use for the kernel console (generally
+used for debugging purposes, or communication with the target.)
+
+As an alternative, the boot loader can pass the relevant 'console='
+option to the kernel via the tagged lists specifing the port, and
+serial format options as described in
+
+       linux/Documentation/kernel-parameters.txt.
+
+
+3. Detect the machine type
+--------------------------
+
+Existing boot loaders:		OPTIONAL
+New boot loaders:		MANDATORY
+
+The boot loader should detect the machine type its running on by some
+method.  Whether this is a hard coded value or some algorithm that
+looks at the connected hardware is beyond the scope of this document.
+The boot loader must ultimately be able to provide a MACH_TYPE_xxx
+value to the kernel. (see linux/arch/arm/tools/mach-types).
+
+
+4. Setup the kernel tagged list
+-------------------------------
+
+Existing boot loaders:		OPTIONAL, HIGHLY RECOMMENDED
+New boot loaders:		MANDATORY
+
+The boot loader must create and initialise the kernel tagged list.
+A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE.
+The ATAG_CORE tag may or may not be empty.  An empty ATAG_CORE tag
+has the size field set to '2' (0x00000002).  The ATAG_NONE must set
+the size field to zero.
+
+Any number of tags can be placed in the list.  It is undefined
+whether a repeated tag appends to the information carried by the
+previous tag, or whether it replaces the information in its
+entirety; some tags behave as the former, others the latter.
+
+The boot loader must pass at a minimum the size and location of
+the system memory, and root filesystem location.  Therefore, the
+minimum tagged list should look:
+
+	+-----------+
+base ->	| ATAG_CORE |  |
+	+-----------+  |
+	| ATAG_MEM  |  | increasing address
+	+-----------+  |
+	| ATAG_NONE |  |
+	+-----------+  v
+
+The tagged list should be stored in system RAM.
+
+The tagged list must be placed in a region of memory where neither
+the kernel decompressor nor initrd 'bootp' program will overwrite
+it.  The recommended placement is in the first 16KiB of RAM.
+
+5. Calling the kernel image
+---------------------------
+
+Existing boot loaders:		MANDATORY
+New boot loaders:		MANDATORY
+
+There are two options for calling the kernel zImage.  If the zImage
+is stored in flash, and is linked correctly to be run from flash,
+then it is legal for the boot loader to call the zImage in flash
+directly.
+
+The zImage may also be placed in system RAM (at any location) and
+called there.  Note that the kernel uses 16K of RAM below the image
+to store page tables.  The recommended placement is 32KiB into RAM.
+
+In either case, the following conditions must be met:
+
+- CPU register settings
+  r0 = 0,
+  r1 = machine type number discovered in (3) above.
+  r2 = physical address of tagged list in system RAM.
+
+- CPU mode
+  All forms of interrupts must be disabled (IRQs and FIQs)
+  The CPU must be in SVC mode.  (A special exception exists for Angel)
+
+- Caches, MMUs
+  The MMU must be off.
+  Instruction cache may be on or off.
+  Data cache must be off.
+
+- The boot loader is expected to call the kernel image by jumping
+  directly to the first instruction of the kernel image.
+
diff -Nru a/Documentation/arm/SA1100/DMA b/Documentation/arm/SA1100/DMA
--- a/Documentation/arm/SA1100/DMA	Mon Jan 13 10:18:05 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,248 +0,0 @@
-Support functions for the SA11x0 internal DMA channels
-======================================================
-
-Nicolas Pitre <nico@cam.org>
-Last updated: 2001/07/15
-
-
-The DMA controller consists of six independent DMA channels. Each channel
-can be configured to service any of the serial controllers. Two channels
-are required to service a full-duplex serial controller. The DMA
-controller is intended to relieve the processor of the interrupt overhead
-in servicing these ports with programmed I/ O.
-
-If desired, any or all peripherals (except the UDC) may be serviced with
-programmed I/ O instead of DMA. Each peripheral is capable of requesting
-processor service through its own interrupt lines or through a DMA
-request.
-
-A set of functions is provided to support drivers working with DMA buffers
-through a generic interface for (wishfully) all DMA usages.  Those
-functions will take care of buffer queueing and splitting, DMA register
-management, interrupt handling, etc.
-
-
-SA11x0 DMA API
---------------
-
-Here is the description for the DMA API.
-
-
-int sa1100_request_dma( dmach_t *channel, const char *device_id,
-			dma_device_t device );
-
-This function will search for a free DMA channel and returns the channel
-number in '*channel'.  'device_id' should point to a string identifying
-the DMA usage or device (mainly for /proc).  'device' is the SA11x0
-peripheral's ports.  Note that reading from a port and writing to the
-same port are actually considered as two different streams requiring
-two DMA channels with their own device type.  All possible dma_device_t
-are defined in include/asm-arm/arch-sa1100/dma.h.  If no channel is
-available, or if the desired device is already in use by another DMA
-channel, then an error code is returned.  This function must be called
-before any other DMA calls.
-
-
-int sa1100_dma_queue_buffer( dmach_t channel, void *buf_id,
-                             dma_addr_t data, int size );
-
-This function enqueue the specified buffer for DMA processing.  The buffer
-will be transmitted or filled with incoming data depending on the channel
-configuration made through sa1100_dma_set_device().  If the queue is
-empty, DMA starts immediately on the given buffer.
-
-Arguments are:
-
-dmach_t channel:	the channel number.
-void *buf_id:		a buffer identification known by the caller.
-dma_addr_t data:	the buffer's physical address.
-int size:		the buffer size in bytes.
-
-Note here the dma_addr_t which is not the same as the virtual address as
-returned by kmalloc() and friends.  The DMA controller must be given a
-physical address to a buffer which is not cached bye the CPU data cache.
-To get such address, the DMA mapping functions (see
-Documentation/DMA-mapping.txt) are recommended.  The only relevant
-functions are pci_alloc_consistent(), pci_map_single() and their unmap
-counterparts.  The PCI dev argument is NULL of course.
-
-There is no restriction on the buffer size.  The DMA code will split it up
-internally to acommodate the DMA controller as needed.  If the buffer
-can't be enqueued the appropriate error code is returned.
-
-
-int sa1100_dma_set_callback( dmach_t channel, dma_callback_t cb );
-
-As soon as the DMa completes with a buffer, a callback function is used to
-notify the driver which would have registered one.  The callback function
-is prototyped as:
-
-void dma_callback( void *buf_id, int size );
-
-The 'buf_id' argument is the buffer identifier as passed to
-sa1100_dma_queue_buffer().  The 'size' argument is the number of bytes the
-DMA processed (should be the same as the buffer size).
-
-Note that this callback function is called while in interrupt context.
-So it has to be small and efficient while posponing more complex
-processing to a bottom-half function or similar.  All
-restrictions for interrupt handlers still apply.
-
-
-int sa1100_dma_get_current( dmach_t channel, void **buf_id,
-                            dma_addr_t *addr );
-
-This returns the buffer ID and the DMA address pointer within the buffer
-currently being processed.  If no such buffer is currently processed, an
-error code is returned.  This is useful for mmap()'ed buffers like in
-audio drivers.
-
-
-int sa1100_dma_stop( dmach_t channel );
-
-This call stops any DMA transfer on the given channel.
-
-
-int sa1100_dma_resume( dmach_t channel );
-
-This call resumes a DMA transfer which would have been stopped through
-sa1100_dma_stop().
-
-
-int sa1100_dma_flush_all( dmach_t channel );
-
-This completely flushes all queued buffers and on-going DMA transfers on a
-given channel.  The next enqueued buffer following this call will be
-processed right away.
-
-
-int sa1100_dma_set_spin( dmach_t channel, dma_addr_t addr, int size );
-
-Because there is at least one device out there that uses its receive
-signal for its transmit clock reference, we need a mecanism to make the
-DMA "spin" on a certain buffer for when there is no more actual buffer to
-process.  The 'addr' argument is the physical memory address to use, and
-the 'size' argument determines the spin DMA chunk.  This size can't be
-larger than 8191 (if so, it is clamped to 4096).  When the size is 0,
-the spin function is turned off.
-
-When activated, DMA will "spin" until there is any buffer in the queue.
-The current DMA chunk will terminate before a newly queued buffer is
-processed.  The spin buffer will only be reused when there is no more
-acctual buffer to process.
-
-It is important not to choose a too small 'size' value since it will
-greatly increase the interrupt load required to restart the spin.  Since
-this feature will typically be used on transmit DMAs, and because a buffer
-full of zeros is probably the best thing to spin out, the 'addr' argument
-may well be used with FLUSH_BASE_PHYS for which no allocation nor memory
-bus request are needed.
-
-The spinning DMA is affected by sa1100_dma_stop() and sa1100_dma_resume()
-but not bu sa1100_dma_flush_all().
-
-
-void sa1100_free_dma( dmach_t channel );
-
-This clears all activities on a given DMA channel and releases it for
-future requests.
-
-
-Buffer allocation
------------------
-
-Like mentionned above, it is the driver's responsibility to allocate, free
-and keep track of buffer space with dma_addr_t type addresses. However the
-driver must not change the state of any buffer after it has been sent to
-sa1100-dma_queue_buffer().  When that function has been called, the buffer
-becomes the DMA's ownership until one of these events occur:
-
-- The callback function is called by the DMA code with a buffer ID to
-  indicate that DMA processing terminated on that buffer.  Then the
-  driver owns the buffer again.
-- The sa1100-dma_flush_all() function is called by the driver at which
-  point *all* queued buffers are owned by the driver again.
-- The sa1100-free_dma() does the same as sa1100-dma_flush_all().
-
-This doesn't mean that you can't change the content of a queued buffer in
-conjonction with the usage of pci_map_consistent() and
-sa1100_dma_get_current()... but then you must be sure you know what you're
-doing (this doesn't work with pci_map_single()).
-
-
-Examples
---------
-
-A real example of audio ring buffers is implemented in the
-drivers/sound/sa1100-audio.c driver.  The SA1110 USB client and the
-SA11x0 FIR drivers are also using this interface to implement packetized
-DMA.
-
-A transmit DMA for network packets could look like this (largely simplified):
-
-struct sk_buff *tx_ring_skb[RING_SIZE];
-dma_addr_t      tx_ring_dma[RING_SIZE];
-int cur_tx;
-...
-
-transmit function:
-
-	tx_ring_skb[cur_tx] = skb;
-	tx_ring_dma[cur_tx] = pci_map_single(NULL, skb->data, skb->len,
-	                                     PCI_DMA_TODEVICE);
-	sa1100_dma_queue_buffer(channel, (void*)cur_tx,
-	                        tx_ring_dma[cur_tx], skb->len);
-	cur_tx++; cur_tx %= RING_SIZE;
-	...
-
-and the callback function:
-
-void tx_done_callback( void *buf_id, int size ) {
-	int done_tx = (int) buf_id;
-	struct sk_buff *skb = tx_ring_skb[done_tx];
-	pci_unmap_single(NULL, tx_ring_dma[done_tx], skb->len,
-	                 PCI_DMA_TODEVICE);
-	stats.tx_packets++;
-	stats.tx_bytes += size;
-	dev_kfree_skb_irq(skb);
-	tx_ring_skb[done_tx] = NULL;
-}
-
-
-For drivers expecting variable length packets i.e. USB client, it is
-necessary to register the appropriate IRQ to be notified when the receiver
-is idle, the packet is complete, etc.  We could use one buffer at a time
-with its ID being the virtual address of the buffer.
-
-Then the sequence:
-
-	/* be sure DMA won't continue under our feet */
-	sa1100_dma_stop(channel);
-	/* get the actual DMA length */
-	sa1100_get_current(channel, &data, &dma_ptr);
-	/* acquire ownership for the buffer */
-	sa1100_dma_flush_all(channel);
-	/* unmap the DMA buffer (actually doing cache coherency on ARM) */
-	pci_unmap_single (NULL, dma_addr, MAX_PKT_SIZE, PCI_DMA_FROMDEVICE);
-	/* get remaining bytes from the fifo */
-	ptr = data + dma_ptr - dma_addr;
-	while (fifo_not_empty)
-		*ptr++ = get_byte_from_fifo;
-	/* feed another free buffer for the next packet */
-	dma_addr2 = pci_map_single(NULL, data2, MAX_PKT_SIZE,
-					PCI_DMA_FROMDEVICE);
-	sa1100_dma_queue_buffer(channel, data2, dma_addr2, MAX_PKT_SIZE);
-	/* process the current packet */
-	...
-
-might do the trick.  This looks a bit ugly but that's a starting point for
-improvements.
-
-
-TODO
-----
-
-- Create kernel-doc comments in the source to document the API and
-  let the documentation be generated automatically.
-
-
diff -Nru a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt
--- a/Documentation/driver-model/binding.txt	Mon Jan 13 10:18:06 2003
+++ b/Documentation/driver-model/binding.txt	Mon Jan 13 10:18:06 2003
@@ -60,7 +60,7 @@
 driver's list of devices. 
 
 
-driverfs
+sysfs
 ~~~~~~~~
 
 A symlink is created in the bus's 'devices' directory that points to
@@ -71,7 +71,7 @@
 
 A directory for the device is created in the class's directory. A
 symlink is created in that directory that points to the device's
-physical location in the driverfs tree. 
+physical location in the sysfs tree. 
 
 A symlink can be created (though this isn't done yet) in the device's
 physical directory to either its class directory, or the class's
diff -Nru a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt
--- a/Documentation/driver-model/bus.txt	Mon Jan 13 10:18:06 2003
+++ b/Documentation/driver-model/bus.txt	Mon Jan 13 10:18:06 2003
@@ -131,7 +131,7 @@
 lock is not held when calling the callback. 
 
 
-driverfs
+sysfs
 ~~~~~~~~
 There is a top-level directory named 'bus'.
 
@@ -184,7 +184,7 @@
 static bus_attribute bus_attr_debug;
 
 This can then be used to add and remove the attribute from the bus's
-driverfs directory using:
+sysfs directory using:
 
 int bus_create_file(struct bus_type *, struct bus_attribute *);
 void bus_remove_file(struct bus_type *, struct bus_attribute *);
diff -Nru a/Documentation/driver-model/class.txt b/Documentation/driver-model/class.txt
--- a/Documentation/driver-model/class.txt	Mon Jan 13 10:18:05 2003
+++ b/Documentation/driver-model/class.txt	Mon Jan 13 10:18:05 2003
@@ -91,9 +91,9 @@
 the struct device_driver::devclass field. 
 
 
-driverfs directory structure
+sysfs directory structure
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There is a top-level driverfs directory named 'class'. 
+There is a top-level sysfs directory named 'class'. 
 
 Each class gets a directory in the class directory, along with two
 default subdirectories:
@@ -143,13 +143,13 @@
 static devclass_attribute devclass_attr_debug;
 
 The bus driver can add and remove the attribute from the class's
-driverfs directory using:
+sysfs directory using:
 
 int devclass_create_file(struct device_class *, struct devclass_attribute *);
 void devclass_remove_file(struct device_class *, struct devclass_attribute *);
 
 In the example above, the file will be named 'debug' in placed in the
-class's directory in driverfs. 
+class's directory in sysfs. 
 
 
 Interfaces
diff -Nru a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
--- a/Documentation/driver-model/device.txt	Mon Jan 13 10:18:06 2003
+++ b/Documentation/driver-model/device.txt	Mon Jan 13 10:18:06 2003
@@ -64,7 +64,7 @@
 
 bus:	       Pointer to struct bus_type that device belongs to.
 
-dir:	       Device's driverfs directory.
+dir:	       Device's sysfs directory.
 
 driver:	       Pointer to struct device_driver that controls the device.
 
@@ -125,8 +125,8 @@
 Attributes of devices can be exported via drivers using a simple
 procfs-like interface. 
 
-Please see Documentation/filesystems/driverfs.txt for more information
-on how driverfs works.
+Please see Documentation/filesystems/sysfs.txt for more information
+on how sysfs works.
 
 Attributes are declared using a macro called DEVICE_ATTR:
 
diff -Nru a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
--- a/Documentation/driver-model/driver.txt	Mon Jan 13 10:18:06 2003
+++ b/Documentation/driver-model/driver.txt	Mon Jan 13 10:18:06 2003
@@ -147,10 +147,10 @@
 accesses it. 
 
 
-driverfs
+sysfs
 ~~~~~~~~
 
-When a driver is registered, a driverfs directory is created in its
+When a driver is registered, a sysfs directory is created in its
 bus's directory. In this directory, the driver can export an interface
 to userspace to control operation of the driver on a global basis;
 e.g. toggling debugging output in the driver.
@@ -268,7 +268,7 @@
         ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
 };
 
-Device drivers can export attributes via their driverfs directories. 
+Device drivers can export attributes via their sysfs directories. 
 Drivers can declare attributes using a DRIVER_ATTR macro that works
 identically to the DEVICE_ATTR macro. 
 
diff -Nru a/Documentation/driver-model/interface.txt b/Documentation/driver-model/interface.txt
--- a/Documentation/driver-model/interface.txt	Mon Jan 13 10:18:06 2003
+++ b/Documentation/driver-model/interface.txt	Mon Jan 13 10:18:06 2003
@@ -81,7 +81,7 @@
 Devices are enumerated within the interface. This happens in interface_add_data()
 and the enumerated value is stored in the struct intf_data for that device. 
 
-driverfs
+sysfs
 ~~~~~~~~
 Each interface is given a directory in the directory of the device
 class it belongs to:
diff -Nru a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt
--- a/Documentation/driver-model/overview.txt	Mon Jan 13 10:18:05 2003
+++ b/Documentation/driver-model/overview.txt	Mon Jan 13 10:18:05 2003
@@ -80,17 +80,17 @@
 By virtue of having a complete hierarchical view of all the devices in the
 system, exporting a complete hierarchical view to userspace becomes relatively
 easy. This has been accomplished by implementing a special purpose virtual
-file system named driverfs. It is hence possible for the user to mount the
-whole driverfs filesystem anywhere in userspace.
+file system named sysfs. It is hence possible for the user to mount the
+whole sysfs filesystem anywhere in userspace.
 
 This can be done permanently by providing the following entry into the
 /etc/fstab (under the provision that the mount point does exist, of course):
 
-none     	/devices	driverfs    defaults		0	0
+none     	/devices	sysfs    defaults		0	0
 
 Or by hand on the command line:
 
-~: mount -t driverfs none /devices
+~: mount -t sysfs none /devices
 
 Whenever a device is inserted into the tree, a directory is created for it.
 This directory may be populated at each layer of discovery - the global layer,
@@ -108,7 +108,7 @@
 A device-specific driver may also export files in its directory to expose
 device-specific data or tunable interfaces.
 
-More information about the driverfs directory layout can be found in
+More information about the sysfs directory layout can be found in
 the other documents in this directory and in the file 
-Documentation/filesystems/driverfs.txt.
+Documentation/filesystems/sysfs.txt.
 
diff -Nru a/Documentation/driver-model/porting.txt b/Documentation/driver-model/porting.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/driver-model/porting.txt	Mon Jan 13 10:18:07 2003
@@ -0,0 +1,445 @@
+
+Porting Drivers to the New Driver Model
+
+Patrick Mochel
+
+7 January 2003
+
+
+Overview
+
+Please refer to Documentation/driver-model/*.txt for definitions of
+various driver types and concepts. 
+
+Most of the work of porting devices drivers to the new model happens
+at the bus driver layer. This was intentional, to minimize the
+negative effect on kernel drivers, and to allow a gradual transition
+of bus drivers.
+
+In a nutshell, the driver model consists of a set of objects that can
+be embedded in larger, bus-specific objects. Fields in these generic
+objects can replace fields in the bus-specific objects. 
+
+The generic objects must be registered with the driver model core. By
+doing so, they will exported via the sysfs filesystem. sysfs can be
+mounted by doing 
+
+	# mount -t sysfs sysfs /sys
+
+
+
+The Process
+
+Step 0: Read include/linux/device.h for object and function definitions. 
+
+Step 1: Registering the bus driver. 
+
+
+- Define a struct bus_type for the bus driver.
+
+struct bus_type pci_bus_type = {
+        .name           = "pci",
+};
+
+
+- Register the bus type.
+  This should be done in the initialization function for the bus type,
+  which is usually the module_init(), or equivalent, function. 
+
+static int __init pci_driver_init(void)
+{
+        return bus_register(&pci_bus_type);
+}
+
+subsys_initcall(pci_driver_init);
+
+
+  The bus type may be unregistered (if the bus driver may be compiled
+  as a module) by doing:
+
+     bus_unregister(&pci_bus_type);
+
+
+- Export the bus type for others to use. 
+
+  Other code may wish to reference the bus type, so declare it in a 
+  shared header file and export the symbol.
+
+From include/linux/pci.h:
+
+extern struct bus_type pci_bus_type;
+
+
+From file the above code appears in:
+
+EXPORT_SYMBOL(pci_bus_type);
+
+
+
+- This will cause the bus to show up in /sys/bus/pci/ with two
+  subdirectories: 'devices' and 'drivers'.
+
+# tree -d /sys/bus/pci/
+/sys/bus/pci/
+|-- devices
+`-- drivers
+
+
+
+Step 2: Registering Devices. 
+
+struct device represents a single device. It mainly contains metadata
+describing the relationship the device has to other entities. 
+
+
+- Embedd a struct device in the bus-specific device type. 
+
+
+struct pci_dev {
+       ...
+       struct  device  dev;            /* Generic device interface */
+       ...
+};
+
+  It is recommended that the generic device not be the first item in 
+  the struct to discourage programmers from doing mindless casts
+  between the object types. Instead macros, or inline functions,
+  should be created to convert from the generic object type.
+
+
+#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
+
+or 
+
+static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
+{
+	return container_of(n, struct pci_dev, dev);
+}
+
+  This allows the compiler to verify type-safety of the operations 
+  that are performed (which is Good).
+
+
+- Initialize the device on registration.
+
+  When devices are discovered or registered with the bus type, the 
+  bus driver should initialize the generic device. The most important
+  things to initialize are the bus_id, parent, and bus fields.
+
+  The bus_id is an ASCII string that contains the device's address on
+  the bus. The format of this string is bus-specific. This is
+  necessary for representing device in sysfs. 
+
+  parent is the physical parent of the device. It is important that
+  the bus driver sets this field correctly. 
+
+  The driver model maintains an ordered list of devices that it uses
+  for power management. This list must be in order to guarantee that
+  devices are shutdown before their physical parents, and vice versa.
+  The order of this list is determined by the parent of registered
+  devices.
+
+  Also, the location of the device's sysfs directory depends on a
+  device's parent. sysfs exports a directory structure that mirrors 
+  the device hierarchy. Accurately setting the parent guarantees that
+  sysfs will accurately represent the hierarchy.
+
+  The device's bus field is a pointer to the bus type the device
+  belongs to. This should be set to the bus_type that was declared
+  and initialized before. 
+
+  Optionally, the bus driver may set the device's name and release
+  fields.
+
+  The name field is an ASCII string describing the device, like
+
+     "ATI Technologies Inc Radeon QD"
+
+  The release field is a callback that the driver model core calls 
+  when the device has been removed, and all references to it have 
+  been released. More on this in a moment.
+
+
+- Register the device. 
+
+  Once the generic device has been initialized, it can be registered
+  with the driver model core by doing:
+
+       device_register(&dev->dev);
+
+  It can later be unregistered by doing: 
+
+       device_unregister(&dev->dev);
+
+  This should happen on buses that support hotpluggable devices. 
+  If a bus driver unregisters a device, it should not immediately free
+  it. It should instead wait for the driver model core to call the 
+  device's release method, then free the bus-specific object. 
+  (There may be other code that is currently referencing the device
+  structure, and it would be rude to free the device while that is 
+  happening).
+
+
+  When the device is registered, a directory in sysfs is created. 
+  The PCI tree in sysfs looks like: 
+
+/sys/devices/pci0/
+|-- 00:00.0
+|-- 00:01.0
+|   `-- 01:00.0
+|-- 00:02.0
+|   `-- 02:1f.0
+|       `-- 03:00.0
+|-- 00:1e.0
+|   `-- 04:04.0
+|-- 00:1f.0
+|-- 00:1f.1
+|   |-- ide0
+|   |   |-- 0.0
+|   |   `-- 0.1
+|   `-- ide1
+|       `-- 1.0
+|-- 00:1f.2
+|-- 00:1f.3
+`-- 00:1f.5
+
+  Also, symlinks are created in the bus's 'devices' directory
+  that point to the device's directory in the physical hierarchy. 
+
+/sys/bus/pci/devices/
+|-- 00:00.0 -> ../../../devices/pci0/00:00.0
+|-- 00:01.0 -> ../../../devices/pci0/00:01.0
+|-- 00:02.0 -> ../../../devices/pci0/00:02.0
+|-- 00:1e.0 -> ../../../devices/pci0/00:1e.0
+|-- 00:1f.0 -> ../../../devices/pci0/00:1f.0
+|-- 00:1f.1 -> ../../../devices/pci0/00:1f.1
+|-- 00:1f.2 -> ../../../devices/pci0/00:1f.2
+|-- 00:1f.3 -> ../../../devices/pci0/00:1f.3
+|-- 00:1f.5 -> ../../../devices/pci0/00:1f.5
+|-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0
+|-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0
+|-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0
+`-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0
+
+
+
+Step 3: Registering Drivers.
+
+struct device_driver is a simple driver structure that contains a set
+of operations that the driver model core may call. 
+
+
+- Embed a struct device_driver in the bus-specific driver. 
+
+  Just like with devices, do something like:
+
+struct pci_driver {
+       ...
+       struct device_driver    driver;
+};
+
+
+- Initialize the generic driver structure. 
+
+  When the driver registers with the bus (e.g. doing pci_register_driver()),
+  initialize the necessary fields of the driver: the name and bus
+  fields. 
+
+
+- Register the driver.
+
+  After the generic driver has been initialized, call
+
+	driver_register(&drv->driver);
+
+  to register the driver with the core.
+
+  When the driver is unregistered from the bus, unregister it from the
+  core by doing:
+
+        driver_unregister(&drv->driver);
+
+  Note that this will block until all references to the driver have
+  gone away. Normally, there will not be any.
+
+
+- Sysfs representation.
+
+  Drivers are exported via sysfs in their bus's 'driver's directory. 
+  For example:
+
+/sys/bus/pci/drivers/
+|-- 3c59x
+|-- Ensoniq AudioPCI
+|-- agpgart-amdk7
+|-- e100
+`-- serial
+
+
+Step 4: Define Generic Methods for Drivers.
+
+struct device_driver defines a set of operations that the driver model
+core calls. Most of these operations are probably similar to
+operations the bus already defines for drivers, but taking different
+parameters. 
+
+It would be difficult and tedious to force every driver on a bus to
+simultaneously convert their drivers to generic format. Instead, the
+bus driver should define single instances of the generic methods that
+forward calls to the bus-specific drivers. For instance: 
+
+
+static int pci_device_remove(struct device * dev)
+{
+        struct pci_dev * pci_dev = to_pci_dev(dev);
+        struct pci_driver * drv = pci_dev->driver;
+
+        if (drv) {
+                if (drv->remove)
+                        drv->remove(pci_dev);
+                pci_dev->driver = NULL;
+        }
+        return 0;
+}
+
+
+The generic driver should be initialized with these methods before it
+is registered. 
+
+        /* initialize common driver fields */
+        drv->driver.name = drv->name;
+        drv->driver.bus = &pci_bus_type;
+        drv->driver.probe = pci_device_probe;
+        drv->driver.resume = pci_device_resume;
+        drv->driver.suspend = pci_device_suspend;
+        drv->driver.remove = pci_device_remove;
+
+        /* register with core */
+        driver_register(&drv->driver);
+
+
+Ideally, the bus should only initialize the fields if they are not
+already set. This allows the drivers to implement their own generic
+methods. 
+
+
+Step 5: Support generic driver binding. 
+
+The model assumes that a device or driver can be dynamically
+registered with the bus at any time. When registration happens,
+devices must be bound to a driver, or drivers must be bound to all
+devices that it supports. 
+
+Drivers typically contain a list of device IDs that it supports. The
+bus driver compares this ID to the ID of devices registered with it. 
+The format of the device IDs, and the semantics for comparing them are
+bus-specific, so the generic model does attempt to generalize them. 
+
+Instead, a bus may supply a method in struct bus_type that does the
+comparison: 
+
+  int (*match)(struct device * dev, struct device_driver * drv);
+
+match should return '1' if the driver supports the device, and '0'
+otherwise. 
+
+When a device is registered, the bus's list of drivers is iterated
+over. bus->match() is called for each one until a match is found. 
+
+When a driver is registered, the bus's list of devices is iterated
+over. bus->match() is called for each device that is not already
+claimed by a driver. 
+
+When a device is successfully bound to a device, device->driver is
+set, the device is added to a per-driver list of devices, and a
+symlink is created in the driver's sysfs directory that points to the
+device's physical directory:
+
+/sys/bus/pci/drivers/
+|-- 3c59x
+|   `-- 00:0b.0 -> ../../../../devices/pci0/00:0b.0
+|-- Ensoniq AudioPCI
+|-- agpgart-amdk7
+|   `-- 00:00.0 -> ../../../../devices/pci0/00:00.0
+|-- e100
+|   `-- 00:0c.0 -> ../../../../devices/pci0/00:0c.0
+`-- serial
+
+
+This driver binding should replace the existing driver binding
+mechanism the bus currently uses. 
+
+
+Step 6: Supply a hotplug callback.
+
+Whenever a device is registered with the driver model core, the
+userspace program /sbin/hotplug is called to notify userspace. 
+Users can define actions to perform when a device is inserted or
+removed. 
+
+The driver model core passes several arguments to userspace via
+environment variables, including
+
+- ACTION: set to 'add' or 'remove'
+- DEVPATH: set to the device's physical path in sysfs. 
+
+A bus driver may also supply additional parameters for userspace to
+consume. To do this, a bus must implement the 'hotplug' method in
+struct bus_type:
+
+     int (*hotplug) (struct device *dev, char **envp, 
+                     int num_envp, char *buffer, int buffer_size);
+
+This is called immediately before /sbin/hotplug is executed. 
+
+
+Step 7: Cleaning up the bus driver.
+
+The generic bus, device, and driver structures provide several fields
+that can replace those define privately to the bus driver. 
+
+- Device list.
+
+struct bus_type contains a list of all devices registered with the bus
+type. This includes all devices on all instances of that bus type.
+An internal list that the bus uses may be removed, in favor of using
+this one.
+
+The core provides an iterator to access these devices. 
+
+int bus_for_each_dev(struct bus_type * bus, struct device * start, 
+                     void * data, int (*fn)(struct device *, void *));
+
+
+- Driver list.
+
+struct bus_type also contains a list of all drivers registered with
+it. An internal list of drivers that the bus driver maintains may 
+be removed in favor of using the generic one. 
+
+The drivers may be iterated over, like devices: 
+
+int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
+                     void * data, int (*fn)(struct device_driver *, void *));
+
+
+Please see drivers/base/bus.c for more information.
+
+
+- rwsem 
+
+struct bus_type contains an rwsem that protects all core accesses to
+the device and driver lists. This can be used by the bus driver
+internally, and should be used when accessing the device or driver
+lists the bus maintains. 
+
+
+- Device and driver fields. 
+
+Some of the fields in struct device and struct device_driver duplicate
+fields in the bus-specific representations of these objects. Feel free
+to remove the bus-specific ones and favor the generic ones. Note
+though, that this will likely mean fixing up all the drivers that
+reference the bus-specific fields (though those should all be 1-line
+changes).
+
diff -Nru a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
--- a/Documentation/filesystems/sysfs.txt	Mon Jan 13 10:18:05 2003
+++ b/Documentation/filesystems/sysfs.txt	Mon Jan 13 10:18:05 2003
@@ -3,10 +3,10 @@
 
 Patrick Mochel	<mochel@osdl.org>
 
-17 October 2002
+10 January 2003
 
 
-Note (17 Oct 2002): the name has just been changed from driverfs to
+Note (17 Oct 2002): the name has just been changed from sysfs to
 sysfs. Updates to the documentation will come soon; after the
 conversion to use it is completely finished.
 
@@ -14,216 +14,274 @@
 
 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. 
+sysfs is a ram-based filesystem initially based on ramfs. It provides
+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. 
+sysfs is tied inherently to the kobject infrastructure. Please read
+Documentation/kobject.txt for more information concerning the kobject
+interface. 
 
 
-Using driverfs
-~~~~~~~~~~~~~~
-driverfs is always compiled in. You can access it by doing something like:
+Using sysfs
+~~~~~~~~~~~
 
-    mount -t driverfs driverfs /devices 
+sysfs is always compiled in. You can access it by doing:
 
+    mount -t sysfs sysfs /sys 
 
-Top Level Directory Layout
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-The driverfs directory arrangement exposes the relationship of kernel
-data structures. 
 
-The top level driverfs diretory looks like:
+Directory Creation
+~~~~~~~~~~~~~~~~~~
 
-bus/
-root/
+For every kobject that is registered with the system, a directory is
+created for it in sysfs. That directory is created as a subdirectory
+of the kobject's parent, expressing internal object hierarchies to
+userspace. Top-level directories in sysfs represent the common
+ancestors of object hierarchies; i.e. the subsystems the objects
+belong to. 
+
+Sysfs internally stores the kobject that owns the directory in the
+->d_fsdata pointer of the directory's dentry. This allows sysfs to do
+reference counting directly on the kobject when the file is opened and
+closed. 
 
-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:
+Attributes
+~~~~~~~~~~
 
-	devices/
-	drivers/
+Attributes can be exported for kobjects in the form of regular files in
+the filesystem. Sysfs forwards file I/O operations to methods defined
+for the attributes, providing a means to read and write kernel
+attributes.
+
+Attributes should be ASCII text files, preferably with only one value
+per file. It is noted that it may not be efficient to contain only
+value per file, so it is socially acceptable to express an array of
+values of the same type. 
+
+Mixing types, expressing mulitple lines of data, and doing fancy
+formatting of data is heavily frowned upon. Doing these things may get
+you publically humiliated and your code rewritten without notice. 
 
-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).
+An attriubte definition is simply:
 
+struct attribute {
+        char                    * name;
+        mode_t                  mode;
+};
 
-More information can device-model specific features can be found in
-Documentation/device-model/. 
 
+int sysfs_create_file(struct kobject * kobj, struct attribute * attr);
+void sysfs_remove_file(struct kobject * kobj, struct attribute * attr);
 
-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. 
+A bare attribute contains no means to read or write the value of the
+attribute. Subsystems are encouraged to define their own attribute
+structure and wrapper functions for adding and removing attributes for
+a specific object type. 
 
-There should be few, if any, exceptions to this rule. You should not
-violate it, for fear of public humilation.
+For example, the driver model defines struct device_attribute like:
 
+struct device_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device * dev, char * buf);
+        ssize_t (*store)(struct device * dev, const char * buf);
+};
 
-The Two-Tier Model
-~~~~~~~~~~~~~~~~~~
+int device_create_file(struct device *, struct device_attribute *);
+void device_remove_file(struct device *, struct device_attribute *);
 
-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. 
+It also defines this helper for defining device attributes: 
 
-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. 
+#define DEVICE_ATTR(_name,_mode,_show,_store)      \
+struct device_attribute dev_attr_##_name = {            \
+        .attr = {.name  = __stringify(_name) , .mode   = _mode },      \
+        .show   = _show,                                \
+        .store  = _store,                               \
+};
 
+For example, declaring
 
-The Subsystem Interface
-~~~~~~~~~~~~~~~~~~~~~~~
+static DEVICE_ATTR(foo,0644,show_foo,store_foo);
 
-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. 
+is equivalent to doing:
 
-It's divided into three sections: directories, files, and operations.
+static struct device_attribute dev_attr_foo = {
+       .attr	= {
+		.name = "foo",
+		.mode = 0644,
+	},
+	.show = show_foo,
+	.store = store_foo,
+};
 
 
-Directories
-~~~~~~~~~~~
+Subsystem-Specific Callbacks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-struct driver_dir_entry {
-        char                    * name;
-        struct dentry           * dentry;
-        mode_t                  mode;
-        struct driverfs_ops     * ops;
+When a subsystem defines a new attribute type, they must implement a
+set of sysfs operations for forwarding read and write calls to the
+show and store methods of the attribute owners. 
+
+struct sysfs_ops {
+        ssize_t (*show)(struct kobject *, struct attribute *,char *);
+        ssize_t (*store)(struct kobject *,struct attribute *,const char *);
 };
 
+[ Subsystems should have already defined a struct kobj_type as a
+descriptor for this type, which is where the sysfs_ops pointer is
+stored. See the kobject documentation for more information. ]
 
-int
-driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
+When a file is read or written, sysfs calls the appropriate method
+for the type. The method then translates the generic struct kobject
+and struct attribute pointers to the appropriate pointer types, and
+calls the associated methods. 
 
-void
-driverfs_remove_dir(struct driver_dir_entry * entry);
 
-The directory structure should be statically allocated, and reside in
-a subsystem-specific data structure:
+To illustrate:
 
-struct device {
-       ...
-       struct driver_dir_entry	dir;
-};
+#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+#define to_dev(d) container_of(d, struct device, kobj)
 
-The subsystem is responsible for initializing the name, mode, and ops
-fields of the directory entry. (More on struct driverfs_ops later)
+static ssize_t
+dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+        struct device_attribute * dev_attr = to_dev_attr(attr);
+        struct device * dev = to_dev(kobj);
+        ssize_t ret = 0;
 
+        if (dev_attr->show)
+                ret = dev_attr->show(dev,buf);
+        return ret;
+}
 
-Files
-~~~~~
 
-struct attribute {
-        char                    * name;
-        mode_t                  mode;
-};
 
+Reading/Writing Attribute Data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-int
-driverfs_create_file(struct attribute * attr, struct driver_dir_entry * parent);
+To read or write attributes, show() or store() methods must be
+specified when declaring the attribute. The method types should be as
+simple as those defined for device attributes:
 
-void
-driverfs_remove_file(struct driver_dir_entry *, const char * name);
+        ssize_t (*show)(struct device * dev, char * buf);
+        ssize_t (*store)(struct device * dev, const char * buf);
 
+IOW, they should take only an object and a buffer as parameters. 
 
-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.
+sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
+method. Sysfs will call the method exactly once for each read or
+write. This forces the following behavior on the method
+implementations: 
 
-An example looks like this:
+- On read(2), the show() method should fill the entire buffer. 
+  Recall that an attribute should only be exporting one value, or an
+  array of similar values, so this shouldn't be that expensive. 
 
-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);
-};
+  This allows userspace to do partial reads and seeks arbitrarily over
+  the entire file at will. 
 
+- On write(2), sysfs expects the entire buffer to be passed during the
+  first write. Sysfs then passes the entire buffer to the store()
+  method. 
+  
+  When writing sysfs files, userspace processes should first read the
+  entire file, modify the values it wishes to change, then write the
+  entire buffer back. 
 
-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:
+  Attribute method implementations should operate on an identical
+  buffer when reading and writing values. 
 
-#define DEVICE_ATTR(_name,_mode,_show,_store)      \
-struct device_attribute dev_attr_##_name = {            \
-        .attr = {.name  = __stringify(_name) , .mode   = _mode },      \
-        .show   = _show,                                \
-        .store  = _store,                               \
-};
+Other notes:
 
-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>.
+- The buffer will always be PAGE_SIZE bytes in length. On i386, this
+  is 4096. 
 
-In order for objects to create files, the subsystem should create
-wrapper functions, like this:
+- show() methods should return the number of bytes printed into the
+  buffer. This is the return value of snprintf().
 
-int device_create_file(struct device *device, struct device_attribute * entry);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
+- show() should always use snprintf(). 
 
-..and forward the call on to the driverfs functions.
+- store() should return the number of bytes used from the buffer. This
+  can be done using strlen().
 
-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. 
+- show() or store() can always return errors. If a bad value comes
+  through, be sure and return an error.
 
+- The object passed to the methods will be pinned in memory via sysfs
+  referencing counting its embedded object. However, the physical 
+  entity (e.g. device) the object represents may not be present. Be 
+  sure to have a way to check this, if necessary. 
 
-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);
-};
+A very simple (and naive) implementation of a device attribute is:
 
+static ssize_t show_name(struct device * dev, char * buf)
+{
+        return sprintf(buf,"%s\n",dev->name);
+}
 
-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:
+static ssize_t store_name(struct device * dev, const char * buf)
+{
+	sscanf(buf,"%20s",dev->name);
+	return strlen(buf);
+}
 
-#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+static DEVICE_ATTR(name,S_IRUGO,show_name,store_name);
+
+
+(Note that the real implementation doesn't allow userspace to set the 
+name for a device).
+
+
+Top Level Directory Layout
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The sysfs directory arrangement exposes the relationship of kernel
+data structures. 
+
+The top level sysfs diretory looks like:
+
+block/
+bus/
+class/
+devices/
+firmware/
+net/
+
+devices/ 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:
 
-#define to_device(d) container_of(d, struct device, dir)
+	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/. 
+
+
+TODO: Finish this section.
 
-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:
+The following interface layers currently exist in sysfs:
 
 
 - devices (include/linux/device.h)
@@ -232,8 +290,8 @@
 
 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);
+        ssize_t (*show)(struct device * dev, char * buf);
+        ssize_t (*store)(struct device * dev, const char * buf);
 };
 
 Declaring:
@@ -242,7 +300,7 @@
 
 Creation/Removal:
 
-int device_create_file(struct device *device, struct device_attribute * entry);
+int device_create_file(struct device *device, struct device_attribute * attr);
 void device_remove_file(struct device * dev, struct device_attribute * attr);
 
 
@@ -252,8 +310,8 @@
 
 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);
+        ssize_t (*show)(struct bus_type *, char * buf);
+        ssize_t (*store)(struct bus_type *, const char * buf);
 };
 
 Declaring:
@@ -273,8 +331,8 @@
 
 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);
+        ssize_t (*show)(struct device_driver *, char * buf);
+        ssize_t (*store)(struct device_driver *, const char * buf);
 };
 
 Declaring:
@@ -286,57 +344,4 @@
 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/rpc-cache.txt b/Documentation/rpc-cache.txt
--- a/Documentation/rpc-cache.txt	Mon Jan 13 10:18:05 2003
+++ b/Documentation/rpc-cache.txt	Mon Jan 13 10:18:05 2003
@@ -148,7 +148,7 @@
 added to the channel but instead all looks that do not find a valid
 entry will fail.  This is partly for backward compatability: The
 previous nfs exports table was deemed to be authoritative and a
-failed lookup meant a definate 'no'.
+failed lookup meant a definite 'no'.
 
 request/response format
 -----------------------
diff -Nru a/Documentation/vm/locking b/Documentation/vm/locking
--- a/Documentation/vm/locking	Mon Jan 13 10:18:05 2003
+++ b/Documentation/vm/locking	Mon Jan 13 10:18:05 2003
@@ -66,10 +66,9 @@
 expand_stack(), it is hard to come up with a destructive scenario without 
 having the vmlist protection in this case.
 
-The page_table_lock nests with the inode i_shared_lock and the kmem cache
-c_spinlock spinlocks. This is okay, since code that holds i_shared_lock 
-never asks for memory, and the kmem code asks for pages after dropping
-c_spinlock. The page_table_lock also nests with pagecache_lock and 
+The page_table_lock nests with the inode i_shared_sem and the kmem cache
+c_spinlock spinlocks.  This is okay, since the kmem code asks for pages after
+dropping c_spinlock.  The page_table_lock also nests with pagecache_lock and
 pagemap_lru_lock spinlocks, and no code asks for memory with these locks
 held.
 
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Mon Jan 13 10:18:05 2003
+++ b/Makefile	Mon Jan 13 10:18:05 2003
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 56
+SUBLEVEL = 57
 EXTRAVERSION =
 
 # *DOCUMENTATION*
diff -Nru a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
--- a/arch/alpha/mm/init.c	Mon Jan 13 10:18:07 2003
+++ b/arch/alpha/mm/init.c	Mon Jan 13 10:18:07 2003
@@ -34,7 +34,7 @@
 #include <asm/console.h>
 #include <asm/tlb.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S
--- a/arch/alpha/vmlinux.lds.S	Mon Jan 13 10:18:06 2003
+++ b/arch/alpha/vmlinux.lds.S	Mon Jan 13 10:18:06 2003
@@ -32,6 +32,13 @@
 	__stop___ksymtab = .;
   }
 
+  /* Kernel symbol table: GPL only */
+  __gpl_ksymtab ALIGN(8) : {
+	__start___gpl_ksymtab = .;
+	*(__gpl_ksymtab)
+	__stop___gpl_ksymtab = .;
+  }
+
   /* All kernel symbols */
   __kallsyms ALIGN(8) : {
 	__start___kallsyms = .;
diff -Nru a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
--- a/arch/arm/boot/compressed/head.S	Mon Jan 13 10:18:07 2003
+++ b/arch/arm/boot/compressed/head.S	Mon Jan 13 10:18:07 2003
@@ -366,9 +366,12 @@
 		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
 		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
 		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
-		orr	r0, r0, #0x1000		@ I-cache enable
+		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
 		orr	r0, r0, #0x0030
-		b	__common_cache_on
+		bl	__common_cache_on
+		mov	r0, #0
+		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
+		mov	pc, r12
 
 __arm6_cache_on:
 		mov	r12, lr
@@ -377,6 +380,11 @@
 		mcr	p15, 0, r0, c7, c0, 0	@ invalidate whole cache v3
 		mcr	p15, 0, r0, c5, c0, 0	@ invalidate whole TLB v3
 		mov	r0, #0x30
+		bl	__common_cache_on
+		mov	r0, #0
+		mcr	p15, 0, r0, c5, c0, 0	@ invalidate whole TLB v3
+		mov	pc, r12
+
 __common_cache_on:
 #ifndef DEBUG
 		orr	r0, r0, #0x000d		@ Write buffer, mmu
@@ -385,7 +393,7 @@
 		mcr	p15, 0, r3, c2, c0, 0	@ load page table pointer
 		mcr	p15, 0, r1, c3, c0, 0	@ load domain access control
 		mcr	p15, 0, r0, c1, c0, 0	@ load control register
-		mov	pc, r12
+		mov	pc, lr
 
 /*
  * All code following this line is relocatable.  It is relocated by
@@ -567,11 +575,12 @@
 __armv4_cache_flush:
 		bic	r1, pc, #31
 		add	r2, r1, #65536		@ 2x the largest dcache size
-1:		ldr	r12, [r1], #32		@ s/w flush D cache
+1:		ldr	r3, [r1], #32		@ s/w flush D cache
 		teq	r1, r2
 		bne	1b
 
-		mcr	p15, 0, r1, c7, c7, 0	@ flush I cache
+		mcr	p15, 0, r1, c7, c5, 0	@ flush I cache
+		mcr	p15, 0, r1, c7, c6, 0	@ flush D cache
 		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
 		mov	pc, lr
 
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	Mon Jan 13 10:18:07 2003
+++ b/arch/arm/kernel/ecard.c	Mon Jan 13 10:18:07 2003
@@ -978,6 +978,8 @@
 	strcpy(ec->dev.name, "fixme!");
 	ec->dev.parent = NULL;
 	ec->dev.bus    = &ecard_bus_type;
+	ec->dev.dma_mask = &ec->dma_mask;
+	ec->dma_mask = (u64)0xffffffff;
 
 	device_register(&ec->dev);
 
diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
--- a/arch/arm/kernel/setup.c	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/kernel/setup.c	Mon Jan 13 10:18:06 2003
@@ -81,7 +81,7 @@
 unsigned long phys_initrd_size __initdata = 0;
 
 static struct meminfo meminfo __initdata = { 0, };
-static struct proc_info_item proc_info;
+static const char *cpu_name;
 static const char *machine_name;
 static char command_line[COMMAND_LINE_SIZE];
 
@@ -275,7 +275,7 @@
 		while (1);
 	}
 
-	proc_info = *list->info;
+	cpu_name = list->cpu_name;
 
 #ifdef MULTI_CPU
 	processor = *list->proc;
@@ -287,9 +287,9 @@
 	cpu_user = *list->user;
 #endif
 
-	printk("CPU: %s %s revision %d (ARMv%s)\n",
-	       proc_info.manufacturer, proc_info.cpu_name,
-	       (int)processor_id & 15, proc_arch[cpu_architecture()]);
+	printk("CPU: %s [%08x] revision %d (ARMv%s)\n",
+	       cpu_name, processor_id, (int)processor_id & 15,
+	       proc_arch[cpu_architecture()]);
 
 	dump_cpu_info();
 
@@ -723,9 +723,8 @@
 {
 	int i;
 
-	seq_printf(m, "Processor\t: %s %s rev %d (%s)\n",
-		   proc_info.manufacturer, proc_info.cpu_name,
-		   (int)processor_id & 15, elf_platform);
+	seq_printf(m, "Processor\t: %s rev %d (%s)\n",
+		   cpu_name, (int)processor_id & 15, elf_platform);
 
 	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 		   loops_per_jiffy / (500000/HZ),
diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
--- a/arch/arm/mach-integrator/cpu.c	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/mach-integrator/cpu.c	Mon Jan 13 10:18:06 2003
@@ -97,18 +97,43 @@
 	return 0;
 }
 
-static void do_set_policy(int cpu, struct cpufreq_policy *policy)
+static int integrator_set_policy(struct cpufreq_policy *policy)
 {
-	struct vco vco = freq_to_vco(policy->max, 1);
+	unsigned long cpus_allowed;
+	int cpu = policy->cpu;
+	struct vco vco;
+	struct cpufreq_freqs freqs;
 	u_int cm_osc;
 
 	/*
+	 * Save this threads cpus_allowed mask.
+	 */
+	cpus_allowed = current->cpus_allowed;
+
+	/*
 	 * Bind to the specified CPU.  When this call returns,
 	 * we should be running on the right CPU.
 	 */
 	set_cpus_allowed(current, 1 << cpu);
 	BUG_ON(cpu != smp_processor_id());
 
+	/* get current setting */
+	cm_osc = __raw_readl(CM_OSC);
+	vco.od = (cm_osc >> 8) & 7;
+	vco.vdw = cm_osc & 255;
+
+	freqs.old = vco_to_freq(vco, 1);
+	freqs.new = target_freq;
+	freqs.cpu = policy->cpu;
+
+	if (freqs.old == freqs.new) {
+		set_cpus_allowed(current, cpus_allowed);
+		return 0;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	vco = freq_to_vco(policy->max, 1);
+
 	cm_osc = __raw_readl(CM_OSC);
 	cm_osc &= 0xfffff800;
 	cm_osc |= vco.vdw | vco.od << 8;
@@ -116,32 +141,14 @@
 	__raw_writel(0xa05f, CM_LOCK);
 	__raw_writel(cm_osc, CM_OSC);
 	__raw_writel(0, CM_LOCK);
-}
-
-static int integrator_set_policy(struct cpufreq_policy *policy)
-{
-	unsigned long cpus_allowed;
-	int cpu;
-
-	/*
-	 * Save this threads cpus_allowed mask.
-	 */
-	cpus_allowed = current->cpus_allowed;
-
-	if (policy->cpu == CPUFREQ_ALL_CPUS) {
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			if (!cpu_online(cpu))
-				continue;
-			do_set_policy(cpu, policy);
-		}
-	} else
-		do_set_policy(policy->cpu, policy);
 
 	/*
 	 * Restore the CPUs allowed mask.
 	 */
 	set_cpus_allowed(current, cpus_allowed);
 
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
 	return 0;
 }
 
@@ -149,8 +156,8 @@
 	.cpu		= 0,
 	.policy		= CPUFREQ_POLICY_POWERSAVE,
 	.cpuinfo	= {
-		.max_cpu_freq		= 160000,
-		.min_cpu_freq		= 12000,
+		.max_freq		= 160000,
+		.min_freq		= 12000,
 		.transition_latency	= CPUFREQ_ETERNAL,
 	},
 };
@@ -168,7 +175,7 @@
 	unsigned long cpus_allowed;
 	int cpu;
 
-	policies = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS,
+	policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS,
 			   GFP_KERNEL);
 	if (!policies) {
 		printk(KERN_ERR "CPU: unable to allocate policies structure\n");
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
--- a/arch/arm/mach-sa1100/cpu-sa1100.c	Mon Jan 13 10:18:05 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c	Mon Jan 13 10:18:05 2003
@@ -183,7 +183,7 @@
 
 	freqs.old = cur;
 	freqs.new = policy->max;
-	freqs.cpu = CPUFREQ_ALL_CPUS;
+	freqs.cpu = 0;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
--- a/arch/arm/mach-sa1100/cpu-sa1110.c	Mon Jan 13 10:18:05 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c	Mon Jan 13 10:18:05 2003
@@ -242,7 +242,7 @@
 
 	freqs.old = sa11x0_getspeed();
 	freqs.new = policy->max;
-	freqs.cpu = CPUFREQ_ALL_CPUS;
+	freqs.cpu = 0;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
--- a/arch/arm/mm/consistent.c	Mon Jan 13 10:18:07 2003
+++ b/arch/arm/mm/consistent.c	Mon Jan 13 10:18:07 2003
@@ -1,48 +1,156 @@
 /*
  *  linux/arch/arm/mm/consistent.c
  *
- *  Copyright (C) 2000 Russell King
+ *  Copyright (C) 2000-2002 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  Dynamic DMA mapping support.
+ *  DMA uncached mapping support.
  */
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/mm.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
-#include <linux/pci.h>
+#include <linux/list.h>
 #include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+#define CONSISTENT_BASE	(0xffc00000)
+#define CONSISTENT_END	(0xffe00000)
+#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
 
 /*
- * This allocates one page of cache-coherent memory space and returns
- * both the virtual and a "dma" address to that space.
+ * This is the page table (2MB) covering uncached, DMA consistent allocations
+ */
+static pte_t *consistent_pte;
+static spinlock_t consistent_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * VM region handling support.
  *
- * We should allow this function to be called from interrupt context.
- * However, we call ioremap, which needs to fiddle around with various
- * things (like the vmlist_lock, and allocating page tables).  These
- * things aren't interrupt safe (yet).
+ * This should become something generic, handling VM region allocations for
+ * vmalloc and similar (ioremap, module space, etc).
  *
- * Note that this does *not* zero the allocated area!
+ * I envisage vmalloc()'s supporting vm_struct becoming:
+ *
+ *  struct vm_struct {
+ *    struct vm_region	region;
+ *    unsigned long	flags;
+ *    struct page	**pages;
+ *    unsigned int	nr_pages;
+ *    unsigned long	phys_addr;
+ *  };
+ *
+ * get_vm_area() would then call vm_region_alloc with an appropriate
+ * struct vm_region head (eg):
+ *
+ *  struct vm_region vmalloc_head = {
+ *	.vm_list	= LIST_HEAD_INIT(vmalloc_head.vm_list),
+ *	.vm_start	= VMALLOC_START,
+ *	.vm_end		= VMALLOC_END,
+ *  };
+ *
+ * However, vmalloc_head.vm_start is variable (typically, it is dependent on
+ * the amount of RAM found at boot time.)  I would imagine that get_vm_area()
+ * would have to initialise this each time prior to calling vm_region_alloc().
  */
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+struct vm_region {
+	struct list_head	vm_list;
+	unsigned long		vm_start;
+	unsigned long		vm_end;
+};
+
+static struct vm_region consistent_head = {
+	.vm_list	= LIST_HEAD_INIT(consistent_head.vm_list),
+	.vm_start	= CONSISTENT_BASE,
+	.vm_end		= CONSISTENT_END,
+};
+
+#if 0
+static void vm_region_dump(struct vm_region *head, char *fn)
 {
-	struct page *page, *end, *free;
-	unsigned long order;
-	void *ret;
+	struct vm_region *c;
 
-	/* FIXME */
-	if (in_interrupt())
-		BUG();
+	printk("Consistent Allocation Map (%s):\n", fn);
+	list_for_each_entry(c, &head->list, vm_list) {
+		printk(" %p:  %08lx - %08lx   (0x%08x)\n", c,
+		       c->vm_start, c->vm_end, c->vm_end - c->vm_start);
+	}
+}
+#else
+#define vm_region_dump(head,fn)	do { } while(0)
+#endif
+
+static int vm_region_alloc(struct vm_region *head, struct vm_region *new, size_t size)
+{
+	unsigned long addr = head->vm_start, end = head->vm_end - size;
+	struct vm_region *c;
+
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if ((addr + size) < addr)
+			goto out;
+		if ((addr + size) <= c->vm_start)
+			goto found;
+		addr = c->vm_end;
+		if (addr > end)
+			goto out;
+	}
+
+ found:
+	/*
+	 * Insert this entry _before_ the one we found.
+	 */
+	list_add_tail(&new->vm_list, &c->vm_list);
+	new->vm_start = addr;
+	new->vm_end = addr + size;
+
+	return 0;
+
+ out:
+	return -ENOMEM;
+}
+
+static struct vm_region *vm_region_find(struct vm_region *head, unsigned long addr)
+{
+	struct vm_region *c;
+	
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if (c->vm_start == addr)
+			goto out;
+	}
+	c = NULL;
+ out:
+	return c;
+}
+
+/*
+ * This allocates one page of cache-coherent memory space and returns
+ * both the virtual and a "dma" address to that space.
+ */
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle,
+		       unsigned long cache_flags)
+{
+	struct page *page;
+	struct vm_region *c;
+	unsigned long order, flags;
+	void *ret = NULL;
+
+	if (!consistent_pte) {
+		printk(KERN_ERR "consistent_alloc: not initialised\n");
+		dump_stack();
+		return NULL;
+	}
 
 	size = PAGE_ALIGN(size);
 	order = get_order(size);
@@ -51,75 +159,177 @@
 	if (!page)
 		goto no_page;
 
-	*dma_handle = page_to_bus(page);
-	ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, 0,
-			PAGE_SIZE << order);
-	if (!ret)
+	/*
+	 * Invalidate any data that might be lurking in the
+	 * kernel direct-mapped region.
+	 */
+	{
+		unsigned long kaddr = (unsigned long)page_address(page);
+		invalidate_dcache_range(kaddr, kaddr + size);
+	}
+
+	/*
+	 * Our housekeeping doesn't need to come from DMA,
+	 * but it must not come from highmem.
+	 */
+	c = kmalloc(sizeof(struct vm_region),
+		    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+	if (!c)
 		goto no_remap;
 
-#if 0 /* ioremap_does_flush_cache_all */
-	{
-		void *virt = page_address(page);
+	spin_lock_irqsave(&consistent_lock, flags);
+	vm_region_dump(&consistent_head, "before alloc");
+
+	/*
+	 * Attempt to allocate a virtual address in the
+	 * consistent mapping region.
+	 */
+	if (!vm_region_alloc(&consistent_head, c, size)) {
+		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+		struct page *end = page + (1 << order);
+		pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
+					 L_PTE_DIRTY | L_PTE_WRITE |
+					 cache_flags);
 
 		/*
-		 * we need to ensure that there are no cachelines in use, or
-		 * worse dirty in this area.  Really, we don't need to do
-		 * this since __ioremap does a flush_cache_all() anyway. --rmk
+		 * Set the "dma handle"
 		 */
-		invalidate_dcache_range(virt, virt + size);
-	}
-#endif
+		*handle = page_to_bus(page);
 
-	/*
-	 * free wasted pages.  We skip the first page since we know
-	 * that it will have count = 1 and won't require freeing.
-	 * We also mark the pages in use as reserved so that
-	 * remap_page_range works.
-	 */
-	free = page + (size >> PAGE_SHIFT);
-	end  = page + (1 << order);
+		do {
+			BUG_ON(!pte_none(*pte));
 
-	for (; page < end; page++) {
-		set_page_count(page, 1);
-		if (page >= free)
-			__free_page(page);
-		else
+			set_page_count(page, 1);
 			SetPageReserved(page);
+			set_pte(pte, mk_pte(page, prot));
+			page++;
+			pte++;
+		} while (size -= PAGE_SIZE);
+
+		/*
+		 * Free the otherwise unused pages.
+		 */
+		while (page < end) {
+			set_page_count(page, 1);
+			__free_page(page);
+			page++;
+		}
+
+		ret = (void *)c->vm_start;
 	}
-	return ret;
 
-no_remap:
-	__free_pages(page, order);
-no_page:
-	return NULL;
+	vm_region_dump(&consistent_head, "after alloc");
+	spin_unlock_irqrestore(&consistent_lock, flags);
+
+ no_remap:
+	if (ret == NULL) {
+		kfree(c);
+		__free_pages(page, order);
+	}
+ no_page:
+	return ret;
 }
 
 /*
- * free a page as defined by the above mapping.  We expressly forbid
- * calling this from interrupt context.
+ * free a page as defined by the above mapping.
  */
 void consistent_free(void *vaddr, size_t size, dma_addr_t handle)
 {
-	struct page *page, *end;
+	struct vm_region *c;
+	unsigned long flags;
+	pte_t *ptep;
 
-	if (in_interrupt())
-		BUG();
-
-	/*
-	 * More messing around with the MM internals.  This is
-	 * sick, but then so is remap_page_range().
-	 */
 	size = PAGE_ALIGN(size);
-	page = virt_to_page(bus_to_virt(handle));
-	end = page + (size >> PAGE_SHIFT);
 
-	for (; page < end; page++)
-		ClearPageReserved(page);
+	spin_lock_irqsave(&consistent_lock, flags);
+	vm_region_dump(&consistent_head, "before free");
 
-	__iounmap(vaddr);
+	c = vm_region_find(&consistent_head, (unsigned long)vaddr);
+	if (!c)
+		goto no_area;
+
+	if ((c->vm_end - c->vm_start) != size) {
+		printk(KERN_ERR "consistent_free: wrong size (%ld != %d)\n",
+		       c->vm_end - c->vm_start, size);
+		dump_stack();
+		size = c->vm_end - c->vm_start;
+	}
+
+	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+	do {
+		pte_t pte = ptep_get_and_clear(ptep);
+		unsigned long pfn;
+
+		ptep++;
+
+		if (!pte_none(pte) && pte_present(pte)) {
+			pfn = pte_pfn(pte);
+
+			if (pfn_valid(pfn)) {
+				struct page *page = pfn_to_page(pfn);
+				ClearPageReserved(page);
+
+				__free_page(page);
+				continue;
+			}
+		}
+
+		printk(KERN_CRIT "consistent_free: bad page in kernel page "
+		       "table\n");
+	} while (size -= PAGE_SIZE);
+
+	flush_tlb_kernel_range(c->vm_start, c->vm_end);
+
+	list_del(&c->vm_list);
+
+	vm_region_dump(&consistent_head, "after free");
+	spin_unlock_irqrestore(&consistent_lock, flags);
+
+	kfree(c);
+	return;
+
+ no_area:
+	spin_unlock_irqrestore(&consistent_lock, flags);
+	printk(KERN_ERR "consistent_free: trying to free "
+	       "invalid area: %p\n", vaddr);
+	dump_stack();
 }
 
 /*
+ * Initialise the consistent memory allocation.
+ */
+static int __init consistent_init(void)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	do {
+		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
+		pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+		if (!pmd) {
+			printk(KERN_ERR "consistent_init: out of pmd tables\n");
+			return -ENOMEM;
+		}
+		if (!pmd_none(*pmd)) {
+			printk(KERN_ERR "consistent_init: PMD already allocated\n");
+			return -EINVAL;
+		}
+		pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE);
+		if (!pte) {
+			printk(KERN_ERR "consistent_init: out of pte tables\n");
+			return -ENOMEM;
+		}
+
+		consistent_pte = pte;
+	} while (0);
+
+	return 0;
+}
+
+core_initcall(consistent_init);
+
+/*
  * make an area consistent.
  */
 void consistent_sync(void *vaddr, size_t size, int direction)
@@ -128,16 +338,16 @@
 	unsigned long end   = start + size;
 
 	switch (direction) {
-	case PCI_DMA_NONE:
-		BUG();
-	case PCI_DMA_FROMDEVICE:	/* invalidate only */
+	case DMA_FROM_DEVICE:		/* invalidate only */
 		invalidate_dcache_range(start, end);
 		break;
-	case PCI_DMA_TODEVICE:		/* writeback only */
+	case DMA_TO_DEVICE:		/* writeback only */
 		clean_dcache_range(start, end);
 		break;
-	case PCI_DMA_BIDIRECTIONAL:	/* writeback and invalidate */
+	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
 		flush_dcache_range(start, end);
 		break;
+	default:
+		BUG();
 	}
 }
diff -Nru a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c
--- a/arch/arm/mm/extable.c	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/mm/extable.c	Mon Jan 13 10:18:06 2003
@@ -1,19 +1,13 @@
 /*
  *  linux/arch/arm/mm/extable.c
  */
-
 #include <linux/config.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
-		 const struct exception_table_entry *last,
-		 unsigned long value)
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+	       const struct exception_table_entry *last,
+	       unsigned long value)
 {
         while (first <= last) {
 		const struct exception_table_entry *mid;
@@ -22,44 +16,11 @@
 		mid = (last - first) / 2 + first;
 		diff = mid->insn - value;
                 if (diff == 0)
-                        return mid->fixup;
+                        return mid;
                 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;
-
-#ifndef CONFIG_MODULES
-	/* There is only the kernel to search.  */
-	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-#else
-	unsigned long flags;
-	struct list_head *l;
-
-	ret = 0;
-	/* The kernel is the last "module" -- no need to treat it special.  */
-	spin_lock_irqsave(&modlist_lock, flags);
-	list_for_each(l, &extables) {
-		struct exception_table *ex
-			= list_entry(l, struct exception_table, list);
-		if (ex->num_entries == 0)
-			continue;
-		ret = search_one_table(ex->entry,
-				       ex->entry + ex->num_entries - 1, addr);
-		if (ret)
-			break;
-	}
-	spin_unlock_irqrestore(&modlist_lock, flags);
-#endif
-
-	return ret;
+        return NULL;
 }
diff -Nru a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
--- a/arch/arm/mm/fault-common.c	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/mm/fault-common.c	Mon Jan 13 10:18:06 2003
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -102,23 +103,25 @@
 __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
 		  struct pt_regs *regs)
 {
-	unsigned long fixup;
+	const struct exception_table_entry *fixup;
 
 	/*
 	 * Are we prepared to handle this kernel fault?
 	 */
-	if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
+	fixup = search_exception_tables(instruction_pointer(regs));
+	if (fixup) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
-			current->comm, regs->ARM_pc, addr, fixup);
+			current->comm, regs->ARM_pc, addr, fixup->fixup);
 #endif
-		regs->ARM_pc = fixup;
+		regs->ARM_pc = fixup->fixup;
 		return;
 	}
 
 	/*
 	 * No handler, we'll have to terminate things with extreme prejudice.
 	 */
+	bust_spinlocks(1);
 	printk(KERN_ALERT
 		"Unable to handle kernel %s at virtual address %08lx\n",
 		(addr < PAGE_SIZE) ? "NULL pointer dereference" :
@@ -126,6 +129,7 @@
 
 	show_pte(mm, addr);
 	die("Oops", regs, fsr);
+	bust_spinlocks(0);
 	do_exit(SIGKILL);
 }
 
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	Mon Jan 13 10:18:05 2003
+++ b/arch/arm/mm/init.c	Mon Jan 13 10:18:05 2003
@@ -47,7 +47,7 @@
 
 #define TABLE_SIZE	((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(pte_t))
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern char _stext, _text, _etext, _end, __init_begin, __init_end;
diff -Nru a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
--- a/arch/arm/mm/proc-arm1020.S	Mon Jan 13 10:18:05 2003
+++ b/arch/arm/mm/proc-arm1020.S	Mon Jan 13 10:18:05 2003
@@ -420,8 +420,6 @@
 	mov	pc, lr
 
 
-cpu_manu_name:
-	.asciz	"ARM/VLSI"
 ENTRY(cpu_arm1020_name)
 	.ascii	"Arm1020"
 #ifndef CONFIG_CPU_ICACHE_DISABLE
@@ -518,15 +516,9 @@
 
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
-	.type	cpu_arm1020_info, #object
-cpu_arm1020_info:
-	.long	cpu_manu_name
-	.long	cpu_arm1020_name
-	.size	cpu_arm1020_info, . - cpu_arm1020_info
-
 	.type	cpu_arch_name, #object
 cpu_arch_name:
-	.asciz	"armv4"
+	.asciz	"armv4t"
 	.size	cpu_arch_name, . - cpu_arch_name
 
 	.type	cpu_elf_name, #object
@@ -546,7 +538,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-	.long	cpu_arm1020_info
+	.long	cpu_arm1020_name
 	.long	arm1020_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
diff -Nru a/arch/arm/mm/proc-arm2_3.S b/arch/arm/mm/proc-arm2_3.S
--- a/arch/arm/mm/proc-arm2_3.S	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/mm/proc-arm2_3.S	Mon Jan 13 10:18:06 2003
@@ -276,10 +276,12 @@
 _arm2_3_check_bugs:
 		bics	pc, lr, #0x04000000		@ Clear FIQ disable bit
 
-armvlsi_name:	.asciz	"ARM/VLSI"
-_arm2_name:	.asciz	"ARM 2"
-_arm250_name:	.asciz	"ARM 250"
-_arm3_name:	.asciz	"ARM 3"
+cpu_arm2_name:
+		.asciz	"ARM 2"
+cpu_arm250_name:
+		.asciz	"ARM 250"
+cpu_arm3_name:
+		.asciz	"ARM 3"
 
 		__INIT
 /*
@@ -295,10 +297,6 @@
 		.word	_arm2_xchg_1
 		.word	_arm2_xchg_4
 
-cpu_arm2_info:
-		.long	armvlsi_name
-		.long	_arm2_name
-
 		.globl	arm250_processor_functions
 arm250_processor_functions:
 		.word	_arm2_3_check_bugs
@@ -308,10 +306,6 @@
 		.word	_arm3_xchg_1
 		.word	_arm3_xchg_4
 
-cpu_arm250_info:
-		.long	armvlsi_name
-		.long	_arm250_name
-
 		.globl	arm3_processor_functions
 arm3_processor_functions:
 		.word	_arm2_3_check_bugs
@@ -321,10 +315,6 @@
 		.word	_arm3_xchg_1
 		.word	_arm3_xchg_4
 
-cpu_arm3_info:
-		.long	armvlsi_name
-		.long	_arm3_name
-
 arm2_arch_name:	.asciz	"armv1"
 arm3_arch_name:	.asciz	"armv2"
 arm2_elf_name:	.asciz	"v1"
@@ -340,7 +330,7 @@
 		.long	arm2_arch_name
 		.long	arm2_elf_name
 		.long	0
-		.long	cpu_arm2_info
+		.long	cpu_arm2_name
 		.long	arm2_processor_functions
 		.long	0
 		.long	0
@@ -352,7 +342,7 @@
 		.long	arm3_arch_name
 		.long	arm3_elf_name
 		.long	0
-		.long	cpu_arm250_info
+		.long	cpu_arm250_name
 		.long	arm250_processor_functions
 		.long	0
 		.long	0
@@ -364,7 +354,7 @@
 		.long	arm3_arch_name
 		.long	arm3_elf_name
 		.long	0
-		.long	cpu_arm3_info
+		.long	cpu_arm3_name
 		.long	arm3_processor_functions
 		.long	0
 		.long	0
diff -Nru a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
--- a/arch/arm/mm/proc-arm6_7.S	Mon Jan 13 10:18:07 2003
+++ b/arch/arm/mm/proc-arm6_7.S	Mon Jan 13 10:18:07 2003
@@ -287,14 +287,12 @@
 		mcr	p15, 0, r1, c1, c0, 0		@ turn off MMU etc
 		mov	pc, r0
 
-cpu_armvlsi_name:
-		.asciz	"ARM/VLSI"
-cpu_arm6_name:	.asciz	"ARM 6"
+cpu_arm6_name:	.asciz	"ARM6"
 cpu_arm610_name:
-		.asciz	"ARM 610"
-cpu_arm7_name:	.asciz	"ARM 7"
+		.asciz	"ARM610"
+cpu_arm7_name:	.asciz	"ARM7"
 cpu_arm710_name:
-		.asciz	"ARM 710"
+		.asciz	"ARM710"
 		.align
 
 		__INIT
@@ -387,30 +385,6 @@
 
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
-		.type	cpu_arm6_info, #object
-cpu_arm6_info:
-		.long	cpu_armvlsi_name
-		.long	cpu_arm6_name
-		.size	cpu_arm6_info, . - cpu_arm6_info
-
-		.type	cpu_arm610_info, #object
-cpu_arm610_info:
-		.long	cpu_armvlsi_name
-		.long	cpu_arm610_name
-		.size	cpu_arm610_info, . - cpu_Arm610_info
-
-		.type	cpu_arm7_info, #object
-cpu_arm7_info:
-		.long	cpu_armvlsi_name
-		.long	cpu_arm7_name
-		.size	cpu_arm7_info, . - cpu_arm7_info
-
-		.type	cpu_arm710_info, #object
-cpu_arm710_info:
-		.long	cpu_armvlsi_name
-		.long	cpu_arm710_name
-		.size	cpu_arm710_info, . - cpu_arm710_info
-
 		.type	cpu_arch_name, #object
 cpu_arch_name:	.asciz	"armv3"
 		.size	cpu_arch_name, . - cpu_arch_name
@@ -431,7 +405,7 @@
 		.long	cpu_arch_name
 		.long	cpu_elf_name
 		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm6_info
+		.long	cpu_arm6_name
 		.long	arm6_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
@@ -446,7 +420,7 @@
 		.long	cpu_arch_name
 		.long	cpu_elf_name
 		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm610_info
+		.long	cpu_arm610_name
 		.long	arm6_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
@@ -461,7 +435,7 @@
 		.long	cpu_arch_name
 		.long	cpu_elf_name
 		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm7_info
+		.long	cpu_arm7_name
 		.long	arm7_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
@@ -476,7 +450,7 @@
 		.long	cpu_arch_name
 		.long	cpu_elf_name
 		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm710_info
+		.long	cpu_arm710_name
 		.long	arm7_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
diff -Nru a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
--- a/arch/arm/mm/proc-arm720.S	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/mm/proc-arm720.S	Mon Jan 13 10:18:06 2003
@@ -168,8 +168,6 @@
 		mov	pc, r0
 
 	
-cpu_armvlsi_name:
-		.asciz	"ARM"
 cpu_arm720_name:
 		.asciz	"ARM720T"
 		.align
@@ -223,14 +221,8 @@
 
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
-		.type	cpu_arm720_info, #object
-cpu_arm720_info:
-		.long	cpu_armvlsi_name
-		.long	cpu_arm720_name
-		.size	cpu_arm720_info, . - cpu_arm720_info
-	
 		.type	cpu_arch_name, #object
-cpu_arch_name:	.asciz	"armv4"
+cpu_arch_name:	.asciz	"armv4t"
 		.size	cpu_arch_name, . - cpu_arch_name
 
 		.type	cpu_elf_name, #object
@@ -253,7 +245,7 @@
 		.long	cpu_arch_name				@ arch_name
 		.long	cpu_elf_name				@ elf_name
 		.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB	@ elf_hwcap
-		.long	cpu_arm720_info				@ info
+		.long	cpu_arm720_name				@ name
 		.long	arm720_processor_functions
 		.long	v4_tlb_fns
 		.long	v4wt_user_fns
diff -Nru a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
--- a/arch/arm/mm/proc-arm920.S	Mon Jan 13 10:18:05 2003
+++ b/arch/arm/mm/proc-arm920.S	Mon Jan 13 10:18:05 2003
@@ -419,8 +419,6 @@
 	mov	pc, lr
 
 
-cpu_manu_name:
-	.asciz	"ARM/CIRRUS"
 ENTRY(cpu_arm920_name)
 	.ascii	"Arm920T"
 #ifndef CONFIG_CPU_ICACHE_DISABLE
@@ -506,15 +504,9 @@
 
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
-	.type	cpu_arm920_info, #object
-cpu_arm920_info:
-	.long	cpu_manu_name
-	.long	cpu_arm920_name
-	.size	cpu_arm920_info, . - cpu_arm920_info
-
 	.type	cpu_arch_name, #object
 cpu_arch_name:
-	.asciz	"armv4"
+	.asciz	"armv4t"
 	.size	cpu_arch_name, . - cpu_arch_name
 
 	.type	cpu_elf_name, #object
@@ -534,7 +526,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-	.long	cpu_arm920_info
+	.long	cpu_arm920_name
 	.long	arm920_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
diff -Nru a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
--- a/arch/arm/mm/proc-arm922.S	Mon Jan 13 10:18:07 2003
+++ b/arch/arm/mm/proc-arm922.S	Mon Jan 13 10:18:07 2003
@@ -418,8 +418,6 @@
 	mov	pc, lr
 
 
-cpu_manu_name:
-	.asciz	"ARM/ALTERA"
 ENTRY(cpu_arm922_name)
 	.ascii	"Arm922T"
 #ifndef CONFIG_CPU_ICACHE_DISABLE
@@ -505,15 +503,9 @@
 
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
-	.type	cpu_arm922_info, #object
-cpu_arm922_info:
-	.long	cpu_manu_name
-	.long	cpu_arm922_name
-	.size	cpu_arm922_info, . - cpu_arm922_info
-
 	.type	cpu_arch_name, #object
 cpu_arch_name:
-	.asciz	"armv4"
+	.asciz	"armv4t"
 	.size	cpu_arch_name, . - cpu_arch_name
 
 	.type	cpu_elf_name, #object
@@ -533,7 +525,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-	.long	cpu_arm922_info
+	.long	cpu_arm922_name
 	.long	arm922_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
diff -Nru a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
--- a/arch/arm/mm/proc-arm926.S	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/mm/proc-arm926.S	Mon Jan 13 10:18:06 2003
@@ -403,8 +403,6 @@
 	mov	pc, lr
 
 
-cpu_manu_name:
-	.asciz	"ARM"
 ENTRY(cpu_arm926_name)
 	.ascii	"ARM926EJ-S"
 #ifndef CONFIG_CPU_ICACHE_DISABLE
@@ -503,12 +501,6 @@
 
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
-	.type	cpu_arm926_info, #object
-cpu_arm926_info:
-	.long	cpu_manu_name
-	.long	cpu_arm926_name
-	.size	cpu_arm926_info, . - cpu_arm926_info
-
 	.type	cpu_arch_name, #object
 cpu_arch_name:
 	.asciz	"armv5tej"
@@ -532,7 +524,7 @@
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \
 		HWCAP_FAST_MULT | HWCAP_JAVA
-	.long	cpu_arm926_info
+	.long	cpu_arm926_name
 	.long	arm926_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
diff -Nru a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
--- a/arch/arm/mm/proc-sa110.S	Mon Jan 13 10:18:06 2003
+++ b/arch/arm/mm/proc-sa110.S	Mon Jan 13 10:18:06 2003
@@ -473,8 +473,6 @@
 	mov	pc, lr
 
 
-cpu_manu_name:
-	.asciz	"Intel"
 cpu_sa110_name:
 	.asciz	"StrongARM-110"
 cpu_sa1100_name:
@@ -547,13 +545,6 @@
 
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
-	.type	cpu_sa110_info, #object
-cpu_sa110_info:
-	.long	cpu_manu_name
-	.long	cpu_sa110_name
-	.size	cpu_sa110_info, . - cpu_sa110_info
-
-
 /*
  * SA1100 and SA1110 share the same function calls
  */
@@ -587,16 +578,6 @@
 
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
-cpu_sa1100_info:
-	.long	cpu_manu_name
-	.long	cpu_sa1100_name
-	.size	cpu_sa1100_info, . - cpu_sa1100_info
-
-cpu_sa1110_info:
-	.long	cpu_manu_name
-	.long	cpu_sa1110_name
-	.size	cpu_sa1110_info, . - cpu_sa1110_info
-
 	.type	cpu_arch_name, #object
 cpu_arch_name:
 	.asciz	"armv4"
@@ -620,7 +601,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
-	.long	cpu_sa110_info
+	.long	cpu_sa110_name
 	.long	sa110_processor_functions
 	.long	v4wb_tlb_fns
 	.long	v4wb_user_fns
@@ -637,7 +618,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
-	.long	cpu_sa1100_info
+	.long	cpu_sa1100_name
 	.long	sa1100_processor_functions
 	.long	v4wb_tlb_fns
 	.long	v4_mc_user_fns
@@ -652,7 +633,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
-	.long	cpu_sa1110_info
+	.long	cpu_sa1110_name
 	.long	sa1100_processor_functions
 	.long	v4wb_tlb_fns
 	.long	v4_mc_user_fns
diff -Nru a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
--- a/arch/arm/mm/proc-xscale.S	Mon Jan 13 10:18:07 2003
+++ b/arch/arm/mm/proc-xscale.S	Mon Jan 13 10:18:07 2003
@@ -651,9 +651,6 @@
 
 	.ltorg
 
-cpu_manu_name:
-	.asciz	"Intel"
-
 cpu_80200_name:
 	.asciz	"XScale-80200"
 
@@ -723,24 +720,6 @@
 	.word	cpu_xscale_set_pte
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
-	.type	cpu_80200_info, #object
-cpu_80200_info:
-	.long	cpu_manu_name
-	.long	cpu_80200_name
-	.size	cpu_80200_info, . - cpu_80200_info
-
-	.type	cpu_pxa250_info, #object
-cpu_pxa250_info:
-	.long	cpu_manu_name
-	.long	cpu_pxa250_name
-	.size	cpu_pxa250_info, . - cpu_pxa250_info
-
-	.type	cpu_pxa210_info, #object
-cpu_pxa210_info:
-	.long	cpu_manu_name
-	.long	cpu_pxa210_name
-	.size	cpu_pxa210_info, . - cpu_pxa210_info
-
 	.type	cpu_arch_name, #object
 cpu_arch_name:
 	.asciz	"armv5te"
@@ -763,7 +742,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_80200_info
+	.long	cpu_80200_name
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
@@ -778,7 +757,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_pxa250_info
+	.long	cpu_pxa250_name
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
@@ -793,7 +772,7 @@
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_pxa210_info
+	.long	cpu_pxa210_name
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
--- a/arch/arm/vmlinux-armo.lds.in	Mon Jan 13 10:18:07 2003
+++ b/arch/arm/vmlinux-armo.lds.in	Mon Jan 13 10:18:07 2003
@@ -78,6 +78,12 @@
 		__stop___ksymtab = .;
 	}
 
+	__gpl_ksymtab : {		/* Kernel symbol table: GPL-only */
+		__start___gpl_ksymtab = .;
+			*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+	}
+
 	.data : {
 		/*
 		 * The cacheline aligned data
diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
--- a/arch/arm/vmlinux-armv.lds.in	Mon Jan 13 10:18:05 2003
+++ b/arch/arm/vmlinux-armv.lds.in	Mon Jan 13 10:18:05 2003
@@ -75,6 +75,12 @@
 		__stop___ex_table = .;
 	}
 
+	__gpl_ksymtab : {		/* GPL Kernel symbol table	*/
+		__start___gpl_ksymtab = .;
+			*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+	}
+
 	__ksymtab : {			/* Kernel symbol table		*/
 		__start___ksymtab = .;
 			*(__ksymtab)
diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S
--- a/arch/cris/vmlinux.lds.S	Mon Jan 13 10:18:06 2003
+++ b/arch/cris/vmlinux.lds.S	Mon Jan 13 10:18:06 2003
@@ -43,6 +43,10 @@
   	__ksymtab : { *(__ksymtab) }
   	__stop___ksymtab = .;
 
+	__start___gpl_ksymtab = .;    /* Kernel symbol table: GPL-only */
+	__gpl_ksymtab : { *(__gpl_ksymtab) }
+	__stop___gpl_ksymtab = .;
+
 	. = ALIGN (4);
 	___data_start = . ;
 	__Sdata = . ;
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/Kconfig	Mon Jan 13 10:18:05 2003
@@ -117,10 +117,10 @@
 	  (time stamp counter) register.
 	  - "Pentium-Classic" for the Intel Pentium.
 	  - "Pentium-MMX" for the Intel Pentium MMX.
-	  - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II.
-	  - "Pentium-III" for the Intel Pentium III
-	  and Celerons based on the Coppermine core.
-	  - "Pentium-4" for the Intel Pentium 4.
+	  - "Pentium-Pro" for the Intel Pentium Pro.
+	  - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron.
+	  - "Pentium-III" for the Intel Pentium III or Coppermine Celeron.
+	  - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron.
 	  - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
 	  - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
 	  - "Crusoe" for the Transmeta Crusoe series.
@@ -159,25 +159,37 @@
 	  extended instructions.
 
 config M686
-	bool "Pentium-Pro/Celeron/Pentium-II"
+	bool "Pentium-Pro"
 	help
-	  Select this for a Pro/Celeron/Pentium II.  This enables the use of
+	  Select this for Intel Pentium Pro chips.  This enables the use of
 	  Pentium Pro extended instructions, and disables the init-time guard
 	  against the f00f bug found in earlier Pentiums.
 
+config MPENTIUMII
+       bool "Pentium-II/Celeron(pre-Coppermine)"
+	help
+	  Select this for Intel chips based on the Pentium-II and
+	  pre-Coppermine Celeron core.  This option enables an unaligned
+	  copy optimization, compiles the kernel with optimization flags
+	  tailored for the chip, and applies any applicable Pentium Pro
+	  optimizations.
+
 config MPENTIUMIII
 	bool "Pentium-III/Celeron(Coppermine)"
 	help
 	  Select this for Intel chips based on the Pentium-III and
-	  Celeron-Coppermine core.  Enables use of some extended prefetch
-	  instructions, in addition to the Pentium II extensions.
+	  Celeron-Coppermine core.  This option enables use of some
+	  extended prefetch instructions in addition to the Pentium II
+	  extensions.
 
 config MPENTIUM4
-	bool "Pentium-4"
+	bool "Pentium-4/Celeron(P4-based)"
 	help
-	  Select this for Intel Pentium 4 chips.  Presently these are
-	  treated almost like Pentium IIIs, but with a different cache
-	  shift.
+	  Select this for Intel Pentium 4 chips.  This includes both
+	  the Pentium 4 and P4-based Celeron chips.  This option
+	  enables compile flags optimized for the chip, uses the
+	  correct cache shift, and applies any applicable Pentium III
+	  optimizations.
 
 config MK6
 	bool "K6/K6-II/K6-III"
@@ -258,7 +270,7 @@
 
 config X86_L1_CACHE_SHIFT
 	int
-	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || M686 || M586MMX || M586TSC || M586
+	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586
 	default "4" if MELAN || M486 || M386
 	default "6" if MK7 || MK8
 	default "7" if MPENTIUM4
@@ -310,22 +322,22 @@
 
 config X86_TSC
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || M586TSC || MK8
+	depends on MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8
 	default y
 
 config X86_GOOD_APIC
 	bool
-	depends on MK7 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || MK8
+	depends on MK7 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8
 	default y
 
 config X86_INTEL_USERCOPY
 	bool
-	depends on MPENTIUM4 || MPENTIUMIII || M586MMX
+	depends on MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M586MMX
 	default y
 
 config X86_USE_PPRO_CHECKSUM
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || MK8
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || MK8
 	default y
 
 config X86_USE_3DNOW
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/Makefile	Mon Jan 13 10:18:05 2003
@@ -34,6 +34,7 @@
 cflags-$(CONFIG_M586TSC)	+= -march=i586
 cflags-$(CONFIG_M586MMX)	+= $(call check_gcc,-march=pentium-mmx,-march=i586)
 cflags-$(CONFIG_M686)		+= -march=i686
+cflags-$(CONFIG_MPENTIUMII)	+= $(call check_gcc,-march=pentium2,-march=i686)
 cflags-$(CONFIG_MPENTIUMIII)	+= $(call check_gcc,-march=pentium3,-march=i686)
 cflags-$(CONFIG_MPENTIUM4)	+= $(call check_gcc,-march=pentium4,-march=i686)
 cflags-$(CONFIG_MK6)		+= $(call check_gcc,-march=k6,-march=i586)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
--- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Mon Jan 13 10:18:05 2003
@@ -61,6 +61,18 @@
 	{99000,	0x01,	0x05}
 };
 
+static struct cpufreq_frequency_table elanfreq_table[] = {
+	{0,	1000},
+	{1,	2000},
+	{2,	4000},
+	{3,	8000},
+	{4,	16000},
+	{5,	33000},
+	{6,	66000},
+	{7,	99000},
+	{0,	CPUFREQ_TABLE_END},
+};
+
 
 /**
  *	elanfreq_get_cpu_frequency: determine current cpu speed
@@ -172,63 +184,17 @@
 
 static int elanfreq_verify (struct cpufreq_policy *policy)
 {
-	unsigned int    number_states = 0;
-	unsigned int    i;
-
-	if (!policy || !max_freq)
-		return -EINVAL;
-
-	policy->cpu = 0;
-
-	cpufreq_verify_within_limits(policy, 1000, max_freq);
-
-	for (i=7; i>=0; i--)
-		if ((elan_multiplier[i].clock >= policy->min) &&
-		    (elan_multiplier[i].clock <= policy->max))
-			number_states++;
-
-	if (number_states)
-		return 0;
-
-	for (i=7; i>=0; i--)
-		if (elan_multiplier[i].clock < policy->max)
-			break;
-
-	policy->max = elan_multiplier[i+1].clock;
-
-	cpufreq_verify_within_limits(policy, 1000, max_freq);
-
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
 }
 
 static int elanfreq_setpolicy (struct cpufreq_policy *policy)
 {
-	unsigned int    i;
-	unsigned int    optimal = 8;
-
-	if (!elanfreq_driver)
-		return -EINVAL;
+	unsigned int    newstate = 0;
 
-	for (i=0; i<8; i++) {
-		if ((elan_multiplier[i].clock > policy->max) ||
-		    (elan_multiplier[i].clock < policy->min))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (optimal == 8)
-				optimal = i;
-			break;
-		case CPUFREQ_POLICY_PERFORMANCE:
-			optimal = i;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-	if ((optimal == 8) || (elan_multiplier[optimal].clock > max_freq))
+	if (cpufreq_frequency_table_setpolicy(policy, &elanfreq_table[0], &newstate))
 		return -EINVAL;
 
-	elanfreq_set_cpu_state(optimal);
+	elanfreq_set_cpu_state(newstate);
 
 	return 0;
 }
@@ -262,7 +228,7 @@
 {	
 	struct cpuinfo_x86 *c = cpu_data;
 	struct cpufreq_driver *driver;
-	int ret;
+	int ret, i;
 
 	/* Test if we have the right hardware */
 	if ((c->x86_vendor != X86_VENDOR_AMD) ||
@@ -282,6 +248,12 @@
 	if (!max_freq)
 		max_freq = elanfreq_get_cpu_frequency();
 
+	/* table init */
+ 	for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if (elanfreq_table[i].frequency > max_freq)
+			elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+	}
+
 #ifdef CONFIG_CPU_FREQ_24_API
 	driver->cpu_cur_freq[0] = elanfreq_get_cpu_frequency();
 #endif
@@ -290,11 +262,12 @@
 	driver->setpolicy     = &elanfreq_setpolicy;
 
 	driver->policy[0].cpu    = 0;
-	driver->policy[0].min    = 1000;
-	driver->policy[0].max    = max_freq;
+	ret = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &elanfreq_table[0]);
+	if (ret) {
+		kfree(driver);
+		return ret;
+	}
 	driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
-	driver->policy[0].cpuinfo.max_freq = max_freq;
-	driver->policy[0].cpuinfo.min_freq = 1000;
 	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
 	elanfreq_driver = driver;
diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Mon Jan 13 10:18:07 2003
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Mon Jan 13 10:18:07 2003
@@ -141,39 +141,27 @@
 }
 
 
+static struct cpufreq_frequency_table p4clockmod_table[] = {
+	{DC_RESV, CPUFREQ_ENTRY_INVALID},
+	{DC_DFLT, 0},
+	{DC_25PT, 0},
+	{DC_38PT, 0},
+	{DC_50PT, 0},
+	{DC_64PT, 0},
+	{DC_75PT, 0},
+	{DC_88PT, 0},
+	{DC_DISABLE, 0},
+	{DC_RESV, CPUFREQ_TABLE_END},
+};
+
+
 static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
 {
-	unsigned int    i;
-	unsigned int    newstate = 0;
-	unsigned int    number_states = 0;
-	unsigned int    minstate = 1;
+	unsigned int    newstate = DC_RESV;
 
-	if (!cpufreq_p4_driver || !stock_freq || 
-	    !policy || !cpu_online(policy->cpu))
+	if (cpufreq_frequency_table_setpolicy(policy, &p4clockmod_table[0], &newstate))
 		return -EINVAL;
 
-	if (has_N44_O17_errata)
-		minstate = 3;
-
-	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
-	{
-		for (i=8; i>=minstate; i--)
-			if ((policy->min <= ((stock_freq / 8) * i)) &&
-			    (policy->max >= ((stock_freq / 8) * i))) 
-			{
-				newstate = i;
-				number_states++;
-			}
-	} else {
-		for (i=minstate; i<=8; i++)
-			if ((policy->min <= ((stock_freq / 8) * i)) &&
-			    (policy->max >= ((stock_freq / 8) * i))) 
-			{
-				newstate = i;
-				number_states++;
-			}
-	}
-
 	cpufreq_p4_setdc(policy->cpu, newstate);
 
 	return 0;
@@ -182,34 +170,7 @@
 
 static int cpufreq_p4_verify(struct cpufreq_policy *policy)
 {
-	unsigned int    number_states = 0;
-	unsigned int    i = 1;
-
-	if (!cpufreq_p4_driver || !stock_freq || 
-	    !policy || !cpu_online(policy->cpu))
-		return -EINVAL;
-
-	cpufreq_verify_within_limits(policy, 
-				     policy->cpuinfo.min_freq, 
-				     policy->cpuinfo.max_freq);
-
-	if (has_N44_O17_errata)
-		i = 3;
-
-	/* is there at least one state within the limit? */
-	for (; i<=8; i++)
-		if ((policy->min <= ((stock_freq / 8) * i)) &&
-		    (policy->max >= ((stock_freq / 8) * i)))
-			number_states++;
-
-	if (number_states)
-		return 0;
-
-	policy->max = (stock_freq / 8) * (((unsigned int) ((policy->max * 8) / stock_freq)) + 1);
-	cpufreq_verify_within_limits(policy, 
-				     policy->cpuinfo.min_freq, 
-				     policy->cpuinfo.max_freq);
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]);
 }
 
 
@@ -262,6 +223,15 @@
 
 	driver->policy = (struct cpufreq_policy *) (driver + 1);
 
+	/* table init */
+	for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if ((i<2) && (has_N44_O17_errata))
+			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+		else
+			p4clockmod_table[i].frequency = (stock_freq * i)/8;
+	}
+	
+
 #ifdef CONFIG_CPU_FREQ_24_API
 	for (i=0;i<NR_CPUS;i++) {
 		driver->cpu_cur_freq[i] = stock_freq;
@@ -272,17 +242,14 @@
 	driver->setpolicy     = &cpufreq_p4_setpolicy;
 
 	for (i=0;i<NR_CPUS;i++) {
-		if (has_N44_O17_errata)
-			driver->policy[i].min    = (stock_freq * 3) / 8;
-		else
-			driver->policy[i].min    = stock_freq / 8;
-		driver->policy[i].max    = stock_freq;
+		driver->policy[i].cpu    = i;
+		ret = cpufreq_frequency_table_cpuinfo(&driver->policy[i], &p4clockmod_table[0]);
+		if (ret) {
+			kfree(driver);
+			return ret;
+		}
 		driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
-		driver->policy[i].cpuinfo.min_freq  = driver->policy[i].min;
-		driver->policy[i].cpuinfo.max_freq  = stock_freq;
 		driver->policy[i].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-
-		driver->policy[i].cpu    = i;
 	}
 
 	cpufreq_p4_driver = driver;
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Mon Jan 13 10:18:05 2003
@@ -31,15 +31,16 @@
 
 
 /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
-static int clock_ratio[8] = {
-	45,  /* 000 -> 4.5x */
-	50,  /* 001 -> 5.0x */
-	40,  /* 010 -> 4.0x */
-	55,  /* 011 -> 5.5x */
-	20,  /* 100 -> 2.0x */
-	30,  /* 101 -> 3.0x */
-	60,  /* 110 -> 6.0x */
-	35   /* 111 -> 3.5x */
+static struct cpufreq_frequency_table clock_ratio[] = {
+	{45,  /* 000 -> 4.5x */ 0},
+	{50,  /* 001 -> 5.0x */ 0},
+	{40,  /* 010 -> 4.0x */ 0},
+	{55,  /* 011 -> 5.5x */ 0},
+	{20,  /* 100 -> 2.0x */ 0},
+	{30,  /* 101 -> 3.0x */ 0},
+	{60,  /* 110 -> 6.0x */ 0},
+	{35,  /* 111 -> 3.5x */ 0},
+	{0, CPUFREQ_TABLE_END}
 };
 
 
@@ -60,7 +61,7 @@
 	msrval = POWERNOW_IOPORT + 0x0;
 	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
 
-	return clock_ratio[(invalue >> 5)&7];
+	return clock_ratio[(invalue >> 5)&7].index;
 }
 
 
@@ -82,7 +83,7 @@
 	}
 
 	freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
-	freqs.new = busfreq * clock_ratio[best_i];
+	freqs.new = busfreq * clock_ratio[best_i].index;
 	freqs.cpu = 0; /* powernow-k6.c is UP only driver */
 	
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -115,39 +116,7 @@
  */
 static int powernow_k6_verify(struct cpufreq_policy *policy)
 {
-	unsigned int    number_states = 0;
-	unsigned int    i, j;
-
-	if (!policy || !busfreq)
-		return -EINVAL;
-
-	policy->cpu = 0;
-	cpufreq_verify_within_limits(policy, (20 * busfreq),
-				     (max_multiplier * busfreq));
-
-	for (i=0; i<8; i++)
-		if ((policy->min <= (busfreq * clock_ratio[i])) &&
-		    (policy->max >= (busfreq * clock_ratio[i])))
-			number_states++;
-
-	if (number_states)
-		return 0;
-
-	/* no state is available within range -- find next larger state */
-
-	j = 6;
-
-	for (i=0; i<8; i++)
-		if (((clock_ratio[i] * busfreq) >= policy->min) &&
-		    (clock_ratio[i] < clock_ratio[j]))
-			j = i;
-
-	policy->max = clock_ratio[j] * busfreq;
-
-	cpufreq_verify_within_limits(policy, (20 * busfreq),
-				     (max_multiplier * busfreq));
-
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &clock_ratio[0]);
 }
 
 
@@ -159,43 +128,12 @@
  */
 static int powernow_k6_setpolicy (struct cpufreq_policy *policy)
 {
-	unsigned int    i;
-	unsigned int    optimal;
+	unsigned int    newstate = 0;
 
-	if (!powernow_driver || !policy || policy->cpu)
+	if (cpufreq_frequency_table_setpolicy(policy, &clock_ratio[0], &newstate))
 		return -EINVAL;
 
-	switch(policy->policy) {
-	case CPUFREQ_POLICY_POWERSAVE:
-		optimal = 6;
-		break;
-	case CPUFREQ_POLICY_PERFORMANCE:
-		optimal = max_multiplier;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (i=0;i<8;i++) {
-		unsigned int freq = busfreq * clock_ratio[i];
-		if (clock_ratio[i] > max_multiplier)
-			continue;
-		if ((freq > policy->max) ||
-		    (freq < policy->min))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (freq < (clock_ratio[optimal] * busfreq))
-				optimal = i;
-			break;
-		case CPUFREQ_POLICY_PERFORMANCE:
-			if (freq > (clock_ratio[optimal] * busfreq))
-				optimal = i;
-			break;
-		}
-	}
-
-	powernow_k6_set_state(optimal);
+	powernow_k6_set_state(newstate);
 
 	return 0;
 }
@@ -213,6 +151,7 @@
 	struct cpuinfo_x86      *c = cpu_data;
 	struct cpufreq_driver   *driver;
 	unsigned int            result;
+	unsigned int            i;
 
 	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
 		((c->x86_model != 12) && (c->x86_model != 13)))
@@ -235,20 +174,29 @@
 	}
 	driver->policy = (struct cpufreq_policy *) (driver + 1);
 
-#ifdef CONFIG_CPU_FREQ_24_API
-	driver->cpu_cur_freq[0]  = busfreq * max_multiplier;
-#endif
+	/* table init */
+ 	for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if (clock_ratio[i].index > max_multiplier)
+			clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
+		else
+			clock_ratio[i].frequency = busfreq * clock_ratio[i].index;
+	}
 
 	driver->verify        = &powernow_k6_verify;
 	driver->setpolicy     = &powernow_k6_setpolicy;
 
+	/* cpuinfo and default policy values */
 	driver->policy[0].cpu    = 0;
-	driver->policy[0].min    = busfreq * 20;
-	driver->policy[0].max    = busfreq * max_multiplier;
-	driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
-	driver->policy[0].cpuinfo.max_freq = busfreq * max_multiplier;
-	driver->policy[0].cpuinfo.min_freq = busfreq * 20;
 	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
+#ifdef CONFIG_CPU_FREQ_24_API
+	driver->cpu_cur_freq[0]  = busfreq * max_multiplier;
+#endif
+	result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &clock_ratio[0]);
+	if (result) {
+		kfree(driver);
+		return result;
+	}
 
 	powernow_driver = driver;
 
@@ -274,7 +222,7 @@
 
 	if (powernow_driver) {
 		for (i=0;i<8;i++)
-			if (clock_ratio[i] == max_multiplier)
+			if (clock_ratio[i].index == max_multiplier)
 				powernow_k6_set_state(i);		
 		cpufreq_unregister();
 		kfree(powernow_driver);
diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c
--- a/arch/i386/kernel/cpu/cpufreq/speedstep.c	Mon Jan 13 10:18:04 2003
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c	Mon Jan 13 10:18:04 2003
@@ -58,12 +58,18 @@
  *   There are only two frequency states for each processor. Values
  * are in kHz for the time being.
  */
-static unsigned int                     speedstep_low_freq;
-static unsigned int                     speedstep_high_freq;
-
 #define SPEEDSTEP_HIGH                  0x00000000
 #define SPEEDSTEP_LOW                   0x00000001
 
+static struct cpufreq_frequency_table speedstep_freqs[] = {
+	{SPEEDSTEP_HIGH, 	0},
+	{SPEEDSTEP_LOW,		0},
+	{0,			CPUFREQ_TABLE_END},
+};
+
+#define speedstep_low_freq	speedstep_freqs[SPEEDSTEP_LOW].frequency
+#define speedstep_high_freq	speedstep_freqs[SPEEDSTEP_HIGH].frequency
+
 
 /* DEBUG
  *   Define it if you want verbose debug output, e.g. for bug reporting
@@ -447,7 +453,7 @@
 		if (c->x86_model != 2)
 			return 0;
 
-		if (c->x86_mask != 4)
+		if ((c->x86_mask != 4) && (c->x86_mask != 7))
 			return 0;
 
 		ebx = cpuid_ebx(0x00000001);
@@ -569,22 +575,13 @@
  */
 static int speedstep_setpolicy (struct cpufreq_policy *policy)
 {
-	if (!speedstep_driver || !policy)
+	unsigned int    newstate = 0;
+
+	if (cpufreq_frequency_table_setpolicy(policy, &speedstep_freqs[0], &newstate))
 		return -EINVAL;
 
-	if (policy->min > speedstep_low_freq) 
-		speedstep_set_state(SPEEDSTEP_HIGH, 1);
-	else {
-		if (policy->max < speedstep_high_freq)
-			speedstep_set_state(SPEEDSTEP_LOW, 1);
-		else {
-			/* both frequency states are allowed */
-			if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
-				speedstep_set_state(SPEEDSTEP_LOW, 1);
-			else
-				speedstep_set_state(SPEEDSTEP_HIGH, 1);
-		}
-	}
+	speedstep_set_state(newstate, 1);
+
 	return 0;
 }
 
@@ -598,19 +595,7 @@
  */
 static int speedstep_verify (struct cpufreq_policy *policy)
 {
-	if (!policy || !speedstep_driver || 
-	    !speedstep_low_freq || !speedstep_high_freq)
-		return -EINVAL;
-
-	policy->cpu = 0; /* UP only */
-
-	cpufreq_verify_within_limits(policy, speedstep_low_freq, speedstep_high_freq);
-
-	if ((policy->min > speedstep_low_freq) && 
-	    (policy->max < speedstep_high_freq))
-		policy->max = speedstep_high_freq;
-	
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
 }
 
 
@@ -692,6 +677,13 @@
 
 	driver->policy = (struct cpufreq_policy *) (driver + 1);
 
+	driver->policy[0].cpu    = 0;
+	result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &speedstep_freqs[0]);
+	if (result) {
+		kfree(driver);
+		return result;
+	}
+
 #ifdef CONFIG_CPU_FREQ_24_API
 	driver->cpu_cur_freq[0] = speed;
 #endif
@@ -699,11 +691,6 @@
 	driver->verify      = &speedstep_verify;
 	driver->setpolicy   = &speedstep_setpolicy;
 
-	driver->policy[0].cpu    = 0;
-	driver->policy[0].min    = speedstep_low_freq;
-	driver->policy[0].max    = speedstep_high_freq;
-	driver->policy[0].cpuinfo.min_freq = speedstep_low_freq;
-	driver->policy[0].cpuinfo.max_freq = speedstep_high_freq;
 	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
 	driver->policy[0].policy = (speed == speedstep_low_freq) ? 
diff -Nru a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c
--- a/arch/i386/kernel/edd.c	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/kernel/edd.c	Mon Jan 13 10:18:05 2003
@@ -61,7 +61,7 @@
 #define EDD_DEVICE_NAME_SIZE 16
 #define REPORT_URL "http://domsch.com/linux/edd30/results.html"
 
-#define left (count - (p - buf) - 1)
+#define left (PAGE_SIZE - (p - buf) - 1)
 
 struct edd_device {
 	struct edd_info *info;
@@ -70,8 +70,7 @@
 
 struct edd_attribute {
 	struct attribute attr;
-	ssize_t(*show) (struct edd_device * edev, char *buf, size_t count,
-			loff_t off);
+	ssize_t(*show) (struct edd_device * edev, char *buf);
 	int (*test) (struct edd_device * edev);
 };
 
@@ -104,15 +103,14 @@
 #define to_edd_device(obj) container_of(obj,struct edd_device,kobj)
 
 static ssize_t
-edd_attr_show(struct kobject * kobj, struct attribute *attr,
-	      char *buf, size_t count, loff_t off)
+edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
 {
 	struct edd_device *dev = to_edd_device(kobj);
 	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);
+		ret = edd_attr->show(dev, buf);
 	return ret;
 }
 
@@ -156,13 +154,13 @@
 }
 
 static ssize_t
-edd_show_host_bus(struct edd_device *edev, char *buf, size_t count, loff_t off)
+edd_show_host_bus(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
 	int i;
 
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -200,13 +198,13 @@
 }
 
 static ssize_t
-edd_show_interface(struct edd_device *edev, char *buf, size_t count, loff_t off)
+edd_show_interface(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
 	int i;
 
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -262,7 +260,7 @@
  * 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)
+edd_show_raw_data(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	int i, rc, warn_padding = 0, email = 0, nonzero_path = 0,
@@ -271,7 +269,7 @@
 	char *p = buf;
 	struct pci_dev *pci_dev=NULL;
 	struct scsi_device *sd;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -372,11 +370,11 @@
 }
 
 static ssize_t
-edd_show_version(struct edd_device *edev, char *buf, size_t count, loff_t off)
+edd_show_version(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -385,12 +383,11 @@
 }
 
 static ssize_t
-edd_show_extensions(struct edd_device *edev, char *buf, size_t count,
-		    loff_t off)
+edd_show_extensions(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -410,12 +407,11 @@
 }
 
 static ssize_t
-edd_show_info_flags(struct edd_device *edev, char *buf, size_t count,
-		    loff_t off)
+edd_show_info_flags(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -439,12 +435,11 @@
 }
 
 static ssize_t
-edd_show_default_cylinders(struct edd_device *edev, char *buf, size_t count,
-			   loff_t off)
+edd_show_default_cylinders(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -453,12 +448,11 @@
 }
 
 static ssize_t
-edd_show_default_heads(struct edd_device *edev, char *buf, size_t count,
-		       loff_t off)
+edd_show_default_heads(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -467,12 +461,11 @@
 }
 
 static ssize_t
-edd_show_default_sectors_per_track(struct edd_device *edev, char *buf,
-				   size_t count, loff_t off)
+edd_show_default_sectors_per_track(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
@@ -481,11 +474,11 @@
 }
 
 static ssize_t
-edd_show_sectors(struct edd_device *edev, char *buf, size_t count, loff_t off)
+edd_show_sectors(struct edd_device *edev, char *buf)
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 	char *p = buf;
-	if (!edev || !info || !buf || off) {
+	if (!edev || !info || !buf) {
 		return 0;
 	}
 
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	Mon Jan 13 10:18:07 2003
+++ b/arch/i386/kernel/i386_ksyms.c	Mon Jan 13 10:18:07 2003
@@ -118,10 +118,8 @@
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(clear_user);
 EXPORT_SYMBOL(__clear_user);
-EXPORT_SYMBOL(copy_from_user);
-EXPORT_SYMBOL(__copy_from_user);
-EXPORT_SYMBOL(copy_to_user);
-EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__copy_from_user_ll);
+EXPORT_SYMBOL(__copy_to_user_ll);
 EXPORT_SYMBOL(strnlen_user);
 
 EXPORT_SYMBOL(dma_alloc_coherent);
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/kernel/ptrace.c	Mon Jan 13 10:18:05 2003
@@ -21,6 +21,8 @@
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/debugreg.h>
+#include <asm/ldt.h>
+#include <asm/desc.h>
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -148,6 +150,85 @@
 	put_stack_long(child, EFL_OFFSET, tmp);
 }
 
+/*
+ * Perform get_thread_area on behalf of the traced child.
+ */
+static int
+ptrace_get_thread_area(struct task_struct *child,
+		       int idx, struct user_desc *user_desc)
+{
+	struct user_desc info;
+	struct desc_struct *desc;
+
+/*
+ * Get the current Thread-Local Storage area:
+ */
+
+#define GET_BASE(desc) ( \
+	(((desc)->a >> 16) & 0x0000ffff) | \
+	(((desc)->b << 16) & 0x00ff0000) | \
+	( (desc)->b        & 0xff000000)   )
+
+#define GET_LIMIT(desc) ( \
+	((desc)->a & 0x0ffff) | \
+	 ((desc)->b & 0xf0000) )
+
+#define GET_32BIT(desc)		(((desc)->b >> 23) & 1)
+#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
+#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
+#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
+#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
+#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+
+	info.entry_number = idx;
+	info.base_addr = GET_BASE(desc);
+	info.limit = GET_LIMIT(desc);
+	info.seg_32bit = GET_32BIT(desc);
+	info.contents = GET_CONTENTS(desc);
+	info.read_exec_only = !GET_WRITABLE(desc);
+	info.limit_in_pages = GET_LIMIT_PAGES(desc);
+	info.seg_not_present = !GET_PRESENT(desc);
+	info.useable = GET_USEABLE(desc);
+
+	if (copy_to_user(user_desc, &info, sizeof(info)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Perform set_thread_area on behalf of the traced child.
+ */
+static int
+ptrace_set_thread_area(struct task_struct *child,
+		       int idx, struct user_desc *user_desc)
+{
+	struct user_desc info;
+	struct desc_struct *desc;
+
+	if (copy_from_user(&info, user_desc, sizeof(info)))
+		return -EFAULT;
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+	if (LDT_empty(&info)) {
+		desc->a = 0;
+		desc->b = 0;
+	} else {
+		desc->a = LDT_entry_a(&info);
+		desc->b = LDT_entry_b(&info);
+	}
+
+	return 0;
+}
+
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -415,6 +496,16 @@
 		ret = set_fpxregs(child, (struct user_fxsr_struct *)data);
 		break;
 	}
+
+	case PTRACE_GET_THREAD_AREA:
+		ret = ptrace_get_thread_area(child,
+					     addr, (struct user_desc *) data);
+		break;
+
+	case PTRACE_SET_THREAD_AREA:
+		ret = ptrace_set_thread_area(child,
+					     addr, (struct user_desc *) data);
+		break;
 
 	default:
 		ret = ptrace_request(child, request, addr, data);
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	Mon Jan 13 10:18:06 2003
+++ b/arch/i386/kernel/signal.c	Mon Jan 13 10:18:06 2003
@@ -350,6 +350,7 @@
 static void setup_frame(int sig, struct k_sigaction *ka,
 			sigset_t *set, struct pt_regs * regs)
 {
+	void *restorer;
 	struct sigframe *frame;
 	int err = 0;
 
@@ -378,8 +379,12 @@
 	if (err)
 		goto give_sigsegv;
 
+	restorer = (void *) (fix_to_virt(FIX_VSYSCALL) + 32);
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+
 	/* Set up to return from userspace.  */
-	err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 32, &frame->pretcode);
+	err |= __put_user(restorer, &frame->pretcode);
 	 
 	/*
 	 * This is popl %eax ; movl $,%eax ; int $0x80
@@ -422,6 +427,7 @@
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			   sigset_t *set, struct pt_regs * regs)
 {
+	void *restorer;
 	struct rt_sigframe *frame;
 	int err = 0;
 
@@ -456,7 +462,10 @@
 		goto give_sigsegv;
 
 	/* Set up to return from userspace.  */
-	err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 64, &frame->pretcode);
+	restorer = (void *) (fix_to_virt(FIX_VSYSCALL) + 64);
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+	err |= __put_user(restorer, &frame->pretcode);
 	 
 	/*
 	 * This is movl $,%eax ; int $0x80
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/kernel/traps.c	Mon Jan 13 10:18:05 2003
@@ -297,26 +297,7 @@
 	}
 
 	kernel_trap: {
-		const struct exception_table_entry *fixup;
-#ifdef CONFIG_PNPBIOS
-		if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */
-		{
-			extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
-			extern u32 pnp_bios_is_utter_crap;
-			pnp_bios_is_utter_crap = 1;
-			printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");
-			__asm__ volatile(
-				"movl %0, %%esp\n\t"
-				"jmp *%1\n\t"
-				: "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip));
-			panic("do_trap: can't hit this");
-		}
-#endif	
-		
-		fixup = search_exception_tables(regs->eip);
-		if (fixup)
-			regs->eip = fixup->fixup;
-		else	
+		if (!fixup_exception(regs))
 			die(str, regs, error_code);
 		return;
 	}
@@ -393,15 +374,8 @@
 	return;
 
 gp_in_kernel:
-	{
-		const struct exception_table_entry *fixup;
-		fixup = search_exception_tables(regs->eip);
-		if (fixup) {
-			regs->eip = fixup->fixup;
-			return;
-		}
+	if (!fixup_exception(regs))
 		die("general protection fault", regs, error_code);
-	}
 }
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
diff -Nru a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
--- a/arch/i386/lib/usercopy.c	Mon Jan 13 10:18:04 2003
+++ b/arch/i386/lib/usercopy.c	Mon Jan 13 10:18:04 2003
@@ -417,7 +417,7 @@
 } while (0)
 
 
-unsigned long __copy_to_user(void *to, const void *from, unsigned long n)
+unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n)
 {
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
@@ -426,27 +426,11 @@
 	return n;
 }
 
-unsigned long __copy_from_user(void *to, const void *from, unsigned long n)
+unsigned long __copy_from_user_ll(void *to, const void *from, unsigned long n)
 {
 	if (movsl_is_ok(to, from, n))
 		__copy_user_zeroing(to, from, n);
 	else
 		n = __copy_user_zeroing_intel(to, from, n);
-	return n;
-}
-
-unsigned long copy_to_user(void *to, const void *from, unsigned long n)
-{
-	prefetch(from);
-	if (access_ok(VERIFY_WRITE, to, n))
-		n = __copy_to_user(to, from, n);
-	return n;
-}
-
-unsigned long copy_from_user(void *to, const void *from, unsigned long n)
-{
-	prefetchw(to);
-	if (access_ok(VERIFY_READ, from, n))
-		n = __copy_from_user(to, from, n);
 	return n;
 }
diff -Nru a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c
--- a/arch/i386/mm/extable.c	Mon Jan 13 10:18:07 2003
+++ b/arch/i386/mm/extable.c	Mon Jan 13 10:18:07 2003
@@ -28,3 +28,31 @@
         }
         return NULL;
 }
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+#ifdef CONFIG_PNPBIOS
+	if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */
+	{
+		extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
+		extern u32 pnp_bios_is_utter_crap;
+		pnp_bios_is_utter_crap = 1;
+		printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");
+		__asm__ volatile(
+			"movl %0, %%esp\n\t"
+			"jmp *%1\n\t"
+			: "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip));
+		panic("do_trap: can't hit this");
+	}
+#endif
+
+	fixup = search_exception_tables(regs->eip);
+	if (fixup) {
+		regs->eip = fixup->fixup;
+		return 1;
+	}
+
+	return 0;
+}
diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
--- a/arch/i386/mm/fault.c	Mon Jan 13 10:18:04 2003
+++ b/arch/i386/mm/fault.c	Mon Jan 13 10:18:04 2003
@@ -155,7 +155,6 @@
 	struct vm_area_struct * vma;
 	unsigned long address;
 	unsigned long page;
-	const struct exception_table_entry *fixup;
 	int write;
 	siginfo_t info;
 
@@ -311,10 +310,8 @@
 
 no_context:
 	/* Are we prepared to handle this kernel fault?  */
-	if ((fixup = search_exception_tables(regs->eip)) != NULL) {
-		regs->eip = fixup->fixup;
+	if (fixup_exception(regs))
 		return;
-	}
 
 /*
  * Oops. The kernel tried to access some bad page. We'll have to
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Mon Jan 13 10:18:07 2003
+++ b/arch/i386/mm/init.c	Mon Jan 13 10:18:07 2003
@@ -41,7 +41,7 @@
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 unsigned long highstart_pfn, highend_pfn;
 
 /*
@@ -71,12 +71,16 @@
  */
 static pte_t * __init one_page_table_init(pmd_t *pmd)
 {
-	pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-	set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
-	if (page_table != pte_offset_kernel(pmd, 0))
-		BUG();	
+	if (pmd_none(*pmd)) {
+		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+		if (page_table != pte_offset_kernel(pmd, 0))
+			BUG();	
 
-	return page_table;
+		return page_table;
+	}
+	
+	return pte_offset_kernel(pmd, 0);
 }
 
 /*
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
--- a/arch/i386/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/i386/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -31,6 +31,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   __start___kallsyms = .;       /* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
   __stop___kallsyms = .;
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	Mon Jan 13 10:18:06 2003
+++ b/arch/ia64/mm/init.c	Mon Jan 13 10:18:06 2003
@@ -29,7 +29,7 @@
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 /* References to section boundaries: */
 extern char _stext, _etext, _edata, __init_begin, __init_end;
diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S
--- a/arch/ia64/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
+++ b/arch/ia64/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
@@ -65,6 +65,11 @@
 	{ *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL only */
+  __gpl_ksymtab : AT(ADDR(__gpl_ksymtab) - PAGE_OFFSET)
+	{ *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   __kallsyms : AT(ADDR(__kallsyms) - PAGE_OFFSET)
 	{
 	  __start___kallsyms = .;	/* All kernel symbols */
diff -Nru a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
--- a/arch/m68k/mac/iop.c	Mon Jan 13 10:18:07 2003
+++ b/arch/m68k/mac/iop.c	Mon Jan 13 10:18:07 2003
@@ -28,7 +28,7 @@
  *		  globally-visible functions take an IOP number instead of an
  *		  an actual base address.
  * 990610 (jmt) - Finished the message passing framework and it seems to work.
- *		  Sending _definately_ works; my adb-bus.c mods can send
+ *		  Sending _definitely_ works; my adb-bus.c mods can send
  *		  messages and receive the MSG_COMPLETED status back from the
  *		  IOP. The trick now is figuring out the message formats.
  * 990611 (jmt) - More cleanups. Fixed problem where unclaimed messages on a
diff -Nru a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
--- a/arch/m68k/mm/init.c	Mon Jan 13 10:18:07 2003
+++ b/arch/m68k/mm/init.c	Mon Jan 13 10:18:07 2003
@@ -33,7 +33,7 @@
 #endif
 #include <asm/tlb.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 /*
  * ZERO_PAGE is a special page that is used for zero-initialized
diff -Nru a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds
--- a/arch/m68k/vmlinux-std.lds	Mon Jan 13 10:18:07 2003
+++ b/arch/m68k/vmlinux-std.lds	Mon Jan 13 10:18:07 2003
@@ -24,6 +24,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table: GPL only */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   _etext = .;			/* End of text section */
 
   .data : {			/* Data */
diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
--- a/arch/m68k/vmlinux-sun3.lds	Mon Jan 13 10:18:04 2003
+++ b/arch/m68k/vmlinux-sun3.lds	Mon Jan 13 10:18:04 2003
@@ -30,6 +30,9 @@
   	__start___ksymtab = .;	/* Kernel symbol table */
   	*(__ksymtab) 
   	__stop___ksymtab = .;
+	__start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+	__gpl_ksymtab : { *(__gpl_ksymtab) }
+	__stop___gpl_ksymtab = .;
 	}
   /* End of data goes *here* so that freeing init code works properly. */
   _edata = .;
diff -Nru a/arch/m68knommu/platform/5206/ARNEWSH/ram.ld b/arch/m68knommu/platform/5206/ARNEWSH/ram.ld
--- a/arch/m68knommu/platform/5206/ARNEWSH/ram.ld	Mon Jan 13 10:18:05 2003
+++ b/arch/m68knommu/platform/5206/ARNEWSH/ram.ld	Mon Jan 13 10:18:05 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld b/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld
--- a/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld	Mon Jan 13 10:18:06 2003
+++ b/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld	Mon Jan 13 10:18:06 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5206e/eLITE/ram.ld b/arch/m68knommu/platform/5206e/eLITE/ram.ld
--- a/arch/m68knommu/platform/5206e/eLITE/ram.ld	Mon Jan 13 10:18:06 2003
+++ b/arch/m68knommu/platform/5206e/eLITE/ram.ld	Mon Jan 13 10:18:06 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5249/MOTOROLA/ram.ld b/arch/m68knommu/platform/5249/MOTOROLA/ram.ld
--- a/arch/m68knommu/platform/5249/MOTOROLA/ram.ld	Mon Jan 13 10:18:05 2003
+++ b/arch/m68knommu/platform/5249/MOTOROLA/ram.ld	Mon Jan 13 10:18:05 2003
@@ -25,6 +25,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5272/MOTOROLA/ram.ld b/arch/m68knommu/platform/5272/MOTOROLA/ram.ld
--- a/arch/m68knommu/platform/5272/MOTOROLA/ram.ld	Mon Jan 13 10:18:07 2003
+++ b/arch/m68knommu/platform/5272/MOTOROLA/ram.ld	Mon Jan 13 10:18:07 2003
@@ -25,6 +25,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5272/NETtel/ram.ld b/arch/m68knommu/platform/5272/NETtel/ram.ld
--- a/arch/m68knommu/platform/5272/NETtel/ram.ld	Mon Jan 13 10:18:04 2003
+++ b/arch/m68knommu/platform/5272/NETtel/ram.ld	Mon Jan 13 10:18:04 2003
@@ -25,6 +25,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5307/ARNEWSH/ram.ld b/arch/m68knommu/platform/5307/ARNEWSH/ram.ld
--- a/arch/m68knommu/platform/5307/ARNEWSH/ram.ld	Mon Jan 13 10:18:05 2003
+++ b/arch/m68knommu/platform/5307/ARNEWSH/ram.ld	Mon Jan 13 10:18:05 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld b/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld
--- a/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld	Mon Jan 13 10:18:05 2003
+++ b/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld	Mon Jan 13 10:18:05 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5307/MOTOROLA/ram.ld b/arch/m68knommu/platform/5307/MOTOROLA/ram.ld
--- a/arch/m68knommu/platform/5307/MOTOROLA/ram.ld	Mon Jan 13 10:18:07 2003
+++ b/arch/m68knommu/platform/5307/MOTOROLA/ram.ld	Mon Jan 13 10:18:07 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5307/MP3/ram.ld b/arch/m68knommu/platform/5307/MP3/ram.ld
--- a/arch/m68knommu/platform/5307/MP3/ram.ld	Mon Jan 13 10:18:07 2003
+++ b/arch/m68knommu/platform/5307/MP3/ram.ld	Mon Jan 13 10:18:07 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5307/NETtel/ram.ld b/arch/m68knommu/platform/5307/NETtel/ram.ld
--- a/arch/m68knommu/platform/5307/NETtel/ram.ld	Mon Jan 13 10:18:06 2003
+++ b/arch/m68knommu/platform/5307/NETtel/ram.ld	Mon Jan 13 10:18:06 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld b/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld
--- a/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld	Mon Jan 13 10:18:07 2003
+++ b/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld	Mon Jan 13 10:18:07 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/5407/MOTOROLA/ram.ld b/arch/m68knommu/platform/5407/MOTOROLA/ram.ld
--- a/arch/m68knommu/platform/5407/MOTOROLA/ram.ld	Mon Jan 13 10:18:05 2003
+++ b/arch/m68knommu/platform/5407/MOTOROLA/ram.ld	Mon Jan 13 10:18:05 2003
@@ -24,6 +24,11 @@
 		__start___ksymtab = .;  /* Kernel symbol table          */
 		*(__ksymtab)
 		__stop___ksymtab = .;
+
+	        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only */
+		*(__gpl_ksymtab)
+		__stop___gpl_ksymtab = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > ram
diff -Nru a/arch/m68knommu/platform/68360/uCquicc/ram.ld b/arch/m68knommu/platform/68360/uCquicc/ram.ld
--- a/arch/m68knommu/platform/68360/uCquicc/ram.ld	Mon Jan 13 10:18:06 2003
+++ b/arch/m68knommu/platform/68360/uCquicc/ram.ld	Mon Jan 13 10:18:06 2003
@@ -38,6 +38,9 @@
 	__start___ksymtab = . ;
 	*(__ksymtab)
         __stop___ksymtab = . ;
+	__start___gpl_ksymtab = . ;
+	*(__gpl_ksymtab)
+        __stop___gpl_ksymtab = . ;
 	__start___ex_table = . ;
 	*(___ex_table)
 	__stop___ex_table = . ;
diff -Nru a/arch/m68knommu/platform/68360/uCquicc/rom.ld b/arch/m68knommu/platform/68360/uCquicc/rom.ld
--- a/arch/m68knommu/platform/68360/uCquicc/rom.ld	Mon Jan 13 10:18:07 2003
+++ b/arch/m68knommu/platform/68360/uCquicc/rom.ld	Mon Jan 13 10:18:07 2003
@@ -38,6 +38,9 @@
         __start___ksymtab = . ;
         *(__ksymtab)
         __stop___ksymtab = . ;
+        __start___gpl_ksymtab = . ;
+        *(__gpl_ksymtab)
+        __stop___gpl_ksymtab = . ;
         __start___ex_table = . ;
         *(___ex_table)
         __stop___ex_table = . ;
diff -Nru a/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld b/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld
--- a/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld	Mon Jan 13 10:18:06 2003
+++ b/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld	Mon Jan 13 10:18:06 2003
@@ -30,6 +30,10 @@
 		 *(__ksymtab)
 	__stop___ksymtab = .;
 
+        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only  */
+		 *(__gpl_ksymtab)
+	__stop___gpl_ksymtab = .;
+
 	. = ALIGN(0x4) ;
 	_etext = . ;
 	__data_rom_start = . ;
diff -Nru a/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld b/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld
--- a/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld	Mon Jan 13 10:18:07 2003
+++ b/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld	Mon Jan 13 10:18:07 2003
@@ -51,6 +51,10 @@
 		 *(__ksymtab)
 	__stop___ksymtab = .;
 
+        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only  */
+		 *(__gpl_ksymtab)
+	__stop___gpl_ksymtab = .;
+
 	_etext = . ;
 	__data_rom_start = ALIGN ( 4 ) ;
         } > ram
diff -Nru a/arch/m68knommu/platform/68VZ328/de2/fixed.ld b/arch/m68knommu/platform/68VZ328/de2/fixed.ld
--- a/arch/m68knommu/platform/68VZ328/de2/fixed.ld	Mon Jan 13 10:18:06 2003
+++ b/arch/m68knommu/platform/68VZ328/de2/fixed.ld	Mon Jan 13 10:18:06 2003
@@ -29,6 +29,10 @@
 		 *(__ksymtab)
 	__stop___ksymtab = .;
 
+        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only  */
+		 *(__gpl_ksymtab)
+	__stop___gpl_ksymtab = .;
+
 	. = ALIGN(0x4) ;
 	_etext = . ;
 	__data_rom_start = . ;
diff -Nru a/arch/m68knommu/platform/68VZ328/de2/ram.ld b/arch/m68knommu/platform/68VZ328/de2/ram.ld
--- a/arch/m68knommu/platform/68VZ328/de2/ram.ld	Mon Jan 13 10:18:06 2003
+++ b/arch/m68knommu/platform/68VZ328/de2/ram.ld	Mon Jan 13 10:18:06 2003
@@ -50,6 +50,10 @@
 		 *(__ksymtab)
 	__stop___ksymtab = .;
 
+        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only  */
+		 *(__gpl_ksymtab)
+	__stop___gpl_ksymtab = .;
+
 	_etext = . ;
 	__data_rom_start = ALIGN ( 4 ) ;
         } > ram
diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld b/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld
--- a/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld	Mon Jan 13 10:18:05 2003
+++ b/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld	Mon Jan 13 10:18:05 2003
@@ -29,6 +29,10 @@
 		 *(__ksymtab)
 	__stop___ksymtab = .;
 
+        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only  */
+		 *(__gpl_ksymtab)
+	__stop___gpl_ksymtab = .;
+
 	. = ALIGN(0x4) ;
 	_etext = . ;
 	__data_rom_start = . ;
diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld b/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld
--- a/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld	Mon Jan 13 10:18:07 2003
+++ b/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld	Mon Jan 13 10:18:07 2003
@@ -50,6 +50,10 @@
 		 *(__ksymtab)
 	__stop___ksymtab = .;
 
+        __start___gpl_ksymtab = .;  /* Kernel symbol table: GPL-only  */
+		 *(__gpl_ksymtab)
+	__stop___gpl_ksymtab = .;
+
 	_etext = . ;
 	__data_rom_start = ALIGN ( 4 ) ;
         } > ram
diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c
--- a/arch/mips/mm/init.c	Mon Jan 13 10:18:07 2003
+++ b/arch/mips/mm/init.c	Mon Jan 13 10:18:07 2003
@@ -42,7 +42,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 extern void prom_free_prom_memory(void);
 
diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S
--- a/arch/mips/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/mips/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -29,6 +29,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   _etext = .;
 
   . = ALIGN(8192);
diff -Nru a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c
--- a/arch/mips64/mm/init.c	Mon Jan 13 10:18:06 2003
+++ b/arch/mips64/mm/init.c	Mon Jan 13 10:18:06 2003
@@ -37,7 +37,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 void pgd_init(unsigned long page)
 {
diff -Nru a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
--- a/arch/parisc/mm/init.c	Mon Jan 13 10:18:06 2003
+++ b/arch/parisc/mm/init.c	Mon Jan 13 10:18:06 2003
@@ -23,7 +23,7 @@
 #include <asm/tlb.h>
 #include <asm/pdc_chassis.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 extern char _text;	/* start of kernel code, defined by linker */
 extern int  data_start;
diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S
--- a/arch/parisc/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/parisc/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -49,6 +49,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   __start___kallsyms = .;       /* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
   __stop___kallsyms = .;
diff -Nru a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
--- a/arch/ppc/lib/string.S	Mon Jan 13 10:18:06 2003
+++ b/arch/ppc/lib/string.S	Mon Jan 13 10:18:06 2003
@@ -507,18 +507,18 @@
 	blr
 
 /* read fault, initial single-byte copy */
-100:	li	r4,0
+100:	li	r9,0
 	b	90f
 /* write fault, initial single-byte copy */
-101:	li	r4,1
+101:	li	r9,1
 90:	subf	r5,r8,r5
 	li	r3,0
 	b	99f
 /* read fault, initial word copy */
-102:	li	r4,0
+102:	li	r9,0
 	b	91f
 /* write fault, initial word copy */
-103:	li	r4,1
+103:	li	r9,1
 91:	li	r3,2
 	b	99f
 
@@ -542,38 +542,47 @@
 #endif
 
 /* read fault in cacheline loop */
-104:	li	r4,0
+104:	li	r9,0
 	b	92f
 /* fault on dcbz (effectively a write fault) */
 /* or write fault in cacheline loop */
-105:	li	r4,1
+105:	li	r9,1
 92:	li	r3,LG_CACHELINE_BYTES
 	b	99f
 /* read fault in final word loop */
-108:	li	r4,0
+108:	li	r9,0
 	b	93f
 /* write fault in final word loop */
-109:	li	r4,1
+109:	li	r9,1
 93:	andi.	r5,r5,3
 	li	r3,2
 	b	99f
 /* read fault in final byte loop */
-110:	li	r4,0
+110:	li	r9,0
 	b	94f
 /* write fault in final byte loop */
-111:	li	r4,1
+111:	li	r9,1
 94:	li	r5,0
 	li	r3,0
 /*
  * At this stage the number of bytes not copied is
- * r5 + (ctr << r3), and r4 is 0 for read or 1 for write.
+ * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
  */
 99:	mfctr	r0
 	slw	r3,r0,r3
-	add	r3,r3,r5
-	cmpwi	0,r4,0
+	add.	r3,r3,r5
+	beq	120f			/* shouldn't happen */
+	cmpwi	0,r9,0
 	bne	120f
-/* for read fault, clear out the destination: r3 bytes starting at 4(r6) */
+/* for a read fault, first try to continue the copy one byte at a time */
+	mtctr	r3
+130:	lbz	r0,4(r4)
+131:	stb	r0,4(r6)
+	addi	r4,r4,1
+	addi	r6,r6,1
+	bdnz	130b
+/* then clear out the destination: r3 bytes starting at 4(r6) */
+132:	mfctr	r3
 	srwi.	r0,r3,2
 	li	r9,0
 	mtctr	r0
@@ -594,6 +603,8 @@
 	.long	31b,109b
 	.long	40b,110b
 	.long	41b,111b
+	.long	130b,132b
+	.long	131b,120b
 	.long	112b,120b
 	.long	114b,120b
 	.text
diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
--- a/arch/ppc/mm/init.c	Mon Jan 13 10:18:05 2003
+++ b/arch/ppc/mm/init.c	Mon Jan 13 10:18:05 2003
@@ -55,7 +55,7 @@
 #endif
 #define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 unsigned long total_memory;
 unsigned long total_lowmem;
diff -Nru a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
--- a/arch/ppc/mm/tlb.c	Mon Jan 13 10:18:06 2003
+++ b/arch/ppc/mm/tlb.c	Mon Jan 13 10:18:06 2003
@@ -50,7 +50,7 @@
  * Called at the end of a mmu_gather operation to make sure the
  * TLB flush is completely done.
  */
-void tlb_flush(mmu_gather_t *tlb)
+void tlb_flush(struct mmu_gather *tlb)
 {
 	if (Hash == 0) {
 		/*
diff -Nru a/arch/ppc/platforms/k2_pci.c b/arch/ppc/platforms/k2_pci.c
--- a/arch/ppc/platforms/k2_pci.c	Mon Jan 13 10:18:07 2003
+++ b/arch/ppc/platforms/k2_pci.c	Mon Jan 13 10:18:07 2003
@@ -156,6 +156,13 @@
 	__raw_writel(0x00000080, K2_PCI32_BAR+PSBAR);	/* Base@0x80 */
 	__raw_writel(0x00000000, K2_PCI32_BAR+PPBAR);
 
+	__raw_writel(0xc0000000, K2_PCI32_BAR+BPMDLK);
+	__raw_writel(0xd0000000, K2_PCI32_BAR+TPMDLK);
+	__raw_writel(0x80000000, K2_PCI32_BAR+BIODLK);
+	__raw_writel(0x80100000, K2_PCI32_BAR+TIODLK);
+	__raw_writel(0xe0008000, K2_PCI32_BAR+DLKCTRL);
+	__raw_writel(0xffffffff, K2_PCI32_BAR+DLKDEV);
+	
 	/* PCI64 mappings */
 	__raw_writel(0x00100000, K2_PCI64_BAR+PIBAR);	/* PCI I/O base */
 	__raw_writel(0x10000000, K2_PCI64_BAR+PMBAR);	/* PCI Mem base */
diff -Nru a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h
--- a/arch/ppc/syslib/cpc710.h	Mon Jan 13 10:18:05 2003
+++ b/arch/ppc/syslib/cpc710.h	Mon Jan 13 10:18:05 2003
@@ -61,6 +61,12 @@
 #define BARPP	0x000f8130
 #define PSBAR	0x000f8140
 #define PPBAR	0x000f8150
+#define BPMDLK	0x000f8200      /* Bottom of Peripheral Memory Space */
+#define TPMDLK	0x000f8210      /* Top of Peripheral Memory Space */
+#define BIODLK	0x000f8220      /* Bottom of Peripheral I/O Space */
+#define TIODLK	0x000f8230      /* Top of Perioheral I/O Space */
+#define DLKCTRL	0x000f8240      /* Deadlock control */
+#define DLKDEV	0x000f8250      /* Deadlock device */
 
 /* System standard configuration registers space */
 #define	DCR	0xff200000
diff -Nru a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c
--- a/arch/ppc/syslib/mpc10x_common.c	Mon Jan 13 10:18:05 2003
+++ b/arch/ppc/syslib/mpc10x_common.c	Mon Jan 13 10:18:05 2003
@@ -243,6 +243,8 @@
 
 #ifdef CONFIG_MPC10X_STORE_GATHERING
 	mpc10x_enable_store_gathering(hose);
+#else
+	mpc10x_disable_store_gathering(hose);
 #endif
 
 	if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100);
@@ -367,6 +369,28 @@
 			        &picr1);
 
 	picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN;
+
+	early_write_config_dword(hose,
+				0,
+				PCI_DEVFN(0,0),
+				MPC10X_CFG_PICR1_REG,
+				picr1);
+
+	return 0;
+}
+
+int __init
+mpc10x_disable_store_gathering(struct pci_controller *hose)
+{
+	uint picr1;
+
+	early_read_config_dword(hose,
+				0,
+				PCI_DEVFN(0,0),
+			        MPC10X_CFG_PICR1_REG,
+			        &picr1);
+
+	picr1 &= ~MPC10X_CFG_PICR1_ST_GATH_EN;
 
 	early_write_config_dword(hose,
 				0,
diff -Nru a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
--- a/arch/ppc/syslib/todc_time.c	Mon Jan 13 10:18:07 2003
+++ b/arch/ppc/syslib/todc_time.c	Mon Jan 13 10:18:07 2003
@@ -240,6 +240,7 @@
 
 		switch (todc_info->rtc_type) {
 			case TODC_TYPE_DS1557:
+			case TODC_TYPE_DS1743:
 			case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
 			case TODC_TYPE_DS1747:
 				break;
@@ -274,6 +275,7 @@
 	if (todc_info->rtc_type != TODC_TYPE_MC146818) {
 		switch (todc_info->rtc_type) {
 			case TODC_TYPE_DS1557:
+			case TODC_TYPE_DS1743:	
 			case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
 			case TODC_TYPE_DS1747:
 				break;
@@ -367,6 +369,7 @@
 
 	switch (todc_info->rtc_type) {
 		case TODC_TYPE_DS1557:
+		case TODC_TYPE_DS1743:
 		case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
 		case TODC_TYPE_DS1747:
 		case TODC_TYPE_MC146818:
@@ -381,6 +384,7 @@
 
 	switch (todc_info->rtc_type) {
 		case TODC_TYPE_DS1557:
+		case TODC_TYPE_DS1743:
 		case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
 		case TODC_TYPE_DS1747:
 		case TODC_TYPE_MC146818:
diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S
--- a/arch/ppc/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
+++ b/arch/ppc/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
@@ -61,6 +61,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   __start___kallsyms = .;     /* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
   __stop___kallsyms = .;
diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
--- a/arch/ppc64/kernel/entry.S	Mon Jan 13 10:18:05 2003
+++ b/arch/ppc64/kernel/entry.S	Mon Jan 13 10:18:05 2003
@@ -114,6 +114,8 @@
 	clrldi	r4,r4,32
 	clrldi	r5,r5,32
 	clrldi	r6,r6,32
+	clrldi	r7,r7,32
+	clrldi	r8,r8,32
 	b	17f
 15:
 #endif
@@ -184,6 +186,8 @@
 	clrldi	r4,r4,32
 	clrldi	r5,r5,32
 	clrldi	r6,r6,32
+	clrldi	r7,r7,32
+	clrldi	r8,r8,32
 	b	57f
 55:
 #endif
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Mon Jan 13 10:18:07 2003
+++ b/arch/ppc64/kernel/misc.S	Mon Jan 13 10:18:07 2003
@@ -567,8 +567,8 @@
 	.llong .sys32_getpriority
 	.llong .sys32_setpriority
 	.llong .sys_ni_syscall		/* old profil syscall */
-	.llong .sys32_statfs
-	.llong .sys32_fstatfs		/* 100 */
+	.llong .compat_sys_statfs
+	.llong .compat_sys_fstatfs		/* 100 */
 	.llong .sys_ioperm
 	.llong .sys32_socketcall
 	.llong .sys32_syslog
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	Mon Jan 13 10:18:07 2003
+++ b/arch/ppc64/kernel/signal32.c	Mon Jan 13 10:18:07 2003
@@ -720,18 +720,11 @@
 	case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
 	case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
 	}
-	if (uts) {
-		ret = get_user(t.tv_sec, &uts->tv_sec);
-		ret |= __get_user(t.tv_nsec, &uts->tv_nsec);
-		if (ret)
-			return -EFAULT;
-	}
+	if (uts && get_compat_timespec(&t, uts))
+		return -EFAULT;
 	set_fs(KERNEL_DS);
-	if (uts) 
-		ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
-	else
-		ret = sys_rt_sigtimedwait(&s, &info, (struct timespec *)uts,
-				sigsetsize);
+	ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL,
+			sigsetsize);
 	set_fs(old_fs);
 	if (ret >= 0 && uinfo) {
 		if (copy_siginfo_to_user32(uinfo, &info))
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Mon Jan 13 10:18:06 2003
+++ b/arch/ppc64/kernel/sys_ppc32.c	Mon Jan 13 10:18:06 2003
@@ -807,65 +807,6 @@
 	return err;
 }
 
-static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
-{
-	int err;
-	
-	err = put_user (kbuf->f_type, &ubuf->f_type);
-	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
-	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
-	err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
-	err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
-	err |= __put_user (kbuf->f_files, &ubuf->f_files);
-	err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
-	err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
-	err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
-	err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
-	return err;
-}
-
-extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
-
-asmlinkage long sys32_statfs(const char * path, struct statfs32 *buf)
-{
-	int ret;
-	struct statfs s;
-	mm_segment_t old_fs = get_fs();
-	char *pth;
-	
-	pth = getname (path);
-	ret = PTR_ERR(pth);
-	if (!IS_ERR(pth)) {
-		set_fs (KERNEL_DS);
-		ret = sys_statfs((const char *)pth, &s);
-		set_fs (old_fs);
-		putname (pth);
-		if (put_statfs(buf, &s))
-			return -EFAULT;
-	}
-	
-	return ret;
-}
-
-extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);
-
-asmlinkage long sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
-{
-	int ret;
-	struct statfs s;
-	mm_segment_t old_fs = get_fs();
-	
-	set_fs (KERNEL_DS);
-	ret = sys_fstatfs(fd, &s);
-	set_fs (old_fs);
-	if (put_statfs(buf, &s))
-		return -EFAULT;
-	
-	return ret;
-}
-
-
-
 extern asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
 
 /* Note: it is necessary to treat option as an unsigned int,
@@ -3603,10 +3544,8 @@
 	set_fs (KERNEL_DS);
 	ret = sys_sched_rr_get_interval((int)pid, &t);
 	set_fs (old_fs);
-	if (put_user (t.tv_sec, &interval->tv_sec) ||
-	    __put_user (t.tv_nsec, &interval->tv_nsec))
+	if (put_compat_timespec(&t, interval))
 		return -EFAULT;
-	
 	return ret;
 }
 
diff -Nru a/arch/ppc64/mm/extable.c b/arch/ppc64/mm/extable.c
--- a/arch/ppc64/mm/extable.c	Mon Jan 13 10:18:05 2003
+++ b/arch/ppc64/mm/extable.c	Mon Jan 13 10:18:05 2003
@@ -1,7 +1,7 @@
 /*
- * linux/arch/ppc64/mm/extable.c
+ * arch/ppc64/mm/extable.c
  *
- * from linux/arch/i386/mm/extable.c
+ * from arch/i386/mm/extable.c
  *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -11,7 +11,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
+#include <linux/init.h>
 #include <asm/uaccess.h>
 
 extern struct exception_table_entry __start___ex_table[];
@@ -45,16 +45,17 @@
 	}
 }
 
-void
+void __init
 sort_exception_table(void)
 {
 	sort_ex_table(__start___ex_table, __stop___ex_table);
 }
 
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
-		 const struct exception_table_entry *last,
-		 unsigned long value)
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+	       const struct exception_table_entry *last,
+	       unsigned long value)
 {
 	while (first <= last) {
 		const struct exception_table_entry *mid;
@@ -63,41 +64,11 @@
 		mid = (last - first) / 2 + first;
 		diff = mid->insn - value;
 		if (diff == 0)
-			return mid->fixup;
+			return mid;
 		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 = 0;
-
-#ifndef CONFIG_MODULES
-	/* There is only the kernel to search.  */
-	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-	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 || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
-			continue;
-		ret = search_one_table(mp->ex_table_start,
-				       mp->ex_table_end - 1, addr);
-		if (ret)
-			break;
-	}
-	spin_unlock_irqrestore(&modlist_lock, flags);
-	return ret;
-#endif
+	return NULL;
 }
diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
--- a/arch/ppc64/mm/fault.c	Mon Jan 13 10:18:07 2003
+++ b/arch/ppc64/mm/fault.c	Mon Jan 13 10:18:07 2003
@@ -28,6 +28,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <linux/module.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -204,12 +205,11 @@
 bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 {
 	extern void die(const char *, struct pt_regs *, long);
-
-	unsigned long fixup;
+	const struct exception_table_entry *entry;
 
 	/* Are we prepared to handle this fault?  */
-	if ((fixup = search_exception_table(regs->nip)) != 0) {
-		regs->nip = fixup;
+	if ((entry = search_exception_tables(regs->nip)) != NULL) {
+		regs->nip = entry->fixup;
 		return;
 	}
 
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	Mon Jan 13 10:18:06 2003
+++ b/arch/ppc64/mm/init.c	Mon Jan 13 10:18:06 2003
@@ -95,7 +95,7 @@
 /* This is declared as we are using the more or less generic 
  * include/asm-ppc64/tlb.h file -- tgall
  */
-mmu_gather_t     mmu_gathers[NR_CPUS];
+struct mmu_gather     mmu_gathers[NR_CPUS];
 
 void show_mem(void)
 {
@@ -592,36 +592,24 @@
  */
 void flush_dcache_page(struct page *page)
 {
+	/* avoid an atomic op if possible */
 	if (test_bit(PG_arch_1, &page->flags))
 		clear_bit(PG_arch_1, &page->flags);
 }
 
-void flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
-	if (cpu_has_noexecute())
-		return;
-
-	if ((vma->vm_flags & VM_EXEC) == 0)
-		return;
-
-	if (page->mapping && !PageReserved(page)
-	    && !test_bit(PG_arch_1, &page->flags)) {
-		__flush_dcache_icache(page_address(page));
-		set_bit(PG_arch_1, &page->flags);
-	}
-}
-
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
 	clear_page(page);
 
-	/* XXX we shouldnt have to do this, but glibc requires it */
-	if (cpu_has_noexecute()) {
-		if (test_bit(PG_arch_1, &pg->flags))
-			clear_bit(PG_arch_1, &pg->flags);
-	} else {
-		__flush_dcache_icache(page);
-	}
+	/*
+	 * We shouldnt have to do this, but some versions of glibc
+	 * require it (ld.so assumes zero filled pages are icache clean)
+	 * - Anton
+	 */
+
+	/* avoid an atomic op if possible */
+	if (test_bit(PG_arch_1, &pg->flags))
+		clear_bit(PG_arch_1, &pg->flags);
 }
 
 void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
@@ -630,20 +618,23 @@
 	copy_page(vto, vfrom);
 
 	/*
-	 * Unfortunately we havent always marked our GOT and PLT sections
-	 * as executable, so we need to flush all file regions - Anton
+	 * We should be able to use the following optimisation, however
+	 * there are two problems.
+	 * Firstly a bug in some versions of binutils meant PLT sections
+	 * were not marked executable.
+	 * Secondly the first word in the GOT section is blrl, used
+	 * to establish the GOT address. Until recently the GOT was
+	 * not marked executable.
+	 * - Anton
 	 */
 #if 0
 	if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0))
 		return;
 #endif
 
-	if (cpu_has_noexecute()) {
-		if (test_bit(PG_arch_1, &pg->flags))
-			clear_bit(PG_arch_1, &pg->flags);
-	} else {
-		__flush_dcache_icache(vto);
-	}
+	/* avoid an atomic op if possible */
+	if (test_bit(PG_arch_1, &pg->flags))
+		clear_bit(PG_arch_1, &pg->flags);
 }
 
 void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
@@ -674,6 +665,19 @@
 	void *pgdir;
 	pte_t *ptep;
 	int local = 0;
+
+	/* handle i-cache coherency */
+	if (!cpu_has_noexecute()) {
+		unsigned long pfn = pte_pfn(pte);
+		if (pfn_valid(pfn)) {
+			struct page *page = pfn_to_page(pfn);
+			if (!PageReserved(page)
+			    && !test_bit(PG_arch_1, &page->flags)) {
+				__flush_dcache_icache(page_address(page));
+				set_bit(PG_arch_1, &page->flags);
+			}
+		}
+	}
 
 	/* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
 	if (!pte_young(pte))
diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S
--- a/arch/ppc64/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
+++ b/arch/ppc64/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
@@ -69,6 +69,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   __start___kallsyms = .;	/* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
   __stop___kallsyms = .;
diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c
--- a/arch/s390/mm/init.c	Mon Jan 13 10:18:07 2003
+++ b/arch/s390/mm/init.c	Mon Jan 13 10:18:07 2003
@@ -38,7 +38,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S
--- a/arch/s390/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/s390/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -30,6 +30,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
 #ifdef CONFIG_SHARED_KERNEL
   . = ALIGN(1048576);		/* VM shared segments are 1MB aligned */
 
diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
--- a/arch/s390x/kernel/entry.S	Mon Jan 13 10:18:05 2003
+++ b/arch/s390x/kernel/entry.S	Mon Jan 13 10:18:05 2003
@@ -490,8 +490,8 @@
         .long  SYSCALL(sys_getpriority,sys32_getpriority_wrapper)
         .long  SYSCALL(sys_setpriority,sys32_setpriority_wrapper)
         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old profil syscall */
-        .long  SYSCALL(sys_statfs,sys32_statfs_wrapper)
-        .long  SYSCALL(sys_fstatfs,sys32_fstatfs_wrapper)   /* 100 */
+        .long  SYSCALL(sys_statfs,compat_sys_statfs_wrapper)
+        .long  SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper)   /* 100 */
         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
         .long  SYSCALL(sys_socketcall,sys32_socketcall_wrapper)
         .long  SYSCALL(sys_syslog,sys32_syslog_wrapper)
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	Mon Jan 13 10:18:06 2003
+++ b/arch/s390x/kernel/linux32.c	Mon Jan 13 10:18:06 2003
@@ -884,61 +884,6 @@
 	return sys32_fcntl(fd, cmd, arg);
 }
 
-static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
-{
-	int err;
-	
-	err = put_user (kbuf->f_type, &ubuf->f_type);
-	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
-	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
-	err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
-	err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
-	err |= __put_user (kbuf->f_files, &ubuf->f_files);
-	err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
-	err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
-	err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
-	err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
-	return err;
-}
-
-extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
-
-asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
-{
-	int ret;
-	struct statfs s;
-	mm_segment_t old_fs = get_fs();
-	char *pth;
-	
-	pth = getname (path);
-	ret = PTR_ERR(pth);
-	if (!IS_ERR(pth)) {
-		set_fs (KERNEL_DS);
-		ret = sys_statfs((const char *)pth, &s);
-		set_fs (old_fs);
-		putname (pth);
-		if (put_statfs(buf, &s))
-			return -EFAULT;
-	}
-	return ret;
-}
-
-extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
-
-asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
-{
-	int ret;
-	struct statfs s;
-	mm_segment_t old_fs = get_fs();
-	
-	set_fs (KERNEL_DS);
-	ret = sys_fstatfs(fd, &s);
-	set_fs (old_fs);
-	if (put_statfs(buf, &s))
-		return -EFAULT;
-	return ret;
-}
-
 extern asmlinkage long sys_truncate(const char * path, unsigned long length);
 extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
 
diff -Nru a/arch/s390x/kernel/linux32.h b/arch/s390x/kernel/linux32.h
--- a/arch/s390x/kernel/linux32.h	Mon Jan 13 10:18:07 2003
+++ b/arch/s390x/kernel/linux32.h	Mon Jan 13 10:18:07 2003
@@ -25,19 +25,6 @@
 #define F_SETLK64       13
 #define F_SETLKW64      14    
 
-struct statfs32 {
-	__s32			f_type;
-	__s32			f_bsize;
-	__s32			f_blocks;
-	__s32			f_bfree;
-	__s32			f_bavail;
-	__s32			f_files;
-	__s32			f_ffree;
-	__kernel_fsid_t		f_fsid;
-	__s32			f_namelen;  
-	__s32			f_spare[6];
-};
-
 typedef __u32 old_sigset_t32;       /* at least 32 bits */ 
 
 struct old_sigaction32 {
diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S
--- a/arch/s390x/kernel/wrapper32.S	Mon Jan 13 10:18:07 2003
+++ b/arch/s390x/kernel/wrapper32.S	Mon Jan 13 10:18:07 2003
@@ -440,17 +440,17 @@
 	lgfr	%r4,%r4			# int
 	jg	sys_setpriority		# branch to system call
 
-	.globl  sys32_statfs_wrapper 
-sys32_statfs_wrapper:
+	.globl  compat_sys_statfs_wrapper 
+compat_sys_statfs_wrapper:
 	llgtr	%r2,%r2			# char *
-	llgtr	%r3,%r3			# struct statfs_emu31 *
-	jg	sys32_statfs		# branch to system call
+	llgtr	%r3,%r3			# struct compat_statfs *
+	jg	compat_sys_statfs	# branch to system call
 
-	.globl  sys32_fstatfs_wrapper 
-sys32_fstatfs_wrapper:
+	.globl  compat_sys_fstatfs_wrapper 
+compat_sys_fstatfs_wrapper:
 	llgfr	%r2,%r2			# unsigned int
-	llgtr	%r3,%r3			# struct statfs_emu31 *
-	jg	sys32_fstatfs		# branch to system call
+	llgtr	%r3,%r3			# struct compat_statfs *
+	jg	compat_sys_fstatfs	# branch to system call
 
 	.globl  sys32_socketcall_wrapper 
 sys32_socketcall_wrapper:
diff -Nru a/arch/s390x/mm/init.c b/arch/s390x/mm/init.c
--- a/arch/s390x/mm/init.c	Mon Jan 13 10:18:05 2003
+++ b/arch/s390x/mm/init.c	Mon Jan 13 10:18:05 2003
@@ -38,7 +38,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S
--- a/arch/s390x/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/s390x/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -30,6 +30,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+	
 #ifdef CONFIG_SHARED_KERNEL
   . = ALIGN(1048576);		/* VM shared segments are 1MB aligned */
 
diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c
--- a/arch/sh/mm/init.c	Mon Jan 13 10:18:07 2003
+++ b/arch/sh/mm/init.c	Mon Jan 13 10:18:07 2003
@@ -36,7 +36,7 @@
 #include <asm/io.h>
 #include <asm/tlb.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 /*
  * Cache of MMU context last used.
diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
--- a/arch/sh/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/sh/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -37,6 +37,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   __start___kallsyms = .;	/* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
   __stop___kallsyms = .;
diff -Nru a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
--- a/arch/sparc/mm/init.c	Mon Jan 13 10:18:06 2003
+++ b/arch/sparc/mm/init.c	Mon Jan 13 10:18:06 2003
@@ -34,7 +34,7 @@
 #include <asm/pgalloc.h>	/* bug in asm-generic/tlb.h: check_pgt_cache */
 #include <asm/tlb.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 unsigned long *sparc_valid_addr_bitmap;
 
diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
--- a/arch/sparc/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/sparc/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -35,6 +35,10 @@
   __ksymtab  : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___gpl_ksymtab = .;
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
+
   __start___kallsyms = .;	/* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
   __stop___kallsyms = .;
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Mon Jan 13 10:18:06 2003
+++ b/arch/sparc64/kernel/sys_sparc32.c	Mon Jan 13 10:18:06 2003
@@ -840,61 +840,6 @@
 	return sys32_fcntl(fd, cmd, arg);
 }
 
-static int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
-{
-	int err;
-	
-	err = put_user (kbuf->f_type, &ubuf->f_type);
-	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
-	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
-	err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
-	err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
-	err |= __put_user (kbuf->f_files, &ubuf->f_files);
-	err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
-	err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
-	err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
-	err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
-	return err;
-}
-
-extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
-
-asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
-{
-	int ret;
-	struct statfs s;
-	mm_segment_t old_fs = get_fs();
-	char *pth;
-	
-	pth = getname (path);
-	ret = PTR_ERR(pth);
-	if (!IS_ERR(pth)) {
-		set_fs (KERNEL_DS);
-		ret = sys_statfs((const char *)pth, &s);
-		set_fs (old_fs);
-		putname (pth);
-		if (put_statfs(buf, &s))
-			return -EFAULT;
-	}
-	return ret;
-}
-
-extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
-
-asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
-{
-	int ret;
-	struct statfs s;
-	mm_segment_t old_fs = get_fs();
-	
-	set_fs (KERNEL_DS);
-	ret = sys_fstatfs(fd, &s);
-	set_fs (old_fs);
-	if (put_statfs(buf, &s))
-		return -EFAULT;
-	return ret;
-}
-
 extern asmlinkage long sys_truncate(const char * path, unsigned long length);
 extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
 
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Mon Jan 13 10:18:06 2003
+++ b/arch/sparc64/kernel/systbls.S	Mon Jan 13 10:18:06 2003
@@ -50,7 +50,7 @@
 /*140*/	.word sys32_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys32_getrlimit
 	.word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
 /*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
-	.word sys32_fcntl64, sys_ni_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
+	.word sys32_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
 /*160*/	.word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 	.word sys_quotactl, sys_set_tid_address, sys32_mount, sys_ustat, sys_setxattr
 /*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
@@ -197,7 +197,7 @@
 	.word sunos_nosys, sunos_nosys
 /*150*/	.word sys_getsockname, sunos_nosys, sunos_nosys
 	.word sys_poll, sunos_nosys, sunos_nosys
-	.word sunos_getdirentries, sys32_statfs, sys32_fstatfs
+	.word sunos_getdirentries, compat_sys_statfs, compat_sys_fstatfs
 	.word sys_oldumount, sunos_nosys, sunos_nosys
 	.word sys_getdomainname, sys_setdomainname
 	.word sunos_nosys, sys_quotactl, sunos_nosys
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Mon Jan 13 10:18:05 2003
+++ b/arch/sparc64/mm/init.c	Mon Jan 13 10:18:05 2003
@@ -36,7 +36,7 @@
 #include <asm/tlb.h>
 #include <asm/spitfire.h>
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 extern void device_scan(void);
 
diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
--- a/arch/sparc64/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
+++ b/arch/sparc64/vmlinux.lds.S	Mon Jan 13 10:18:07 2003
@@ -39,6 +39,9 @@
   __start___ksymtab = .;
   __ksymtab  : { *(__ksymtab) }
   __stop___ksymtab = .;
+  __start___gpl_ksymtab = .;
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
   __kstrtab  : { *(.kstrtab) }
   __start___kallsyms = .;	/* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
--- a/arch/um/kernel/mem.c	Mon Jan 13 10:18:05 2003
+++ b/arch/um/kernel/mem.c	Mon Jan 13 10:18:05 2003
@@ -44,7 +44,7 @@
 extern long physmem_size;
 
 /* Not changed by UML */
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 /* Changed during early boot */
 int kmalloc_ok = 0;
diff -Nru a/arch/v850/README b/arch/v850/README
--- a/arch/v850/README	Mon Jan 13 10:18:07 2003
+++ b/arch/v850/README	Mon Jan 13 10:18:07 2003
@@ -1,7 +1,6 @@
 This port to the NEC V850E processor supports the following platforms:
 
-   + The gdb v850e simulator (CONFIG_V850E_SIM); see the subdirectory `sim'
-     for some more support files for this.
+   + The gdb v850e simulator (CONFIG_V850E_SIM).
 
    + The Midas labs RTE-V850E/MA1-CB evaluation board (CONFIG_RTE_CB_MA1),
      with untested support for the RTE-V850E/NB85E-CB board
diff -Nru a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
--- a/arch/v850/kernel/as85ep1.c	Mon Jan 13 10:18:07 2003
+++ b/arch/v850/kernel/as85ep1.c	Mon Jan 13 10:18:07 2003
@@ -44,8 +44,10 @@
 
 void __init mach_early_init (void)
 {
+#ifndef CONFIG_ROM_KERNEL
 	const u32 *src;
 	register u32 *dst asm ("ep");
+#endif
 
 	AS85EP1_CSC(0) = 0x0403;
 	AS85EP1_BCT(0) = 0xB8B8;
@@ -53,25 +55,28 @@
 	AS85EP1_BCC    = 0x0012;
 	AS85EP1_ASC    = 0;
 	AS85EP1_LBS    = 0x00A9;
-	AS85EP1_RFS(1) = 0x8205;
-	AS85EP1_RFS(3) = 0x8205;
-	AS85EP1_SCR(1) = 0x20A9;
-	AS85EP1_SCR(3) = 0x20A9;
 
 	AS85EP1_PORT_PMC(6)  = 0xFF; /* A20-25, A0,A1 $BM-8z(B */
 	AS85EP1_PORT_PMC(7)  = 0x0E; /* CS1,2,3       $BM-8z(B */
 	AS85EP1_PORT_PMC(9)  = 0xFF; /* D16-23        $BM-8z(B */
 	AS85EP1_PORT_PMC(10) = 0xFF; /* D24-31        $BM-8z(B */
 
-	AS85EP1_IRAMM = 0x3;	/* $BFbB"L?Na(BRAM$B$O!V(Bwrite-mode$B!W$K$J$j$^$9(B */
+	AS85EP1_RFS(1) = 0x800c;
+	AS85EP1_RFS(3) = 0x800c;
+	AS85EP1_SCR(1) = 0x20A9;
+	AS85EP1_SCR(3) = 0x20A9;
 
-	/* The early chip we have is buggy, so that writing the interrupt
+#ifndef CONFIG_ROM_KERNEL
+	/* The early chip we have is buggy, and writing the interrupt
 	   vectors into low RAM may screw up, so for non-ROM kernels, we
 	   only rely on the reset vector being downloaded, and copy the
 	   rest of the interrupt vectors into place here.  The specific bug
 	   is that writing address N, where (N & 0x10) == 0x10, will _also_
 	   write to address (N - 0x10).  We avoid this (effectively) by
 	   writing in 16-byte chunks backwards from the end.  */
+
+	AS85EP1_IRAMM = 0x3;	/* $BFbB"L?Na(BRAM$B$O!V(Bwrite-mode$B!W$K$J$j$^$9(B */
+
 	src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF);
 	dst = (u32 *)&_intv_copy_dst_start
 		+ (src - (u32 *)&_intv_copy_src_start);
@@ -83,6 +88,7 @@
 	} while (src > (u32 *)&_intv_copy_src_start);
 
 	AS85EP1_IRAMM = 0x0;	/* $BFbB"L?Na(BRAM$B$O!V(Bread-mode$B!W$K$J$j$^$9(B */
+#endif /* !CONFIG_ROM_KERNEL */
 
 	nb85e_intc_disable_irqs ();
 }
@@ -107,16 +113,20 @@
 	*ram_len = RAM_END - RAM_START;
 }
 
+/* Convenience macros.  */
+#define SRAM_END	(SRAM_ADDR + SRAM_SIZE)
+#define SDRAM_END	(SDRAM_ADDR + SDRAM_SIZE)
+
 void __init mach_reserve_bootmem ()
 {
 	extern char _root_fs_image_start, _root_fs_image_end;
 	u32 root_fs_image_start = (u32)&_root_fs_image_start;
 	u32 root_fs_image_end = (u32)&_root_fs_image_end;
 
-	/* We can't use the space between SRAM and SDRAM, so prevent the
-	   kernel from trying.  */
-	reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
-			 SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
+	if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START)
+		/* We can't use the space between SRAM and SDRAM, so
+		   prevent the kernel from trying.  */
+		reserve_bootmem (SRAM_END, SDRAM_ADDR - SRAM_END);
 
 	/* Reserve the memory used by the root filesystem image if it's
 	   in RAM.  */
diff -Nru a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c
--- a/arch/v850/kernel/module.c	Mon Jan 13 10:18:05 2003
+++ b/arch/v850/kernel/module.c	Mon Jan 13 10:18:05 2003
@@ -1,9 +1,9 @@
 /*
  * arch/v850/kernel/module.c -- Architecture-specific module functions
  *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
- *  Copyright (C) 2001  Rusty Russell
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,03  Rusty Russell
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -100,18 +100,31 @@
 	return ret;
 }
 
-long module_core_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs,
-		       const char *secstrings, struct module *mod)
+int module_frob_arch_sections(Elf32_Ehdr *hdr,
+			      Elf32_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *me)
 {
-	mod->arch.core_plt_offset = (mod->core_size + 3) & ~3;
-	return mod->core_size + get_plt_size (hdr, sechdrs, secstrings, 1);
-}
+	unsigned int i;
 
-long module_init_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs,
-		       const char *secstrings, struct module *mod)
-{
-	mod->arch.init_plt_offset = (mod->init_size + 3) & ~3;
-	return mod->init_size + get_plt_size (hdr, sechdrs, secstrings, 1);
+	/* Find .plt and .pltinit sections */
+	for (i = 0; i < hdr->e_shnum; i++) {
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
+			me->arch.init_plt_section = i;
+		else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
+			me->arch.core_plt_section = i;
+	}
+	if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
+		printk("Module doesn't contain .plt or .plt.init sections.\n");
+		return -ENOEXEC;
+	}
+
+	/* Override their sizes */
+	sechdrs[me->arch.core_plt_section].sh_size
+		= get_plt_size(hdr, sechdrs, secstrings, 0);
+	sechdrs[me->arch.init_plt_section].sh_size
+		= get_plt_size(hdr, sechdrs, secstrings, 1);
+	return 0;
 }
 
 int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab,
@@ -123,7 +136,8 @@
 }
 
 /* Set up a trampoline in the PLT to bounce us to the distant function */
-static uint32_t do_plt_call(void *location, Elf32_Addr val, struct module *mod)
+static uint32_t do_plt_call (void *location, Elf32_Addr val,
+			     Elf32_Shdr *sechdrs, struct module *mod)
 {
 	struct v850_plt_entry *entry;
 	/* Instructions used to do the indirect jump.  */
@@ -137,10 +151,10 @@
 
 	/* Init, or core PLT? */
 	if (location >= mod->module_core
-	    && location < mod->module_core + mod->arch.core_plt_offset)
-		entry = mod->module_core + mod->arch.core_plt_offset;
+	    && location < mod->module_core + mod->core_size)
+		entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
 	else
-		entry = mod->module_init + mod->arch.init_plt_offset;
+		entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
 
 	/* Find this entry, or if that fails, the next avail. entry */
 	while (entry->tramp[0])
@@ -199,7 +213,7 @@
 			/* Maybe jump indirectly via a PLT table entry.  */
 			if ((int32_t)(val - (uint32_t)loc) > 0x1fffff
 			    || (int32_t)(val - (uint32_t)loc) < -0x200000)
-				val = do_plt_call (loc, val, mod);
+				val = do_plt_call (loc, val, sechdrs, mod);
 
 			val -= (uint32_t)loc;
 
diff -Nru a/arch/v850/vmlinux.lds.S b/arch/v850/vmlinux.lds.S
--- a/arch/v850/vmlinux.lds.S	Mon Jan 13 10:18:06 2003
+++ b/arch/v850/vmlinux.lds.S	Mon Jan 13 10:18:06 2003
@@ -1,8 +1,8 @@
 /*
  * arch/v850/vmlinux.lds.S -- kernel linker script for v850 platforms
  *
- *  Copyright (C) 2002  NEC Electronics Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -51,6 +51,9 @@
 		___start___ksymtab = . ;/* Kernel symbol table.  */	      \
 			*(__ksymtab)					      \
 		___stop___ksymtab = . ;					      \
+		___start___gpl_ksymtab = . ; /* Same for GPL symbols.  */     \
+			*(__gpl_ksymtab)				      \
+		___stop___gpl_ksymtab = . ;				      \
 		. = ALIGN (4) ;						      \
 		__etext = . ;
 
diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
--- a/arch/x86_64/mm/init.c	Mon Jan 13 10:18:05 2003
+++ b/arch/x86_64/mm/init.c	Mon Jan 13 10:18:05 2003
@@ -40,7 +40,7 @@
 
 unsigned long start_pfn, end_pfn;
 
-mmu_gather_t mmu_gathers[NR_CPUS];
+struct mmu_gather mmu_gathers[NR_CPUS];
 
 /*
  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S
--- a/arch/x86_64/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
+++ b/arch/x86_64/vmlinux.lds.S	Mon Jan 13 10:18:05 2003
@@ -30,6 +30,9 @@
   __start___ksymtab = .;	/* Kernel symbol table */
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
+  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
+  __gpl_ksymtab : { *(__gpl_ksymtab) }
+  __stop___gpl_ksymtab = .;
 
   __start___kallsyms = .;	/* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c
--- a/drivers/acorn/scsi/cumana_2.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/acorn/scsi/cumana_2.c	Mon Jan 13 10:18:06 2003
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
@@ -163,26 +164,27 @@
 		       fasdmadir_t direction, fasdmatype_t min_type)
 {
 	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
+	struct device *dev = scsi_get_device(host);
 	int dmach = host->dma_channel;
 
 	outb(ALATCH_DIS_DMA, info->alatch);
 
 	if (dmach != NO_DMA &&
 	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
-		int bufs, pci_dir, dma_dir, alatch_dir;
+		int bufs, map_dir, dma_dir, alatch_dir;
 
 		bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
 
 		if (direction == DMA_OUT)
-			pci_dir = PCI_DMA_TODEVICE,
+			map_dir = DMA_TO_DEVICE,
 			dma_dir = DMA_MODE_WRITE,
 			alatch_dir = ALATCH_DMA_OUT;
 		else
-			pci_dir = PCI_DMA_FROMDEVICE,
+			map_dir = DMA_FROM_DEVICE,
 			dma_dir = DMA_MODE_READ,
 			alatch_dir = ALATCH_DMA_IN;
 
-		pci_map_sg(NULL, info->sg, bufs + 1, pci_dir);
+		dma_map_sg(dev, info->sg, bufs + 1, map_dir);
 
 		disable_dma(dmach);
 		set_dma_sg(dmach, info->sg, bufs + 1);
diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
--- a/drivers/acorn/scsi/eesox.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/acorn/scsi/eesox.c	Mon Jan 13 10:18:07 2003
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -165,22 +166,23 @@
 		       fasdmadir_t direction, fasdmatype_t min_type)
 {
 	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
+	struct device *dev = scsi_get_device(host);
 	int dmach = host->dma_channel;
 
 	if (dmach != NO_DMA &&
 	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
-		int bufs, pci_dir, dma_dir;
+		int bufs, map_dir, dma_dir;
 
 		bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
 
 		if (direction == DMA_OUT)
-			pci_dir = PCI_DMA_TODEVICE,
+			map_dir = DMA_TO_DEVICE,
 			dma_dir = DMA_MODE_WRITE;
 		else
-			pci_dir = PCI_DMA_FROMDEVICE,
+			map_dir = DMA_FROM_DEVICE,
 			dma_dir = DMA_MODE_READ;
 
-		pci_map_sg(NULL, info->sg, bufs + 1, pci_dir);
+		dma_map_sg(dev, info->sg, bufs + 1, map_dir);
 
 		disable_dma(dmach);
 		set_dma_sg(dmach, info->sg, bufs + 1);
diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c
--- a/drivers/acorn/scsi/powertec.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/acorn/scsi/powertec.c	Mon Jan 13 10:18:06 2003
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
@@ -135,22 +136,23 @@
 		       fasdmadir_t direction, fasdmatype_t min_type)
 {
 	struct powertec_info *info = (struct powertec_info *)host->hostdata;
+	struct device *dev = scsi_get_device(host);
 	int dmach = host->dma_channel;
 
 	if (dmach != NO_DMA &&
 	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
-		int bufs, pci_dir, dma_dir;
+		int bufs, map_dir, dma_dir;
 
 		bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
 
 		if (direction == DMA_OUT)
-			pci_dir = PCI_DMA_TODEVICE,
+			map_dir = DMA_TO_DEVICE,
 			dma_dir = DMA_MODE_WRITE;
 		else
-			pci_dir = PCI_DMA_FROMDEVICE,
+			map_dir = DMA_FROM_DEVICE,
 			dma_dir = DMA_MODE_READ;
 
-		pci_map_sg(NULL, info->sg, bufs + 1, pci_dir);
+		dma_map_sg(dev, info->sg, bufs + 1, map_dir);
 
 		disable_dma(dmach);
 		set_dma_sg(dmach, info->sg, bufs + 1);
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/base/bus.c	Mon Jan 13 10:18:05 2003
@@ -31,28 +31,26 @@
 
 
 static ssize_t
-drv_attr_show(struct kobject * kobj, struct attribute * attr,
-	      char * buf, size_t count, loff_t off)
+drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
 	struct driver_attribute * drv_attr = to_drv_attr(attr);
 	struct device_driver * drv = to_driver(kobj);
 	ssize_t ret = 0;
 
 	if (drv_attr->show)
-		ret = drv_attr->show(drv,buf,count,off);
+		ret = drv_attr->show(drv,buf);
 	return ret;
 }
 
 static ssize_t
-drv_attr_store(struct kobject * kobj, struct attribute * attr,
-	       const char * buf, size_t count, loff_t off)
+drv_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf)
 {
 	struct driver_attribute * drv_attr = to_drv_attr(attr);
 	struct device_driver * drv = to_driver(kobj);
 	ssize_t ret = 0;
 
 	if (drv_attr->store)
-		ret = drv_attr->store(drv,buf,count,off);
+		ret = drv_attr->store(drv,buf);
 	return ret;
 }
 
@@ -80,28 +78,26 @@
 
 
 static ssize_t
-bus_attr_show(struct kobject * kobj, struct attribute * attr,
-	      char * buf, size_t count, loff_t off)
+bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
 	struct bus_attribute * bus_attr = to_bus_attr(attr);
 	struct bus_type * bus = to_bus(kobj);
 	ssize_t ret = 0;
 
 	if (bus_attr->show)
-		ret = bus_attr->show(bus,buf,count,off);
+		ret = bus_attr->show(bus,buf);
 	return ret;
 }
 
 static ssize_t
-bus_attr_store(struct kobject * kobj, struct attribute * attr,
-	       const char * buf, size_t count, loff_t off)
+bus_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf)
 {
 	struct bus_attribute * bus_attr = to_bus_attr(attr);
 	struct bus_type * bus = to_bus(kobj);
 	ssize_t ret = 0;
 
 	if (bus_attr->store)
-		ret = bus_attr->store(bus,buf,count,off);
+		ret = bus_attr->store(bus,buf);
 	return ret;
 }
 
@@ -316,12 +312,14 @@
  *	If bus_match() returns 0 and the @dev->driver is set, we've found
  *	a compatible pair, so we call devclass_add_device() to add the 
  *	device to the class. 
+ *
+ *	Note that we ignore the error from bus_match(), since it's perfectly
+ *	valid for a driver not to bind to any devices.
  */
 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;
@@ -333,7 +331,7 @@
 				devclass_add_device(dev);
 		}
 	}
-	return error;
+	return 0;
 }
 
 
@@ -387,15 +385,18 @@
 int bus_add_device(struct device * dev)
 {
 	struct bus_type * bus = get_bus(dev->bus);
+	int error = 0;
+
 	if (bus) {
 		down_write(&dev->bus->subsys.rwsem);
 		pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id);
 		list_add_tail(&dev->bus_list,&dev->bus->devices.list);
-		device_attach(dev);
+		if ((error = device_attach(dev)))
+			list_del_init(&dev->bus_list);
 		up_write(&dev->bus->subsys.rwsem);
 		sysfs_create_link(&bus->devices.kobj,&dev->kobj,dev->bus_id);
 	}
-	return 0;
+	return error;
 }
 
 /**
@@ -429,19 +430,33 @@
 int bus_add_driver(struct device_driver * drv)
 {
 	struct bus_type * bus = get_bus(drv->bus);
+	int error = 0;
+
 	if (bus) {
 		pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
 
 		strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
 		drv->kobj.kset = &bus->drivers;
-		kobject_register(&drv->kobj);
+
+		if ((error = kobject_register(&drv->kobj))) {
+			put_bus(bus);
+			return error;
+		}
 
 		down_write(&bus->subsys.rwsem);
-		devclass_add_driver(drv);
-		driver_attach(drv);
+		if (!(error = devclass_add_driver(drv))) {
+			if ((error = driver_attach(drv))) {
+				devclass_remove_driver(drv);
+			}
+		}
 		up_write(&bus->subsys.rwsem);
+
+		if (error) {
+			kobject_unregister(&drv->kobj);
+			put_bus(bus);
+		}
 	}
-	return 0;
+	return error;
 }
 
 
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/base/class.c	Mon Jan 13 10:18:07 2003
@@ -2,7 +2,7 @@
  * class.c - basic device class management
  */
 
-#define DEBUG
+#undef DEBUG
 
 #include <linux/device.h>
 #include <linux/module.h>
@@ -14,28 +14,26 @@
 #define to_class(obj) container_of(obj,struct device_class,subsys.kset.kobj)
 
 static ssize_t
-devclass_attr_show(struct kobject * kobj, struct attribute * attr,
-	      char * buf, size_t count, loff_t off)
+devclass_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
 	struct devclass_attribute * class_attr = to_class_attr(attr);
 	struct device_class * dc = to_class(kobj);
 	ssize_t ret = 0;
 
 	if (class_attr->show)
-		ret = class_attr->show(dc,buf,count,off);
+		ret = class_attr->show(dc,buf);
 	return ret;
 }
 
 static ssize_t
-devclass_attr_store(struct kobject * kobj, struct attribute * attr,
-	       const char * buf, size_t count, loff_t off)
+devclass_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf)
 {
 	struct devclass_attribute * class_attr = to_class_attr(attr);
 	struct device_class * dc = to_class(kobj);
 	ssize_t ret = 0;
 
 	if (class_attr->store)
-		ret = class_attr->store(dc,buf,count,off);
+		ret = class_attr->store(dc,buf);
 	return ret;
 }
 
@@ -100,15 +98,19 @@
 int devclass_add_driver(struct device_driver * drv)
 {
 	struct device_class * cls = get_devclass(drv->devclass);
+	int error = 0;
+
 	if (cls) {
 		down_write(&cls->subsys.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.list);
-		devclass_drv_link(drv);
+		error = devclass_drv_link(drv);
+		
+		if (!error)
+			list_add_tail(&drv->class_list,&cls->drivers.list);
 		up_write(&cls->subsys.rwsem);
 	}
-	return 0;
+	return error;
 }
 
 void devclass_remove_driver(struct device_driver * drv)
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/base/core.c	Mon Jan 13 10:18:05 2003
@@ -35,28 +35,26 @@
 extern struct attribute * dev_default_attrs[];
 
 static ssize_t
-dev_attr_show(struct kobject * kobj, struct attribute * attr,
-	      char * buf, size_t count, loff_t off)
+dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
 	struct device_attribute * dev_attr = to_dev_attr(attr);
 	struct device * dev = to_dev(kobj);
 	ssize_t ret = 0;
 
 	if (dev_attr->show)
-		ret = dev_attr->show(dev,buf,count,off);
+		ret = dev_attr->show(dev,buf);
 	return ret;
 }
 
 static ssize_t
-dev_attr_store(struct kobject * kobj, struct attribute * attr,
-	       const char * buf, size_t count, loff_t off)
+dev_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf)
 {
 	struct device_attribute * dev_attr = to_dev_attr(attr);
 	struct device * dev = to_dev(kobj);
 	ssize_t ret = 0;
 
 	if (dev_attr->store)
-		ret = dev_attr->store(dev,buf,count,off);
+		ret = dev_attr->store(dev,buf);
 	return ret;
 }
 
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/base/driver.c	Mon Jan 13 10:18:07 2003
@@ -3,7 +3,7 @@
  *
  */
 
-#define DEBUG
+#undef DEBUG
 
 #include <linux/device.h>
 #include <linux/module.h>
diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c
--- a/drivers/base/interface.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/base/interface.c	Mon Jan 13 10:18:05 2003
@@ -10,21 +10,21 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 
-static ssize_t device_read_name(struct device * dev, char * buf, size_t count, loff_t off)
+static ssize_t device_read_name(struct device * dev, char * buf)
 {
-	return off ? 0 : sprintf(buf,"%s\n",dev->name);
+	return sprintf(buf,"%s\n",dev->name);
 }
 
 static DEVICE_ATTR(name,S_IRUGO,device_read_name,NULL);
 
 static ssize_t
-device_read_power(struct device * dev, char * page, size_t count, loff_t off)
+device_read_power(struct device * dev, char * page)
 {
-	return off ? 0 : sprintf(page,"%d\n",dev->power_state);
+	return sprintf(page,"%d\n",dev->power_state);
 }
 
 static ssize_t
-device_write_power(struct device * dev, const char * buf, size_t count, loff_t off)
+device_write_power(struct device * dev, const char * buf)
 {
 	char	str_command[20];
 	char	str_level[20];
@@ -33,9 +33,6 @@
 	u32	int_level;
 	int	error = 0;
 
-	if (off)
-		return 0;
-
 	if (!dev->driver)
 		goto done;
 
@@ -83,7 +80,7 @@
 			error = 0;
 	}
  done:
-	return error < 0 ? error : count;
+	return error < 0 ? error : strlen(buf);
 }
 
 static DEVICE_ATTR(power,S_IWUSR | S_IRUGO,
diff -Nru a/drivers/base/intf.c b/drivers/base/intf.c
--- a/drivers/base/intf.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/base/intf.c	Mon Jan 13 10:18:07 2003
@@ -2,7 +2,7 @@
  * intf.c - class-specific interface management
  */
 
-#define DEBUG
+#undef DEBUG
 
 #include <linux/device.h>
 #include <linux/module.h>
@@ -66,8 +66,7 @@
 		kobject_register(&data->kobj);
 
 		list_add_tail(&data->dev_entry,&data->dev->intf_list);
-		intf_dev_link(data);
-		return 0;
+		return intf_dev_link(data);
 	}
 	return -EINVAL;
 }
diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c
--- a/drivers/base/sys.c	Mon Jan 13 10:18:04 2003
+++ b/drivers/base/sys.c	Mon Jan 13 10:18:04 2003
@@ -80,7 +80,7 @@
  *	and @root->dev.
  *	If both are 0, they will be cleaned up by the core.
  */
-void sys_unegister_root(struct sys_root *  root)
+void sys_unregister_root(struct sys_root *root)
 {
 	device_unregister(&root->sysdev);
 	device_unregister(&root->dev);
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/block/genhd.c	Mon Jan 13 10:18:06 2003
@@ -276,17 +276,17 @@
 
 struct disk_attribute {
 	struct attribute attr;
-	ssize_t (*show)(struct gendisk *, char *, size_t, loff_t);
+	ssize_t (*show)(struct gendisk *, char *);
 };
 
 static ssize_t disk_attr_show(struct kobject * kobj, struct attribute * attr,
-			      char * page, size_t count, loff_t off)
+			      char * page)
 {
 	struct gendisk * disk = to_disk(kobj);
 	struct disk_attribute * disk_attr = container_of(attr,struct disk_attribute,attr);
 	ssize_t ret = 0;
 	if (disk_attr->show)
-		ret = disk_attr->show(disk,page,count,off);
+		ret = disk_attr->show(disk,page);
 	return ret;
 }
 
@@ -294,21 +294,18 @@
 	.show	= &disk_attr_show,
 };
 
-static ssize_t disk_dev_read(struct gendisk * disk,
-			     char *page, size_t count, loff_t off)
+static ssize_t disk_dev_read(struct gendisk * disk, char *page)
 {
 	dev_t base = MKDEV(disk->major, disk->first_minor); 
-	return off ? 0 : sprintf(page, "%04x\n",base);
+	return sprintf(page, "%04x\n",base);
 }
-static ssize_t disk_range_read(struct gendisk * disk,
-			       char *page, size_t count, loff_t off)
+static ssize_t disk_range_read(struct gendisk * disk, char *page)
 {
-	return off ? 0 : sprintf(page, "%d\n",disk->minors);
+	return sprintf(page, "%d\n",disk->minors);
 }
-static ssize_t disk_size_read(struct gendisk * disk,
-			      char *page, size_t count, loff_t off)
+static ssize_t disk_size_read(struct gendisk * disk, char *page)
 {
-	return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
+	return sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
 }
 
 static inline unsigned jiffies_to_msec(unsigned jif)
@@ -321,11 +318,10 @@
 	return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ;
 #endif
 }
-static ssize_t disk_stat_read(struct gendisk * disk,
-			      char *page, size_t count, loff_t off)
+static ssize_t disk_stat_read(struct gendisk * disk, char *page)
 {
 	disk_round_stats(disk);
-	return off ? 0 : sprintf(page,
+	return sprintf(page,
 		"%8u %8u %8llu %8u "
 		"%8u %8u %8llu %8u "
 		"%8u %8u %8u"
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/block/umem.c	Mon Jan 13 10:18:07 2003
@@ -371,11 +371,12 @@
 {
 	request_queue_t *q = data;
 	struct cardinfo *card = q->queuedata;
+	unsigned long flags;
 
-	spin_lock_bh(&card->lock);
+	spin_lock_irqsave(&card->lock, flags);
 	if (blk_remove_plug(q))
 		activate(card);
-	spin_unlock_bh(&card->lock);
+	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 /* 
@@ -557,12 +558,12 @@
 	PRINTK("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
 
 	bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/
-	spin_lock_bh(&card->lock);
+	spin_lock_irq(&card->lock);
 	*card->biotail = bio;
 	bio->bi_next = NULL;
 	card->biotail = &bio->bi_next;
 	blk_plug_device(q);
-	spin_unlock_bh(&card->lock);
+	spin_unlock_irq(&card->lock);
 
 	return 0;
 }
diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
--- a/drivers/char/rio/rioctrl.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/char/rio/rioctrl.c	Mon Jan 13 10:18:06 2003
@@ -203,7 +203,7 @@
 	
 	func_enter ();
 	
-	/* Confuse teh compiler to think that we've initialized these */
+	/* Confuse the compiler to think that we've initialized these */
 	Host=0;
 	PortP = NULL;
 
diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
--- a/drivers/char/watchdog/Kconfig	Mon Jan 13 10:18:06 2003
+++ b/drivers/char/watchdog/Kconfig	Mon Jan 13 10:18:06 2003
@@ -168,6 +168,19 @@
 
 	  Not sure? It's safe to say N.
 
+config SA1100_WATCHDOG
+	tristate "SA1100 watchdog"
+	depends on WATCHDOG && ARCH_SA1100
+	help
+	  Watchdog timer embedded into SA11x0 chips. This will reboot your
+	  system when timeout is reached.
+	  NOTE, that once enabled, this timer cannot be disabled.
+
+	  This driver 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
+	  Documentation/modules.txt. The module will be called sa1100_wdt.o.
+
 config EUROTECH_WDT
 	tristate "Eurotech CPU-1220/1410 Watchdog Timer"
 	depends on WATCHDOG
diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
--- a/drivers/char/watchdog/Makefile	Mon Jan 13 10:18:06 2003
+++ b/drivers/char/watchdog/Makefile	Mon Jan 13 10:18:06 2003
@@ -21,6 +21,7 @@
 obj-$(CONFIG_I810_TCO) += i810-tco.o
 obj-$(CONFIG_MACHZ_WDT) += machzwd.o
 obj-$(CONFIG_SH_WDT) += shwdt.o
+obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
 obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
 obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
diff -Nru a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/watchdog/sa1100_wdt.c	Mon Jan 13 10:18:07 2003
@@ -0,0 +1,217 @@
+/*
+ *	Watchdog driver for the SA11x0
+ *
+ *      (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *          Based on SoftDog driver by Alan Cox <alan@redhat.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
+ *	warranty for any of this software. This material is provided
+ *	"AS-IS" and at no charge.
+ *
+ *	(c) Copyright 2000           Oleg Drokin <green@crimea.edu>
+ *
+ *      27/11/2000 Initial release
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#define OSCR_FREQ		3686400
+#define SA1100_CLOSE_MAGIC	(0x5afc4453)
+
+static unsigned long sa1100wdt_users;
+static int expect_close;
+static int pre_margin;
+static int boot_status;
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+/*
+ *	Allow only one person to hold it open
+ */
+static int sa1100dog_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(1,&sa1100wdt_users))
+		return -EBUSY;
+
+	/* Activate SA1100 Watchdog timer */
+	OSMR3 = OSCR + pre_margin;
+	OSSR = OSSR_M3;
+	OWER = OWER_WME;
+	OIER |= OIER_E3;
+	return 0;
+}
+
+/*
+ *	Shut off the timer.
+ * 	Lock it in if it's a module and we defined ...NOWAYOUT
+ *	Oddly, the watchdog can only be enabled, but we can turn off
+ *	the interrupt, which appears to prevent the watchdog timing out.
+ */
+static int sa1100dog_release(struct inode *inode, struct file *file)
+{
+	OSMR3 = OSCR + pre_margin;
+
+	if (expect_close == SA1100_CLOSE_MAGIC) {
+		OIER &= ~OIER_E3;
+	} else {
+		printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly.  WDT will not stop!\n");
+	}
+
+	clear_bit(1, &sa1100wdt_users);
+
+	return 0;
+}
+
+static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+	/* Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			expect_close = 0;
+
+			for (i = 0; i != len; i++) {
+				char c;
+
+				if (get_user(c, data + i))
+					return -EFAULT;
+				if (c == 'V')
+					expect_close = SA1100_CLOSE_MAGIC;
+			}
+		}
+		/* Refresh OSMR3 timer. */
+		OSMR3 = OSCR + pre_margin;
+	}
+
+	return len ? 1 : 0;
+}
+
+static struct watchdog_info ident = {
+	.options	= WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
+			  WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.identity	= "SA1100 Watchdog",
+};
+
+static int sa1100dog_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOIOCTLCMD;
+	int time;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		ret = copy_to_user((struct watchdog_info *)arg, &ident,
+				   sizeof(ident)) ? -EFAULT : 0;
+		break;
+
+	case WDIOC_GETSTATUS:
+		ret = put_user(0, (int *)arg);
+		break;
+
+	case WDIOC_GETBOOTSTATUS:
+		ret = put_user(boot_status, (int *)arg);
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		ret = get_user(time, (int *)arg);
+		if (ret)
+			break;
+
+		if (time <= 0 || time > 255) {
+			ret = -EINVAL;
+			break;
+		}
+
+		pre_margin = OSCR_FREQ * time;
+		OSMR3 = OSCR + pre_margin;
+		/*fall through*/
+
+	case WDIOC_GETTIMEOUT:
+		ret = put_user(pre_margin / OSCR_FREQ, (int *)arg);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		OSMR3 = OSCR + pre_margin;
+		ret = 0;
+		break;
+	}
+	return ret;
+}
+
+static struct file_operations sa1100dog_fops =
+{
+	.owner		= THIS_MODULE,
+	.write		= sa1100dog_write,
+	.ioctl		= sa1100dog_ioctl,
+	.open		= sa1100dog_open,
+	.release	= sa1100dog_release,
+};
+
+static struct miscdevice sa1100dog_miscdev =
+{
+	.minor		= WATCHDOG_MINOR,
+	.name		= "SA1100 watchdog",
+	.fops		= &sa1100dog_fops,
+};
+
+static int margin __initdata = 60;		/* (secs) Default is 1 minute */
+
+static int __init sa1100dog_init(void)
+{
+	int ret;
+
+	/*
+	 * Read the reset status, and save it for later.  If
+	 * we suspend, RCSR will be cleared, and the watchdog
+	 * reset reason will be lost.
+	 */
+	boot_status = (RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0;
+	pre_margin = OSCR_FREQ * margin;
+
+	ret = misc_register(&sa1100dog_miscdev);
+	if (ret == 0)
+		printk("SA1100 Watchdog Timer: timer margin %d sec\n",
+		       margin);
+
+	return ret;
+}
+
+static void __exit sa1100dog_exit(void)
+{
+	misc_deregister(&sa1100dog_miscdev);
+}
+
+module_init(sa1100dog_init);
+module_exit(sa1100dog_exit);
+
+MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>");
+MODULE_DESCRIPTION("SA1100 Watchdog");
+MODULE_PARM(margin,"i");
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
+
+MODULE_PARM(nowayout, "i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig
--- a/drivers/ide/Kconfig	Mon Jan 13 10:18:06 2003
+++ b/drivers/ide/Kconfig	Mon Jan 13 10:18:06 2003
@@ -438,7 +438,7 @@
 	  SAY N!
 
 config BLK_DEV_AMD74XX
-	tristate "AMD Viper support"
+	tristate "AMD and nVidia IDE support"
 	depends on BLK_DEV_IDEDMA_PCI
 	help
 	  This driver adds explicit support for AMD-7xx and AMD-8111 chips
@@ -446,10 +446,6 @@
 	  change PIO, DMA and UDMA speeds and to configure the chip to
 	  optimum performance.
 
-config AMD74XX_OVERRIDE
-	bool "AMD Viper ATA-66 Override"
-	depends on BLK_DEV_AMD74XX
-
 config BLK_DEV_CMD64X
 	tristate "CMD64{3|6|8|9} chipset support"
 	depends on BLK_DEV_IDEDMA_PCI
@@ -457,6 +453,13 @@
 	  Say Y here if you have an IDE controller which uses any of these
 	  chipsets: CMD643, CMD646, or CMD648.
 
+config BLK_DEV_TRIFLEX
+	tristate "Compaq Triflex IDE support"
+	depends on BLK_DEV_IDEDMA_PCI
+	help
+	  Say Y here if you have a Compaq Triflex IDE controller, such
+	  as those commonly found on Compaq Pentium-Pro systems
+
 config BLK_DEV_CY82C693
 	tristate "CY82C693 chipset support"
 	depends on BLK_DEV_IDEDMA_PCI
@@ -556,10 +559,6 @@
 	  Technology Express, Inc. ITE8172 SBC.  Vendor page at
 	  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
 	  board at <http://www.mvista.com/allies/semiconductor/ite.html>.
-
-config BLK_DEV_NFORCE
-	tristate "nVidia NFORCE support"
-	depends on BLK_DEV_IDEDMA_PCI
 
 config BLK_DEV_NS87415
 	tristate "NS87415 chipset support"
diff -Nru a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
--- a/drivers/ide/ide-pnp.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/ide/ide-pnp.c	Mon Jan 13 10:18:06 2003
@@ -21,10 +21,7 @@
 
 #include <linux/isapnp.h>
 
-#define DEV_IO(dev, index) (dev->resource[index].start)
-#define DEV_IRQ(dev, index) (dev->irq_resource[index].start)
-
-#define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP")
+#define DEV_NAME(dev) (dev->name)
 
 #define GENERIC_HD_DATA		0
 #define GENERIC_HD_ERROR	1
@@ -44,12 +41,12 @@
 /* ISA PnP device table entry */
 struct pnp_dev_t {
 	unsigned short card_vendor, card_device, vendor, device;
-	int (*init_fn)(struct pci_dev *dev, int enable);
+	int (*init_fn)(struct pnp_dev *dev, int enable);
 };
 
 /* Generic initialisation function for ISA PnP IDE interface */
 
-static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
+static int __init pnpide_generic_init(struct pnp_dev *dev, int enable)
 {
 	hw_regs_t hw;
 	ide_hwif_t *hwif;
@@ -58,21 +55,21 @@
 	if (!enable)
 		return 0;
 
-	if (!(DEV_IO(dev, 0) && DEV_IO(dev, 1) && DEV_IRQ(dev, 0)))
+	if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
 		return 1;
 
-	ide_setup_ports(&hw, (ide_ioreg_t) DEV_IO(dev, 0),
+	ide_setup_ports(&hw, (ide_ioreg_t) pnp_port_start(dev, 0),
 			generic_ide_offsets,
-			(ide_ioreg_t) DEV_IO(dev, 1),
+			(ide_ioreg_t) pnp_port_start(dev, 1),
 			0, NULL,
 //			generic_pnp_ide_iops,
-			DEV_IRQ(dev, 0));
+			pnp_irq(dev, 0));
 
 	index = ide_register_hw(&hw, &hwif);
 
 	if (index != -1) {
 	    	printk(KERN_INFO "ide%d: %s IDE interface\n", index, DEV_NAME(dev));
-		hwif->pci_dev = dev;
+		hwif->pnp_dev = dev;
 		return 0;
 	}
 
@@ -90,7 +87,7 @@
 
 #define NR_PNP_DEVICES 8
 struct pnp_dev_inst {
-	struct pci_dev *dev;
+	struct pnp_dev *dev;
 	struct pnp_dev_t *dev_type;
 };
 static struct pnp_dev_inst devices[NR_PNP_DEVICES];
@@ -102,7 +99,7 @@
 
 void __init pnpide_init(int enable)
 {
-	struct pci_dev *dev = NULL;
+	struct pnp_dev *dev = NULL;
 	struct pnp_dev_t *dev_type;
 
 	if (!isapnp_present())
@@ -114,33 +111,26 @@
 		for (i = 0; i < pnp_ide_dev_idx; i++) {
 			dev = devices[i].dev;
 			devices[i].dev_type->init_fn(dev, 0);
-			if (dev->deactivate)
-				dev->deactivate(dev);
+			pnp_device_detach(dev);
 		}
 		return;
 	}
 
 	for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) {
-		while ((dev = isapnp_find_dev(NULL, dev_type->vendor,
+		while ((dev = pnp_find_dev(NULL, dev_type->vendor,
 			dev_type->device, dev))) {
-
-			if (dev->active)
-				continue;
-
-       			if (dev->prepare && dev->prepare(dev) < 0) {
-				printk(KERN_ERR"ide-pnp: %s prepare failed\n", DEV_NAME(dev));
+			
+			if (pnp_device_attach(dev) < 0)
 				continue;
-			}
-
-			if (dev->activate && dev->activate(dev) < 0) {
+				
+			if (pnp_activate_dev(dev, NULL) < 0) {
 				printk(KERN_ERR"ide: %s activate failed\n", DEV_NAME(dev));
 				continue;
 			}
 
 			/* Call device initialization function */
 			if (dev_type->init_fn(dev, 1)) {
-				if (dev->deactivate(dev))
-					dev->deactivate(dev);
+				pnp_device_detach(dev);
 			} else {
 #ifdef MODULE
 				/*
diff -Nru a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
--- a/drivers/ide/pci/Makefile	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/Makefile	Mon Jan 13 10:18:05 2003
@@ -15,7 +15,6 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IT8172)		+= it8172.o
 obj-$(CONFIG_BLK_DEV_NS87415)		+= ns87415.o
-obj-$(CONFIG_BLK_DEV_NFORCE)		+= nvidia.o
 obj-$(CONFIG_BLK_DEV_OPTI621)		+= opti621.o
 obj-$(CONFIG_BLK_DEV_PDC202XX_OLD)	+= pdc202xx_old.o
 obj-$(CONFIG_BLK_DEV_PDC202XX_NEW)	+= pdc202xx_new.o
@@ -27,6 +26,7 @@
 obj-$(CONFIG_BLK_DEV_SIS5513)		+= sis5513.o
 obj-$(CONFIG_BLK_DEV_SL82C105)		+= sl82c105.o
 obj-$(CONFIG_BLK_DEV_SLC90E66)		+= slc90e66.o
+obj-$(CONFIG_BLK_DEV_TRIFLEX)		+= triflex.o
 obj-$(CONFIG_BLK_DEV_TRM290)		+= trm290.o
 obj-$(CONFIG_BLK_DEV_VIA82CXXX)		+= via82cxxx.o
 
diff -Nru a/drivers/ide/pci/adma100.c b/drivers/ide/pci/adma100.c
--- a/drivers/ide/pci/adma100.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/adma100.c	Mon Jan 13 10:18:05 2003
@@ -18,7 +18,7 @@
 
 void __init ide_init_adma100 (ide_hwif_t *hwif)
 {
-	u32  phy_admctl = pci_resource_start(hwif->pci_dev, 4) + 0x80 + (hwif->channel * 0x20);
+	unsigned long  phy_admctl = pci_resource_start(hwif->pci_dev, 4) + 0x80 + (hwif->channel * 0x20);
 	void *v_admctl;
 
 	hwif->autodma = 0;		// not compatible with normal IDE DMA transfers
diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
--- a/drivers/ide/pci/aec62xx.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/ide/pci/aec62xx.c	Mon Jan 13 10:18:07 2003
@@ -42,7 +42,7 @@
 
 	for (i = 0; i < n_aec_devs; i++) {
 		struct pci_dev *dev	= aec_devs[i];
-		u32 iobase		= pci_resource_start(dev, 4);
+		unsigned long iobase = pci_resource_start(dev, 4);
 		u8 c0 = 0, c1 = 0, art	= 0;
 #ifdef DEBUG_AEC_REGS
 		u8 uart			= 0;
@@ -493,7 +493,7 @@
 
 static void __init init_setup_aec6x80 (struct pci_dev *dev, ide_pci_device_t *d)
 {
-	u32 bar4reg = pci_resource_start(dev, 4);
+	unsigned long bar4reg = pci_resource_start(dev, 4);
 
 	if (inb(bar4reg+2) & 0x10) {
 		strcpy(d->name, "AEC6880");
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/ide/pci/amd74xx.c	Mon Jan 13 10:18:07 2003
@@ -1,390 +1,439 @@
 /*
- * linux/drivers/ide/amd74xx.c		Version 0.05	June 9, 2000
+ * Version 2.9
  *
- * Copyright (C) 1999-2000		Andre Hedrick <andre@linux-ide.org>
- * May be copied or modified under the terms of the GNU General Public License
+ * AMD 755/756/766/8111 and nVidia nForce IDE driver for Linux.
  *
+ * Copyright (c) 2000-2002 Vojtech Pavlik
+ *
+ * Based on the work of:
+ *      Andre Hedrick
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
-#include <linux/interrupt.h>
-#include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 #include <linux/ide.h>
-
 #include <asm/io.h>
-#include <asm/irq.h>
 
-#include "ide_modes.h"
+#include "ide-timing.h"
 #include "amd74xx.h"
 
-#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
+#define AMD_IDE_ENABLE		(0x00 + amd_config->base)
+#define AMD_IDE_CONFIG		(0x01 + amd_config->base)
+#define AMD_CABLE_DETECT	(0x02 + amd_config->base)
+#define AMD_DRIVE_TIMING	(0x08 + amd_config->base)
+#define AMD_8BIT_TIMING		(0x0e + amd_config->base)
+#define AMD_ADDRESS_SETUP	(0x0c + amd_config->base)
+#define AMD_UDMA_TIMING		(0x10 + amd_config->base)
+
+#define AMD_UDMA		0x07
+#define AMD_UDMA_33		0x01
+#define AMD_UDMA_66		0x02
+#define AMD_UDMA_100		0x03
+#define AMD_CHECK_SWDMA		0x08
+#define AMD_BAD_SWDMA		0x10
+#define AMD_BAD_FIFO		0x20
+
+/*
+ * AMD SouthBridge chips.
+ */
+
+static struct amd_ide_chip {
+	unsigned short id;
+	unsigned char rev;
+	unsigned long base;
+	unsigned char flags;
+} amd_ide_chips[] = {
+	{ PCI_DEVICE_ID_AMD_8111_IDE,  0x00, 0x40, AMD_UDMA_100 },			/* AMD-8111 */
+	{ PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, 0x40, AMD_UDMA_100 },			/* AMD-768 Opus */
+	{ PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO },	/* AMD-766 Viper */
+	{ PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },	/* AMD-756 Viper */
+	{ PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },	/* AMD-755 Cobra */
+        { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x00, 0x50, AMD_UDMA_100 },                  /* nVidia nForce */
+
+	{ 0 }
+};
+
+static struct amd_ide_chip *amd_config;
+static unsigned char amd_enabled;
+static unsigned int amd_80w;
+static unsigned int amd_clock;
+
+static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3 };
+static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 1 };
+static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" };
+
+/*
+ * AMD /proc entry.
+ */
+
+#ifdef CONFIG_PROC_FS
+
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
-static u8 amd74xx_proc = 0;
-
+static int amd_base;
 static struct pci_dev *bmide_dev;
+extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
 
-static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count)
-{
+#define amd_print(format, arg...) p += sprintf(p, format "\n" , ## arg)
+#define amd_print_drive(name, format, arg...)\
+	p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n");
+
+static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
+{
+	int speed[4], cycle[4], setup[4], active[4], recover[4], den[4],
+		 uen[4], udma[4], active8b[4], recover8b[4];
+	struct pci_dev *dev = bmide_dev;
+	unsigned int v, u, i;
+	unsigned short c, w;
+	unsigned char t;
 	char *p = buffer;
-	u32 bibma = pci_resource_start(bmide_dev, 4);
-	u8 c0 = 0, c1 = 0;
 
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-	c0 = inb((unsigned short)bibma + 0x02);
-	c1 = inb((unsigned short)bibma + 0x0a);
-
-	p += sprintf(p, "\n                                "
-			"AMD %04X VIPER Chipset.\n", bmide_dev->device);
-	p += sprintf(p, "--------------- Primary Channel "
-			"---------------- Secondary Channel "
-			"-------------\n");
-	p += sprintf(p, "                %sabled "
-			"                        %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
-	p += sprintf(p, "--------------- drive0 --------- drive1 "
-			"-------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s "
-			"            %s               %s\n",
-			(c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
-	p += sprintf(p, "UDMA\n");
-	p += sprintf(p, "DMA\n");
-	p += sprintf(p, "PIO\n");
-
-	return p-buffer;	/* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-static int amd74xx_mode5_check (struct pci_dev *dev)
-{
-	switch(dev->device) {
-		case PCI_DEVICE_ID_AMD_VIPER_7411:
-		case PCI_DEVICE_ID_AMD_VIPER_7441:
-		case PCI_DEVICE_ID_AMD_8111_IDE:
-			return 1;
-		default:
-			return 0;
+	amd_print("----------AMD BusMastering IDE Configuration----------------");
+
+	amd_print("Driver Version:                     2.8");
+	amd_print("South Bridge:                       %s", bmide_dev->dev.name);
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
+	amd_print("Revision:                           IDE %#x", t);
+	amd_print("Highest DMA rate:                   %s", amd_dma[amd_config->flags & AMD_UDMA]);
+
+	amd_print("BM-DMA base:                        %#lx", amd_base);
+	amd_print("PCI clock:                          %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10);
+	
+	amd_print("-----------------------Primary IDE-------Secondary IDE------");
+
+	pci_read_config_byte(dev, AMD_IDE_CONFIG, &t);
+	amd_print("Prefetch Buffer:       %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no");
+	amd_print("Post Write Buffer:     %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
+
+	pci_read_config_byte(dev, AMD_IDE_ENABLE, &t);
+	amd_print("Enabled:               %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no");
+
+	c = inb(amd_base + 0x02) | (inb(amd_base + 0x0a) << 8);
+	amd_print("Simplex only:          %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no");
+
+	amd_print("Cable Type:            %10s%20s", (amd_80w & 1) ? "80w" : "40w", (amd_80w & 2) ? "80w" : "40w");
+
+	if (!amd_clock)
+                return p - buffer;
+
+	amd_print("-------------------drive0----drive1----drive2----drive3-----");
+
+	pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t);
+	pci_read_config_dword(dev, AMD_DRIVE_TIMING, &v);
+	pci_read_config_word(dev, AMD_8BIT_TIMING, &w);
+	pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
+
+	for (i = 0; i < 4; i++) {
+		setup[i]     = ((t >> ((3 - i) << 1)) & 0x3) + 1;
+		recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1;
+		active8b[i]  = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1;
+		active[i]    = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;
+		recover[i]   = ((v >> ((3 - i) << 3)) & 0xf) + 1;
+
+		udma[i] = amd_udma2cyc[((u >> ((3 - i) << 3)) & 0x7)];
+		uen[i]  = ((u >> ((3 - i) << 3)) & 0x40) ? 1 : 0;
+		den[i]  = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2));
+
+		if (den[i] && uen[i] && udma[i] == 1) {
+			speed[i] = amd_clock * 3;
+			cycle[i] = 666666 / amd_clock;
+			continue;
+		}
+
+		speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2);
+		cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2;
 	}
-}
 
-static unsigned int amd74xx_swdma_check (struct pci_dev *dev)
-{
-	unsigned int class_rev;
+	amd_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO");
 
-	if (amd74xx_mode5_check(dev))
-		return 1;
+	amd_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / amd_clock);
+	amd_print_drive("Cmd Active:    ", "%8dns", 1000000 * active8b[i] / amd_clock);
+	amd_print_drive("Cmd Recovery:  ", "%8dns", 1000000 * recover8b[i] / amd_clock);
+	amd_print_drive("Data Active:   ", "%8dns", 1000000 * active[i] / amd_clock);
+	amd_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / amd_clock);
+	amd_print_drive("Cycle Time:    ", "%8dns", cycle[i]);
+	amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10);
 
-	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-	class_rev &= 0xff;
-	return ((int) (class_rev >= 7) ? 1 : 0);
+	return p - buffer;	/* hoping it is less than 4K... */
 }
 
-static u8 amd74xx_ratemask (ide_drive_t *drive)
+#endif
+
+/*
+ * amd_set_speed() writes timing values to the chipset registers
+ */
+
+static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing)
 {
-	u8 mode;
+	unsigned char t;
 
-        switch(HWIF(drive)->pci_dev->device) {
-		case PCI_DEVICE_ID_AMD_8111_IDE:
-		case PCI_DEVICE_ID_AMD_VIPER_7441:
-		case PCI_DEVICE_ID_AMD_VIPER_7411:
-			mode = 3;
-			break;
-		case PCI_DEVICE_ID_AMD_VIPER_7409:
-			mode = 2;
-			break;
-		case PCI_DEVICE_ID_AMD_COBRA_7401:
-			return 1;
-		default:
-			return 0;
-	}
+	pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t);
+	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+	pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t);
 
-	if (!eighty_ninty_three(drive))
-		mode = min(mode, (u8)1);
+	pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)),
+		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
 
-	return mode;
+	pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
+		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
+
+	switch (amd_config->flags & AMD_UDMA) {
+		case AMD_UDMA_33:  t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+		case AMD_UDMA_66:  t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
+		case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+		default: return;
+	}
+
+	pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
 }
 
 /*
- * Here is where all the hard work goes to program the chipset.
+ * amd_set_drive() computes timing values configures the drive and
+ * the chipset to a desired transfer mode. It also can be called
+ * by upper layers.
  */
-static int amd74xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+
+static int amd_set_drive(ide_drive_t *drive, u8 speed)
 {
-	u8 drive_pci[]		= { 0x53, 0x52, 0x51, 0x50 };
-	u8 drive_pci2[]		= { 0x4b, 0x4a, 0x49, 0x48 };
-#if 0
-	u8 ultra_rate[]		= { 0x42, 0x41, 0x40, 0x44, 0x45, 0x46 };
-	u8 mwdma_rate[]		= { 0x77, 0x21, 0x20 };
-	u8 swdma_rate[]		= { 0xA8, 0x65, 0x42 };
-	u8 pio_rate[]		= { 0xA8, 0x65, 0x42, 0x22, 0x20};
-#endif
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
-	u8 speed	= ide_rate_filter(amd74xx_ratemask(drive), xferspeed);
-	u8 ultra_timing	= 0, dma_pio_timing = 0, pio_timing = 0;
-
-	pci_read_config_byte(dev, drive_pci[drive->dn], &ultra_timing);
-	pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_pio_timing);
-	pci_read_config_byte(dev, 0x4c, &pio_timing);
-
-	ultra_timing	&= ~0xC7;
-	dma_pio_timing	&= ~0xFF;
-	pio_timing	&= ~(0x03 << drive->dn);
-
-	switch(speed) {
-		case XFER_UDMA_7:
-		case XFER_UDMA_6:
-			speed = XFER_UDMA_5;
-		case XFER_UDMA_5:
-			ultra_timing |= 0x46;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_4:
-			ultra_timing |= 0x45;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_3:
-			ultra_timing |= 0x44;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_2:
-			ultra_timing |= 0x40;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_1:
-			ultra_timing |= 0x41;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_0:
-			ultra_timing |= 0x42;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_MW_DMA_2:
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_MW_DMA_1:
-			dma_pio_timing |= 0x21;
-			break;
-		case XFER_MW_DMA_0:
-			dma_pio_timing |= 0x77;
-			break;
-		case XFER_SW_DMA_2:
-			dma_pio_timing |= 0x42;
-			break;
-		case XFER_SW_DMA_1:
-			dma_pio_timing |= 0x65;
-			break;
-		case XFER_SW_DMA_0:
-			dma_pio_timing |= 0xA8;
-			break;
-		case XFER_PIO_4:
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_PIO_3:
-			dma_pio_timing |= 0x22;
-			break;
-		case XFER_PIO_2:
-			dma_pio_timing |= 0x42;
-			break;
-		case XFER_PIO_1:
-			dma_pio_timing |= 0x65;
-			break;
-		case XFER_PIO_0:
-		default:
-			dma_pio_timing |= 0xA8;
-			break;
-        }
+	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	struct ide_timing t, p;
+	int T, UT;
+
+	if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
+		if (ide_config_drive_speed(drive, speed))
+			printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n",
+				drive->dn >> 1, drive->dn & 1);
 
-	pio_timing |= (0x03 << drive->dn);
+	T = 1000000000 / amd_clock;
+	UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2);
 
-	pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing);
-	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing);
-	pci_write_config_byte(dev, 0x4c, pio_timing);
+	ide_timing_compute(drive, speed, &t, T, UT);
+
+	if (peer->present) {
+		ide_timing_compute(peer, peer->current_speed, &p, T, UT);
+		ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
+	}
 
-	return (ide_config_drive_speed(drive, speed));
+	if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
+
+	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
+
+	if (!drive->init_speed)	
+		drive->init_speed = speed;
+	drive->current_speed = speed;
+
+	return 0;
 }
 
-static void amd74xx_tune_drive (ide_drive_t *drive, u8 pio)
+/*
+ * amd74xx_tune_drive() is a callback from upper layers for
+ * PIO-only tuning.
+ */
+
+static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
 {
-	pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
-	(void) amd74xx_tune_chipset(drive, (XFER_PIO_0 + pio));
+	if (!((amd_enabled >> HWIF(drive)->channel) & 1))
+		return;
+
+	if (pio == 255) {
+		amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+		return;
+	}
+
+	amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
 }
 
 /*
- * This allows the configuration of ide_pci chipset registers
- * for cards that learn about the drive's UDMA, DMA, PIO capabilities
- * after the drive is reported by the OS.
+ * amd74xx_dmaproc() is a callback from upper layers that can do
+ * a lot, but we use it for DMA/PIO tuning only, delegating everything
+ * else to the default ide_dmaproc().
  */
-static int config_chipset_for_dma (ide_drive_t *drive)
+
+static int amd74xx_ide_dma_check(ide_drive_t *drive)
 {
-	u8 speed = ide_dma_speed(drive, amd74xx_ratemask(drive));
+	int w80 = HWIF(drive)->udma_four;
+
+	u8 speed = ide_find_best_mode(drive,
+		XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
+		((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
+		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
+		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0));
 
-	if (!(speed))
-		return 0;
+	amd_set_drive(drive, speed);
 
-	(void) amd74xx_tune_chipset(drive, speed);
-	return ide_dma_enable(drive);
+	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
+		return HWIF(drive)->ide_dma_on(drive);
+	return HWIF(drive)->ide_dma_off_quietly(drive);
 }
 
-static int amd74xx_config_drive_xfer_rate (ide_drive_t *drive)
+/*
+ * The initialization callback. Here we determine the IDE chip type
+ * and initialize its drive independent registers.
+ */
+
+unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
+	unsigned char t;
+	unsigned int u;
+	int i;
 
-	drive->init_speed = 0;
+/*
+ * Check for bad SWDMA.
+ */
 
-	if (id && (id->capability & 1) && drive->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (hwif->ide_dma_bad_drive(drive))
-			goto fast_ata_pio;
-		if (id->field_valid & 4) {
-			if (id->dma_ultra & hwif->ultra_mask) {
-				/* Force if Capable UltraDMA */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && dma)
-					goto try_dma_modes;
-			}
-		} else if (id->field_valid & 2) {
-try_dma_modes:
-			if ((id->dma_mword & hwif->mwdma_mask) ||
-			    (id->dma_1word & hwif->swdma_mask)) {
-				/* Force if Capable regular DMA modes */
-				if (!config_chipset_for_dma(drive))
-					goto no_dma_set;
-			}
+	if (amd_config->flags & AMD_CHECK_SWDMA) {
+		pci_read_config_byte(dev, PCI_REVISION_ID, &t);
+		if (t <= 7)
+			amd_config->flags |= AMD_BAD_SWDMA;
+	}
 
-		} else if (hwif->ide_dma_good_drive(drive) &&
-			   (id->eide_dma_time < 150)) {
-			/* Consult the list of known "good" drives */
-			if (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
-		}
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-no_dma_set:
-		amd74xx_tune_drive(drive, 5);
-		return hwif->ide_dma_off_quietly(drive);
+/*
+ * Check 80-wire cable presence.
+ */
+
+	switch (amd_config->flags & AMD_UDMA) {
+
+		case AMD_UDMA_100:
+			pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
+			amd_80w = ((u & 0x3) ? 1 : 0) | ((u & 0xc) ? 2 : 0);
+			for (i = 24; i >= 0; i -= 8)
+				if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
+					printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits corectly. Enabling workaround.\n");
+					amd_80w |= (1 << (1 - (i >> 4)));
+				}
+			break;
+
+		case AMD_UDMA_66:
+			pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
+			for (i = 24; i >= 0; i -= 8)
+				if ((u >> i) & 4)
+					amd_80w |= (1 << (1 - (i >> 4)));
+			break;
 	}
-	return hwif->ide_dma_on(drive);
-}
 
-static unsigned int __init init_chipset_amd74xx (struct pci_dev *dev, const char *name)
-{
-	if (!amd74xx_swdma_check(dev))
-		printk("%s: disabling single-word DMA support (revision < C4)\n", name);
+	pci_read_config_dword(dev, AMD_IDE_ENABLE, &u);
+	amd_enabled = ((u & 1) ? 2 : 0) | ((u & 2) ? 1 : 0);
 
-#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!amd74xx_proc) {
-		amd74xx_proc = 1;
-		bmide_dev = dev;
-		ide_pci_register_host_proc(&amd74xx_procs[0]);
+/*
+ * Take care of prefetch & postwrite.
+ */
+
+	pci_read_config_byte(dev, AMD_IDE_CONFIG, &t);
+	pci_write_config_byte(dev, AMD_IDE_CONFIG,
+		(amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0));
+
+/*
+ * Determine the system bus clock.
+ */
+
+	amd_clock = system_bus_clock() * 1000;
+
+	switch (amd_clock) {
+		case 33000: amd_clock = 33333; break;
+		case 37000: amd_clock = 37500; break;
+		case 41000: amd_clock = 41666; break;
+	}
+
+	if (amd_clock < 20000 || amd_clock > 50000) {
+		printk(KERN_WARNING "AMD_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", amd_clock);
+		printk(KERN_WARNING "AMD_IDE: Use ide0=ata66 if you want to assume 80-wire cable\n");
+		amd_clock = 33333;
 	}
-#endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */
+
+/*
+ * Print the boot message.
+ */
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
+	printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n",
+		dev->dev.name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name);
+
+/*
+ * Register /proc/ide/amd74xx entry
+ */
+
+#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS)
+        if (!amd74xx_proc) {
+                amd_base = pci_resource_start(dev, 4);
+                bmide_dev = dev;
+                ide_pci_register_host_proc(&amd74xx_procs[0]);
+                amd74xx_proc = 1;
+        }
+#endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */
+
 
 	return 0;
 }
 
-static unsigned int __init ata66_amd74xx (ide_hwif_t *hwif)
+unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev	= hwif->pci_dev;
-	u8 cable_80_pin[2]	= { 0, 0 };
-	u8 ata66		= 0;
-	u8 tmpbyte;
-
-	/*
-	 * Ultra66 cable detection (from Host View)
-	 * 7411, 7441, 0x42, bit0: primary, bit2: secondary 80 pin
-	 */
-	pci_read_config_byte(dev, 0x42, &tmpbyte);
-
-	/*
-	 * 0x42, bit0 is 1 => primary channel
-	 * has 80-pin (from host view)
-	 */
-	if (tmpbyte & 0x01) cable_80_pin[0] = 1;
-
-	/*
-	 * 0x42, bit2 is 1 => secondary channel
-	 * has 80-pin (from host view)
-	 */
-	if (tmpbyte & 0x04) cable_80_pin[1] = 1;
-
-	switch(dev->device) {
-		case PCI_DEVICE_ID_AMD_COBRA_7401:
-			cable_80_pin[hwif->channel] = 0;
-			return 0;
-		case PCI_DEVICE_ID_AMD_8111_IDE:
-		case PCI_DEVICE_ID_AMD_VIPER_7441:
-		case PCI_DEVICE_ID_AMD_VIPER_7411:
-			ata66 = (hwif->channel) ?
-				cable_80_pin[1] :
-				cable_80_pin[0];
-		default:
-			break;
-	}
-	return (unsigned int) ata66;
+	return ((amd_enabled & amd_80w) >> hwif->channel) & 1;
 }
 
-static void __init init_hwif_amd74xx (ide_hwif_t *hwif)
+void __init init_hwif_amd74xx(ide_hwif_t *hwif)
 {
+	int i;
+
 	hwif->autodma = 0;
+
 	hwif->tuneproc = &amd74xx_tune_drive;
-	hwif->speedproc = &amd74xx_tune_chipset;
+	hwif->speedproc = &amd_set_drive;
 
-	if (!hwif->dma_base) {
-		hwif->drives[0].autotune = 1;
-		hwif->drives[1].autotune = 1;
-		return;
+	for (i = 0; i < 2; i++) {
+		hwif->drives[i].io_32bit = 1;
+		hwif->drives[i].unmask = 1;
+		hwif->drives[i].autotune = 1;
+		hwif->drives[i].dn = hwif->channel * 2 + i;
 	}
 
-	hwif->atapi_dma = 1;
-	hwif->ultra_mask = 0x3f;
-	hwif->mwdma_mask = 0x07;
-	if (amd74xx_swdma_check(hwif->pci_dev))
-		hwif->swdma_mask = 0x07;
-
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_amd74xx(hwif);
-	hwif->ide_dma_check = &amd74xx_config_drive_xfer_rate;
-	if (!noautodma)
-		hwif->autodma = 1;
-	hwif->drives[0].autodma = hwif->autodma;
-	hwif->drives[1].autodma = hwif->autodma;
-}
-
-static void __init init_dma_amd74xx (ide_hwif_t *hwif, unsigned long dmabase)
-{
-	if (!(hwif->channel))
-		hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2);
-	ide_setup_dma(hwif, dmabase, 8);
+	if (!hwif->dma_base)
+		return;
+
+        hwif->atapi_dma = 1;
+        hwif->ultra_mask = 0x7f;
+        hwif->mwdma_mask = 0x07;
+        hwif->swdma_mask = 0x07;
+
+        if (!(hwif->udma_four))
+                hwif->udma_four = ((amd_enabled & amd_80w) >> hwif->channel) & 1;
+        hwif->ide_dma_check = &amd74xx_ide_dma_check;
+        if (!noautodma)
+                hwif->autodma = 1;
+        hwif->drives[0].autodma = hwif->autodma;
+        hwif->drives[1].autodma = hwif->autodma;
 }
 
-extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+/*
+ * We allow the BM-DMA driver only work on enabled interfaces.
+ */
 
+static void __init init_dma_amd74xx(ide_hwif_t *hwif, unsigned long dmabase)
+{
+	if ((amd_enabled >> hwif->channel) & 1)
+		ide_setup_dma(hwif, dmabase, 8);
+}
+
+extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
 
-static int __devinit amd74xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	ide_pci_device_t *d = &amd74xx_chipsets[id->driver_data];
-	if (dev->device != d->device)
-		BUG();
+	ide_pci_device_t *d = amd74xx_chipsets + id->driver_data;
+	amd_config = amd_ide_chips + id->driver_data;
+	if (dev->device != d->device) BUG();
+	if (dev->device != amd_config->id) BUG();
 	ide_setup_pci_device(dev, d);
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -396,13 +445,14 @@
 	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
 	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
 	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, 	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
 	{ 0, },
 };
 
 static struct pci_driver driver = {
 	.name		= "AMD IDE",
 	.id_table	= amd74xx_pci_tbl,
-	.probe		= amd74xx_init_one,
+	.probe		= amd74xx_probe,
 };
 
 static int amd74xx_ide_init(void)
@@ -418,8 +468,8 @@
 module_init(amd74xx_ide_init);
 module_exit(amd74xx_ide_exit);
 
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for AMD IDE");
+MODULE_AUTHOR("Vojtech Pavlik");
+MODULE_DESCRIPTION("AMD PCI IDE driver");
 MODULE_LICENSE("GPL");
 
 EXPORT_NO_SYMBOLS;
diff -Nru a/drivers/ide/pci/amd74xx.h b/drivers/ide/pci/amd74xx.h
--- a/drivers/ide/pci/amd74xx.h	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/amd74xx.h	Mon Jan 13 10:18:05 2003
@@ -5,9 +5,9 @@
 #include <linux/pci.h>
 #include <linux/ide.h>
 
-#define DISPLAY_VIPER_TIMINGS
+#define DISPLAY_AMD_TIMINGS
 
-#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
+#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS)
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
@@ -23,7 +23,7 @@
 		.parent		= NULL,
 	},
 };
-#endif  /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */
+#endif  /* defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) */
 
 static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *);
 static void init_hwif_amd74xx(ide_hwif_t *);
@@ -95,7 +95,22 @@
 		.enablebits	= {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
 		.bootable	= ON_BOARD,
 		.extra		= 0
-	},{
+	},
+	{	/* 5 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,
+		.name		= "NFORCE",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_amd74xx,
+		.init_dma	= init_dma_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x01,0x01}, {0x50,0x02,0x02}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
+	},
+	{
 		.vendor		= 0,
 		.device		= 0,
 		.channels	= 0,
diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
--- a/drivers/ide/pci/cs5520.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/cs5520.c	Mon Jan 13 10:18:05 2003
@@ -73,8 +73,8 @@
 	 * at that point bibma+0x2 et bibma+0xa are byte registers
 	 * to investigate:
 	 */
-	c0 = inb((unsigned short)bmiba + 0x02);
-	c1 = inb((unsigned short)bmiba + 0x0a);
+	c0 = inb(bmiba + 0x02);
+	c1 = inb(bmiba + 0x0a);
 	
 	p += sprintf(p, "\nCyrix CS55x0 IDE\n");
 	p += sprintf(p, "--------------- Primary Channel "
@@ -203,7 +203,7 @@
 
 static void __devinit cs5520_init_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif)
 {
-	u32 bmide = pci_resource_start(dev, 2);	/* Not the usual 4 */
+	unsigned long bmide = pci_resource_start(dev, 2);	/* Not the usual 4 */
 	if(hwif->mate && hwif->mate->dma_base)	/* Second channel at primary + 8 */
 		bmide += 8;
 	ide_setup_dma(hwif, bmide, 8);
diff -Nru a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
--- a/drivers/ide/pci/cs5530.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/cs5530.c	Mon Jan 13 10:18:05 2003
@@ -42,7 +42,7 @@
 static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	u32 bibma = pci_resource_start(bmide_dev, 4);
+	unsigned long bibma = pci_resource_start(bmide_dev, 4);
 	u8  c0 = 0, c1 = 0;
 
 	/*
@@ -124,7 +124,8 @@
 static void cs5530_tuneproc (ide_drive_t *drive, u8 pio)	/* pio=255 means "autotune" */
 {
 	ide_hwif_t	*hwif = HWIF(drive);
-	unsigned int	format, basereg = CS5530_BASEREG(hwif);
+	unsigned int	format;
+	unsigned long basereg = CS5530_BASEREG(hwif);
 	static u8	modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
 
 	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
@@ -151,7 +152,8 @@
 	int			unit = drive->select.b.unit;
 	ide_drive_t		*mate = &hwif->drives[unit^1];
 	struct hd_driveid	*id = drive->id;
-	unsigned int		basereg, reg, timings;
+	unsigned int		reg, timings;
+	unsigned long		basereg;
 
 	/*
 	 * Default to DMA-off in case we run into trouble here.
@@ -365,7 +367,8 @@
 
 static void __init init_hwif_cs5530 (ide_hwif_t *hwif)
 {
-	unsigned int basereg, d0_timings;
+	unsigned long basereg;
+	u32 d0_timings;
 	hwif->autodma = 0;
 
 	if (hwif->mate)
diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
--- a/drivers/ide/pci/hpt34x.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/hpt34x.c	Mon Jan 13 10:18:05 2003
@@ -64,7 +64,7 @@
 			"HPT34X Chipset.\n");
 	for (i = 0; i < n_hpt34x_devs; i++) {
 		struct pci_dev *dev = hpt34x_devs[i];
-		u32 bibma = pci_resource_start(dev, 4);
+		unsigned long bibma = pci_resource_start(dev, 4);
 		u8  c0 = 0, c1 = 0;
 
 		/*
diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
--- a/drivers/ide/pci/hpt366.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/ide/pci/hpt366.c	Mon Jan 13 10:18:06 2003
@@ -659,7 +659,7 @@
 static void hpt3xx_reset (ide_drive_t *drive)
 {
 #if 0
-	u32 high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
+	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
 	u8 reset	= (HWIF(drive)->channel) ? 0x80 : 0x40;
 	u8 reg59h	= 0;
 
@@ -818,7 +818,10 @@
 	} else {
 		pll = F_LOW_PCI_66;
 		if (hpt_minimum_revision(dev,8))
+		{
+			printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
 			return -EOPNOTSUPP;
+		}
 		else if (hpt_minimum_revision(dev,5))
 			pci_set_drvdata(dev, (void *) sixty_six_base_hpt372);
 		else if (hpt_minimum_revision(dev,4))
diff -Nru a/drivers/ide/pci/nvidia.c b/drivers/ide/pci/nvidia.c
--- a/drivers/ide/pci/nvidia.c	Mon Jan 13 10:18:07 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,370 +0,0 @@
-/*
- * linux/drivers/ide/nvidia.c		Version 0.01
- *
- * Copyright (C) 2002-2002		Andre Hedrick <andre@linux-ide.org>
- * May be copied or modified under the terms of the GNU General Public License
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "ide_modes.h"
-#include "nvidia.h"
-
-#if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 nforce_proc = 0;
-static struct pci_dev *bmide_dev;
-
-static int nforce_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	unsigned long bibma = pci_resource_start(bmide_dev, 4);
-	u8 c0 = 0, c1 = 0;
-
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-	c0 = inb((unsigned short)bibma + 0x02);
-	c1 = inb((unsigned short)bibma + 0x0a);
-
-	p += sprintf(p, "\n                                "
-			"nVidia %04X Chipset.\n", bmide_dev->device);
-	p += sprintf(p, "--------------- Primary Channel "
-			"---------------- Secondary Channel "
-			"-------------\n");
-	p += sprintf(p, "                %sabled "
-			"                        %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
-	p += sprintf(p, "--------------- drive0 --------- drive1 "
-			"-------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s "
-			"            %s               %s\n",
-			(c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
-	p += sprintf(p, "UDMA\n");
-	p += sprintf(p, "DMA\n");
-	p += sprintf(p, "PIO\n");
-
-	return p-buffer;	/* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-static u8 nforce_ratemask (ide_drive_t *drive)
-{
-	u8 mode;
-
-        switch(HWIF(drive)->pci_dev->device) {
-		case PCI_DEVICE_ID_NVIDIA_NFORCE_IDE:
-			mode = 3;
-			break;
-		default:
-			return 0;
-	}
-	if (!eighty_ninty_three(drive))
-		mode = min(mode, (u8)1);
-	return mode;
-}
-
-/*
- * Here is where all the hard work goes to program the chipset.
- */
-static int nforce_tune_chipset (ide_drive_t *drive, u8 xferspeed)
-{
-	static const u8 drive_pci[] = { 0x63, 0x62, 0x61, 0x60 };
-	static const u8 drive_pci2[] = { 0x5b, 0x5a, 0x59, 0x58 };
-
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
-	u8 speed	= ide_rate_filter(nforce_ratemask(drive), xferspeed);
-	u8 ultra_timing	= 0, dma_pio_timing = 0, pio_timing = 0;
-
-	pci_read_config_byte(dev, drive_pci[drive->dn], &ultra_timing);
-	pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_pio_timing);
-	pci_read_config_byte(dev, 0x5c, &pio_timing);
-
-	ultra_timing	&= ~0xC7;
-	dma_pio_timing	&= ~0xFF;
-	pio_timing	&= ~(0x03 << drive->dn);
-
-	switch(speed) {
-		case XFER_UDMA_7:
-		case XFER_UDMA_6:
-			speed = XFER_UDMA_5;
-		case XFER_UDMA_5:
-			ultra_timing |= 0x46;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_4:
-			ultra_timing |= 0x45;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_3:
-			ultra_timing |= 0x44;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_2:
-			ultra_timing |= 0x40;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_1:
-			ultra_timing |= 0x41;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_UDMA_0:
-			ultra_timing |= 0x42;
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_MW_DMA_2:
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_MW_DMA_1:
-			dma_pio_timing |= 0x21;
-			break;
-		case XFER_MW_DMA_0:
-			dma_pio_timing |= 0x77;
-			break;
-		case XFER_SW_DMA_2:
-			dma_pio_timing |= 0x42;
-			break;
-		case XFER_SW_DMA_1:
-			dma_pio_timing |= 0x65;
-			break;
-		case XFER_SW_DMA_0:
-			dma_pio_timing |= 0xA8;
-			break;
-		case XFER_PIO_4:
-			dma_pio_timing |= 0x20;
-			break;
-		case XFER_PIO_3:
-			dma_pio_timing |= 0x22;
-			break;
-		case XFER_PIO_2:
-			dma_pio_timing |= 0x42;
-			break;
-		case XFER_PIO_1:
-			dma_pio_timing |= 0x65;
-			break;
-		case XFER_PIO_0:
-		default:
-			dma_pio_timing |= 0xA8;
-			break;
-        }
-
-	pio_timing |= (0x03 << drive->dn);
-
-	pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing);
-	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing);
-	pci_write_config_byte(dev, 0x5c, pio_timing);
-
-	return (ide_config_drive_speed(drive, speed));
-}
-
-static void nforce_tune_drive (ide_drive_t *drive, u8 pio)
-{
-	pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
-	(void) nforce_tune_chipset(drive, (XFER_PIO_0 + pio));
-}
-
-/*
- * This allows the configuration of ide_pci chipset registers
- * for cards that learn about the drive's UDMA, DMA, PIO capabilities
- * after the drive is reported by the OS.
- */
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
-	u8 speed = ide_dma_speed(drive, nforce_ratemask(drive));
-
-	if (!(speed))
-		return 0;
-
-	(void) nforce_tune_chipset(drive, speed);
-	return ide_dma_enable(drive);
-}
-
-static int nforce_config_drive_xfer_rate (ide_drive_t *drive)
-{
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
-	drive->init_speed = 0;
-
-	if (id && (id->capability & 1) && drive->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (hwif->ide_dma_bad_drive(drive))
-			goto fast_ata_pio;
-		if (id->field_valid & 4) {
-			if (id->dma_ultra & hwif->ultra_mask) {
-				/* Force if Capable UltraDMA */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					goto try_dma_modes;
-			}
-		} else if (id->field_valid & 2) {
-try_dma_modes:
-			if ((id->dma_mword & hwif->mwdma_mask) ||
-			    (id->dma_1word & hwif->swdma_mask)) {
-				/* Force if Capable regular DMA modes */
-				if (!config_chipset_for_dma(drive))
-					goto no_dma_set;
-			}
-
-		} else if (hwif->ide_dma_good_drive(drive) &&
-			   (id->eide_dma_time < 150)) {
-			/* Consult the list of known "good" drives */
-			if (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
-		}
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-no_dma_set:
-		nforce_tune_drive(drive, 5);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	return hwif->ide_dma_on(drive);
-}
-
-static unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name)
-{
-#if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!nforce_proc) {
-		nforce_proc = 1;
-		bmide_dev = dev;
-		ide_pci_register_host_proc(&nforce_procs[0]);
-	}
-#endif /* DISPLAY_NFORCE_TIMINGS && CONFIG_PROC_FS */
-	return 0;
-}
-
-static unsigned int __init ata66_nforce (ide_hwif_t *hwif)
-{
-	struct pci_dev *dev	= hwif->pci_dev;
-	u8 cable_80_pin[2]	= { 0, 0 };
-	u8 ata66		= 0;
-	u8 tmpbyte;
-
-	/*
-	 * Ultra66 cable detection (from Host View)
-	 * 7411, 7441, 0x52, bit0: primary, bit2: secondary 80 pin
-	 */
-	pci_read_config_byte(dev, 0x52, &tmpbyte);
-
-	/*
-	 * 0x52, bit0 is 1 => primary channel
-	 * has 80-pin (from host view)
-	 */
-	if (tmpbyte & 0x01) cable_80_pin[0] = 1;
-
-	/*
-	 * 0x52, bit2 is 1 => secondary channel
-	 * has 80-pin (from host view)
-	 */
-	if (tmpbyte & 0x04) cable_80_pin[1] = 1;
-
-	switch(dev->device) {
-		case PCI_DEVICE_ID_NVIDIA_NFORCE_IDE:
-			ata66 = (hwif->channel) ?
-				cable_80_pin[1] :
-				cable_80_pin[0];
-		default:
-			break;
-	}
-	return (unsigned int) ata66;
-}
-
-static void __init init_hwif_nforce (ide_hwif_t *hwif)
-{
-	hwif->tuneproc = &nforce_tune_drive;
-	hwif->speedproc = &nforce_tune_chipset;
-	hwif->autodma = 0;
-
-	if (!hwif->dma_base) {
-		hwif->drives[0].autotune = 1;
-		hwif->drives[1].autotune = 1;
-		return;
-	}
-
-	hwif->atapi_dma = 1;
-	hwif->ultra_mask = 0x3f;
-	hwif->mwdma_mask = 0x07;
-	hwif->swdma_mask = 0x07;
-
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_nforce(hwif);
-	hwif->ide_dma_check = &nforce_config_drive_xfer_rate;
-	if (!noautodma)
-		hwif->autodma = 1;
-	hwif->drives[0].autodma = hwif->autodma;
-	hwif->drives[1].autodma = hwif->autodma;
-}
-
-/* FIXME - not needed */
-static void __init init_dma_nforce (ide_hwif_t *hwif, unsigned long dmabase)
-{
-	ide_setup_dma(hwif, dmabase, 8);
-}
-
-extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
-
-static int __devinit nforce_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	ide_pci_device_t *d = &nvidia_chipsets[id->driver_data];
-	if (dev->device != d->device)
-		BUG();
-	ide_setup_pci_device(dev, d);
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static struct pci_device_id nforce_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ 0, },
-};
-
-static struct pci_driver driver = {
-	.name		= "nForce IDE",
-	.id_table	= nforce_pci_tbl,
-	.probe		= nforce_init_one,
-};
-
-static int nforce_ide_init(void)
-{
-	return ide_pci_register_driver(&driver);
-}
-
-static void nforce_ide_exit(void)
-{
-	ide_pci_unregister_driver(&driver);
-}
-
-module_init(nforce_ide_init);
-module_exit(nforce_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for nVidia nForce IDE");
-MODULE_LICENSE("GPL");
-
-EXPORT_NO_SYMBOLS;
diff -Nru a/drivers/ide/pci/nvidia.h b/drivers/ide/pci/nvidia.h
--- a/drivers/ide/pci/nvidia.h	Mon Jan 13 10:18:06 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,50 +0,0 @@
-#ifndef NFORCE_H
-#define NFORCE_H
-
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#define DISPLAY_NFORCE_TIMINGS
-
-#if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 nforce_proc;
-
-static int nforce_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t nforce_procs[] __initdata = {
-	{
-		.name		= "nforce",
-		.set		= 1,
-		.get_info	= nforce_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-static unsigned int init_chipset_nforce(struct pci_dev *, const char *);
-static void init_hwif_nforce(ide_hwif_t *);
-static void init_dma_nforce(ide_hwif_t *, unsigned long);
-
-static ide_pci_device_t nvidia_chipsets[] __devinitdata = {
-	{
-		.vendor		= PCI_VENDOR_ID_NVIDIA,
-		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,
-		.name		= "NFORCE",
-		.init_chipset	= init_chipset_nforce,
-		.init_iops	= NULL,
-		.init_hwif	= init_hwif_nforce,
-		.init_dma	= init_dma_nforce,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.enablebits	= {{0x50,0x01,0x01}, {0x50,0x02,0x02}},
-		.bootable	= ON_BOARD,
-		.extra		= 0,
-	}
-};
-
-
-#endif /* NFORCE_H */
diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
--- a/drivers/ide/pci/pdc202xx_new.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/ide/pci/pdc202xx_new.c	Mon Jan 13 10:18:07 2003
@@ -237,11 +237,11 @@
 static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	u32 indexreg		= hwif->dma_vendor1;
-	u32 datareg		= hwif->dma_vendor3;
+	unsigned long indexreg	= hwif->dma_vendor1;
+	unsigned long datareg	= hwif->dma_vendor3;
 	u8 thold		= 0x10;
 	u8 adj			= (drive->dn%2) ? 0x08 : 0x00;
-	u8 speed	= ide_rate_filter(pdcnew_ratemask(drive), xferspeed);
+	u8 speed		= ide_rate_filter(pdcnew_ratemask(drive), xferspeed);
 
 	if (speed == XFER_UDMA_2) {
 		hwif->OUTB((thold + adj), indexreg);
diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
--- a/drivers/ide/pci/pdc202xx_old.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/ide/pci/pdc202xx_old.c	Mon Jan 13 10:18:07 2003
@@ -64,7 +64,7 @@
 {
 	char *p = buf;
 
-	u32 bibma  = pci_resource_start(dev, 4);
+	unsigned long bibma  = pci_resource_start(dev, 4);
 	u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
 	u16 reg50h = 0, pmask = (1<<10), smask = (1<<11);
 	u8 hi = 0, lo = 0;
@@ -535,9 +535,9 @@
 		struct request *rq	= HWGROUP(drive)->rq;
 		ide_hwif_t *hwif	= HWIF(drive);
 //		struct pci_dev *dev	= hwif->pci_dev;
-//		u32 high_16	= pci_resource_start(dev, 4);
-		u32 high_16	= hwif->dma_master;
-		u32 atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
+//		unsgned long high_16	= pci_resource_start(dev, 4);
+		unsigned long high_16   = hwif->dma_master;
+		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
 		u32 word_count	= 0;
 		u8 clock = hwif->INB(high_16 + 0x11);
 
@@ -555,10 +555,10 @@
 {
 	if (drive->addressing == 1) {
 		ide_hwif_t *hwif	= HWIF(drive);
-//		u32 high_16	= pci_resource_start(hwif->pci_dev, 4);
-		u32 high_16	= hwif->dma_master;
-		u32 atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
-		u8 clock	= 0;
+//		unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
+		unsigned long high_16	= hwif->dma_master;
+		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
+		u8 clock		= 0;
 
 		hwif->OUTL(0, atapi_reg); /* zero out extra */
 		clock = hwif->INB(high_16 + 0x11);
@@ -572,7 +572,7 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 //	struct pci_dev *dev	= hwif->pci_dev;
 //	unsigned long high_16	= pci_resource_start(dev, 4);
-	u32 high_16		= hwif->dma_master;
+	unsigned long high_16	= hwif->dma_master;
 	u8 dma_stat		= hwif->INB(hwif->dma_status);
 	u8 sc1d			= hwif->INB((high_16 + 0x001d));
 
diff -Nru a/drivers/ide/pci/pdcadma.c b/drivers/ide/pci/pdcadma.c
--- a/drivers/ide/pci/pdcadma.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/ide/pci/pdcadma.c	Mon Jan 13 10:18:07 2003
@@ -43,7 +43,7 @@
 
 	for (i = 0; i < n_pdc_devs; i++) {
 		struct pci_dev *dev	= pdc_devs[i];
-		u32 bibma = pci_resource_start(dev, 4);
+		unsigned long bibma = pci_resource_start(dev, 4);
 
 		p += sprintf(p, "\n                                "
 			"PDC ADMA %04X Chipset.\n", dev->device);
diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
--- a/drivers/ide/pci/piix.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/piix.c	Mon Jan 13 10:18:05 2003
@@ -1,8 +1,10 @@
 /*
- *  linux/drivers/ide/piix.c		Version 0.40	August 18, 2002
+ *  linux/drivers/ide/piix.c		Version 0.42	January 11, 2003
  *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ *
  *  May be copied or modified under the terms of the GNU General Public License
  *
  *  PIO mode setting function for Intel chipsets.  
@@ -51,6 +53,41 @@
  * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
  * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, &reg54);
  *
+ * Documentation
+ *	Publically available from Intel web site. Errata documentation
+ * is also publically available. As an aide to anyone hacking on this
+ * driver the list of errata that are relevant is below.going back to
+ * PIIX4. Older device documentation is now a bit tricky to find.
+ *
+ * Errata of note:
+ *
+ * Unfixable
+ *	PIIX4    errata #9	- Only on ultra obscure hw
+ *	ICH3	 errata #13     - Not observed to affect real hw
+ *				  by Intel
+ *
+ * Things we must deal with
+ *	PIIX4	errata #10	- BM IDE hang with non UDMA
+ *				  (must stop/start dma to recover)
+ *	440MX   errata #15	- As PIIX4 errata #10
+ *	PIIX4	errata #15	- Must not read control registers
+ * 				  during a PIO transfer
+ *	440MX   errata #13	- As PIIX4 errata #15
+ *	ICH2	errata #21	- DMA mode 0 doesn't work right
+ *	ICH0/1  errata #55	- As ICH2 errata #21
+ *	ICH2	spec c #9	- Extra operations needed to handle
+ *				  drive hotswap [NOT YET SUPPORTED]
+ *	ICH2    spec c #20	- IDE PRD must not cross a 64K boundary
+ *				  and must be dword aligned
+ *	ICH2    spec c #24	- UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ *
+ * Should have been BIOS fixed:
+ *	450NX:	errata #19	- DMA hangs on old 450NX
+ *	450NX:  errata #20	- DMA hangs on old 450NX
+ *	450NX:  errata #25	- Corruption with DMA on old 450NX
+ *	ICH3    errata #15      - IDE deadlock under high load
+ *				  (BIOS must set dev 31 fn 0 bit 23)
+ *	ICH3	errata #18	- Don't use native mode
  */
 
 #include <linux/config.h>
@@ -77,6 +114,7 @@
 #define PIIX_MAX_DEVS		5
 static struct pci_dev *piix_devs[PIIX_MAX_DEVS];
 static int n_piix_devs;
+static int no_piix_dma = 0;
 
 /**
  *	piix_get_info		-	fill in /proc for PIIX ide
@@ -96,7 +134,7 @@
 
 	for (i = 0; i < n_piix_devs; i++) {
 		struct pci_dev *dev	= piix_devs[i];
-		u32 bibma = pci_resource_start(dev, 4);
+		unsigned long bibma = pci_resource_start(dev, 4);
 	        u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
 		u8  c0 = 0, c1 = 0, reg54 = 0, reg55 = 0;
 		u8  reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
@@ -155,8 +193,8 @@
 		 * at that point bibma+0x2 et bibma+0xa are byte registers
 		 * to investigate:
 		 */
-		c0 = inb((unsigned short)bibma + 0x02);
-		c1 = inb((unsigned short)bibma + 0x0a);
+		c0 = inb(bibma + 0x02);
+		c1 = inb(bibma + 0x0a);
 
 		p += sprintf(p, "--------------- Primary Channel "
 				"---------------- Secondary Channel "
@@ -443,6 +481,33 @@
 }
 
 /**
+ *	piix_faulty_dma0		-	check for DMA0 errata
+ *	@hwif: IDE interface to check
+ *
+ *	If an ICH/ICH0/ICH2 interface is is operating in multi-word
+ *	DMA mode with 600nS cycle time the IDE PIO prefetch buffer will
+ *	inadvertently provide an extra piece of secondary data to the primary
+ *	device resulting in data corruption.
+ *
+ *	With such a device this test function returns true. This allows
+ *	our tuning code to follow Intel recommendations and use PIO on
+ *	such devices.
+ */
+ 
+static int piix_faulty_dma0(ide_hwif_t *hwif)
+{
+	switch(hwif->pci_dev->device)
+	{
+		case PCI_DEVICE_ID_INTEL_82801AA_1:	/* ICH */
+		case PCI_DEVICE_ID_INTEL_82801AB_1:	/* ICH0 */
+		case PCI_DEVICE_ID_INTEL_82801BA_8:	/* ICH2 */
+		case PCI_DEVICE_ID_INTEL_82801BA_9:	/* ICH2 */
+			return 1;
+	}
+	return 0;
+}
+
+/**
  *	piix_config_drive_for_dma	-	configure drive for DMA
  *	@drive: IDE drive to configure
  *
@@ -454,8 +519,15 @@
 static int piix_config_drive_for_dma (ide_drive_t *drive)
 {
 	u8 speed = ide_dma_speed(drive, piix_ratemask(drive));
-
-	if (!(speed)) {
+	
+	/* Some ICH devices cannot support DMA mode 0 */
+	if(speed == XFER_MW_DMA_0 && piix_faulty_dma0(HWIF(drive)))
+		speed = 0;
+
+	/* If no DMA speed was available or the chipset has DMA bugs
+	   then disable DMA and use PIO */
+	   
+	if (!speed || no_piix_dma) {
 		u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
 		speed = piix_dma_2_pio(XFER_PIO_0 + tspeed);
 	}
@@ -675,6 +747,37 @@
 	return 0;
 }
 
+/**
+ *	piix_check_450nx	-	Check for problem 450NX setup
+ *	
+ *	Check for the present of 450NX errata #19 and errata #25. If
+ *	they are found, disable use of DMA IDE
+ */
+ 
+static void __init piix_check_450nx(void)
+{
+	struct pci_dev *pdev = NULL;
+	u16 cfg;
+	u8 rev;
+	while((pdev=pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
+	{
+		/* Look for 450NX PXB. Check for problem configurations
+		   A PCI quirk checks bit 6 already */
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+		pci_read_config_word(pdev, 0x41, &cfg);
+		/* Only on the original revision: IDE DMA can hang */
+		if(rev == 0x00)
+			no_piix_dma = 1;
+		/* On all revisions PXB bus lock must be disabled for IDE */
+		else if(cfg & (1<<14))
+			no_piix_dma = 2;
+	}
+	if(no_piix_dma)
+		printk(KERN_WARNING "piix: 450NX errata present, disabling IDE DMA.\n");
+	if(no_piix_dma == 2)
+		printk(KERN_WARNING "piix: A BIOS update may resolve this.\n");
+}		
+
 static struct pci_device_id piix_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
@@ -703,6 +806,7 @@
 
 static int piix_ide_init(void)
 {
+	piix_check_450nx();
 	return ide_pci_register_driver(&driver);
 }
 
diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
--- a/drivers/ide/pci/sc1200.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/ide/pci/sc1200.c	Mon Jan 13 10:18:06 2003
@@ -83,7 +83,7 @@
 static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	u32 bibma = pci_resource_start(bmide_dev, 4);
+	unsigned long bibma = pci_resource_start(bmide_dev, 4);
 	u8  c0 = 0, c1 = 0;
 
 	/*
@@ -91,8 +91,8 @@
 	 * to investigate:
 	 */
 
-	c0 = inb_p((unsigned short)bibma + 0x02);
-	c1 = inb_p((unsigned short)bibma + 0x0a);
+	c0 = inb_p(bibma + 0x02);
+	c1 = inb_p(bibma + 0x0a);
 
 	p += sprintf(p, "\n                               National SCx200 Chipset.\n");
 	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
--- a/drivers/ide/pci/serverworks.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/pci/serverworks.c	Mon Jan 13 10:18:05 2003
@@ -61,7 +61,7 @@
 
 	for (i = 0; i < n_svwks_devs; i++) {
 		struct pci_dev *dev = svwks_devs[i];
-		u32 bibma = pci_resource_start(dev, 4);
+		unsigned long bibma = pci_resource_start(dev, 4);
 		u32 reg40, reg44;
 		u16 reg48, reg56;
 		u8  reg54, c0=0, c1=0;
@@ -76,8 +76,8 @@
 		 * at that point bibma+0x2 et bibma+0xa are byte registers
 		 * to investigate:
 		 */
-		c0 = inb_p((unsigned short)bibma + 0x02);
-		c1 = inb_p((unsigned short)bibma + 0x0a);
+		c0 = inb_p(bibma + 0x02);
+		c1 = inb_p(bibma + 0x0a);
 
 		p += sprintf(p, "\n                            ServerWorks ");
 		switch(dev->device) {
diff -Nru a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
--- a/drivers/ide/pci/slc90e66.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/ide/pci/slc90e66.c	Mon Jan 13 10:18:07 2003
@@ -34,7 +34,7 @@
 static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	u32 bibma = pci_resource_start(bmide_dev, 4);
+	unsigned long bibma = pci_resource_start(bmide_dev, 4);
         u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
 	u8  c0 = 0, c1 = 0;
 	u8  reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
diff -Nru a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/pci/triflex.c	Mon Jan 13 10:18:07 2003
@@ -0,0 +1,252 @@
+/*
+ * triflex.c
+ * 
+ * IDE Chipset driver for the Compaq TriFlex IDE controller.
+ * 
+ * Known to work with the Compaq Workstation 5x00 series.
+ *
+ * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
+ * Author: Torben Mathiasen <torben.mathiasen@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * 
+ * Loosely based on the piix & svwks drivers.
+ *
+ * Documentation:
+ *	Not publically available.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include "ide_modes.h"
+#include "triflex.h"
+
+static struct pci_dev *triflex_dev;
+
+static int triflex_get_info(char *buf, char **addr, off_t offset, int count)
+{
+	char *p = buf;
+
+	struct pci_dev *dev	= triflex_dev;
+	unsigned long bibma = pci_resource_start(dev, 4);
+	u8  c0 = 0, c1 = 0;
+	u32 pri_timing, sec_timing;
+
+	p += sprintf(p, "\n                                Compaq Triflex Chipset\n");
+	
+	pci_read_config_dword(dev, 0x70, &pri_timing);
+	pci_read_config_dword(dev, 0x74, &sec_timing);
+
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+	c0 = inb((unsigned short)bibma + 0x02);
+	c1 = inb((unsigned short)bibma + 0x0a);
+
+	p += sprintf(p, "--------------- Primary Channel "
+			"---------------- Secondary Channel "
+			"-------------\n");
+	p += sprintf(p, "                %sabled "
+			"                        %sabled\n",
+			(c0&0x80) ? "dis" : " en",
+			(c1&0x80) ? "dis" : " en");
+	p += sprintf(p, "--------------- drive0 --------- drive1 "
+			"-------- drive0 ---------- drive1 ------\n");
+	p += sprintf(p, "DMA enabled:    %s              %s "
+			"            %s               %s\n",
+			(c0&0x20) ? "yes" : "no ",
+			(c0&0x40) ? "yes" : "no ",
+			(c1&0x20) ? "yes" : "no ",
+			(c1&0x40) ? "yes" : "no " );
+
+	p += sprintf(p, "DMA\n");
+	p += sprintf(p, "PIO\n");
+	
+	return p-buf;
+}
+
+static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = hwif->pci_dev;
+	u8 channel_offset = hwif->channel ? 0x74 : 0x70;
+	u16 timing = 0;
+	u32 triflex_timings = 0;
+	u8 unit = (drive->select.b.unit & 0x01);
+	u8 speed = ide_rate_filter(0, xferspeed);
+	
+	pci_read_config_dword(dev, channel_offset, &triflex_timings);
+	
+	switch(speed) {
+		case XFER_MW_DMA_2:
+			timing = 0x0103; 
+			break;
+		case XFER_MW_DMA_1:
+			timing = 0x0203;
+			break;
+		case XFER_MW_DMA_0:
+			timing = 0x0808;
+			break;
+		case XFER_SW_DMA_2:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+			timing = 0x0f0f;
+			break;
+		case XFER_PIO_4:
+			timing = 0x0202;
+			break;
+		case XFER_PIO_3:
+			timing = 0x0204;
+			break;
+		case XFER_PIO_2:
+			timing = 0x0404;
+			break;
+		case XFER_PIO_1:
+			timing = 0x0508;
+			break;
+		case XFER_PIO_0:
+			timing = 0x0808;
+			break;
+		default:
+			return -1;
+	}
+
+	triflex_timings &= ~(0xFFFF << (16 * unit));
+	triflex_timings |= (timing << (16 * unit));
+	
+	pci_write_config_dword(dev, channel_offset, triflex_timings);
+	
+	return (ide_config_drive_speed(drive, speed));
+}
+
+static void triflex_tune_drive(ide_drive_t *drive, u8 pio)
+{
+	int use_pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	(void) triflex_tune_chipset(drive, (XFER_PIO_0 + use_pio));
+}
+
+static int triflex_config_drive_for_dma(ide_drive_t *drive)
+{
+	int speed = ide_dma_speed(drive, 0); /* No ultra speeds */
+
+	if (!speed) { 
+		u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL);
+		speed = XFER_PIO_0 + pspeed;
+	}
+	
+	(void) triflex_tune_chipset(drive, speed);
+	 return ide_dma_enable(drive);
+}
+
+static int triflex_config_drive_xfer_rate(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct hd_driveid *id	= drive->id;
+	
+	if (id && (id->capability & 1) && drive->autodma) {
+		if (hwif->ide_dma_bad_drive(drive))
+			goto tune_pio;
+		if (id->field_valid & 2) {
+			if ((id->dma_mword & hwif->mwdma_mask) ||
+				(id->dma_1word & hwif->swdma_mask)) {
+				if (!triflex_config_drive_for_dma(drive))
+					goto tune_pio;
+			}
+		} else 
+			goto tune_pio;
+	} else {
+tune_pio:
+		hwif->tuneproc(drive, 255);
+		return hwif->ide_dma_off_quietly(drive);
+	}
+
+	return hwif->ide_dma_on(drive);
+}
+
+static void __init init_hwif_triflex(ide_hwif_t *hwif)
+{
+	hwif->tuneproc = &triflex_tune_drive;
+	hwif->speedproc = &triflex_tune_chipset;
+
+	hwif->atapi_dma  = 1;
+	hwif->mwdma_mask = 0x07;
+	hwif->swdma_mask = 0x07;
+	hwif->ide_dma_check = &triflex_config_drive_xfer_rate;
+	
+	if (!noautodma)
+		hwif->autodma = 1;
+	hwif->drives[0].autodma = hwif->autodma;
+	hwif->drives[1].autodma = hwif->autodma;
+}
+
+static unsigned int __init init_chipset_triflex(struct pci_dev *dev, 
+		const char *name) 
+{
+#ifdef CONFIG_PROC_FS
+	ide_pci_register_host_proc(&triflex_proc);
+#endif
+	return 0;	
+}
+
+static int __devinit triflex_init_one(struct pci_dev *dev, 
+		const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &triflex_devices[id->driver_data];
+	if (dev->device != d->device)
+		BUG();
+	
+	ide_setup_pci_device(dev, d);
+	triflex_dev = dev;
+	MOD_INC_USE_COUNT;
+	
+	return 0;
+}
+
+static struct pci_driver driver = {
+	.name		= "TRIFLEX IDE",
+	.id_table	= triflex_pci_tbl,
+	.probe		= triflex_init_one,
+};
+
+static int triflex_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+static void triflex_ide_exit(void)
+{
+	ide_pci_unregister_driver(&driver);
+}
+
+module_init(triflex_ide_init);
+module_exit(triflex_ide_exit);
+
+MODULE_AUTHOR("Torben Mathiasen");
+MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
+MODULE_LICENSE("GPL");
+
+
diff -Nru a/drivers/ide/pci/triflex.h b/drivers/ide/pci/triflex.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/pci/triflex.h	Mon Jan 13 10:18:07 2003
@@ -0,0 +1,55 @@
+/* 
+ * triflex.h
+ *
+ * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
+ * Author: Torben Mathiasen <torben.mathiasen@hp.com>
+ *
+ */
+#ifndef TRIFLEX_H
+#define TRIFLEX_H
+
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *);
+static void init_hwif_triflex(ide_hwif_t *);
+static int triflex_get_info(char *, char **, off_t, int);
+
+static ide_pci_device_t triflex_devices[] __devinitdata = {
+	{
+		.vendor 	PCI_VENDOR_ID_COMPAQ,
+		.device		PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE,
+		.name		"TRIFLEX",
+		.init_chipset	init_chipset_triflex,
+		.init_iops	NULL,
+		.init_hwif	init_hwif_triflex,
+		.channels	2,
+		.autodma	AUTODMA,
+		.enablebits	{{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
+		.bootable	ON_BOARD,
+		.extra		0,
+	},{	
+		.vendor		0,
+		.device		0,
+		.channels	0,
+		.bootable	EOL,
+	}
+};
+
+#ifdef CONFIG_PROC_FS
+static ide_pci_host_proc_t triflex_proc __initdata = {
+		name:		"triflex",
+		set:		1,
+		get_info: 	triflex_get_info,
+		parent: 	NULL,
+};
+#endif
+
+static struct pci_device_id triflex_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, PCI_ANY_ID, 
+		PCI_ANY_ID, 0, 0, 0 },
+	{ 0, },
+};
+
+#endif /* TRIFLEX_H */
diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
--- a/drivers/ide/setup-pci.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/ide/setup-pci.c	Mon Jan 13 10:18:05 2003
@@ -315,7 +315,7 @@
 				"Could not enable device.\n", d->name);
 			return -EBUSY;
 		} else
-			printk(KERN_WARNING "%s: Not fully BIOS configured!\n", d->name);
+			printk(KERN_WARNING "%s: BIOS configuration fixed.\n", d->name);
 	}
 
 	/*
@@ -482,7 +482,7 @@
 	if ((d->autodma == AUTODMA) ||
 	    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
 	     (dev->class & 0x80))) {
-		u32 dma_base = ide_get_or_set_dma_base(hwif);
+		unsigned long dma_base = ide_get_or_set_dma_base(hwif);
 		if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
 			/*
  			 * Set up BM-DMA capability
diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- a/drivers/input/gameport/gameport.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/input/gameport/gameport.c	Mon Jan 13 10:18:06 2003
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/slab.h>
-#include <linux/isapnp.h>
 #include <linux/stddef.h>
 #include <linux/delay.h>
 
diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
--- a/drivers/input/gameport/ns558.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/input/gameport/ns558.c	Mon Jan 13 10:18:07 2003
@@ -194,7 +194,7 @@
 	int ioport, iolen;
 	struct ns558 *port;
 
-	if (!(dev->resource[0].flags & IORESOURCE_IO)) {
+	if (!pnp_port_valid(dev, 0)) {
 		printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n");
 		return -ENODEV;
 	}
diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
--- a/drivers/input/serio/Kconfig	Mon Jan 13 10:18:06 2003
+++ b/drivers/input/serio/Kconfig	Mon Jan 13 10:18:06 2003
@@ -89,6 +89,7 @@
 config SERIO_RPCKBD
 	tristate "Acorn RiscPC keyboard controller"
 	depends on ARCH_ACORN && SERIO
+	default y
 	help
 	  Say Y here if you have the Acorn RiscPC and want to use an AT
 	  keyboard connected to its keyboard controller.
diff -Nru a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c
--- a/drivers/isdn/divert/divert_init.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/divert/divert_init.c	Mon Jan 13 10:18:06 2003
@@ -51,9 +51,6 @@
      printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n",i);
      return(-EIO);
    } 
-#if (LINUX_VERSION_CODE < 0x020111)
-  register_symtab(0);
-#endif
   printk(KERN_INFO "dss1_divert module successfully installed\n");
   return(0);
 }
diff -Nru a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
--- a/drivers/isdn/hisax/Kconfig	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/Kconfig	Mon Jan 13 10:18:07 2003
@@ -109,6 +109,7 @@
 
 config HISAX_TELESPCI
 	bool "Teles PCI"
+	depends on PCI
 	help
 	  This enables HiSax support for the Teles PCI.
 	  See <file:Documentation/isdn/README.HiSax> on how to configure it.
@@ -235,6 +236,7 @@
 
 config HISAX_NETJET
 	bool "NETjet card"
+	depends on PCI
 	help
 	  This enables HiSax support for the NetJet from Traverse
 	  Technologies.
@@ -245,6 +247,7 @@
 
 config HISAX_NETJET_U
 	bool "NETspider U card"
+	depends on PCI
 	help
 	  This enables HiSax support for the Netspider U interface ISDN card
 	  from Traverse Technologies.
@@ -283,6 +286,7 @@
 
 config HISAX_BKM_A4T
 	bool "Telekom A4T card"
+	depends on PCI
 	help
 	  This enables HiSax support for the Telekom A4T card.
 
@@ -292,6 +296,7 @@
 
 config HISAX_SCT_QUADRO
 	bool "Scitel Quadro card"
+	depends on PCI
 	help
 	  This enables HiSax support for the Scitel Quadro card.
 
@@ -310,6 +315,7 @@
 
 config HISAX_HFC_PCI
 	bool "HFC PCI-Bus cards"
+	depends on PCI
 	help
 	  This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
 
@@ -318,6 +324,7 @@
 
 config HISAX_W6692
 	bool "Winbond W6692 based cards"
+	depends on PCI
 	help
 	  This enables HiSax support for Winbond W6692 based PCI ISDN cards.
 
@@ -335,7 +342,7 @@
 
 config HISAX_ENTERNOW_PCI
 	bool "Formula-n enter:now PCI card (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on PCI && EXPERIMENTAL
 	help
 	  This enables HiSax support for the Formula-n enter:now PCI
 	  ISDN card.
@@ -397,14 +404,14 @@
 
 config HISAX_FRITZ_CLASSIC
 	tristate "AVM Fritz!Card classic support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on ISA && EXPERIMENTAL
 	help
 	  This enables the driver for the AVM Fritz!Card classic, formerly
 	  known as AVM A1.
 
 config HISAX_HFCPCI
 	tristate "HFC PCI support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on PCI && EXPERIMENTAL
 	help
 	  This enables the driver for CCD HFC PCI based cards.
 
diff -Nru a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
--- a/drivers/isdn/hisax/Makefile	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/Makefile	Mon Jan 13 10:18:05 2003
@@ -38,12 +38,12 @@
 hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o
 hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o
 hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o
-hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o
+hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o ipac.o
 hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o
-hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o
-hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
+hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o 
+hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o ipac.o
 hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
-hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o
+hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o ipac.o isar.o
 hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o
 hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o
 hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o
@@ -55,8 +55,8 @@
 hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o
 hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o
 hisax-objs-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o
-hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o
-hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o
+hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o ipac.o
+hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o ipac.o
 hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o
 hisax-objs-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o
 #hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o
diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c
--- a/drivers/isdn/hisax/amd7930.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/amd7930.c	Mon Jan 13 10:18:05 2003
@@ -686,31 +686,19 @@
 	Bchan_mode(cs->bcs + 1, 0, 0);
 }
 
-void
-release_amd7930(struct IsdnCardState *cs)
-{
-}
-
 static int
-amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+amd7930_init(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			return(0);
-		case CARD_RELEASE:
-			release_amd7930(cs);
-			return(0);
-		case CARD_INIT:
-			cs->l1cmd = amd7930_l1cmd;
-			amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
-			init_amd7930(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
+	cs->l1cmd = amd7930_l1cmd;
+	amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
+	init_amd7930(cs);
+	return 0;
 }
 
+static struct card_ops amd7930_ops = {
+	.init     = amd7930_init,
+};
+
 int __init
 setup_amd7930(struct IsdnCard *card)
 {
@@ -719,14 +707,11 @@
 
 	strcpy(tmp, amd7930_revision);
 	printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_AMD7930)
-		return (0);
 
         cs->irq = amd7930_get_irqnum(0);
         if (cs->irq == 0)
-		return (0);
-
-	cs->cardmsg = &amd7930_card_msg;
+		return 0;
 
-	return (1);
+	cs->card_ops = &amd7930_ops;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
--- a/drivers/isdn/hisax/amd7930_fn.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/amd7930_fn.c	Mon Jan 13 10:18:06 2003
@@ -659,7 +659,7 @@
 	}
 }
 
-void
+static int
 setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
 {
 
@@ -667,16 +667,9 @@
 		debugl1(cs, "Amd7930: setstack called");
 
         st->l1.l1hw = Amd7930_l1hw;
+	return 0;
 }
 
-
-void
-DC_Close_Amd7930(struct IsdnCardState *cs) {
-        if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "Amd7930: DC_Close called");
-}
-
-
 static void
 dbusy_timer_handler(struct IsdnCardState *cs)
 {
@@ -723,7 +716,7 @@
 			/* Transmitter reset, abort transmit */
 			wByteAMD(cs, 0x21, 0x82);
 			wByteAMD(cs, 0x21, 0x02);
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */
 
                         if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");
@@ -764,26 +757,26 @@
 
 	0xFFFF};
 
+static struct dc_l1_ops amd7930_l1_ops = {
+	.open       = setstack_Amd7930,
+	.bh_func    = Amd7930_bh,
+	.dbusy_func = dbusy_timer_handler,
+};
 
 void __devinit
 Amd7930_init(struct IsdnCardState *cs)
 {
-    u16 *ptr;
-    u8 cmd, cnt;
+	u16 *ptr;
+	u8 cmd, cnt;
 
         if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "Amd7930: initamd called");
 
+	dc_l1_init(cs, &amd7930_l1_ops);
         cs->dc.amd7930.tx_xmtlen = 0;
         cs->dc.amd7930.old_state = 0;
         cs->dc.amd7930.lmr1 = 0x40;
         cs->dc.amd7930.ph_command = Amd7930_ph_command;
-	INIT_WORK(&cs->work, Amd7930_bh, cs);
-	cs->setstack_d = setstack_Amd7930;
-	cs->DC_Close = DC_Close_Amd7930;
-	cs->dbusytimer.function = (void *) dbusy_timer_handler;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
 
 	/* AMD Initialisation */
 	for (ptr = initAMD; *ptr != 0xFFFF; ) {
@@ -810,4 +803,13 @@
 				wByteAMD(cs, 0x01, LOBYTE(*ptr++));
 		}
 	}
+}
+
+int
+amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops,
+	      void (*set_irq_mask)(struct IsdnCardState *, u8 val))
+{
+	cs->dc_hw_ops = amd7930_ops;
+        cs->dc.amd7930.setIrqMask = set_irq_mask;
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/amd7930_fn.h b/drivers/isdn/hisax/amd7930_fn.h
--- a/drivers/isdn/hisax/amd7930_fn.h	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/amd7930_fn.h	Mon Jan 13 10:18:07 2003
@@ -18,5 +18,7 @@
 
 #define DBUSY_TIMER_VALUE 80
 
-extern void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags);
-extern void Amd7930_init(struct IsdnCardState *cs);
+void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags);
+void Amd7930_init(struct IsdnCardState *cs);
+int  amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops,
+		   void (*set_irq_mask)(struct IsdnCardState *, u8 val));
diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
--- a/drivers/isdn/hisax/asuscom.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/asuscom.c	Mon Jan 13 10:18:07 2003
@@ -114,37 +114,6 @@
 };
 
 static u8
-ipac_dc_read(struct IsdnCardState *cs, u8 offset)
-{
-	return readreg(cs, cs->hw.asus.isac, offset|0x80);
-}
-
-static void
-ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	writereg(cs, cs->hw.asus.isac, offset|0x80, value);
-}
-
-static void
-ipac_dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	readfifo(cs, cs->hw.asus.isac, 0x80, data, size);
-}
-
-static void
-ipac_dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	writefifo(cs, cs->hw.asus.isac, 0x80, data, size);
-}
-
-static struct dc_hw_ops ipac_dc_ops = {
-	.read_reg   = ipac_dc_read,
-	.write_reg  = ipac_dc_write,
-	.read_fifo  = ipac_dc_read_fifo,
-	.write_fifo = ipac_dc_write_fifo,
-};
-
-static u8
 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
 {
 	return readreg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0));
@@ -175,141 +144,93 @@
 	.write_fifo = hscx_write_fifo,
 };
 
-static void
-asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+static inline u8
+ipac_read(struct IsdnCardState *cs, u8 off)
 {
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u8 ret;
+	unsigned long flags;
 
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
+	spin_lock_irqsave(&asuscom_lock, flags);
+	byteout(cs->hw.asus.adr, off);
+	ret = bytein(cs->hw.asus.isac);
+	spin_unlock_irqrestore(&asuscom_lock, flags);
+	return ret;
 }
 
-static void
-asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+static inline void
+ipac_write(struct IsdnCardState *cs, u8 off, u8 data)
 {
-	struct IsdnCardState *cs = dev_id;
-	u8 ista, val, icnt = 5;
+	unsigned long flags;
 
-	if (!cs) {
-		printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
-		return;
-	}
-	ista = readreg(cs, cs->hw.asus.isac, IPAC_ISTA);
-Start_IPAC:
-	if (cs->debug & L1_DEB_IPAC)
-		debugl1(cs, "IPAC ISTA %02X", ista);
-	if (ista & 0x0f) {
-		val = hscx_read(cs, 1, HSCX_ISTA);
-		if (ista & 0x01)
-			val |= 0x01;
-		if (ista & 0x04)
-			val |= 0x02;
-		if (ista & 0x08)
-			val |= 0x04;
-		if (val)
-			hscx_int_main(cs, val);
-	}
-	if (ista & 0x20) {
-		val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe;
-		if (val) {
-			isac_interrupt(cs, val);
-		}
-	}
-	if (ista & 0x10) {
-		val = 0x01;
-		isac_interrupt(cs, val);
-	}
-	ista  = readreg(cs, cs->hw.asus.isac, IPAC_ISTA);
-	if ((ista & 0x3f) && icnt) {
-		icnt--;
-		goto Start_IPAC;
-	}
-	if (!icnt)
-		printk(KERN_WARNING "ASUS IRQ LOOP\n");
-	writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xFF);
-	writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xC0);
+	spin_lock_irqsave(&asuscom_lock, flags);
+	byteout(cs->hw.asus.adr, off);
+	byteout(cs->hw.asus.isac, data);
+	spin_unlock_irqrestore(&asuscom_lock, flags);
 }
 
-void
-release_io_asuscom(struct IsdnCardState *cs)
+static inline void
+ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
 {
-	int bytecnt = 8;
+	byteout(cs->hw.asus.adr, off);
+	insb(cs->hw.asus.isac, data, size);
+}
 
-	if (cs->hw.asus.cfg_reg)
-		release_region(cs->hw.asus.cfg_reg, bytecnt);
+
+static inline void
+ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
+{
+	byteout(cs->hw.asus.adr, off);
+	outsb(cs->hw.asus.isac, data, size);
 }
 
-static void
-reset_asuscom(struct IsdnCardState *cs)
+/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
+ * above */
+
+BUILD_IPAC_OPS(ipac);
+
+static int
+asuscom_reset(struct IsdnCardState *cs)
 {
-	if (cs->subtyp == ASUS_IPAC)
-		writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20);
-	else
-		byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
+	byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
-	if (cs->subtyp == ASUS_IPAC)
-		writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0);
-	else
-		byteout(cs->hw.asus.adr, 0);	/* Reset Off */
+	byteout(cs->hw.asus.adr, 0);	/* Reset Off */
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
-	if (cs->subtyp == ASUS_IPAC) {
-		writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0);
-		writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff);
-		writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0);
-		writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0);
-		writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12);
-	}
+	return 0;
 }
 
 static int
-Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+asuscom_ipac_reset(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_asuscom(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_asuscom(cs);
-			return(0);
-		case CARD_INIT:
-			cs->debug |= L1_DEB_IPAC;
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
+	writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0);
+	writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff);
+	writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0);
+	writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0);
+	writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12);
+	return 0;
 }
 
+static struct card_ops asuscom_ops = {
+	.init     = inithscxisac,
+	.reset    = asuscom_reset,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
+
+static struct card_ops asuscom_ipac_ops = {
+	.init     = ipac_init,
+	.reset    = asuscom_ipac_reset,
+	.release  = hisax_release_resources,
+	.irq_func = ipac_irq,
+};
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id asus_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
@@ -328,7 +249,7 @@
 };
 
 static struct isapnp_device_id *adev = &asus_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __init
@@ -341,33 +262,40 @@
 
 	strcpy(tmp, Asuscom_revision);
 	printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_ASUSCOM)
-		return (0);
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pci_bus *pb;
-		struct pci_dev *pd;
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
 
 		while(adev->card_vendor) {
-			if ((pb = isapnp_find_card(adev->card_vendor,
-				adev->card_device, pnp_c))) {
+			if ((pb = pnp_find_card(adev->card_vendor,
+						adev->card_device,
+						pnp_c))) {
 				pnp_c = pb;
 				pd = NULL;
-				if ((pd = isapnp_find_dev(pnp_c,
-					adev->vendor, adev->function, pd))) {
+				if ((pd = pnp_find_dev(pnp_c,
+						       adev->vendor,
+						       adev->function,
+						       pd))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
 						(char *)adev->driver_data);
-					pd->prepare(pd);
-					pd->deactivate(pd);
-					pd->activate(pd);
-					card->para[1] = pd->resource[0].start;
-					card->para[0] = pd->irq_resource[0].start;
-					if (!card->para[0] || !card->para[1]) {
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "AsusPnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd, NULL) < 0) {
+						printk(KERN_ERR "AsusPnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
 						printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n",
-						card->para[0], card->para[1]);
-						pd->deactivate(pd);
+							pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
 						return(0);
 					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
 					break;
 				} else {
 					printk(KERN_ERR "AsusPnP: PnP error card found, no device\n");
@@ -385,47 +313,33 @@
 	bytecnt = 8;
 	cs->hw.asus.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
-	if (!request_region((cs->hw.asus.cfg_reg), bytecnt,
-			    "asuscom isdn")) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.asus.cfg_reg,
-		       cs->hw.asus.cfg_reg + bytecnt);
-		return (0);
-	}
+	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn"))
+		goto err;
 	printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
 		cs->hw.asus.cfg_reg, cs->irq);
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &Asus_card_msg;
 	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
 	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
 	if ((val == 1) || (val == 2)) {
 		cs->subtyp = ASUS_IPAC;
+		cs->card_ops = &asuscom_ipac_ops;
 		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
-		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
-		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-		cs->dc_hw_ops = &ipac_dc_ops;
-		cs->irq_func = &asuscom_interrupt_ipac;
-		printk(KERN_INFO "Asus: IPAC version %x\n", val);
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
 	} else {
 		cs->subtyp = ASUS_ISACHSCX;
+		cs->card_ops = &asuscom_ops;
 		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
 		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
 		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
 		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
 		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-		cs->dc_hw_ops = &isac_ops;
-		cs->irq_func = &asuscom_interrupt;
-		ISACVersion(cs, "ISDNLink:");
-		if (HscxVersion(cs, "ISDNLink:")) {
-			printk(KERN_WARNING
-		     	"ISDNLink: wrong HSCX versions check IO address\n");
-			release_io_asuscom(cs);
-			return (0);
-		}
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
 	}
 	printk(KERN_INFO "ISDNLink: resetting card\n");
-	reset_asuscom(cs);
-	return (1);
+	cs->card_ops->reset(cs);
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
--- a/drivers/isdn/hisax/avm_a1.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/avm_a1.c	Mon Jan 13 10:18:05 2003
@@ -146,43 +146,19 @@
 	spin_unlock(&cs->lock);
 }
 
-inline static void
-release_ioregs(struct IsdnCardState *cs, int mask)
+static void
+avm_a1_init(struct IsdnCardState *cs)
 {
-	release_region(cs->hw.avm.cfg_reg, 8);
-	if (mask & 1)
-		release_region(cs->hw.avm.isac + 32, 32);
-	if (mask & 2)
-		release_region(cs->hw.avm.isacfifo, 1);
-	if (mask & 4)
-		release_region(cs->hw.avm.hscx[0] + 32, 32);
-	if (mask & 8)
-		release_region(cs->hw.avm.hscxfifo[0], 1);
-	if (mask & 0x10)
-		release_region(cs->hw.avm.hscx[1] + 32, 32);
-	if (mask & 0x20)
-		release_region(cs->hw.avm.hscxfifo[1], 1);
+	byteout(cs->hw.avm.cfg_reg, 0x16);
+	byteout(cs->hw.avm.cfg_reg, 0x1E);
+	inithscxisac(cs);
 }
 
-static int
-AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			return(0);
-		case CARD_RELEASE:
-			release_ioregs(cs, 0x3f);
-			return(0);
-		case CARD_INIT:
-			byteout(cs->hw.avm.cfg_reg, 0x16);
-			byteout(cs->hw.avm.cfg_reg, 0x1E);
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
+static struct card_ops avm_a1_ops = {
+	.init     = avm_a1_init,
+	.release  = hisax_release_resources,
+	.irq_func = avm_a1_interrupt,
+};
 
 int __init
 setup_avm_a1(struct IsdnCard *card)
@@ -193,76 +169,26 @@
 
 	strcpy(tmp, avm_revision);
 	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_A1)
-		return (0);
 
-	cs->hw.avm.cfg_reg = card->para[1] + 0x1800;
-	cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20;
-	cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20;
-	cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20;
-	cs->hw.avm.isacfifo = card->para[1] + 0x1000;
-	cs->hw.avm.hscxfifo[0] = card->para[1];
-	cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800;
+	cs->hw.avm.cfg_reg     = request_io(&cs->rs, card->para[1] + 0x1800,  8, "avm cfg");
+	if (!cs->hw.avm.cfg_reg) goto err;
+	cs->hw.avm.isac        = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac");
+	if (!cs->hw.avm.isac) goto err;
+	cs->hw.avm.isacfifo    = request_io(&cs->rs, card->para[1] + 0x1000,  1, "HiSax isac fifo");
+	if (!cs->hw.avm.isacfifo) goto err;
+	cs->hw.avm.hscx[0]     = request_io(&cs->rs, card->para[1] + 0x400,  32, "HiSax hscx A");
+	if (!cs->hw.avm.hscx[0]) goto err;
+	cs->hw.avm.hscxfifo[0] = request_io(&cs->rs, card->para[1],           1, "HiSax hscx A fifo");
+	if (!cs->hw.avm.hscxfifo[0]) goto err;
+	cs->hw.avm.hscx[1]     = request_io(&cs->rs, card->para[1] + 0xc00,  32, "HiSax hscx B");
+	if (!cs->hw.avm.hscx[1]) goto err;
+	cs->hw.avm.hscxfifo[1] = request_io(&cs->rs, card->para[1] + 0x800,   1, "HiSax hscx B fifo");
+	if (!cs->hw.avm.hscxfifo[1]) goto err;
+	cs->hw.avm.isac    -= 0x20;
+	cs->hw.avm.hscx[0] -= 0x20;
+	cs->hw.avm.hscx[1] -= 0x20;
 	cs->irq = card->para[0];
-	if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.avm.cfg_reg,
-		       cs->hw.avm.cfg_reg + 8);
-		return (0);
-	}
-	if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) {
-		printk(KERN_WARNING
-		       "HiSax: %s isac ports %x-%x already in use\n",
-		       CardType[cs->typ],
-		       cs->hw.avm.isac + 32,
-		       cs->hw.avm.isac + 64);
-		release_ioregs(cs, 0);
-		return (0);
-	}
-	if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) {
-		printk(KERN_WARNING
-		       "HiSax: %s isac fifo port %x already in use\n",
-		       CardType[cs->typ],
-		       cs->hw.avm.isacfifo);
-		release_ioregs(cs, 1);
-		return (0);
-	}
-	if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) {
-		printk(KERN_WARNING
-		       "HiSax: %s hscx A ports %x-%x already in use\n",
-		       CardType[cs->typ],
-		       cs->hw.avm.hscx[0] + 32,
-		       cs->hw.avm.hscx[0] + 64);
-		release_ioregs(cs, 3);
-		return (0);
-	}
-	if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) {
-		printk(KERN_WARNING
-		       "HiSax: %s hscx A fifo port %x already in use\n",
-		       CardType[cs->typ],
-		       cs->hw.avm.hscxfifo[0]);
-		release_ioregs(cs, 7);
-		return (0);
-	}
-	if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) {
-		printk(KERN_WARNING
-		       "HiSax: %s hscx B ports %x-%x already in use\n",
-		       CardType[cs->typ],
-		       cs->hw.avm.hscx[1] + 32,
-		       cs->hw.avm.hscx[1] + 64);
-		release_ioregs(cs, 0xf);
-		return (0);
-	}
-	if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) {
-		printk(KERN_WARNING
-		       "HiSax: %s hscx B fifo port %x already in use\n",
-		       CardType[cs->typ],
-		       cs->hw.avm.hscxfifo[1]);
-		release_ioregs(cs, 0x1f);
-		return (0);
-	}
+
 	byteout(cs->hw.avm.cfg_reg, 0x0);
 	HZDELAY(HZ / 5 + 1);
 	byteout(cs->hw.avm.cfg_reg, 0x1);
@@ -302,16 +228,11 @@
 	       cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
 	       cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
 
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &AVM_card_msg;
-	cs->irq_func = &avm_a1_interrupt;
-	ISACVersion(cs, "AVM A1:");
-	if (HscxVersion(cs, "AVM A1:")) {
-		printk(KERN_WARNING
-		       "AVM A1: wrong HSCX versions check IO address\n");
-		release_ioregs(cs, 0x3f);
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &avm_a1_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
--- a/drivers/isdn/hisax/avm_a1p.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/avm_a1p.c	Mon Jan 13 10:18:07 2003
@@ -189,39 +189,32 @@
 	spin_unlock(&cs->lock);
 }
 
+static void
+avm_a1p_init(struct IsdnCardState *cs)
+{
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,
+		ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
+	inithscxisac(cs);
+}
+
 static int
-AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+avm_a1p_reset(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
-			HZDELAY(HZ / 5 + 1);
-			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
-			HZDELAY(HZ / 5 + 1);
-			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
-			return 0;
-
-		case CARD_RELEASE:
-			/* free_irq is done in HiSax_closecard(). */
-		        /* free_irq(cs->irq, cs); */
-			return 0;
-
-		case CARD_INIT:
-			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
-			inithscxisac(cs);
-			return 0;
-
-		case CARD_TEST:
-			/* we really don't need it for the PCMCIA Version */
-			return 0;
-
-		default:
-			/* all card drivers ignore others, so we do the same */
-			return 0;
-	}
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+	HZDELAY(HZ / 5 + 1);
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
+	HZDELAY(HZ / 5 + 1);
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+
 	return 0;
 }
 
+static struct card_ops avm_a1p_ops = {
+	.init     = avm_a1p_init,
+	.reset    = avm_a1p_reset,
+	.irq_func = avm_a1p_interrupt,
+};
+
 int __devinit
 setup_avm_a1_pcmcia(struct IsdnCard *card)
 {
@@ -232,10 +225,7 @@
 
 	strcpy(tmp, avm_revision);
 	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
-						 HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
-		return (0);
-
+	       HiSax_getrev(tmp));
 	cs->hw.avm.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
 
@@ -256,16 +246,9 @@
 	printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
 				cs->hw.avm.cfg_reg, cs->irq, model, vers);
 
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &AVM_card_msg;
-	cs->irq_func = &avm_a1p_interrupt;
-
-	ISACVersion(cs, "AVM A1 PCMCIA:");
-	if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
-		printk(KERN_WARNING
-		       "AVM A1 PCMCIA: wrong HSCX versions check IO address\n");
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &avm_a1p_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return 0;
+
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
--- a/drivers/isdn/hisax/avm_pci.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/avm_pci.c	Mon Jan 13 10:18:05 2003
@@ -175,6 +175,39 @@
 	spin_unlock_irqrestore(&avm_pci_lock, flags);
 }
 
+static void
+hdlc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
+{
+	u8 idx = hscx ? AVM_HDLC_2 : AVM_HDLC_1;
+	int i;
+
+	if (cs->subtyp == AVM_FRITZ_PCI) {
+		u32 *ptr = (u32 *) data;
+
+		outl(idx, cs->hw.avm.cfg_reg + 4);
+		for (i = 0; i < len; i += 4) {
+#ifdef __powerpc__
+#ifdef CONFIG_APUS
+			*ptr++ = in_le32((u32 *)(cs->hw.avm.isac +_IO_BASE));
+#else
+			*ptr++ = in_be32((u32 *)(cs->hw.avm.isac +_IO_BASE));
+#endif /* CONFIG_APUS */
+#else
+			*ptr++ = inl(cs->hw.avm.isac);
+#endif /* __powerpc__ */
+		}
+	} else {
+		outb(idx, cs->hw.avm.cfg_reg + 4);
+		for (i = 0; i < len; i++) {
+			*data++ = inb(cs->hw.avm.isac);
+		}
+	}
+}
+
+static struct bc_hw_ops hdlc_hw_ops = {
+	.read_fifo  = hdlc_read_fifo,
+};
+
 static inline
 struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
 {
@@ -259,52 +292,7 @@
 static inline void
 hdlc_empty_fifo(struct BCState *bcs, int count)
 {
-	register u_int *ptr;
-	u8 *p;
-	u8 idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
-	int cnt=0;
-	struct IsdnCardState *cs = bcs->cs;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hdlc_empty_fifo %d", count);
-	if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
-		return;
-	}
-	ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
-	bcs->hw.hdlc.rcvidx += count;
-	if (cs->subtyp == AVM_FRITZ_PCI) {
-		outl(idx, cs->hw.avm.cfg_reg + 4);
-		while (cnt < count) {
-#ifdef __powerpc__
-#ifdef CONFIG_APUS
-			*ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
-#else
-			*ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
-#endif /* CONFIG_APUS */
-#else
-			*ptr++ = inl(cs->hw.avm.isac);
-#endif /* __powerpc__ */
-			cnt += 4;
-		}
-	} else {
-		outb(idx, cs->hw.avm.cfg_reg + 4);
-		while (cnt < count) {
-			*p++ = inb(cs->hw.avm.isac);
-			cnt++;
-		}
-	}
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		if (cs->subtyp == AVM_FRITZ_PNP)
-			p = (u8 *) ptr;
-		t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', count);
-		QuickHex(t, p, count);
-		debugl1(cs, bcs->blog);
-	}
+	recv_empty_fifo_b(bcs, count);
 }
 
 static void
@@ -360,15 +348,10 @@
 	hdlc_fill_fifo(bcs);
 }
 
-static struct bc_l1_ops hdlc_l1_ops = {
-	.fill_fifo = hdlc_fill_fifo,
-};
-
 static inline void
 HDLC_irq(struct BCState *bcs, u_int stat)
 {
 	int len;
-	struct sk_buff *skb;
 
 	if (bcs->cs->debug & L1_DEB_HSCX)
 		debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
@@ -384,7 +367,7 @@
 			write_ctrl(bcs, 1);
 			bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
 			write_ctrl(bcs, 1);
-			bcs->hw.hdlc.rcvidx = 0;
+			bcs->rcvidx = 0;
 		} else {
 			if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
 				len = 32;
@@ -392,21 +375,13 @@
 			if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
 				if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
 					(bcs->mode == L1_MODE_TRANS)) {
-					if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
-						printk(KERN_WARNING "HDLC: receive out of memory\n");
-					else {
-						memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
-							bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
-						skb_queue_tail(&bcs->rqueue, skb);
-					}
-					bcs->hw.hdlc.rcvidx = 0;
-					sched_b_event(bcs, B_RCVBUFREADY);
+					recv_rme_b(bcs);
 				} else {
 					if (bcs->cs->debug & L1_DEB_HSCX)
 						debugl1(bcs->cs, "invalid frame");
 					else
 						debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);
-					bcs->hw.hdlc.rcvidx = 0;
+					bcs->rcvidx = 0;
 				}
 			}
 		}
@@ -492,57 +467,20 @@
 close_hdlcstate(struct BCState *bcs)
 {
 	modehdlc(bcs, 0, 0);
-	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (bcs->hw.hdlc.rcvbuf) {
-			kfree(bcs->hw.hdlc.rcvbuf);
-			bcs->hw.hdlc.rcvbuf = NULL;
-		}
-		if (bcs->blog) {
-			kfree(bcs->blog);
-			bcs->blog = NULL;
-		}
-		skb_queue_purge(&bcs->rqueue);
-		skb_queue_purge(&bcs->squeue);
-		if (bcs->tx_skb) {
-			dev_kfree_skb_any(bcs->tx_skb);
-			bcs->tx_skb = NULL;
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		}
-	}
+	bc_close(bcs);
 }
 
 int
 open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-			       "HiSax: No memory for hdlc.rcvbuf\n");
-			return (1);
-		}
-		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-				"HiSax: No memory for bcs->blog\n");
-			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-			kfree(bcs->hw.hdlc.rcvbuf);
-			bcs->hw.hdlc.rcvbuf = NULL;
-			return (2);
-		}
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	bcs->tx_skb = NULL;
-	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	bcs->event = 0;
-	bcs->hw.hdlc.rcvidx = 0;
-	bcs->tx_cnt = 0;
-	return (0);
+	return bc_open(bcs);
 }
 
 int
 setstack_hdlc(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
+	bcs->unit = bcs->channel;
 	if (open_hdlcstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
@@ -553,6 +491,12 @@
 	return (0);
 }
 
+static struct bc_l1_ops hdlc_l1_ops = {
+	.fill_fifo = hdlc_fill_fifo,
+	.open      = setstack_hdlc,
+	.close     = close_hdlcstate,
+};
+
 void __init
 inithdlc(struct IsdnCardState *cs)
 {
@@ -582,10 +526,6 @@
 		debugl1(cs, "HDLC 2 VIN %x", val);
 	}
 
-	cs->bcs[0].BC_SetStack = setstack_hdlc;
-	cs->bcs[1].BC_SetStack = setstack_hdlc;
-	cs->bcs[0].BC_Close = close_hdlcstate;
-	cs->bcs[1].BC_Close = close_hdlcstate;
 	modehdlc(cs->bcs, -1, 0);
 	modehdlc(cs->bcs + 1, -1, 1);
 }
@@ -616,8 +556,8 @@
 	WriteISAC(cs, ISAC_MASK, 0x0);
 }
 
-static void
-reset_avmpcipnp(struct IsdnCardState *cs)
+static int
+avm_pcipnp_reset(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "AVM PCI/PnP: reset\n");
 	outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
@@ -628,37 +568,38 @@
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 	printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));
+	return 0;
 }
 
-static int
-AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+avm_pcipnp_init(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_avmpcipnp(cs);
-			return(0);
-		case CARD_RELEASE:
-			outb(0, cs->hw.avm.cfg_reg + 2);
-			release_region(cs->hw.avm.cfg_reg, 32);
-			return(0);
-		case CARD_INIT:
-			initisac(cs);
-			inithdlc(cs);
-			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
-				cs->hw.avm.cfg_reg + 2);
-			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
-				AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
+	initisac(cs);
+	inithdlc(cs);
+	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
+	     cs->hw.avm.cfg_reg + 2);
+	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
+	     AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
+}
+
+static void
+avm_pcipnp_release(struct IsdnCardState *cs)
+{
+	outb(0, cs->hw.avm.cfg_reg + 2);
+	hisax_release_resources(cs);
 }
 
+static struct card_ops avm_pci_ops = {
+	.init     = avm_pcipnp_init,
+	.reset    = avm_pcipnp_reset,
+	.release  = avm_pcipnp_release,
+	.irq_func = avm_pcipnp_interrupt,
+};
+
 static struct pci_dev *dev_avm __initdata = NULL;
 #ifdef __ISAPNP__
-static struct pci_bus *bus_avm __initdata = NULL;
-static struct pci_dev *pnp_avm __initdata = NULL;
+static struct pnp_card *card_avm __initdata = NULL;
+static struct pnp_dev *pnp_avm __initdata = NULL;
 #endif
 
 int __init
@@ -670,8 +611,6 @@
 
 	strcpy(tmp, avm_pci_rev);
 	printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_FRITZPCI)
-		return (0);
 	if (card->para[1]) {
 		/* old manual method */
 		cs->hw.avm.cfg_reg = card->para[1];
@@ -680,32 +619,36 @@
 	} else {
 #ifdef __ISAPNP__
 		if (isapnp_present()) {
-			struct pci_bus *ba;
-			if ((ba = isapnp_find_card(
+			struct pnp_card *ba;
+			if ((ba = pnp_find_card(
 				ISAPNP_VENDOR('A', 'V', 'M'),
-				ISAPNP_FUNCTION(0x0900), bus_avm))) {
-				bus_avm = ba;
+				ISAPNP_FUNCTION(0x0900), card_avm))) {
+				card_avm = ba;
 				pnp_avm = NULL;
-				if ((pnp_avm = isapnp_find_dev(bus_avm,
+				if ((pnp_avm = pnp_find_dev(card_avm,
 					ISAPNP_VENDOR('A', 'V', 'M'),
 					ISAPNP_FUNCTION(0x0900), pnp_avm))) {
-					pnp_avm->prepare(pnp_avm);
-					pnp_avm->deactivate(pnp_avm);
-					pnp_avm->activate(pnp_avm);
-					cs->hw.avm.cfg_reg =
-						pnp_avm->resource[0].start;
-					cs->irq = 
-						pnp_avm->irq_resource[0].start;
-					if (!cs->irq) {
+					if (pnp_device_attach(pnp_avm) < 0) {
+						printk(KERN_ERR "FritzPnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pnp_avm, NULL) < 0) {
+						printk(KERN_ERR "FritzPnP: activate failed\n");
+						pnp_device_detach(pnp_avm);
+						return 0;
+					}
+					if (!pnp_irq_valid(pnp_avm, 0)) {
 						printk(KERN_ERR "FritzPnP:No IRQ\n");
-						pnp_avm->deactivate(pnp_avm);
+						pnp_device_detach(pnp_avm);
 						return(0);
 					}
-					if (!cs->hw.avm.cfg_reg) {
+					if (!pnp_port_valid(pnp_avm, 0)) {
 						printk(KERN_ERR "FritzPnP:No IO address\n");
-						pnp_avm->deactivate(pnp_avm);
+						pnp_device_detach(pnp_avm);
 						return(0);
 					}
+					cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0);
+					cs->irq = pnp_irq(pnp_avm, 0);
 					cs->subtyp = AVM_FRITZ_PNP;
 					goto ready;
 				}
@@ -715,10 +658,6 @@
 		}
 #endif
 #if CONFIG_PCI
-		if (!pci_present()) {
-			printk(KERN_ERR "FritzPCI: no PCI bus present\n");
-			return(0);
-		}
 		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
 			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
 			cs->irq = dev_avm->irq;
@@ -739,22 +678,14 @@
 			return(0);
 		}
 		cs->irq_flags |= SA_SHIRQ;
-#else
-		printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
-		return (0);
 #endif /* CONFIG_PCI */
 	}
 ready:
 	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
-	if (!request_region((cs->hw.avm.cfg_reg), 32, (cs->subtyp == AVM_FRITZ_PCI)
-			 ? "avm PCI" : "avm PnP")) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.avm.cfg_reg,
-		       cs->hw.avm.cfg_reg + 31);
-		return (0);
-	}
+	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32,
+		 cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP"))
+		goto err;
+	
 	switch (cs->subtyp) {
 	  case AVM_FRITZ_PCI:
 		val = inl(cs->hw.avm.cfg_reg);
@@ -766,17 +697,19 @@
 		val = inb(cs->hw.avm.cfg_reg);
 		ver = inb(cs->hw.avm.cfg_reg + 1);
 		printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
-		reset_avmpcipnp(cs);
+		avm_pcipnp_reset(cs);
 		break;
 	}
 	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
 		(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
 		cs->irq, cs->hw.avm.cfg_reg);
 
-	cs->dc_hw_ops = &isac_ops;
+	cs->bc_hw_ops = &hdlc_hw_ops;
 	cs->bc_l1_ops = &hdlc_l1_ops;
-	cs->cardmsg = &AVM_card_msg;
-	cs->irq_func = &avm_pcipnp_interrupt;
-	ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
-	return (1);
+	cs->card_ops = &avm_pci_ops;
+	isac_setup(cs, &isac_ops);
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
--- a/drivers/isdn/hisax/bkm_a4t.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/bkm_a4t.c	Mon Jan 13 10:18:05 2003
@@ -174,89 +174,81 @@
 	spin_unlock(&cs->lock);
 }
 
-void
-release_io_bkm(struct IsdnCardState *cs)
+static void
+enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
 {
-	if (cs->hw.ax.base) {
-		iounmap((void *) cs->hw.ax.base);
-		cs->hw.ax.base = 0;
-	}
+	I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	if (bEnable)
+		pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
+	else
+		/* CAUTION: This disables the video capture driver too */
+		pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
 }
 
 static void
-enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
+reset_bkm(struct IsdnCardState *cs)
 {
-	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
-		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-		if (bEnable)
-			pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
-		else
-			/* CAUTION: This disables the video capture driver too */
-			pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
-	}
+	I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	/* Issue the I20 soft reset     */
+	pI20_Regs->i20SysControl = 0xFF;	/* all in */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10 * HZ) / 1000);
+	/* Remove the soft reset */
+	pI20_Regs->i20SysControl = sysRESET | 0xFF;
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10 * HZ) / 1000);
+	/* Set our configuration */
+	pI20_Regs->i20SysControl = sysRESET | sysCFG;
+	/* Issue ISDN reset     */
+	pI20_Regs->i20GuestControl = guestWAIT_CFG |
+		g_A4T_JADE_RES |
+		g_A4T_ISAR_RES |
+		g_A4T_ISAC_RES |
+		g_A4T_JADE_BOOTR |
+		g_A4T_ISAR_BOOTR;
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10 * HZ) / 1000);
+
+	/* Remove RESET state from ISDN */
+	pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
+					g_A4T_JADE_RES |
+					g_A4T_ISAR_RES);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10 * HZ) / 1000);
 }
 
 static void
-reset_bkm(struct IsdnCardState *cs)
+bkm_a4t_init(struct IsdnCardState *cs)
 {
-	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
-		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-		/* Issue the I20 soft reset     */
-		pI20_Regs->i20SysControl = 0xFF;	/* all in */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10 * HZ) / 1000);
-		/* Remove the soft reset */
-		pI20_Regs->i20SysControl = sysRESET | 0xFF;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10 * HZ) / 1000);
-		/* Set our configuration */
-		pI20_Regs->i20SysControl = sysRESET | sysCFG;
-		/* Issue ISDN reset     */
-		pI20_Regs->i20GuestControl = guestWAIT_CFG |
-		    g_A4T_JADE_RES |
-		    g_A4T_ISAR_RES |
-		    g_A4T_ISAC_RES |
-		    g_A4T_JADE_BOOTR |
-		    g_A4T_ISAR_BOOTR;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10 * HZ) / 1000);
-
-		/* Remove RESET state from ISDN */
-		pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
-						g_A4T_JADE_RES |
-						g_A4T_ISAR_RES);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10 * HZ) / 1000);
-	}
+	initisac(cs);
+	initjade(cs);
+	/* Enable ints */
+	enable_bkm_int(cs, 1);
 }
 
 static int
-BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+bkm_a4t_reset(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			/* Disable ints */
-			enable_bkm_int(cs, 0);
-			reset_bkm(cs);
-			return (0);
-		case CARD_RELEASE:
-			/* Sanity */
-			enable_bkm_int(cs, 0);
-			reset_bkm(cs);
-			release_io_bkm(cs);
-			return (0);
-		case CARD_INIT:
-			initisac(cs);
-			initjade(cs);
-			/* Enable ints */
-			enable_bkm_int(cs, 1);
-			return (0);
-		case CARD_TEST:
-			return (0);
-	}
-	return (0);
+	/* Disable ints */
+	enable_bkm_int(cs, 0);
+	reset_bkm(cs);
+	return 0;
 }
 
+static void
+bkm_a4t_release(struct IsdnCardState *cs)
+{
+	reset_bkm(cs);
+	hisax_release_resources(cs);
+}
+
+static struct card_ops bkm_a4t_ops = {
+	.init     = bkm_a4t_init,
+	.reset    = bkm_a4t_reset,
+	.release  = bkm_a4t_release,
+	.irq_func = bkm_interrupt,
+};
+
 static struct pci_dev *dev_a4t __initdata = NULL;
 
 int __init
@@ -266,21 +258,9 @@
 	char tmp[64];
 	u_int pci_memaddr = 0, found = 0;
 	I20_REGISTER_FILE *pI20_Regs;
-#if CONFIG_PCI
-#endif
 
 	strcpy(tmp, bkm_a4t_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
-		cs->subtyp = BKM_A4T;
-	} else
-		return (0);
-
-#if CONFIG_PCI
-	if (!pci_present()) {
-		printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
-		return (0);
-	}
 	while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
 		PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
 		u16 sub_sys;
@@ -305,40 +285,32 @@
 		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
 		return (0);
 	}
-	if (!pci_memaddr) {
+	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T");
+	if (!cs->hw.ax.base) {
 		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
 		return (0);
 	}
-	cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
+	
 	/* Check suspecious address */
 	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
 	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
 		printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
 		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
-		iounmap((void *) cs->hw.ax.base);
-		cs->hw.ax.base = 0;
+		hisax_release_resources(cs);
 		return (0);
 	}
 	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
 	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
 	cs->hw.ax.isac_ale = GCS_1;
 	cs->hw.ax.jade_ale = GCS_3;
-#else
-	printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
-	printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
-	return (0);
-#endif				/* CONFIG_PCI */
+
 	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
 	       CardType[card->typ], cs->hw.ax.base, cs->irq);
 
 	reset_bkm(cs);
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &jade_ops;
-	cs->cardmsg = &BKM_card_msg;
-	cs->irq_func = &bkm_interrupt;
 	cs->irq_flags |= SA_SHIRQ;
-	ISACVersion(cs, "Telekom A4T:");
-	/* Jade version */
-	JadeVersion(cs, "Telekom A4T:");
-	return (1);
+	cs->card_ops = &bkm_a4t_ops;
+	isac_setup(cs, &isac_ops);
+	jade_setup(cs, &jade_ops);
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
--- a/drivers/isdn/hisax/bkm_a8.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/bkm_a8.c	Mon Jan 13 10:18:07 2003
@@ -20,8 +20,6 @@
 #include <linux/pci.h>
 #include "bkm_ax.h"
 
-#if CONFIG_PCI
-
 #define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
 
 extern const char *CardType[];
@@ -42,7 +40,7 @@
 #define wordin(addr) inw(addr)
 
 static inline u8
-readreg(struct IsdnCardState *cs, u8 off)
+ipac_read(struct IsdnCardState *cs, u8 off)
 {
 	u8 ret;
 	unsigned long flags;
@@ -51,13 +49,14 @@
 	wordout(cs->hw.ax.base, off);
 	ret = wordin(cs->hw.ax.data_adr) & 0xFF;
 	spin_unlock_irqrestore(&bkm_a8_lock, flags);
-	return (ret);
+	return ret;
 }
 
 static inline void
-writereg(struct IsdnCardState *cs, u8 off, u8 data)
+ipac_write(struct IsdnCardState *cs, u8 off, u8 data)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&bkm_a8_lock, flags);
 	wordout(cs->hw.ax.base, off);
 	wordout(cs->hw.ax.data_adr, data);
@@ -65,7 +64,7 @@
 }
 
 static inline void
-readfifo(struct IsdnCardState *cs, u8 off, u8 *data, int size)
+ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 *data, int size)
 {
 	int i;
 
@@ -75,7 +74,7 @@
 }
 
 static inline void
-writefifo(struct IsdnCardState *cs, u8 off, u8 *data, int size)
+ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 *data, int size)
 {
 	int i;
 
@@ -84,144 +83,26 @@
 		wordout(cs->hw.ax.data_adr, data[i]);
 }
 
-static u8
-ipac_dc_read(struct IsdnCardState *cs, u8 offset)
-{
-	return readreg(cs, offset | 0x80);
-}
-
-static void
-ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	writereg(cs, offset | 0x80, value);
-}
-
-static void
-ipac_dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	readfifo(cs, 0x80, data, size);
-}
-
-static void
-ipac_dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	writefifo(cs, 0x80, data, size);
-}
-
-static struct dc_hw_ops ipac_dc_ops = {
-	.read_reg   = ipac_dc_read,
-	.write_reg  = ipac_dc_write,
-	.read_fifo  = ipac_dc_read_fifo,
-	.write_fifo = ipac_dc_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
-{
-	return readreg(cs, offset + (hscx ? 0x40 : 0));
-}
-
-static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
-{
-	writereg(cs, offset + (hscx ? 0x40 : 0), value);
-}
-
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	readfifo(cs, hscx ? 0x40 : 0, data, size);
-}
-
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	writefifo(cs, hscx ? 0x40 : 0, data, size);
-}
-
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
+ * above */
 
+BUILD_IPAC_OPS(ipac);
+  
 /* Set the specific ipac to active */
 static void
 set_ipac_active(struct IsdnCardState *cs, u_int active)
 {
 	/* set irq mask */
-	writereg(cs, IPAC_MASK, active ? 0xc0 : 0xff);
-}
-
-static void
-bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u8 ista, val, icnt = 5;
-
-	spin_lock(&cs->lock);
-	ista = readreg(cs, IPAC_ISTA);
-	if (!(ista & 0x3f)) /* not this IPAC */
-		goto unlock;
-      Start_IPAC:
-	if (cs->debug & L1_DEB_IPAC)
-		debugl1(cs, "IPAC ISTA %02X", ista);
-	if (ista & 0x0f) {
-		val = hscx_read(cs, 1, HSCX_ISTA);
-		if (ista & 0x01)
-			val |= 0x01;
-		if (ista & 0x04)
-			val |= 0x02;
-		if (ista & 0x08)
-			val |= 0x04;
-		if (val) {
-			hscx_int_main(cs, val);
-		}
-	}
-	if (ista & 0x20) {
-		val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe;
-		if (val) {
-			isac_interrupt(cs, val);
-		}
-	}
-	if (ista & 0x10) {
-		val = 0x01;
-		isac_interrupt(cs, val);
-	}
-	ista = readreg(cs, IPAC_ISTA);
-	if ((ista & 0x3f) && icnt) {
-		icnt--;
-		goto Start_IPAC;
-	}
-	if (!icnt)
-		printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n",
-		       CardType[cs->typ],
-		       sct_quadro_subtypes[cs->subtyp]);
-	writereg(cs, IPAC_MASK, 0xFF);
-	writereg(cs, IPAC_MASK, 0xC0);
- unlock:
-	spin_unlock(&cs->lock);
-}
-
-
-void
-release_io_sct_quadro(struct IsdnCardState *cs)
-{
-	release_region(cs->hw.ax.base & 0xffffffc0, 128);
-	if (cs->subtyp == SCT_1)
-		release_region(cs->hw.ax.plx_adr, 64);
+	ipac_write(cs, IPAC_MASK, active ? 0xc0 : 0xff);
 }
 
 static void
 enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
 {
-	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
-		if (bEnable)
-			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
-		else
-			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
-	}
+	if (bEnable)
+		wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
+	else
+		wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
 }
 
 static void
@@ -238,58 +119,49 @@
 	}
 }
 
+static void
+bkm_a8_init(struct IsdnCardState *cs)
+{
+	cs->debug |= L1_DEB_IPAC;
+	set_ipac_active(cs, 1);
+	ipac_init(cs);
+	/* Enable ints */
+	enable_bkm_int(cs, 1);
+}
+
 static int
-BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+bkm_a8_reset(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			/* Disable ints */
-			set_ipac_active(cs, 0);
-			enable_bkm_int(cs, 0);
-			reset_bkm(cs);
-			return (0);
-		case CARD_RELEASE:
-			/* Sanity */
-			set_ipac_active(cs, 0);
-			enable_bkm_int(cs, 0);
-			release_io_sct_quadro(cs);
-			return (0);
-		case CARD_INIT:
-			cs->debug |= L1_DEB_IPAC;
-			set_ipac_active(cs, 1);
-			inithscxisac(cs);
-			/* Enable ints */
-			enable_bkm_int(cs, 1);
-			return (0);
-		case CARD_TEST:
-			return (0);
-	}
-	return (0);
+	/* Disable ints */
+	set_ipac_active(cs, 0);
+	enable_bkm_int(cs, 0);
+	reset_bkm(cs);
+	return 0;
 }
 
-int __init
-sct_alloc_io(u_int adr, u_int len)
+static void
+bkm_a8_release(struct IsdnCardState *cs)
 {
-	if (!request_region(adr, len, "scitel")) {
-		printk(KERN_WARNING
-			"HiSax: Scitel port %#x-%#x already in use\n",
-			adr, adr + len);
-		return (1);
-	}
-	return(0);
+	set_ipac_active(cs, 0);
+	enable_bkm_int(cs, 0);
+	hisax_release_resources(cs);
 }
 
+static struct card_ops bkm_a8_ops = {
+	.init     = bkm_a8_init,
+	.reset    = bkm_a8_reset,
+	.release  = bkm_a8_release,
+	.irq_func = ipac_irq,
+};
+
 static struct pci_dev *dev_a8 __initdata = NULL;
 static u16  sub_vendor_id __initdata = 0;
 static u16  sub_sys_id __initdata = 0;
 static u8 pci_irq __initdata = 0;
 
-#endif /* CONFIG_PCI */
-
 int __init
 setup_sct_quadro(struct IsdnCard *card)
 {
-#if CONFIG_PCI
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u8 pci_rev_id;
@@ -298,11 +170,6 @@
 
 	strcpy(tmp, sct_quadro_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
-		cs->subtyp = SCT_1;	/* Preset */
-	} else
-		return (0);
-
 	/* Identify subtype by para[0] */
 	if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
 		cs->subtyp = card->para[0];
@@ -315,10 +182,6 @@
 		(sub_vendor_id != PCI_VENDOR_ID_BERKOM)))
 		return (0);
 	if (cs->subtyp == SCT_1) {
-		if (!pci_present()) {
-			printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
-			return (0);
-		}
 		while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX,
 			PCI_DEVICE_ID_PLX_9050, dev_a8))) {
 			
@@ -390,31 +253,31 @@
 	cs->hw.ax.plx_adr = pci_ioaddr1;
 	/* Enter all ipac_base addresses */
 	switch(cs->subtyp) {
-		case 1:
-			cs->hw.ax.base = pci_ioaddr5 + 0x00;
-			if (sct_alloc_io(pci_ioaddr1, 128))
-				return(0);
-			if (sct_alloc_io(pci_ioaddr5, 64))
-				return(0);
-			break;
-		case 2:
-			cs->hw.ax.base = pci_ioaddr4 + 0x08;
-			if (sct_alloc_io(pci_ioaddr4, 64))
-				return(0);
-			break;
-		case 3:
-			cs->hw.ax.base = pci_ioaddr3 + 0x10;
-			if (sct_alloc_io(pci_ioaddr3, 64))
-				return(0);
-			break;
-		case 4:
-			cs->hw.ax.base = pci_ioaddr2 + 0x20;
-			if (sct_alloc_io(pci_ioaddr2, 64))
-				return(0);
-			break;
+	case 1:
+		cs->hw.ax.base = pci_ioaddr5 + 0x00;
+		if (!request_io(&cs->rs, pci_ioaddr1, 128, "scitel"))
+			goto err;
+		if (!request_io(&cs->rs, pci_ioaddr5, 64, "scitel"))
+			goto err;
+		break;
+	case 2:
+		cs->hw.ax.base = pci_ioaddr4 + 0x08;
+		if (!request_io(&cs->rs, pci_ioaddr4, 64, "scitel"))
+			goto err;
+		break;
+	case 3:
+		cs->hw.ax.base = pci_ioaddr3 + 0x10;
+		if (!request_io(&cs->rs, pci_ioaddr3, 64, "scitel"))
+			goto err;
+		break;
+	case 4:
+		cs->hw.ax.base = pci_ioaddr2 + 0x20;
+		if (!request_io(&cs->rs, pci_ioaddr2, 64, "scitel"))
+			goto err;
+		break;
 	}	
 	cs->hw.ax.data_adr = cs->hw.ax.base + 4;
-	writereg(cs, IPAC_MASK, 0xFF);
+	ipac_write(cs, IPAC_MASK, 0xFF);
 
 	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
 	       CardType[card->typ],
@@ -424,19 +287,12 @@
 	       cs->hw.ax.data_adr,
 	       cs->irq);
 
-	test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-
-	cs->dc_hw_ops = &ipac_dc_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &BKM_card_msg;
-	cs->irq_func = &bkm_interrupt_ipac;
-
-	printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n",
-		CardType[card->typ],
-		sct_quadro_subtypes[cs->subtyp],
-		readreg(cs, IPAC_ID));
-	return (1);
-#else
-	printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n");
-#endif /* CONFIG_PCI */
+	cs->card_ops = &bkm_a8_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
--- a/drivers/isdn/hisax/callc.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/callc.c	Mon Jan 13 10:18:06 2003
@@ -205,13 +205,49 @@
 }
 
 static inline void
+mdl_info_setup(struct Channel *chanp)
+{
+	if (chanp->chan)
+		chanp->cs->status |=  0x0200;
+	else
+		chanp->cs->status |=  0x0100;
+
+	if (chanp->cs->card_ops->led_handler)
+		chanp->cs->card_ops->led_handler(chanp->cs);
+}
+
+static inline void
+mdl_info_connect(struct Channel *chanp)
+{
+	if (chanp->chan)
+		chanp->cs->status |=  0x2000;
+	else
+		chanp->cs->status |=  0x1000;
+
+	if (chanp->cs->card_ops->led_handler)
+		chanp->cs->card_ops->led_handler(chanp->cs);
+}
+
+static inline void
+mdl_info_release(struct Channel *chanp)
+{
+	if (chanp->chan)
+		chanp->cs->status &=  ~0x2200;
+	else
+		chanp->cs->status &=  ~0x1100;
+
+	if (chanp->cs->card_ops->led_handler)
+		chanp->cs->card_ops->led_handler(chanp->cs);
+}
+
+static void
 lli_close(struct FsmInst *fi)
 {
 	struct Channel *chanp = fi->userdata;
 
 	FsmChangeState(fi, ST_NULL);
 	chanp->Flags = 0;
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+	mdl_info_release(chanp);
 }
 
 static void
@@ -223,7 +259,8 @@
 
 	if (!chanp->leased)
 		return;
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+
+	mdl_info_setup(chanp);
 	FsmChangeState(fi, ST_IN_WAIT_LL);
 	if (chanp->debug & 1)
 		link_debug(chanp, 0, "STAT_ICALL_LEASED");
@@ -240,7 +277,7 @@
 	if (chanp->debug & 1)
 		link_debug(chanp, 1, "statcallb ret=%d", ret);
 	if (!ret) {
-		chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+		mdl_info_release(chanp);
 		FsmChangeState(fi, ST_NULL);
 	}
 }
@@ -270,7 +307,7 @@
 	FsmDelTimer(&chanp->dial_timer, 73);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = 0;
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+	mdl_info_setup(chanp);
 	if (chanp->leased) {
 		lli_init_bchan_out(fi, event, arg);
 	} else {
@@ -288,7 +325,7 @@
 	FsmDelTimer(&chanp->dial_timer, 73);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = 0;
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+	mdl_info_setup(chanp);
 	if (chanp->leased) {
 		lli_init_bchan_out(fi, event, arg);
 	} else {
@@ -316,7 +353,7 @@
 	ic.command = ISDN_STAT_BCONN;
 	ic.arg = chanp->chan;
 	chanp->cs->iif.statcallb(&ic);
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan);
+	mdl_info_connect(chanp);
 }
 
 
@@ -333,7 +370,7 @@
 	isdn_ctrl ic;
 	int ret;
 
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+	mdl_info_setup(chanp);
 	/*
 	 * Report incoming calls only once to linklevel, use CallFlags
 	 * which is set to 3 with each broadcast message in isdnl1.c
@@ -381,13 +418,13 @@
 			case 0:	/* OK, nobody likes this call */
 			default:	/* statcallb problems */
 				L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
-				chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+				mdl_info_release(chanp);
 				FsmChangeState(fi, ST_NULL);
 				break;
 		}
 	} else {
 		L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
-		chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+		mdl_info_release(chanp);
 	}
 }
 
@@ -730,7 +767,7 @@
 	chanp->cs->iif.statcallb(&ic);
 	HL_LL(chanp, ISDN_STAT_DHUP);
 	chanp->Flags = 0;
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+	mdl_info_release(chanp);
 }
 
 static void
@@ -853,10 +890,11 @@
 static void
 release_b_st(struct Channel *chanp)
 {
+	struct IsdnCardState *cs = chanp->cs;
 	struct PStack *st = chanp->b_st;
 
 	if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) {
-		chanp->bcs->BC_Close(chanp->bcs);
+		cs->bc_l1_ops->close(chanp->bcs);
 		switch (chanp->l2_active_protocol) {
 			case (ISDN_PROTO_L2_X75I):
 				releasestack_isdnl2(st);
@@ -1297,7 +1335,7 @@
 			break;
 	}
 	chanp->bcs->conmsg = NULL;
-	if (chanp->bcs->BC_SetStack(st, chanp->bcs))
+	if (cs->bc_l1_ops->open(st, chanp->bcs))
 		return (-1);
 	st->l2.flag = 0;
 	test_and_set_bit(FLG_LAPB, &st->l2.flag);
@@ -1457,12 +1495,8 @@
 
 void
 lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
-	if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
-		(cs->typ == ISDN_CTYPE_ELSA_PCI)) {
-		if (cs->hw.elsa.MFlag) {
-			cs->cardmsg(cs, CARD_AUX_IND, cm->para);
-		}
-	}
+	if (cs->card_ops->aux_ind)
+		cs->card_ops->aux_ind(cs, cm->para);
 }
 
 
diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
--- a/drivers/isdn/hisax/config.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/config.c	Mon Jan 13 10:18:07 2003
@@ -24,6 +24,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
+#include "isdnl1.h"
 #define HISAX_STATUS_BUFSIZE 4096
 #define INCLUDE_INLINE_FUNCS
 
@@ -825,9 +826,9 @@
 {
 	struct IsdnCardState *csta = cards[cardnr].cs;
 
-	if (csta->bcs->BC_Close != NULL) {
-		csta->bcs->BC_Close(csta->bcs + 1);
-		csta->bcs->BC_Close(csta->bcs);
+	if (csta->bc_l1_ops->close) {
+		csta->bc_l1_ops->close(csta->bcs + 1);
+		csta->bc_l1_ops->close(csta->bcs);
 	}
 
 	skb_queue_purge(&csta->rq);
@@ -840,11 +841,11 @@
 		dev_kfree_skb(csta->tx_skb);
 		csta->tx_skb = NULL;
 	}
-	if (csta->DC_Close != NULL) {
-		csta->DC_Close(csta);
-	}
-	if (csta->cardmsg)
-		csta->cardmsg(csta, CARD_RELEASE, NULL);
+	if (csta->dc_l1_ops->close)
+		csta->dc_l1_ops->close(csta);
+
+	if (csta->card_ops->release)
+		csta->card_ops->release(csta);
 	if (csta->dbusytimer.function != NULL) // FIXME?
 		del_timer(&csta->dbusytimer);
 	ll_unload(csta);
@@ -854,19 +855,18 @@
 {
 	int irq_cnt, cnt = 3;
 
-	if (!cs->irq)
-		return cs->cardmsg(cs, CARD_INIT, NULL);
+	cs->card_ops->init(cs);
 
 	irq_cnt = kstat_irqs(cs->irq);
 	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
 	       cs->irq, irq_cnt);
-	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
+	if (request_irq(cs->irq, cs->card_ops->irq_func, cs->irq_flags, "HiSax", cs)) {
 		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
 		       cs->irq);
 		return 1;
 	}
 	while (cnt) {
-		cs->cardmsg(cs, CARD_INIT, NULL);
+		cs->card_ops->init(cs);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		/* Timeout 10ms */
 		schedule_timeout((10 * HZ) / 1000);
@@ -880,11 +880,13 @@
 				free_irq(cs->irq, cs);
 				return 2;
 			} else {
-				cs->cardmsg(cs, CARD_RESET, NULL);
+				if (cs->card_ops->reset)
+					cs->card_ops->reset(cs);
 				cnt--;
 			}
 		} else {
-			cs->cardmsg(cs, CARD_TEST, NULL);
+			if (cs->card_ops->test)
+				cs->card_ops->test(cs);
 			return 0;
 		}
 	}
@@ -943,6 +945,7 @@
 	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
 	cs->typ = card->typ;
 	spin_lock_init(&cs->lock);
+	resources_init(&cs->rs);
 	SET_MODULE_OWNER(&cs->iif);
 	strcpy(cs->iif.id, id);
 	cs->iif.channels = 2;
@@ -1741,12 +1744,15 @@
 static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg);
 static void hisax_d_l2l1(struct PStack *st, int pr, void *arg);
 static void hisax_b_l2l1(struct PStack *st, int pr, void *arg);
-static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg);
 static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs);
 static void hisax_bc_close(struct BCState *bcs);
 static void hisax_bh(void *data);
 static void EChannel_proc_rcv(struct hisax_d_if *d_if);
 
+static struct dc_l1_ops hisax_l1_ops = {
+	.bh_func = hisax_bh,
+};
+
 int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
 		   char *name, int protocol)
 {
@@ -1775,14 +1781,13 @@
 	cs = cards[i].cs;
 	hisax_d_if->cs = cs;
 	cs->hw.hisax_d_if = hisax_d_if;
-	cs->cardmsg = hisax_cardmsg;
 	cs->iif.owner = hisax_d_if->owner; // FIXME should be done before registering
-	INIT_WORK(&cs->work, hisax_bh, cs);
+	dc_l1_init(cs, &hisax_l1_ops);
 	cs->channel[0].d_st->l1.l2l1 = hisax_d_l2l1;
-	for (i = 0; i < 2; i++) {
-		cs->bcs[i].BC_SetStack = hisax_bc_setstack;
-		cs->bcs[i].BC_Close = hisax_bc_close;
+	cs->bc_l1_ops->open = hisax_bc_setstack;
+	cs->bc_l1_ops->close = hisax_bc_close;
 
+	for (i = 0; i < 2; i++) {
 		b_if[i]->ifc.l1l2 = hisax_b_l1l2;
 
 		hisax_d_if->b_if[i] = b_if[i];
@@ -1954,11 +1959,6 @@
 	}
 }
 
-static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	return 0;
-}
-
 static void hisax_b_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct BCState *bcs = st->l1.bcs;
@@ -2047,6 +2047,100 @@
 		}
 		dev_kfree_skb_any(skb);
 	}
+}
+
+void
+resources_init(struct resources *rs)
+{
+	INIT_LIST_HEAD(&rs->res_head);
+}
+
+void
+resources_release(struct resources *rs)
+{
+	struct res *r;
+
+	list_for_each_entry(r, &rs->res_head, node) {
+		if (r->flags & IORESOURCE_IO) {
+			release_region(r->start, r->end - r->start + 1);
+		}
+		if (r->flags & IORESOURCE_MEM) {
+			iounmap(r->r_u.ioremap_addr);
+			release_mem_region(r->start, r->end - r->start + 1);
+		}
+	}
+}
+
+unsigned long
+request_io(struct resources *rs, unsigned long start, int len,
+	   const char *name)
+{
+	struct res *r;
+
+	r = kmalloc(sizeof(*r), GFP_KERNEL);
+	if (!r) {
+		printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
+		goto err;
+	}
+	if (!request_region(start, len, name)) {
+		printk(KERN_WARNING "%s: IO %#lx-%#lx already in use\n",
+		       __FUNCTION__, start, start + len - 1);
+		goto err_free;
+	}
+	r->flags = IORESOURCE_IO;
+	r->start = start;
+	r->end   = start + len - 1;
+	r->name  = name;
+	list_add_tail(&r->node, &rs->res_head);
+
+	return r->start;
+
+ err_free:
+	kfree(r);
+ err:
+	return 0;
+}
+
+void *
+request_mmio(struct resources *rs, unsigned long start, int len,
+	     const char *name)
+{
+	struct res *r;
+
+	r = kmalloc(sizeof(*r), GFP_KERNEL);
+	if (!r) {
+		printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
+		goto err;
+	}
+	if (!request_mem_region(start, len, name)) {
+		printk(KERN_WARNING "%s: MMIO %#lx-%#lx already in use\n",
+		       __FUNCTION__, start, start + len - 1);
+		goto err_free;
+	}
+	r->flags            = IORESOURCE_MEM;
+	r->start            = start;
+	r->end              = start + len - 1;
+	r->name             = name;
+	r->r_u.ioremap_addr = ioremap(start, len);
+	if (!r->r_u.ioremap_addr)
+		goto err_release;
+
+	list_add_tail(&r->node, &rs->res_head);
+
+	return r->r_u.ioremap_addr;
+
+ err_release:
+	release_mem_region(r->start, r->end - r->start + 1);
+ err_free:
+	kfree(r);
+ err:
+	return 0;
+}
+
+void
+hisax_resources_release(struct IsdnCardState *cs)
+{
+	resources_release(&cs->rs);
 }
 
 #include <linux/pci.h>
diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
--- a/drivers/isdn/hisax/diva.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/diva.c	Mon Jan 13 10:18:07 2003
@@ -164,37 +164,6 @@
 };
 
 static u8
-ipac_dc_read(struct IsdnCardState *cs, u8 offset)
-{
-	return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80);
-}
-
-static void
-ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value);
-}
-
-static void
-ipac_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
-{
-	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
-}
-
-static void
-ipac_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
-{
-	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
-}
-
-static struct dc_hw_ops ipac_dc_ops = {
-	.read_reg   = ipac_dc_read,
-	.write_reg  = ipac_dc_write,
-	.read_fifo  = ipac_dc_read_fifo,
-	.write_fifo = ipac_dc_write_fifo,
-};
-
-static u8
 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
 {
 	return readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, 
@@ -227,55 +196,65 @@
 	.write_fifo = hscx_write_fifo,
 };
 
-static u8
-mem_ipac_dc_read(struct IsdnCardState *cs, u8 offset)
+static inline u8
+ipac_read(struct IsdnCardState *cs, u8 offset)
 {
-	return memreadreg(cs->hw.diva.cfg_reg, offset+0x80);
+	return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset);
 }
 
-static void
-mem_ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value)
+static inline void
+ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
 {
-	memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value);
 }
 
-static void
-mem_ipac_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
+static inline void
+ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
 {
-	while(size--)
-		*data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80);
+	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size);
 }
 
-static void
-mem_ipac_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
+static inline void
+ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
 {
-	while(size--)
-		memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++);
+	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size);
 }
 
-static struct dc_hw_ops mem_ipac_dc_ops = {
-	.read_reg   = mem_ipac_dc_read,
-	.write_reg  = mem_ipac_dc_write,
-	.read_fifo  = mem_ipac_dc_read_fifo,
-	.write_fifo = mem_ipac_dc_write_fifo,
-};
+/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
+ * above */
 
-static u8
-mem_hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+BUILD_IPAC_OPS(ipac);
+
+static inline u8
+mem_ipac_read(struct IsdnCardState *cs, u8 offset)
 {
-	return memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0));
+	return memreadreg(cs->hw.diva.cfg_reg, offset);
 }
 
-static void
-mem_hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+static inline void
+mem_ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
 {
-	memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
+	memwritereg(cs->hw.diva.cfg_reg, offset, value);
 }
 
-static struct bc_hw_ops mem_hscx_ops = {
-	.read_reg   = mem_hscx_read,
-	.write_reg  = mem_hscx_write,
-};
+static inline void
+mem_ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+{
+	while(size--)
+		*data++ = memreadreg(cs->hw.diva.cfg_reg, offset);
+}
+
+static inline void
+mem_ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+{
+	while(size--)
+		memwritereg(cs->hw.diva.cfg_reg, offset, *data++);
+}
+
+/* This will generate mem_ipac_dc_ops and mem_ipac_bc_ops using the functions
+ * above */
+
+BUILD_IPAC_OPS(mem_ipac);
 
 /* IO-Functions for IPACX type cards */
 static u8
@@ -325,457 +304,151 @@
               (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value);
 }
 
+static void
+ipacx_bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
+{
+	int i;
+
+	for (i = 0; i < len ; i++)
+		*data++ = ipacx_bc_read(cs, hscx, IPACX_RFIFOB);
+}
+
 static struct bc_hw_ops ipacx_bc_ops = {
 	.read_reg   = ipacx_bc_read,
 	.write_reg  = ipacx_bc_write,
+	.read_fifo  = ipacx_bc_read_fifo,
 };
 
 static void
 diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val, sval;
+	u8 sval;
 	int cnt=5;
 
-	spin_lock(&cs->lock);
 	while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) {
-		val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40);
-		if (val)
-			hscx_int_main(cs, val);
-		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA);
-		if (val)
-			isac_interrupt(cs, val);
-		cnt--;
+		hscxisac_irq(intno, dev_id, regs);
 	}
 	if (!cnt)
 		printk(KERN_WARNING "Diva: IRQ LOOP\n");
-	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
-	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
-	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
-	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
-	spin_unlock(&cs->lock);
 }
 
 static void
-diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
+diva_ipac_pci_irq(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 ista,val;
-	int icnt=5;
-
-	if (!cs) {
-		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
-		return;
-	}
-	ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
-Start_IPACISA:
-	if (cs->debug & L1_DEB_IPAC)
-		debugl1(cs, "IPAC ISTA %02X", ista);
-	if (ista & 0x0f) {
-		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40);
-		if (ista & 0x01)
-			val |= 0x01;
-		if (ista & 0x04)
-			val |= 0x02;
-		if (ista & 0x08)
-			val |= 0x04;
-		if (val)
-			hscx_int_main(cs, val);
-	}
-	if (ista & 0x20) {
-		val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80);
-		if (val) {
-			isac_interrupt(cs, val);
-		}
-	}
-	if (ista & 0x10) {
-		val = 0x01;
-		isac_interrupt(cs, val);
-	}
-	ista  = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
-	if ((ista & 0x3f) && icnt) {
-		icnt--;
-		goto Start_IPACISA;
-	}
-	if (!icnt)
-		printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n");
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF);
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
-}
-
-static inline void
-MemwaitforCEC(struct IsdnCardState *cs, int hscx)
-{
-	int to = 50;
-
-	while ((mem_hscx_read(cs, hscx, HSCX_STAR) & 0x04) && to) {
-		udelay(1);
-		to--;
-	}
-	if (!to)
-		printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
-}
-
-
-static inline void
-MemwaitforXFW(struct IsdnCardState *cs, int hscx)
-{
-	int to = 50;
-
-	while ((!(mem_hscx_read(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
-		udelay(1);
-		to--;
-	}
-	if (!to)
-		printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
-}
+	u8 val;
 
-static inline void
-MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u8 data)
-{
-	unsigned long flags;
+	val = readb(cs->hw.diva.pci_cfg);
+	if (!(val & PITA_INT0_STATUS))
+		return; /* other shared IRQ */
+	writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); /* Reset pending INT0 */
 
-	spin_lock_irqsave(&diva_lock, flags);
-	MemwaitforCEC(cs, hscx);
-	mem_hscx_write(cs, hscx, HSCX_CMDR, data);
-	spin_unlock_irqrestore(&diva_lock, flags);
+	ipac_irq(intno, dev_id, regs);
 }
 
 static void
-Memhscx_empty_fifo(struct BCState *bcs, int count)
+diva_ipacx_pci_irq(int intno, void *dev_id, struct pt_regs *regs)
 {
-	u8 *ptr;
-	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
-	int cnt;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hscx_empty_fifo");
+	struct IsdnCardState *cs = dev_id;
+	u8 val;
 
-	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
-		MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
-		bcs->hw.hscx.rcvidx = 0;
-		return;
-	}
-	spin_lock_irqsave(&diva_lock, flags);
-	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
-	cnt = count;
-	while (cnt--)
-		*ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
-	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
-	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
-	bcs->hw.hscx.rcvidx += count;
-	spin_unlock_irqrestore(&diva_lock, flags);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
-			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
+	val = readb(cs->hw.diva.pci_cfg);
+	if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ
+	interrupt_ipacx(cs);      // handler for chip
+	writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg);  // Reset PLX interrupt
 }
 
 static void
-Memhscx_fill_fifo(struct BCState *bcs)
+diva_release(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = bcs->cs;
-	int more, count;
-	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
-	unsigned char *p;
-
-	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
-	if (!p)
-		return;
-
-	MemwaitforXFW(cs, bcs->hw.hscx.hscx);
-	while (count--)
-		memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
-			*p++);
-	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
-}
-
-static struct bc_l1_ops mem_hscx_l1_ops = {
-	.fill_fifo = Memhscx_fill_fifo,
-};
+	del_timer(&cs->hw.diva.tl);
+	if (cs->hw.diva.cfg_reg)
+		byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
 
-static inline void
-Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
-{
-	u8 r;
-	struct BCState *bcs = cs->bcs + hscx;
-	struct sk_buff *skb;
-	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
-	int count;
-
-	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
-		return;
-
-	if (val & 0x80) {	/* RME */
-		r = mem_hscx_read(cs, hscx, HSCX_RSTA);
-		if ((r & 0xf0) != 0xa0) {
-			if (!(r & 0x80))
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, "HSCX invalid frame");
-			if ((r & 0x40) && bcs->mode)
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, "HSCX RDO mode=%d",
-						bcs->mode);
-			if (!(r & 0x20))
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, "HSCX CRC error");
-			MemWriteHSCXCMDR(cs, hscx, 0x80);
-		} else {
-			count = mem_hscx_read(cs, hscx, HSCX_RBCL) & (
-				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
-			if (count == 0)
-				count = fifo_size;
-			Memhscx_empty_fifo(bcs, count);
-			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
-				if (cs->debug & L1_DEB_HSCX_FIFO)
-					debugl1(cs, "HX Frame %d", count);
-				if (!(skb = dev_alloc_skb(count)))
-					printk(KERN_WARNING "HSCX: receive out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
-					skb_queue_tail(&bcs->rqueue, skb);
-				}
-			}
-		}
-		bcs->hw.hscx.rcvidx = 0;
-		sched_b_event(bcs, B_RCVBUFREADY);
-	}
-	if (val & 0x40) {	/* RPF */
-		Memhscx_empty_fifo(bcs, fifo_size);
-		if (bcs->mode == L1_MODE_TRANS) {
-			/* receive audio data */
-			if (!(skb = dev_alloc_skb(fifo_size)))
-				printk(KERN_WARNING "HiSax: receive out of memory\n");
-			else {
-				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
-				skb_queue_tail(&bcs->rqueue, skb);
-			}
-			bcs->hw.hscx.rcvidx = 0;
-			sched_b_event(bcs, B_RCVBUFREADY);
-		}
-	}
-	if (val & 0x10) {
-		xmit_xpr_b(bcs);/* XPR */
-	}
+	hisax_release_resources(cs);
 }
 
 static void
-Memhscx_reset_xmit(struct BCState *bcs)
+diva_ipac_pci_release(struct IsdnCardState *cs)
 {
-	MemWriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01);
+	writel(0, cs->hw.diva.pci_cfg); /* disable INT0/1 */ 
+	writel(2, cs->hw.diva.pci_cfg); /* reset pending INT0 */
+	hisax_release_resources(cs);
 }
 
-static inline void
-Memhscx_int_main(struct IsdnCardState *cs, u8 val)
-{
-
-	u8 exval;
-	struct BCState *bcs;
-
-	if (val & 0x01) { // EXB
-		bcs = cs->bcs + 1;
-		exval = mem_hscx_read(cs, 1, HSCX_EXIR);
-		if (exval & 0x40) {
-			if (cs->debug & L1_DEB_HSCX)
-				debugl1(cs, "HSCX B EXIR %x", exval);
-			xmit_xdu_b(bcs, Memhscx_reset_xmit);
-		}
-	}
-	if (val & 0xf8) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX B interrupt %x", val);
-		Memhscx_interrupt(cs, val, 1);
-	}
-	if (val & 0x02) {	// EXA
-		bcs = cs->bcs;
-		exval = mem_hscx_read(cs, 0, HSCX_EXIR);
-		if (exval & 0x40) {
-			if (cs->debug & L1_DEB_HSCX)
-				debugl1(cs, "HSCX A EXIR %x", exval);
-			xmit_xdu_b(bcs, Memhscx_reset_xmit);
-		}
-	}
-	if (val & 0x04) {	// ICA
-		exval = mem_hscx_read(cs, 0, HSCX_ISTA);
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX A interrupt %x", exval);
-		Memhscx_interrupt(cs, exval, 0);
-	}
-}
-
-static void
-diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
+static int
+diva_ipac_isa_reset(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = dev_id;
-	u8 ista,val;
-	int icnt=5;
-	u8 *cfg;
-
-	if (!cs) {
-		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
-		return;
-	}
-	cfg = (u8 *) cs->hw.diva.pci_cfg;
-	val = *cfg;
-	if (!(val & PITA_INT0_STATUS))
-		return; /* other shared IRQ */
-	*cfg = PITA_INT0_STATUS; /* Reset pending INT0 */
-	ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
-Start_IPACPCI:
-	if (cs->debug & L1_DEB_IPAC)
-		debugl1(cs, "IPAC ISTA %02X", ista);
-	if (ista & 0x0f) {
-		val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40);
-		if (ista & 0x01)
-			val |= 0x01;
-		if (ista & 0x04)
-			val |= 0x02;
-		if (ista & 0x08)
-			val |= 0x04;
-		if (val)
-			Memhscx_int_main(cs, val);
-	}
-	if (ista & 0x20) {
-		val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80);
-		if (val) {
-			isac_interrupt(cs, val);
-		}
-	}
-	if (ista & 0x10) {
-		val = 0x01;
-		isac_interrupt(cs, val);
-	}
-	ista  = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
-	if ((ista & 0x3f) && icnt) {
-		icnt--;
-		goto Start_IPACPCI;
-	}
-	if (!icnt)
-		printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n");
-	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF);
-	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
+	return 0;
 }
 
-static void
-diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs)
+static int
+diva_ipac_pci_reset(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
-	u8 *cfg;
+	unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG;
 
-	if (!cs) {
-		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
-		return;
-	}
-	cfg = (u8 *) cs->hw.diva.pci_cfg;
-	val = *cfg;
-	if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ
-	interrupt_ipacx(cs);      // handler for chip
-	*cfg = PITA_INT0_STATUS;  // Reset PLX interrupt
+	writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writel(PITA_PARA_MPX_MODE, misc_reg);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
+	return 0;
 }
 
-void
-release_io_diva(struct IsdnCardState *cs)
+static int
+diva_ipacx_pci_reset(struct IsdnCardState *cs)
 {
-	int bytecnt;
+	unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG;
 
-	if ((cs->subtyp == DIVA_IPAC_PCI) || 
-	    (cs->subtyp == DIVA_IPACX_PCI)   ) {
-		u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
-
-		*cfg = 0; /* disable INT0/1 */ 
-		*cfg = 2; /* reset pending INT0 */
-		iounmap((void *)cs->hw.diva.cfg_reg);
-		iounmap((void *)cs->hw.diva.pci_cfg);
-		return;
-	} else if (cs->subtyp != DIVA_IPAC_ISA) {
-		del_timer(&cs->hw.diva.tl);
-		if (cs->hw.diva.cfg_reg)
-			byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
-	}
-	if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))
-		bytecnt = 8;
-	else
-		bytecnt = 32;
-	if (cs->hw.diva.cfg_reg) {
-		release_region(cs->hw.diva.cfg_reg, bytecnt);
-	}
+	writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET, misc_reg);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	ipacx_dc_write(cs, IPACX_MASK, 0xff); // Interrupts off
+	return 0;
 }
 
-static void
-reset_diva(struct IsdnCardState *cs)
+static int
+diva_reset(struct IsdnCardState *cs)
 {
-	if (cs->subtyp == DIVA_IPAC_ISA) {
-		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
-	} else if (cs->subtyp == DIVA_IPAC_PCI) {
-		unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
-					PITA_MISC_REG);
-		*ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		*ireg = PITA_PARA_MPX_MODE;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
-	} else if (cs->subtyp == DIVA_IPACX_PCI) {
-		unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
-					PITA_MISC_REG);
-		*ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		*ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		ipacx_dc_write(cs, IPACX_MASK, 0xff); // Interrupts off
-	} else { /* DIVA 2.0 */
-		cs->hw.diva.ctrl_reg = 0;        /* Reset On */
-		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
-		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		if (cs->subtyp == DIVA_ISA)
-			cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
-		else {
-			/* Workaround PCI9060 */
-			byteout(cs->hw.diva.pci_cfg + 0x69, 9);
-			cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
-		}
-		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+	/* DIVA 2.0 */
+	cs->hw.diva.ctrl_reg = 0;        /* Reset On */
+	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
+	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	if (cs->subtyp == DIVA_ISA) {
+		cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
+	} else {
+		/* Workaround PCI9060 */
+		byteout(cs->hw.diva.pci_cfg + 0x69, 9);
+		cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
 	}
+	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+	return 0;
 }
 
-#define DIVA_ASSIGN 1
-
 static void
 diva_led_handler(struct IsdnCardState *cs)
 {
 	int blink = 0;
 
-//	if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI))
-	if ((cs->subtyp == DIVA_IPAC_ISA) ||
-	    (cs->subtyp == DIVA_IPAC_PCI) ||
-	    (cs->subtyp == DIVA_IPACX_PCI)   )
-		return;
-	del_timer(&cs->hw.diva.tl);
-	if (cs->hw.diva.status & DIVA_ASSIGN)
+	if (cs->status & 0x0001)
 		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_A : DIVA_PCI_LED_A;
 	else {
@@ -783,10 +456,10 @@
 			DIVA_ISA_LED_A : DIVA_PCI_LED_A;
 		blink = 250;
 	}
-	if (cs->hw.diva.status & 0xf000)
+	if (cs->status & 0xf000)
 		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
-	else if (cs->hw.diva.status & 0x0f00) {
+	else if (cs->status & 0x0f00) {
 		cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
 		blink = 500;
@@ -795,75 +468,53 @@
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B);
 
 	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-	if (blink) {
-		init_timer(&cs->hw.diva.tl);
-		cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000);
-		add_timer(&cs->hw.diva.tl);
-	}
+	if (blink)
+		mod_timer(&cs->hw.diva.tl, jiffies + (blink * HZ) / 1000);
 }
 
-static int
-Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+diva_ipacx_pci_init(struct IsdnCardState *cs)
 {
-	u_int *ireg;
+	writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg);
+	init_ipacx(cs, 3); // init chip and enable interrupts
+}
 
-	switch (mt) {
-		case CARD_RESET:
-			reset_diva(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_diva(cs);
-			return(0);
-		case CARD_INIT:
-			if (cs->subtyp == DIVA_IPACX_PCI) {
-				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
-				*ireg = PITA_INT0_ENABLE;
-			  init_ipacx(cs, 3); // init chip and enable interrupts
-        return (0);
-			}
-			if (cs->subtyp == DIVA_IPAC_PCI) {
-				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
-				*ireg = PITA_INT0_ENABLE;
-			}
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-		case (MDL_REMOVE | REQUEST):
-			cs->hw.diva.status = 0;
-			break;
-		case (MDL_ASSIGN | REQUEST):
-			cs->hw.diva.status |= DIVA_ASSIGN;
-			break;
-		case MDL_INFO_SETUP:
-			if ((long)arg)
-				cs->hw.diva.status |=  0x0200;
-			else
-				cs->hw.diva.status |=  0x0100;
-			break;
-		case MDL_INFO_CONN:
-			if ((long)arg)
-				cs->hw.diva.status |=  0x2000;
-			else
-				cs->hw.diva.status |=  0x1000;
-			break;
-		case MDL_INFO_REL:
-			if ((long)arg) {
-				cs->hw.diva.status &=  ~0x2000;
-				cs->hw.diva.status &=  ~0x0200;
-			} else {
-				cs->hw.diva.status &=  ~0x1000;
-				cs->hw.diva.status &=  ~0x0100;
-			}
-			break;
-	}
-	if ((cs->subtyp != DIVA_IPAC_ISA) && 
-	    (cs->subtyp != DIVA_IPAC_PCI) &&
-	    (cs->subtyp != DIVA_IPACX_PCI)   )
-		diva_led_handler(cs);
-	return(0);
+static void
+diva_ipac_pci_init(struct IsdnCardState *cs)
+{
+	writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg);
+	ipac_init(cs);
 }
 
+static struct card_ops diva_ops = {
+	.init        = inithscxisac,
+	.reset       = diva_reset,
+	.release     = diva_release,
+	.led_handler = diva_led_handler,
+	.irq_func    = diva_interrupt,
+};
+
+static struct card_ops diva_ipac_isa_ops = {
+	.init        = ipac_init,
+	.reset       = diva_ipac_isa_reset,
+	.release     = hisax_release_resources,
+	.irq_func    = ipac_irq,
+};
+
+static struct card_ops diva_ipac_pci_ops = {
+	.init        = diva_ipac_pci_init,
+	.reset       = diva_ipac_pci_reset,
+	.release     = diva_ipac_pci_release,
+	.irq_func    = diva_ipac_pci_irq,
+};
+
+static struct card_ops diva_ipacx_pci_ops = {
+	.init        = diva_ipacx_pci_init,
+	.reset       = diva_ipacx_pci_reset,
+	.release     = diva_ipac_pci_release,
+	.irq_func    = diva_ipacx_pci_irq,
+};
+
 static struct pci_dev *dev_diva __initdata = NULL;
 static struct pci_dev *dev_diva_u __initdata = NULL;
 static struct pci_dev *dev_diva201 __initdata = NULL;
@@ -891,7 +542,7 @@
 };
 
 static struct isapnp_device_id *pdev = &diva_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 
@@ -905,9 +556,6 @@
 
 	strcpy(tmp, Diva_revision);
 	printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_DIEHLDIVA)
-		return(0);
-	cs->hw.diva.status = 0;
 	if (card->para[1]) {
 		cs->hw.diva.ctrl_reg = 0;
 		cs->hw.diva.cfg_reg = card->para[1];
@@ -921,7 +569,6 @@
 			cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
 			cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
 			cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
-			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
 		} else {
 			cs->subtyp = DIVA_ISA;
 			cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
@@ -934,31 +581,38 @@
 	} else {
 #ifdef __ISAPNP__
 		if (isapnp_present()) {
-			struct pci_bus *pb;
-			struct pci_dev *pd;
+			struct pnp_card *pb;
+			struct pnp_dev *pd;
 
 			while(pdev->card_vendor) {
-				if ((pb = isapnp_find_card(pdev->card_vendor,
-					pdev->card_device, pnp_c))) {
+				if ((pb = pnp_find_card(pdev->card_vendor,
+							pdev->card_device,
+							pnp_c))) {
 					pnp_c = pb;
 					pd = NULL;
-					if ((pd = isapnp_find_dev(pnp_c,
-						pdev->vendor, pdev->function, pd))) {
+					if ((pd = pnp_find_dev(pnp_c,
+							       pdev->vendor,
+							       pdev->function,
+							       pd))) {
 						printk(KERN_INFO "HiSax: %s detected\n",
 							(char *)pdev->driver_data);
-						pd->prepare(pd);
-						pd->deactivate(pd);
-						pd->activate(pd);
-						card->para[1] =
-							pd->resource[0].start;
-						card->para[0] =
-							pd->irq_resource[0].start;
-						if (!card->para[0] || !card->para[1]) {
+						if (pnp_device_attach(pd) < 0) {
+							printk(KERN_ERR "Diva PnP: attach failed\n");
+							return 0;
+						}
+						if (pnp_activate_dev(pd, NULL) < 0) {
+							printk(KERN_ERR "Diva PnP: activate failed\n");
+							pnp_device_detach(pd);
+							return 0;
+						}
+						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
 							printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
-								card->para[0], card->para[1]);
-							pd->deactivate(pd);
+								pnp_irq(pd, 0), pnp_port_start(pd, 0));
+							pnp_device_detach(pd);
 							return(0);
 						}
+						card->para[1] = pnp_port_start(pd, 0);
+						card->para[0] = pnp_irq(pd, 0);
 						cs->hw.diva.cfg_reg  = card->para[1];
 						cs->irq = card->para[0];
 						if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
@@ -972,7 +626,6 @@
 								card->para[1] + DIVA_IPAC_ADR;
 							cs->hw.diva.hscx_adr =
 								card->para[1] + DIVA_IPAC_ADR;
-							test_and_set_bit(HW_IPAC, &cs->HW_Flags);
 						} else {
 							cs->subtyp = DIVA_ISA;
 							cs->hw.diva.ctrl =
@@ -1001,11 +654,6 @@
 		}
 #endif
 #if CONFIG_PCI
-		if (!pci_present()) {
-			printk(KERN_ERR "Diva: no PCI bus present\n");
-			return(0);
-		}
-
 		cs->subtyp = 0;
 		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
 			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
@@ -1027,10 +675,8 @@
 				return(0);
 			cs->subtyp = DIVA_IPAC_PCI;
 			cs->irq = dev_diva201->irq;
-			cs->hw.diva.pci_cfg =
-				(ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
-			cs->hw.diva.cfg_reg =
-				(ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
+			cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva");
+			cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva");
 		} else {
 			printk(KERN_WARNING "Diva: No PCI card found\n");
 			return(0);
@@ -1038,18 +684,14 @@
 
 		if (!cs->irq) {
 			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
-			return(0);
+			goto err;
 		}
 
 		if (!cs->hw.diva.cfg_reg) {
 			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
-			return(0);
+			goto err;
 		}
 		cs->irq_flags |= SA_SHIRQ;
-#else
-		printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
-		printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
-		return (0);
 #endif /* CONFIG_PCI */
 		if ((cs->subtyp == DIVA_IPAC_PCI) ||
 		    (cs->subtyp == DIVA_IPACX_PCI)   ) {
@@ -1058,7 +700,6 @@
 			cs->hw.diva.hscx = 0;
 			cs->hw.diva.isac_adr = 0;
 			cs->hw.diva.hscx_adr = 0;
-			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
 			bytecnt = 0;
 		} else {
 			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
@@ -1086,51 +727,36 @@
 			cs->hw.diva.pci_cfg);
 	if ((cs->subtyp != DIVA_IPAC_PCI) &&
 	    (cs->subtyp != DIVA_IPACX_PCI)   ) {
-		if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
-			printk(KERN_WARNING
-			       "HiSax: %s config port %lx-%lx already in use\n",
-			       CardType[card->typ],
-			       cs->hw.diva.cfg_reg,
-			       cs->hw.diva.cfg_reg + bytecnt);
-			return (0);
-		} else {
-			request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn");
-		}
+		if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn"))
+			return 0;
 	}
-	reset_diva(cs);
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &Diva_card_msg;
 	if (cs->subtyp == DIVA_IPAC_ISA) {
-		cs->dc_hw_ops = &ipac_dc_ops;
-		cs->irq_func = &diva_irq_ipac_isa;
-		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);
-		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+		diva_ipac_isa_reset(cs);
+		cs->card_ops = &diva_ipac_isa_ops;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
 	} else if (cs->subtyp == DIVA_IPAC_PCI) {
-		cs->dc_hw_ops = &mem_ipac_dc_ops;
-		cs->bc_hw_ops = &mem_hscx_ops;
-		cs->bc_l1_ops = &mem_hscx_l1_ops;
-		cs->irq_func = &diva_irq_ipac_pci;
-		val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
-		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+		diva_ipac_pci_reset(cs);
+		cs->card_ops = &diva_ipac_pci_ops;
+		if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
+			goto err;
 	} else if (cs->subtyp == DIVA_IPACX_PCI) {
-		cs->dc_hw_ops = &ipacx_dc_ops;
-		cs->bc_hw_ops = &ipacx_bc_ops;
-		cs->irq_func = &diva_irq_ipacx_pci;
-		printk(KERN_INFO "Diva: IPACX Design Id: %x\n", 
-		       ipacx_dc_read(cs, IPACX_ID) &0x3F);
+		diva_ipacx_pci_reset(cs);
+		cs->card_ops = &diva_ipacx_pci_ops;
+		if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
+			goto err;
 	} else { /* DIVA 2.0 */
+		diva_reset(cs);
 		cs->hw.diva.tl.function = (void *) diva_led_handler;
 		cs->hw.diva.tl.data = (long) cs;
 		init_timer(&cs->hw.diva.tl);
-		cs->dc_hw_ops = &isac_ops;
-		cs->irq_func = &diva_interrupt;
-		ISACVersion(cs, "Diva:");
-		if (HscxVersion(cs, "Diva:")) {
-			printk(KERN_WARNING
-		       "Diva: wrong HSCX versions check IO address\n");
-			release_io_diva(cs);
-			return (0);
-		}
-	}
-	return (1);
+		cs->card_ops = &diva_ops;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
+	}
+	return 1;
+ err:
+	diva_release(cs);
+	return 0;
+
 }
diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
--- a/drivers/isdn/hisax/elsa.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/elsa.c	Mon Jan 13 10:18:05 2003
@@ -106,7 +106,6 @@
 /* Status Flags */
 #define ELSA_TIMER_AKTIV 1
 #define ELSA_BAD_PWR     2
-#define ELSA_ASSIGN      4
 
 #define RS_ISR_PASS_LIMIT 256
 #define _INLINE_ inline
@@ -212,37 +211,6 @@
 };
 
 static u8
-ipac_dc_read(struct IsdnCardState *cs, u8 offset)
-{
-	return readreg(cs, cs->hw.elsa.isac, offset+0x80);
-}
-
-static void
-ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	writereg(cs, cs->hw.elsa.isac, offset|0x80, value);
-}
-
-static void
-ipac_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
-{
-	readfifo(cs, cs->hw.elsa.isac, 0x80, data, size);
-}
-
-static void
-ipac_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
-{
-	writefifo(cs, cs->hw.elsa.isac, 0x80, data, size);
-}
-
-static struct dc_hw_ops ipac_dc_ops = {
-	.read_reg   = ipac_dc_read,
-	.write_reg  = ipac_dc_write,
-	.read_fifo  = ipac_dc_read_fifo,
-	.write_fifo = ipac_dc_write_fifo,
-};
-
-static u8
 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
 {
 	return readreg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0));
@@ -274,6 +242,35 @@
 };
 
 static inline u8
+ipac_read(struct IsdnCardState *cs, u8 offset)
+{
+	return readreg(cs, cs->hw.elsa.isac, offset);
+}
+
+static inline void
+ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+{
+	writereg(cs, cs->hw.elsa.isac, offset, value);
+}
+
+static inline void
+ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+{
+	readfifo(cs, cs->hw.elsa.isac, offset, data, size);
+}
+
+static inline void
+ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+{
+	writefifo(cs, cs->hw.elsa.isac, offset, data, size);
+}
+
+/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
+ * above */
+
+BUILD_IPAC_OPS(ipac);
+
+static inline u8
 readitac(struct IsdnCardState *cs, u8 off)
 {
 	u8 ret;
@@ -315,53 +312,26 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u8 val;
-	int icnt=5;
 
-	spin_lock(&cs->lock);
 	if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
 	/* The card tends to generate interrupts while being removed
 	   causing us to just crash the kernel. bad. */
 		printk(KERN_WARNING "Elsa: card not available!\n");
-		goto unlock;
+		return;
 	}
 #if ARCOFI_USE
 	if (cs->hw.elsa.MFlag) {
 		val = serial_inp(cs, UART_IIR);
 		if (!(val & UART_IIR_NO_INT)) {
 			debugl1(cs,"IIR %02x", val);
+			spin_lock(&cs->lock);
 			rs_interrupt_elsa(intno, cs);
+			spin_unlock(&cs->lock);
 		}
 	}
 #endif
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val) {
-		hscx_int_main(cs, val);
-	}
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val) {
-		isac_interrupt(cs, val);
-	}
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val && icnt) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		icnt--;
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val && icnt) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		icnt--;
-		goto Start_ISAC;
-	}
-	if (!icnt)
-		printk(KERN_WARNING"ELSA IRQ LOOP\n");
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
+	hscxisac_irq(intno, dev_id, regs);
+
 	if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) {
 		if (!TimerRun(cs)) {
 			/* Timer Restart */
@@ -381,19 +351,13 @@
 #endif
 	if (cs->hw.elsa.trig)
 		byteout(cs->hw.elsa.trig, 0x00);
-	hscx_write(cs, 0, HSCX_MASK, 0x00);
-	hscx_write(cs, 1, HSCX_MASK, 0x00);
-	isac_write(cs, ISAC_MASK, 0x00);
- unlock:
-	spin_unlock(&cs->lock);
 }
 
 static void
 elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 ista,val;
-	int icnt=5;
+	u8 val;
 
 	if (!cs) {
 		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
@@ -410,51 +374,18 @@
 		val = serial_inp(cs, UART_IIR);
 		if (!(val & UART_IIR_NO_INT)) {
 			debugl1(cs,"IIR %02x", val);
+			spin_lock(&cs->lock);
 			rs_interrupt_elsa(intno, cs);
+			spin_unlock(&cs->lock);
 		}
 	}
 #endif
-	ista = readreg(cs, cs->hw.elsa.isac, IPAC_ISTA);
-Start_IPAC:
-	if (cs->debug & L1_DEB_IPAC)
-		debugl1(cs, "IPAC ISTA %02X", ista);
-	if (ista & 0x0f) {
-		val = hscx_read(cs, 1, HSCX_ISTA);
-		if (ista & 0x01)
-			val |= 0x01;
-		if (ista & 0x04)
-			val |= 0x02;
-		if (ista & 0x08)
-			val |= 0x04;
-		if (val)
-			hscx_int_main(cs, val);
-	}
-	if (ista & 0x20) {
-		val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe;
-		if (val) {
-			isac_interrupt(cs, val);
-		}
-	}
-	if (ista & 0x10) {
-		val = 0x01;
-		isac_interrupt(cs, val);
-	}
-	ista  = readreg(cs, cs->hw.elsa.isac, IPAC_ISTA);
-	if ((ista & 0x3f) && icnt) {
-		icnt--;
-		goto Start_IPAC;
-	}
-	if (!icnt)
-		printk(KERN_WARNING "ELSA IRQ LOOP\n");
-	writereg(cs, cs->hw.elsa.isac, IPAC_MASK, 0xFF);
-	writereg(cs, cs->hw.elsa.isac, IPAC_MASK, 0xC0);
+	ipac_irq(intno, dev_id, regs);
 }
 
-void
-release_io_elsa(struct IsdnCardState *cs)
+static void
+elsa_release(struct IsdnCardState *cs)
 {
-	int bytecnt = 8;
-
 	del_timer(&cs->hw.elsa.tl);
 #if ARCOFI_USE
 	clear_arcofi(cs);
@@ -464,32 +395,27 @@
 	if (cs->subtyp == ELSA_QS1000PCI) {
 		byteout(cs->hw.elsa.cfg + 0x4c, 0x01);  /* disable IRQ */
 		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff);
-		bytecnt = 2;
-		release_region(cs->hw.elsa.cfg, 0x80);
 	}
 	if (cs->subtyp == ELSA_QS3000PCI) {
 		byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */
 		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff);
-		release_region(cs->hw.elsa.cfg, 0x80);
 	}
  	if (cs->subtyp == ELSA_PCMCIA_IPAC) {
 		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff);
  	}
+#if ARCOFI_USE
 	if ((cs->subtyp == ELSA_PCFPRO) ||
 		(cs->subtyp == ELSA_QS3000) ||
 		(cs->subtyp == ELSA_PCF) ||
 		(cs->subtyp == ELSA_QS3000PCI)) {
-		bytecnt = 16;
-#if ARCOFI_USE
 		release_modem(cs);
-#endif
 	}
-	if (cs->hw.elsa.base)
-		release_region(cs->hw.elsa.base, bytecnt);
+#endif
+	hisax_release_resources(cs);
 }
 
-static void
-reset_elsa(struct IsdnCardState *cs)
+static int
+elsa_reset(struct IsdnCardState *cs)
 {
 	if (cs->hw.elsa.timer) {
 		/* Wait 1 Timer */
@@ -531,6 +457,7 @@
 		else if (cs->subtyp == ELSA_QS3000PCI)
 			byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */
 	}
+	return 0;
 }
 
 #if ARCOFI_USE
@@ -597,28 +524,14 @@
 				"Elsa: %s detected modem at 0x%lx\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
-			release_region(cs->hw.elsa.base, 8);
-			if (!request_region(cs->hw.elsa.base, 16,"elsa isdn modem")) {
-				printk(KERN_WARNING
-				"HiSax: %s config port %lx-%lx already in use\n",
-				Elsa_Types[cs->subtyp],
-				cs->hw.elsa.base + 8,
-				cs->hw.elsa.base + 16);
-			}
+			request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem");
 		} else if (cs->subtyp==ELSA_PCC16) {
 			cs->subtyp = ELSA_PCF;
 			printk(KERN_INFO
 				"Elsa: %s detected modem at 0x%lx\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
-			release_region(cs->hw.elsa.base, 8);
-			if (!request_region(cs->hw.elsa.base, 16,"elsa isdn modem")) {
-				printk(KERN_WARNING
-				"HiSax: %s config port %lx-%lx already in use\n",
-				Elsa_Types[cs->subtyp],
-				cs->hw.elsa.base + 8,
-				cs->hw.elsa.base + 16);
-			}
+			request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem");
 		} else
 			printk(KERN_INFO
 				"Elsa: %s detected modem at 0x%lx\n",
@@ -639,8 +552,15 @@
 
 	if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC)
 		return;
-	del_timer(&cs->hw.elsa.tl);
-	if (cs->hw.elsa.status & ELSA_ASSIGN)
+
+	if (cs->typ == ISDN_CTYPE_ELSA) {
+		int pwr = bytein(cs->hw.elsa.ale);
+		if (pwr & 0x08)
+			cs->hw.elsa.status |= ELSA_BAD_PWR;
+		else
+			cs->hw.elsa.status &= ~ELSA_BAD_PWR;
+	}
+	if (cs->status & 0x0001)
 		cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED;
 	else if (cs->hw.elsa.status & ELSA_BAD_PWR)
 		cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED;
@@ -648,9 +568,9 @@
 		cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED;
 		blink = 250;
 	}
-	if (cs->hw.elsa.status & 0xf000)
+	if (cs->status & 0xf000)
 		cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED;
-	else if (cs->hw.elsa.status & 0x0f00) {
+	else if (cs->status & 0x0f00) {
 		cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED;
 		blink = 500;
 	} else
@@ -666,128 +586,110 @@
 		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, led);
 	} else
 		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
-	if (blink) {
-		init_timer(&cs->hw.elsa.tl);
-		cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000);
-		add_timer(&cs->hw.elsa.tl);
-	}
-}
 
-static int
-Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	int ret = 0;
+	if (blink)
+		mod_timer(&cs->hw.elsa.tl, jiffies + (blink * HZ) / 1000);
+}
 
-	switch (mt) {
-		case CARD_RESET:
-			reset_elsa(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_elsa(cs);
-			return(0);
-		case CARD_INIT:
-			cs->debug |= L1_DEB_IPAC;
-			if ((cs->subtyp == ELSA_QS1000) ||
-			    (cs->subtyp == ELSA_QS3000))
-			{
-				byteout(cs->hw.elsa.timer, 0);
-			}
-			if (cs->hw.elsa.trig)
-				byteout(cs->hw.elsa.trig, 0xff);
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			if ((cs->subtyp == ELSA_PCMCIA) ||
-				(cs->subtyp == ELSA_PCMCIA_IPAC) ||
-				(cs->subtyp == ELSA_QS1000PCI)) {
-				return(0);
-			} else if (cs->subtyp == ELSA_QS3000PCI) {
-				ret = 0;
-			} else {
-				cs->hw.elsa.counter = 0;
-				cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT;
-				cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
-				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
-				byteout(cs->hw.elsa.timer, 0);
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout((110*HZ)/1000);
-				cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
-				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
-				cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
-				printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
-				       cs->hw.elsa.counter);
-				if ((cs->hw.elsa.counter > 10) &&
-					(cs->hw.elsa.counter < 16)) {
-					printk(KERN_INFO "Elsa: timer and irq OK\n");
-					ret = 0;
-				} else {
-					printk(KERN_WARNING
-					       "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
-					       cs->hw.elsa.counter, cs->irq);
-					ret = 1;
-				}
-			}
-#if ARCOFI_USE
-			if (check_arcofi(cs)) {
-				init_modem(cs);
-			}
-#endif
-			elsa_led_handler(cs);
-			return(ret);
-		case (MDL_REMOVE | REQUEST):
-			cs->hw.elsa.status &= 0;
-			break;
-		case (MDL_ASSIGN | REQUEST):
-			cs->hw.elsa.status |= ELSA_ASSIGN;
-			break;
-		case MDL_INFO_SETUP:
-			if ((long) arg)
-				cs->hw.elsa.status |= 0x0200;
-			else
-				cs->hw.elsa.status |= 0x0100;
-			break;
-		case MDL_INFO_CONN:
-			if ((long) arg)
-				cs->hw.elsa.status |= 0x2000;
-			else
-				cs->hw.elsa.status |= 0x1000;
-			break;
-		case MDL_INFO_REL:
-			if ((long) arg) {
-				cs->hw.elsa.status &= ~0x2000;
-				cs->hw.elsa.status &= ~0x0200;
-			} else {
-				cs->hw.elsa.status &= ~0x1000;
-				cs->hw.elsa.status &= ~0x0100;
-			}
-			break;
 #if ARCOFI_USE
-		case CARD_AUX_IND:
-			if (cs->hw.elsa.MFlag) {
-				int len;
-				u8 *msg;
-
-				if (!arg)
-					return(0);
-				msg = arg;
-				len = *msg;
-				msg++;
-				modem_write_cmd(cs, msg, len);
-			}
-			break;
+static void
+elsa_aux_ind(struct IsdnCardState *cs, void *arg)
+{
+	 if (cs->hw.elsa.MFlag) {
+		 int len;
+		 u8 *msg;
+		 
+		 if (!arg)
+			 return;
+		 msg = arg;
+		 len = *msg;
+		 msg++;
+		 modem_write_cmd(cs, msg, len);
+	 }
+}
+#else
+#define elsa_aux_ind NULL
 #endif
+
+static void
+elsa_init(struct IsdnCardState *cs)
+{
+	if (cs->subtyp == ELSA_QS1000 || cs->subtyp == ELSA_QS3000)
+		byteout(cs->hw.elsa.timer, 0);
+
+	if (cs->hw.elsa.trig)
+		byteout(cs->hw.elsa.trig, 0xff);
+
+	inithscxisac(cs);
+}
+
+static void
+elsa_ipac_init(struct IsdnCardState *cs)
+{
+	if (cs->hw.elsa.trig)
+		byteout(cs->hw.elsa.trig, 0xff);
+
+	ipac_init(cs);
+}
+
+static void
+elsa_test(struct IsdnCardState *cs)
+{
+	if ((cs->subtyp == ELSA_PCMCIA) ||
+	    (cs->subtyp == ELSA_PCMCIA_IPAC) ||
+	    (cs->subtyp == ELSA_QS1000PCI)) {
+		return;
+	} 
+	if (cs->subtyp != ELSA_QS3000PCI) {
+		cs->hw.elsa.counter = 0;
+		cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT;
+		cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
+		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+		byteout(cs->hw.elsa.timer, 0);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout((110*HZ)/1000);
+		cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
+		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+		cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
+		printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
+		       cs->hw.elsa.counter);
+		if ((cs->hw.elsa.counter > 10) &&
+		    (cs->hw.elsa.counter < 16)) {
+			printk(KERN_INFO "Elsa: timer and irq OK\n");
+		} else {
+			printk(KERN_WARNING
+			       "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
+			       cs->hw.elsa.counter, cs->irq);
+		}
 	}
-	if (cs->typ == ISDN_CTYPE_ELSA) {
-		int pwr = bytein(cs->hw.elsa.ale);
-		if (pwr & 0x08)
-			cs->hw.elsa.status |= ELSA_BAD_PWR;
-		else
-			cs->hw.elsa.status &= ~ELSA_BAD_PWR;
+#if ARCOFI_USE
+	if (check_arcofi(cs)) {
+		init_modem(cs);
 	}
+#endif
 	elsa_led_handler(cs);
-	return(ret);
 }
 
+static struct card_ops elsa_ops = {
+	.init        = elsa_init,
+	.test        = elsa_test,
+	.reset       = elsa_reset,
+	.release     = elsa_release,
+	.aux_ind     = elsa_aux_ind,
+	.led_handler = elsa_led_handler,
+	.irq_func    = elsa_interrupt,
+};
+
+static struct card_ops elsa_ipac_ops = {
+	.init        = elsa_ipac_init,
+	.test        = elsa_test,
+	.reset       = elsa_reset,
+	.release     = elsa_release,
+	.aux_ind     = elsa_aux_ind,
+	.led_handler = elsa_led_handler,
+	.irq_func    = elsa_interrupt_ipac,
+};
+
 static unsigned char
 probe_elsa_adr(unsigned int adr, int typ)
 {
@@ -863,7 +765,7 @@
 };
 
 static struct isapnp_device_id *pdev = &elsa_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
@@ -943,31 +845,39 @@
 	} else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
 #ifdef __ISAPNP__
 		if (!card->para[1] && isapnp_present()) {
-			struct pci_bus *pb;
-			struct pci_dev *pd;
+			struct pnp_card *pb;
+			struct pnp_dev *pd;
 
 			while(pdev->card_vendor) {
-				if ((pb = isapnp_find_card(pdev->card_vendor,
-					pdev->card_device, pnp_c))) {
+				if ((pb = pnp_find_card(pdev->card_vendor,
+							pdev->card_device,
+							pnp_c))) {
 					pnp_c = pb;
 					pd = NULL;
-					if ((pd = isapnp_find_dev(pnp_c,
-						pdev->vendor, pdev->function, pd))) {
+					if ((pd = pnp_find_dev(pnp_c,
+							       pdev->vendor,
+							       pdev->function,
+							       pd))) {
 						printk(KERN_INFO "HiSax: %s detected\n",
 							(char *)pdev->driver_data);
-						pd->prepare(pd);
-						pd->deactivate(pd);
-						pd->activate(pd);
-						card->para[1] =
-							pd->resource[0].start;
-						card->para[0] =
-							pd->irq_resource[0].start;
-						if (!card->para[0] || !card->para[1]) {
+						if (pnp_device_attach(pd) < 0) {
+							printk(KERN_ERR "Elsa PnP: attach failed\n");
+							return 0;
+						}
+						if (pnp_activate_dev(pd, NULL) < 0) {
+							pnp_device_detach(pd);
+							printk(KERN_ERR "Elsa PnP: activate failed\n");
+							return 0;
+						}
+						if (!pnp_port_valid(pd, 0) ||
+						    !pnp_irq_valid(pd, 0)) {
 							printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
-								card->para[0], card->para[1]);
-							pd->deactivate(pd);
+							       pnp_irq(pd, 0), pnp_port_start(pd, 0));
+							pnp_device_detach(pd);
 							return(0);
 						}
+						card->para[1] = pnp_port_start(pd, 0);
+						card->para[0] = pnp_irq(pd, 0);
 						if (pdev->function == ISAPNP_FUNCTION(0x133))
 							cs->subtyp = ELSA_QS1000;
 						else
@@ -1016,7 +926,6 @@
 			cs->subtyp = ELSA_PCMCIA_IPAC;
 			cs->hw.elsa.isac = cs->hw.elsa.base + 2;
 			cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
-			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
 		} else {
 			cs->subtyp = ELSA_PCMCIA;
 			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
@@ -1033,10 +942,6 @@
 		       cs->irq);
 	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
 #if CONFIG_PCI
-		if (!pci_present()) {
-			printk(KERN_ERR "Elsa: no PCI bus present\n");
-			return(0);
-		}
 		cs->subtyp = 0;
 		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
@@ -1076,7 +981,6 @@
 		cs->hw.elsa.ale  = cs->hw.elsa.base;
 		cs->hw.elsa.isac = cs->hw.elsa.base +1;
 		cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
-		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
 		cs->hw.elsa.timer = 0;
 		cs->hw.elsa.trig  = 0;
 		cs->irq_flags |= SA_SHIRQ;
@@ -1086,10 +990,6 @@
 		       cs->hw.elsa.base,
 		       cs->hw.elsa.cfg,
 		       cs->irq);
-#else
-		printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n");
-		printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n");
-		return (0);
 #endif /* CONFIG_PCI */
 	} else 
 		return (0);
@@ -1121,29 +1021,17 @@
 	   reserved for us by the card manager. So we do not check it
 	   here, it would fail. */
 	if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA)
-		if (!request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) {		
-			printk(KERN_WARNING
-			       "HiSax: %s config port %#lx-%#lx already in use\n",
-			       CardType[card->typ],
-			       cs->hw.elsa.base,
-			       cs->hw.elsa.base + bytecnt);
-			return (0);
-		}
+		if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+			goto err;
 	
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
-		if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) {
-			printk(KERN_WARNING
-			       "HiSax: %s pci port %x-%x already in use\n",
-				CardType[card->typ],
-				cs->hw.elsa.cfg,
-				cs->hw.elsa.cfg + 0x80);
-			release_region(cs->hw.elsa.base, bytecnt);
-			return (0);
-		}
-	}
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI))
+		if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
+			goto err;
+
 #if ARCOFI_USE
 	init_arcofi(cs);
 #endif
+
 	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
 	cs->hw.elsa.tl.data = (long) cs;
 	init_timer(&cs->hw.elsa.tl);
@@ -1156,36 +1044,25 @@
 			if (!TimerRun(cs)) {
 				printk(KERN_WARNING
 				       "Elsa: timer do not start\n");
-				release_io_elsa(cs);
-				return (0);
+				goto err;
 			}
 		}
 		HZDELAY(1);	/* wait >=10 ms */
 		if (TimerRun(cs)) {
 			printk(KERN_WARNING "Elsa: timer do not run down\n");
-			release_io_elsa(cs);
-			return (0);
+			goto err;
 		}
 		printk(KERN_INFO "Elsa: timer OK; resetting card\n");
 	}
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &Elsa_card_msg;
-	reset_elsa(cs);
+	elsa_reset(cs);
 	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
-		cs->dc_hw_ops = &ipac_dc_ops;
-		cs->irq_func = &elsa_interrupt_ipac;
-		val = readreg(cs, cs->hw.elsa.isac, IPAC_ID);
-		printk(KERN_INFO "Elsa: IPAC version %x\n", val);
+		cs->card_ops = &elsa_ipac_ops;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
 	} else {
-		cs->dc_hw_ops = &isac_ops;
-		cs->irq_func = &elsa_interrupt;
-		ISACVersion(cs, "Elsa:");
-		if (HscxVersion(cs, "Elsa:")) {
-			printk(KERN_WARNING
-				"Elsa: wrong HSCX versions check IO address\n");
-			release_io_elsa(cs);
-			return (0);
-		}
+		cs->card_ops = &elsa_ops;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
 	}
 	if (cs->subtyp == ELSA_PC) {
 		val = readitac(cs, ITAC_SYS);
@@ -1196,5 +1073,8 @@
 		writeitac(cs, ITAC_SCIE, 0);
 		writeitac(cs, ITAC_STIE, 0);
 	}
-	return (1);
+	return 1;
+ err:
+	elsa_release(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
--- a/drivers/isdn/hisax/elsa_ser.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/elsa_ser.c	Mon Jan 13 10:18:05 2003
@@ -375,11 +375,6 @@
 	}
 }
 
-static struct bc_l1_ops modem_l1_ops = {
-	.fill_fifo = modem_fill,
-};
-
-
 static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
 {
 	int status, iir, msr;
@@ -424,10 +419,10 @@
 {
 	modehscx(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (bcs->hw.hscx.rcvbuf) {
+		if (bcs->rcvbuf) {
 			if (bcs->mode != L1_MODE_MODEM)
-				kfree(bcs->hw.hscx.rcvbuf);
-			bcs->hw.hscx.rcvbuf = NULL;
+				kfree(bcs->rcvbuf);
+			bcs->rcvbuf = NULL;
 		}
 		skb_queue_purge(&bcs->rqueue);
 		skb_queue_purge(&bcs->squeue);
@@ -597,23 +592,23 @@
 			if (open_hscxstate(st->l1.hardware, bcs))
 				return (-1);
 			st->l1.l2l1 = hscx_l2l1;
-			// bcs->cs->BC_Send_Data = hscx_fill_fifo;
+			// bcs->cs->BC_Send_Data = hscx_fill_fifo; FIXME
 			break;
 		case L1_MODE_MODEM:
 			bcs->mode = L1_MODE_MODEM;
 			if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-				bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
+				bcs->rcvbuf = bcs->cs->hw.elsa.rcvbuf;
 				skb_queue_head_init(&bcs->rqueue);
 				skb_queue_head_init(&bcs->squeue);
 			}
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			bcs->event = 0;
-			bcs->hw.hscx.rcvidx = 0;
+			bcs->rcvidx = 0;
 			bcs->tx_cnt = 0;
 			bcs->cs->hw.elsa.bcs = bcs;
 			st->l1.l2l1 = modem_l2l1;
-			bcs->cs->bc_l1_ops = &modem_l1_ops;
+//			bcs->cs->bc_l1_ops = &modem_l1_ops;
 			break;
 	}
 	st->l1.bcs = bcs;
@@ -623,13 +618,17 @@
 	return (0);
 }
 
+static struct bc_l1_ops modem_l1_ops = {
+	.fill_fifo = modem_fill,
+	.open      = setstack_elsa,
+	.close     = close_elsastate,
+};
+
 void
-init_modem(struct IsdnCardState *cs) {
+init_modem(struct IsdnCardState *cs)
+{
+	cs->bc_l1_ops = &modem_l1_ops;
 
-	cs->bcs[0].BC_SetStack = setstack_elsa;
-	cs->bcs[1].BC_SetStack = setstack_elsa;
-	cs->bcs[0].BC_Close = close_elsastate;
-	cs->bcs[1].BC_Close = close_elsastate;
 	if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
 		GFP_ATOMIC))) {
 		printk(KERN_WARNING
diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
--- a/drivers/isdn/hisax/enternow_pci.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/enternow_pci.c	Mon Jan 13 10:18:07 2003
@@ -110,13 +110,14 @@
 }
 
 
-static struct dc_hw_ops enternow_ops = {
+static struct dc_hw_ops amd7930_ops = {
 	.read_reg   = ReadByteAmd7930,
 	.write_reg  = WriteByteAmd7930,
 };
 
-void
-enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) {
+static void
+enpci_setIrqMask(struct IsdnCardState *cs, BYTE val)
+{
         if (!val)
 	        OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00);
         else
@@ -152,72 +153,60 @@
 	OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off
 }
 
-
-static int
-enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+enpci_bc_activate(struct IsdnCardState *cs, int chan)
 {
-        BYTE *chan;
-
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt);
+		debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", chan);
+	
+	cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (chan + 1)), "MDL_BC_ASSIGN");
+	/* at least one b-channel in use, LED 2 on */
+	cs->hw.njet.auxd |= TJ_AMD_IRQ << 2;
+	OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+}
 
-        switch (mt) {
-		case CARD_RESET:
-			reset_enpci(cs);
-                        Amd7930_init(cs);
-			break;
-		case CARD_RELEASE:
-			release_io_netjet(cs);
-			break;
-		case CARD_INIT:
-			inittiger(cs);
-			Amd7930_init(cs);
-			break;
-		case CARD_TEST:
-			break;
-                case MDL_ASSIGN:
-                        /* TEI assigned, LED1 on */
-                        cs->hw.njet.auxd = TJ_AMD_IRQ << 1;
-                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
-                        break;
-                case MDL_REMOVE:
-                        /* TEI removed, LEDs off */
-	                cs->hw.njet.auxd = 0;
-                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00);
-                        break;
-                case MDL_BC_ASSIGN:
-                        /* activate B-channel */
-                        chan = (BYTE *)arg;
-
-                        if (cs->debug & L1_DEB_ISAC)
-		                debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan);
-
-                        cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN");
-                        /* at least one b-channel in use, LED 2 on */
-                        cs->hw.njet.auxd |= TJ_AMD_IRQ << 2;
-                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
-                        break;
-                case MDL_BC_RELEASE:
-                        /* deactivate B-channel */
-                        chan = (BYTE *)arg;
-
-                        if (cs->debug & L1_DEB_ISAC)
-		                debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan);
-
-                        cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(*chan + 1)), "MDL_BC_RELEASE");
-                        /* no b-channel active -> LED2 off */
-                        if (!(cs->dc.amd7930.lmr1 & 3)) {
-                                cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2);
-                                OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
-                        }
-                        break;
-                default:
-                        break;
+static void
+enpci_bc_deactivate(struct IsdnCardState *cs, int chan)
+{
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", chan);
+	
+	cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(chan + 1)), "MDL_BC_RELEASE");
+	/* no b-channel active -> LED2 off */
+	if (!(cs->dc.amd7930.lmr1 & 3)) {
+		cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2);
+		OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+	}
+}
 
+static void
+enpci_led_handler(struct IsdnCardState *cs)
+{
+	if (cs->status & 0x0001) {
+		/* TEI assigned, LED1 on */
+		cs->hw.njet.auxd = TJ_AMD_IRQ << 1;
+		OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+	} else {
+		/* TEI removed, LEDs off */
+		cs->hw.njet.auxd = 0;
+		OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00);
 	}
-	return(0);
 }
 
+static void
+enpci_init(struct IsdnCardState *cs)
+{
+	inittiger(cs);
+	Amd7930_init(cs);
+}
+
+static int
+enpci_reset(struct IsdnCardState *cs)
+{
+	reset_enpci(cs);
+	Amd7930_init(cs);
+	return 0;
+}
 
 static void
 enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
@@ -266,6 +255,13 @@
 	spin_unlock(&cs->lock);
 }
 
+static struct card_ops enpci_ops = {
+	.init        = enpci_init,
+	.reset       = enpci_reset,
+	.release     = netjet_release,
+	.led_handler = enpci_led_handler,
+	.irq_func    = enpci_interrupt,
+};
 
 static struct pci_dev *dev_netjet __initdata = NULL;
 
@@ -273,25 +269,16 @@
 int __init
 setup_enternow_pci(struct IsdnCard *card)
 {
-	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
-#if CONFIG_PCI
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
         strcpy(tmp, enternow_pci_rev);
 	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_ENTERNOW)
-		return(0);
 
-	for ( ;; )
-	{
-		if (!pci_present()) {
-			printk(KERN_ERR "enter:now PCI: no PCI bus present\n");
-			return(0);
-		}
+	for ( ;; ) {
 		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
 			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
 			if (pci_enable_device(dev_netjet))
@@ -344,61 +331,19 @@
 
 			   break;
 	}
-#else
-
-	printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n");
-	printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n");
-	return (0);
-
-#endif /* CONFIG_PCI */
-
-	bytecnt = 256;
-
 	printk(KERN_INFO
 		"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
 		cs->hw.njet.base, cs->irq);
-	if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) {
-		printk(KERN_WARNING
-			   "HiSax: %s config port %lx-%lx already in use\n",
-			   CardType[card->typ],
-			   cs->hw.njet.base,
-			   cs->hw.njet.base + bytecnt);
-		return (0);
-	}
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
+		return 0;
 	reset_enpci(cs);
 	cs->hw.njet.last_is0 = 0;
-	cs->dc_hw_ops = &enternow_ops;
-        cs->dc.amd7930.setIrqMask = &enpci_setIrqMask;
+	cs->hw.njet.bc_activate = enpci_bc_activate;
+	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
+	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
 
-	cs->cardmsg = &enpci_card_msg;
-	cs->irq_func = &enpci_interrupt;
 	cs->irq_flags |= SA_SHIRQ;
+	cs->card_ops = &enpci_ops;
 
-        return (1);
+        return 1;
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
--- a/drivers/isdn/hisax/gazel.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/gazel.c	Mon Jan 13 10:18:06 2003
@@ -69,431 +69,313 @@
 	outsb(adr, data, size);
 }
 
-static inline u8
-readreg_ipac(struct IsdnCardState *cs, u_short off)
-{
-	register u8 ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gazel_lock, flags);
-	byteout(cs->hw.gazel.ipac, off);
-	ret = bytein(cs->hw.gazel.ipac + 4);
-	spin_unlock_irqrestore(&gazel_lock, flags);
-	return ret;
-}
-
-static inline void
-writereg_ipac(struct IsdnCardState *cs, u_short off, u8 data)
+static u8
+r685_isac_read(struct IsdnCardState *cs, u8 off)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&gazel_lock, flags);
-	byteout(cs->hw.gazel.ipac, off);
-	byteout(cs->hw.gazel.ipac + 4, data);
-	spin_unlock_irqrestore(&gazel_lock, flags);
+	return readreg(cs->hw.gazel.isac, off);
 }
 
-
-static inline void
-read_fifo_ipac(struct IsdnCardState *cs, u_short off, u8 * data, int size)
+static u8
+r647_isac_read(struct IsdnCardState *cs, u8 off)
 {
-	byteout(cs->hw.gazel.ipac, off);
-	insb(cs->hw.gazel.ipac + 4, data, size);
+	return readreg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf));
 }
 
 static void
-write_fifo_ipac(struct IsdnCardState *cs, u_short off, u8 * data, int size)
+r685_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
 {
-	byteout(cs->hw.gazel.ipac, off);
-	outsb(cs->hw.gazel.ipac + 4, data, size);
-}
-
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
-{
-	u_short off2 = offset;
-
-	switch (cs->subtyp) {
-		case R647:
-			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
-		case R685:
-			return (readreg(cs->hw.gazel.isac, off2));
-		case R753:
-		case R742:
-			return (readreg_ipac(cs, 0x80 + off2));
-	}
-	return 0;
+	writereg(cs->hw.gazel.isac, off, value);
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+r647_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
 {
-	u_short off2 = offset;
-
-	switch (cs->subtyp) {
-		case R647:
-			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
-		case R685:
-			writereg(cs->hw.gazel.isac, off2, value);
-			break;
-		case R753:
-		case R742:
-			writereg_ipac(cs, 0x80 + off2, value);
-			break;
-	}
+	writereg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf), value);
 }
 
 static void
 isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
 {
-	switch (cs->subtyp) {
-		case R647:
-		case R685:
-			read_fifo(cs->hw.gazel.isacfifo, data, size);
-			break;
-		case R753:
-		case R742:
-			read_fifo_ipac(cs, 0x80, data, size);
-			break;
-	}
+	read_fifo(cs->hw.gazel.isacfifo, data, size);
 }
 
 static void
 isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
 {
-	switch (cs->subtyp) {
-		case R647:
-		case R685:
-			write_fifo(cs->hw.gazel.isacfifo, data, size);
-			break;
-		case R753:
-		case R742:
-			write_fifo_ipac(cs, 0x80, data, size);
-			break;
-	}
+	write_fifo(cs->hw.gazel.isacfifo, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
+static struct dc_hw_ops r685_isac_ops = {
+	.read_reg   = r685_isac_read,
+	.write_reg  = r685_isac_write,
 	.read_fifo  = isac_read_fifo,
 	.write_fifo = isac_write_fifo,
 };
 
+static struct dc_hw_ops r647_isac_ops = {
+	.read_reg   = r647_isac_read,
+	.write_reg  = r647_isac_write,
+	.read_fifo  = isac_read_fifo,
+	.write_fifo = isac_write_fifo,
+};
+  
 static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+r685_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
 {
-	u_short off2 = offset;
+	return readreg(cs->hw.gazel.hscx[hscx], off);
+}
 
-	switch (cs->subtyp) {
-		case R647:
-			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
-		case R685:
-			return readreg(cs->hw.gazel.hscx[hscx], off2);
-		case R753:
-		case R742:
-			return readreg_ipac(cs, hscx * 0x40 + off2);
-	}
-	return 0;
+static u8
+r647_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
+{
+	return readreg(cs->hw.gazel.hscx[hscx],
+		       (off << 8 & 0xf000) | (off & 0xf));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+r685_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
 {
-	u_short off2 = offset;
+	writereg(cs->hw.gazel.hscx[hscx], off, value);
+}
 
-	switch (cs->subtyp) {
-		case R647:
-			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
-		case R685:
-			writereg(cs->hw.gazel.hscx[hscx], off2, value);
-			break;
-		case R753:
-		case R742:
-			writereg_ipac(cs, hscx * 0x40 + off2, value);
-			break;
-	}
+static void
+r647_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
+{
+	writereg(cs->hw.gazel.hscx[hscx],
+		 (off << 8 & 0xf000) | (off & 0xf), value);
 }
 
 static void
 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
 {
-	switch (cs->subtyp) {
-		case R647:
-		case R685:
-			read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
-			break;
-		case R753:
-		case R742:
-			read_fifo_ipac(cs, hscx * 0x40, data, size);
-			break;
-	}
+	read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
 }
 
 static void
 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
 {
-	switch (cs->subtyp) {
-		case R647:
-		case R685:
-			write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
-			break;
-		case R753:
-		case R742:
-			write_fifo_ipac(cs, hscx * 0x40, data, size);
-			break;
-	}
+	write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
+static struct bc_hw_ops r685_hscx_ops = {
+	.read_reg   = r685_hscx_read,
+	.write_reg  = r685_hscx_write,
 	.read_fifo  = hscx_read_fifo,
 	.write_fifo = hscx_write_fifo,
 };
 
-static void
-gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+static struct bc_hw_ops r647_hscx_ops = {
+	.read_reg   = r647_hscx_read,
+	.write_reg  = r647_hscx_write,
+	.read_fifo  = hscx_read_fifo,
+	.write_fifo = hscx_write_fifo,
+};
+
+static inline u8
+ipac_read(struct IsdnCardState *cs, u_short off)
 {
-#define MAXCOUNT 5
-	struct IsdnCardState *cs = dev_id;
-	u8 valisac, valhscx;
-	int count = 0;
-
-	spin_lock(&cs->lock);
-	do {
-		valhscx = hscx_read(cs, 1, HSCX_ISTA);
-		if (valhscx)
-			hscx_int_main(cs, valhscx);
-		valisac = isac_read(cs, ISAC_ISTA);
-		if (valisac)
-			isac_interrupt(cs, valisac);
-		count++;
-	} while ((valhscx || valisac) && (count < MAXCOUNT));
-
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-}
+	register u8 ret;
+	unsigned long flags;
 
+	spin_lock_irqsave(&gazel_lock, flags);
+	byteout(cs->hw.gazel.ipac, off);
+	ret = bytein(cs->hw.gazel.ipac + 4);
+	spin_unlock_irqrestore(&gazel_lock, flags);
+	return ret;
+}
 
-static void
-gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+static inline void
+ipac_write(struct IsdnCardState *cs, u_short off, u8 data)
 {
-	struct IsdnCardState *cs = dev_id;
-	u8 ista, val;
-	int count = 0;
-
-	if (!cs) {
-		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
-		return;
-	}
-	ista = readreg_ipac(cs, IPAC_ISTA);
-	do {
-		if (ista & 0x0f) {
-			val = hscx_read(cs, 1, HSCX_ISTA);
-			if (ista & 0x01)
-				val |= 0x01;
-			if (ista & 0x04)
-				val |= 0x02;
-			if (ista & 0x08)
-				val |= 0x04;
-			if (val) {
-				hscx_int_main(cs, val);
-			}
-		}
-		if (ista & 0x20) {
-			val = isac_read(cs, ISAC_ISTA) & 0xfe;
-			if (val) {
-				isac_interrupt(cs, val);
-			}
-		}
-		if (ista & 0x10) {
-			val = 0x01;
-			isac_interrupt(cs, val);
-		}
-		ista = readreg_ipac(cs, IPAC_ISTA);
-		count++;
-	}
-	while ((ista & 0x3f) && (count < MAXCOUNT));
+	unsigned long flags;
 
-	writereg_ipac(cs, IPAC_MASK, 0xFF);
-	writereg_ipac(cs, IPAC_MASK, 0xC0);
+	spin_lock_irqsave(&gazel_lock, flags);
+	byteout(cs->hw.gazel.ipac, off);
+	byteout(cs->hw.gazel.ipac + 4, data);
+	spin_unlock_irqrestore(&gazel_lock, flags);
 }
-void
-release_io_gazel(struct IsdnCardState *cs)
+
+
+static inline void
+ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
 {
-	unsigned int i;
+	byteout(cs->hw.gazel.ipac, off);
+	insb(cs->hw.gazel.ipac + 4, data, size);
+}
 
-	switch (cs->subtyp) {
-		case R647:
-			for (i = 0x0000; i < 0xC000; i += 0x1000)
-				release_region(i + cs->hw.gazel.hscx[0], 16);
-			release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
-			break;
+static inline void
+ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
+{
+	byteout(cs->hw.gazel.ipac, off);
+	outsb(cs->hw.gazel.ipac + 4, data, size);
+}
 
-		case R685:
-			release_region(cs->hw.gazel.hscx[0], 0x100);
-			release_region(cs->hw.gazel.cfg_reg, 0x80);
-			break;
+/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
+ * above */
 
-		case R753:
-			release_region(cs->hw.gazel.ipac, 0x8);
-			release_region(cs->hw.gazel.cfg_reg, 0x80);
-			break;
+BUILD_IPAC_OPS(ipac);
 
-		case R742:
-			release_region(cs->hw.gazel.ipac, 8);
-			break;
-	}
+static int
+r647_reset(struct IsdnCardState *cs)
+{
+	writereg(cs->hw.gazel.cfg_reg, 0, 0);
+	HZDELAY(10);
+	writereg(cs->hw.gazel.cfg_reg, 0, 1);
+	HZDELAY(2);
+	return 0;
 }
 
 static int
-reset_gazel(struct IsdnCardState *cs)
+r685_reset(struct IsdnCardState *cs)
 {
 	unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
 
-	switch (cs->subtyp) {
-		case R647:
-			writereg(addr, 0, 0);
-			HZDELAY(10);
-			writereg(addr, 0, 1);
-			HZDELAY(2);
-			break;
-		case R685:
-			plxcntrl = inl(addr + PLX_CNTRL);
-			plxcntrl |= (RESET_9050 + RESET_GAZEL);
-			outl(plxcntrl, addr + PLX_CNTRL);
-			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
-			HZDELAY(4);
-			outl(plxcntrl, addr + PLX_CNTRL);
-			HZDELAY(10);
-			outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
-			break;
-		case R753:
-			if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags))
-				/* we can't read, assume the default */
-				plxcntrl = 0x18784db6;
-			else
-				plxcntrl = inl(addr + PLX_CNTRL);
-			plxcntrl |= (RESET_9050 + RESET_GAZEL);
-			outl(plxcntrl, addr + PLX_CNTRL);
-			writereg_ipac(cs, IPAC_POTA2, 0x20);
-			HZDELAY(4);
-			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
-			outl(plxcntrl, addr + PLX_CNTRL);
-			HZDELAY(10);
-			writereg_ipac(cs, IPAC_POTA2, 0x00);
-			writereg_ipac(cs, IPAC_ACFG, 0xff);
-			writereg_ipac(cs, IPAC_AOE, 0x0);
-			writereg_ipac(cs, IPAC_MASK, 0xff);
-			writereg_ipac(cs, IPAC_CONF, 0x1);
-			outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
-			writereg_ipac(cs, IPAC_MASK, 0xc0);
-			break;
-		case R742:
-			writereg_ipac(cs, IPAC_POTA2, 0x20);
-			HZDELAY(4);
-			writereg_ipac(cs, IPAC_POTA2, 0x00);
-			writereg_ipac(cs, IPAC_ACFG, 0xff);
-			writereg_ipac(cs, IPAC_AOE, 0x0);
-			writereg_ipac(cs, IPAC_MASK, 0xff);
-			writereg_ipac(cs, IPAC_CONF, 0x1);
-			writereg_ipac(cs, IPAC_MASK, 0xc0);
-			break;
-	}
-	return (0);
+	plxcntrl = inl(addr + PLX_CNTRL);
+	plxcntrl |= (RESET_9050 + RESET_GAZEL);
+	outl(plxcntrl, addr + PLX_CNTRL);
+	plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+	HZDELAY(4);
+	outl(plxcntrl, addr + PLX_CNTRL);
+	HZDELAY(10);
+	outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
+	return 0;
 }
 
 static int
-Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+r753_reset(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_gazel(cs);
-			return (0);
-		case CARD_RELEASE:
-			release_io_gazel(cs);
-			return (0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
-				int i;
-				for (i=0;i<(2+MAX_WAITING_CALLS);i++) {
-					cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
-					cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
-				}
-			}
-			return (0);
-		case CARD_TEST:
-			return (0);
-	}
-	return (0);
+	unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
+
+	if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags))
+		/* we can't read, assume the default */
+		plxcntrl = 0x18784db6;
+	else
+		plxcntrl = inl(addr + PLX_CNTRL);
+	plxcntrl |= (RESET_9050 + RESET_GAZEL);
+	outl(plxcntrl, addr + PLX_CNTRL);
+	ipac_write(cs, IPAC_POTA2, 0x20);
+	HZDELAY(4);
+	plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+	outl(plxcntrl, addr + PLX_CNTRL);
+	HZDELAY(10);
+	ipac_write(cs, IPAC_POTA2, 0x00);
+	ipac_write(cs, IPAC_ACFG, 0xff);
+	ipac_write(cs, IPAC_AOE, 0x0);
+	ipac_write(cs, IPAC_MASK, 0xff);
+	ipac_write(cs, IPAC_CONF, 0x1);
+	outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
+	ipac_write(cs, IPAC_MASK, 0xc0);
+	return 0;
 }
 
 static int
-reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
+r742_reset(struct IsdnCardState *cs)
 {
-	unsigned int i, base = 0, adr = 0, len = 0;
-
-	switch (cs->subtyp) {
-		case R647:
-			base = cs->hw.gazel.hscx[0];
-			for (i = 0x0000; i < 0xC000; i += 0x1000) {
-				if (!request_region(adr = (i + base), len = 16, "gazel")) {
-					int j;
-
-					for (j = 0x0000; j < i; j += 0x1000)
-						release_region ((j + base), len);					
-					goto error;
-				}
-			}
-			if (!request_region(adr = (0xC000 + base), len = 1, "gazel")) {
-				for (i = 0x0000; i < 0xC000; i += 0x1000) 
-					release_region ((i + base), 16);
-				goto error;
-			}
-
-			break;
-
-		case R685:
-			if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel"))
-				goto error;
-			if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
-				release_region (cs->hw.gazel.hscx[0], 0x100);
-				goto error;
-			}
+	ipac_write(cs, IPAC_POTA2, 0x20);
+	HZDELAY(4);
+	ipac_write(cs, IPAC_POTA2, 0x00);
+	ipac_write(cs, IPAC_ACFG, 0xff);
+	ipac_write(cs, IPAC_AOE, 0x0);
+	ipac_write(cs, IPAC_MASK, 0xff);
+	ipac_write(cs, IPAC_CONF, 0x1);
+	ipac_write(cs, IPAC_MASK, 0xc0);
+	return 0;
+}
 
-			break;
+static void
+gazel_init(struct IsdnCardState *cs)
+{
+	int i;
 
-		case R753:
-			if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
-				goto error;
-			if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
-				release_region (cs->hw.gazel.ipac, 0x8);
-				goto error;
-			}
+	for (i = 0; i < 2; i++) {
+		cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
+		cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
+	}
+	inithscxisac(cs);
+}
 
-			break;
+static int
+r647_reserve_regions(struct IsdnCardState *cs)
+{
+	int i, base = cs->hw.gazel.hscx[0];
 
-		case R742:
-			if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
-				goto error;
-			break;
+	for (i = 0; i < 0xc000; i += 0x1000) {
+		if (!request_io(&cs->rs, i + base, 16, "gazel"))
+			goto err;
 	}
+	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
 
+static int
+r685_reserve_regions(struct IsdnCardState *cs)
+{
+	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
 
-      error:
-	printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
-	       CardType[cs->typ], adr, adr + len);
-	return 1;
+static int
+r742_reserve_regions(struct IsdnCardState *cs)
+{
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int
+r753_reserve_regions(struct IsdnCardState *cs)
+{
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
 }
 
+static struct card_ops r647_ops = {
+	.init     = gazel_init,
+	.reset    = r647_reset,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
+
+static struct card_ops r685_ops = {
+	.init     = gazel_init,
+	.reset    = r685_reset,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
+
+static struct card_ops r742_ops = {
+	.init     = ipac_init,
+	.reset    = r742_reset,
+	.release  = hisax_release_resources,
+	.irq_func = ipac_irq,
+};
+
+static struct card_ops r753_ops = {
+	.init     = ipac_init,
+	.reset    = r753_reset,
+	.release  = hisax_release_resources,
+	.irq_func = ipac_irq,
+};
+
 static int __init
 setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
 {
@@ -503,7 +385,7 @@
 	// R647 returns FF if not present or not started
 	// eventually needs improvment
 	cs->hw.gazel.ipac = card->para[1];
-	if (readreg_ipac(cs, IPAC_ID) == 1)
+	if (ipac_read(cs, IPAC_ID) == 1)
 		cs->subtyp = R742;
 	else
 		cs->subtyp = R647;
@@ -518,27 +400,25 @@
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
 
 	switch (cs->subtyp) {
-		case R647:
-			printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
-			cs->dc.isac.adf2 = 0x87;
-			printk(KERN_INFO
-				"Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-				cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-			printk(KERN_INFO
-				"Gazel: hscx A:0x%X  hscx B:0x%X\n",
-				cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-
-			break;
-		case R742:
-			printk(KERN_INFO "Gazel: Card ISA R742 found\n");
-			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-			printk(KERN_INFO
-			       "Gazel: config irq:%d ipac:0x%X\n",
-			       cs->irq, cs->hw.gazel.ipac);
-			break;
+	case R647:
+		printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
+		cs->dc.isac.adf2 = 0x87;
+		printk(KERN_INFO
+		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+		printk(KERN_INFO
+		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+		
+		return r647_reserve_regions(cs);
+	case R742:
+		printk(KERN_INFO "Gazel: Card ISA R742 found\n");
+		printk(KERN_INFO
+		       "Gazel: config irq:%d ipac:0x%X\n",
+		       cs->irq, cs->hw.gazel.ipac);
+		return r742_reserve_regions(cs);
 	}
-
-	return (0);
+	return 0;
 }
 
 static struct pci_dev *dev_tel __initdata = NULL;
@@ -572,22 +452,22 @@
 			break;
 		else {
 			switch (seekcard) {
-				case PCI_DEVICE_ID_PLX_R685:
-					seekcard = PCI_DEVICE_ID_PLX_R753;
-					break;
-				case PCI_DEVICE_ID_PLX_R753:
-					seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
-					break;
+			case PCI_DEVICE_ID_PLX_R685:
+				seekcard = PCI_DEVICE_ID_PLX_R753;
+				break;
+			case PCI_DEVICE_ID_PLX_R753:
+				seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
+				break;
 			}
 		}
 	}
 	if (!found) {
 		printk(KERN_WARNING "Gazel: No PCI card found\n");
-		return (1);
+		return -ENODEV;
 	}
 	if (!pci_irq) {
 		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
-		return 1;
+		return -ENODEV;
 	}
 	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
 	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
@@ -605,41 +485,39 @@
 	cs->irq_flags |= SA_SHIRQ;
 
 	switch (seekcard) {
-		case PCI_DEVICE_ID_PLX_R685:
-			printk(KERN_INFO "Gazel: Card PCI R685 found\n");
-			cs->subtyp = R685;
-			cs->dc.isac.adf2 = 0x87;
-			printk(KERN_INFO
-			    "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-			cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-			printk(KERN_INFO
-			       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-			     cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-			break;
-		case PCI_DEVICE_ID_PLX_R753:
-		case PCI_DEVICE_ID_PLX_DJINN_ITOO:
-			printk(KERN_INFO "Gazel: Card PCI R753 found\n");
-			cs->subtyp = R753;
-			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-			printk(KERN_INFO
-			    "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
-			cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
-			/* 
-			 * Erratum for PLX9050, revision 1:
-			 * If bit 7 of BAR 0/1 is set, local config registers
-			 * can not be read (write is okay)
-			 */
-			if (cs->hw.gazel.cfg_reg & 0x80) {
-				pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
-				if (pci_rev == 1) {
-					printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n");
-					set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-				}
+	case PCI_DEVICE_ID_PLX_R685:
+		printk(KERN_INFO "Gazel: Card PCI R685 found\n");
+		cs->subtyp = R685;
+		cs->dc.isac.adf2 = 0x87;
+		printk(KERN_INFO
+		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+		printk(KERN_INFO
+		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+		return r685_reserve_regions(cs);
+	case PCI_DEVICE_ID_PLX_R753:
+	case PCI_DEVICE_ID_PLX_DJINN_ITOO:
+		printk(KERN_INFO "Gazel: Card PCI R753 found\n");
+		cs->subtyp = R753;
+		printk(KERN_INFO
+		       "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
+		       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+		/* 
+		 * Erratum for PLX9050, revision 1:
+		 * If bit 7 of BAR 0/1 is set, local config registers
+		 * can not be read (write is okay)
+		 */
+		if (cs->hw.gazel.cfg_reg & 0x80) {
+			pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
+			if (pci_rev == 1) {
+				printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n");
+				set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
 			}
-			break;
+		}
+		return r753_reserve_regions(cs);
 	}
-
-	return (0);
+	return 0;
 }
 
 int __init
@@ -647,59 +525,46 @@
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u8 val;
 
 	strcpy(tmp, gazel_revision);
 	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
 
-	if (cs->typ != ISDN_CTYPE_GAZEL)
-		return (0);
-
 	if (card->para[0]) {
 		if (setup_gazelisa(card, cs))
 			return (0);
 	} else {
-
-#if CONFIG_PCI
 		if (setup_gazelpci(cs))
 			return (0);
-#else
-		printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n");
-		return (0);
-#endif				/* CONFIG_PCI */
-	}
-
-	if (reserve_regions(card, cs)) {
-		return (0);
-	}
-	if (reset_gazel(cs)) {
-		printk(KERN_WARNING "Gazel: wrong IRQ\n");
-		release_io_gazel(cs);
-		return (0);
 	}
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &Gazel_card_msg;
 
 	switch (cs->subtyp) {
-		case R647:
-		case R685:
-			cs->irq_func = &gazel_interrupt;
-			ISACVersion(cs, "Gazel:");
-			if (HscxVersion(cs, "Gazel:")) {
-				printk(KERN_WARNING
-				       "Gazel: wrong HSCX versions check IO address\n");
-				release_io_gazel(cs);
-				return (0);
-			}
-			break;
-		case R742:
-		case R753:
-			cs->irq_func = &gazel_interrupt_ipac;
-			val = readreg_ipac(cs, IPAC_ID);
-			printk(KERN_INFO "Gazel: IPAC version %x\n", val);
-			break;
+	case R647:
+	case R685:
+		if (cs->subtyp == R647) {
+			cs->card_ops  = &r647_ops;
+			if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
+				goto err;
+		} else {
+			cs->card_ops  = &r685_ops;
+			if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
+				goto err;
+		}
+		cs->card_ops->reset(cs);
+		break;
+	case R742:
+	case R753:
+		if (cs->subtyp == R742) {
+			cs->card_ops = &r742_ops;
+		} else {
+			cs->card_ops = &r753_ops;
+		}
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+		cs->card_ops->reset(cs);
+		break;
 	}
-
 	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
--- a/drivers/isdn/hisax/hfc_2bds0.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/hfc_2bds0.c	Mon Jan 13 10:18:05 2003
@@ -824,10 +824,11 @@
 	}
 }
 
-void
+static int
 setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCD_l1hw;
+	return 0;
 }
 
 static void
@@ -850,25 +851,30 @@
 	return(send);
 }
 
+static struct bc_l1_ops hfcd_bc_l1_ops = {
+	.fill_fifo = hfc_fill_fifo,
+	.open      = setstack_2b,
+	.close     = close_2bs0,
+};
+
+static struct dc_l1_ops hfcd_dc_l1_ops = {
+	.fill_fifo  = hfc_fill_dfifo,
+	.open       = setstack_hfcd,
+	.bh_func    = hfcd_bh,
+	.dbusy_func = hfc_dbusy_timer,
+};
+
 void __init
 init2bds0(struct IsdnCardState *cs)
 {
-	cs->setstack_d = setstack_hfcd;
-	cs->dbusytimer.function = (void *) hfc_dbusy_timer;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
-	INIT_WORK(&cs->work, hfcd_bh, cs);
+	dc_l1_init(cs, &hfcd_dc_l1_ops);
+	cs->bc_l1_ops = &hfcd_bc_l1_ops;
 	if (!cs->hw.hfcD.send)
 		cs->hw.hfcD.send = init_send_hfcd(16);
 	if (!cs->bcs[0].hw.hfc.send)
 		cs->bcs[0].hw.hfc.send = init_send_hfcd(32);
 	if (!cs->bcs[1].hw.hfc.send)
 		cs->bcs[1].hw.hfc.send = init_send_hfcd(32);
-	cs->DC_Send_Data = hfc_fill_dfifo;
-	cs->bcs[0].BC_SetStack = setstack_2b;
-	cs->bcs[1].BC_SetStack = setstack_2b;
-	cs->bcs[0].BC_Close = close_2bs0;
-	cs->bcs[1].BC_Close = close_2bs0;
 	mode_2bs0(cs->bcs, 0, 0);
 	mode_2bs0(cs->bcs + 1, 0, 1);
 }
diff -Nru a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
--- a/drivers/isdn/hisax/hfc_2bs0.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/hfc_2bs0.c	Mon Jan 13 10:18:05 2003
@@ -546,6 +546,8 @@
 
 static struct bc_l1_ops hfc_l1_ops = {
 	.fill_fifo = hfc_fill_fifo,
+	.open      = setstack_hfc,
+	.close     = close_hfcstate,
 };
 
 void __init
@@ -554,10 +556,6 @@
 	init_send(&cs->bcs[0]);
 	init_send(&cs->bcs[1]);
 	cs->bc_l1_ops = &hfc_l1_ops;
-	cs->bcs[0].BC_SetStack = setstack_hfc;
-	cs->bcs[1].BC_SetStack = setstack_hfc;
-	cs->bcs[0].BC_Close = close_hfcstate;
-	cs->bcs[1].BC_Close = close_hfcstate;
 	mode_hfc(cs->bcs, 0, 0);
 	mode_hfc(cs->bcs + 1, 0, 0);
 }
@@ -573,4 +571,11 @@
 		kfree(cs->bcs[1].hw.hfc.send);
 		cs->bcs[1].hw.hfc.send = NULL;
 	}
+}
+
+int
+hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops)
+{
+	cs->bc_hw_ops = hfc_ops;
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/hfc_2bs0.h b/drivers/isdn/hisax/hfc_2bs0.h
--- a/drivers/isdn/hisax/hfc_2bs0.h	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/hfc_2bs0.h	Mon Jan 13 10:18:05 2003
@@ -58,3 +58,4 @@
 extern void main_irq_hfc(struct BCState *bcs);
 extern void inithfc(struct IsdnCardState *cs);
 extern void releasehfc(struct IsdnCardState *cs);
+extern int  hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops);
diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
--- a/drivers/isdn/hisax/hfc_pci.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/hfc_pci.c	Mon Jan 13 10:18:06 2003
@@ -65,13 +65,11 @@
 };
 
 
-#if CONFIG_PCI
-
 /******************************************/
 /* free hardware resources used by driver */
 /******************************************/
-void
-release_io_hfcpci(struct IsdnCardState *cs)
+static void
+hfcpci_release(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "HiSax: release hfcpci at %p\n",
 		cs->hw.hfcpci.pci_io);
@@ -83,16 +81,16 @@
 	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
 	pci_disable_device(cs->hw.hfcpci.pdev);
 	del_timer(&cs->hw.hfcpci.timer);
-	iounmap(cs->hw.hfcpci.pci_io);
 	pci_free_consistent(cs->hw.hfcpci.pdev, 32768, cs->hw.hfcpci.fifos, cs->hw.hfcpci.fifos_dma);
+	hisax_release_resources(cs);
 }
 
 /********************************************************************************/
 /* function called to reset the HFC PCI chip. A complete software reset of chip */
 /* and fifos is done.                                                           */
 /********************************************************************************/
-static void
-reset_hfcpci(struct IsdnCardState *cs)
+static int
+hfcpci_reset(struct IsdnCardState *cs)
 {
 	pci_disable_device(cs->hw.hfcpci.pdev);
 	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
@@ -159,6 +157,8 @@
 	cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
 	if (Read_hfc(cs, HFCPCI_INT_S2));
+	
+	return 0;
 }
 
 /***************************************************/
@@ -1047,10 +1047,11 @@
 /***********************************************/
 /* called during init setting l1 stack pointer */
 /***********************************************/
-void
+static int
 setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCPCI_l1hw;
+	return 0;
 }
 
 /***************************************************************/
@@ -1335,8 +1336,17 @@
 		DChannel_proc_xmt(cs);
 }
 
-static struct bc_l1_ops hfcpci_l1_ops = {
+static struct bc_l1_ops hfcpci_bc_l1_ops = {
 	.fill_fifo = hfcpci_fill_fifo,
+	.open      = setstack_2b,
+	.close     = close_hfcpci,
+};
+
+static struct dc_l1_ops hfcpci_dc_l1_ops = {
+	.fill_fifo  = hfcpci_fill_dfifo,
+	.open       = setstack_hfcpci,
+	.bh_func    = hfcpci_bh,
+	.dbusy_func = hfcpci_dbusy_timer,
 };
 
 /********************************/
@@ -1345,60 +1355,36 @@
 void __init
 inithfcpci(struct IsdnCardState *cs)
 {
-	cs->setstack_d = setstack_hfcpci;
-	cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
-	INIT_WORK(&cs->work, hfcpci_bh, cs);
-	cs->bc_l1_ops = &hfcpci_l1_ops;
-	cs->DC_Send_Data = hfcpci_fill_dfifo;
-	cs->bcs[0].BC_SetStack = setstack_2b;
-	cs->bcs[1].BC_SetStack = setstack_2b;
-	cs->bcs[0].BC_Close = close_hfcpci;
-	cs->bcs[1].BC_Close = close_hfcpci;
+	dc_l1_init(cs, &hfcpci_dc_l1_ops);
+	cs->bc_l1_ops = &hfcpci_bc_l1_ops;
 	mode_hfcpci(cs->bcs, 0, 0);
 	mode_hfcpci(cs->bcs + 1, 0, 1);
 }
 
-
-
-/*******************************************/
-/* handle card messages from control layer */
-/*******************************************/
-static int
-hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+hfcpci_init(struct IsdnCardState *cs)
 {
-	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFCPCI: card_msg %x", mt);
-	switch (mt) {
-		case CARD_RESET:
-			reset_hfcpci(cs);
-			return (0);
-		case CARD_RELEASE:
-			release_io_hfcpci(cs);
-			return (0);
-		case CARD_INIT:
-			inithfcpci(cs);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
-			/* now switch timer interrupt off */
-			cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
-			Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-			/* reinit mode reg */
-			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
-			return (0);
-		case CARD_TEST:
-			return (0);
-	}
-	return (0);
+	inithfcpci(cs);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
+	/* now switch timer interrupt off */
+	cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+	/* reinit mode reg */
+	Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
 }
 
+static struct card_ops hfcpci_ops = {
+	.init     = hfcpci_init,
+	.reset    = hfcpci_reset,
+	.release  = hfcpci_release,
+	.irq_func = hfcpci_interrupt,
+};
+
 
 /* this variable is used as card index when more than one cards are present */
 static struct pci_dev *dev_hfcpci __initdata = NULL;
 
-#endif				/* CONFIG_PCI */
-
 int __init
 setup_hfcpci(struct IsdnCard *card)
 {
@@ -1409,86 +1395,78 @@
 
 	strcpy(tmp, hfcpci_revision);
 	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-#if CONFIG_PCI
 	cs->hw.hfcpci.int_s1 = 0;
 	cs->dc.hfcpci.ph_state = 0;
 	cs->hw.hfcpci.fifo = 255;
-	if (cs->typ == ISDN_CTYPE_HFC_PCI) {
-		i = 0;
-		while (id_list[i].vendor_id) {
-			tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
-						     id_list[i].device_id,
-						     dev_hfcpci);
-			i++;
-			if (tmp_hfcpci) {
-				if (pci_enable_device(tmp_hfcpci))
-					continue;
-				pci_set_master(tmp_hfcpci);
-				if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
-					continue;
-				else
-					break;
-			}
-		}
 
+	i = 0;
+	while (id_list[i].vendor_id) {
+		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+					     id_list[i].device_id,
+					     dev_hfcpci);
+		i++;
 		if (tmp_hfcpci) {
-			i--;
-			dev_hfcpci = tmp_hfcpci;	/* old device */
-			cs->irq = dev_hfcpci->irq;
-			cs->hw.hfcpci.pdev = tmp_hfcpci;
-			if (!cs->irq) {
-				printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
-				return (0);
-			}
-			cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start;
-			printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
-		} else {
-			printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
-			return (0);
+			if (pci_enable_device(tmp_hfcpci))
+				continue;
+			pci_set_master(tmp_hfcpci);
+			if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
+				continue;
+			else
+				break;
 		}
-		if (!cs->hw.hfcpci.pci_io) {
-			printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
+	}
+	
+	if (tmp_hfcpci) {
+		i--;
+		dev_hfcpci = tmp_hfcpci;	/* old device */
+		cs->irq = dev_hfcpci->irq;
+		cs->hw.hfcpci.pdev = tmp_hfcpci;
+		if (!cs->irq) {
+			printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
 			return (0);
 		}
-		/* Allocate memory for FIFOS */
-		cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma);
-		if (!cs->hw.hfcpci.fifos) {
-			printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
-			return 0;
-		}
-		pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
-				       (u_int)cs->hw.hfcpci.fifos_dma);
-		cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
-		printk(KERN_INFO
-		       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
-		       (u_int) cs->hw.hfcpci.pci_io,
-		       (u_int) cs->hw.hfcpci.fifos,
-		       (u_int) cs->hw.hfcpci.fifos_dma,
-		       cs->irq, HZ);
-		printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
-		cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
-		cs->hw.hfcpci.int_m1 = 0;
-		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-		Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
-		/* At this point the needed PCI config is done */
-		/* fifos are still not enabled */
-	} else
-		return (0);	/* no valid card type */
-
+		printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
+	} else {
+		printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
+		return (0);
+	}
+	/* Allocate memory for FIFOS */
+	cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma);
+	if (!cs->hw.hfcpci.fifos) {
+		printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+		return 0;
+	}
+	pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
+			       (u_int)cs->hw.hfcpci.fifos_dma);
+	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci");
+	if (!cs->hw.hfcpci.pci_io)
+		goto err;
+	
+	printk(KERN_INFO
+	       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+	       (u_int) cs->hw.hfcpci.pci_io,
+	       (u_int) cs->hw.hfcpci.fifos,
+	       (u_int) cs->hw.hfcpci.fifos_dma,
+	       cs->irq, HZ);
+	printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
+	cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
+	cs->hw.hfcpci.int_m1 = 0;
+	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+	/* At this point the needed PCI config is done */
+	/* fifos are still not enabled */
 
-	cs->irq_func = &hfcpci_interrupt;
 	cs->irq_flags |= SA_SHIRQ;
 
 	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
 	cs->hw.hfcpci.timer.data = (long) cs;
 	init_timer(&cs->hw.hfcpci.timer);
 
-	reset_hfcpci(cs);
-	cs->cardmsg = &hfcpci_card_msg;
+	hfcpci_reset(cs);
 	cs->auxcmd = &hfcpci_auxcmd;
-	return (1);
-#else
-	printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
-	return (0);
-#endif				/* CONFIG_PCI */
+	cs->card_ops = &hfcpci_ops;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
--- a/drivers/isdn/hisax/hfc_sx.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/hfc_sx.c	Mon Jan 13 10:18:05 2003
@@ -308,8 +308,8 @@
 /******************************************/
 /* free hardware resources used by driver */
 /******************************************/
-void
-release_io_hfcsx(struct IsdnCardState *cs)
+static void
+hfcsx_release(struct IsdnCardState *cs)
 {
 	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
@@ -318,7 +318,7 @@
 	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
 	Write_hfc(cs, HFCSX_CIRM, 0);	/* Reset Off */
 	del_timer(&cs->hw.hfcsx.timer);
-	release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */
+	hisax_release_resources(cs);
 	kfree(cs->hw.hfcsx.extra);
 	cs->hw.hfcsx.extra = NULL;
 }
@@ -347,8 +347,8 @@
 /* function called to reset the HFC SX chip. A complete software reset of chip */
 /* and fifos is done.                                                           */
 /********************************************************************************/
-static void
-reset_hfcsx(struct IsdnCardState *cs)
+static int
+hfcsx_reset(struct IsdnCardState *cs)
 {
 	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
@@ -415,6 +415,7 @@
 	cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
 	if (Read_hfc(cs, HFCSX_INT_S2));
+	return 0;
 }
 
 /***************************************************/
@@ -838,10 +839,11 @@
 /***********************************************/
 /* called during init setting l1 stack pointer */
 /***********************************************/
-void
+static int
 setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCSX_l1hw;
+	return 0;
 }
 
 /***************************************************************/
@@ -1112,8 +1114,17 @@
 		DChannel_proc_xmt(cs);
 }
 
-static struct bc_l1_ops hfcsx_l1_ops = {
+static struct bc_l1_ops hfcsx_bc_l1_ops = {
 	.fill_fifo = hfcsx_fill_fifo,
+	.open      = setstack_2b,
+	.close     = close_hfcsx,
+};
+
+static struct dc_l1_ops hfcsx_dc_l1_ops = {
+	.fill_fifo  = hfcsx_fill_dfifo,
+	.open       = setstack_hfcsx,
+	.bh_func    = hfcsx_bh,
+	.dbusy_func = hfcsx_dbusy_timer,
 };
 
 /********************************/
@@ -1122,54 +1133,32 @@
 void __devinit
 inithfcsx(struct IsdnCardState *cs)
 {
-	cs->setstack_d = setstack_hfcsx;
-	cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
-	INIT_WORK(&cs->work, hfcsx_bh, cs);
-	cs->bc_l1_ops = &hfcsx_l1_ops;
-	cs->DC_Send_Data = hfcsx_fill_dfifo;
-	cs->bcs[0].BC_SetStack = setstack_2b;
-	cs->bcs[1].BC_SetStack = setstack_2b;
-	cs->bcs[0].BC_Close = close_hfcsx;
-	cs->bcs[1].BC_Close = close_hfcsx;
+	dc_l1_init(cs, &hfcsx_dc_l1_ops);
+	cs->bc_l1_ops = &hfcsx_bc_l1_ops;
 	mode_hfcsx(cs->bcs, 0, 0);
 	mode_hfcsx(cs->bcs + 1, 0, 1);
 }
 
-
-
-/*******************************************/
-/* handle card messages from control layer */
-/*******************************************/
-static int
-hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+hfcsx_init(struct IsdnCardState *cs)
 {
-	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFCSX: card_msg %x", mt);
-	switch (mt) {
-		case CARD_RESET:
-			reset_hfcsx(cs);
-			return (0);
-		case CARD_RELEASE:
-			release_io_hfcsx(cs);
-			return (0);
-		case CARD_INIT:
-			inithfcsx(cs);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
-			/* now switch timer interrupt off */
-			cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
-			Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-			/* reinit mode reg */
-			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
-			return (0);
-		case CARD_TEST:
-			return (0);
-	}
-	return (0);
+	inithfcsx(cs);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
+	/* now switch timer interrupt off */
+	cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	/* reinit mode reg */
+	Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
 }
 
+static struct card_ops hfcsx_ops = {
+	.init     = hfcsx_init,
+	.reset    = hfcsx_reset,
+	.release  = hfcsx_release,
+	.irq_func = hfcsx_interrupt,
+};
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
@@ -1179,7 +1168,7 @@
 };
 
 static struct isapnp_device_id *hdev = &hfc_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
@@ -1192,29 +1181,38 @@
 	printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pci_bus *pb;
-		struct pci_dev *pd;
+		struct pnp_card *pb;
+		struct pnp_dev  *pd;
 
 		while(hdev->card_vendor) {
-			if ((pb = isapnp_find_card(hdev->card_vendor,
-				hdev->card_device, pnp_c))) {
+			if ((pb = pnp_find_card(hdev->card_vendor,
+						hdev->card_device,
+						pnp_c))) {
 				pnp_c = pb;
 				pd = NULL;
-				if ((pd = isapnp_find_dev(pnp_c,
-					hdev->vendor, hdev->function, pd))) {
+				if ((pd = pnp_find_dev(pnp_c,
+						       hdev->vendor,
+						       hdev->function,
+						       pd))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
 						(char *)hdev->driver_data);
-					pd->prepare(pd);
-					pd->deactivate(pd);
-					pd->activate(pd);
-					card->para[1] = pd->resource[0].start;
-					card->para[0] = pd->irq_resource[0].start;
-					if (!card->para[0] || !card->para[1]) {
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "HFC PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd, NULL) < 0) {
+						printk(KERN_ERR "HFC PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
 						printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
-						card->para[0], card->para[1]);
-						pd->deactivate(pd);
+							pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
 						return(0);
 					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
 					break;
 				} else {
 					printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
@@ -1234,61 +1232,48 @@
 	cs->hw.hfcsx.int_s1 = 0;
 	cs->dc.hfcsx.ph_state = 0;
 	cs->hw.hfcsx.fifo = 255;
-	if ((cs->typ == ISDN_CTYPE_HFC_SX) || 
-	    (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) {
-	        if ((!cs->hw.hfcsx.base) || 
-		    check_region((cs->hw.hfcsx.base), 2)) {
-		  printk(KERN_WARNING
-			 "HiSax: HFC-SX io-base %#lx already in use\n",
-		          cs->hw.hfcsx.base);
-		  return(0);
-		} else {
-		  request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn");
-		}
-		byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
-		byteout(cs->hw.hfcsx.base + 1,
-			((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
-		udelay(10);
-	        cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
-                switch (cs->hw.hfcsx.chip >> 4) {
-		  case 1: 
-		    tmp[0] ='+';
-		    break;
-		  case 9: 
-		    tmp[0] ='P';
-		    break;
-		  default:
-		    printk(KERN_WARNING
-			   "HFC-SX: invalid chip id 0x%x\n",
-			   cs->hw.hfcsx.chip >> 4);
-		    release_region(cs->hw.hfcsx.base, 2);
-		    return(0);
-		}  
-		if (!ccd_sp_irqtab[cs->irq & 0xF]) {
-		  printk(KERN_WARNING 
-			 "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF);
-		  release_region(cs->hw.hfcsx.base, 2);
-		  return(0);
-		}  
-		if (!(cs->hw.hfcsx.extra = (void *)
-		      kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
-		  release_region(cs->hw.hfcsx.base, 2);
-		  printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
-		  return(0);
-		}
-
-		printk(KERN_INFO
-		       "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
-		       tmp[0], (u_int) cs->hw.hfcsx.base,
-		       cs->irq, HZ);
-		cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
-		cs->hw.hfcsx.int_m1 = 0;
-		Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-		Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
-	} else
-		return (0);	/* no valid card type */
 
-	cs->irq_func = &hfcsx_interrupt;
+	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
+		return 0;
+	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
+	byteout(cs->hw.hfcsx.base + 1,
+		((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
+	udelay(10);
+	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
+	switch (cs->hw.hfcsx.chip >> 4) {
+	case 1: 
+		tmp[0] ='+';
+		break;
+	case 9: 
+		tmp[0] ='P';
+		break;
+	default:
+		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
+		       cs->hw.hfcsx.chip >> 4);
+		hisax_release_resources(cs);
+		return 0;
+	}  
+	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
+		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
+		       cs->irq & 0xF);
+		hisax_release_resources(cs);
+		return 0;
+	}  
+	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), 
+				     GFP_ATOMIC);
+	if (!cs->hw.hfcsx.extra) {
+		hisax_release_resources(cs);
+		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
+		return 0;
+	}
+	
+	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
+	       tmp[0], (u_int) cs->hw.hfcsx.base,
+	       cs->irq, HZ);
+	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
+	cs->hw.hfcsx.int_m1 = 0;
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
 
 	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
 	cs->hw.hfcsx.timer.data = (long) cs;
@@ -1296,8 +1281,8 @@
 	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
 	init_timer(&cs->hw.hfcsx.timer);
 
-	reset_hfcsx(cs);
-	cs->cardmsg = &hfcsx_card_msg;
+	hfcsx_reset(cs);
 	cs->auxcmd = &hfcsx_auxcmd;
-	return (1);
+	cs->card_ops = &hfcsx_ops;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
--- a/drivers/isdn/hisax/hfcscard.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/hfcscard.c	Mon Jan 13 10:18:07 2003
@@ -64,17 +64,16 @@
 */
 }
 
-void
-release_io_hfcs(struct IsdnCardState *cs)
+static void
+hfcs_release(struct IsdnCardState *cs)
 {
 	release2bds0(cs);
 	del_timer(&cs->hw.hfcD.timer);
-	if (cs->hw.hfcD.addr)
-		release_region(cs->hw.hfcD.addr, 2);
+	hisax_release_resources(cs);
 }
 
-static void
-reset_hfcs(struct IsdnCardState *cs)
+static int
+hfcs_reset(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "HFCS: resetting card\n");
 	cs->hw.hfcD.cirm = HFCD_RESET;
@@ -111,36 +110,29 @@
 	hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */
 	cs->hw.hfcD.sctrl = 0;
 	hfcs_write_reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
+	return 0;
 }
 
-static int
-hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+hfcs_init(struct IsdnCardState *cs)
 {
-	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFCS: card_msg %x", mt);
-	switch (mt) {
-		case CARD_RESET:
-			reset_hfcs(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_hfcs(cs);
-			return(0);
-		case CARD_INIT:
-			cs->hw.hfcD.timer.expires = jiffies + 75;
-			add_timer(&cs->hw.hfcD.timer);
-			init2bds0(cs);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout((80*HZ)/1000);
-			cs->hw.hfcD.ctmt |= HFCD_TIM800;
-			hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); 
-			hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
+	cs->hw.hfcD.timer.expires = jiffies + 75;
+	add_timer(&cs->hw.hfcD.timer);
+	init2bds0(cs);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((80*HZ)/1000);
+	cs->hw.hfcD.ctmt |= HFCD_TIM800;
+	hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); 
+	hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
 }
 
+static struct card_ops hfcs_ops = {
+	.init     = hfcs_init,
+	.reset    = hfcs_reset,
+	.release  = hfcs_release,
+	.irq_func = hfcs_interrupt,
+};
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
@@ -168,7 +160,7 @@
 };
 
 static struct isapnp_device_id *hdev = &hfc_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __init
@@ -182,29 +174,38 @@
 
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pci_bus *pb;
-		struct pci_dev *pd;
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
 
 		while(hdev->card_vendor) {
-			if ((pb = isapnp_find_card(hdev->card_vendor,
-				hdev->card_device, pnp_c))) {
+			if ((pb = pnp_find_card(hdev->card_vendor,
+						hdev->card_device,
+						pnp_c))) {
 				pnp_c = pb;
 				pd = NULL;
-				if ((pd = isapnp_find_dev(pnp_c,
-					hdev->vendor, hdev->function, pd))) {
+				if ((pd = pnp_find_dev(pnp_c,
+						       hdev->vendor,
+						       hdev->function,
+						       pd))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
 						(char *)hdev->driver_data);
-					pd->prepare(pd);
-					pd->deactivate(pd);
-					pd->activate(pd);
-					card->para[1] = pd->resource[0].start;
-					card->para[0] = pd->irq_resource[0].start;
-					if (!card->para[0] || !card->para[1]) {
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "HFC PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd, NULL) < 0) {
+						printk(KERN_ERR "HFC PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
 						printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
-						card->para[0], card->para[1]);
-						pd->deactivate(pd);
+							pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
 						return(0);
 					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
 					break;
 				} else {
 					printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
@@ -235,16 +236,8 @@
 		cs->hw.hfcD.bfifosize = 7*1024 + 512;
 	} else
 		return (0);
-	if (check_region((cs->hw.hfcD.addr), 2)) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.hfcD.addr,
-		       cs->hw.hfcD.addr + 2);
-		return (0);
-	} else {
-		request_region(cs->hw.hfcD.addr, 2, "HFCS isdn");
-	}
+	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
+		return 0;
 	printk(KERN_INFO
 	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
 	       cs->hw.hfcD.addr,
@@ -262,8 +255,7 @@
 	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
 	cs->hw.hfcD.timer.data = (long) cs;
 	init_timer(&cs->hw.hfcD.timer);
-	reset_hfcs(cs);
-	cs->cardmsg = &hfcs_card_msg;
-	cs->irq_func = &hfcs_interrupt;
+	hfcs_reset(cs);
+	cs->card_ops = &hfcs_ops;
 	return (1);
 }
diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
--- a/drivers/isdn/hisax/hisax.h	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/hisax.h	Mon Jan 13 10:18:06 2003
@@ -6,6 +6,10 @@
  * of the GNU General Public License, incorporated herein by reference.
  *
  */
+
+#ifndef __HISAX_H__
+#define __HISAX_H__
+
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -46,11 +50,6 @@
 #define HW_INFO4_P10	0x0048
 #define HW_RSYNC	0x0060
 #define HW_TESTLOOP	0x0070
-#define CARD_RESET	0x00F0
-#define CARD_INIT	0x00F2
-#define CARD_RELEASE	0x00F3
-#define CARD_TEST	0x00F4
-#define CARD_AUX_IND	0x00F5
 
 #define PH_ACTIVATE	0x0100
 #define PH_DEACTIVATE	0x0110
@@ -68,14 +67,9 @@
 #define DL_FLUSH	0x0224
 #define DL_UNIT_DATA	0x0230
 
-#define MDL_BC_RELEASE  0x0278  // Formula-n enter:now
-#define MDL_BC_ASSIGN   0x027C  // Formula-n enter:now
 #define MDL_ASSIGN	0x0280
 #define MDL_REMOVE	0x0284
 #define MDL_ERROR	0x0288
-#define MDL_INFO_SETUP	0x02E0
-#define MDL_INFO_CONN	0x02E4
-#define MDL_INFO_REL	0x02E8
 
 #define CC_SETUP	0x0300
 #define CC_RESUME	0x0304
@@ -150,6 +144,35 @@
 /* #define I4L_IRQ_FLAG SA_INTERRUPT */
 #define I4L_IRQ_FLAG    0
 
+struct res {
+	struct list_head node;
+	const char *name;
+	unsigned long start, end;
+	unsigned long flags;
+	union {
+		void *ioremap_addr;
+	} r_u;
+};
+
+struct resources {
+	struct list_head res_head;
+};
+
+void
+resources_init(struct resources *rs);
+
+void
+resources_release(struct resources *rs);
+
+unsigned long
+request_io(struct resources *rs, unsigned long start, int len,
+	   const char *name);
+
+void *
+request_mmio(struct resources *rs, unsigned long start, int len,
+	     const char *name);
+
+
 /*
  * Statemachine
  */
@@ -349,17 +372,12 @@
 };
 
 struct hscx_hw {
-	int hscx;
-	int rcvidx;
-	u8 *rcvbuf;         /* B-Channel receive Buffer */
 	u8 tsaxr0;
 	u8 tsaxr1;
 };
 
 struct w6692B_hw {
 	int bchan;
-	int rcvidx;
-	u8 *rcvbuf;         /* B-Channel receive Buffer */
 };
 
 struct isar_reg {
@@ -407,8 +425,6 @@
 		struct hdlc_stat_reg sr;
 	} ctrl;
 	u_int stat;
-	int rcvidx;
-	u8 *rcvbuf;         /* B-Channel receive Buffer */
 };
 
 struct hfcB_hw {
@@ -479,10 +495,13 @@
 struct BCState {
 	int channel;
 	int mode;
-	long Flag; /* long req'd for set_bit --RR */
+	long Flag;
 	struct IsdnCardState *cs;
-	int tx_cnt;		/* B-Channel transmit counter */
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
+	int unit;                       /* first or second unit (e.g. HSCX) */
+	int rcvidx;
+	u8 *rcvbuf;                     /* B-Channel receive Buffer */
+	int tx_cnt;  		        /* B-Channel transmit counter */
+	struct sk_buff *tx_skb;         /* B-Channel transmit Buffer */
 	struct sk_buff_head rqueue;	/* B-Channel receive queue */
 	struct sk_buff_head squeue;	/* B-Channel send queue */
 	struct sk_buff_head cmpl_queue;	/* B-Channel send complete queue */
@@ -492,8 +511,6 @@
 	struct timer_list transbusy;
 	struct work_struct work;
 	unsigned long event;
-	int  (*BC_SetStack) (struct PStack *, struct BCState *);
-	void (*BC_Close) (struct BCState *);
 #ifdef ERROR_STATISTIC
 	int err_crc;
 	int err_tx;
@@ -570,8 +587,8 @@
 
 struct teles0_hw {
 	unsigned int cfg_reg;
-	unsigned long membase;
 	unsigned long phymem;
+	void *membase;
 };
 
 struct avm_hw {
@@ -599,7 +616,6 @@
 	unsigned int isac;
 	unsigned long hscx_adr;
 	unsigned int hscx;
-	unsigned int status;
 	struct timer_list tl;
 	u8 ctrl_reg;
 };
@@ -661,6 +677,8 @@
 	unsigned char irqstat0;
 	unsigned char last_is0;
 	struct pci_dev *pdev;
+	void (*bc_activate)(struct IsdnCardState *cs, int bc);
+	void (*bc_deactivate)(struct IsdnCardState *cs, int bc);
 };
 
 struct hfcPCI_hw {
@@ -737,9 +755,8 @@
 
 struct isurf_hw {
 	unsigned int reset;
-	unsigned long phymem;
-	unsigned long isac;
-	unsigned long isar;
+	void *isac;
+	void *isar;
 	struct isar_reg isar_r;
 };
 
@@ -861,6 +878,18 @@
 
 struct IsdnCardState;
 
+/* Methods provided by driver for a specific card */
+
+struct card_ops {
+	void   (*init)       (struct IsdnCardState *);
+	void   (*test)       (struct IsdnCardState *);
+	int    (*reset)      (struct IsdnCardState *);
+	void   (*release)    (struct IsdnCardState *);
+	void   (*aux_ind)    (struct IsdnCardState *, void *);
+	void   (*led_handler)(struct IsdnCardState *);
+	void   (*irq_func)   (int, void *, struct pt_regs *);
+};
+
 /* Card specific drivers provide methods to access the
  * chips to the chip drivers */
 
@@ -878,10 +907,23 @@
 	void   (*write_fifo) (struct IsdnCardState *, u8 *, int);
 };
 
-/* Methods provided to shared FIFO handling */
+/* Methods provided to shared B-channel FIFO handling */
 
 struct bc_l1_ops {
 	void   (*fill_fifo)  (struct BCState *);
+	int    (*open)       (struct PStack *, struct BCState *);
+	void   (*close)      (struct BCState *);
+};
+
+/* Methods provided to shared D-channel FIFO handling */
+
+struct dc_l1_ops {
+	void   (*fill_fifo)  (struct IsdnCardState *);
+	int    (*open)       (struct PStack *, struct IsdnCardState *);
+	void   (*close)      (struct IsdnCardState *);
+
+	void   (*bh_func)    (void *);
+	void   (*dbusy_func) (struct IsdnCardState *);
 };
 
 #define HW_IOM1			0
@@ -900,9 +942,12 @@
 	unsigned char typ;
 	unsigned char subtyp;
 	spinlock_t lock;
+	struct card_ops *card_ops;
 	int protocol;
+	struct resources rs;
 	unsigned int irq;
 	unsigned long irq_flags;
+	int status;
 	long HW_Flags;
 	int *busy_flag;
         int chanlimit; /* limited number of B-chans to use */
@@ -942,12 +987,9 @@
 	u8 *status_end;
 	struct dc_hw_ops *dc_hw_ops;
 	struct bc_hw_ops *bc_hw_ops;
+	struct dc_l1_ops *dc_l1_ops;
 	struct bc_l1_ops *bc_l1_ops;
 	int    (*cardmsg) (struct IsdnCardState *, int, void *);
-	void   (*setstack_d) (struct PStack *, struct IsdnCardState *);
-	void   (*DC_Send_Data) (struct IsdnCardState *);
-	void   (*DC_Close) (struct IsdnCardState *);
-	void   (*irq_func) (int, void *, struct pt_regs *);
 	int    (*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
 	struct Channel channel[2+MAX_WAITING_CALLS];
 	struct BCState bcs[2+MAX_WAITING_CALLS];
@@ -979,6 +1021,9 @@
 #endif
 };
 
+void
+hisax_release_resources(struct IsdnCardState *cs);
+
 #define  MON0_RX	1
 #define  MON1_RX	2
 #define  MON0_TX	4
@@ -1363,9 +1408,6 @@
 void LogFrame(struct IsdnCardState *cs, u8 * p, int size);
 void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
 void iecpy(u8 * dest, u8 * iestart, int ieoffset);
-#ifdef ISDN_CHIP_ISAC
-void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
-#endif	/* ISDN_CHIP_ISAC */
 #endif	/* __KERNEL__ */
 
 #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
@@ -1424,3 +1466,6 @@
 {
 	st->l3.l4l3(st, pr, arg);
 }
+
+
+#endif
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	Mon Jan 13 10:18:07 2003
@@ -27,7 +27,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/isapnp.h>
+#include <linux/pnp.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
@@ -46,6 +46,9 @@
 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
 MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
 
+// FIXME temporary hack until I sort out the new PnP stuff
+#define __ISAPNP__
+
 static struct pci_device_id fcpci_ids[] __devinitdata = {
 	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1   , PCI_ANY_ID, PCI_ANY_ID,
 	  0, 0, (unsigned long) "Fritz!Card PCI" },
@@ -55,13 +58,12 @@
 };
 MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
-static struct isapnp_device_id fcpnp_ids[] __devinitdata = {
-	{ ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900),
-	  ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), 
-	  (unsigned long) "Fritz!Card PnP" },
-	{ }
+static struct pnp_card_id fcpnp_ids[] __devinitdata = {
+	{ .id = "AVM0900", 
+	  .driver_data = (unsigned long) "Fritz!Card PnP",
+	  .devs = { { "AVM0900" } } }
 };
-MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
+//MODULE_DEVICE_TABLE(pnpc, fcpnp_ids); FIXME
 
 static int protocol = 2;       /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
@@ -908,50 +910,54 @@
 
 #ifdef __ISAPNP__
 
-static int __devinit fcpnp_probe(struct pci_dev *pdev,
-				 const struct isapnp_device_id *ent)
+static int __devinit fcpnp_probe(struct pnp_card *card,
+				 const struct pnp_card_id *card_id)
 {
 	struct fritz_adapter *adapter;
+	struct pnp_dev *pnp_dev;
 	int retval;
 
+	retval = -ENODEV;
+	pnp_dev = pnp_request_card_device(card, card_id->devs[0].id, NULL);
+	if (!pnp_dev)
+		goto err;
+
+	if (!pnp_port_valid(pnp_dev, 0) || !pnp_irq_valid(pnp_dev, 0))
+		goto err;
+
 	retval = -ENOMEM;
-	adapter = new_adapter(pdev);
+	adapter = new_adapter((struct pci_dev *)pnp_dev); // FIXME
 	if (!adapter)
 		goto err;
-
+	
 	adapter->type = AVM_FRITZ_PNP;
-
-	pdev->prepare(pdev);
-	pdev->deactivate(pdev); // why?
-	pdev->activate(pdev);
-	adapter->io = pdev->resource[0].start;
-	adapter->irq = pdev->irq_resource[0].start;
-
+	adapter->io = pnp_port_start(pnp_dev, 0);
+	adapter->irq = pnp_irq(pnp_dev, 0);
+	
 	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
-	       (char *) ent->driver_data, adapter->io, adapter->irq);
-
+	       (char *) card_id->driver_data, adapter->io, adapter->irq);
+	
 	retval = fcpcipnp_setup(adapter);
 	if (retval)
-		goto err_free;
-
+		goto err_delete;
+	
 	return 0;
 	
- err_free:
+ err_delete:
 	delete_adapter(adapter);
  err:
 	return retval;
 }
 
-static void __devexit fcpnp_remove(struct pci_dev *pdev)
+static void __devexit fcpnp_remove(struct pnp_card *pcard)
 {
-	struct fritz_adapter *adapter = pci_get_drvdata(pdev);
+	struct fritz_adapter *adapter = pnpc_get_drvdata(pcard);
 
 	fcpcipnp_release(adapter);
-	pdev->deactivate(pdev);
 	delete_adapter(adapter);
 }
 
-static struct isapnp_driver fcpnp_driver = {
+static struct pnpc_driver fcpnp_driver = {
 	.name     = "fcpnp",
 	.probe    = fcpnp_probe,
 	.remove   = __devexit_p(fcpnp_remove),
@@ -972,7 +978,7 @@
 	pci_nr_found = retval;
 
 #ifdef __ISAPNP__
-	retval = isapnp_register_driver(&fcpnp_driver);
+	retval = pnpc_register_driver(&fcpnp_driver);
 #else
 	retval = 0;
 #endif
@@ -990,7 +996,7 @@
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
  out_unregister_isapnp:
 #ifdef __ISAPNP__
-	isapnp_unregister_driver(&fcpnp_driver);
+	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 #endif
  out_unregister_pci:
@@ -1002,7 +1008,7 @@
 static void __exit hisax_fcpcipnp_exit(void)
 {
 #ifdef __ISAPNP__
-	isapnp_unregister_driver(&fcpnp_driver);
+	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 	pci_unregister_driver(&fcpci_driver);
 }
diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c
--- a/drivers/isdn/hisax/hisax_hfcpci.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/hisax_hfcpci.c	Mon Jan 13 10:18:05 2003
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/isapnp.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
@@ -1605,7 +1604,7 @@
 static struct pci_driver hfcpci_driver = {
 	.name     = "hfcpci",
 	.probe    = hfcpci_probe,
-	.remove   = hfcpci_remove,
+	.remove   = __devexit_p(hfcpci_remove),
 	.id_table = hfcpci_ids,
 };
 
diff -Nru a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
--- a/drivers/isdn/hisax/hscx.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/hscx.c	Mon Jan 13 10:18:05 2003
@@ -25,39 +25,27 @@
 hscx_read(struct BCState *bcs, u8 addr)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
 
-	return cs->bc_hw_ops->read_reg(cs, hscx, addr);
+	return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr);
 }
 
 static inline void
 hscx_write(struct BCState *bcs, u8 addr, u8 val)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
 
-	cs->bc_hw_ops->write_reg(cs, hscx, addr, val);
-}
-
-static inline void
-hscx_read_fifo(struct BCState *bcs, u8 *p, int len)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
-
-	cs->bc_hw_ops->read_fifo(cs, hscx, p, len);
+	cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val);
 }
 
 static inline void
 hscx_write_fifo(struct BCState *bcs, u8 *p, int len)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
 
-	cs->bc_hw_ops->write_fifo(cs, hscx, p, len);
+	cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len);
 }
 
-int __init
+static int
 HscxVersion(struct IsdnCardState *cs, char *s)
 {
 	int verA, verB;
@@ -67,16 +55,16 @@
 	printk(KERN_INFO "%s HSCX version A: %s  B: %s\n", s,
 	       HSCXVer[verA], HSCXVer[verB]);
 	if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf))
-		return (1);
+		return 1;
 	else
-		return (0);
+		return 0;
 }
 
 void
 modehscx(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int hscx = bcs->hw.hscx.hscx;
+	int hscx = bcs->unit;
 
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "hscx %c mode %d ichan %d",
@@ -164,52 +152,17 @@
 close_hscxstate(struct BCState *bcs)
 {
 	modehscx(bcs, 0, bcs->channel);
-	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (bcs->hw.hscx.rcvbuf) {
-			kfree(bcs->hw.hscx.rcvbuf);
-			bcs->hw.hscx.rcvbuf = NULL;
-		}
-		if (bcs->blog) {
-			kfree(bcs->blog);
-			bcs->blog = NULL;
-		}
-		skb_queue_purge(&bcs->rqueue);
-		skb_queue_purge(&bcs->squeue);
-		skb_queue_purge(&bcs->cmpl_queue);
-		if (bcs->tx_skb) {
-			dev_kfree_skb_any(bcs->tx_skb);
-			bcs->tx_skb = NULL;
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		}
-	}
+	bc_close(bcs);
 }
 
 int
 open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-				"HiSax: No memory for hscx.rcvbuf\n");
-			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-			return (1);
-		}
-		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-				"HiSax: No memory for bcs->blog\n");
-			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-			kfree(bcs->hw.hscx.rcvbuf);
-			bcs->hw.hscx.rcvbuf = NULL;
-			return (2);
-		}
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-		skb_queue_head_init(&bcs->cmpl_queue);
-	}
+	bc_open(bcs);
 	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	bcs->event = 0;
-	bcs->hw.hscx.rcvidx = 0;
+	bcs->rcvidx = 0;
 	bcs->tx_cnt = 0;
 	return (0);
 }
@@ -228,8 +181,12 @@
 	return (0);
 }
 
+static void hscx_fill_fifo(struct BCState *bcs);
+
 static struct bc_l1_ops hscx_l1_ops = {
 	.fill_fifo = hscx_fill_fifo,
+	.open      = setstack_hscx,
+	.close     = close_hscxstate,
 };
 
 void __init
@@ -238,12 +195,8 @@
 	int val, eval;
 	
 	cs->bc_l1_ops = &hscx_l1_ops;
-	cs->bcs[0].BC_SetStack = setstack_hscx;
-	cs->bcs[1].BC_SetStack = setstack_hscx;
-	cs->bcs[0].BC_Close = close_hscxstate;
-	cs->bcs[1].BC_Close = close_hscxstate;
-	cs->bcs[0].hw.hscx.hscx = 0;
-	cs->bcs[1].hw.hscx.hscx = 1;
+	cs->bcs[0].unit = 0;
+	cs->bcs[1].unit = 1;
 	cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
 	cs->bcs[0].hw.hscx.tsaxr1 = 3;
 	cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
@@ -277,11 +230,24 @@
 	hscx_write(&cs->bcs[1], HSCX_MASK, 0x0);
 }
 
-void __init
+void
 inithscxisac(struct IsdnCardState *cs)
 {
 	initisac(cs);
 	inithscx(cs);
+}
+
+int
+hscxisac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops,
+	       struct bc_hw_ops *hscx_ops)
+{
+	isac_setup(cs, isac_ops);
+	cs->bc_hw_ops = hscx_ops;
+	if (HscxVersion(cs, "HiSax:")) {
+		printk(KERN_WARNING "HiSax: invalid HSCX version\n");
+		return -ENODEV;
+	}
+	return 0;
 }
 
 #include "hscx_irq.c"
diff -Nru a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h
--- a/drivers/isdn/hisax/hscx.h	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/hscx.h	Mon Jan 13 10:18:06 2003
@@ -34,8 +34,10 @@
 #define HSCX_RLCR 0x2e
 #define HSCX_MASK 0x20
 
-extern int HscxVersion(struct IsdnCardState *cs, char *s);
 extern void modehscx(struct BCState *bcs, int mode, int bc);
 extern void inithscxisac(struct IsdnCardState *cs);
 extern void hscx_int_main(struct IsdnCardState *cs, u8 val);
-extern void hscx_fill_fifo(struct BCState *bcs);
+extern void hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs);
+extern int  hscxisac_setup(struct IsdnCardState *cs,
+			   struct dc_hw_ops *isac_ops,
+			   struct bc_hw_ops *hscx_ops);
diff -Nru a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
--- a/drivers/isdn/hisax/hscx_irq.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/hscx_irq.c	Mon Jan 13 10:18:07 2003
@@ -26,7 +26,7 @@
 }
 
 
-static inline void
+static void
 waitforXFW(struct BCState *bcs)
 {
 	int to = 50;
@@ -50,71 +50,25 @@
 static void
 hscx_empty_fifo(struct BCState *bcs, int count)
 {
-	u8 *ptr;
-	struct IsdnCardState *cs = bcs->cs;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hscx_empty_fifo");
-
-	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
-		WriteHSCXCMDR(bcs, 0x80);
-		bcs->hw.hscx.rcvidx = 0;
-		return;
-	}
-	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
-	bcs->hw.hscx.rcvidx += count;
-	hscx_read_fifo(bcs, ptr, count);
+	recv_empty_fifo_b(bcs, count);
 	WriteHSCXCMDR(bcs, 0x80);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
-			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
 }
 
-void
+static void
 hscx_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
 	int more, count;
 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
-	u8 *ptr;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hscx_fill_fifo");
+	u8 *p;
 
-	if (!bcs->tx_skb)
-		return;
-	if (bcs->tx_skb->len <= 0)
+	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
+	if (!p)
 		return;
 
-	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
-	if (bcs->tx_skb->len > fifo_size) {
-		more = !0;
-		count = fifo_size;
-	} else
-		count = bcs->tx_skb->len;
-
 	waitforXFW(bcs);
-	ptr = bcs->tx_skb->data;
-	skb_pull(bcs->tx_skb, count);
-	bcs->tx_cnt -= count;
-	bcs->count += count;
-	hscx_write_fifo(bcs, ptr, count);
+	hscx_write_fifo(bcs, p, count);
 	WriteHSCXCMDR(bcs, more ? 0x8 : 0xa);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
-			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
 }
 
 static inline void
@@ -122,7 +76,6 @@
 {
 	u8 r;
 	struct BCState *bcs = cs->bcs + hscx;
-	struct sk_buff *skb;
 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
 	int count;
 
@@ -155,39 +108,19 @@
 #endif
 			}
 			WriteHSCXCMDR(bcs, 0x80);
+			bcs->rcvidx = 0;
 		} else {
-			count = hscx_read(bcs, HSCX_RBCL) & (
-				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
+			count = hscx_read(bcs, HSCX_RBCL) & (fifo_size-1);
 			if (count == 0)
 				count = fifo_size;
+
 			hscx_empty_fifo(bcs, count);
-			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
-				if (cs->debug & L1_DEB_HSCX_FIFO)
-					debugl1(cs, "HX Frame %d", count);
-				if (!(skb = dev_alloc_skb(count)))
-					printk(KERN_WARNING "HSCX: receive out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
-					skb_queue_tail(&bcs->rqueue, skb);
-				}
-			}
+			recv_rme_b(bcs);
 		}
-		bcs->hw.hscx.rcvidx = 0;
-		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		hscx_empty_fifo(bcs, fifo_size);
-		if (bcs->mode == L1_MODE_TRANS) {
-			/* receive audio data */
-			if (!(skb = dev_alloc_skb(fifo_size)))
-				printk(KERN_WARNING "HiSax: receive out of memory\n");
-			else {
-				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
-				skb_queue_tail(&bcs->rqueue, skb);
-			}
-			bcs->hw.hscx.rcvidx = 0;
-			sched_b_event(bcs, B_RCVBUFREADY);
-		}
+		recv_rpf_b(bcs);
 	}
 	if (val & 0x10) {
 		xmit_xpr_b(bcs);
@@ -203,11 +136,9 @@
 void
 hscx_int_main(struct IsdnCardState *cs, u8 val)
 {
-
 	u8 exval;
 	struct BCState *bcs;
 
-	spin_lock(&cs->lock);
 	if (val & 0x01) {
 		bcs = cs->bcs + 1;
 		exval = hscx_read(bcs, HSCX_EXIR);
@@ -238,5 +169,57 @@
 			debugl1(cs, "HSCX A interrupt %x", exval);
 		hscx_interrupt(cs, exval, 0);
 	}
+}
+
+/* ====================================================================== */
+
+static inline u8
+isac_read(struct IsdnCardState *cs, u8 addr)
+{
+	return cs->dc_hw_ops->read_reg(cs, addr);
+}
+
+static inline void
+isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
+{
+	cs->dc_hw_ops->write_reg(cs, addr, val);
+}
+
+void
+hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u8 val;
+	int count = 0;
+
+	spin_lock(&cs->lock);
+	val = hscx_read(&cs->bcs[1], HSCX_ISTA);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = isac_read(cs, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	count++;
+	val = hscx_read(&cs->bcs[1], HSCX_ISTA);
+	if (val && count < 5) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = isac_read(cs, ISAC_ISTA);
+	if (val && count < 5) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF);
+	hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF);
+	isac_write(cs, ISAC_MASK, 0xFF);
+	isac_write(cs, ISAC_MASK, 0x0);
+	hscx_write(&cs->bcs[0], HSCX_MASK, 0x0);
+	hscx_write(&cs->bcs[1], HSCX_MASK, 0x0);
 	spin_unlock(&cs->lock);
 }
+
diff -Nru a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
--- a/drivers/isdn/hisax/icc.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/icc.c	Mon Jan 13 10:18:05 2003
@@ -23,7 +23,6 @@
 
 #define DBUSY_TIMER_VALUE 80
 #define ARCOFI_USE 0
-static spinlock_t icc_lock = SPIN_LOCK_UNLOCKED;
 
 static inline u8
 icc_read_reg(struct IsdnCardState *cs, u8 addr)
@@ -52,7 +51,7 @@
 static char *ICCVer[] __initdata =
 {"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"};
 
-void
+static void
 ICCVersion(struct IsdnCardState *cs, char *s)
 {
 	int val;
@@ -137,33 +136,8 @@
 void
 icc_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	u8 *ptr;
-	unsigned long flags;
-
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, "icc_empty_fifo");
-
-	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "icc_empty_fifo overrun %d",
-				cs->rcvidx + count);
-		icc_write_reg(cs, ICC_CMDR, 0x80);
-		cs->rcvidx = 0;
-		return;
-	}
-	ptr = cs->rcvbuf + cs->rcvidx;
-	cs->rcvidx += count;
-	spin_lock_irqsave(&icc_lock, flags);
-	icc_read_fifo(cs, ptr, count);
+	recv_empty_fifo_d(cs, count);
 	icc_write_reg(cs, ICC_CMDR, 0x80);
-	spin_unlock_irqrestore(&icc_lock, flags);
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "icc_empty_fifo cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
 }
 
 static void
@@ -171,13 +145,11 @@
 {
 	int count, more;
 	unsigned char *p;
-	unsigned long flags;
 
 	p = xmit_fill_fifo_d(cs, 32, &count, &more);
 	if (!p)
 		return;
 
-	spin_lock_irqsave(&icc_lock, flags);
 	icc_write_fifo(cs, p, count);
 	icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa);
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
@@ -187,16 +159,13 @@
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
-	spin_unlock_irqrestore(&icc_lock, flags);
 }
 
 void
 icc_interrupt(struct IsdnCardState *cs, u8 val)
 {
 	u8 exval, v1;
-	struct sk_buff *skb;
 	unsigned int count;
-	unsigned long flags;
 
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "ICC interrupt %x", val);
@@ -218,25 +187,14 @@
 #endif
 			}
 			icc_write_reg(cs, ICC_CMDR, 0x80);
+			cs->rcvidx = 0;
 		} else {
 			count = icc_read_reg(cs, ICC_RBCL) & 0x1f;
 			if (count == 0)
 				count = 32;
 			icc_empty_fifo(cs, count);
-			spin_lock_irqsave(&icc_lock, flags);
-			if ((count = cs->rcvidx) > 0) {
-				cs->rcvidx = 0;
-				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
-					printk(KERN_WARNING "HiSax: D receive out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), cs->rcvbuf, count);
-					skb_queue_tail(&cs->rq, skb);
-				}
-			}
-			spin_unlock_irqrestore(&icc_lock, flags);
+			recv_rme_d(cs);
 		}
-		cs->rcvidx = 0;
-		sched_d_event(cs, D_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		icc_empty_fifo(cs, 32);
@@ -485,10 +443,11 @@
 	}
 }
 
-void
+static int
 setstack_icc(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = ICC_l1hw;
+	return 0;
 }
 
 void 
@@ -534,25 +493,27 @@
 				debugl1(cs, "D-Channel Busy no skb");
 			}
 			icc_write_reg(cs, ICC_CMDR, 0x01); /* Transmitter reset */
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */
 		}
 	}
 }
 
+static struct dc_l1_ops icc_l1_ops = {
+	.fill_fifo  = icc_fill_fifo,
+	.open       = setstack_icc,
+	.close      = DC_Close_icc,
+	.bh_func    = icc_bh,
+	.dbusy_func = dbusy_timer_handler,
+};
+
 void __init
 initicc(struct IsdnCardState *cs)
 {
 	int val, eval;
 
-	INIT_WORK(&cs->work, icc_bh, cs);
-	cs->setstack_d = setstack_icc;
-	cs->DC_Send_Data = icc_fill_fifo;
-	cs->DC_Close = DC_Close_icc;
+	dc_l1_init(cs, &icc_l1_ops);
 	cs->dc.icc.mon_tx = NULL;
 	cs->dc.icc.mon_rx = NULL;
-	cs->dbusytimer.function = (void *) dbusy_timer_handler;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
 
 	val = icc_read_reg(cs, ICC_STAR);
 	debugl1(cs, "ICC STAR %x", val);
@@ -596,4 +557,12 @@
 	ph_command(cs, ICC_CMD_RES);
 	icc_write_reg(cs, ICC_MASK, 0x0);
 	ph_command(cs, ICC_CMD_DI);
+}
+
+int
+icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops)
+{
+	cs->dc_hw_ops = icc_ops;
+	ICCVersion(cs, "HiSax:");
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h
--- a/drivers/isdn/hisax/icc.h	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/icc.h	Mon Jan 13 10:18:07 2003
@@ -65,6 +65,6 @@
 #define ICC_IND_AIL    0xE
 #define ICC_IND_DC     0xF
 
-extern void ICCVersion(struct IsdnCardState *cs, char *s);
+extern int  icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops);
 extern void initicc(struct IsdnCardState *cs);
 extern void icc_interrupt(struct IsdnCardState *cs, u8 val);
diff -Nru a/drivers/isdn/hisax/ipac.c b/drivers/isdn/hisax/ipac.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/isdn/hisax/ipac.c	Mon Jan 13 10:18:07 2003
@@ -0,0 +1,105 @@
+#include "hisax.h"
+#include "isdnl1.h"
+#include "ipac.h"
+#include "hscx.h"
+#include "isac.h"
+
+static inline u8
+ipac_dc_read(struct IsdnCardState *cs, u8 addr)
+{
+	return cs->dc_hw_ops->read_reg(cs, addr);
+}
+
+static inline void
+ipac_dc_write(struct IsdnCardState *cs, u8 addr, u8 val)
+{
+	cs->dc_hw_ops->write_reg(cs, addr, val);
+}
+
+static inline u8
+ipac_bc_read(struct IsdnCardState *cs, int hscx, u8 addr)
+{
+	return cs->bc_hw_ops->read_reg(cs, hscx, addr);
+}
+
+static inline void
+ipac_bc_write(struct IsdnCardState *cs, int hscx, u8 addr, u8 val)
+{
+	cs->bc_hw_ops->write_reg(cs, hscx, addr, val);
+}
+
+static inline u8
+ipac_read(struct IsdnCardState *cs, u8 offset)
+{
+	return ipac_dc_read(cs, offset - 0x80);
+}
+
+static inline void
+ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+{
+	ipac_dc_write(cs, offset - 0x80, value);
+}
+
+void
+ipac_init(struct IsdnCardState *cs)
+{
+	set_bit(HW_IPAC, &cs->HW_Flags);
+	inithscxisac(cs);
+}
+
+void
+ipac_irq(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u8 ista, val, icnt = 5;
+
+	spin_lock(&cs->lock);
+	ista = ipac_read(cs, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = ipac_bc_read(cs, 1, HSCX_ISTA);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe;
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = ipac_read(cs, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "IRQ LOOP\n");
+
+	ipac_write(cs, IPAC_MASK, 0xFF);
+	ipac_write(cs, IPAC_MASK, 0xC0);
+	spin_unlock(&cs->lock);
+}
+
+int
+ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops,
+	   struct bc_hw_ops *ipac_bc_ops)
+{
+	u8 val;
+
+	cs->dc_hw_ops = ipac_dc_ops;
+	cs->bc_hw_ops = ipac_bc_ops;
+	val = ipac_read(cs, IPAC_ID);
+	printk(KERN_INFO "HiSax: IPAC version %#x\n", val);
+}
diff -Nru a/drivers/isdn/hisax/ipac.h b/drivers/isdn/hisax/ipac.h
--- a/drivers/isdn/hisax/ipac.h	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/ipac.h	Mon Jan 13 10:18:07 2003
@@ -27,3 +27,76 @@
 #define IPAC_PCFG	0xCA
 #define IPAC_SCFG	0xCB
 #define IPAC_TIMR2	0xCC
+
+void ipac_init(struct IsdnCardState *cs);
+void ipac_irq(int intno, void *dev_id, struct pt_regs *regs);
+int  ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops,
+		struct bc_hw_ops *ipac_bc_ops);
+
+/* Macro to build the needed D- and B-Channel access routines given
+ * access functions for the IPAC */
+
+#define BUILD_IPAC_OPS(ipac)                                                  \
+                                                                              \
+static u8                                                                     \
+ipac ## _dc_read(struct IsdnCardState *cs, u8 offset)                         \
+{                                                                             \
+	return ipac ## _read(cs, offset+0x80);                                \
+}                                                                             \
+                                                                              \
+static void                                                                   \
+ipac ## _dc_write(struct IsdnCardState *cs, u8 offset, u8 value)              \
+{                                                                             \
+	ipac ## _write(cs, offset+0x80, value);                               \
+}                                                                             \
+                                                                              \
+static void                                                                   \
+ipac ## _dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size)          \
+{                                                                             \
+	ipac ## _readfifo(cs, 0x80, data, size);                              \
+}                                                                             \
+                                                                              \
+static void                                                                   \
+ipac ## _dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size)         \
+{                                                                             \
+	ipac ## _writefifo(cs, 0x80, data, size);                             \
+}                                                                             \
+                                                                              \
+static struct dc_hw_ops ipac ## _dc_ops = {                                   \
+	.read_reg   = ipac ## _dc_read,                                       \
+	.write_reg  = ipac ## _dc_write,                                      \
+	.read_fifo  = ipac ## _dc_read_fifo,                                  \
+	.write_fifo = ipac ## _dc_write_fifo,                                 \
+};                                                                            \
+                                                                              \
+static u8                                                                     \
+ipac ## _bc_read(struct IsdnCardState *cs, int hscx, u8 offset)               \
+{                                                                             \
+	return ipac ## _read(cs, offset + (hscx ? 0x40 : 0));                 \
+}                                                                             \
+                                                                              \
+static void                                                                   \
+ipac ## _bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)    \
+{                                                                             \
+	ipac ## _write(cs, offset + (hscx ? 0x40 : 0), value);                \
+}                                                                             \
+                                                                              \
+static void                                                                   \
+ipac ## _bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) \
+{                                                                             \
+	ipac ## _readfifo(cs, hscx ? 0x40 : 0, data, size);                   \
+}                                                                             \
+                                                                              \
+static void                                                                   \
+ipac ## _bc_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)\
+{                                                                             \
+	ipac ## _writefifo(cs, hscx ? 0x40 : 0, data, size);                  \
+}                                                                             \
+                                                                              \
+static struct bc_hw_ops ipac ## _bc_ops = {                                   \
+	.read_reg   = ipac ## _bc_read,                                       \
+	.write_reg  = ipac ## _bc_write,                                      \
+	.read_fifo  = ipac ## _bc_read_fifo,                                  \
+	.write_fifo = ipac ## _bc_write_fifo,                                 \
+}
+
diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
--- a/drivers/isdn/hisax/ipacx.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/ipacx.c	Mon Jan 13 10:18:06 2003
@@ -41,10 +41,8 @@
 static void dch_empty_fifo(struct IsdnCardState *cs, int count);
 static void dch_fill_fifo(struct IsdnCardState *cs);
 static inline void dch_int(struct IsdnCardState *cs);
-static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
-static void __devinit dch_init(struct IsdnCardState *cs);
 static void bch_l2l1(struct PStack *st, int pr, void *arg);
-static void bch_empty_fifo(struct BCState *bcs, int count);
+static void ipacx_bc_empty_fifo(struct BCState *bcs, int count);
 static void bch_int(struct IsdnCardState *cs, u8 hscx);
 static void bch_mode(struct BCState *bcs, int mode, int bc);
 static void bch_close_state(struct BCState *bcs);
@@ -57,18 +55,16 @@
 ipacx_bc_read_reg(struct BCState *bcs, u8 addr)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
 
-	return cs->bc_hw_ops->read_reg(cs, hscx, addr);
+	return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr);
 }
 
 static inline void
 ipacx_bc_write_reg(struct BCState *bcs, u8 addr, u8 val)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
 
-	cs->bc_hw_ops->write_reg(cs, hscx, addr, val);
+	cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val);
 }
 
 static inline u8
@@ -305,33 +301,8 @@
 static void 
 dch_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	u8 *ptr;
-
-	if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
-		debugl1(cs, "dch_empty_fifo()");
-
-  // message too large, remove
-	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
-		if (cs->debug &L1_DEB_WARN)
-			debugl1(cs, "dch_empty_fifo() incoming message too large");
-	  ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
-		cs->rcvidx = 0;
-		return;
-	}
-  
-	ptr = cs->rcvbuf + cs->rcvidx;
-	cs->rcvidx += count;
-  
-	ipacx_read_fifo(cs, ptr, count);
+	recv_empty_fifo_d(cs, count);
 	ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
-  
-	if (cs->debug &L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "dch_empty_fifo() cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
 }
 
 //----------------------------------------------------------
@@ -372,7 +343,6 @@
 static inline void 
 dch_int(struct IsdnCardState *cs)
 {
-	struct sk_buff *skb;
 	u8 istad, rstad;
 	int count;
 
@@ -383,32 +353,25 @@
 		if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
 			if (!(rstad &0x80))
 				if (cs->debug &L1_DEB_WARN) 
-          debugl1(cs, "dch_int(): invalid frame");
+					debugl1(cs, "dch_int(): invalid frame");
 			if ((rstad &0x40))
 				if (cs->debug &L1_DEB_WARN) 
-          debugl1(cs, "dch_int(): RDO");
+					debugl1(cs, "dch_int(): RDO");
 			if (!(rstad &0x20))
 				if (cs->debug &L1_DEB_WARN) 
-          debugl1(cs, "dch_int(): CRC error");
-	    ipacx_write_reg(cs, IPACX_CMDRD, 0x80);  // RMC
+					debugl1(cs, "dch_int(): CRC error");
+			ipacx_write_reg(cs, IPACX_CMDRD, 0x80);  // RMC
+			cs->rcvidx = 0;
 		} else {  // received frame ok
 			count = ipacx_read_reg(cs, IPACX_RBCLD);
-      if (count) count--; // RSTAB is last byte
+			// FIXME this looks flaky
+			if (count) count--; // RSTAB is last byte
 			count &= D_FIFO_SIZE-1;
-			if (count == 0) count = D_FIFO_SIZE;
+			if (count == 0)
+				count = D_FIFO_SIZE;
 			dch_empty_fifo(cs, count);
-			if ((count = cs->rcvidx) > 0) {
-	      cs->rcvidx = 0;
-				if (!(skb = dev_alloc_skb(count)))
-					printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), cs->rcvbuf, count);
-					skb_queue_tail(&cs->rq, skb);
-				}
-			}
-    }
-	  cs->rcvidx = 0;
-		sched_d_event(cs, D_RCVBUFREADY);
+			recv_rme_d(cs);
+		}
 	}
 
 	if (istad &0x40) {  // RPF
@@ -431,12 +394,20 @@
 
 //----------------------------------------------------------
 //----------------------------------------------------------
-static void __devinit
+static int
 dch_setstack(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = dch_l2l1;
+	return 0;
 }
 
+static struct dc_l1_ops ipacx_dc_l1_ops = {
+	.fill_fifo  = dch_fill_fifo,
+	.open       = dch_setstack,
+	.bh_func    = dch_bh,
+	.dbusy_func = dbusy_timer_handler,
+};
+
 //----------------------------------------------------------
 //----------------------------------------------------------
 static void __devinit
@@ -444,17 +415,12 @@
 {
 	printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n");
 
-	INIT_WORK(&cs->work, dch_bh, cs);
-	cs->setstack_d      = dch_setstack;
-	cs->DC_Send_Data = dch_fill_fifo;
-	cs->dbusytimer.function = (void *) dbusy_timer_handler;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
+	dc_l1_init(cs, &ipacx_dc_l1_ops);
 
-  ipacx_write_reg(cs, IPACX_TR_CONF0, 0x00);  // clear LDD
-  ipacx_write_reg(cs, IPACX_TR_CONF2, 0x00);  // enable transmitter
-  ipacx_write_reg(cs, IPACX_MODED,    0xC9);  // transparent mode 0, RAC, stop/go
-  ipacx_write_reg(cs, IPACX_MON_CR,   0x00);  // disable monitor channel
+	ipacx_write_reg(cs, IPACX_TR_CONF0, 0x00);  // clear LDD
+	ipacx_write_reg(cs, IPACX_TR_CONF2, 0x00);  // enable transmitter
+	ipacx_write_reg(cs, IPACX_MODED,    0xC9);  // transparent mode 0, RAC, stop/go
+	ipacx_write_reg(cs, IPACX_MON_CR,   0x00);  // disable monitor channel
 }
 
 
@@ -501,49 +467,17 @@
 // Read B channel fifo to receive buffer
 //----------------------------------------------------------
 static void
-bch_empty_fifo(struct BCState *bcs, int count)
+ipacx_bc_empty_fifo(struct BCState *bcs, int count)
 {
-	u8 *ptr, hscx;
-	struct IsdnCardState *cs;
-	int cnt;
-
-	cs = bcs->cs;
-  hscx = bcs->hw.hscx.hscx;
-	if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
-		debugl1(cs, "bch_empty_fifo()");
-
-  // message too large, remove
-	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
-		if (cs->debug &L1_DEB_WARN)
-			debugl1(cs, "bch_empty_fifo() incoming packet too large");
-	  ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80);  // RMC
-		bcs->hw.hscx.rcvidx = 0;
-		return;
-	}
-  
-  // Read data uninterruptible
-	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
-	cnt = count;
-	while (cnt--) *ptr++ = ipacx_bc_read_reg(bcs, IPACX_RFIFOB); 
+	recv_empty_fifo_b(bcs, count);
 	ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80);  // RMC
-  
-	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
-	bcs->hw.hscx.rcvidx += count;
-  
-	if (cs->debug &L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
 }
 
 //----------------------------------------------------------
 // Fill buffer to transmit FIFO
 //----------------------------------------------------------
-void
-ipacx_fill_fifo(struct BCState *bcs)
+static void
+ipacx_bc_fill_fifo(struct BCState *bcs)
 {
 	int more, count;
 	unsigned char *p;
@@ -573,7 +507,6 @@
 {
 	u8 istab;
 	struct BCState *bcs;
-	struct sk_buff *skb;
 	int count;
 	u8 rstab;
 
@@ -586,48 +519,28 @@
 		if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
 			if (!(rstab &0x80))
 				if (cs->debug &L1_DEB_WARN) 
-          debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
+					debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
 			if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL))
 				if (cs->debug &L1_DEB_WARN) 
-          debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
+					debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
 			if (!(rstab &0x20))
 				if (cs->debug &L1_DEB_WARN) 
-          debugl1(cs, "bch_int() B-%d: CRC error", hscx);
-	    ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80);  // RMC
-		} 
-    else {  // received frame ok
+					debugl1(cs, "bch_int() B-%d: CRC error", hscx);
+			ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80);  // RMC
+			bcs->rcvidx = 0;
+		}  else {  // received frame ok
 			count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1);
-			if (count == 0) count = B_FIFO_SIZE;
-			bch_empty_fifo(bcs, count);
-			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
-				if (cs->debug &L1_DEB_HSCX_FIFO)
-					debugl1(cs, "bch_int Frame %d", count);
-				if (!(skb = dev_alloc_skb(count)))
-					printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
-					skb_queue_tail(&bcs->rqueue, skb);
-				}
-			}
+			if (count == 0)
+				count = B_FIFO_SIZE;
+
+			ipacx_bc_empty_fifo(bcs, count);
+			recv_rme_b(bcs);
 		}
-		bcs->hw.hscx.rcvidx = 0;
-		sched_b_event(bcs, B_RCVBUFREADY);
 	}
   
 	if (istab &0x40) {	// RPF
-		bch_empty_fifo(bcs, B_FIFO_SIZE);
-
-		if (bcs->mode == L1_MODE_TRANS) { // queue every chunk
-			// receive transparent audio data
-			if (!(skb = dev_alloc_skb(B_FIFO_SIZE)))
-				printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n");
-			else {
-				memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE);
-				skb_queue_tail(&bcs->rqueue, skb);
-			}
-			bcs->hw.hscx.rcvidx = 0;
-			sched_b_event(bcs, B_RCVBUFREADY);
-		}
+		ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE);
+		recv_rpf_b(bcs);
 	}
   
 	if (istab &0x20) {	// RFO
@@ -651,7 +564,7 @@
 bch_mode(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int hscx = bcs->hw.hscx.hscx;
+	int hscx = bcs->unit;
 
         bc = bc ? 1 : 0;  // in case bc is greater than 1
 	if (cs->debug & L1_DEB_HSCX)
@@ -699,23 +612,7 @@
 bch_close_state(struct BCState *bcs)
 {
 	bch_mode(bcs, 0, bcs->channel);
-	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (bcs->hw.hscx.rcvbuf) {
-			kfree(bcs->hw.hscx.rcvbuf);
-			bcs->hw.hscx.rcvbuf = NULL;
-		}
-		if (bcs->blog) {
-			kfree(bcs->blog);
-			bcs->blog = NULL;
-		}
-		skb_queue_purge(&bcs->rqueue);
-		skb_queue_purge(&bcs->squeue);
-		if (bcs->tx_skb) {
-			dev_kfree_skb_any(bcs->tx_skb);
-			bcs->tx_skb = NULL;
-			clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		}
-	}
+	bc_close(bcs);
 }
 
 //----------------------------------------------------------
@@ -723,30 +620,7 @@
 static int
 bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-				"HiSax open_bchstate(): No memory for hscx.rcvbuf\n");
-			clear_bit(BC_FLG_INIT, &bcs->Flag);
-			return (1);
-		}
-		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-				"HiSax open_bchstate: No memory for bcs->blog\n");
-			clear_bit(BC_FLG_INIT, &bcs->Flag);
-			kfree(bcs->hw.hscx.rcvbuf);
-			bcs->hw.hscx.rcvbuf = NULL;
-			return (2);
-		}
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	bcs->tx_skb = NULL;
-	clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	bcs->event = 0;
-	bcs->hw.hscx.rcvidx = 0;
-	bcs->tx_cnt = 0;
-	return (0);
+	return bc_open(bcs);
 }
 
 //----------------------------------------------------------
@@ -769,9 +643,7 @@
 static void __devinit
 bch_init(struct IsdnCardState *cs, int hscx)
 {
-	cs->bcs[hscx].BC_SetStack   = bch_setstack;
-	cs->bcs[hscx].BC_Close      = bch_close_state;
-	cs->bcs[hscx].hw.hscx.hscx  = hscx;
+	cs->bcs[hscx].unit          = hscx;
 	cs->bcs[hscx].cs            = cs;
 	bch_mode(cs->bcs + hscx, 0, hscx);
 }
@@ -821,7 +693,9 @@
 }
 
 static struct bc_l1_ops ipacx_bc_l1_ops = {
-	.fill_fifo = ipacx_fill_fifo,
+	.fill_fifo = ipacx_bc_fill_fifo,
+	.open      = bch_setstack,
+	.close     = bch_close_state,
 };
 
 //----------------------------------------------------------
@@ -852,5 +726,15 @@
 	}
 }
 
-//----------------- end of file -----------------------
+int
+ipacx_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipacx_dc_ops,
+	    struct bc_hw_ops *ipacx_bc_ops)
+{
+	u8 val;
+
+	cs->dc_hw_ops = ipacx_dc_ops;
+	cs->bc_hw_ops = ipacx_bc_ops;
+	val = ipacx_read_reg(cs, IPACX_ID) & 0x3f;
+	printk(KERN_INFO "HiSax: IPACX Design Id: %#x\n", val);
+}
 
diff -Nru a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h
--- a/drivers/isdn/hisax/ipacx.h	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/ipacx.h	Mon Jan 13 10:18:05 2003
@@ -157,6 +157,8 @@
 
 extern void init_ipacx(struct IsdnCardState *cs, int part);
 extern void interrupt_ipacx(struct IsdnCardState *cs);
-extern void ipacx_fill_fifo(struct BCState *bcs);
+extern int  ipacx_setup(struct IsdnCardState *cs,
+			struct dc_hw_ops *ipacx_dc_ops,
+			struct bc_hw_ops *ipacx_bc_ops);
 
 #endif
diff -Nru a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
--- a/drivers/isdn/hisax/isac.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/isac.c	Mon Jan 13 10:18:05 2003
@@ -40,18 +40,12 @@
 }
 
 static inline void
-isac_read_fifo(struct IsdnCardState *cs, u8 *p, int len)
-{
-	return cs->dc_hw_ops->read_fifo(cs, p, len);
-}
-
-static inline void
 isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len)
 {
 	return cs->dc_hw_ops->write_fifo(cs, p, len);
 }
 
-void
+static void
 ISACVersion(struct IsdnCardState *cs, char *s)
 {
 	int val;
@@ -140,30 +134,8 @@
 void
 isac_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	u8 *ptr;
-
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, "isac_empty_fifo");
-
-	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "isac_empty_fifo overrun %d",
-				cs->rcvidx + count);
-		isac_write(cs, ISAC_CMDR, 0x80);
-		cs->rcvidx = 0;
-		return;
-	}
-	ptr = cs->rcvbuf + cs->rcvidx;
-	cs->rcvidx += count;
-	isac_read_fifo(cs, ptr, count);
+	recv_empty_fifo_d(cs, count);
 	isac_write(cs, ISAC_CMDR, 0x80);
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "isac_empty_fifo cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
 }
 
 static void
@@ -191,7 +163,6 @@
 isac_interrupt(struct IsdnCardState *cs, u8 val)
 {
 	u8 exval, v1;
-	struct sk_buff *skb;
 	unsigned int count;
 
 	if (cs->debug & L1_DEB_ISAC)
@@ -214,20 +185,13 @@
 #endif
 			}
 			isac_write(cs, ISAC_CMDR, 0x80);
+			cs->rcvidx = 0;
 		} else {
 			count = isac_read(cs, ISAC_RBCL) & 0x1f;
 			if (count == 0)
 				count = 32;
 			isac_empty_fifo(cs, count);
-			if ((count = cs->rcvidx) > 0) {
-				cs->rcvidx = 0;
-				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
-					printk(KERN_WARNING "HiSax: D receive out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), cs->rcvbuf, count);
-					skb_queue_tail(&cs->rq, skb);
-				}
-			}
+ 			recv_rme_d(cs);
 		}
 		cs->rcvidx = 0;
 		sched_d_event(cs, D_RCVBUFREADY);
@@ -477,13 +441,14 @@
 	}
 }
 
-void
+static int
 setstack_isac(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = ISAC_l1hw;
+	return 0;
 }
 
-void 
+static void 
 DC_Close_isac(struct IsdnCardState *cs) {
 	if (cs->dc.isac.mon_rx) {
 		kfree(cs->dc.isac.mon_rx);
@@ -526,16 +491,26 @@
 				debugl1(cs, "D-Channel Busy no skb");
 			}
 			isac_write(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->card_ops->irq_func(cs->irq, cs, NULL);
 		}
 	}
 }
 
+static struct dc_l1_ops isac_l1_ops = {
+	.fill_fifo  = isac_fill_fifo,
+	.open       = setstack_isac,
+	.close      = DC_Close_isac,
+	.bh_func    = isac_bh,
+	.dbusy_func = dbusy_timer_handler,
+};
+
 void __devinit
 initisac(struct IsdnCardState *cs)
 {
 	int val, eval;
 
+	dc_l1_init(cs, &isac_l1_ops);
+
 	val = isac_read(cs, ISAC_STAR);
 	debugl1(cs, "ISAC STAR %x", val);
 	val = isac_read(cs, ISAC_MODE);
@@ -551,16 +526,8 @@
 	/* Disable all IRQ */
 	isac_write(cs, ISAC_MASK, 0xFF);
 
-	INIT_WORK(&cs->work, isac_bh, cs);
-	cs->setstack_d = setstack_isac;
-	cs->DC_Send_Data = isac_fill_fifo;
-	cs->DC_Close = DC_Close_isac;
 	cs->dc.isac.mon_tx = NULL;
 	cs->dc.isac.mon_rx = NULL;
-	cs->dbusytimer.function = (void *) dbusy_timer_handler;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
-  	isac_write(cs, ISAC_MASK, 0xff);
   	cs->dc.isac.mocr = 0xaa;
 	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 		/* IOM 1 Mode */
@@ -591,4 +558,12 @@
 
 	/* RESET Receiver and Transmitter */
 	isac_write(cs, ISAC_CMDR, 0x41);
+}
+
+int
+isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops)
+{
+	cs->dc_hw_ops = isac_ops;
+	ISACVersion(cs, "HiSax:");
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h
--- a/drivers/isdn/hisax/isac.h	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/isac.h	Mon Jan 13 10:18:07 2003
@@ -63,6 +63,6 @@
 #define ISAC_IND_AI10	0xD
 #define ISAC_IND_DID	0xF
 
-extern void ISACVersion(struct IsdnCardState *cs, char *s);
 extern void initisac(struct IsdnCardState *cs);
 extern void isac_interrupt(struct IsdnCardState *cs, u8 val);
+extern int  isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops);
diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
--- a/drivers/isdn/hisax/isar.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/isar.c	Mon Jan 13 10:18:06 2003
@@ -25,7 +25,7 @@
 const u8 faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; 
 #define FAXMODCNT 13
 
-void isar_setup(struct IsdnCardState *cs);
+static void __isar_setup(struct IsdnCardState *cs);
 static void isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para);
 static inline void ll_deliver_faxstat(struct BCState *bcs, u8 status);
 static spinlock_t isar_lock = SPIN_LOCK_UNLOCKED;
@@ -165,7 +165,7 @@
 	return(1);
 }
 
-int
+static int
 ISARVersion(struct IsdnCardState *cs, char *s)
 {
 	int ver;
@@ -174,7 +174,7 @@
 	u8 len;
 	int debug;
 
-	cs->cardmsg(cs, CARD_RESET,  NULL);
+	cs->card_ops->reset(cs);
 	/* disable ISAR IRQ */
 	isar_write_reg(cs, 0, ISAR_IRQBIT, 0);
 	debug = cs->debug;
@@ -420,7 +420,7 @@
 		}
 	}
 	cs->debug = debug;
-	isar_setup(cs);
+	__isar_setup(cs);
 	ret = 0;
 reterror:
 	cs->debug = debug;
@@ -1531,7 +1531,7 @@
 }
 
 void
-isar_setup(struct IsdnCardState *cs)
+__isar_setup(struct IsdnCardState *cs)
 {
 	u8 msg;
 	int i;
@@ -1745,14 +1745,19 @@
 
 static struct bc_l1_ops isar_l1_ops = {
 	.fill_fifo = isar_fill_fifo,
+	.open      = setstack_isar,
+	.close     = close_isarstate,
 };
 
 void __devinit
 initisar(struct IsdnCardState *cs)
 {
 	cs->bc_l1_ops = &isar_l1_ops;
-	cs->bcs[0].BC_SetStack = setstack_isar;
-	cs->bcs[1].BC_SetStack = setstack_isar;
-	cs->bcs[0].BC_Close = close_isarstate;
-	cs->bcs[1].BC_Close = close_isarstate;
+}
+
+int
+isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops)
+{
+	cs->bc_hw_ops = isar_ops;
+	return ISARVersion(cs, "HiSax:");
 }
diff -Nru a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h
--- a/drivers/isdn/hisax/isar.h	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/isar.h	Mon Jan 13 10:18:05 2003
@@ -207,8 +207,8 @@
 #define STFAX_ESCAPE	5
 #define STFAX_SILDET	6
 
-extern int ISARVersion(struct IsdnCardState *cs, char *s);
 extern void isar_int_main(struct IsdnCardState *cs);
 extern void initisar(struct IsdnCardState *cs);
 extern void isar_fill_fifo(struct BCState *bcs);
 extern int isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic);
+extern int isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops);
diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
--- a/drivers/isdn/hisax/isdnl1.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/isdnl1.c	Mon Jan 13 10:18:05 2003
@@ -358,8 +358,6 @@
 	bcs->cs = cs;
 	bcs->channel = bc;
 	INIT_WORK(&bcs->work, BChannel_bh, bcs);
-	bcs->BC_SetStack = NULL;
-	bcs->BC_Close = NULL;
 	bcs->Flag = 0;
 }
 
@@ -907,8 +905,18 @@
 	setstack_manager(st);
 	st->l1.stlistp = &(cs->stlist);
 	st->l1.l2l1  = dch_l2l1;
-	if (cs->setstack_d)
-		cs->setstack_d(st, cs);
+	if (cs->dc_l1_ops->open)
+		cs->dc_l1_ops->open(st, cs);
+}
+
+void
+dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops)
+{
+	cs->dc_l1_ops = ops;
+	INIT_WORK(&cs->work, ops->bh_func, cs);
+	init_timer(&cs->dbusytimer);
+	cs->dbusytimer.function = (void *)(unsigned long) ops->dbusy_func;
+	cs->dbusytimer.data = (unsigned long) cs;
 }
 
 void
diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
--- a/drivers/isdn/hisax/isdnl1.h	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/isdnl1.h	Mon Jan 13 10:18:07 2003
@@ -7,6 +7,9 @@
  *
  */
 
+#ifndef __ISDNL1_H__
+#define __ISDNL1_H__
+
 #define D_RCVBUFREADY	0
 #define D_XMTBUFREADY	1
 #define D_L1STATECHANGE	2
@@ -31,12 +34,20 @@
 extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
 extern void l1_msg_b(struct PStack *st, int pr, void *arg);
 
+void dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops);
+
 static inline void
 fill_fifo_b(struct BCState *bcs)
 {
 	bcs->cs->bc_l1_ops->fill_fifo(bcs);
 }
 
+static inline void
+fill_fifo_d(struct IsdnCardState *cs)
+{
+	cs->dc_l1_ops->fill_fifo(cs);
+}
+
 #ifdef L2FRAME_DEBUG
 extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
 #endif
@@ -94,7 +105,7 @@
 	cs->tx_skb = skb_dequeue(&cs->sq);
 	if (cs->tx_skb) {
 		cs->tx_cnt = 0;
-		cs->DC_Send_Data(cs);
+		fill_fifo_d(cs);
 	} else {
 		sched_d_event(cs, D_XMTBUFREADY);
 	}
@@ -141,7 +152,7 @@
 		if (cs->debug & L1_DEB_LAPD)
 			Logl2Frame(cs, skb, "PH_DATA", 0);
 #endif
-		cs->DC_Send_Data(cs);
+		fill_fifo_d(cs);
 	}
 	spin_unlock_irqrestore(&cs->lock, flags);
 }
@@ -183,7 +194,7 @@
 #endif
 		cs->tx_skb = skb;
 		cs->tx_cnt = 0;
-		cs->DC_Send_Data(cs);
+		fill_fifo_d(cs);
 	}
 	spin_unlock_irqrestore(&cs->lock, flags);
 }
@@ -296,7 +307,7 @@
 	if (cs->tx_skb) {
 		/* last frame not done yet? */
 		if (cs->tx_skb->len) {
-			cs->DC_Send_Data(cs);
+			fill_fifo_d(cs);
 			return;
 		}
 		xmit_complete_d(cs);
@@ -372,7 +383,7 @@
 		char *t = bcs->blog;
 
 		t += sprintf(t, "%s %c cnt %d", __FUNCTION__,
-			     bcs->hw.hscx.hscx ? 'B' : 'A', *count);
+			     bcs->unit ? 'B' : 'A', *count);
 		QuickHex(t, p, *count);
 		debugl1(cs, bcs->blog);
 	}
@@ -413,3 +424,174 @@
 	}
 	return p;
 }
+
+static inline void
+recv_empty_fifo_d(struct IsdnCardState *cs, int count)
+{
+	u8 *p;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, __FUNCTION__);
+
+	if (cs->rcvidx + count > MAX_DFRAME_LEN_L1) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "%s: incoming packet too large", __FUNCTION__);
+		cs->rcvidx = 0;
+		return;
+	}
+	p = cs->rcvbuf + cs->rcvidx;
+	cs->rcvidx += count;
+	cs->dc_hw_ops->read_fifo(cs, p, count);
+
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "%s cnt %d", __FUNCTION__, count);
+		QuickHex(t, p, count);
+		debugl1(cs, cs->dlog);
+	}
+}
+
+static inline void
+recv_empty_fifo_b(struct BCState *bcs, int count)
+{
+	u8 *p;
+	struct IsdnCardState *cs = bcs->cs;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, __FUNCTION__);
+
+	if (bcs->rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "%s: incoming packet too large", __FUNCTION__);
+		bcs->rcvidx = 0;
+		return;
+	}
+	p = bcs->rcvbuf + bcs->rcvidx;
+	bcs->rcvidx += count;
+	cs->bc_hw_ops->read_fifo(cs, bcs->unit, p, count);
+
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "%s %c cnt %d", __FUNCTION__,
+			     bcs->unit ? 'B' : 'A', count);
+		QuickHex(t, p, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+/* RME - receive message end */
+static inline void
+recv_rme_d(struct IsdnCardState *cs)
+{
+	struct sk_buff *skb;
+	int count;
+
+	count = cs->rcvidx - 1;
+	cs->rcvidx = 0;
+	if (count == 0)
+		return;
+
+	skb = dev_alloc_skb(count);
+	if (!skb) {
+		printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
+		return;
+	}
+	memcpy(skb_put(skb, count), cs->rcvbuf, count);
+	skb_queue_tail(&cs->rq, skb);
+	sched_d_event(cs, D_RCVBUFREADY);
+}
+
+static inline void
+recv_rme_b(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	struct sk_buff *skb;
+	int count;
+
+	count = bcs->rcvidx - 1;
+	bcs->rcvidx = 0;
+	if (count == 0)
+		return;
+
+	if (cs->debug & L1_DEB_HSCX_FIFO)
+		debugl1(cs, "HX Frame %d", count);
+
+	skb = dev_alloc_skb(count);
+	if (!skb) {
+		printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
+		return;
+	}
+	memcpy(skb_put(skb, count), bcs->rcvbuf, count);
+	skb_queue_tail(&bcs->rqueue, skb);
+	sched_b_event(bcs, B_RCVBUFREADY);
+}
+
+/* RPF - receive pull full */
+static inline void
+recv_rpf_b(struct BCState *bcs)
+{
+	if (bcs->mode != L1_MODE_TRANS)
+		return;
+
+	recv_rme_b(bcs);
+}
+	
+static inline int
+bc_open(struct BCState *bcs)
+{
+	if (test_and_set_bit(BC_FLG_INIT, &bcs->Flag))
+		return 0;
+
+	bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC);
+	if (!bcs->rcvbuf)
+		goto err;
+
+	bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC);
+	if (!bcs->blog)
+		goto err_rcvbuf;
+	
+	skb_queue_head_init(&bcs->rqueue);
+	skb_queue_head_init(&bcs->squeue);
+	skb_queue_head_init(&bcs->cmpl_queue);
+
+	clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->tx_skb = NULL;
+	bcs->rcvidx = 0;
+	bcs->tx_cnt = 0;
+	bcs->event = 0;
+
+	return 0;
+
+ err_rcvbuf:
+	kfree(bcs->rcvbuf);
+ err:
+	clear_bit(BC_FLG_INIT, &bcs->Flag);
+	printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
+	return -ENOMEM;;
+}
+
+static inline void
+bc_close(struct BCState *bcs)
+{
+	if (!test_and_clear_bit(BC_FLG_INIT, &bcs->Flag))
+		return;
+
+	kfree(bcs->rcvbuf);
+	bcs->rcvbuf = NULL;
+
+	kfree(bcs->blog);
+	bcs->blog = NULL;
+
+	skb_queue_purge(&bcs->rqueue);
+	skb_queue_purge(&bcs->squeue);
+	skb_queue_purge(&bcs->cmpl_queue);
+	if (bcs->tx_skb) {
+		dev_kfree_skb_any(bcs->tx_skb);
+		bcs->tx_skb = NULL;
+		clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	}
+}
+
+#endif
diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
--- a/drivers/isdn/hisax/isurf.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/isurf.c	Mon Jan 13 10:18:06 2003
@@ -132,14 +132,6 @@
 	spin_unlock(&cs->lock);
 }
 
-void
-release_io_isurf(struct IsdnCardState *cs)
-{
-	release_region(cs->hw.isurf.reset, 1);
-	iounmap((unsigned char *)cs->hw.isurf.isar);
-	release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
-}
-
 static void
 reset_isurf(struct IsdnCardState *cs, u8 chips)
 {
@@ -154,27 +146,6 @@
 }
 
 static int
-ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			reset_isurf(cs, ISURF_RESET);
-			return(0);
-		case CARD_RELEASE:
-			release_io_isurf(cs);
-			return(0);
-		case CARD_INIT:
-			writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
-			initisac(cs);
-			initisar(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
-
-static int
 isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
 	int ret;
 
@@ -190,56 +161,82 @@
 	return(isar_auxcmd(cs, ic));
 }
 
+static void
+isurf_init(struct IsdnCardState *cs)
+{
+	writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT);
+	initisac(cs);
+	initisar(cs);
+}
+
+static int
+isurf_reset(struct IsdnCardState *cs)
+{
+	reset_isurf(cs, ISURF_RESET);
+	return 0;
+}
+
+static struct card_ops isurf_ops = {
+	.init     = isurf_init,
+	.reset    = isurf_reset,
+	.release  = hisax_release_resources,
+	.irq_func = isurf_interrupt,
+};
+
 #ifdef __ISAPNP__
-static struct pci_bus *pnp_surf __devinitdata = NULL;
+static struct pnp_card *pnp_surf __devinitdata = NULL;
 #endif
 
 int __init
 setup_isurf(struct IsdnCard *card)
 {
-	int ver;
 	struct IsdnCardState *cs = card->cs;
+	unsigned long phymem;
 	char tmp[64];
 
 	strcpy(tmp, ISurf_revision);
 	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
 	
- 	if (cs->typ != ISDN_CTYPE_ISURF)
- 		return(0);
 	if (card->para[1] && card->para[2]) {
 		cs->hw.isurf.reset = card->para[1];
-		cs->hw.isurf.phymem = card->para[2];
+		phymem = card->para[2];
 		cs->irq = card->para[0];
 	} else {
 #ifdef __ISAPNP__
-		struct pci_bus *pb;
-		struct pci_dev *pd;
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
 
 		if (isapnp_present()) {
 			cs->subtyp = 0;
-			if ((pb = isapnp_find_card(
+			if ((pb = pnp_find_card(
 				ISAPNP_VENDOR('S', 'I', 'E'),
 				ISAPNP_FUNCTION(0x0010), pnp_surf))) {
 				pnp_surf = pb;
 				pd = NULL;
-				if (!(pd = isapnp_find_dev(pnp_surf,
+				if (!(pd = pnp_find_dev(pnp_surf,
 					ISAPNP_VENDOR('S', 'I', 'E'),
 					ISAPNP_FUNCTION(0x0010), pd))) {
 					printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
 					return (0);
 				}
-				pd->prepare(pd);
-				pd->deactivate(pd);
-				pd->activate(pd);
-				cs->hw.isurf.reset = pd->resource[0].start;
-				cs->hw.isurf.phymem = pd->resource[1].start;
-				cs->irq = pd->irq_resource[0].start;
-				if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
-					printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
-						cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
-					pd->deactivate(pd);
+				if (pnp_device_attach(pd) < 0) {
+					printk(KERN_ERR "ISurfPnP: attach failed\n");
+					return 0;
+				}
+				if (pnp_activate_dev(pd, NULL) < 0) {
+					printk(KERN_ERR "ISurfPnP: activate failed\n");
+					pnp_device_detach(pd);
+					return 0;
+				}
+				if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
+					printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
+						pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
+					pnp_device_detach(pd);
 					return(0);
 				}
+				cs->hw.isurf.reset = pnp_port_start(pd, 0);
+				phymem = pnp_port_start(pd, 1);
+				cs->irq = pnp_irq(pd, 0);
 			} else {
 				printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
 				return(0);
@@ -254,50 +251,31 @@
 		return (0);
 #endif
 	}
-	if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) {
-		printk(KERN_WARNING
-			"HiSax: %s config port %x already in use\n",
-			CardType[card->typ],
-			cs->hw.isurf.reset);
-			return (0);
-	}
-	if (check_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE)) {
-		printk(KERN_WARNING
-			"HiSax: %s memory region %lx-%lx already in use\n",
-			CardType[card->typ],
-			cs->hw.isurf.phymem,
-			cs->hw.isurf.phymem + ISURF_IOMEM_SIZE);
-		release_region(cs->hw.isurf.reset, 1);
-		return (0);
-	} else {
-		request_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE,
-			"isurf iomem");
-	}
-	cs->hw.isurf.isar =
-		(unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
+	if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn"))
+		goto err;
+	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem");
+	if (!cs->hw.isurf.isar)
+		goto err;
+
 	cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
 	printk(KERN_INFO
 	       "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
 	       cs->hw.isurf.reset,
-	       cs->hw.isurf.phymem,
+	       card->para[2],
 	       cs->irq);
 
-	cs->cardmsg = &ISurf_card_msg;
-	cs->irq_func = &isurf_interrupt;
 	cs->auxcmd = &isurf_auxcmd;
-	cs->dc_hw_ops = &isac_ops;
+	cs->card_ops = &isurf_ops;
 	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
 	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
 	reset_isurf(cs, ISURF_RESET);
 	test_and_set_bit(HW_ISAR, &cs->HW_Flags);
-	ISACVersion(cs, "ISurf:");
-	cs->bc_hw_ops = &isar_ops;
-	ver = ISARVersion(cs, "ISurf:");
-	if (ver < 0) {
-		printk(KERN_WARNING
-			"ISurf: wrong ISAR version (ret = %d)\n", ver);
-		release_io_isurf(cs);
-		return (0);
-	}
-	return (1);
+	isac_setup(cs, &isac_ops);
+	if (isar_setup(cs, &isar_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
+
 }
diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
--- a/drivers/isdn/hisax/ix1_micro.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/ix1_micro.c	Mon Jan 13 10:18:07 2003
@@ -140,50 +140,7 @@
 	.write_fifo = hscx_write_fifo,
 };
 
-static void
-ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
-
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-}
-
-void
-release_io_ix1micro(struct IsdnCardState *cs)
-{
-	if (cs->hw.ix1.cfg_reg)
-		release_region(cs->hw.ix1.cfg_reg, 4);
-}
-
-static void
+static int
 ix1_reset(struct IsdnCardState *cs)
 {
 	int cnt;
@@ -195,26 +152,15 @@
 		HZDELAY(1);	/* wait >=10 ms */
 	}
 	byteout(cs->hw.ix1.cfg_reg + SPECIAL_PORT_OFFSET, 0);
+	return 0;
 }
 
-static int
-ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			ix1_reset(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_ix1micro(cs);
-			return(0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
+static struct card_ops ix1_ops = {
+	.init     = inithscxisac,
+	.reset    = ix1_reset,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
 
 #ifdef __ISAPNP__
 static struct isapnp_device_id itk_ids[] __initdata = {
@@ -228,7 +174,7 @@
 };
 
 static struct isapnp_device_id *idev = &itk_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 
@@ -240,34 +186,41 @@
 
 	strcpy(tmp, ix1_revision);
 	printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_IX1MICROR2)
-		return (0);
 
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pci_bus *pb;
-		struct pci_dev *pd;
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
 
 		while(idev->card_vendor) {
-			if ((pb = isapnp_find_card(idev->card_vendor,
-				idev->card_device, pnp_c))) {
+			if ((pb = pnp_find_card(idev->card_vendor,
+						idev->card_device,
+						pnp_c))) {
 				pnp_c = pb;
 				pd = NULL;
-				if ((pd = isapnp_find_dev(pnp_c,
-					idev->vendor, idev->function, pd))) {
+				if ((pd = pnp_find_dev(pnp_c,
+						       idev->vendor,
+						       idev->function,
+						       pd))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
 						(char *)idev->driver_data);
-					pd->prepare(pd);
-					pd->deactivate(pd);
-					pd->activate(pd);
-					card->para[1] = pd->resource[0].start;
-					card->para[0] = pd->irq_resource[0].start;
-					if (!card->para[0] || !card->para[1]) {
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "ITK PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd, NULL) < 0) {
+						printk(KERN_ERR "ITK PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_port_valid(pd, 0) || !pnp_irq_valid(pd, 0)) {
 						printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n",
-						card->para[0], card->para[1]);
-						pd->deactivate(pd);
+							pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
 						return(0);
 					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
 					break;
 				} else {
 					printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
@@ -288,32 +241,17 @@
 	cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
 	cs->hw.ix1.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
-	if (cs->hw.ix1.cfg_reg) {
-		if (check_region((cs->hw.ix1.cfg_reg), 4)) {
-			printk(KERN_WARNING
-			  "HiSax: %s config port %x-%x already in use\n",
-			       CardType[card->typ],
-			       cs->hw.ix1.cfg_reg,
-			       cs->hw.ix1.cfg_reg + 4);
-			return (0);
-		} else
-			request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg");
-	}
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.ix1.cfg_reg);
+	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
+		goto err;
+	
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
 	ix1_reset(cs);
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &ix1_card_msg;
-	cs->irq_func = &ix1micro_interrupt;
-	ISACVersion(cs, "ix1-Micro:");
-	if (HscxVersion(cs, "ix1-Micro:")) {
-		printk(KERN_WARNING
-		    "ix1-Micro: wrong HSCX versions check IO address\n");
-		release_io_ix1micro(cs);
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &ix1_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
--- a/drivers/isdn/hisax/jade.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/jade.c	Mon Jan 13 10:18:05 2003
@@ -33,24 +33,14 @@
 }
 
 static inline void
-jade_read_fifo(struct BCState *bcs, u8 *p, int len)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
-
-	cs->bc_hw_ops->read_fifo(cs, hscx, p, len);
-}
-
-static inline void
 jade_write_fifo(struct BCState *bcs, u8 *p, int len)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 hscx = bcs->hw.hscx.hscx;
 
-	cs->bc_hw_ops->write_fifo(cs, hscx, p, len);
+	cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len);
 }
 
-int __init
+static int
 JadeVersion(struct IsdnCardState *cs, char *s)
 {
     int ver,i;
@@ -112,7 +102,7 @@
 modejade(struct BCState *bcs, int mode, int bc)
 {
     struct IsdnCardState *cs = bcs->cs;
-    int jade = bcs->hw.hscx.hscx;
+    int jade = bcs->unit;
 
     if (cs->debug & L1_DEB_HSCX) {
 	char tmp[40];
@@ -199,53 +189,14 @@
 void
 close_jadestate(struct BCState *bcs)
 {
-    modejade(bcs, 0, bcs->channel);
-    if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-	if (bcs->hw.hscx.rcvbuf) {
-		kfree(bcs->hw.hscx.rcvbuf);
-		bcs->hw.hscx.rcvbuf = NULL;
-	}
-	if (bcs->blog) {
-		kfree(bcs->blog);
-		bcs->blog = NULL;
-	}
-	skb_queue_purge(&bcs->rqueue);
-	skb_queue_purge(&bcs->squeue);
-	if (bcs->tx_skb) {
-		dev_kfree_skb_any(bcs->tx_skb);
-		bcs->tx_skb = NULL;
-		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	}
-    }
+	modejade(bcs, 0, bcs->channel);
+	bc_close(bcs);
 }
 
 static int
 open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-			       "HiSax: No memory for hscx.rcvbuf\n");
-			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-			return (1);
-		}
-		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-				"HiSax: No memory for bcs->blog\n");
-			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-			kfree(bcs->hw.hscx.rcvbuf);
-			bcs->hw.hscx.rcvbuf = NULL;
-			return (2);
-		}
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	bcs->tx_skb = NULL;
-	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	bcs->event = 0;
-	bcs->hw.hscx.rcvidx = 0;
-	bcs->tx_cnt = 0;
-	return (0);
+	return bc_open(bcs);;
 }
 
 
@@ -263,8 +214,12 @@
 	return (0);
 }
 
+static void jade_fill_fifo(struct BCState *bcs);
+
 static struct bc_l1_ops jade_l1_ops = {
 	.fill_fifo = jade_fill_fifo,
+	.open      = setstack_jade,
+	.close     = close_jadestate,
 };
 
 void __init
@@ -273,12 +228,8 @@
 	int val;
 
 	cs->bc_l1_ops = &jade_l1_ops;
-	cs->bcs[0].BC_SetStack = setstack_jade;
-	cs->bcs[1].BC_SetStack = setstack_jade;
-	cs->bcs[0].BC_Close = close_jadestate;
-	cs->bcs[1].BC_Close = close_jadestate;
-	cs->bcs[0].hw.hscx.hscx = 0;
-	cs->bcs[1].hw.hscx.hscx = 1;
+	cs->bcs[0].unit = 0;
+	cs->bcs[1].unit = 1;
 
 	jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00);
 	jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00);
@@ -317,6 +268,13 @@
 	/* once again TRANSPARENT */	
 	modejade(cs->bcs, 0, 0);
 	modejade(cs->bcs + 1, 0, 0);
+}
+
+int
+jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops)
+{
+	cs->bc_hw_ops = jade_ops;
+	return JadeVersion(cs, "HiSax:");
 }
 
 #include "jade_irq.c"
diff -Nru a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h
--- a/drivers/isdn/hisax/jade.h	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/jade.h	Mon Jan 13 10:18:05 2003
@@ -127,12 +127,10 @@
 #define	jade_TXAUDIOCH1CFG				0x17
 #define	jade_TXAUDIOCH2CFG				0x1A
 
-extern int JadeVersion(struct IsdnCardState *cs, char *s);
 extern void jade_sched_event(struct BCState *bcs, int event);
 extern void modejade(struct BCState *bcs, int mode, int bc);
 extern void initjade(struct IsdnCardState *cs);
-extern void jade_int_main(struct IsdnCardState *cs, u_char val, int jade);
-extern void jade_fill_fifo(struct BCState *bcs);
-
+extern void jade_int_main(struct IsdnCardState *cs, u8 val, int jade);
+extern int  jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops);
 
 #endif	/* __JADE_H__ */
diff -Nru a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
--- a/drivers/isdn/hisax/jade_irq.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/jade_irq.c	Mon Jan 13 10:18:05 2003
@@ -9,7 +9,6 @@
  * of the GNU General Public License, incorporated herein by reference.
  *
  */
-static spinlock_t jade_irq_lock = SPIN_LOCK_UNLOCKED;
 
 static inline void
 waitforCEC(struct IsdnCardState *cs, int jade, int reg)
@@ -26,20 +25,17 @@
 
 
 static inline void
-waitforXFW(struct IsdnCardState *cs, int jade)
+waitforXFW(struct BCState *bcs)
 {
-  	/* Does not work on older jade versions, don't care */
 }
 
 static inline void
-WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u8 data)
+WriteJADECMDR(struct BCState *bcs, int reg, u8 data)
 {
-	unsigned long flags;
+	int jade = bcs->unit;
 
-	spin_lock_irqsave(&jade_irq_lock, flags);
-	waitforCEC(cs, jade, reg);
-	jade_write_reg(cs, jade, reg, data);
-	spin_unlock_irqrestore(&jade_irq_lock, flags);
+	waitforCEC(bcs->cs, jade, reg);
+	jade_write_reg(bcs->cs, jade, reg, data);
 }
 
 
@@ -47,49 +43,24 @@
 static void
 jade_empty_fifo(struct BCState *bcs, int count)
 {
-	u8 *ptr;
-	struct IsdnCardState *cs = bcs->cs;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "jade_empty_fifo");
-
-	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "jade_empty_fifo: incoming packet too large");
-		WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
-		bcs->hw.hscx.rcvidx = 0;
-		return;
-	}
-	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
-	bcs->hw.hscx.rcvidx += count;
-	jade_read_fifo(bcs, ptr, count);
-	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "jade_empty_fifo %c cnt %d",
-			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
+	recv_empty_fifo_b(bcs, count);
+	WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC);
 }
 
-void
+static void
 jade_fill_fifo(struct BCState *bcs)
 {
-	struct IsdnCardState *cs = bcs->cs;
 	int more, count;
 	int fifo_size = 32;
-	int hscx = bcs->hw.hscx.hscx;
 	unsigned char *p;
 
 	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
 	if (!p)
 		return;
 
-	waitforXFW(cs, hscx);
+	waitforXFW(bcs);
 	jade_write_fifo(bcs, p, count);
-	WriteJADECMDR(cs, hscx, jade_HDLC_XCMD,
+	WriteJADECMDR(bcs, jade_HDLC_XCMD,
 		      more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
 }
 
@@ -99,7 +70,6 @@
 {
 	u8 r;
 	struct BCState *bcs = cs->bcs + jade;
-	struct sk_buff *skb;
 	int fifo_size = 32;
 	int count;
 	int i_jade = (int) jade; /* To satisfy the compiler */
@@ -119,39 +89,20 @@
 			if (!(r & 0x20))
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "JADE %c CRC error", 'A'+jade);
-			WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
+			WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC);
+			bcs->rcvidx = 0;
 		} else {
 			count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
 			if (count == 0)
 				count = fifo_size;
+
 			jade_empty_fifo(bcs, count);
-			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
-				if (cs->debug & L1_DEB_HSCX_FIFO)
-					debugl1(cs, "HX Frame %d", count);
-				if (!(skb = dev_alloc_skb(count)))
-					printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
-				else {
-					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
-					skb_queue_tail(&bcs->rqueue, skb);
-				}
-			}
+			recv_rme_b(bcs);
 		}
-		bcs->hw.hscx.rcvidx = 0;
-		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		jade_empty_fifo(bcs, fifo_size);
-		if (bcs->mode == L1_MODE_TRANS) {
-			/* receive audio data */
-			if (!(skb = dev_alloc_skb(fifo_size)))
-				printk(KERN_WARNING "HiSax: receive out of memory\n");
-			else {
-				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
-				skb_queue_tail(&bcs->rqueue, skb);
-			}
-			bcs->hw.hscx.rcvidx = 0;
-			sched_b_event(bcs, B_RCVBUFREADY);
-		}
+		recv_rpf_b(bcs);
 	}
 	if (val & 0x10) {	/* XPR */
 		xmit_xpr_b(bcs);
@@ -161,7 +112,7 @@
 static void
 reset_xmit(struct BCState *bcs)
 {
-	WriteJADECMDR(bcs->cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
+	WriteJADECMDR(bcs, jade_HDLC_XCMD, jadeXCMD_XRES);
 }
 
 void
diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
--- a/drivers/isdn/hisax/mic.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/mic.c	Mon Jan 13 10:18:07 2003
@@ -132,111 +132,37 @@
 	.write_fifo = hscx_write_fifo,
 };
 
-static void
-mic_interrupt(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
-
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-}
-
-void
-release_io_mic(struct IsdnCardState *cs)
-{
-	int bytecnt = 8;
-
-	if (cs->hw.mic.cfg_reg)
-		release_region(cs->hw.mic.cfg_reg, bytecnt);
-}
-
-static int
-mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			return(0);
-		case CARD_RELEASE:
-			release_io_mic(cs);
-			return(0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
+static struct card_ops mic_ops = {
+	.init     = inithscxisac,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
 
 int __init
 setup_mic(struct IsdnCard *card)
 {
-	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, mic_revision);
 	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_MIC)
-		return (0);
 
-	bytecnt = 8;
 	cs->hw.mic.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
 	cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
 	cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
 	cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
 
-	if (!request_region((cs->hw.mic.cfg_reg), bytecnt, "mic isdn")) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.mic.cfg_reg,
-		       cs->hw.mic.cfg_reg + bytecnt);
-		return (0);
-	}
-
-	printk(KERN_INFO
-	       "mic: defined at 0x%x IRQ %d\n",
-	       cs->hw.mic.cfg_reg,
-	       cs->irq);
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &mic_card_msg;
-	cs->irq_func = &mic_interrupt;
-	ISACVersion(cs, "mic:");
-	if (HscxVersion(cs, "mic:")) {
-		printk(KERN_WARNING
-		    "mic: wrong HSCX versions check IO address\n");
-		release_io_mic(cs);
-		return (0);
-	}
-	return (1);
+	if (!request_io(&cs->rs, cs->hw.mic.cfg_reg, 8, "mic isdn"))
+		goto err;
+  
+	printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
+	       cs->hw.mic.cfg_reg, cs->irq);
+	cs->card_ops = &mic_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
--- a/drivers/isdn/hisax/netjet.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/netjet.c	Mon Jan 13 10:18:05 2003
@@ -839,6 +839,7 @@
 tiger_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
+	struct IsdnCardState *cs = st->l1.bcs->cs;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
@@ -853,13 +854,13 @@
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
 			mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
-			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
-			st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc));
+			if (cs->hw.njet.bc_activate)
+				(cs->hw.njet.bc_activate)(cs, st->l1.bc);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
-			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
-			st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc));
+			if (cs->hw.njet.bc_deactivate)
+				(cs->hw.njet.bc_deactivate)(cs, st->l1.bc);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
@@ -937,6 +938,8 @@
  
 static struct bc_l1_ops netjet_l1_ops = {
 	.fill_fifo = netjet_fill_dma,
+	.open      = setstack_tiger,
+	.close     = close_tigerstate,
 };
 
 void __init
@@ -994,13 +997,9 @@
 		inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
 		bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
 	cs->hw.njet.last_is0 = 0;
-	cs->bcs[0].BC_SetStack = setstack_tiger;
-	cs->bcs[1].BC_SetStack = setstack_tiger;
-	cs->bcs[0].BC_Close = close_tigerstate;
-	cs->bcs[1].BC_Close = close_tigerstate;
 }
 
-void
+static void
 releasetiger(struct IsdnCardState *cs)
 {
 	if (cs->bcs[0].hw.tiger.send) {
@@ -1026,11 +1025,11 @@
 }
 
 void
-release_io_netjet(struct IsdnCardState *cs)
+netjet_release(struct IsdnCardState *cs)
 {
 	byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
 	byteout(cs->hw.njet.base + NETJET_IRQMASK1, 0);
 	releasetiger(cs);
-	release_region(cs->hw.njet.base, 256);
+	hisax_release_resources(cs);
 }
 
diff -Nru a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h
--- a/drivers/isdn/hisax/netjet.h	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/netjet.h	Mon Jan 13 10:18:07 2003
@@ -70,5 +70,5 @@
 void netjet_fill_dma(struct BCState *bcs);
 void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs);
 void inittiger(struct IsdnCardState *cs);
-void release_io_netjet(struct IsdnCardState *cs);
+void netjet_release(struct IsdnCardState *cs);
 
diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
--- a/drivers/isdn/hisax/niccy.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/niccy.c	Mon Jan 13 10:18:05 2003
@@ -155,9 +155,7 @@
 niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
 	
-	spin_lock(&cs->lock);
 	if (cs->subtyp == NICCY_PCI) {
 		int ival;
 		ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
@@ -165,37 +163,11 @@
 			return;
 		outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
 	}
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
+	hscxisac_irq(intno, dev_id, regs);
 }
 
 void
-release_io_niccy(struct IsdnCardState *cs)
+niccy_release(struct IsdnCardState *cs)
 {
 	if (cs->subtyp == NICCY_PCI) {
 		int val;
@@ -203,15 +175,11 @@
 		val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
 		val &= PCI_IRQ_DISABLE;
 		outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
-		release_region(cs->hw.niccy.cfg_reg, 0x40);
-		release_region(cs->hw.niccy.isac, 4);
-	} else {
-		release_region(cs->hw.niccy.isac, 2);
-		release_region(cs->hw.niccy.isac_ale, 2);
 	}
+	hisax_release_resources(cs);
 }
 
-static void
+static int
 niccy_reset(struct IsdnCardState *cs)
 {
 	if (cs->subtyp == NICCY_PCI) {
@@ -221,31 +189,19 @@
 		val |= PCI_IRQ_ENABLE;
 		outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
 	}
-	inithscxisac(cs);
+	return 0;
 }
 
-static int
-niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			niccy_reset(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_niccy(cs);
-			return(0);
-		case CARD_INIT:
-			niccy_reset(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
+static struct card_ops niccy_ops = {
+	.init     = inithscxisac,
+	.reset    = niccy_reset,
+	.release  = niccy_release,
+	.irq_func = niccy_interrupt,
+};
 
 static struct pci_dev *niccy_dev __initdata = NULL;
 #ifdef __ISAPNP__
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __init
@@ -256,36 +212,40 @@
 
 	strcpy(tmp, niccy_revision);
 	printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_NICCY)
-		return (0);
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pci_bus *pb;
-		struct pci_dev *pd;
+		struct pnp_card *pb;
+		struct pnp_dev  *pd;
 
-		if ((pb = isapnp_find_card(
+		if ((pb = pnp_find_card(
 			ISAPNP_VENDOR('S', 'D', 'A'),
 			ISAPNP_FUNCTION(0x0150), pnp_c))) {
 			pnp_c = pb;
 			pd = NULL;
-			if (!(pd = isapnp_find_dev(pnp_c,
+			if (!(pd = pnp_find_dev(pnp_c,
 				ISAPNP_VENDOR('S', 'D', 'A'),
 				ISAPNP_FUNCTION(0x0150), pd))) {
 				printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n");
 				return (0);
 			}
-			pd->prepare(pd);
-			pd->deactivate(pd);
-			pd->activate(pd);
-			card->para[1] = pd->resource[0].start;
-			card->para[2] = pd->resource[1].start;
-			card->para[0] = pd->irq_resource[0].start;
-			if (!card->para[0] || !card->para[1] || !card->para[2]) {
+			if (pnp_device_attach(pd) < 0) {
+				printk(KERN_ERR "NiccyPnP: attach failed\n");
+				return 0;
+			}
+			if (pnp_activate_dev(pd, NULL) < 0) {
+				printk(KERN_ERR "NiccyPnP: activate failed\n");
+				pnp_device_detach(pd);
+				return 0;
+			}
+			if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
 				printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n",
-					card->para[0], card->para[1], card->para[2]);
-				pd->deactivate(pd);
+					pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
+				pnp_device_detach(pd);
 				return(0);
 			}
+			card->para[1] = pnp_port_start(pd, 0);
+			card->para[2] = pnp_port_start(pd, 1);
+			card->para[0] = pnp_irq(pd, 0);
 		} else {
 			printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n");
 		}
@@ -299,30 +259,13 @@
 		cs->hw.niccy.cfg_reg = 0;
 		cs->subtyp = NICCY_PNP;
 		cs->irq = card->para[0];
-		if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) {
-			printk(KERN_WARNING
-				"HiSax: %s data port %x-%x already in use\n",
-				CardType[card->typ],
-				cs->hw.niccy.isac,
-				cs->hw.niccy.isac + 1);
-			return (0);
-		}
-		if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) {
-			printk(KERN_WARNING
-				"HiSax: %s address port %x-%x already in use\n",
-				CardType[card->typ],
-				cs->hw.niccy.isac_ale,
-				cs->hw.niccy.isac_ale + 1);
-			release_region(cs->hw.niccy.isac, 2);
-			return (0);
-		}
+		if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
+			goto err;
+		if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
+			goto err;
 	} else {
 #if CONFIG_PCI
 		u_int pci_ioaddr;
-		if (!pci_present()) {
-			printk(KERN_ERR "Niccy: no PCI bus present\n");
-			return(0);
-		}
 		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
 			PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
@@ -354,43 +297,21 @@
 		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
 		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
 		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-		if (!request_region(cs->hw.niccy.isac, 4, "niccy")) {
-			printk(KERN_WARNING
-				"HiSax: %s data port %x-%x already in use\n",
-				CardType[card->typ],
-				cs->hw.niccy.isac,
-				cs->hw.niccy.isac + 4);
-			return (0);
-		}
-		if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) {
-			printk(KERN_WARNING
-			       "HiSax: %s pci port %x-%x already in use\n",
-				CardType[card->typ],
-				cs->hw.niccy.cfg_reg,
-				cs->hw.niccy.cfg_reg + 0x40);
-			release_region(cs->hw.niccy.isac, 4);
-			return (0);
-		}
-#else
-		printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n");
-		printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n");
-		return (0);
+
+		if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
+			goto err;
+		if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
+			goto err;
 #endif /* CONFIG_PCI */
 	}
-	printk(KERN_INFO
-		"HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
+	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
 		CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
 		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &niccy_card_msg;
-	cs->irq_func = &niccy_interrupt;
-	ISACVersion(cs, "Niccy:");
-	if (HscxVersion(cs, "Niccy:")) {
-		printk(KERN_WARNING
-		    "Niccy: wrong HSCX versions check IO address\n");
-		release_io_niccy(cs);
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &niccy_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	niccy_release(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
--- a/drivers/isdn/hisax/nj_s.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/nj_s.c	Mon Jan 13 10:18:05 2003
@@ -18,7 +18,7 @@
 const char *NETjet_S_revision = "$Revision: 2.7.6.6 $";
 
 static void
-netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+nj_s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
 	u8 val, sval;
@@ -72,8 +72,8 @@
 	spin_unlock(&cs->lock);
 }
 
-static void
-reset_netjet_s(struct IsdnCardState *cs)
+static int
+nj_s_reset(struct IsdnCardState *cs)
 {
 	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
@@ -89,34 +89,28 @@
 	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
 	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+	return 0;
 }
 
-static int
-NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+nj_s_init(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_netjet_s(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_netjet(cs);
-			return(0);
-		case CARD_INIT:
-			inittiger(cs);
-			initisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
+	inittiger(cs);
+	initisac(cs);
 }
 
+static struct card_ops nj_s_ops = {
+	.init     = nj_s_init,
+	.reset    = nj_s_reset,
+	.release  = netjet_release,
+	.irq_func = nj_s_interrupt,
+};
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_s(struct IsdnCard *card)
 {
-	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
@@ -125,17 +119,8 @@
 #endif
 	strcpy(tmp, NETjet_S_revision);
 	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_NETJET_S)
-		return(0);
 
-#if CONFIG_PCI
-
-	for ( ;; )
-	{
-		if (!pci_present()) {
-			printk(KERN_ERR "Netjet: no PCI bus present\n");
-			return(0);
-		}
+	for ( ;; ) {
 		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
 			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
 			if (pci_enable_device(dev_netjet))
@@ -202,34 +187,15 @@
                 }
                 break;
 	}
-#else
-
-	printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n");
-	printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n");
-	return (0);
-
-#endif /* CONFIG_PCI */
-
-	bytecnt = 256;
-
 	printk(KERN_INFO
 		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
 		cs->hw.njet.base, cs->irq);
-	if (check_region(cs->hw.njet.base, bytecnt)) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %#lx-%#lx already in use\n",
-		       CardType[card->typ],
-		       cs->hw.njet.base,
-		       cs->hw.njet.base + bytecnt);
-		return (0);
-	} else {
-		request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn");
-	}
-	reset_netjet_s(cs);
-	cs->dc_hw_ops = &netjet_dc_ops;
-	cs->cardmsg = &NETjet_S_card_msg;
-	cs->irq_func = &netjet_s_interrupt;
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		return 0;
+	
+	nj_s_reset(cs);
 	cs->irq_flags |= SA_SHIRQ;
-	ISACVersion(cs, "NETjet-S:");
-	return (1);
+	cs->card_ops = &nj_s_ops;
+	isac_setup(cs, &netjet_dc_ops);
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
--- a/drivers/isdn/hisax/nj_u.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/nj_u.c	Mon Jan 13 10:18:05 2003
@@ -18,7 +18,7 @@
 const char *NETjet_U_revision = "$Revision: 2.8.6.6 $";
 
 static void
-netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+nj_u_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
 	u8 val, sval;
@@ -72,8 +72,8 @@
 	spin_unlock(&cs->lock);
 }
 
-static void
-reset_netjet_u(struct IsdnCardState *cs)
+static int
+nj_u_reset(struct IsdnCardState *cs)
 {
 	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
@@ -91,56 +91,39 @@
 	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
 	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+	return 0;
 }
 
-static int
-NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+nj_u_init(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_netjet_u(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_netjet(cs);
-			return(0);
-		case CARD_INIT:
-			inittiger(cs);
-			initicc(cs);
-			/* Reenable all IRQ */
-			NETjet_WriteIC(cs, ICC_MASK, 0);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
+	inittiger(cs);
+	initicc(cs);
+	/* Reenable all IRQ */
+	NETjet_WriteIC(cs, ICC_MASK, 0);
 }
 
+static struct card_ops nj_u_ops = {
+	.init     = nj_u_init,
+	.reset    = nj_u_reset,
+	.release  = netjet_release,
+	.irq_func = nj_u_interrupt,
+};
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_u(struct IsdnCard *card)
 {
-	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-#if CONFIG_PCI
-#endif
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_U_revision);
 	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_NETJET_U)
-		return(0);
-
-#if CONFIG_PCI
 
-	for ( ;; )
-	{
-		if (!pci_present()) {
-			printk(KERN_ERR "Netjet: no PCI bus present\n");
-			return(0);
-		}
+	for ( ;; ) {
 		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
 			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
 			if (pci_enable_device(dev_netjet))
@@ -200,32 +183,15 @@
                 }
                 break;
 	}
-#else
-
-	printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n");
-	printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n");
-	return (0);
-
-#endif /* CONFIG_PCI */
-
-	bytecnt = 256;
-
 	printk(KERN_INFO
 		"NETspider-U: PCI card configured at %#lx IRQ %d\n",
 		cs->hw.njet.base, cs->irq);
-	if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %#lx-%#lx already in use\n",
-		       CardType[card->typ],
-		       cs->hw.njet.base,
-		       cs->hw.njet.base + bytecnt);
-		return (0);
-	}
-	reset_netjet_u(cs);
-	cs->dc_hw_ops = &netjet_dc_ops;
-	cs->cardmsg = &NETjet_U_card_msg;
-	cs->irq_func = &netjet_u_interrupt;
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		return 0;
+	
+	nj_u_reset(cs);
 	cs->irq_flags |= SA_SHIRQ;
-	ICCVersion(cs, "NETspider-U:");
-	return (1);
+	cs->card_ops = &nj_u_ops;
+	icc_setup(cs, &netjet_dc_ops);
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
--- a/drivers/isdn/hisax/s0box.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/s0box.c	Mon Jan 13 10:18:05 2003
@@ -166,70 +166,11 @@
 	.write_fifo = hscx_write_fifo,
 };
  
-static void
-s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
-{
-#define MAXCOUNT 5
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
-	int count = 0;
-
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	count++;
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val && count < MAXCOUNT) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val && count < MAXCOUNT) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	if (count >= MAXCOUNT)
-		printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-}
-
-void
-release_io_s0box(struct IsdnCardState *cs)
-{
-	release_region(cs->hw.teles3.cfg_reg, 8);
-}
-
-static int
-S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			break;
-		case CARD_RELEASE:
-			release_io_s0box(cs);
-			break;
-		case CARD_INIT:
-			inithscxisac(cs);
-			break;
-		case CARD_TEST:
-			break;
-	}
-	return(0);
-}
+static struct card_ops s0box_ops = {
+	.init     = inithscxisac,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
 
 int __init
 setup_s0box(struct IsdnCard *card)
@@ -239,9 +180,6 @@
 
 	strcpy(tmp, s0box_revision);
 	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_S0BOX)
-		return (0);
-
 	cs->hw.teles3.cfg_reg = card->para[1];
 	cs->hw.teles3.hscx[0] = -0x20;
 	cs->hw.teles3.hscx[1] = 0x0;
@@ -250,14 +188,8 @@
 	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
 	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
 	cs->irq = card->para[0];
-	if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) {
-		printk(KERN_WARNING
-		       "HiSax: %s ports %x-%x already in use\n",
-		       CardType[cs->typ],
-                       cs->hw.teles3.cfg_reg,
-                       cs->hw.teles3.cfg_reg + 7);
-		return 0;
-	} 
+	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O"))
+		goto err;
 	printk(KERN_INFO
 	       "HiSax: %s config irq:%d isac:0x%x  cfg:0x%x\n",
 	       CardType[cs->typ], cs->irq,
@@ -265,16 +197,11 @@
 	printk(KERN_INFO
 	       "HiSax: hscx A:0x%x  hscx B:0x%x\n",
 	       cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &S0Box_card_msg;
-	cs->irq_func = &s0box_interrupt;
-	ISACVersion(cs, "S0Box:");
-	if (HscxVersion(cs, "S0Box:")) {
-		printk(KERN_WARNING
-		       "S0Box: wrong HSCX versions check IO address\n");
-		release_io_s0box(cs);
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &s0box_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
--- a/drivers/isdn/hisax/saphir.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/saphir.c	Mon Jan 13 10:18:05 2003
@@ -136,42 +136,9 @@
 saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
 
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	/* Watchdog */
-	if (cs->hw.saphir.timer.function) 
-		mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
-	else
-		printk(KERN_WARNING "saphir: Spurious timer!\n");
-
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
+	hscxisac_irq(intno, dev_id, regs);
+	mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
 }
 
 static void
@@ -182,14 +149,13 @@
 	mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
 }
 
-void
-release_io_saphir(struct IsdnCardState *cs)
+static void
+saphir_release(struct IsdnCardState *cs)
 {
 	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
 	del_timer_sync(&cs->hw.saphir.timer);
 	cs->hw.saphir.timer.function = NULL;
-	if (cs->hw.saphir.cfg_reg)
-		release_region(cs->hw.saphir.cfg_reg, 6);
+	hisax_release_resources(cs);
 }
 
 static int
@@ -228,25 +194,12 @@
 	return (0);
 }
 
-static int
-saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			saphir_reset(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_saphir(cs);
-			return(0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
-
+static struct card_ops saphir_ops = {
+	.init     = inithscxisac,
+	.reset    = saphir_reset,
+	.release  = saphir_release,
+	.irq_func = saphir_interrupt,
+};
 
 int __init
 setup_saphir(struct IsdnCard *card)
@@ -259,20 +212,15 @@
 	if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
 		return (0);
 
+	init_timer(&cs->hw.saphir.timer);
 	/* IO-Ports */
 	cs->hw.saphir.cfg_reg = card->para[1];
 	cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
 	cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
 	cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
 	cs->irq = card->para[0];
-	if (!request_region((cs->hw.saphir.cfg_reg), 6, "saphir")) {
-		printk(KERN_WARNING
-			"HiSax: %s config port %x-%x already in use\n",
-			CardType[card->typ],
-			cs->hw.saphir.cfg_reg,
-			cs->hw.saphir.cfg_reg + 5);
-		return (0);
-	}
+	if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir"))
+		goto err;
 
 	printk(KERN_INFO
 	       "HiSax: %s config irq:%d io:0x%X\n",
@@ -281,23 +229,17 @@
 
 	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
 	cs->hw.saphir.timer.data = (long) cs;
-	init_timer(&cs->hw.saphir.timer);
 	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
 	add_timer(&cs->hw.saphir.timer);
-	if (saphir_reset(cs)) {
-		release_io_saphir(cs);
-		return (0);
-	}
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &saphir_card_msg;
-	cs->irq_func = &saphir_interrupt;
-	ISACVersion(cs, "saphir:");
-	if (HscxVersion(cs, "saphir:")) {
-		printk(KERN_WARNING
-		    "saphir: wrong HSCX versions check IO address\n");
-		release_io_saphir(cs);
-		return (0);
-	}
-	return (1);
+	if (saphir_reset(cs))
+		goto err;
+
+	cs->card_ops = &saphir_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+
+	return 1;
+ err:
+	saphir_release(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
--- a/drivers/isdn/hisax/sedlbauer.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/sedlbauer.c	Mon Jan 13 10:18:07 2003
@@ -189,37 +189,6 @@
 };
 
 static u8
-ipac_dc_read(struct IsdnCardState *cs, u8 offset)
-{
-	return readreg(cs, cs->hw.sedl.isac, offset|0x80);
-}
-
-static void
-ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	writereg(cs, cs->hw.sedl.isac, offset|0x80, value);
-}
-
-static void
-ipac_dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	readfifo(cs, cs->hw.sedl.isac, 0x80, data, size);
-}
-
-static void
-ipac_dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	writefifo(cs, cs->hw.sedl.isac, 0x80, data, size);
-}
-
-static struct dc_hw_ops ipac_dc_ops = {
-	.read_reg   = ipac_dc_read,
-	.write_reg  = ipac_dc_write,
-	.read_fifo  = ipac_dc_read_fifo,
-	.write_fifo = ipac_dc_write_fifo,
-};
-
-static u8
 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
 {
 	return readreg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0));
@@ -250,6 +219,36 @@
 	.write_fifo = hscx_write_fifo,
 };
 
+static inline u8
+ipac_read(struct IsdnCardState *cs, u8 offset)
+{
+	return readreg(cs, cs->hw.sedl.isac, offset);
+}
+
+static inline void
+ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+{
+	writereg(cs, cs->hw.sedl.isac, offset, value);
+}
+
+static inline void
+ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+{
+	readfifo(cs, cs->hw.sedl.isac, offset, data, size);
+}
+
+static inline void
+ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+{
+	writefifo(cs, cs->hw.sedl.isac, offset, data, size);
+}
+
+/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
+ * above */
+
+BUILD_IPAC_OPS(ipac);
+
+
 /* ISAR access routines
  * mode = 0 access with IRQ on
  * mode = 1 access with IRQ off
@@ -289,12 +288,6 @@
 sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
-
-	if (!cs) {
-		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
-		return;
-	}
 
 	if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
 		/* The card tends to generate interrupts while being removed
@@ -302,84 +295,11 @@
 		printk(KERN_WARNING "Sedlbauer: card not available!\n");
 		return;
 	}
-
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
+	hscxisac_irq(intno, dev_id, regs);
 }
 
 static void
-sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u8 ista, val, icnt = 5;
-
-	if (!cs) {
-		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
-		return;
-	}
-	ista = readreg(cs, cs->hw.sedl.isac, IPAC_ISTA);
-Start_IPAC:
-	if (cs->debug & L1_DEB_IPAC)
-		debugl1(cs, "IPAC ISTA %02X", ista);
-	if (ista & 0x0f) {
-		val = hscx_read(cs, 1, HSCX_ISTA);
-		if (ista & 0x01)
-			val |= 0x01;
-		if (ista & 0x04)
-			val |= 0x02;
-		if (ista & 0x08)
-			val |= 0x04;
-		if (val)
-			hscx_int_main(cs, val);
-	}
-	if (ista & 0x20) {
-		val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe;
-		if (val) {
-			isac_interrupt(cs, val);
-		}
-	}
-	if (ista & 0x10) {
-		val = 0x01;
-		isac_interrupt(cs, val);
-	}
-	ista  = readreg(cs, cs->hw.sedl.isac, IPAC_ISTA);
-	if ((ista & 0x3f) && icnt) {
-		icnt--;
-		goto Start_IPAC;
-	}
-	if (!icnt)
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "Sedlbauer IRQ LOOP");
-	writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
-	writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
-}
-
-static void
-sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
+sedlbauer_isar_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
 	u8 val;
@@ -417,108 +337,121 @@
 	spin_unlock(&cs->lock);
 }
 
-void
-release_io_sedlbauer(struct IsdnCardState *cs)
+static int
+sedlbauer_ipac_reset(struct IsdnCardState *cs)
 {
-	int bytecnt = 8;
+	writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);
+	writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0);
+	writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
+	writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0);
+	writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
+	writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
+	return 0;
+}
 
-	if (cs->subtyp == SEDL_SPEED_FAX) {
-		bytecnt = 16;
-	} else if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
-		bytecnt = 256;
-	}
-	if (cs->hw.sedl.cfg_reg)
-		release_region(cs->hw.sedl.cfg_reg, bytecnt);
+static int
+sedlbauer_isar_pci_reset(struct IsdnCardState *cs)
+{
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout((20*HZ)/1000);
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout((20*HZ)/1000);
+	return 0;
 }
 
-static void
-reset_sedlbauer(struct IsdnCardState *cs)
+static int
+sedlbauer_reset(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "Sedlbauer: resetting card\n");
+	if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA &&
+	   cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX)
+		return 0;
 
-	if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
-	   (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
-		if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
-			writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout((10*HZ)/1000);
-			writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout((10*HZ)/1000);
-			writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0);
-			writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
-			writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0);
-			writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
-			writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
-		} else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
-			(cs->hw.sedl.bus == SEDL_BUS_PCI)) {
-			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout((20*HZ)/1000);
-			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout((20*HZ)/1000);
-		} else {		
-			byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout((10*HZ)/1000);
-			byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout((10*HZ)/1000);
-		}
+	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+		return sedlbauer_ipac_reset(cs);
+	} else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
+		   (cs->hw.sedl.bus == SEDL_BUS_PCI)) {
+		return sedlbauer_isar_pci_reset(cs);
+	} else {		
+		byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout((10*HZ)/1000);
+		byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout((10*HZ)/1000);
 	}
+	return 0;
 }
 
-static int
-Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+sedlbauer_isar_release(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_sedlbauer(cs);
-			return(0);
-		case CARD_RELEASE:
-			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-				isar_write(cs, 0, ISAR_IRQBIT, 0);
-				isac_write(cs, ISAC_MASK, 0xFF);
-				reset_sedlbauer(cs);
-				isar_write(cs, 0, ISAR_IRQBIT, 0);
-				isac_write(cs, ISAC_MASK, 0xFF);
-			}
-			release_io_sedlbauer(cs);
-			return(0);
-		case CARD_INIT:
-			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-				isar_write(cs, 0, ISAR_IRQBIT, 0);
-				initisac(cs);
-				initisar(cs);
-			} else {
-				inithscxisac(cs);
-			}
-			return(0);
-		case CARD_TEST:
-			return(0);
-		case MDL_INFO_CONN:
-			if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
-				return(0);
-			if ((long) arg)
-				cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
-			else
-				cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
-			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-			break;
-		case MDL_INFO_REL:
-			if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
-				return(0);
-			if ((long) arg)
-				cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2;
-			else
-				cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1;
-			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-			break;
-	}
-	return(0);
+	isar_write(cs, 0, ISAR_IRQBIT, 0);
+	isac_write(cs, ISAC_MASK, 0xFF);
+	sedlbauer_reset(cs);
+	isar_write(cs, 0, ISAR_IRQBIT, 0);
+	isac_write(cs, ISAC_MASK, 0xFF);
+	hisax_release_resources(cs);
+}
+
+static void
+sedlbauer_led_handler(struct IsdnCardState *cs)
+{
+	if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
+		return;
+
+	if (cs->status & 0x2000)
+		cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
+	else
+		cs->hw.sedl.reset_off |=  SEDL_ISAR_PCI_LED2;
+
+	if (cs->status & 0x1000)
+		cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
+	else
+		cs->hw.sedl.reset_off |=  SEDL_ISAR_PCI_LED1;
+
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+}
+
+static void
+sedlbauer_isar_init(struct IsdnCardState *cs)
+{
+	isar_write(cs, 0, ISAR_IRQBIT, 0);
+	initisac(cs);
+	initisar(cs);
 }
 
+static struct card_ops sedlbauer_ops = {
+	.init        = inithscxisac,
+	.reset       = sedlbauer_reset,
+	.release     = hisax_release_resources,
+	.led_handler = sedlbauer_led_handler,
+	.irq_func    = sedlbauer_interrupt,
+};
+
+static struct card_ops sedlbauer_ipac_ops = {
+	.init        = ipac_init,
+	.reset       = sedlbauer_reset,
+	.release     = hisax_release_resources,
+	.led_handler = sedlbauer_led_handler,
+	.irq_func    = ipac_irq,
+};
+
+static struct card_ops sedlbauer_isar_ops = {
+	.init        = sedlbauer_isar_init,
+	.reset       = sedlbauer_reset,
+	.release     = sedlbauer_isar_release,
+	.led_handler = sedlbauer_led_handler,
+	.irq_func    = sedlbauer_isar_interrupt,
+};
+
 static struct pci_dev *dev_sedl __devinitdata = NULL;
 
 #ifdef __ISAPNP__
@@ -533,13 +466,13 @@
 };
 
 static struct isapnp_device_id *pdev = &sedl_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
 setup_sedlbauer(struct IsdnCard *card)
 {
-	int bytecnt, ver, val;
+	int bytecnt, val;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u16 sub_vendor_id, sub_id;
@@ -572,31 +505,38 @@
 	} else {
 #ifdef __ISAPNP__
 		if (isapnp_present()) {
-			struct pci_bus *pb;
-			struct pci_dev *pd;
+			struct pnp_card *pb;
+			struct pnp_dev *pd;
 
 			while(pdev->card_vendor) {
-				if ((pb = isapnp_find_card(pdev->card_vendor,
-					pdev->card_device, pnp_c))) {
+				if ((pb = pnp_find_card(pdev->card_vendor,
+						        pdev->card_device,
+						        pnp_c))) {
 					pnp_c = pb;
 					pd = NULL;
-					if ((pd = isapnp_find_dev(pnp_c,
-						pdev->vendor, pdev->function, pd))) {
+					if ((pd = pnp_find_dev(pnp_c,
+							       pdev->vendor,
+							       pdev->function,
+							       pd))) {
 						printk(KERN_INFO "HiSax: %s detected\n",
 							(char *)pdev->driver_data);
-						pd->prepare(pd);
-						pd->deactivate(pd);
-						pd->activate(pd);
-						card->para[1] =
-							pd->resource[0].start;
-						card->para[0] =
-							pd->irq_resource[0].start;
-						if (!card->para[0] || !card->para[1]) {
+						if (pnp_device_attach(pd) < 0) {
+							printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
+							return 0;
+						}
+						if (pnp_activate_dev(pd, NULL) < 0) {
+							printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
+							pnp_device_detach(pd);
+							return 0;
+						}
+						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
 							printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
-								card->para[0], card->para[1]);
-							pd->deactivate(pd);
-							return(0);
+								pnp_irq(pd, 0), pnp_port_start(pd, 0));
+							pnp_device_detach(pd);
+							goto err;
 						}
+						card->para[1] = pnp_port_start(pd, 0);
+						card->para[0] = pnp_irq(pd, 0);
 						cs->hw.sedl.cfg_reg = card->para[1];
 						cs->irq = card->para[0];
 						if (pdev->function == ISAPNP_FUNCTION(0x2)) {
@@ -610,7 +550,7 @@
 						goto ready;
 					} else {
 						printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
-						return(0);
+						goto err;
 					}
 				}
 				pdev++;
@@ -623,23 +563,19 @@
 #endif
 /* Probe for Sedlbauer speed pci */
 #if CONFIG_PCI
-		if (!pci_present()) {
-			printk(KERN_ERR "Sedlbauer: no PCI bus present\n");
-			return(0);
-		}
 		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
 				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
 			if (pci_enable_device(dev_sedl))
-				return(0);
+				goto err;
 			cs->irq = dev_sedl->irq;
 			if (!cs->irq) {
 				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
-				return(0);
+				goto err;
 			}
 			cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
 		} else {
 			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
-			return(0);
+			goto err;
 		}
 		cs->irq_flags |= SA_SHIRQ;
 		cs->hw.sedl.bus = SEDL_BUS_PCI;
@@ -651,7 +587,7 @@
 			cs->hw.sedl.cfg_reg);
 		if (sub_id != PCI_SUB_ID_SEDLBAUER) {
 			printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
-			return(0);
+			goto err;
 		}
 		if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
 			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
@@ -665,7 +601,7 @@
 		} else {
 			printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
 				sub_vendor_id);
-			return(0);
+			goto err;
 		}
 		bytecnt = 256;
 		cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
@@ -678,9 +614,6 @@
 		current->state = TASK_UNINTERRUPTIBLE;
 		schedule_timeout((10*HZ)/1000);
 		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-#else
-		printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
-		return (0);
 #endif /* CONFIG_PCI */
 	}	
 ready:	
@@ -688,14 +621,9 @@
 	 * reserved for us by the card manager. So we do not check it
 	 * here, it would fail.
 	 */
-	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
-	    (!request_region((cs->hw.sedl.cfg_reg), bytecnt, "sedlbauer isdn"))) {
-		printk(KERN_WARNING
-			"HiSax: %s config port %x-%x already in use\n",
-			CardType[card->typ],
-			cs->hw.sedl.cfg_reg,
-			cs->hw.sedl.cfg_reg + bytecnt);
-			return (0);
+	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) {
+		if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn"))
+			goto err;
 	}
 
 	printk(KERN_INFO
@@ -704,9 +632,6 @@
 	       cs->hw.sedl.cfg_reg + bytecnt,
 	       cs->irq);
 
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &Sedl_card_msg;
-
 /*
  * testing ISA and PCMCIA Cards for IPAC, default is ISAC
  * do not test for PCI card, because ports are different
@@ -749,16 +674,12 @@
 			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
 			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
 		}
-		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-		cs->dc_hw_ops = &ipac_dc_ops;
-		cs->irq_func = &sedlbauer_interrupt_ipac;
-
-		val = readreg(cs, cs->hw.sedl.isac, IPAC_ID);
-		printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
-		reset_sedlbauer(cs);
+		cs->card_ops = &sedlbauer_ipac_ops;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+		sedlbauer_reset(cs);
 	} else {
 		/* ISAC_HSCX oder ISAC_ISAR */
-		cs->dc_hw_ops = &isac_ops;
 		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
 			if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
 				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
@@ -782,17 +703,11 @@
 			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
 			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
 			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
-			cs->irq_func = &sedlbauer_interrupt_isar;
+			cs->card_ops = &sedlbauer_isar_ops;
 			cs->auxcmd = &isar_auxcmd;
-			ISACVersion(cs, "Sedlbauer:");
-			cs->bc_hw_ops = &isar_ops;
-			ver = ISARVersion(cs, "Sedlbauer:");
-			if (ver < 0) {
-				printk(KERN_WARNING
-					"Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
-				release_io_sedlbauer(cs);
-				return (0);
-			}
+			isac_setup(cs, &isac_ops);
+			if (isar_setup(cs, &isar_ops))
+				goto err;
 		} else {
 			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
 				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
@@ -807,17 +722,15 @@
 				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
 				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
 			}
-			cs->irq_func = &sedlbauer_interrupt;
-			ISACVersion(cs, "Sedlbauer:");
-		
-			if (HscxVersion(cs, "Sedlbauer:")) {
-				printk(KERN_WARNING
-					"Sedlbauer: wrong HSCX versions check IO address\n");
-				release_io_sedlbauer(cs);
-				return (0);
-			}
-			reset_sedlbauer(cs);
+			cs->card_ops = &sedlbauer_ops;
+			if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+				goto err;
+
+			sedlbauer_reset(cs);
 		}
 	}
-	return (1);
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
--- a/drivers/isdn/hisax/sportster.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/sportster.c	Mon Jan 13 10:18:05 2003
@@ -115,36 +115,13 @@
 sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
 
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	/* get a new irq impulse if there any pending */
+	hscxisac_irq(intno, dev_id, regs);
 	bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1);
-	spin_unlock(&cs->lock);
 }
 
-void
-release_io_sportster(struct IsdnCardState *cs)
+static void
+sportster_release(struct IsdnCardState *cs)
 {
 	int i, adr;
 
@@ -155,8 +132,8 @@
 	}
 }
 
-void
-reset_sportster(struct IsdnCardState *cs)
+static int
+sportster_reset(struct IsdnCardState *cs)
 {
 	cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */
 	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
@@ -166,33 +143,34 @@
 	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
+	return 0;
 }
 
 static int
 Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_sportster(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_sportster(cs);
-			return(0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
-			byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
 	return(0);
 }
 
+static void
+sportster_init(struct IsdnCardState *cs)
+{
+	inithscxisac(cs);
+	cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
+	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
+}
+
+static struct card_ops sportster_ops = {
+	.init     = sportster_init,
+	.reset    = sportster_reset,
+	.release  = sportster_release,
+	.irq_func = sportster_interrupt,
+};
+
 static int __init
 get_io_range(struct IsdnCardState *cs)
 {
-	int i, j, adr;
+	int i, adr;
 	
 	for (i=0;i<64;i++) {
 		adr = cs->hw.spt.cfg_reg + i *1024;
@@ -200,20 +178,18 @@
 			printk(KERN_WARNING
 				"HiSax: %s config port %x-%x already in use\n",
 				CardType[cs->typ], adr, adr + 8);
-			break;
+			goto err;
 		}
 	}
-	if (i==64)
-		return(1);
-	else {
-		for (j=0; j<i; j++) {
-			adr = cs->hw.spt.cfg_reg + j *1024;
-			release_region(adr, 8);
-		}
-		return(0);
+	return 1;
+ err:
+	for (i=i-1; i >= 0; i--) {
+		adr = cs->hw.spt.cfg_reg + i *1024;
+		release_region(adr, 8);
 	}
+	return 0;
 }
-
+  
 int __init
 setup_sportster(struct IsdnCard *card)
 {
@@ -222,8 +198,6 @@
 
 	strcpy(tmp, sportster_revision);
 	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_SPORTSTER)
-		return (0);
 
 	cs->hw.spt.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
@@ -248,26 +222,20 @@
 			break;
 		case 15:cs->hw.spt.res_irq = 7;
 			break;
-		default:release_io_sportster(cs);
+		default:sportster_release(cs);
 			printk(KERN_WARNING "Sportster: wrong IRQ\n");
 			return(0);
 	}
-	reset_sportster(cs);
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.spt.cfg_reg);
+	sportster_reset(cs);
+	printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg);
 
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
 	cs->cardmsg = &Sportster_card_msg;
-	cs->irq_func = &sportster_interrupt;
-	ISACVersion(cs, "Sportster:");
-	if (HscxVersion(cs, "Sportster:")) {
-		printk(KERN_WARNING
-		       "Sportster: wrong HSCX versions check IO address\n");
-		release_io_sportster(cs);
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &sportster_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
--- a/drivers/isdn/hisax/tei.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/tei.c	Mon Jan 13 10:18:07 2003
@@ -74,6 +74,22 @@
 	"EV_T202",
 };
 
+static inline void
+mdl_assign(struct IsdnCardState *cs)
+{
+	cs->status |= 0x0001;
+	if (cs->card_ops->led_handler)
+		cs->card_ops->led_handler(cs);
+}
+
+static inline void
+mdl_remove(struct IsdnCardState *cs)
+{
+	cs->status = 0;
+	if (cs->card_ops->led_handler)
+		cs->card_ops->led_handler(cs);
+}
+
 unsigned int
 random_ri(void)
 {
@@ -167,7 +183,7 @@
 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
 		L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
+		mdl_assign(cs);
 	}
 }
 
@@ -241,7 +257,7 @@
 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
 		L3L2(st, MDL_REMOVE | REQUEST, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
+		mdl_remove(cs);
 	}
 }
 
@@ -277,7 +293,7 @@
 		st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
 		L3L2(st, MDL_ERROR | RESPONSE, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
+		mdl_remove(cs);
 		FsmChangeState(fi, ST_TEI_NOP);
 	}
 }
@@ -300,7 +316,7 @@
 			"verify req for tei %d failed", st->l2.tei);
 		L3L2(st, MDL_REMOVE | REQUEST, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
+		mdl_remove(cs);
 		FsmChangeState(fi, ST_TEI_NOP);
 	}
 }
@@ -373,7 +389,7 @@
 					"fixed assign tei %d", st->l2.tei);
 			L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
 			cs = (struct IsdnCardState *) st->l1.hardware;
-			cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
+			mdl_assign(cs);
 		}
 		return;
 	}
diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
--- a/drivers/isdn/hisax/teleint.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/teleint.c	Mon Jan 13 10:18:07 2003
@@ -179,7 +179,7 @@
 };
 
 static void
-TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+teleint_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
 	u8 val;
@@ -217,17 +217,16 @@
 	add_timer(&cs->hw.hfc.timer);
 }
 
-void
-release_io_TeleInt(struct IsdnCardState *cs)
+static void
+teleint_release(struct IsdnCardState *cs)
 {
 	del_timer(&cs->hw.hfc.timer);
 	releasehfc(cs);
-	if (cs->hw.hfc.addr)
-		release_region(cs->hw.hfc.addr, 2);
+	hisax_release_resources(cs);
 }
 
-static void
-reset_TeleInt(struct IsdnCardState *cs)
+static int
+teleint_reset(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "TeleInt: resetting card\n");
 	cs->hw.hfc.cirm |= HFC_RESET;
@@ -238,30 +237,25 @@
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset Off */
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
+	return 0;
 }
 
-static int
-TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+static void
+teleint_init(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			reset_TeleInt(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_TeleInt(cs);
-			return(0);
-		case CARD_INIT:
-			inithfc(cs);
-			initisac(cs);
-			cs->hw.hfc.timer.expires = jiffies + 1;
-			add_timer(&cs->hw.hfc.timer);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
+	inithfc(cs);
+	initisac(cs);
+	cs->hw.hfc.timer.expires = jiffies + 1;
+	add_timer(&cs->hw.hfc.timer);
 }
 
+static struct card_ops teleint_ops = {
+	.init     = teleint_init,
+	.reset    = teleint_reset,
+	.release  = teleint_release,
+	.irq_func = teleint_interrupt,
+};
+
 int __init
 setup_TeleInt(struct IsdnCard *card)
 {
@@ -270,8 +264,6 @@
 
 	strcpy(tmp, TeleInt_revision);
 	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_TELEINT)
-		return (0);
 
 	cs->hw.hfc.addr = card->para[1] & 0x3fe;
 	cs->irq = card->para[0];
@@ -285,16 +277,9 @@
 	cs->hw.hfc.timer.function = (void *) TeleInt_Timer;
 	cs->hw.hfc.timer.data = (long) cs;
 	init_timer(&cs->hw.hfc.timer);
-	if (check_region((cs->hw.hfc.addr), 2)) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.hfc.addr,
-		       cs->hw.hfc.addr + 2);
-		return (0);
-	} else {
-		request_region(cs->hw.hfc.addr, 2, "TeleInt isdn");
-	}
+	if (!request_io(&cs->rs, cs->hw.hfc.addr, 2, "TeleInt isdn"))
+		goto err;
+	
 	/* HW IO = IO */
 	byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
 	byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
@@ -319,8 +304,7 @@
 			break;
 		default:
 			printk(KERN_WARNING "TeleInt: wrong IRQ\n");
-			release_io_TeleInt(cs);
-			return (0);
+			goto err;
 	}
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
@@ -330,11 +314,12 @@
 	       cs->hw.hfc.addr,
 	       cs->irq);
 
-	reset_TeleInt(cs);
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hfc_ops;
-	cs->cardmsg = &TeleInt_card_msg;
-	cs->irq_func = &TeleInt_interrupt;
-	ISACVersion(cs, "TeleInt:");
-	return (1);
+	cs->card_ops = &teleint_ops;
+	teleint_reset(cs);
+	isac_setup(cs, &isac_ops);
+	hfc_setup(cs, &hfc_ops);
+	return 1;
+ err:
+	teleint_release(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
--- a/drivers/isdn/hisax/teles0.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/teles0.c	Mon Jan 13 10:18:06 2003
@@ -48,7 +48,7 @@
 isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
 {
 	int i;
-	unsigned long ad = cs->hw.teles0.membase + 0x100;
+	void *ad = cs->hw.teles0.membase + 0x100;
 	for (i = 0; i < size; i++)
 		data[i] = readb(ad);
 }
@@ -57,7 +57,7 @@
 isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
 {
 	int i;
-	unsigned long ad = cs->hw.teles0.membase + 0x100;
+	void *ad = cs->hw.teles0.membase + 0x100;
 	for (i = 0; i < size; i++) {
 		writeb(data[i], ad); mb();
 	}
@@ -88,7 +88,7 @@
 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
 {
 	int i;
-	unsigned long ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180);
+	void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180);
 	for (i = 0; i < size; i++)
 		data[i] = readb(ad);
 }
@@ -97,7 +97,7 @@
 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
 {
 	int i;
-	unsigned long ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180);
+	void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180);
 	for (i = 0; i < size; i++) {
 		writeb(data[i], ad);
 	}
@@ -110,55 +110,8 @@
 	.write_fifo = hscx_write_fifo,
 };
 
-static void
-teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
-	int count = 0;
-
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	count++;
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val && count < 5) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val && count < 5) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-}
-
-void
-release_io_teles0(struct IsdnCardState *cs)
-{
-	if (cs->hw.teles0.cfg_reg)
-		release_region(cs->hw.teles0.cfg_reg, 8);
-	iounmap((unsigned char *)cs->hw.teles0.membase);
-	release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
-}
-
 static int
-reset_teles0(struct IsdnCardState *cs)
+teles0_reset(struct IsdnCardState *cs)
 {
 	u8 cfval;
 
@@ -205,24 +158,12 @@
 	return(0);
 }
 
-static int
-Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			reset_teles0(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_teles0(cs);
-			return(0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
+static struct card_ops teles0_ops = {
+	.init     = inithscxisac,
+	.reset    = teles0_reset,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
 
 int __init
 setup_teles0(struct IsdnCard *card)
@@ -233,9 +174,6 @@
 
 	strcpy(tmp, teles0_revision);
 	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
-	if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0))
-		return (0);
-
 	if (cs->typ == ISDN_CTYPE_16_0)
 		cs->hw.teles0.cfg_reg = card->para[2];
 	else			/* 8.0 */
@@ -249,76 +187,50 @@
 	}
 	cs->irq = card->para[0];
 	if (cs->hw.teles0.cfg_reg) {
-		if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) {
-			printk(KERN_WARNING
-			  "HiSax: %s config port %x-%x already in use\n",
-			       CardType[card->typ],
-			       cs->hw.teles0.cfg_reg,
-			       cs->hw.teles0.cfg_reg + 8);
-			return (0);
-		}
-	}
-	if (cs->hw.teles0.cfg_reg) {
+		if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
+			goto err;
+
 		if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
 			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
 			       cs->hw.teles0.cfg_reg + 0, val);
-			release_region(cs->hw.teles0.cfg_reg, 8);
-			return (0);
+			goto err;
 		}
 		if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
 			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
 			       cs->hw.teles0.cfg_reg + 1, val);
-			release_region(cs->hw.teles0.cfg_reg, 8);
-			return (0);
+			goto err;
 		}
-		val = bytein(cs->hw.teles0.cfg_reg + 2);	/* 0x1e=without AB
-								   * 0x1f=with AB
-								   * 0x1c 16.3 ???
-								 */
+		val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
+							 * 0x1f=with AB
+							 * 0x1c 16.3 ???
+							 */
 		if (val != 0x1e && val != 0x1f) {
 			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
 			       cs->hw.teles0.cfg_reg + 2, val);
-			release_region(cs->hw.teles0.cfg_reg, 8);
-			return (0);
+			goto err;
 		}
 	}
 	/* 16.0 and 8.0 designed for IOM1 */
 	test_and_set_bit(HW_IOM1, &cs->HW_Flags);
 	cs->hw.teles0.phymem = card->para[1];
-	if (check_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE)) {
-		printk(KERN_WARNING
-			"HiSax: %s memory region %lx-%lx already in use\n",
-			CardType[card->typ],
-			cs->hw.teles0.phymem,
-			cs->hw.teles0.phymem + TELES_IOMEM_SIZE);
-		if (cs->hw.teles0.cfg_reg)
-			release_region(cs->hw.teles0.cfg_reg, 8);
-		return (0);
-	} else {
-		request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE,
-			"teles iomem");
-	}
-	cs->hw.teles0.membase =
-		(unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
+	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem");
+	if (!cs->hw.teles0.membase)
+		goto err;
+
 	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n",
+	       "HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n",
 	       CardType[cs->typ], cs->irq,
 	       cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
-	if (reset_teles0(cs)) {
+	if (teles0_reset(cs)) {
 		printk(KERN_WARNING "Teles0: wrong IRQ\n");
-		release_io_teles0(cs);
-		return (0);
-	}
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &Teles_card_msg;
-	cs->irq_func = &teles0_interrupt;
-	ISACVersion(cs, "Teles0:");
-	if (HscxVersion(cs, "Teles0:")) {
-		printk(KERN_WARNING
-		 "Teles0: wrong HSCX versions check IO/MEM addresses\n");
-		release_io_teles0(cs);
-		return (0);
+		goto err;
 	}
-	return (1);
+	cs->card_ops = &teles0_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+  		goto err;
+	return 1;
+
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
--- a/drivers/isdn/hisax/teles3.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/teles3.c	Mon Jan 13 10:18:07 2003
@@ -113,77 +113,8 @@
 	.write_fifo = hscx_write_fifo,
 };
 
-static void
-teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs)
-{
-#define MAXCOUNT 5
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
-	int count = 0;
-
-	spin_lock(&cs->lock);
-	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	count++;
-	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
-	if (val && count < MAXCOUNT) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
-	if (val && count < MAXCOUNT) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	if (count >= MAXCOUNT)
-		printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count);
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-}
-
-inline static void
-release_ioregs(struct IsdnCardState *cs, int mask)
-{
-	if (mask & 1)
-		release_region(cs->hw.teles3.isac + 32, 32);
-	if (mask & 2)
-		release_region(cs->hw.teles3.hscx[0] + 32, 32);
-	if (mask & 4)
-		release_region(cs->hw.teles3.hscx[1] + 32, 32);
-}
-
-void
-release_io_teles3(struct IsdnCardState *cs)
-{
-	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		release_region(cs->hw.teles3.hscx[1], 96);
-	} else {
-		if (cs->hw.teles3.cfg_reg) {
-			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-				release_region(cs->hw.teles3.cfg_reg, 1);
-			} else {
-				release_region(cs->hw.teles3.cfg_reg, 8);
-			}
-		}
-		release_ioregs(cs, 0x7);
-	}
-}
-
 static int
-reset_teles3(struct IsdnCardState *cs)
+teles3_reset(struct IsdnCardState *cs)
 {
 	u8 irqcfg;
 
@@ -238,24 +169,12 @@
 	return(0);
 }
 
-static int
-Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			reset_teles3(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_teles3(cs);
-			return(0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
+static struct card_ops teles3_ops = {
+	.init     = inithscxisac,
+	.reset    = teles3_reset,
+	.release  = hisax_release_resources,
+	.irq_func = hscxisac_irq,
+};
 
 #ifdef __ISAPNP__
 static struct isapnp_device_id teles_ids[] __initdata = {
@@ -272,7 +191,7 @@
 };
 
 static struct isapnp_device_id *tdev = &teles_ids[0];
-static struct pci_bus *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
@@ -290,31 +209,41 @@
 
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pci_bus *pb;
-		struct pci_dev *pd;
+		struct pnp_card *pnp_card;
+		struct pnp_dev *pnp_dev;
 
 		while(tdev->card_vendor) {
-			if ((pb = isapnp_find_card(tdev->card_vendor,
-				tdev->card_device, pnp_c))) {
-				pnp_c = pb;
-				pd = NULL;
-				if ((pd = isapnp_find_dev(pnp_c,
-					tdev->vendor, tdev->function, pd))) {
+			if ((pnp_card = pnp_find_card(tdev->card_vendor,
+						      tdev->card_device, pnp_c))) {
+				pnp_c = pnp_card;
+				pnp_dev = NULL;
+				if ((pnp_dev = pnp_find_dev(pnp_card,
+							    tdev->vendor,
+							    tdev->function,
+							    pnp_dev))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
 						(char *)tdev->driver_data);
-					pd->prepare(pd);
-					pd->deactivate(pd);
-					pd->activate(pd);
-					card->para[3] = pd->resource[2].start;
-					card->para[2] = pd->resource[1].start;
-					card->para[1] = pd->resource[0].start;
-					card->para[0] = pd->irq_resource[0].start;
-					if (!card->para[0] || !card->para[1] || !card->para[2]) {
-						printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n",
-						card->para[0], card->para[1], card->para[2]);
-						pd->deactivate(pd);
-						return(0);
+					if (pnp_device_attach(pnp_dev) < 0) {
+						printk(KERN_ERR "Teles PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pnp_dev, NULL) < 0) {
+						printk(KERN_ERR "Teles PnP: activate failed\n");
+						pnp_device_detach(pnp_dev);
+						return 0;
+					}
+					if (!pnp_irq_valid(pnp_dev, 0) ||
+					    !pnp_port_valid(pnp_dev, 0) ||
+					    !pnp_port_valid(pnp_dev, 1)) {
+						printk(KERN_ERR "Teles PnP: some resources are missing %ld/%lx/%lx\n",
+							pnp_irq(pnp_dev, 0), pnp_port_start(pnp_dev, 0), pnp_port_start(pnp_dev, 1));
+						pnp_device_detach(pnp_dev);
+						return 0;
 					}
+					card->para[3] = pnp_port_start(pnp_dev, 2);
+					card->para[2] = pnp_port_start(pnp_dev, 1);
+					card->para[1] = pnp_port_start(pnp_dev, 0);
+					card->para[0] = pnp_irq(pnp_dev, 0);
 					break;
 				} else {
 					printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
@@ -362,95 +291,35 @@
 	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
 	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
 	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (!request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) {
-			printk(KERN_WARNING
-			       "HiSax: %s ports %x-%x already in use\n",
-			       CardType[cs->typ],
-			       cs->hw.teles3.hscx[1],
-			       cs->hw.teles3.hscx[1] + 96);
-			return (0);
-		}
+		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA"))
+			goto err;
 	} else {
 		if (cs->hw.teles3.cfg_reg) {
 			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-				if (!request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) {
-					printk(KERN_WARNING
-						"HiSax: %s config port %x already in use\n",
-						CardType[card->typ],
-						cs->hw.teles3.cfg_reg);
-					return (0);
-				}
+				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
+					goto err;
 			} else {
-				if (!request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) {
-					printk(KERN_WARNING
-					       "HiSax: %s config port %x-%x already in use\n",
-					       CardType[card->typ],
-					       cs->hw.teles3.cfg_reg,
-						cs->hw.teles3.cfg_reg + 8);
-					return (0);
-				}
-			}
-		}
-		if (!request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac")) {
-			printk(KERN_WARNING
-			   "HiSax: %s isac ports %x-%x already in use\n",
-			       CardType[cs->typ],
-			       cs->hw.teles3.isac + 32,
-			       cs->hw.teles3.isac + 64);
-			if (cs->hw.teles3.cfg_reg) {
-				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-					release_region(cs->hw.teles3.cfg_reg, 1);
-				} else {
-					release_region(cs->hw.teles3.cfg_reg, 8);
-				}
+				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
+					goto err;
 			}
-			return (0);
-		}
-		if (!request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) {
-			printk(KERN_WARNING
-			 "HiSax: %s hscx A ports %x-%x already in use\n",
-			       CardType[cs->typ],
-			       cs->hw.teles3.hscx[0] + 32,
-			       cs->hw.teles3.hscx[0] + 64);
-			if (cs->hw.teles3.cfg_reg) {
-				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-					release_region(cs->hw.teles3.cfg_reg, 1);
-				} else {
-					release_region(cs->hw.teles3.cfg_reg, 8);
-				}
-			}
-			release_ioregs(cs, 1);
-			return (0);
-		}
-		if (!request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) {
-			printk(KERN_WARNING
-			 "HiSax: %s hscx B ports %x-%x already in use\n",
-			       CardType[cs->typ],
-			       cs->hw.teles3.hscx[1] + 32,
-			       cs->hw.teles3.hscx[1] + 64);
-			if (cs->hw.teles3.cfg_reg) {
-				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-					release_region(cs->hw.teles3.cfg_reg, 1);
-				} else {
-					release_region(cs->hw.teles3.cfg_reg, 8);
-				}
-			}
-			release_ioregs(cs, 3);
-			return (0);
 		}
+		if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
+			goto err;
+		if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A"))
+			goto err;
+		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B"))
+			goto err;
 	}
 	if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
 		if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
 			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
 			       cs->hw.teles3.cfg_reg + 0, val);
-			release_io_teles3(cs);
-			return (0);
+			goto err;
 		}
 		if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
 			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
 			       cs->hw.teles3.cfg_reg + 1, val);
-			release_io_teles3(cs);
-			return (0);
+			goto err;
 		}
 		val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
 							 * 0x1f=with AB
@@ -462,8 +331,7 @@
 		if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
 			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
 			       cs->hw.teles3.cfg_reg + 2, val);
-			release_io_teles3(cs);
-			return (0);
+			goto err;
 		}
 	}
 	printk(KERN_INFO
@@ -474,21 +342,16 @@
 	       "HiSax: hscx A:0x%X  hscx B:0x%X\n",
 	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
 
-	if (reset_teles3(cs)) {
+	if (teles3_reset(cs)) {
 		printk(KERN_WARNING "Teles3: wrong IRQ\n");
-		release_io_teles3(cs);
-		return (0);
+		goto err;
 	}
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &Teles_card_msg;
-	cs->irq_func = &teles3_interrupt;
-	ISACVersion(cs, "Teles3:");
-	if (HscxVersion(cs, "Teles3:")) {
-		printk(KERN_WARNING
-		       "Teles3: wrong HSCX versions check IO address\n");
-		release_io_teles3(cs);
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &teles3_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
+
 }
diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
--- a/drivers/isdn/hisax/telespci.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/hisax/telespci.c	Mon Jan 13 10:18:06 2003
@@ -45,7 +45,7 @@
 static u8
 isac_read(struct IsdnCardState *cs, u8 off)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 
 	ZORAN_WAIT_NOBUSY;
@@ -63,7 +63,7 @@
 static void
 isac_write(struct IsdnCardState *cs, u8 off, u8 data)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 
 	ZORAN_WAIT_NOBUSY;
@@ -80,7 +80,7 @@
 static void
 isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 	int i;
 
@@ -99,7 +99,7 @@
 static void
 isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 	int i;
 
@@ -124,7 +124,7 @@
 static u8
 hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 
 	ZORAN_WAIT_NOBUSY;
@@ -141,7 +141,7 @@
 static void
 hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 
 	ZORAN_WAIT_NOBUSY;
@@ -157,7 +157,7 @@
 static void
 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 	int i;
 
@@ -176,7 +176,7 @@
 static void
 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
 {
-	unsigned long adr = cs->hw.teles0.membase + 0x200;
+	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
 	int i;
 
@@ -225,29 +225,11 @@
 	spin_unlock(&cs->lock);
 }
 
-void
-release_io_telespci(struct IsdnCardState *cs)
-{
-	iounmap((void *)cs->hw.teles0.membase);
-}
-
-static int
-TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			return(0);
-		case CARD_RELEASE:
-			release_io_telespci(cs);
-			return(0);
-		case CARD_INIT:
-			inithscxisac(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
+static struct card_ops telespci_ops = {
+	.init     = inithscxisac,
+	.release  = hisax_release_resources,
+	.irq_func = telespci_interrupt,
+};
 
 static struct pci_dev *dev_tel __initdata = NULL;
 
@@ -262,13 +244,6 @@
 #endif
 	strcpy(tmp, telespci_revision);
 	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_TELESPCI)
-		return (0);
-#if CONFIG_PCI
-	if (!pci_present()) {
-		printk(KERN_ERR "TelesPCI: no PCI bus present\n");
-		return(0);
-	}
 	if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
 		if (pci_enable_device(dev_tel))
 			return(0);
@@ -277,19 +252,15 @@
 			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
 			return(0);
 		}
-		cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0),
-			PAGE_SIZE);
+		cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci");
+		if (!cs->hw.teles0.membase)
+			goto err;
 		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
 			pci_resource_start(dev_tel, 0), dev_tel->irq);
 	} else {
 		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
 		return(0);
 	}
-#else
-	printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
-	printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
-	return (0);
-#endif /* CONFIG_PCI */
 
 	/* Initialize Zoran PCI controller */
 	writel(0x00000000, cs->hw.teles0.membase + 0x28);
@@ -299,23 +270,17 @@
 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
 	writel(0x61000000, cs->hw.teles0.membase + 0x40);
 	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
-
 	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:%lx\n",
+	       "HiSax: %s config irq:%d mem:%p\n",
 	       CardType[cs->typ], cs->irq,
 	       cs->hw.teles0.membase);
 
-	cs->dc_hw_ops = &isac_ops;
-	cs->bc_hw_ops = &hscx_ops;
-	cs->cardmsg = &TelesPCI_card_msg;
-	cs->irq_func = &telespci_interrupt;
 	cs->irq_flags |= SA_SHIRQ;
-	ISACVersion(cs, "TelesPCI:");
-	if (HscxVersion(cs, "TelesPCI:")) {
-		printk(KERN_WARNING
-		 "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
-		release_io_telespci(cs);
-		return (0);
-	}
-	return (1);
+	cs->card_ops = &telespci_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 1;
+ err:
+	hisax_release_resources(cs);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
--- a/drivers/isdn/hisax/w6692.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/isdn/hisax/w6692.c	Mon Jan 13 10:18:07 2003
@@ -57,7 +57,7 @@
 	outb(value, cs->hw.w6692.iobase + offset);
 }
 
-static inline void
+static void
 w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
 {
 	insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);
@@ -69,6 +69,10 @@
 	outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);
 }
 
+static struct dc_hw_ops w6692_dc_hw_ops = {
+	.read_fifo = w6692_read_fifo,
+};
+
 static inline u8
 w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset)
 {
@@ -81,6 +85,16 @@
 	outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);
 }
 
+static void
+w6692_bc_read_fifo(struct IsdnCardState *cs, int bchan, u8 *data, int len)
+{
+	insb(cs->hw.w6692.iobase + W_B_RFIFO + (bchan ? 0x40:0), data, len);
+}
+
+static struct bc_hw_ops w6692_bc_hw_ops = {
+	.read_fifo  = w6692_bc_read_fifo,
+};
+
 static char *W6692Ver[] __initdata =
 {"W6692 V00", "W6692 V01", "W6692 V10",
  "W6692 V11"};
@@ -171,30 +185,8 @@
 static void
 W6692_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	u8 *ptr;
-
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, "W6692_empty_fifo");
-
-	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "W6692_empty_fifo overrun %d",
-				cs->rcvidx + count);
-		w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK);
-		cs->rcvidx = 0;
-		return;
-	}
-	ptr = cs->rcvbuf + cs->rcvidx;
-	cs->rcvidx += count;
-	w6692_read_fifo(cs, ptr, count);
+	recv_empty_fifo_d(cs, count);
 	w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK);
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "W6692_empty_fifo cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
 }
 
 static void
@@ -221,31 +213,8 @@
 static void
 W6692B_empty_fifo(struct BCState *bcs, int count)
 {
-	u8 *ptr;
-	struct IsdnCardState *cs = bcs->cs;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "W6692B_empty_fifo");
-
-	if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "W6692B_empty_fifo: incoming packet too large");
-		w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
-		bcs->hw.w6692.rcvidx = 0;
-		return;
-	}
-	ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx;
-	bcs->hw.w6692.rcvidx += count;
-	READW6692BFIFO(cs, bcs->channel, ptr, count);
-	w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
-			     bcs->channel + '1', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
+	recv_empty_fifo_b(bcs, count);
+	w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
 }
 
 static void
@@ -276,7 +245,6 @@
 	u8 val;
 	u8 r;
 	struct BCState *bcs;
-	struct sk_buff *skb;
 	int count;
 
 	bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1);
@@ -298,38 +266,18 @@
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "W6692 B CRC error");
 			w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
+			bcs->rcvidx = 0;
 		} else {
 			count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
 			if (count == 0)
 				count = W_B_FIFO_THRESH;
 			W6692B_empty_fifo(bcs, count);
-			if ((count = bcs->hw.w6692.rcvidx) > 0) {
-				if (cs->debug & L1_DEB_HSCX_FIFO)
-					debugl1(cs, "W6692 Bchan Frame %d", count);
-				if (!(skb = dev_alloc_skb(count)))
-					printk(KERN_WARNING "W6692: Bchan receive out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count);
-					skb_queue_tail(&bcs->rqueue, skb);
-				}
-			}
+			recv_rme_b(bcs);
 		}
-		bcs->hw.w6692.rcvidx = 0;
-		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & W_B_EXI_RMR) {	/* RMR */
 		W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
-		if (bcs->mode == L1_MODE_TRANS) {
-			/* receive audio data */
-			if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH)))
-				printk(KERN_WARNING "HiSax: receive out of memory\n");
-			else {
-				memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH);
-				skb_queue_tail(&bcs->rqueue, skb);
-			}
-			bcs->hw.w6692.rcvidx = 0;
-			sched_b_event(bcs, B_RCVBUFREADY);
-		}
+		recv_rpf_b(bcs);
 	}
 	if (val & W_B_EXI_XFR) {	/* XFR */
 		xmit_xpr_b(bcs);
@@ -340,11 +288,10 @@
 }
 
 static void
-W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
 	u8 val, exval, v1;
-	struct sk_buff *skb;
 	unsigned int count;
 	int icnt = 5;
 
@@ -369,23 +316,14 @@
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "W6692 D-channel ABORT");
 			w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
+			cs->rcvidx = 0;
 		} else {
 			count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
 			if (count == 0)
 				count = W_D_FIFO_THRESH;
 			W6692_empty_fifo(cs, count);
-			if ((count = cs->rcvidx) > 0) {
-				cs->rcvidx = 0;
-				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
-					printk(KERN_WARNING "HiSax: D receive out of memory\n");
-				else {
-					memcpy(skb_put(skb, count), cs->rcvbuf, count);
-					skb_queue_tail(&cs->rq, skb);
-				}
-			}
+			recv_rme_d(cs);
 		}
-		cs->rcvidx = 0;
-		sched_d_event(cs, D_RCVBUFREADY);
 	}
 	if (val & W_INT_D_RMR) {	/* RMR */
 		W6692_empty_fifo(cs, W_D_FIFO_THRESH);
@@ -518,15 +456,11 @@
 	}
 }
 
-static void
+static int
 setstack_W6692(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = W6692_l1hw;
-}
-
-static void
-DC_Close_W6692(struct IsdnCardState *cs)
-{
+	return 0;
 }
 
 static void
@@ -560,7 +494,7 @@
 				debugl1(cs, "D-Channel Busy no skb");
 			}
 			w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_XRST);	/* Transmitter reset */
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */
 		}
 	}
 }
@@ -632,52 +566,13 @@
 close_w6692state(struct BCState *bcs)
 {
 	W6692Bmode(bcs, 0, bcs->channel);
-	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (bcs->hw.w6692.rcvbuf) {
-			kfree(bcs->hw.w6692.rcvbuf);
-			bcs->hw.w6692.rcvbuf = NULL;
-		}
-		if (bcs->blog) {
-			kfree(bcs->blog);
-			bcs->blog = NULL;
-		}
-		skb_queue_purge(&bcs->rqueue);
-		skb_queue_purge(&bcs->squeue);
-		if (bcs->tx_skb) {
-			dev_kfree_skb_any(bcs->tx_skb);
-			bcs->tx_skb = NULL;
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		}
-	}
+	bc_close(bcs);
 }
 
 static int
 open_w6692state(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-			       "HiSax: No memory for w6692.rcvbuf\n");
-			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-			return (1);
-		}
-		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
-			printk(KERN_WARNING
-			       "HiSax: No memory for bcs->blog\n");
-			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-			kfree(bcs->hw.w6692.rcvbuf);
-			bcs->hw.w6692.rcvbuf = NULL;
-			return (2);
-		}
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	bcs->tx_skb = NULL;
-	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	bcs->event = 0;
-	bcs->hw.w6692.rcvidx = 0;
-	bcs->tx_cnt = 0;
-	return (0);
+	return bc_open(bcs);
 }
 
 static int
@@ -694,7 +589,8 @@
 	return (0);
 }
 
-void resetW6692(struct IsdnCardState *cs)
+static int
+w6692_reset(struct IsdnCardState *cs)
 {
 	w6692_write_reg(cs, W_D_CTL, W_D_CTL_SRST);
 	schedule_timeout((10*HZ)/1000);
@@ -714,72 +610,81 @@
 		w6692_write_reg(cs, W_PCTL, 0x80);
 		w6692_write_reg(cs, W_XDATA, 0x00);
 	}
+	return 0;
 }
 
-void __init initW6692(struct IsdnCardState *cs, int part)
+static void
+w6692_init(struct IsdnCardState *cs)
 {
-	if (part & 1) {
-		INIT_WORK(&cs->work, W6692_bh, cs);
-		cs->setstack_d = setstack_W6692;
-		cs->DC_Close = DC_Close_W6692;
-		cs->dbusytimer.function = (void *) dbusy_timer_handler;
-		cs->dbusytimer.data = (long) cs;
-		init_timer(&cs->dbusytimer);
-		resetW6692(cs);
-		ph_command(cs, W_L1CMD_RST);
-		cs->dc.w6692.ph_state = W_L1CMD_RST;
-		W6692_new_ph(cs);
-		ph_command(cs, W_L1CMD_ECK);
+	w6692_reset(cs);
+	ph_command(cs, W_L1CMD_RST);
+	cs->dc.w6692.ph_state = W_L1CMD_RST;
+	W6692_new_ph(cs);
+	ph_command(cs, W_L1CMD_ECK);
+	
+	W6692Bmode(cs->bcs, 0, 0);
+	W6692Bmode(cs->bcs + 1, 0, 0);
 
-		cs->bcs[0].BC_SetStack = setstack_w6692;
-		cs->bcs[1].BC_SetStack = setstack_w6692;
-		cs->bcs[0].BC_Close = close_w6692state;
-		cs->bcs[1].BC_Close = close_w6692state;
-		W6692Bmode(cs->bcs, 0, 0);
-		W6692Bmode(cs->bcs + 1, 0, 0);
-	}
-	if (part & 2) {
-		/* Reenable all IRQ */
-		w6692_write_reg(cs, W_IMASK, 0x18);
-		w6692_write_reg(cs, W_D_EXIM, 0x00);
-		w6692_bc_write_reg(cs, 0, W_B_EXIM, 0x00);
-		w6692_bc_write_reg(cs, 1, W_B_EXIM, 0x00);
-		/* Reset D-chan receiver and transmitter */
-		w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
-	}
+	/* Reenable all IRQ */
+	w6692_write_reg(cs, W_IMASK, 0x18);
+	w6692_write_reg(cs, W_D_EXIM, 0x00);
+	w6692_bc_write_reg(cs, 0, W_B_EXIM, 0x00);
+	w6692_bc_write_reg(cs, 1, W_B_EXIM, 0x00);
+	/* Reset D-chan receiver and transmitter */
+	w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
 }
 
-static int
-w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+
+static void
+w6692_release(struct IsdnCardState *cs)
 {
-	switch (mt) {
-		case CARD_RESET:
-			resetW6692(cs);
-			return (0);
-		case CARD_RELEASE:
-			w6692_write_reg(cs, W_IMASK, 0xff);
-			release_region(cs->hw.w6692.iobase, 256);
-			if (cs->subtyp == W6692_USR) {
-				w6692_write_reg(cs, W_XDATA, 0x04);
-			}
-			return (0);
-		case CARD_INIT:
-			initW6692(cs, 3);
-			return (0);
-		case CARD_TEST:
-			return (0);
-	}
-	return (0);
+	w6692_write_reg(cs, W_IMASK, 0xff);
+	if (cs->subtyp == W6692_USR)
+		w6692_write_reg(cs, W_XDATA, 0x04);
+	hisax_release_resources(cs);
 }
 
+static struct card_ops w6692_ops = {
+	.init     = w6692_init,
+	.reset    = w6692_reset,
+	.release  = w6692_release,
+	.irq_func = w6692_interrupt,
+};
+
+static struct dc_l1_ops w6692_dc_l1_ops = {
+	.fill_fifo  = W6692_fill_fifo,
+	.open       = setstack_W6692,
+	.bh_func    = W6692_bh,
+	.dbusy_func = dbusy_timer_handler,
+};
+
 static struct bc_l1_ops w6692_bc_l1_ops = {
 	.fill_fifo = W6692B_fill_fifo,
+	.open      = setstack_w6692,
+	.close     = close_w6692state,
 };
 
 static int id_idx ;
 
 static struct pci_dev *dev_w6692 __initdata = NULL;
 
+static int
+w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops,
+	    struct bc_hw_ops *bc_ops)
+{
+	cs->dc_hw_ops = dc_ops;
+	cs->bc_hw_ops = bc_ops;
+	dc_l1_init(cs, &w6692_dc_l1_ops);
+	cs->bc_l1_ops = &w6692_bc_l1_ops;
+	W6692Version(cs, "W6692:");
+	printk(KERN_INFO "W6692 ISTA=0x%X\n", w6692_read_reg(cs, W_ISTA));
+	printk(KERN_INFO "W6692 IMASK=0x%X\n", w6692_read_reg(cs, W_IMASK));
+	printk(KERN_INFO "W6692 D_EXIR=0x%X\n", w6692_read_reg(cs, W_D_EXIR));
+	printk(KERN_INFO "W6692 D_EXIM=0x%X\n", w6692_read_reg(cs, W_D_EXIM));
+	printk(KERN_INFO "W6692 D_RSTA=0x%X\n", w6692_read_reg(cs, W_D_RSTA));
+	return 0;
+}
+
 int __init 
 setup_w6692(struct IsdnCard *card)
 {
@@ -794,13 +699,6 @@
 #endif
 	strcpy(tmp, w6692_revision);
 	printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_W6692)
-		return (0);
-#if CONFIG_PCI
-	if (!pci_present()) {
-		printk(KERN_ERR "W6692: no PCI bus present\n");
-		return (0);
-	}
 	while (id_list[id_idx].vendor_id) {
 		dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
 					    id_list[id_idx].device_id,
@@ -844,36 +742,16 @@
 	printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
 	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
 	       pci_ioaddr, pci_irq);
-	if (!request_region((cs->hw.w6692.iobase), 256,
-			    id_list[cs->subtyp].card_name)) {
-		printk(KERN_WARNING
-		       "HiSax: %s I/O ports %x-%x already in use\n",
-		       id_list[cs->subtyp].card_name,
-		       cs->hw.w6692.iobase,
-		       cs->hw.w6692.iobase + 255);
-		return (0);
-	}
-#else
-	printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
-	printk(KERN_WARNING "HiSax: W6692 unable to config\n");
-	return (0);
-#endif				/* CONFIG_PCI */
-
+	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name))
+		return 0;
+	
 	printk(KERN_INFO
 	       "HiSax: %s config irq:%d I/O:%x\n",
 	       id_list[cs->subtyp].card_name, cs->irq,
 	       cs->hw.w6692.iobase);
 
-	cs->bc_l1_ops = &w6692_bc_l1_ops;
-	cs->DC_Send_Data = &W6692_fill_fifo;
-	cs->cardmsg = &w6692_card_msg;
-	cs->irq_func = &W6692_interrupt;
+	cs->card_ops = &w6692_ops;
+	w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops);
 	cs->irq_flags |= SA_SHIRQ;
-	W6692Version(cs, "W6692:");
-	printk(KERN_INFO "W6692 ISTA=0x%X\n", w6692_read_reg(cs, W_ISTA));
-	printk(KERN_INFO "W6692 IMASK=0x%X\n", w6692_read_reg(cs, W_IMASK));
-	printk(KERN_INFO "W6692 D_EXIR=0x%X\n", w6692_read_reg(cs, W_D_EXIR));
-	printk(KERN_INFO "W6692 D_EXIM=0x%X\n", w6692_read_reg(cs, W_D_EXIM));
-	printk(KERN_INFO "W6692 D_RSTA=0x%X\n", w6692_read_reg(cs, W_D_RSTA));
 	return (1);
 }
diff -Nru a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h
--- a/drivers/isdn/hisax/w6692.h	Mon Jan 13 10:18:05 2003
+++ b/drivers/isdn/hisax/w6692.h	Mon Jan 13 10:18:05 2003
@@ -18,9 +18,6 @@
 
 /* B-channel FIFO read/write routines */
 
-#define READW6692BFIFO(cs,bchan,ptr,count) \
-	insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count)
-
 #define WRITEW6692BFIFO(cs,bchan,ptr,count) \
 	outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count)
 
diff -Nru a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
--- a/drivers/isdn/i4l/isdn_tty.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/isdn/i4l/isdn_tty.c	Mon Jan 13 10:18:06 2003
@@ -1876,7 +1876,7 @@
 	 * line status register.
 	 */
 	if (info->flags & ISDN_ASYNC_INITIALIZED) {
-		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
+		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
@@ -1901,7 +1901,7 @@
 	tty->closing = 0;
 	if (info->blocked_open) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(50);
+		schedule_timeout(HZ/2);
 		wake_up_interruptible(&info->open_wait);
 	}
 	info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE |
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/md/md.c	Mon Jan 13 10:18:05 2003
@@ -2838,16 +2838,18 @@
 				       mdidx(mddev), mdidx(mddev2));
 				if (mddev < mddev2) {/* arbitrarily yield */
 					mddev->curr_resync = 1;
-					yield();
+					wake_up(&resync_wait);
 				}
 				if (wait_event_interruptible(resync_wait,
-							     mddev2->curr_resync < 2)) {
+							     mddev2->curr_resync < mddev->curr_resync)) {
 					flush_curr_signals();
 					err = -EINTR;
 					mddev_put(mddev2);
 					goto skip;
 				}
 			}
+			if (mddev->curr_resync == 1)
+				break;
 		}
 	} while (mddev->curr_resync < 2);
 
diff -Nru a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
--- a/drivers/media/radio/radio-cadet.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/media/radio/radio-cadet.c	Mon Jan 13 10:18:06 2003
@@ -47,7 +47,7 @@
 static int cadet_lock=0;
 
 static int cadet_probe(void);
-static struct pci_dev *dev;
+static struct pnp_dev *dev = NULL;
 static int isapnp_cadet_probe(void);
 
 /*
@@ -543,23 +543,26 @@
 
 static int isapnp_cadet_probe(void)
 {
-	dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'),
-	                       ISAPNP_FUNCTION(0x0c24), NULL);
+	dev = pnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'),
+			    ISAPNP_FUNCTION(0x0c24), NULL);
 
 	if (!dev)
 		return -ENODEV;
-	if (dev->prepare(dev)<0)
+	if (pnp_device_attach(dev) < 0)
 		return -EAGAIN;
-	if (!(dev->resource[0].flags & IORESOURCE_IO))
+	if (pnp_activate_dev(dev, NULL) < 0) {
+		printk ("radio-cadet: pnp configure failed (out of resources?)\n");
+		pnp_device_detach(dev);
+		return -EIO;
+	}
+	if (!pnp_port_valid(dev, 0)) {
+		pnp_device_detach(dev);
 		return -ENODEV;
-	if (dev->activate(dev)<0) {
-		printk ("radio-cadet: isapnp configure failed (out of resources?)\n");
-		return -ENOMEM;
 	}
 
-	io = dev->resource[0].start;
+	io = pnp_port_start(dev, 0);
 
-	printk ("radio-cadet: ISAPnP reports card at %#x\n", io);
+	printk ("radio-cadet: PnP reports device at %#x\n", io);
 
 	return io;
 }
@@ -645,7 +648,7 @@
 	release_region(io,2);
 
 	if (dev)
-		dev->deactivate(dev);
+		pnp_device_detach(dev);
 }
 
 module_init(cadet_init);
diff -Nru a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
--- a/drivers/media/radio/radio-sf16fmi.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/media/radio/radio-sf16fmi.c	Mon Jan 13 10:18:07 2003
@@ -36,7 +36,7 @@
 
 static int io = -1; 
 static int radio_nr = -1;
-static struct pci_dev *dev = NULL;
+static struct pnp_dev *dev = NULL;
 static struct semaphore lock;
 
 /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
@@ -253,24 +253,27 @@
 	int i = 0;
 
 	while (id_table[i].card_vendor != 0 && dev == NULL) {
-		dev = isapnp_find_dev(NULL, id_table[i].vendor,
-				      id_table[i].function, NULL);
+		dev = pnp_find_dev(NULL, id_table[i].vendor,
+				   id_table[i].function, NULL);
 		i++;
 	}
 
 	if (!dev)
 		return -ENODEV;
-	if (dev->prepare(dev) < 0)
+	if (pnp_device_attach(dev) < 0)
 		return -EAGAIN;
-	if (!(dev->resource[0].flags & IORESOURCE_IO))
-		return -ENODEV;
-	if (dev->activate(dev) < 0) {
-		printk ("radio-sf16fmi: ISAPnP configure failed (out of resources?)\n");
+	if (pnp_activate_dev(dev, NULL) < 0) {
+		printk ("radio-sf16fmi: PnP configure failed (out of resources?)\n");
+		pnp_device_detach(dev);
 		return -ENOMEM;
 	}
+	if (!pnp_port_valid(dev, 0)) {
+		pnp_device_detach(dev);
+		return -ENODEV;
+	}
 
-	i = dev->resource[0].start;
-	printk ("radio-sf16fmi: ISAPnP reports card at %#x\n", i);
+	i = pnp_port_start(dev, 0);
+	printk ("radio-sf16fmi: PnP reports card at %#x\n", i);
 
 	return i;
 }
@@ -320,7 +323,7 @@
 	video_unregister_device(&fmi_radio);
 	release_region(io, 2);
 	if (dev)
-		dev->deactivate(dev);
+		pnp_device_detach(dev);
 }
 
 module_init(fmi_init);
diff -Nru a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
--- a/drivers/mtd/devices/blkmtd.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/mtd/devices/blkmtd.c	Mon Jan 13 10:18:05 2003
@@ -1219,7 +1219,7 @@
   INIT_LIST_HEAD(&mtd_rawdevice->as.dirty_pages);
   INIT_LIST_HEAD(&mtd_rawdevice->as.locked_pages);
   mtd_rawdevice->as.host = NULL;
-  spin_lock_init(&(mtd_rawdevice->as.i_shared_lock));
+  init_MUTEX(&(mtd_rawdevice->as.i_shared_sem));
 
   mtd_rawdevice->as.a_ops = &blkmtd_aops;
   INIT_LIST_HEAD(&mtd_rawdevice->as.i_mmap);
diff -Nru a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
--- a/drivers/mtd/maps/sa1100-flash.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/mtd/maps/sa1100-flash.c	Mon Jan 13 10:18:05 2003
@@ -74,15 +74,15 @@
 }
 
 static struct map_info sa1100_map __initdata = {
-	name:		"SA1100 flash",
-	read8:		sa1100_read8,
-	read16:		sa1100_read16,
-	read32:		sa1100_read32,
-	copy_from:	sa1100_copy_from,
-	write8:		sa1100_write8,
-	write16:	sa1100_write16,
-	write32:	sa1100_write32,
-	copy_to:	sa1100_copy_to,
+	.name		= "SA1100 flash",
+	.read8		= sa1100_read8,
+	.read16		= sa1100_read16,
+	.read32		= sa1100_read32,
+	.copy_from	= sa1100_copy_from,
+	.write8		= sa1100_write8,
+	.write16	= sa1100_write16,
+	.write32	= sa1100_write32,
+	.copy_to	= sa1100_copy_to,
 };
 
 
@@ -108,24 +108,24 @@
 #ifdef CONFIG_SA1100_ADSBITSY
 static struct mtd_partition adsbitsy_partitions[] = {
 	{
-		name:		"bootROM",
-		size:		0x80000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"zImage",
-		size:		0x100000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"ramdisk.gz",
-		size:		0x300000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"User FS",
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "bootROM",
+		.size		= 0x80000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "zImage",
+		.size		= 0x100000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "ramdisk.gz",
+		.size		= 0x300000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "User FS",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 #endif
@@ -134,38 +134,38 @@
 /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
 static struct mtd_partition assabet4_partitions[] = {
 	{
-		name:		"bootloader",
-		size:		0x00020000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"bootloader params",
-		size:		0x00020000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"jffs",
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "bootloader",
+		.size		= 0x00020000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "bootloader params",
+		.size		= 0x00020000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "jffs",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 
 /* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */
 static struct mtd_partition assabet5_partitions[] = {
 	{
-		name:		"bootloader",
-		size:		0x00040000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"bootloader params",
-		size:		0x00040000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"jffs",
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "bootloader",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "bootloader params",
+		.size		= 0x00040000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "jffs",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 
@@ -180,21 +180,21 @@
  */
 static struct mtd_partition badge4_partitions[] = {
 	{
-		name:		"BLOB boot loader",
-		offset:		0,
-		size:		0x0000A000
-	}, {
-		name:		"params",
-		offset:		MTDPART_OFS_APPEND,
-		size:		0x00006000
-	}, {
-		name:		"kernel",
-		offset:		MTDPART_OFS_APPEND,
-		size:		0x00100000
-	}, {
-		name:		"root",
-		offset:		MTDPART_OFS_APPEND,
-		size:		MTDPART_SIZ_FULL
+		.name		= "BLOB boot loader",
+		.offset		= 0,
+		.size		= 0x0000A000
+	}, {
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 0x00006000
+	}, {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 0x00100000
+	}, {
+		.name		= "root",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL
 	}
 };
 #endif
@@ -204,41 +204,41 @@
 #ifdef CONFIG_SA1100_CERF_FLASH_32MB
 static struct mtd_partition cerf_partitions[] = {
 	{
-		name:		"firmware",
-		size:		0x00040000,
-		offset:		0,
-	}, {
-		name:		"params",
-		size:		0x00040000,
-		offset:		0x00040000,
-	}, {
-		name:		"kernel",
-		size:		0x00100000,
-		offset:		0x00080000,
-	}, {
-		name:		"rootdisk",
-		size:		0x01E80000,
-		offset:		0x00180000,
+		.name		= "firmware",
+		.size		= 0x00040000,
+		.offset		= 0,
+	}, {
+		.name		= "params",
+		.size		= 0x00040000,
+		.offset		= 0x00040000,
+	}, {
+		.name		= "kernel",
+		.size		= 0x00100000,
+		.offset		= 0x00080000,
+	}, {
+		.name		= "rootdisk",
+		.size		= 0x01E80000,
+		.offset		= 0x00180000,
 	}
 };
 #elif defined CONFIG_SA1100_CERF_FLASH_16MB
 static struct mtd_partition cerf_partitions[] = {
 	{
-		name:		"firmware",
-		size:		0x00020000,
-		offset:		0,
-	}, {
-		name:		"params",
-		size:		0x00020000,
-		offset:		0x00020000,
-	}, {
-		name:		"kernel",
-		size:		0x00100000,
-		offset:		0x00040000,
-	}, {
-		name:		"rootdisk",
-		size:		0x00EC0000,
-		offset:		0x00140000,
+		.name		= "firmware",
+		.size		= 0x00020000,
+		.offset		= 0,
+	}, {
+		.name		= "params",
+		.size		= 0x00020000,
+		.offset		= 0x00020000,
+	}, {
+		.name		= "kernel",
+		.size		= 0x00100000,
+		.offset		= 0x00040000,
+	}, {
+		.name		= "rootdisk",
+		.size		= 0x00EC0000,
+		.offset		= 0x00140000,
 	}
 };
 #elif defined CONFIG_SA1100_CERF_FLASH_8MB
@@ -251,36 +251,36 @@
 #ifdef CONFIG_SA1100_CONSUS
 static struct mtd_partition consus_partitions[] = {
 	{
-		name:		"Consus boot firmware",
-		offset: 	0,
-		size:		0x00040000,
-		mask_flags:	MTD_WRITABLE, /* force read-only */
-	}, {
-		name:		"Consus kernel",
-		offset: 	0x00040000,
-		size:		0x00100000,
-		mask_flags:	0,
+		.name		= "Consus boot firmware",
+		.offset		= 0,
+		.size		= 0x00040000,
+		.mask_flags	= MTD_WRITABLE, /* force read-only */
+	}, {
+		.name		= "Consus kernel",
+		.offset		= 0x00040000,
+		.size		= 0x00100000,
+		.mask_flags	= 0,
 	}, {
-		name:		"Consus disk",
-		offset: 	0x00140000,
+		.name		= "Consus disk",
+		.offset		= 0x00140000,
 		/* The rest (up to 16M) for jffs.  We could put 0 and
 		   make it find the size automatically, but right now
 		   i have 32 megs.  jffs will use all 32 megs if given
 		   the chance, and this leads to horrible problems
 		   when you try to re-flash the image because blob
 		   won't erase the whole partition. */
-		size:		0x01000000 - 0x00140000,
-		mask_flags:	0,
+		.size		= 0x01000000 - 0x00140000,
+		.mask_flags	= 0,
 	}, {
 		/* this disk is a secondary disk, which can be used as
 		   needed, for simplicity, make it the size of the other
 		   consus partition, although realistically it could be
 		   the remainder of the disk (depending on the file
 		   system used) */
-		 name:		"Consus disk2",
-		 offset:	0x01000000,
-		 size:		0x01000000 - 0x00140000,
-		 mask_flags:	0,
+		 .name		= "Consus disk2",
+		 .offset	= 0x01000000,
+		 .size		= 0x01000000 - 0x00140000,
+		 .mask_flags	= 0,
 	}
 };
 #endif
@@ -290,45 +290,45 @@
 #define FLEXANET_FLASH_SIZE		0x02000000
 static struct mtd_partition flexanet_partitions[] = {
 	{
-		name:		"bootloader",
-		size:		0x00040000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"bootloader params",
-		size:		0x00040000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"kernel",
-		size:		0x000C0000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"altkernel",
-		size:		0x000C0000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"root",
-		size:		0x00400000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"free1",
-		size:		0x00300000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"free2",
-		size:		0x00300000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
-	}, {
-		name:		"free3",
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,
+		.name		= "bootloader",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "bootloader params",
+		.size		= 0x00040000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "kernel",
+		.size		= 0x000C0000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "altkernel",
+		.size		= 0x000C0000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "root",
+		.size		= 0x00400000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "free1",
+		.size		= 0x00300000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "free2",
+		.size		= 0x00300000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "free3",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,
 	}
 };
 #endif
@@ -337,48 +337,48 @@
 static struct mtd_partition freebird_partitions[] = {
 #if CONFIG_SA1100_FREEBIRD_NEW
 	{
-		name:		"firmware",
-		size:		0x00040000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"kernel",
-		size:		0x00080000,
-		offset:		0x00040000,
-	}, {
-		name:		"params",
-		size:		0x00040000,
-		offset:		0x000C0000,
-	}, {
-		name:		"initrd",
-		size:		0x00100000,
-		offset:		0x00100000,
-	}, {
-		name:		"root cramfs",
-		size:		0x00300000,
-		offset:		0x00200000,
-	}, {
-		name:		"usr cramfs",
-		size:		0x00C00000,
-		offset:		0x00500000,
-	}, {
-		name:		"local",
-		size:		MTDPART_SIZ_FULL,
-		offset:		0x01100000,
+		.name		= "firmware",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "kernel",
+		.size		= 0x00080000,
+		.offset		= 0x00040000,
+	}, {
+		.name		= "params",
+		.size		= 0x00040000,
+		.offset		= 0x000C0000,
+	}, {
+		.name		= "initrd",
+		.size		= 0x00100000,
+		.offset		= 0x00100000,
+	}, {
+		.name		= "root cramfs",
+		.size		= 0x00300000,
+		.offset		= 0x00200000,
+	}, {
+		.name		= "usr cramfs",
+		.size		= 0x00C00000,
+		.offset		= 0x00500000,
+	}, {
+		.name		= "local",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= 0x01100000,
 	}
 #else
 	{
-		size:		0x00040000,
-		offset:		0,
+		.size		= 0x00040000,
+		.offset		= 0,
 	}, {
-		size:		0x000c0000,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= 0x000c0000,
+		.offset		= MTDPART_OFS_APPEND,
 	}, {
-		size:		0x00400000,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= 0x00400000,
+		.offset		= MTDPART_OFS_APPEND,
 	}, {
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 #endif
 };
@@ -389,29 +389,29 @@
 static struct mtd_partition frodo_partitions[] =
 {
 	{
-		name:		"bootloader",
-		size:		0x00040000,
-		offset: 	0x00000000,
-		mask_flags:	MTD_WRITEABLE
-	}, {
-		name:		"bootloader params",
-		size:		0x00040000,
-		offset: 	MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE
-	}, {
-		name:		"kernel",
-		size:		0x00100000,
-		offset: 	MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE
-	}, {
-		name:		"ramdisk",
-		size:		0x00400000,
-		offset: 	MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE
-	}, {
-		name:		"file system",
-		size:		MTDPART_SIZ_FULL,
-		offset: 	MTDPART_OFS_APPEND
+		.name		= "bootloader",
+		.size		= 0x00040000,
+		.offset		= 0x00000000,
+		.mask_flags	= MTD_WRITEABLE
+	}, {
+		.name		= "bootloader params",
+		.size		= 0x00040000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE
+	}, {
+		.name		= "kernel",
+		.size		= 0x00100000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE
+	}, {
+		.name		= "ramdisk",
+		.size		= 0x00400000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE
+	}, {
+		.name		= "file system",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND
 	}
 };
 #endif
@@ -419,19 +419,19 @@
 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
 static struct mtd_partition graphicsclient_partitions[] = {
 	{
-		name:		"zImage",
-		size:		0x100000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"ramdisk.gz",
-		size:		0x300000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"User FS",
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "zImage",
+		.size		= 0x100000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "ramdisk.gz",
+		.size		= 0x300000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "User FS",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 #endif
@@ -439,21 +439,21 @@
 #ifdef CONFIG_SA1100_GRAPHICSMASTER
 static struct mtd_partition graphicsmaster_partitions[] = {
 	{
-		name:		"zImage",
-		size:		0x100000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
+		.name		= "zImage",
+		.size		= 0x100000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
 	},
 	{
-		name:		"ramdisk.gz",
-		size:		0x300000,
-		offset:		MTDPART_OFS_APPEND,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
+		.name		= "ramdisk.gz",
+		.size		= 0x300000,
+		.offset		= MTDPART_OFS_APPEND,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
 	},
 	{
-		name:		"User FS",
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "User FS",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 #endif
@@ -461,44 +461,44 @@
 #ifdef CONFIG_SA1100_H3XXX
 static struct mtd_partition h3xxx_partitions[] = {
 	{
-		name:		"H3XXX boot firmware",
-		size:		0x00040000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
+		.name		= "H3XXX boot firmware",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
 	}, {
 #ifdef CONFIG_MTD_2PARTS_IPAQ
-		name:		"H3XXX root jffs2",
-		size:		MTDPART_SIZ_FULL,
-		offset:		0x00040000,
+		.name		= "H3XXX root jffs2",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= 0x00040000,
 #else
-		name:		"H3XXX kernel",
-		size:		0x00080000,
-		offset:		0x00040000,
-	}, {
-		name:		"H3XXX params",
-		size:		0x00040000,
-		offset:		0x000C0000,
+		.name		= "H3XXX kernel",
+		.size		= 0x00080000,
+		.offset		= 0x00040000,
+	}, {
+		.name		= "H3XXX params",
+		.size		= 0x00040000,
+		.offset		= 0x000C0000,
 	}, {
 #ifdef CONFIG_JFFS2_FS
-		name:		"H3XXX root jffs2",
-		size:		MTDPART_SIZ_FULL,
-		offset:		0x00100000,
+		.name		= "H3XXX root jffs2",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= 0x00100000,
 #else
-		name:		"H3XXX initrd",
-		size:		0x00100000,
-		offset:		0x00100000,
-	}, {
-		name:		"H3XXX root cramfs",
-		size:		0x00300000,
-		offset:		0x00200000,
-	}, {
-		name:		"H3XXX usr cramfs",
-		size:		0x00800000,
-		offset:		0x00500000,
-	}, {
-		name:		"H3XXX usr local",
-		size:		MTDPART_SIZ_FULL,
-		offset:		0x00d00000,
+		.name		= "H3XXX initrd",
+		.size		= 0x00100000,
+		.offset		= 0x00100000,
+	}, {
+		.name		= "H3XXX root cramfs",
+		.size		= 0x00300000,
+		.offset		= 0x00200000,
+	}, {
+		.name		= "H3XXX usr cramfs",
+		.size		= 0x00800000,
+		.offset		= 0x00500000,
+	}, {
+		.name		= "H3XXX usr local",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= 0x00d00000,
 #endif
 #endif
 	}
@@ -515,16 +515,16 @@
 #ifdef CONFIG_SA1100_HUW_WEBPANEL
 static struct mtd_partition huw_webpanel_partitions[] = {
 	{
-		name:		"Loader",
-		size:		0x00040000,
-		offset:		0,
-	}, {
-		name:		"Sector 1",
-		size:		0x00040000,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "Loader",
+		.size		= 0x00040000,
+		.offset		= 0,
+	}, {
+		.name		= "Sector 1",
+		.size		= 0x00040000,
+		.offset		= MTDPART_OFS_APPEND,
 	}, {
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 #endif
@@ -532,38 +532,38 @@
 #ifdef CONFIG_SA1100_JORNADA720
 static struct mtd_partition jornada720_partitions[] = {
 	{
-		name:		"JORNADA720 boot firmware",
-		size:		0x00040000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
+		.name		= "JORNADA720 boot firmware",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
 	}, {
-		name:		"JORNADA720 kernel",
-		size:		0x000c0000,
-		offset:		0x00040000,
+		.name		= "JORNADA720 kernel",
+		.size		= 0x000c0000,
+		.offset		= 0x00040000,
 	}, {
-		name:		"JORNADA720 params",
-		size:		0x00040000,
-		offset:		0x00100000,
+		.name		= "JORNADA720 params",
+		.size		= 0x00040000,
+		.offset		= 0x00100000,
 	}, {
-		name:		"JORNADA720 initrd",
-		size:		0x00100000,
-		offset:		0x00140000,
+		.name		= "JORNADA720 initrd",
+		.size		= 0x00100000,
+		.offset		= 0x00140000,
 	}, {
-		name:		"JORNADA720 root cramfs",
-		size:		0x00300000,
-		offset:		0x00240000,
+		.name		= "JORNADA720 root cramfs",
+		.size		= 0x00300000,
+		.offset		= 0x00240000,
 	}, {
-		name:		"JORNADA720 usr cramfs",
-		size:		0x00800000,
-		offset:		0x00540000,
+		.name		= "JORNADA720 usr cramfs",
+		.size		= 0x00800000,
+		.offset		= 0x00540000,
 	}, {
-		name:		"JORNADA720 usr local",
-		size:		0  /* will expand to the end of the flash */
-		offset:		0x00d00000,
+		.name		= "JORNADA720 usr local",
+		.size		= 0,  /* will expand to the end of the flash */
+		.offset		= 0x00d00000,
 	}
 };
 
-static void jornada720_set_vpp(int vpp)
+static void jornada720_set_vpp(struct map_info *map, int vpp)
 {
 	if (vpp)
 		PPSR |= 0x80;
@@ -578,22 +578,22 @@
 #ifdef CONFIG_SA1100_PANGOLIN
 static struct mtd_partition pangolin_partitions[] = {
 	{
-		name:		"boot firmware",
-		size:		0x00080000,
-		offset:		0x00000000,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"kernel",
-		size:		0x00100000,
-		offset:		0x00080000,
-	}, {
-		name:		"initrd",
-		size:		0x00280000,
-		offset:		0x00180000,
-	}, {
-		name:		"initrd-test",
-		size:		0x03C00000,
-		offset:		0x00400000,
+		.name		= "boot firmware",
+		.size		= 0x00080000,
+		.offset		= 0x00000000,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "kernel",
+		.size		= 0x00100000,
+		.offset		= 0x00080000,
+	}, {
+		.name		= "initrd",
+		.size		= 0x00280000,
+		.offset		= 0x00180000,
+	}, {
+		.name		= "initrd-test",
+		.size		= 0x03C00000,
+		.offset		= 0x00400000,
 	}
 };
 #endif
@@ -602,22 +602,22 @@
 /* erase size is 0x40000 == 256k partitions have to have this boundary */
 static struct mtd_partition system3_partitions[] = {
 	{
-		name:		"BLOB",
-		size:		0x00040000,
-		offset:		0x00000000,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"config",
-		size:		0x00040000,
-		offset:		MTDPART_OFS_APPEND,
-	}, {
-		name:		"kernel",
-		size:		0x00100000,
-		offset:		MTDPART_OFS_APPEND,
-	}, {
-		name:		"root",
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "BLOB",
+		.size		= 0x00040000,
+		.offset		= 0x00000000,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "config",
+		.size		= 0x00040000,
+		.offset		= MTDPART_OFS_APPEND,
+	}, {
+		.name		= "kernel",
+		.size		= 0x00100000,
+		.offset		= MTDPART_OFS_APPEND,
+	}, {
+		.name		= "root",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 #endif
@@ -625,19 +625,19 @@
 #ifdef CONFIG_SA1100_SHANNON
 static struct mtd_partition shannon_partitions[] = {
 	{
-		name: "BLOB boot loader",
-		offset: 0,
-		size: 0x20000
+		.name		= "BLOB boot loader",
+		.offset		= 0,
+		.size		= 0x20000
 	},
 	{
-		name: "kernel",
-		offset: MTDPART_OFS_APPEND,
-		size: 0xe0000
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 0xe0000
 	},
 	{ 
-		name: "initrd",
-		offset: MTDPART_OFS_APPEND,	
-		size: MTDPART_SIZ_FULL
+		.name		= "initrd",
+		.offset		= MTDPART_OFS_APPEND,	
+		.size		= MTDPART_SIZ_FULL
 	}
 };
 
@@ -646,17 +646,17 @@
 #ifdef CONFIG_SA1100_SHERMAN
 static struct mtd_partition sherman_partitions[] = {
 	{
-		size:		0x50000,
-		offset:		0,
+		.size		= 0x50000,
+		.offset		= 0,
 	}, {
-		size:		0x70000,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= 0x70000,
+		.offset		= MTDPART_OFS_APPEND,
 	}, {
-		size:		0x600000,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= 0x600000,
+		.offset		= MTDPART_OFS_APPEND,
 	}, {
-		size:		0xA0000,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= 0xA0000,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 #endif
@@ -664,35 +664,35 @@
 #ifdef CONFIG_SA1100_SIMPAD
 static struct mtd_partition simpad_partitions[] = {
 	{
-		name:		"SIMpad boot firmware",
-		size:		0x00080000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"SIMpad kernel",
-		size:		0x00100000,
-		offset:		0x00080000,
+		.name		= "SIMpad boot firmware",
+		.size		= 0x00080000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "SIMpad kernel",
+		.size		= 0x00100000,
+		.offset		= 0x00080000,
 	}, {
 #ifdef CONFIG_JFFS2_FS
-		name:		"SIMpad root jffs2",
-		size:		MTDPART_SIZ_FULL,
-		offset:		0x00180000,
+		.name		= "SIMpad root jffs2",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= 0x00180000,
 #else
-		name:		"SIMpad initrd",
-		size:		0x00300000,
-		offset:		0x00180000,
-	}, {
-		name:		"SIMpad root cramfs",
-		size:		0x00300000,
-		offset:		0x00480000,
-	}, {
-		name:		"SIMpad usr cramfs",
-		size:		0x005c0000,
-		offset:		0x00780000,
-	}, {
-		name:		"SIMpad usr local",
-		size:		MTDPART_SIZ_FULL,
-		offset:		0x00d40000,
+		.name		= "SIMpad initrd",
+		.size		= 0x00300000,
+		.offset		= 0x00180000,
+	}, {
+		.name		= "SIMpad root cramfs",
+		.size		= 0x00300000,
+		.offset		= 0x00480000,
+	}, {
+		.name		= "SIMpad usr cramfs",
+		.size		= 0x005c0000,
+		.offset		= 0x00780000,
+	}, {
+		.name		= "SIMpad usr local",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= 0x00d40000,
 #endif
 	}
 };
@@ -701,39 +701,39 @@
 #ifdef CONFIG_SA1100_STORK
 static struct mtd_partition stork_partitions[] = {
 	{
-		name:		"STORK boot firmware",
-		size:		0x00040000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"STORK params",
-		size:		0x00040000,
-		offset:		0x00040000,
-	}, {
-		name:		"STORK kernel",
-		size:		0x00100000,
-		offset:		0x00080000,
+		.name		= "STORK boot firmware",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "STORK params",
+		.size		= 0x00040000,
+		.offset		= 0x00040000,
+	}, {
+		.name		= "STORK kernel",
+		.size		= 0x00100000,
+		.offset		= 0x00080000,
 	}, {
 #ifdef CONFIG_JFFS2_FS
-		name:		"STORK root jffs2",
-		offset:		0x00180000,
-		size:		MTDPART_SIZ_FULL,
+		.name		= "STORK root jffs2",
+		.offset		= 0x00180000,
+		.size		= MTDPART_SIZ_FULL,
 #else
-		name:		"STORK initrd",
-		size:		0x00100000,
-		offset:		0x00180000,
-	}, {
-		name:		"STORK root cramfs",
-		size:		0x00300000,
-		offset:		0x00280000,
-	}, {
-		name:		"STORK usr cramfs",
-		size:		0x00800000,
-		offset:		0x00580000,
-	}, {
-		name:		"STORK usr local",
-		offset:		0x00d80000,
-		size:		MTDPART_SIZ_FULL,
+		.name		= "STORK initrd",
+		.size		= 0x00100000,
+		.offset		= 0x00180000,
+	}, {
+		.name		= "STORK root cramfs",
+		.size		= 0x00300000,
+		.offset		= 0x00280000,
+	}, {
+		.name		= "STORK usr cramfs",
+		.size		= 0x00800000,
+		.offset		= 0x00580000,
+	}, {
+		.name		= "STORK usr local",
+		.offset		= 0x00d80000,
+		.size		= MTDPART_SIZ_FULL,
 #endif
 	}
 };
@@ -742,16 +742,16 @@
 #ifdef CONFIG_SA1100_TRIZEPS
 static struct mtd_partition trizeps_partitions[] = {
 	{
-		name:		"Bootloader & the kernel",
-		size:		0x00200000,
-		offset:		0,
-	}, {
-		name:		"Data",
-		size:		0x00400000,
-		offset:		MTDPART_OFS_APPEND,
+		.name		= "Bootloader & the kernel",
+		.size		= 0x00200000,
+		.offset		= 0,
+	}, {
+		.name		= "Data",
+		.size		= 0x00400000,
+		.offset		= MTDPART_OFS_APPEND,
 	}, {
-		size:		MTDPART_SIZ_FULL,
-		offset:		MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
 	}
 };
 #endif
@@ -759,22 +759,22 @@
 #ifdef CONFIG_SA1100_YOPY
 static struct mtd_partition yopy_partitions[] = {
 	{
-		name:		"boot firmware",
-		size:		0x00040000,
-		offset:		0x00000000,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"kernel",
-		size:		0x00080000,
-		offset:		0x00080000,
-	}, {
-		name:		"initrd",
-		size:		0x00300000,
-		offset:		0x00100000,
-	}, {
-		name:		"root",
-		size:		0x01000000,
-		offset:		0x00400000,
+		.name		= "boot firmware",
+		.size		= 0x00040000,
+		.offset		= 0x00000000,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "kernel",
+		.size		= 0x00080000,
+		.offset		= 0x00080000,
+	}, {
+		.name		= "initrd",
+		.size		= 0x00300000,
+		.offset		= 0x00100000,
+	}, {
+		.name		= "root",
+		.size		= 0x01000000,
+		.offset		= 0x00400000,
 	}
 };
 #endif
diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c
--- a/drivers/net/3c501.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/3c501.c	Mon Jan 13 10:18:05 2003
@@ -36,6 +36,10 @@
 
     Check up pass for 2.5. Nothing significant changed
     		20021009 Alan Cox <alan@redhat.com>
+
+    Fixed zero fill corner case 
+    		20030104 Alan Cox <alan@redhat.com>
+    		
     		
    For the avoidance of doubt the "preferred form" of this code is one which
    is in an open non patent encumbered format. Where cryptographic key signing
@@ -421,8 +425,15 @@
 
 	do
 	{
-		int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
+		int len = skb->len;
+		int pad = 0;
+		int gp_start;
 		unsigned char *buf = skb->data;
+		
+		if (len < ETH_ZLEN)
+			pad = ETH_ZLEN - len;
+			
+		gp_start = 0x800 - ( len + pad );
 
 		lp->tx_pkt_start = gp_start;
     		lp->collisions = 0;
@@ -450,7 +461,11 @@
 		
 		outw(0x00, RX_BUF_CLR);		/* Set rx packet area to 0. */
 		outw(gp_start, GP_LOW);		/* aim - packet will be loaded into buffer start */
-		outsb(DATAPORT,buf,skb->len);	/* load buffer (usual thing each byte increments the pointer) */
+		outsb(DATAPORT,buf,len);	/* load buffer (usual thing each byte increments the pointer) */
+		if (pad) {
+			while(pad--)		/* Zero fill buffer tail */
+				outb(0, DATAPORT);
+		}
 		outw(gp_start, GP_LOW);		/* the board reuses the same register */
 	
 		if(lp->loading != 2)
diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c
--- a/drivers/net/3c505.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/3c505.c	Mon Jan 13 10:18:07 2003
@@ -1037,8 +1037,9 @@
 	adapter->current_dma.direction = 1;
 	adapter->current_dma.start_time = jiffies;
 
-	if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS) {
+	if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) {
 		memcpy(adapter->dma_buffer, skb->data, nlen);
+		memset(adapter->dma_buffer+skb->len, 0, nlen-skb->len);
 		target = isa_virt_to_bus(adapter->dma_buffer);
 	}
 	else {
diff -Nru a/drivers/net/3c507.c b/drivers/net/3c507.c
--- a/drivers/net/3c507.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/3c507.c	Mon Jan 13 10:18:07 2003
@@ -297,7 +297,7 @@
 static struct net_device_stats *el16_get_stats(struct net_device *dev);
 static void el16_tx_timeout (struct net_device *dev);
 
-static void hardware_send_packet(struct net_device *dev, void *buf, short length);
+static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad);
 static void init_82586_mem(struct net_device *dev);
 static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
@@ -499,7 +499,7 @@
 	/* Disable the 82586's input to the interrupt line. */
 	outb (0x80, ioaddr + MISC_CTRL);
 
-	hardware_send_packet (dev, buf, length);
+	hardware_send_packet (dev, buf, skb->len, length - skb->len);
 
 	dev->trans_start = jiffies;
 	/* Enable the 82586 interrupt input. */
@@ -752,12 +752,13 @@
 	return;
 }
 
-static void hardware_send_packet(struct net_device *dev, void *buf, short length)
+static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	short ioaddr = dev->base_addr;
 	ushort tx_block = lp->tx_head;
 	unsigned long write_ptr = dev->mem_start + tx_block;
+	static char padding[ETH_ZLEN];
 
 	/* Set the write pointer to the Tx block, and put out the header. */
 	isa_writew(0x0000,write_ptr);			/* Tx status */
@@ -766,7 +767,7 @@
 	isa_writew(tx_block+8,write_ptr+=2);			/* Data Buffer offset. */
 
 	/* Output the data buffer descriptor. */
-	isa_writew(length | 0x8000,write_ptr+=2);		/* Byte count parameter. */
+	isa_writew((pad + length) | 0x8000,write_ptr+=2);		/* Byte count parameter. */
 	isa_writew(-1,write_ptr+=2);			/* No next data buffer. */
 	isa_writew(tx_block+22+SCB_BASE,write_ptr+=2);	/* Buffer follows the NoOp command. */
 	isa_writew(0x0000,write_ptr+=2);			/* Buffer address high bits (always zero). */
@@ -778,6 +779,8 @@
 
 	/* Output the packet at the write pointer. */
 	isa_memcpy_toio(write_ptr+2, buf, length);
+	if (pad)
+		isa_memcpy_toio(write_ptr+length+2, padding, pad);
 
 	/* Set the old command link pointing to this send packet. */
 	isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link);
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/3c509.c	Mon Jan 13 10:18:05 2003
@@ -167,6 +167,9 @@
 #ifdef CONFIG_PM
 	struct pm_dev *pmdev;
 #endif
+#ifdef __ISAPNP__
+	struct pnp_dev *pnpdev;
+#endif
 };
 static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new sound cards.*/
 static struct net_device *el3_root_dev;
@@ -247,6 +250,7 @@
 	int mca_slot = -1;
 #ifdef __ISAPNP__
 	static int pnp_cards;
+	struct pnp_dev *idev = NULL;
 #endif /* __ISAPNP__ */
 
 	if (dev) SET_MODULE_OWNER(dev);
@@ -356,23 +360,26 @@
 		goto no_pnp;
 
 	for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) {
-		struct pci_dev *idev = NULL;
 		int j;
-		while ((idev = isapnp_find_dev(NULL,
-						el3_isapnp_adapters[i].vendor,
-						el3_isapnp_adapters[i].function,
-						idev))) {
-			idev->prepare(idev);
-			/* Deactivation is needed if the driver was called
-			   with "nopnp=1" before, does not harm if not. */
-			idev->deactivate(idev);
-			idev->activate(idev);
-			if (!idev->resource[0].start || check_region(idev->resource[0].start, EL3_IO_EXTENT))
+		while ((idev = pnp_find_dev(NULL,
+					    el3_isapnp_adapters[i].vendor,
+					    el3_isapnp_adapters[i].function,
+					    idev))) {
+			if (pnp_device_attach(idev) < 0)
 				continue;
-			ioaddr = idev->resource[0].start;
-			if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP"))
+			if (pnp_activate_dev(idev, NULL) < 0) {
+			      __again:
+			      	pnp_device_detach(idev);
+			      	continue;
+			}
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
+				goto __again;
+			ioaddr = pnp_port_start(idev, 0);
+			if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP")) {
+				pnp_device_detach(idev);
 				return -EBUSY;
-			irq = idev->irq_resource[0].start;
+			}
+			irq = pnp_irq(idev, 0);
 			if (el3_debug > 3)
 				printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n",
 					(char*) el3_isapnp_adapters[i].driver_data, ioaddr, irq);
@@ -531,6 +538,9 @@
 	memset(dev->priv, 0, sizeof(struct el3_private));
 	
 	lp = dev->priv;
+#ifdef __ISAPNP__
+	lp->pnpdev = idev;
+#endif
 	lp->mca_slot = mca_slot;
 	lp->next_dev = el3_root_dev;
 	spin_lock_init(&lp->lock);
@@ -1466,6 +1476,10 @@
 		next_dev = lp->next_dev;
 		unregister_netdev(el3_root_dev);
 		release_region(el3_root_dev->base_addr, EL3_IO_EXTENT);
+#ifdef __ISAPNP__
+		if (lp->pnpdev)
+			pnp_device_detach(lp->pnpdev);
+#endif
 		kfree(el3_root_dev);
 		el3_root_dev = next_dev;
 	}
diff -Nru a/drivers/net/3c515.c b/drivers/net/3c515.c
--- a/drivers/net/3c515.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/3c515.c	Mon Jan 13 10:18:05 2003
@@ -460,33 +460,34 @@
 	if(nopnp == 1)
 		goto no_pnp;
 	for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) {
-		struct pci_dev *idev = NULL;
+		struct pnp_dev *idev = NULL;
 		int irq;
-		while((idev = isapnp_find_dev(NULL,
-						corkscrew_isapnp_adapters[i].vendor,
-						corkscrew_isapnp_adapters[i].function,
-						idev))) {
+		while((idev = pnp_find_dev(NULL,
+					   corkscrew_isapnp_adapters[i].vendor,
+					   corkscrew_isapnp_adapters[i].function,
+					   idev))) {
 
-			if(idev->active) idev->deactivate(idev);
-
-			if(idev->prepare(idev)<0)
-				continue;
-			if (!(idev->resource[0].flags & IORESOURCE_IO))
+			if (pnp_device_attach(idev) < 0)
 				continue;
-			if(idev->activate(idev)<0) {
-				printk("isapnp configure failed (out of resources?)\n");
+			if (pnp_activate_dev(idev, NULL) < 0) {
+				printk("pnp activate failed (out of resources?)\n");
+				pnp_device_detach(idev);
 				return -ENOMEM;
 			}
-			if (!idev->resource[0].start || check_region(idev->resource[0].start,16))
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
+				pnp_device_detach(idev);
 				continue;
-			ioaddr = idev->resource[0].start;
-			irq = idev->irq_resource[0].start;
+			}
+			ioaddr = pnp_port_start(idev, 0);
+			irq = pnp_irq(idev, 0);
 			if(corkscrew_debug)
 				printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n",
 					(char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
 					
-			if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
+			if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) {
+				pnp_device_detach(idev);
 				continue;
+			}
 			/* Verify by reading the device ID from the EEPROM. */
 			{
 				int timer;
@@ -498,8 +499,10 @@
 				    		== 0)
 							break;
 				}
-				if (inw(ioaddr + Wn0EepromData) != 0x6d50)
+				if (inw(ioaddr + Wn0EepromData) != 0x6d50) {
+					pnp_device_detach(idev);
 					continue;
+				}
 			}
 			printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
 		     		inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c
--- a/drivers/net/3c523.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/3c523.c	Mon Jan 13 10:18:06 2003
@@ -1120,8 +1120,11 @@
 
 	netif_stop_queue(dev);
 
-	memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
 	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+	
+	if (len != skb->len)
+		memset((char *) p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
+	memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
 
 #if (NUM_XMIT_BUFFS == 1)
 #ifdef NO_NOPCOMMANDS
diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c
--- a/drivers/net/3c527.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/3c527.c	Mon Jan 13 10:18:06 2003
@@ -1084,6 +1084,11 @@
 	/* We will need this to flush the buffer out */
 	lp->tx_ring[lp->tx_ring_head].skb=skb;
    	   
+   	if (skb->len < ETH_ZLEN) {
+   		skb = skb_padto(skb, ETH_ZLEN);
+   		if (skb == NULL)
+   			goto out;
+   	}
 	np->length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; 
 			
 	np->data	= isa_virt_to_bus(skb->data);
@@ -1092,7 +1097,7 @@
 	wmb();
 		
 	p->control     &= ~CONTROL_EOL;     /* Clear EOL on p */ 
-	
+out:	
 	restore_flags(flags);
 
 	netif_wake_queue(dev);
diff -Nru a/drivers/net/7990.c b/drivers/net/7990.c
--- a/drivers/net/7990.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/7990.c	Mon Jan 13 10:18:06 2003
@@ -528,6 +528,8 @@
         ib->btx_ring [entry].length = (-len) | 0xf000;
         ib->btx_ring [entry].misc = 0;
     
+    	if (skb->len < ETH_ZLEN)
+    		memset((char *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
         memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen);
     
         /* Now, give the packet to the lance */
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	Mon Jan 13 10:18:04 2003
+++ b/drivers/net/8139too.c	Mon Jan 13 10:18:04 2003
@@ -1686,6 +1686,8 @@
 	entry = tp->cur_tx % NUM_TX_DESC;
 
 	if (likely(len < TX_BUF_SIZE)) {
+		if (len < ETH_ZLEN)
+			memset(tp->tx_buf[entry], 0, ETH_ZLEN);
 		skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
 		dev_kfree_skb(skb);
 	} else {
diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c
--- a/drivers/net/82596.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/82596.c	Mon Jan 13 10:18:06 2003
@@ -1063,12 +1063,18 @@
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	struct tx_cmd *tx_cmd;
 	struct i596_tbd *tbd;
-	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	short length = skb->len;
 	dev->trans_start = jiffies;
 
 	DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%x) called\n", dev->name,
 				skb->len, (unsigned int)skb->data));
 
+	if (skb->len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
 	netif_stop_queue(dev);
 
 	tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
diff -Nru a/drivers/net/8390.c b/drivers/net/8390.c
--- a/drivers/net/8390.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/8390.c	Mon Jan 13 10:18:05 2003
@@ -270,6 +270,7 @@
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
 	int length, send_length, output_page;
 	unsigned long flags;
+	char scratch[ETH_ZLEN];
 
 	length = skb->len;
 
@@ -340,8 +341,15 @@
 	 * isn't already sending. If it is busy, the interrupt handler will
 	 * trigger the send later, upon receiving a Tx done interrupt.
 	 */
-
-	ei_block_output(dev, length, skb->data, output_page);
+	 
+	if (length == send_length)
+		ei_block_output(dev, length, skb->data, output_page);
+	else {
+		memset(scratch, 0, ETH_ZLEN);
+		memcpy(scratch, skb->data, skb->len);
+		ei_block_output(dev, ETH_ZLEN, scratch, output_page);
+	}
+		
 	if (! ei_local->txing) 
 	{
 		ei_local->txing = 1;
@@ -373,7 +381,13 @@
 	 * reasonable hardware if you only use one Tx buffer.
 	 */
 
-	ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
+	if (length == send_length)
+		ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
+	else {
+		memset(scratch, 0, ETH_ZLEN);
+		memcpy(scratch, skb->data, skb->len);
+		ei_block_output(dev, ETH_ZLEN, scratch, ei_local->tx_start_page);
+	}
 	ei_local->txing = 1;
 	NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
 	dev->trans_start = jiffies;
diff -Nru a/drivers/net/a2065.c b/drivers/net/a2065.c
--- a/drivers/net/a2065.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/a2065.c	Mon Jan 13 10:18:06 2003
@@ -570,6 +570,14 @@
 	unsigned long flags;
 
 	skblen = skb->len;
+	len = skblen;
+	
+	if (len < ETH_ZLEN) {
+		len = ETH_ZLEN;
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+	}
 
 	local_irq_save(flags);
 
@@ -590,7 +598,6 @@
 		}
 	}
 #endif
-	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
 	entry = lp->tx_new & lp->tx_ring_mod_mask;
 	ib->btx_ring [entry].length = (-len) | 0xf000;
 	ib->btx_ring [entry].misc = 0;
diff -Nru a/drivers/net/aironet4500_card.c b/drivers/net/aironet4500_card.c
--- a/drivers/net/aironet4500_card.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/aironet4500_card.c	Mon Jan 13 10:18:06 2003
@@ -273,16 +273,17 @@
 #include <linux/isapnp.h>
 #define AIRONET4X00_IO_SIZE 	0x40
 
-#define isapnp_logdev pci_dev
-#define isapnp_dev    pci_bus
-#define isapnp_find_device isapnp_find_card
-#define isapnp_find_logdev isapnp_find_dev
-#define PNP_BUS bus
+#define isapnp_logdev pnp_dev
+#define isapnp_dev    pnp_card
+#define isapnp_find_device pnp_find_card
+#define isapnp_find_logdev pnp_find_dev
+#define PNP_BUS card
 #define PNP_BUS_NUMBER number
-#define PNP_DEV_NUMBER devfn
+#define PNP_DEV_NUMBER number
 
 
 int awc4500_pnp_hw_reset(struct net_device *dev){
+
 	struct isapnp_logdev *logdev;
 
 	DEBUG(0, "awc_pnp_reset \n");
@@ -299,23 +300,16 @@
 		return -1;
 	};
 
-	if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER)<0)
-		printk("isapnp cfg failed at release \n");
-	isapnp_deactivate(logdev->PNP_DEV_NUMBER);
-	isapnp_cfg_end();
+	pnp_disable_dev(logdev);
 
 	udelay(100);
 
-
-	if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) {
+	if (pnp_activate_dev(logdev, NULL) < 0) {
 		printk("%s cfg begin failed in hw_reset for csn %x devnum %x \n",
 				dev->name, logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER);
 		return -EAGAIN;
 	}
 
-	isapnp_activate(logdev->PNP_DEV_NUMBER);	/* activate device */
-	isapnp_cfg_end();
-
 	return 0;
 }
 
@@ -341,32 +335,33 @@
 		isa_index++;
 
 		logdev = isapnp_find_logdev(pnp_dev, ISAPNP_VENDOR('A','W','L'),
-				    ISAPNP_FUNCTION(1),
-				    0);
+					    ISAPNP_FUNCTION(1),
+					    0);
 		if (!logdev){
 			printk("No logical device found on Aironet board \n");
 			return -ENODEV;
 		}
-		if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) {
-			printk("cfg begin failed for csn %x devnum %x \n",
+		if (pnp_device_attach(logdev) < 0) {
+			printk("pnp_device_attach failed for csn %x devnum %x \n",
 					logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER);
 			return -EAGAIN;
 		}
-		isapnp_activate(logdev->PNP_DEV_NUMBER);	/* activate device */
-		isapnp_cfg_end();
+		if (pnp_activate_dev(logdev, NULL) < 0) {
+			printk("pnp_activate_dev failed for csn %x devnum %x \n",
+					logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER);
+			pnp_device_detach(logdev);
+			return -EIO;
+		}
 
-		isa_irq_line = logdev->irq;
-		isa_ioaddr = logdev->resource[0].start;
+		isa_irq_line = pnp_irq(logdev, 0);
+		isa_ioaddr = pnp_port_start(logdev, 0);
 		request_region(isa_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr");
 
 		if (!dev) {
 			dev = init_etherdev(NULL, 0);	
 			if (!dev) {
 				release_region(isa_ioaddr, AIRONET4X00_IO_SIZE);
-				isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER,
-						 logdev->PNP_DEV_NUMBER);
-				isapnp_deactivate(logdev->PNP_DEV_NUMBER);
-				isapnp_cfg_end();
+				pnp_device_detach(logdev);
 				return -ENOMEM;
 			}
 		}
diff -Nru a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c
--- a/drivers/net/aironet4500_proc.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/aironet4500_proc.c	Mon Jan 13 10:18:05 2003
@@ -42,7 +42,7 @@
 #define DEV_AWC_INFO 	1
 #define DEV_AWC 	1
 
-spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
 
 struct awc_proc_private{
 	struct ctl_table_header *	sysctl_header;
diff -Nru a/drivers/net/am79c961a.c b/drivers/net/am79c961a.c
--- a/drivers/net/am79c961a.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/am79c961a.c	Mon Jan 13 10:18:07 2003
@@ -407,10 +407,18 @@
 am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
-	unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	unsigned int length = skb->len;
 	unsigned int hdraddr, bufaddr;
 	unsigned int head;
 	unsigned long flags;
+	
+	/* FIXME: I thought the 79c961 could do padding - RMK ??? */
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
 
 	head = priv->txhead;
 	hdraddr = priv->txhdr + (head << 3);
diff -Nru a/drivers/net/ariadne.c b/drivers/net/ariadne.c
--- a/drivers/net/ariadne.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/ariadne.c	Mon Jan 13 10:18:06 2003
@@ -574,6 +574,7 @@
     volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
     int entry;
     unsigned long flags;
+    int len = skb->len;
 
 #if 0
     if (ariadne_debug > 3) {
@@ -584,6 +585,15 @@
     }
 #endif
 
+    /* FIXME: is the 79C960 new enough to do its own padding right ? */
+    if (skb->len < ETH_ZLEN)
+    {
+    	skb = skb_padto(skb, ETH_ZLEN);
+    	if (skb == NULL)
+    	    return 0;
+    	len = ETH_ZLEN;
+    }
+
     /* Fill in a Tx ring entry */
 
 #if 0
@@ -613,8 +623,7 @@
 
     priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
     priv->tx_ring[entry]->TMD3 = 0x0000;
-    memcpyw(priv->tx_buff[entry], (u_short *)skb->data,
-	    skb->len <= ETH_ZLEN ? ETH_ZLEN : skb->len);
+    memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
 
 #if 0
     {
diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c
--- a/drivers/net/at1700.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/at1700.c	Mon Jan 13 10:18:05 2003
@@ -572,7 +572,9 @@
 	struct net_local *lp = (struct net_local *) dev->priv;
 	int ioaddr = dev->base_addr;
 	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	short len = skb->len;
 	unsigned char *buf = skb->data;
+	static u8 pad[ETH_ZLEN];
 
 	netif_stop_queue (dev);
 
@@ -584,7 +586,16 @@
 	lp->tx_queue_ready = 0;
 	{
 		outw (length, ioaddr + DATAPORT);
-		outsw (ioaddr + DATAPORT, buf, (length + 1) >> 1);
+		/* Packet data */
+		outsw (ioaddr + DATAPORT, buf, len >> 1);
+		/* Check for dribble byte */
+		if (len & 1) {
+			outw(skb->data[skb->len-1], ioaddr + DATAPORT);
+			len++;
+		}
+		/* Check for packet padding */
+		if (length != skb->len)
+			outsw(ioaddr + DATAPORT, pad, (length - len + 1) >> 1);
 
 		lp->tx_queue++;
 		lp->tx_queue_len += length + 2;
diff -Nru a/drivers/net/atarilance.c b/drivers/net/atarilance.c
--- a/drivers/net/atarilance.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/atarilance.c	Mon Jan 13 10:18:05 2003
@@ -787,6 +787,21 @@
 	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
 				  dev->name, DREG ));
 
+
+	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
+	len = skb->len;
+	if (len < ETH_ZLEN)
+		len = ETH_ZLEN;
+	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
+	else if (lp->cardtype == PAM_CARD && (len & 1))
+		++len;
+		
+	if (len > skb->len) {
+		skb = skb_padto(skb, len);
+		if (skb == NULL)
+			return 0;
+	}
+		
 	netif_stop_queue (dev);
 
 	/* Fill in a Tx ring entry */
@@ -816,11 +831,6 @@
 	 * last.
 	 */
 
-	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
-	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
-	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
-	if (lp->cardtype == PAM_CARD && (len & 1))
-		++len;
 
 	head->length = -len;
 	head->misc = 0;
diff -Nru a/drivers/net/atp.c b/drivers/net/atp.c
--- a/drivers/net/atp.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/atp.c	Mon Jan 13 10:18:07 2003
@@ -200,7 +200,7 @@
 static unsigned short eeprom_op(long ioaddr, unsigned int cmd);
 static int net_open(struct net_device *dev);
 static void hardware_init(struct net_device *dev);
-static void write_packet(long ioaddr, int length, unsigned char *packet, int mode);
+static void write_packet(long ioaddr, int length, unsigned char *packet, int pad, int mode);
 static void trigger_send(long ioaddr, int length);
 static int	atp_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void atp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -499,15 +499,23 @@
 	write_reg(ioaddr, CMR1, CMR1_Xmit);
 }
 
-static void write_packet(long ioaddr, int length, unsigned char *packet, int data_mode)
+static void write_packet(long ioaddr, int length, unsigned char *packet, int pad_len, int data_mode)
 {
-    length = (length + 1) & ~1;		/* Round up to word length. */
+    if (length & 1)
+    {
+    	length++;
+    	pad_len++;
+    }
+
     outb(EOC+MAR, ioaddr + PAR_DATA);
     if ((data_mode & 1) == 0) {
 		/* Write the packet out, starting with the write addr. */
 		outb(WrAddr+MAR, ioaddr + PAR_DATA);
 		do {
 			write_byte_mode0(ioaddr, *packet++);
+		} while (--length > pad_len) ;
+		do {
+			write_byte_mode0(ioaddr, 0);
 		} while (--length > 0) ;
     } else {
 		/* Write the packet out in slow mode. */
@@ -521,8 +529,10 @@
 		outbyte >>= 4;
 		outb(outbyte & 0x0f, ioaddr + PAR_DATA);
 		outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
-		while (--length > 0)
+		while (--length > pad_len)
 			write_byte_mode1(ioaddr, *packet++);
+		while (--length > 0)
+			write_byte_mode1(ioaddr, 0);
     }
     /* Terminate the Tx frame.  End of write: ECB. */
     outb(0xff, ioaddr + PAR_DATA);
@@ -564,7 +574,7 @@
 	write_reg_high(ioaddr, IMR, 0);
 	spin_unlock_irqrestore(&lp->lock, flags);
 
-	write_packet(ioaddr, length, skb->data, dev->if_port);
+	write_packet(ioaddr, length, skb->data, length-skb->len, dev->if_port);
 
 	lp->pac_cnt_in_tx_buf++;
 	if (lp->tx_unit_busy == 0) {
diff -Nru a/drivers/net/bagetlance.c b/drivers/net/bagetlance.c
--- a/drivers/net/bagetlance.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/bagetlance.c	Mon Jan 13 10:18:05 2003
@@ -830,6 +830,18 @@
 	struct lance_tx_head *head;
 	unsigned long flags;
 
+	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
+	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
+	if (lp->cardtype == PAM_CARD && (len & 1))
+		++len;
+
+	if (len > skb->len) {
+		skb = skb_padto(skb, len);
+		if (skb == NULL)
+			return 0;
+	}	
+
 	/* Transmitter timeout, serious problems. */
 	if (dev->tbusy) {
 		int tickssofar = jiffies - dev->trans_start;
@@ -915,12 +927,6 @@
 	/* Caution: the write order is important here, set the "ownership" bits
 	 * last.
 	 */
-
-	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
-	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
-	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
-	if (lp->cardtype == PAM_CARD && (len & 1))
-		++len;
 
 	head->length = -len;
 	head->misc = 0;
diff -Nru a/drivers/net/de600.c b/drivers/net/de600.c
--- a/drivers/net/de600.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/de600.c	Mon Jan 13 10:18:07 2003
@@ -187,6 +187,7 @@
 	int	len;
 	int	tickssofar;
 	u8	*buffer = skb->data;
+	int	i;
 
 	if (free_tx_pages <= 0) {	/* Do timeouts, to avoid hangs. */
 		tickssofar = jiffies - dev->trans_start;
@@ -228,8 +229,10 @@
 	}
 
 	de600_setup_address(transmit_from, RW_ADDR);
-	for ( ; len > 0; --len, ++buffer)
+	for (i = 0;  i < skb->len ; ++i, ++buffer)
 		de600_put_byte(*buffer);
+	for (; i < len; ++i)
+		de600_put_byte(0);
 
 	if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
 		dev->trans_start = jiffies;
diff -Nru a/drivers/net/de620.c b/drivers/net/de620.c
--- a/drivers/net/de620.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/de620.c	Mon Jan 13 10:18:06 2003
@@ -315,7 +315,7 @@
 }
 
 static inline void
-de620_write_block(struct net_device *dev, byte *buffer, int count)
+de620_write_block(struct net_device *dev, byte *buffer, int count, int pad)
 {
 #ifndef LOWSPEED
 	byte uflip = NIC_Cmd ^ (DS0 | DS1);
@@ -334,6 +334,9 @@
 	for ( ; count > 0; --count, ++buffer) {
 		de620_put_byte(dev,*buffer);
 	}
+	for ( count = pad ; count > 0; --count, ++buffer) {
+		de620_put_byte(dev, 0);
+	}
 	de620_send_command(dev,W_DUMMY);
 #ifdef COUNT_LOOPS
 	/* trial debug output: loops per byte in de620_ready() */
@@ -571,7 +574,7 @@
 		spin_unlock_irqrestore(&de620_lock, flags);
 		return 1;
 	}
-	de620_write_block(dev, buffer, len);
+	de620_write_block(dev, buffer, skb->len, len-skb->len);
 
 	dev->trans_start = jiffies;
 	if(!(using_txbuf == (TXBF0 | TXBF1)))
diff -Nru a/drivers/net/declance.c b/drivers/net/declance.c
--- a/drivers/net/declance.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/declance.c	Mon Jan 13 10:18:06 2003
@@ -869,7 +869,14 @@
 
 	skblen = skb->len;
 
-	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+	len = skblen;
+	
+	if (len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		len = ETH_ZLEN;
+	}
 
 	lp->stats.tx_bytes += len;
 
diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c
--- a/drivers/net/depca.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/depca.c	Mon Jan 13 10:18:06 2003
@@ -862,6 +862,12 @@
 	if (skb->len < 1)
 		goto out;
 
+	if (skb->len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			goto out;
+	}
+	
 	netif_stop_queue(dev);
 
 	if (TX_BUFFS_AVAIL) {	/* Fill in a Tx ring entry */
diff -Nru a/drivers/net/eepro.c b/drivers/net/eepro.c
--- a/drivers/net/eepro.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/eepro.c	Mon Jan 13 10:18:07 2003
@@ -1130,17 +1130,23 @@
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	unsigned long flags;
 	int ioaddr = dev->base_addr;
+	short length = skb->len;
 
 	if (net_debug > 5)
 		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
 
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
 	netif_stop_queue (dev);
 
 	eepro_dis_int(ioaddr);
 	spin_lock_irqsave(&lp->lock, flags);
 
 	{
-		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		unsigned char *buf = skb->data;
 
 		if (hardware_send_packet(dev, buf, length))
diff -Nru a/drivers/net/eexpress.c b/drivers/net/eexpress.c
--- a/drivers/net/eexpress.c	Mon Jan 13 10:18:04 2003
+++ b/drivers/net/eexpress.c	Mon Jan 13 10:18:04 2003
@@ -636,6 +636,7 @@
 static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
+	short length = buf->len;
 #ifdef CONFIG_SMP
 	unsigned long flags;
 #endif
@@ -644,6 +645,13 @@
 	printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
 #endif
 
+	if (buf->len < ETH_ZLEN) {
+		buf = skb_padto(buf, ETH_ZLEN);
+		if (buf == NULL)
+			return 0;
+		length = buf->len;
+	}
+
 	disable_irq(dev->irq);
 
 	/*
@@ -656,8 +664,6 @@
 #endif
   
 	{
-		unsigned short length = (ETH_ZLEN < buf->len) ? buf->len :
-			ETH_ZLEN;
 		unsigned short *data = (unsigned short *)buf->data;
 
 		lp->stats.tx_bytes += length;
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/epic100.c	Mon Jan 13 10:18:06 2003
@@ -974,6 +974,12 @@
 	int entry, free_count;
 	u32 ctrl_word;
 	long flags;
+	
+	if (skb->len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+	}
 
 	/* Caution: the write order is important here, set the field with the
 	   "ownership" bit last. */
diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c
--- a/drivers/net/eth16i.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/eth16i.c	Mon Jan 13 10:18:05 2003
@@ -1052,10 +1052,16 @@
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
 	int status = 0;
-	ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	ushort length = skb->len;
 	unsigned char *buf = skb->data;
 	unsigned long flags;
 
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
 
 	netif_stop_queue(dev);
 		
diff -Nru a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
--- a/drivers/net/fmv18x.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/fmv18x.c	Mon Jan 13 10:18:05 2003
@@ -366,7 +366,7 @@
 {
 	struct net_local *lp = dev->priv;
 	int ioaddr = dev->base_addr;
-	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	short length = skb->len;
 	unsigned char *buf = skb->data;
 	unsigned long flags;
 
@@ -378,6 +378,14 @@
 				dev->name, length);
 		return 1;
 	}
+	
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
+	
 	if (net_debug > 4)
 		printk("%s: Transmitting a packet of length %lu.\n", dev->name,
 			   (unsigned long)skb->len);
diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c
--- a/drivers/net/hp100.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/hp100.c	Mon Jan 13 10:18:05 2003
@@ -1555,6 +1555,12 @@
 
 	if (skb->len <= 0)
 		return 0;
+		
+	if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+	}
 
 	/* Get Tx ring tail pointer */
 	if (lp->txrtail->next == lp->txrhead) {
@@ -2097,6 +2103,7 @@
 	struct hp100_private *lp = (struct hp100_private *) dev->priv;
 
 #ifdef HP100_DEBUG_B
+	int ioaddr = dev->base_addr;
 	hp100_outw(0x4216, TRACE);
 	printk("hp100: %s: misc_interrupt\n", dev->name);
 #endif
@@ -2536,6 +2543,11 @@
 		return HP100_LAN_10;
 
 	if (val_10 & HP100_AUI_ST) {	/* have we BNC or AUI onboard? */
+		/*
+		 * This can be overriden by dos utility, so if this has no effect,
+		 * perhaps you need to download that utility from HP and set card
+		 * back to "auto detect".
+		 */
 		val_10 |= HP100_AUI_SEL | HP100_LOW_TH;
 		hp100_page(MAC_CTRL);
 		hp100_outb(val_10, 10_LAN_CFG_1);
diff -Nru a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
--- a/drivers/net/irda/sa1100_ir.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/irda/sa1100_ir.c	Mon Jan 13 10:18:05 2003
@@ -10,8 +10,7 @@
  *  Infra-red driver for the StrongARM SA1100 embedded microprocessor
  *
  *  Note that we don't have to worry about the SA1111's DMA bugs in here,
- *  so we use the straight forward pci_map_* functions with a null pointer.
- *  IMHO we should really be using our own machine specific set.
+ *  so we use the straight forward dma_map_* functions with a null pointer.
  *
  *  This driver takes one kernel command line parameter, sa1100ir=, with
  *  the following options:
@@ -29,8 +28,8 @@
 #include <linux/rtnetlink.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/wrapper.h>
@@ -57,11 +56,6 @@
 static int tx_lpm;
 static int max_rate = 4000000;
 
-/*
- * Our netdevice.  There is only ever one of these.
- */
-static struct net_device *netdev;
-
 struct sa1100_irda {
 	unsigned char		hscr0;
 	unsigned char		utcr4;
@@ -79,8 +73,8 @@
 	dma_regs_t		*rxdma;
 
 	struct net_device_stats	stats;
+	struct device		*dev;
 	struct irlap_cb		*irlap;
-	struct pm_dev		*pmdev;
 	struct qos_info		qos;
 
 	iobuff_t		tx_buff;
@@ -112,9 +106,9 @@
 	 */
 	skb_reserve(si->rxskb, 1);
 
-	si->rxbuf_dma = pci_map_single(NULL, si->rxskb->data,
+	si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data,
 					HPSIR_MAX_RXLEN,
-					PCI_DMA_FROMDEVICE);
+					DMA_FROM_DEVICE);
 	return 0;
 }
 
@@ -361,11 +355,12 @@
 /*
  * Suspend the IrDA interface.
  */
-static int sa1100_irda_suspend(struct net_device *dev, int state)
+static int sa1100_irda_suspend(struct device *_dev, u32 state, u32 level)
 {
+	struct net_device *dev = dev_get_drvdata(_dev);
 	struct sa1100_irda *si = dev->priv;
 
-	if (si && si->open) {
+	if (si && si->open && level == SUSPEND_DISABLE) {
 		/*
 		 * Stop the transmit queue
 		 */
@@ -381,11 +376,12 @@
 /*
  * Resume the IrDA interface.
  */
-static int sa1100_irda_resume(struct net_device *dev)
+static int sa1100_irda_resume(struct device *_dev, u32 level)
 {
+	struct net_device *dev = dev_get_drvdata(_dev);
 	struct sa1100_irda *si = dev->priv;
 
-	if (si && si->open) {
+	if (si && si->open && level == RESUME_ENABLE) {
 		/*
 		 * If we missed a speed change, initialise at the new speed
 		 * directly.  It is debatable whether this is actually
@@ -410,31 +406,9 @@
 
 	return 0;
 }
-
-static int sa1100_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-	int ret;
-
-	if (!dev->data)
-		return -EINVAL;
-
-	switch (rqst) {
-	case PM_SUSPEND:
-		ret = sa1100_irda_suspend((struct net_device *)dev->data,
-					  (int)data);
-		break;
-
-	case PM_RESUME:
-		ret = sa1100_irda_resume((struct net_device *)dev->data);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
+#else
+#define sa1100_irda_suspend	NULL
+#define sa1100_irda_resume	NULL
 #endif
 
 /*
@@ -555,7 +529,7 @@
 	len = dma_addr - si->rxbuf_dma;
 	if (len > HPSIR_MAX_RXLEN)
 		len = HPSIR_MAX_RXLEN;
-	pci_unmap_single(NULL, si->rxbuf_dma, len, PCI_DMA_FROMDEVICE);
+	dma_unmap_single(si->dev, si->rxbuf_dma, len, DMA_FROM_DEVICE);
 
 	do {
 		/*
@@ -603,9 +577,9 @@
 		/*
 		 * Remap the buffer.
 		 */
-		si->rxbuf_dma = pci_map_single(NULL, si->rxskb->data,
+		si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data,
 						HPSIR_MAX_RXLEN,
-						PCI_DMA_FROMDEVICE);
+						DMA_FROM_DEVICE);
 	}
 }
 
@@ -716,7 +690,7 @@
 	 * Account and free the packet.
 	 */
 	if (skb) {
-		pci_unmap_single(NULL, si->txbuf_dma, skb->len, PCI_DMA_TODEVICE);
+		dma_unmap_single(si->dev, si->txbuf_dma, skb->len, DMA_TO_DEVICE);
 		si->stats.tx_packets ++;
 		si->stats.tx_bytes += skb->len;
 		dev_kfree_skb_irq(skb);
@@ -782,8 +756,8 @@
 		netif_stop_queue(dev);
 
 		si->txskb = skb;
-		si->txbuf_dma = pci_map_single(NULL, skb->data,
-					 skb->len, PCI_DMA_TODEVICE);
+		si->txbuf_dma = dma_map_single(si->dev, skb->data,
+					 skb->len, DMA_TO_DEVICE);
 
 		sa1100_start_dma(si->txdma, si->txbuf_dma, skb->len);
 
@@ -931,8 +905,8 @@
 	 * tidy that up cleanly.
 	 */
 	if (si->rxskb) {
-		pci_unmap_single(NULL, si->rxbuf_dma, HPSIR_MAX_RXLEN,
-				 PCI_DMA_FROMDEVICE);
+		dma_unmap_single(si->dev, si->rxbuf_dma, HPSIR_MAX_RXLEN,
+				 DMA_FROM_DEVICE);
 		dev_kfree_skb(si->rxskb);
 		si->rxskb = NULL;
 	}
@@ -972,6 +946,24 @@
 	return io->head ? 0 : -ENOMEM;
 }
 
+static struct device_driver sa1100ir_driver = {
+	.name		= "sa1100ir",
+	.bus		= &system_bus_type,
+	.suspend	= sa1100_irda_suspend,
+	.resume		= sa1100_irda_resume,
+};
+
+static struct sys_device sa1100ir_device = {
+	.name		= "sa1100ir",
+	.id		= 0,
+	.root		= NULL,
+	.dev		= {
+		.name	= "Intel Corporation SA11x0 [IrDA]",
+		.bus_id	= "0",
+		.driver	= &sa1100ir_driver,
+	},
+};
+
 static int sa1100_irda_net_init(struct net_device *dev)
 {
 	struct sa1100_irda *si = dev->priv;
@@ -984,6 +976,8 @@
 
 	memset(si, 0, sizeof(*si));
 
+	si->dev = &sa1100ir_device.dev;
+
 	/*
 	 * Initialise the HP-SIR buffers
 	 */
@@ -1035,15 +1029,6 @@
 	Ser2UTCR4 = si->utcr4;
 	Ser2HSCR0 = HSCR0_UART;
 
-#ifdef CONFIG_PM
-	/*
-	 * Power-Management is optional.
-	 */
-	si->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, sa1100_irda_pmproc);
-	if (si->pmdev)
-		si->pmdev->data = dev;
-#endif
-
 	return 0;
 
 	kfree(si->tx_buff.head);
@@ -1071,15 +1056,12 @@
 	dev->get_stats		= NULL;
 	dev->priv		= NULL;
 
-	pm_unregister(si->pmdev);
-
 	kfree(si->tx_buff.head);
 	kfree(si->rx_buff.head);
 	kfree(si);
 }
 
-static
-int __init sa1100_irda_init(void)
+static int __init sa1100_irda_init(void)
 {
 	struct net_device *dev;
 	int err;
@@ -1102,6 +1084,9 @@
 	if (err)
 		goto err_mem_3;
 
+	driver_register(&sa1100ir_driver);
+	sys_device_register(&sa1100ir_device);
+
 	rtnl_lock();
 	dev = dev_alloc("irda%d", &err);
 	if (dev) {
@@ -1114,11 +1099,14 @@
 		if (err)
 			kfree(dev);
 		else
-			netdev = dev;
+			dev_set_drvdata(&sa1100ir_device.dev, dev);
 	}
 	rtnl_unlock();
 
 	if (err) {
+		sys_device_unregister(&sa1100ir_device);
+		driver_unregister(&sa1100ir_driver);
+
 		release_mem_region(__PREG(Ser2HSCR2), 0x04);
 err_mem_3:
 		release_mem_region(__PREG(Ser2HSCR0), 0x1c);
@@ -1131,14 +1119,16 @@
 
 static void __exit sa1100_irda_exit(void)
 {
-	struct net_device *dev = netdev;
+	struct net_device *dev = dev_get_drvdata(&sa1100ir_device.dev);
 
-	netdev = NULL;
 	if (dev) {
 		rtnl_lock();
 		unregister_netdevice(dev);
 		rtnl_unlock();
 	}
+
+	sys_device_unregister(&sa1100ir_device);
+	driver_unregister(&sa1100ir_driver);
 
 	release_mem_region(__PREG(Ser2HSCR2), 0x04);
 	release_mem_region(__PREG(Ser2HSCR0), 0x1c);
diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c
--- a/drivers/net/lance.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/lance.c	Mon Jan 13 10:18:05 2003
@@ -899,8 +899,14 @@
 
 	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
 	if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) {
-		lp->tx_ring[entry].length =
-			-(ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
+		if (skb->len < ETH_ZLEN) {
+			skb = skb_padto(skb, ETH_ZLEN);
+			if (skb == NULL)
+				goto out;
+			lp->tx_ring[entry].length = -ETH_ZLEN;
+		}
+		else 
+			lp->tx_ring[entry].length = -skb->len;
 	} else
 		lp->tx_ring[entry].length = -skb->len;
 
@@ -933,6 +939,7 @@
 	if ((lp->cur_tx - lp->dirty_tx) >= TX_RING_SIZE)
 		netif_stop_queue(dev);
 
+out:
 	spin_unlock_irqrestore(&lp->devlock, flags);
 	return 0;
 }
diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
--- a/drivers/net/lasi_82596.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/lasi_82596.c	Mon Jan 13 10:18:05 2003
@@ -1080,12 +1080,19 @@
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	struct tx_cmd *tx_cmd;
 	struct i596_tbd *tbd;
-	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	short length = skb->len;
 	dev->trans_start = jiffies;
 
 	DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%p) called\n", dev->name,
 				skb->len, skb->data));
 
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
+	
 	netif_stop_queue(dev);
 
 	tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
diff -Nru a/drivers/net/lp486e.c b/drivers/net/lp486e.c
--- a/drivers/net/lp486e.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/lp486e.c	Mon Jan 13 10:18:05 2003
@@ -885,7 +885,15 @@
 	if (skb->len <= 0)
 		return 0;
 
-	length = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+	length = skb->len;
+	
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
+	
 	dev->trans_start = jiffies;
 
 	tx_cmd = (struct tx_cmd *)
diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c
--- a/drivers/net/ne.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/ne.c	Mon Jan 13 10:18:06 2003
@@ -196,29 +196,32 @@
 	int i;
 
 	for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
-		struct pci_dev *idev = NULL;
+		struct pnp_dev *idev = NULL;
 
-		while ((idev = isapnp_find_dev(NULL,
-					       isapnp_clone_list[i].vendor,
-					       isapnp_clone_list[i].function,
-					       idev))) {
+		while ((idev = pnp_find_dev(NULL,
+					    isapnp_clone_list[i].vendor,
+					    isapnp_clone_list[i].function,
+					    idev))) {
 			/* Avoid already found cards from previous calls */
-			if (idev->prepare(idev))
-				continue;
-			if (idev->activate(idev))
-				continue;
-			/* if no irq, search for next */
-			if (idev->irq_resource[0].start == 0)
+			if (pnp_device_attach(idev) < 0)
 				continue;
+			if (pnp_activate_dev(idev, NULL) < 0) {
+			      __again:
+			      	pnp_device_detach(idev);
+			      	continue;
+			}
+			/* if no io and irq, search for next */
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
+				goto __again;
 			/* found it */
-			dev->base_addr = idev->resource[0].start;
-			dev->irq = idev->irq_resource[0].start;
+			dev->base_addr = pnp_port_start(idev, 0);
+			dev->irq = pnp_irq(idev, 0);
 			printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
 				(char *) isapnp_clone_list[i].driver_data,
-
 				dev->base_addr, dev->irq);
 			if (ne_probe1(dev, dev->base_addr) != 0) {	/* Shouldn't happen. */
 				printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+				pnp_device_detach(idev);
 				return -ENXIO;
 			}
 			ei_status.priv = (unsigned long)idev;
diff -Nru a/drivers/net/ni5010.c b/drivers/net/ni5010.c
--- a/drivers/net/ni5010.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/ni5010.c	Mon Jan 13 10:18:06 2003
@@ -114,7 +114,7 @@
 
 static int	process_xmt_interrupt(struct net_device *dev);
 #define tx_done(dev) 1
-static void	hardware_send_packet(struct net_device *dev, char *buf, int length);
+static void	hardware_send_packet(struct net_device *dev, char *buf, int length, int pad);
 static void 	chipset_init(struct net_device *dev, int startp);
 static void	dump_packet(void *buf, int len);
 static void 	ni5010_show_registers(struct net_device *dev);
@@ -441,7 +441,7 @@
 	 */
 	
 	netif_stop_queue(dev);
-	hardware_send_packet(dev, (unsigned char *)skb->data, length);
+	hardware_send_packet(dev, (unsigned char *)skb->data, skb->len, length-skb->len);
 	dev->trans_start = jiffies;
 	dev_kfree_skb (skb);
 	return 0;
@@ -665,7 +665,7 @@
 	}
 }
 
-static void hardware_send_packet(struct net_device *dev, char *buf, int length)
+static void hardware_send_packet(struct net_device *dev, char *buf, int length, int pad)
 {
 	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
 	int ioaddr = dev->base_addr;
@@ -690,8 +690,8 @@
 	
 	if (NI5010_DEBUG > 3) dump_packet(buf, length);
 
-        buf_offs = NI5010_BUFSIZE - length;
-        lp->o_pkt_size = length;
+        buf_offs = NI5010_BUFSIZE - length - pad;
+        lp->o_pkt_size = length + pad;
 
 	save_flags(flags);	
 	cli();
@@ -702,6 +702,9 @@
 
 	outw(buf_offs, IE_GP); /* Point GP at start of packet */
 	outsb(IE_XBUF, buf, length); /* Put data in buffer */
+	while(pad--)
+		outb(0, IE_XBUF);
+		
 	outw(buf_offs, IE_GP); /* Rewrite where packet starts */
 
 	/* should work without that outb() (Crynwr used it) */
diff -Nru a/drivers/net/ni52.c b/drivers/net/ni52.c
--- a/drivers/net/ni52.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/ni52.c	Mon Jan 13 10:18:06 2003
@@ -1169,7 +1169,11 @@
 #endif
 	{
 		memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
-		len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+		len = skb->len;
+		if (len < ETH_ZLEN) {
+			len = ETH_ZLEN;
+			memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0, len - skb->len);
+		}
 
 #if (NUM_XMIT_BUFFS == 1)
 #	ifdef NO_NOPCOMMANDS
diff -Nru a/drivers/net/ni65.c b/drivers/net/ni65.c
--- a/drivers/net/ni65.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/ni65.c	Mon Jan 13 10:18:05 2003
@@ -1145,6 +1145,8 @@
 
 			memcpy((char *) p->tmdbounce[p->tmdbouncenum] ,(char *)skb->data,
 							 (skb->len > T_BUF_SIZE) ? T_BUF_SIZE : skb->len);
+			if (len > skb->len)
+				memset((char *)p->tmdbounce[p->tmdbouncenum]+skb->len, 0, len-skb->len);
 			dev_kfree_skb (skb);
 
 			save_flags(flags);
diff -Nru a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
--- a/drivers/net/pcmcia/axnet_cs.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/pcmcia/axnet_cs.c	Mon Jan 13 10:18:06 2003
@@ -1216,7 +1216,8 @@
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
 	int length, send_length, output_page;
 	unsigned long flags;
-
+	u8 packet[ETH_ZLEN];
+	
 	netif_stop_queue(dev);
 
 	length = skb->len;
@@ -1241,7 +1242,7 @@
 	ei_local->irqlock = 1;
 
 	send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
-    
+	
 	/*
 	 * We have two Tx slots available for use. Find the first free
 	 * slot, and then perform some sanity checks. With two Tx bufs,
@@ -1286,7 +1287,14 @@
 	 * trigger the send later, upon receiving a Tx done interrupt.
 	 */
 
-	ei_block_output(dev, length, skb->data, output_page);
+	if (length == skb->len)
+		ei_block_output(dev, length, skb->data, output_page);
+	else {
+		memset(packet, 0, ETH_ZLEN);
+		memcpy(packet, skb->data, skb->len);
+		ei_block_output(dev, length, packet, output_page);
+	}
+	
 	if (! ei_local->txing) 
 	{
 		ei_local->txing = 1;
diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
--- a/drivers/net/pcmcia/fmvj18x_cs.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/pcmcia/fmvj18x_cs.c	Mon Jan 13 10:18:06 2003
@@ -951,11 +951,19 @@
 {
     struct local_info_t *lp = (struct local_info_t *)dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
+    short length = skb->len;
+    
+    if (length < ETH_ZLEN)
+    {
+    	skb = skb_padto(skb, ETH_ZLEN);
+    	if (skb == NULL)
+    		return 0;
+    	length = ETH_ZLEN;
+    }
 
     netif_stop_queue(dev);
 
     {
-	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 	unsigned char *buf = skb->data;
 
 	if (length > ETH_FRAME_LEN) {
diff -Nru a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c
--- a/drivers/net/pcmcia/ray_cs.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/pcmcia/ray_cs.c	Mon Jan 13 10:18:05 2003
@@ -1052,7 +1052,7 @@
 {
     ray_dev_t *local = dev->priv;
     dev_link_t *link = local->finder;
-    short length;
+    short length = skb->len;
 
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_dev_start_xmit - device not present\n");
@@ -1068,7 +1068,13 @@
         }
     }
 
-    length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+    if (length < ETH_ZLEN)
+    {
+    	skb = skb_padto(skb, ETH_ZLEN);
+    	if (skb == NULL)
+    		return 0;
+    	length = ETH_ZLEN;
+    }
     switch (ray_hw_xmit( skb->data, length, dev, DATA_TYPE)) {
         case XMIT_NO_CCS:
         case XMIT_NEED_AUTH:
diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
--- a/drivers/net/pcmcia/xirc2ps_cs.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/pcmcia/xirc2ps_cs.c	Mon Jan 13 10:18:05 2003
@@ -1547,7 +1547,6 @@
     DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
 	  skb, dev, pktlen);
 
-    netif_stop_queue(dev);
 
     /* adjust the packet length to min. required
      * and hope that the buffer is large enough
@@ -1557,8 +1556,14 @@
      * pad this in his buffer with random bytes
      */
     if (pktlen < ETH_ZLEN)
+    {
+        skb = skb_padto(skb, ETH_ZLEN);
+        if (skb == NULL)
+        	return 0;
 	pktlen = ETH_ZLEN;
+    }
 
+    netif_stop_queue(dev);
     SelectPage(0);
     PutWord(XIRCREG0_TRS, (u_short)pktlen+2);
     freespace = GetWord(XIRCREG0_TSO);
diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c
--- a/drivers/net/r8169.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/r8169.c	Mon Jan 13 10:18:06 2003
@@ -822,6 +822,12 @@
 	void *ioaddr = tp->mmio_addr;
 	int entry = tp->cur_tx % NUM_TX_DESC;
 
+	if (skb->len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+	}
+	
 	spin_lock_irq(&tp->lock);
 
 	if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
diff -Nru a/drivers/net/sb1000.c b/drivers/net/sb1000.c
--- a/drivers/net/sb1000.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/sb1000.c	Mon Jan 13 10:18:05 2003
@@ -145,7 +145,7 @@
 {
 
 	unsigned short ioaddr[2], irq;
-	struct pci_dev *idev=NULL;
+	struct pnp_dev *idev=NULL;
 	unsigned int serial_number;
 	
 	while(1)
@@ -154,55 +154,58 @@
 		 *	Find the card
 		 */
 		 
-		idev=isapnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'),
+		idev=pnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'),
 			ISAPNP_FUNCTION(0x1000), idev);
 			
 		/*
 		 *	No card
 		 */
 		 
-		if(idev==NULL)
+		if(idev==NULL || idev->card == NULL)
 			return -ENODEV;
 			
 		/*
 		 *	Bring it online
 		 */
 		 
-		idev->prepare(idev);
-		idev->activate(idev);
+		if (pnp_device_attach(idev) < 0)
+			continue;
+		if (pnp_activate_dev(idev, NULL) < 0) {
+		      __again:
+			pnp_device_detach(idev);
+			continue;
+		}
 		
 		/*
 		 *	Ports free ?
 		 */
 		 
-		if(!idev->resource[0].start || check_region(idev->resource[0].start, 16))
-			continue;
-		if(!idev->resource[1].start || check_region(idev->resource[1].start, 16))
-			continue;
+		if(!pnp_port_valid(idev, 0) || !pnp_port_valid(idev, 1) || !pnp_irq_valid(idev, 0))
+			goto __again;
 		
-		serial_number = idev->bus->serial;
+		serial_number = idev->card->serial;
 		
-		ioaddr[0]=idev->resource[0].start;
-		ioaddr[1]=idev->resource[1].start;
+		ioaddr[0]=pnp_port_start(idev, 0);
+		ioaddr[1]=pnp_port_start(idev, 0);
 		
-		irq = idev->irq_resource[0].start;
+		irq = pnp_irq(idev, 0);
 
 		/* check I/O base and IRQ */
 		if (dev->base_addr != 0 && dev->base_addr != ioaddr[0])
-			continue;
+			goto __again;
 		if (dev->mem_start != 0 && dev->mem_start != ioaddr[1])
-			continue;
+			goto __again;
 		if (dev->irq != 0 && dev->irq != irq)
-			continue;
+			goto __again;
 			
 		/*
 		 *	Ok set it up.
 		 */
 		if (!request_region(ioaddr[0], 16, dev->name))
-			continue;
+			goto __again;
 		if (!request_region(ioaddr[1], 16, dev->name)) {
 			release_region(ioaddr[0], 16);
-			continue;
+			goto __again;
 		}
 		 
 		dev->base_addr = ioaddr[0];
@@ -216,8 +219,12 @@
 				dev->mem_start, serial_number, dev->irq);
 
 		dev = init_etherdev(dev, 0);
-		if (!dev)
+		if (!dev) {
+			pnp_device_detach(idev);
+			release_region(ioaddr[1], 16);
+			release_region(ioaddr[0], 16);
 			return -ENOMEM;
+		}
 		SET_MODULE_OWNER(dev);
 
 		/* Make up a SB1000-specific-data structure. */
diff -Nru a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
--- a/drivers/net/seeq8005.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/seeq8005.c	Mon Jan 13 10:18:07 2003
@@ -377,9 +377,15 @@
 static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
-	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	short length = skb->len;
 	unsigned char *buf = skb->data;
 
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
 	/* Block a timer-based transmit from overlapping */
 	netif_stop_queue(dev);
 	
diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
--- a/drivers/net/sgiseeq.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/sgiseeq.c	Mon Jan 13 10:18:07 2003
@@ -531,6 +531,8 @@
 	 *    added this new entry and restarted it.
 	 */
 	memcpy((char *)(long)td->buf_vaddr, skb->data, skblen);
+	if (len != skblen)
+		memset((char *)(long)td->buf_vaddr + skb->len, 0, len-skblen);
 	td->tdma.cntinfo = (len & HPCDMA_BCNT) |
 	                   (HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX);
 	if (sp->tx_old != sp->tx_new) {
diff -Nru a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c
--- a/drivers/net/sk_g16.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/sk_g16.c	Mon Jan 13 10:18:07 2003
@@ -1254,6 +1254,7 @@
 {
     struct priv *p = (struct priv *) dev->priv;
     struct tmd *tmdp;
+    static char pad[64];
 
     PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", 
 	    SK_NAME, SK_read_reg(CSR0)));
@@ -1278,6 +1279,8 @@
 	/* Copy data into dual ported ram */
 
 	memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len);
+	if (len != skb->len)
+		memcpy_toio((tmdp->u.buffer & 0x00ffffff) + sb->len, pad, len-skb->len);
 
 	writew(-len, &tmdp->blen);            /* set length to transmit */
 
diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
--- a/drivers/net/smc-ultra.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/smc-ultra.c	Mon Jan 13 10:18:05 2003
@@ -284,29 +284,33 @@
         int i;
 
         for (i = 0; ultra_device_ids[i].vendor != 0; i++) {
-                struct pci_dev *idev = NULL;
+		struct pnp_dev *idev = NULL;
 
-                while ((idev = isapnp_find_dev(NULL,
-                                               ultra_device_ids[i].vendor,
-                                               ultra_device_ids[i].function,
-                                               idev))) {
+                while ((idev = pnp_find_dev(NULL,
+                                            ultra_device_ids[i].vendor,
+                                            ultra_device_ids[i].function,
+                                            idev))) {
                         /* Avoid already found cards from previous calls */
-                        if (idev->prepare(idev))
-                                continue;
-                        if (idev->activate(idev))
-                                continue;
-                        /* if no irq, search for next */
-                        if (idev->irq_resource[0].start == 0)
-                                continue;
+                        if (pnp_device_attach(idev) < 0)
+                        	continue;
+                        if (pnp_activate_dev(idev, NULL) < 0) {
+                              __again:
+                        	pnp_device_detach(idev);
+                        	continue;
+                        }
+			/* if no io and irq, search for next */
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
+				goto __again;
                         /* found it */
-                        dev->base_addr = idev->resource[0].start;
-                        dev->irq = idev->irq_resource[0].start;
+			dev->base_addr = pnp_port_start(idev, 0);
+			dev->irq = pnp_irq(idev, 0);
                         printk(KERN_INFO "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
                                 (char *) ultra_device_ids[i].driver_data,
-
                                 dev->base_addr, dev->irq);
                         if (ultra_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
-                                printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);                                return -ENXIO;
+                                printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+                                pnp_device_detach(idev);
+				return -ENXIO;
                         }
                         ei_status.priv = (unsigned long)idev;
                         break;
diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c
--- a/drivers/net/smc9194.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/smc9194.c	Mon Jan 13 10:18:07 2003
@@ -484,8 +484,16 @@
 	}
 	lp->saved_skb = skb;
 
-	length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	length = skb->len;
 
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL) {
+			netif_wake_queue(dev);
+			return 0;
+		}
+		length = ETH_ZLEN;
+	}
 		
 	/*
 	** The MMU wants the number of pages to be the number of 256 bytes
diff -Nru a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
--- a/drivers/net/sun3_82586.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/net/sun3_82586.c	Mon Jan 13 10:18:06 2003
@@ -1010,8 +1010,12 @@
 	else
 #endif
 	{
+		len = skb->len;
+		if (len < ETH_ZLEN) {
+			memset((char *)p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
+			len = ETH_ZLEN;
+		}
 		memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
-		len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 
 #if (NUM_XMIT_BUFFS == 1)
 #	ifdef NO_NOPCOMMANDS
diff -Nru a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
--- a/drivers/net/sun3lance.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/sun3lance.c	Mon Jan 13 10:18:07 2003
@@ -593,6 +593,9 @@
 	head->misc = 0;
 
 	memcpy( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
+	if (len != skb->len)
+		memset(PKTBUF_ADDR(head) + skb->len, 0, len-skb->len);
+
 	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
 	lp->new_tx = (lp->new_tx + 1) & TX_RING_MOD_MASK;
 	lp->stats.tx_bytes += skb->len;
diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
--- a/drivers/net/wireless/wavelan.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/net/wireless/wavelan.c	Mon Jan 13 10:18:07 2003
@@ -3008,6 +3008,12 @@
 	       (unsigned) skb);
 #endif
 
+	if (skb->len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+	}
+
 	/*
 	 * Block a timer-based transmit from overlapping.
 	 * In other words, prevent reentering this routine.
diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
--- a/drivers/net/yellowfin.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/net/yellowfin.c	Mon Jan 13 10:18:05 2003
@@ -862,6 +862,7 @@
 {
 	struct yellowfin_private *yp = dev->priv;
 	unsigned entry;
+	int len = skb->len;
 
 	netif_stop_queue (dev);
 
@@ -876,28 +877,36 @@
 	if (gx_fix) {	/* Note: only works for paddable protocols e.g.  IP. */
 		int cacheline_end = ((unsigned long)skb->data + skb->len) % 32;
 		/* Fix GX chipset errata. */
-		if (cacheline_end > 24  || cacheline_end == 0)
-			skb->len += 32 - cacheline_end + 1;
+		if (cacheline_end > 24  || cacheline_end == 0) {
+			len = skb->len + 32 - cacheline_end + 1;
+			if (len != skb->len)
+				skb = skb_padto(skb, len);
+		}
+		if (skb == NULL) {
+			yp->tx_skbuff[entry] = NULL;
+			netif_wake_queue(dev);
+			return 0;
+		}
 	}
 #ifdef NO_TXSTATS
 	yp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(yp->pci_dev, 
-		skb->data, skb->len, PCI_DMA_TODEVICE));
+		skb->data, len, PCI_DMA_TODEVICE));
 	yp->tx_ring[entry].result_status = 0;
 	if (entry >= TX_RING_SIZE-1) {
 		/* New stop command. */
 		yp->tx_ring[0].dbdma_cmd = cpu_to_le32(CMD_STOP);
 		yp->tx_ring[TX_RING_SIZE-1].dbdma_cmd =
-			cpu_to_le32(CMD_TX_PKT|BRANCH_ALWAYS | skb->len);
+			cpu_to_le32(CMD_TX_PKT|BRANCH_ALWAYS | len);
 	} else {
 		yp->tx_ring[entry+1].dbdma_cmd = cpu_to_le32(CMD_STOP);
 		yp->tx_ring[entry].dbdma_cmd =
-			cpu_to_le32(CMD_TX_PKT | BRANCH_IFTRUE | skb->len);
+			cpu_to_le32(CMD_TX_PKT | BRANCH_IFTRUE | len);
 	}
 	yp->cur_tx++;
 #else
-	yp->tx_ring[entry<<1].request_cnt = skb->len;
+	yp->tx_ring[entry<<1].request_cnt = len;
 	yp->tx_ring[entry<<1].addr = cpu_to_le32(pci_map_single(yp->pci_dev, 
-		skb->data, skb->len, PCI_DMA_TODEVICE));
+		skb->data, len, PCI_DMA_TODEVICE));
 	/* The input_last (status-write) command is constant, but we must 
 	   rewrite the subsequent 'stop' command. */
 
@@ -910,7 +919,7 @@
 
 	yp->tx_ring[entry<<1].dbdma_cmd =
 		cpu_to_le32( ((entry % 6) == 0 ? CMD_TX_PKT|INTR_ALWAYS|BRANCH_IFTRUE :
-					  CMD_TX_PKT | BRANCH_IFTRUE) | skb->len);
+					  CMD_TX_PKT | BRANCH_IFTRUE) | len);
 #endif
 
 	/* Non-x86 Todo: explicitly flush cache lines here. */
diff -Nru a/drivers/net/znet.c b/drivers/net/znet.c
--- a/drivers/net/znet.c	Mon Jan 13 10:18:04 2003
+++ b/drivers/net/znet.c	Mon Jan 13 10:18:04 2003
@@ -538,10 +538,18 @@
 	int ioaddr = dev->base_addr;
 	struct znet_private *znet = dev->priv;
 	unsigned long flags;
+	short length = skb->len;
 
 	if (znet_debug > 4)
 		printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name);
 
+	if (length < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+		length = ETH_ZLEN;
+	}
+	
 	netif_stop_queue (dev);
 	
 	/* Check that the part hasn't reset itself, probably from suspend. */
@@ -556,7 +564,6 @@
 	}
 
 	if (1) {
-		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		unsigned char *buf = (void *)skb->data;
 		ushort *tx_link = znet->tx_cur - 1;
 		ushort rnd_len = (length + 1)>>1;
diff -Nru a/drivers/pci/Kconfig b/drivers/pci/Kconfig
--- a/drivers/pci/Kconfig	Mon Jan 13 10:18:05 2003
+++ b/drivers/pci/Kconfig	Mon Jan 13 10:18:05 2003
@@ -3,6 +3,7 @@
 #
 config PCI_LEGACY_PROC
 	bool "Legacy /proc/pci interface"
+	depends on PCI
 	---help---
 	  This feature enables a procfs file -- /proc/pci -- that provides a 
 	  summary of PCI devices in the system. 
diff -Nru a/drivers/pci/pool.c b/drivers/pci/pool.c
--- a/drivers/pci/pool.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/pci/pool.c	Mon Jan 13 10:18:07 2003
@@ -34,19 +34,16 @@
 DECLARE_MUTEX (pools_lock);
 
 static ssize_t
-show_pools (struct device *dev, char *buf, size_t count, loff_t off)
+show_pools (struct device *dev, char *buf)
 {
 	struct pci_dev		*pdev;
 	unsigned		temp, size;
 	char			*next;
 	struct list_head	*i, *j;
 
-	if (off != 0)
-		return 0;
-
 	pdev = container_of (dev, struct pci_dev, dev);
 	next = buf;
-	size = count;
+	size = PAGE_SIZE;
 
 	temp = snprintf (next, size, "poolinfo - 0.1\n");
 	size -= temp;
@@ -77,7 +74,7 @@
 	}
 	up (&pools_lock);
 
-	return count - size;
+	return PAGE_SIZE - size;
 }
 static DEVICE_ATTR (pools, S_IRUGO, show_pools, NULL);
 
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/pci/probe.c	Mon Jan 13 10:18:06 2003
@@ -262,7 +262,8 @@
 
 	pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
 	DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass);
-	if ((buses & 0xffff00) && !pcibios_assign_all_busses()) {
+	if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
+		unsigned int cmax;
 		/*
 		 * Bus already configured by firmware, process it in the first
 		 * pass and just note the configuration.
@@ -274,13 +275,8 @@
 		child->secondary = (buses >> 8) & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
 		child->number = child->secondary;
-		if (!is_cardbus) {
-			unsigned int cmax = pci_do_scan_bus(child);
-			if (cmax > max) max = cmax;
-		} else {
-			unsigned int cmax = child->subordinate;
-			if (cmax > max) max = cmax;
-		}
+		cmax = pci_do_scan_bus(child);
+		if (cmax > max) max = cmax;
 	} else {
 		/*
 		 * We need to assign a number to this bus which we always
diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c
--- a/drivers/pci/proc.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/pci/proc.c	Mon Jan 13 10:18:06 2003
@@ -374,32 +374,25 @@
 struct proc_dir_entry *proc_bus_pci_dir;
 
 /* driverfs files */
-static ssize_t pci_show_irq(struct device * dev, char * buf, size_t count, loff_t off)
+static ssize_t pci_show_irq(struct device * dev, char * buf)
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
-	return off ? 0 : sprintf(buf,"%u\n",pci_dev->irq);
+	return sprintf(buf,"%u\n",pci_dev->irq);
 }
 
 static DEVICE_ATTR(irq,S_IRUGO,pci_show_irq,NULL);
 
-static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off)
+static ssize_t pci_show_resources(struct device * dev, char * buf)
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	char * str = buf;
 	int i;
 
-	if (off && off < DEVICE_COUNT_RESOURCE) {
+	for (i = 0; i < DEVICE_COUNT_RESOURCE && pci_resource_start(pci_dev,i); i++) {
 		str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n",
-				       pci_resource_start(pci_dev,off),
-				       pci_resource_end(pci_dev,off),
-				       pci_resource_flags(pci_dev,off));
-	} else if (!off) {
-		for (i = 0; i < DEVICE_COUNT_RESOURCE && pci_resource_start(pci_dev,i); i++) {
-			str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n",
-				       pci_resource_start(pci_dev,i),
-				       pci_resource_end(pci_dev,i),
-				       pci_resource_flags(pci_dev,i));
-		}
+			       pci_resource_start(pci_dev,i),
+			       pci_resource_end(pci_dev,i),
+			       pci_resource_flags(pci_dev,i));
 	}
 	return (str - buf);
 }
diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/pcmcia/cardbus.c	Mon Jan 13 10:18:05 2003
@@ -281,6 +281,8 @@
 		dev->vendor = vend;
 		pci_readw(dev, PCI_DEVICE_ID, &dev->device);
 		dev->hdr_type = hdr & 0x7f;
+		dev->dma_mask = 0xffffffff;
+		dev->dev.dma_mask = &dev->dma_mask;
 
 		pci_setup_device(dev);
 		if (pci_enable_device(dev))
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/pcmcia/i82365.c	Mon Jan 13 10:18:07 2003
@@ -839,18 +839,24 @@
 
     for (devid = id_table; devid->vendor; devid++) {
 	if ((dev = pnp_find_dev(NULL, devid->vendor, devid->function, NULL))) {
+	
+	    if (pnp_device_attach(dev) < 0)
+	    	continue;
+	
 	    printk("PNP ");
-
+	    
 	    if (pnp_activate_dev(dev, NULL) < 0) {
 		printk("activate failed\n");
+		pnp_device_detach(dev);
 		break;
 	    }
 
-	    i365_base = pnp_port_start(dev, 0);
-	    if (i365_base) {
-		printk("no resources ?\n");
+	    if (pnp_port_valid(dev, 0)) {
+		printk("invalid resources ?\n");
+		pnp_device_detach(dev);
 		break;
 	    }
+	    i365_base = pnp_port_start(dev, 0);
 	    i82365_pnpdev = dev;
 	    break;
 	}
diff -Nru a/drivers/pnp/card.c b/drivers/pnp/card.c
--- a/drivers/pnp/card.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/pnp/card.c	Mon Jan 13 10:18:07 2003
@@ -62,6 +62,7 @@
 		return -EINVAL;
 	if (!card)
 		return -EINVAL;
+	id->next = NULL;
 	ptr = card->id;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
@@ -109,6 +110,7 @@
 	card->dev.parent = &card->protocol->dev;
 	card->dev.bus = &pnpc_bus_type;
 	card->dev.release = &pnp_release_card;
+	card->status = PNP_READY;
 	error = device_register(&card->dev);
 	if (error == 0){
 		struct list_head *pos;
@@ -131,16 +133,17 @@
 
 void pnpc_remove_card(struct pnp_card *card)
 {
-	struct list_head *pos;
+	struct list_head *pos, *temp;
 	if (!card)
 		return;
 	device_unregister(&card->dev);
 	spin_lock(&pnp_lock);
-	list_del_init(&card->global_list);
-	list_del_init(&card->protocol_list);
+	list_del(&card->global_list);
+	list_del(&card->protocol_list);
 	spin_unlock(&pnp_lock);
-	list_for_each(pos,&card->devices){
+	list_for_each_safe(pos,temp,&card->devices){
 		struct pnp_dev *dev = card_to_pnp_dev(pos);
+		pnpc_remove_device(dev);
 		__pnp_remove_device(dev);
 	}
 }
@@ -174,7 +177,7 @@
 {
 	spin_lock(&pnp_lock);
 	dev->card = NULL;
-	list_del_init(&dev->card_list);
+	list_del(&dev->card_list);
 	spin_unlock(&pnp_lock);
 	__pnp_remove_device(dev);
 }
@@ -213,6 +216,13 @@
 	return NULL;
 
 found:
+	spin_lock(&pnp_lock);
+	if(dev->status != PNP_READY){
+		spin_unlock(&pnp_lock);
+		return NULL;
+	}
+	dev->status = PNP_ATTACHED;
+	spin_unlock(&pnp_lock);
 	cdrv = to_pnpc_driver(card->dev.driver);
 	if (dev->active == 0) {
 		if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) {
@@ -239,20 +249,43 @@
 void pnp_release_card_device(struct pnp_dev *dev)
 {
 	spin_lock(&pnp_lock);
-	list_del_init(&dev->rdev_list);
+	list_del(&dev->rdev_list);
+	if (dev->status == PNP_ATTACHED)
+		dev->status = PNP_READY;
 	spin_unlock(&pnp_lock);
 	pnp_disable_dev(dev);
 }
 
 static void pnpc_recover_devices(struct pnp_card *card)
 {
-	struct list_head *pos;
-	list_for_each(pos,&card->rdevs){
+	struct list_head *pos, *temp;
+	list_for_each_safe(pos,temp,&card->rdevs){
 		struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list);
 		pnp_release_card_device(dev);
 	}
 }
 
+int pnpc_attach(struct pnp_card *pnp_card)
+{
+	spin_lock(&pnp_lock);
+	if(pnp_card->status != PNP_READY){
+		spin_unlock(&pnp_lock);
+		return -EBUSY;
+	}
+	pnp_card->status = PNP_ATTACHED;
+	spin_unlock(&pnp_lock);
+	return 0;
+}
+ 
+void pnpc_detach(struct pnp_card *pnp_card)
+{
+	spin_lock(&pnp_lock);
+	if (pnp_card->status == PNP_ATTACHED)
+		pnp_card->status = PNP_READY;
+	spin_unlock(&pnp_lock);
+	pnpc_recover_devices(pnp_card);
+}
+
 static int pnpc_card_probe(struct device *dev)
 {
 	int error = 0;
@@ -262,6 +295,9 @@
 
 	pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name);
 
+	error = pnpc_attach(card);
+	if (error < 0)
+		return error;
 	if (drv->probe) {
 		card_id = match_card(drv, card);
 		if (card_id != NULL)
@@ -270,7 +306,7 @@
 			card->driver = drv;
 			error = 0;
 		} else
-			pnpc_recover_devices(card);
+			pnpc_detach(card);
 	}
 	return error;
 }
@@ -285,7 +321,7 @@
 			drv->remove(card);
 		card->driver = NULL;
 	}
-	pnpc_recover_devices(card);
+	pnpc_detach(card);
 	return 0;
 }
 
@@ -348,3 +384,5 @@
 EXPORT_SYMBOL(pnpc_register_driver);
 EXPORT_SYMBOL(pnpc_unregister_driver);
 EXPORT_SYMBOL(pnpc_add_id);
+EXPORT_SYMBOL(pnpc_attach);
+EXPORT_SYMBOL(pnpc_detach);
diff -Nru a/drivers/pnp/core.c b/drivers/pnp/core.c
--- a/drivers/pnp/core.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/pnp/core.c	Mon Jan 13 10:18:05 2003
@@ -81,7 +81,7 @@
 void pnp_unregister_protocol(struct pnp_protocol *protocol)
 {
 	spin_lock(&pnp_lock);
-	list_del_init(&protocol->protocol_list);
+	list_del(&protocol->protocol_list);
 	spin_unlock(&pnp_lock);
 	device_unregister(&protocol->dev);
 }
@@ -119,6 +119,7 @@
 	dev->dev.name[DEVICE_NAME_SIZE-1] = '\0';
 	dev->dev.bus = &pnp_bus_type;
 	dev->dev.release = &pnp_release_device;
+	dev->status = PNP_READY;
 	error = device_register(&dev->dev);
 	if (error == 0){
 		spin_lock(&pnp_lock);
@@ -149,8 +150,8 @@
 void __pnp_remove_device(struct pnp_dev *dev)
 {
 	spin_lock(&pnp_lock);
-	list_del_init(&dev->global_list);
-	list_del_init(&dev->protocol_list);
+	list_del(&dev->global_list);
+	list_del(&dev->protocol_list);
 	spin_unlock(&pnp_lock);
 	device_unregister(&dev->dev);
 }
@@ -171,7 +172,7 @@
 
 static int __init pnp_init(void)
 {
-	printk(KERN_INFO "Linux Plug and Play Support v0.93 (c) Adam Belay\n");
+	printk(KERN_INFO "Linux Plug and Play Support v0.94 (c) Adam Belay\n");
 	return bus_register(&pnp_bus_type);
 }
 
diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c
--- a/drivers/pnp/driver.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/pnp/driver.c	Mon Jan 13 10:18:07 2003
@@ -19,6 +19,7 @@
 #endif
 
 #include <linux/pnp.h>
+#include "base.h"
 
 static int compare_func(const char *ida, const char *idb)
 {
@@ -64,6 +65,27 @@
 	return NULL;
 }
 
+int pnp_device_attach(struct pnp_dev *pnp_dev)
+{
+	spin_lock(&pnp_lock);
+	if(pnp_dev->status != PNP_READY){
+		spin_unlock(&pnp_lock);
+		return -EBUSY;
+	}
+	pnp_dev->status = PNP_ATTACHED;
+	spin_unlock(&pnp_lock);
+	return 0;
+}
+
+void pnp_device_detach(struct pnp_dev *pnp_dev)
+{
+	spin_lock(&pnp_lock);
+	if (pnp_dev->status == PNP_ATTACHED)
+		pnp_dev->status = PNP_READY;
+	spin_unlock(&pnp_lock);
+	pnp_disable_dev(pnp_dev);
+}
+
 static int pnp_device_probe(struct device *dev)
 {
 	int error;
@@ -75,6 +97,10 @@
 
 	pnp_dbg("pnp: match found with the PnP device '%s' and the driver '%s'", dev->bus_id,pnp_drv->name);
 
+	error = pnp_device_attach(pnp_dev);
+	if (error < 0)
+		return error;
+
 	if (pnp_dev->active == 0) {
 		if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) {
 			error = pnp_activate_dev(pnp_dev, NULL);
@@ -95,6 +121,12 @@
 		pnp_dev->driver = pnp_drv;
 		error = 0;
 	}
+	else
+	goto fail;
+	return error;
+
+fail:
+	pnp_device_detach(pnp_dev);
 	return error;
 }
 
@@ -108,7 +140,7 @@
 			drv->remove(pnp_dev);
 		pnp_dev->driver = NULL;
 	}
-	pnp_disable_dev(pnp_dev);
+	pnp_device_detach(pnp_dev);
 	return 0;
 }
 
@@ -172,6 +204,7 @@
 		return -EINVAL;
 	if (!dev)
 		return -EINVAL;
+	id->next = NULL;
 	ptr = dev->id;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
@@ -185,3 +218,5 @@
 EXPORT_SYMBOL(pnp_register_driver);
 EXPORT_SYMBOL(pnp_unregister_driver);
 EXPORT_SYMBOL(pnp_add_id);
+EXPORT_SYMBOL(pnp_device_attach);
+EXPORT_SYMBOL(pnp_device_detach);
diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- a/drivers/pnp/interface.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/pnp/interface.c	Mon Jan 13 10:18:05 2003
@@ -215,14 +215,13 @@
 		pnp_print_mem32(buffer, space, mem32);
 }
 
-static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf, size_t count, loff_t off)
+static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf)
 {
 	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;
@@ -242,57 +241,58 @@
 
 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)
+static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
 {
 	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_IO; i++) {
+		if (pnp_port_valid(dev, i)) {
+			str += sprintf(str,"io");
+			str += sprintf(str," 0x%lx-0x%lx \n",
+						pnp_port_start(dev, i),
+						pnp_port_end(dev, i));
+		}
+	}
+	for (i = 0; i < DEVICE_COUNT_MEM; i++) {
+		if (pnp_mem_valid(dev, i)) {
+			str += sprintf(str,"mem");
+			str += sprintf(str," 0x%lx-0x%lx \n",
+						pnp_mem_start(dev, i),
+						pnp_mem_end(dev, i));
+		}
 	}
-	for (i = 0; i < DEVICE_COUNT_IRQ && dev->irq_resource[i].flags
-			 & IORESOURCE_IRQ; i++) {
+	for (i = 0; i < DEVICE_COUNT_IRQ; i++) {
+		if (pnp_irq_valid(dev, i)) {
 			str += sprintf(str,"irq");
-			str += sprintf(str," %ld \n", dev->irq_resource[i].start);
+			str += sprintf(str," %ld \n", pnp_irq(dev, i));
+		}
 	}
-	for (i = 0; i < DEVICE_COUNT_DMA && dev->dma_resource[i].flags
-			 & IORESOURCE_DMA; i++) {
+	for (i = 0; i < DEVICE_COUNT_DMA; i++) {
+		if (pnp_dma_valid(dev, i)) {
 			str += sprintf(str,"dma");
-			str += sprintf(str," %ld \n", dev->dma_resource[i].start);
+			str += sprintf(str," %ld \n", pnp_dma(dev, i));
+		}
 	}
 	done:
 	return (str - buf);
 }
 
 static ssize_t
-pnp_set_current_resources(struct device * dmdev, const char * buf, size_t count, loff_t off)
+pnp_set_current_resources(struct device * dmdev, const char * buf)
 {
 	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);
+	int	depnum;
+
+	num_args = sscanf(buf,"%10s %i",command,&depnum);
 	if (!num_args)
 		goto done;
 	if (!strnicmp(command,"lock",4)) {
@@ -320,27 +320,24 @@
 		goto done;
 	}
 	if (!strnicmp(command,"manual",6)) {
-		if (num_args != 3)
+		if (num_args != 2)
 			goto done;
-		if (!strnicmp(type,"static",6))
-			mode = PNP_STATIC;
-		error = pnp_raw_set_dev(dev,depnum,NULL,mode);
+		error = pnp_raw_set_dev(dev,depnum,NULL);
 		goto done;
 	}
  done:
-	return error < 0 ? error : count;
+	return error < 0 ? error : strlen(buf);
 }
 
 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)
+static ssize_t pnp_show_current_ids(struct device *dmdev, char *buf)
 {
 	char *str = buf;
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	struct pnp_id * pos = dev->id;
-	if (off)
-		return 0;
+
 	while (pos) {
 		str += sprintf(str,"%s\n", pos->id);
 		pos = pos->next;
diff -Nru a/drivers/pnp/isapnp/compat.c b/drivers/pnp/isapnp/compat.c
--- a/drivers/pnp/isapnp/compat.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/pnp/isapnp/compat.c	Mon Jan 13 10:18:07 2003
@@ -8,10 +8,11 @@
  
 /* TODO: see if more isapnp functions are needed here */
 
-#include <linux/pnp.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
 #include <linux/isapnp.h>
 #include <linux/string.h>
-#include <linux/module.h>
 
 static void pnp_convert_id(char *buf, unsigned short vendor, unsigned short device)
 {
@@ -29,8 +30,8 @@
 			       unsigned short device,
 			       struct pnp_card *from)
 {
-	char id[7];
-	char any[7];
+	char id[8];
+	char any[8];
 	struct list_head *list;
 	pnp_convert_id(id, vendor, device);
 	pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID);
@@ -51,8 +52,8 @@
 			     unsigned short function,
 			     struct pnp_dev *from)
 {
-	char id[7];
-	char any[7];
+	char id[8];
+	char any[8];
 	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 */
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/pnp/isapnp/core.c	Mon Jan 13 10:18:06 2003
@@ -454,6 +454,10 @@
 	if (size > 5)
 		dev->regs |= tmp[5] << 8;
 	dev->protocol = &isapnp_protocol;
+	dev->capabilities |= PNP_CONFIGURABLE;
+	dev->capabilities |= PNP_READ;
+	dev->capabilities |= PNP_WRITE;
+	dev->capabilities |= PNP_DISABLE;
 	return dev;
 }
 
@@ -889,7 +893,7 @@
 		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;
-		card->protocol = &isapnp_card_protocol;
+		card->protocol = &isapnp_protocol;
 		pnpc_add_card(card);
 	}
 	return 0;
@@ -903,7 +907,7 @@
 {
 	struct pnp_card *card;
 	pnp_for_each_card(card) {
-		if (card->protocol == &isapnp_card_protocol)
+		if (card->protocol == &isapnp_protocol)
 			return 1;
 	}
 	return 0;
@@ -956,19 +960,25 @@
 		dev->irq_resource[idx].name = NULL;
 		dev->irq_resource[idx].start = -1;
 		dev->irq_resource[idx].end = -1;
-		dev->irq_resource[idx].flags = 0;
+		dev->irq_resource[idx].flags = IORESOURCE_IRQ|IORESOURCE_UNSET;
 	}
 	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;
+		dev->dma_resource[idx].flags = IORESOURCE_DMA|IORESOURCE_UNSET;
 	}
-	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;
+	for (idx = 0; idx < DEVICE_COUNT_IO; idx++) {
+		dev->io_resource[idx].name = NULL;
+		dev->io_resource[idx].start = 0;
+		dev->io_resource[idx].end = 0;
+		dev->io_resource[idx].flags = IORESOURCE_IO|IORESOURCE_UNSET;
+	}
+	for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) {
+		dev->mem_resource[idx].name = NULL;
+		dev->mem_resource[idx].start = 0;
+		dev->mem_resource[idx].end = 0;
+		dev->mem_resource[idx].flags = IORESOURCE_MEM|IORESOURCE_UNSET;
 	}
 	return 0;
 }
@@ -993,16 +1003,17 @@
 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))
+	if (pnp_port_valid(dev, 0) == 0 &&
+	    pnp_mem_valid(dev, 0) == 0 &&
+	    pnp_irq_valid(dev, 0) == 0 &&
+	    pnp_dma_valid(dev, 0) == 0)
 		dev->active = 0;
 	else
 		dev->active = 1;
 	return 0;
 }
 
-static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_cfg *cfg, char flags)
+static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_cfg *cfg)
 {
 	int tmp;
       	isapnp_cfg_begin(dev->card->number, dev->number);
@@ -1011,21 +1022,22 @@
 	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;
+	for (tmp = 0; tmp < DEVICE_COUNT_IO; tmp++)
+		dev->io_resource[tmp] = cfg->request.io_resource[tmp];
+	for (tmp = 0; tmp < DEVICE_COUNT_MEM; tmp++)
+		dev->mem_resource[tmp] = cfg->request.mem_resource[tmp];
+	for (tmp = 0; tmp < 8 && pnp_port_valid(dev, tmp); tmp++)
+		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), pnp_port_start(dev, tmp));
+	for (tmp = 0; tmp < 2 && pnp_irq_valid(dev, tmp); tmp++) {
+		int irq = pnp_irq(dev, tmp);
 		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);
+	for (tmp = 0; tmp < 2 && pnp_dma_valid(dev, tmp); tmp++)
+		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, pnp_dma(dev, tmp));
+	for (tmp = 0; tmp < 4 && pnp_mem_valid(dev, tmp); tmp++)
+		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (pnp_mem_start(dev, tmp) >> 8) & 0xffff);
 	isapnp_activate(dev->number);
 	isapnp_cfg_end();
 	return 0;
@@ -1042,15 +1054,8 @@
 	return 0;
 }
 
-struct pnp_protocol isapnp_card_protocol = {
-	.name	= "ISA Plug and Play - card",
-	.get	= NULL,
-	.set	= NULL,
-	.disable = NULL,
-};
-
 struct pnp_protocol isapnp_protocol = {
-	.name	= "ISA Plug and Play - device",
+	.name	= "ISA Plug and Play",
 	.get	= isapnp_get_resources,
 	.set	= isapnp_set_resources,
 	.disable = isapnp_disable_resources,
@@ -1081,9 +1086,6 @@
 		return -EBUSY;
 	}
 
-	if(pnp_register_protocol(&isapnp_card_protocol)<0)
-		return -EBUSY;
-
 	if(pnp_register_protocol(&isapnp_protocol)<0)
 		return -EBUSY;
 
@@ -1123,7 +1125,7 @@
 	isapnp_build_device_list();
 	cards = 0;
 
-	protocol_for_each_card(&isapnp_protocol,card) {
+	protocol_for_each_card(&isapnp_card_protocol,card) {
 		cards++;
 		if (isapnp_verbose) {
 			printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
@@ -1144,7 +1146,7 @@
 	return 0;
 }
 
-device_initcall(isapnp_init);
+subsys_initcall(isapnp_init);
 
 /* format is: noisapnp */
 
diff -Nru a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
--- a/drivers/pnp/isapnp/proc.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/pnp/isapnp/proc.c	Mon Jan 13 10:18:05 2003
@@ -19,12 +19,12 @@
  *
  */
 
-
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
 #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>
 
diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
--- a/drivers/pnp/pnpbios/core.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/pnp/pnpbios/core.c	Mon Jan 13 10:18:05 2003
@@ -671,9 +671,10 @@
 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++;
+	while (pnp_irq_valid(dev, i) && i < DEVICE_COUNT_IRQ) i++;
 	if (i < DEVICE_COUNT_IRQ) {
-		dev->irq_resource[i].start = (unsigned long) irq;
+		dev->irq_resource[i].start = 
+		dev->irq_resource[i].end = (unsigned long) irq;
 		dev->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
 	}
 }
@@ -681,9 +682,10 @@
 static void add_dmaresource(struct pnp_dev *dev, int dma)
 {
 	int i = 0;
-	while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++;
+	while (pnp_dma_valid(dev, i) && i < DEVICE_COUNT_DMA) i++;
 	if (i < DEVICE_COUNT_DMA) {
-		dev->dma_resource[i].start = (unsigned long) dma;
+		dev->dma_resource[i].start =
+		dev->dma_resource[i].end = (unsigned long) dma;
 		dev->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
 	}
 }
@@ -691,22 +693,22 @@
 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++;
+	while (pnp_port_valid(dev, i) && i < DEVICE_COUNT_IO) 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
+		dev->io_resource[i].start = (unsigned long) io;
+		dev->io_resource[i].end = (unsigned long)(io + len - 1);
+		dev->io_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
 	}
 }
 
 static void add_memresource(struct pnp_dev *dev, int mem, int len)
 {
-	int i = 8;
-	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
+	int i = 0;
+	while (pnp_mem_valid(dev, i) && i < DEVICE_COUNT_MEM) 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
+		dev->mem_resource[i].start = (unsigned long) mem;
+		dev->mem_resource[i].end = (unsigned long)(mem + len - 1);
+		dev->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
 	}
 }
 
@@ -718,17 +720,25 @@
 	/*
 	 * 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_IO;i++) {
+		dev->io_resource[i].start = 0;
+		dev->io_resource[i].end = 0;
+		dev->io_resource[i].flags = IORESOURCE_IO|IORESOURCE_UNSET;
+	}
+	for (i=0;i<DEVICE_COUNT_MEM;i++) {
+		dev->mem_resource[i].start = 0;
+		dev->mem_resource[i].end = 0;
+		dev->mem_resource[i].flags = IORESOURCE_MEM|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;
+		dev->irq_resource[i].start = (unsigned long)-1;
+		dev->irq_resource[i].end = (unsigned long)-1;
+		dev->irq_resource[i].flags = IORESOURCE_IRQ|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;
+		dev->dma_resource[i].start = (unsigned long)-1;
+		dev->dma_resource[i].end = (unsigned long)-1;
+		dev->dma_resource[i].flags = IORESOURCE_DMA|IORESOURCE_UNSET;
 	}
 
 	/*
@@ -815,10 +825,10 @@
 
         } /* while */
 	end:
-	if ((dev->resource[0].start == 0) &&
-	    (dev->resource[8].start == 0) &&
-	    (dev->irq_resource[0].start == -1) &&
-	    (dev->dma_resource[0].start == -1))
+	if (pnp_port_valid(dev, 0) == 0 &&
+	    pnp_mem_valid(dev, 0) == 0 &&
+	    pnp_irq_valid(dev, 0) == 0 &&
+	    pnp_dma_valid(dev, 0) == 0)
 		dev->active = 0;
 	else
 		dev->active = 1;
@@ -1261,9 +1271,7 @@
 	struct pnp_bios_node * node;
 		
 	/* just in case */
-	if(pnp_dev_has_driver(dev))
-		return -EBUSY;
-	if(!pnp_is_dynamic(dev))
+	if(!pnpbios_is_dynamic(dev))
 		return -EPERM;
 	if (pnp_bios_dev_node_info(&node_info) != 0)
 		return -ENODEV;
@@ -1277,16 +1285,14 @@
 	return 0;
 }
 
-static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config, char flags)
+static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config)
 {
 	struct pnp_dev_node_info node_info;
 	u8 nodenum = dev->number;
 	struct pnp_bios_node * node;
 
 	/* just in case */
-	if(pnp_dev_has_driver(dev))
-		return -EBUSY;
-	if (flags == PNP_DYNAMIC && !pnp_is_dynamic(dev))
+	if (!pnpbios_is_dynamic(dev))
 		return -EPERM;
 	if (pnp_bios_dev_node_info(&node_info) != 0)
 		return -ENODEV;
@@ -1338,9 +1344,7 @@
 	if (!config)
 		return -1;
 	/* just in case */
-	if(pnp_dev_has_driver(dev))
-		return -EBUSY;
-	if(dev->flags & PNP_NO_DISABLE || !pnp_is_dynamic(dev))
+	if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
 		return -EPERM;
 	memset(config, 0, sizeof(struct pnp_cfg));
 	if (!dev || !dev->active)
@@ -1449,6 +1453,15 @@
 		pos = node_possible_resource_data_to_dev(pos,node,dev);
 		node_id_data_to_dev(pos,node,dev);
 		dev->flags = node->flags;
+		if (!(dev->flags & PNPBIOS_NO_CONFIG))
+			dev->capabilities |= PNP_CONFIGURABLE;
+		if (!(dev->flags & PNPBIOS_NO_DISABLE))
+			dev->capabilities |= PNP_DISABLE;
+		dev->capabilities |= PNP_READ;
+		if (pnpbios_is_dynamic(dev))
+			dev->capabilities |= PNP_WRITE;
+		if (dev->flags & PNPBIOS_REMOVABLE)
+			dev->capabilities |= PNP_REMOVABLE;
 
 		dev->protocol = &pnpbios_protocol;
 
diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c
--- a/drivers/pnp/resource.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/pnp/resource.c	Mon Jan 13 10:18:06 2003
@@ -328,9 +328,9 @@
 	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 (pnp_port_valid(dev, tmp)) {
+					rport = pnp_port_start(dev, tmp);
+					rsize = pnp_port_len(dev, tmp);
 					if (port >= rport && port < rport + rsize)
 						return 1;
 					if (port + size > rport && port + size < (rport + rsize) - 1)
@@ -340,9 +340,10 @@
 		}
 	}
 	for (tmp = 0; tmp < 8 && tmp != idx; tmp++) {
-		if (dev->resource[tmp].flags) {
-			rport = config->request.resource[tmp].start;
-			rsize = (config->request.resource[tmp].end - rport) + 1;
+		if (pnp_port_valid(dev, tmp) &&
+		    pnp_flags_valid(&config->request.io_resource[tmp])) {
+			rport = config->request.io_resource[tmp].start;
+			rsize = (config->request.io_resource[tmp].end - rport) + 1;
 			if (port >= rport && port < rport + rsize)
 				return 1;
 			if (port + size > rport && port + size < (rport + rsize) - 1)
@@ -371,9 +372,9 @@
 	pnp_for_each_dev(dev) {
 		if (dev->active) {
 			for (tmp = 0; tmp < 4; tmp++) {
-				if (dev->resource[tmp + 8].flags) {
-					raddr = dev->resource[tmp + 8].start;
-					rsize = (dev->resource[tmp + 8].end - raddr) + 1;
+				if (pnp_mem_valid(dev, tmp)) {
+					raddr = pnp_mem_start(dev, tmp);
+					rsize = pnp_mem_len(dev, tmp);
 					if (addr >= raddr && addr < raddr + rsize)
 						return 1;
 					if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
@@ -383,9 +384,10 @@
 		}
 	}
 	for (tmp = 0; tmp < 4 && tmp != idx; tmp++) {
-		if (dev->resource[tmp + 8].flags) {
-			raddr = config->request.resource[tmp + 8].start;
-			rsize = (config->request.resource[tmp + 8].end - raddr) + 1;
+		if (pnp_mem_valid(dev, tmp) &&
+		    pnp_flags_valid(&config->request.mem_resource[tmp])) {
+			raddr = config->request.mem_resource[tmp].start;
+			rsize = (config->request.mem_resource[tmp].end - raddr) + 1;
 			if (addr >= raddr && addr < raddr + rsize)
 				return 1;
 			if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
@@ -417,13 +419,14 @@
 	}
 	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))
+			if ((pnp_irq_valid(dev, 0) && dev->irq_resource[0].start == irq) ||
+			    (pnp_irq_valid(dev, 1) && 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))
+	if (pnp_flags_valid(&config->request.irq_resource[0]) &&
+	    pnp_flags_valid(&config->request.irq_resource[1]) &&
+	    (config->request.irq_resource[0].start == irq))
 		return 1;
 #ifdef CONFIG_PCI
 	if (!pnp_skip_pci_scan) {
@@ -456,13 +459,14 @@
 	}
 	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))
+			if ((pnp_dma_valid(dev, 0) && pnp_dma(dev, 0) == dma) ||
+			    (pnp_dma_valid(dev, 1) && pnp_dma(dev, 1) == dma))
 				return 1;
 		}
 	}
-	if (config->request.dma_resource[0].flags && config->request.dma_resource[1].flags &&
-	   (config->request.dma_resource[0].start == dma))
+	if (pnp_flags_valid(&config->request.dma_resource[0]) &&
+	    pnp_flags_valid(&config->request.dma_resource[1]) &&
+	    (config->request.dma_resource[0].start == dma))
 		return 1;
 	if (request_dma(dma, "pnp"))
 		return 1;
@@ -481,11 +485,11 @@
 	port = config->port[num];
 	if (!port)
 		return 0;
-	value1 = &config->request.resource[num].start;
-	value2 = &config->request.resource[num].end;
-	value3 = &config->request.resource[num].flags;
+	value1 = &config->request.io_resource[num].start;
+	value2 = &config->request.io_resource[num].end;
+	value3 = &config->request.io_resource[num].flags;
 	*value1 = port->min;
-	*value2 = *value1 + port->size -1;
+	*value2 = *value1 + port->size - 1;
 	*value3 = port->flags | IORESOURCE_IO;
 	while (pnp_check_port(*value1, port->size, num, config)) {
 		*value1 += port->align;
@@ -505,11 +509,11 @@
 	mem = config->mem[num];
 	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 = &config->request.mem_resource[num].start;
+	value2 = &config->request.mem_resource[num].end;
+	value3 = &config->request.mem_resource[num].flags;
 	*value1 = mem->min;
-	*value2 = *value1 + mem->size -1;
+	*value2 = *value1 + mem->size - 1;
 	*value3 = mem->flags | IORESOURCE_MEM;
 	if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))
 		*value3 |= IORESOURCE_READONLY;
@@ -597,19 +601,25 @@
 	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
 		res_config->irq_resource[idx].start = -1;
 		res_config->irq_resource[idx].end = -1;
-		res_config->irq_resource[idx].flags = 0;
+		res_config->irq_resource[idx].flags = IORESOURCE_IRQ|IORESOURCE_UNSET;
 	}
 	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
 		res_config->dma_resource[idx].name = NULL;
 		res_config->dma_resource[idx].start = -1;
 		res_config->dma_resource[idx].end = -1;
-		res_config->dma_resource[idx].flags = 0;
+		res_config->dma_resource[idx].flags = IORESOURCE_DMA|IORESOURCE_UNSET;
 	}
-	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
-		res_config->resource[idx].name = NULL;
-		res_config->resource[idx].start = 0;
-		res_config->resource[idx].end = 0;
-		res_config->resource[idx].flags = 0;
+	for (idx = 0; idx < DEVICE_COUNT_IO; idx++) {
+		res_config->io_resource[idx].name = NULL;
+		res_config->io_resource[idx].start = 0;
+		res_config->io_resource[idx].end = 0;
+		res_config->io_resource[idx].flags = IORESOURCE_IO|IORESOURCE_UNSET;
+	}
+	for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) {
+		res_config->mem_resource[idx].name = NULL;
+		res_config->mem_resource[idx].start = 0;
+		res_config->mem_resource[idx].end = 0;
+		res_config->mem_resource[idx].flags = IORESOURCE_MEM|IORESOURCE_UNSET;
 	}
 	return 0;
 }
@@ -629,14 +639,17 @@
 	if (!template)
 		return 0;
 	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++)
-		if (template->irq_resource[idx].start >= 0)
+		if (pnp_flags_valid(&template->irq_resource[idx]))
 			config->request.irq_resource[idx] = template->irq_resource[idx];
 	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++)
-		if (template->dma_resource[idx].start >= 0)
+		if (pnp_flags_valid(&template->dma_resource[idx]))
 			config->request.dma_resource[idx] = template->dma_resource[idx];
-	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++)
-		if (template->resource[idx].start > 0)
-			config->request.resource[idx] = template->resource[idx];
+	for (idx = 0; idx < DEVICE_COUNT_IO; idx++)
+		if (pnp_flags_valid(&template->io_resource[idx]))
+			config->request.io_resource[idx] = template->io_resource[idx];
+	for (idx = 0; idx < DEVICE_COUNT_MEM; idx++)
+		if (pnp_flags_valid(&template->io_resource[idx]))
+			config->request.mem_resource[idx] = template->mem_resource[idx];
 	return 0;
 }
 
@@ -750,7 +763,7 @@
 		dma = dma->next;
 	}
 	return config;
-	
+
 	fail:
 	kfree(config);
 	return NULL;
@@ -772,13 +785,13 @@
 	if (!dev)
 		return -EINVAL;
         max = pnp_get_max_depnum(dev);
-	if (dev->active)
+	if (!pnp_can_configure(dev))
 		return -EBUSY;
-	if (pnp_dev_has_driver(dev)){
+	if (dev->status != PNP_READY && dev->status != PNP_ATTACHED){
 		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)
+	if (!pnp_can_write(dev))
 		return -EINVAL;
 	if (max == 0)
 		return 0;
@@ -796,8 +809,8 @@
 
 	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->set(dev,config);
+	if (pnp_can_read(dev))
 		dev->protocol->get(dev);
 	kfree(config);
 	return 0;
@@ -814,13 +827,13 @@
 {
         if (!dev)
                 return -EINVAL;
-	if (pnp_dev_has_driver(dev)){
+	if (dev->status != PNP_READY){
 		printk(KERN_INFO "pnp: Disable failed becuase the PnP device '%s' is busy\n", dev->dev.bus_id);
 		return -EINVAL;
 	}
 	if (dev->lock_resources)
 		return -EPERM;
-	if (!dev->protocol->disable || !dev->active)
+	if (!pnp_can_disable(dev) || !dev->active)
 		return -EINVAL;
 	pnp_dbg("the device '%s' has been disabled", dev->dev.bus_id);
 	return dev->protocol->disable(dev);
@@ -834,16 +847,16 @@
  *
  */
 
-int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template, int mode)
+int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template)
 {
 	struct pnp_cfg *config;
 	if (!dev)
 		return -EINVAL;
-	if (pnp_dev_has_driver(dev)){
+	if (dev->status != PNP_READY){
 		printk(KERN_INFO "pnp: Unable to set resources because the PnP device '%s' is busy\n", dev->dev.bus_id);
 		return -EINVAL;
 	}
-	if (!dev->protocol->get || !dev->protocol->set)
+	if (!pnp_can_write(dev) || !pnp_can_configure(dev))
 		return -EINVAL;
         config = pnp_generate_config(dev,depnum);
 	if (!config)
@@ -855,8 +868,8 @@
 	return -ENOENT;
 
 	done:
-	dev->protocol->set(dev,config,mode);
-	if (dev->protocol->get)
+	dev->protocol->set(dev,config);
+	if (pnp_can_read(dev))
 		dev->protocol->get(dev);
 	kfree(config);
 	return 0;
@@ -874,7 +887,7 @@
 {
 	if (resource == NULL)
 		return;
-	resource->flags &= ~IORESOURCE_AUTO;
+	resource->flags &= ~(IORESOURCE_AUTO|IORESOURCE_UNSET);
 	resource->start = start;
 	resource->end = start + size - 1;
 }
diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c
--- a/drivers/pnp/system.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/pnp/system.c	Mon Jan 13 10:18:07 2003
@@ -53,44 +53,33 @@
 {
 	int i;
 
-	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
-		if ( dev->resource[i].flags & IORESOURCE_UNSET )
+	for (i=0;i<DEVICE_COUNT_IO;i++) {
+		if (pnp_port_valid(dev, i))
 			/* 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 */
+		if (pnp_port_start(dev, i) == 0)
+			/* disabled */
 			/* Do nothing */
 			continue;
-		}
+		if (pnp_port_start(dev, i) < 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 (pnp_port_end(dev, i) < pnp_port_start(dev, i))
+			/* invalid endpoint */
+			/* Do nothing */
+			continue;
+		reserve_ioport_range(
+			dev->dev.bus_id,
+			pnp_port_start(dev, i),
+			pnp_port_end(dev, i)
+		);
 	}
 
 	return;
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/scsi/NCR53C9x.c	Mon Jan 13 10:18:05 2003
@@ -1164,7 +1164,7 @@
 		 *           ID bit on the data bus even though the ESP is
 		 *           at ID 7 and is the obvious winner for any
 		 *           arbitration.  The ESP is a poor sport and refuses
-		 *           to lose arbitration, it will continue indefinately
+		 *           to lose arbitration, it will continue indefinitely
 		 *           trying to arbitrate for the bus and can only be
 		 *           stopped via a chip reset or SCSI bus reset.
 		 *           Therefore _no_ disconnects for SCSI1 targets
diff -Nru a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
--- a/drivers/scsi/aha152x.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/scsi/aha152x.c	Mon Jan 13 10:18:05 2003
@@ -970,7 +970,7 @@
 }
 
 #ifdef __ISAPNP__
-static struct pci_dev *pnpdev[2];
+static struct pnp_dev *pnpdev[2];
 static int num_pnpdevs;
 #endif
 int aha152x_detect(Scsi_Host_Template * tpnt)
@@ -979,7 +979,7 @@
 #if defined(AUTOCONF)
 	aha152x_config conf;
 #ifdef __ISAPNP__
-	struct pci_dev *dev = NULL;
+	struct pnp_dev *dev = NULL;
 #endif
 #endif
 	tpnt->proc_name = "aha152x"; 
@@ -1128,22 +1128,23 @@
 #endif
 
 #ifdef __ISAPNP__
-	while ( setup_count<ARRAY_SIZE(setup) && (dev=isapnp_find_dev(NULL, ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), dev)) ) {
-		if (dev->prepare(dev) < 0)
+	while ( setup_count<ARRAY_SIZE(setup) && (dev=pnp_find_dev(NULL, ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), dev)) ) {
+		if (pnp_device_attach(dev) < 0)
 			continue;
-		if (dev->active)
+		if (pnp_activate_dev(dev, NULL) < 0) {
+			pnp_device_detach(dev);
 			continue;
-		if (!(dev->resource[0].flags & IORESOURCE_IO))
-			continue;
-		dev->resource[0].flags |= IORESOURCE_AUTO;
-		if (dev->activate(dev) < 0)
+		}
+		if (!pnp_port_valid(dev, 0)) {
+			pnp_device_detach(dev);
 			continue;
-		if ( setup_count==1 && dev->resource[0].start==setup[0].io_port) {
-			dev->deactivate(dev);
+		}
+		if (setup_count==1 && pnp_port_start(dev, 0)==setup[0].io_port) {
+			pnp_device_detach(dev);
 			continue;
 		}
-		setup[setup_count].io_port     = dev->resource[0].start;
-		setup[setup_count].irq         = dev->irq_resource[0].start;
+		setup[setup_count].io_port     = pnp_port_start(dev, 0);
+		setup[setup_count].irq         = pnp_irq(dev, 0);
 		setup[setup_count].scsiid      = 7;
 		setup[setup_count].reconnect   = 1;
 		setup[setup_count].parity      = 1;
@@ -1421,7 +1422,7 @@
 
 #ifdef __ISAPNP__
 	while (num_pnpdevs--)
-		pnpdev[num_pnpdevs]->deactivate(pnpdev[num_pnpdevs]);
+		pnp_device_detach(pnpdev[num_pnpdevs]);
 #endif
 	scsi_unregister(shpnt);
 
diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
--- a/drivers/scsi/aha1542.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/scsi/aha1542.c	Mon Jan 13 10:18:06 2003
@@ -1144,12 +1144,12 @@
 	 
 	if(isapnp)
 	{
-		struct pci_dev *pdev = NULL;
+		struct pnp_dev *pdev = NULL;
 		for(indx = 0; indx <sizeof(bases)/sizeof(bases[0]);indx++)
 		{
 			if(bases[indx])
 				continue;
-			pdev = isapnp_find_dev(NULL, ISAPNP_VENDOR('A', 'D', 'P'), 
+			pdev = pnp_find_dev(NULL, ISAPNP_VENDOR('A', 'D', 'P'), 
 				ISAPNP_FUNCTION(0x1542), pdev);
 			if(pdev==NULL)
 				break;
@@ -1157,18 +1157,20 @@
 			 *	Activate the PnP card
 			 */
 			 
-			if(pdev->prepare(pdev)<0)
+			if(pnp_device_attach(pdev)<0)
 				continue;
-				
-			if(!(pdev->resource[0].flags&IORESOURCE_IO))
+			
+			if(pnp_activate_dev(pdev, NULL)<0) {
+				pnp_device_detach(pdev);
 				continue;
-				
-			pdev->resource[0].flags|=IORESOURCE_AUTO;
-
-			if(pdev->activate(pdev)<0)
+			}
+			
+			if(!pnp_port_valid(pdev, 0)) {
+				pnp_device_detach(pdev);
 				continue;
+			}
 				
-			bases[indx] = pdev->resource[0].start;
+			bases[indx] = pnp_port_start(pdev, 0);
 			
 			/* The card can be queried for its DMA, we have 
 			   the DMA set up that is enough */
diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c
--- a/drivers/scsi/esp.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/scsi/esp.c	Mon Jan 13 10:18:07 2003
@@ -1720,7 +1720,7 @@
 		 *           ID bit on the data bus even though the ESP is
 		 *           at ID 7 and is the obvious winner for any
 		 *           arbitration.  The ESP is a poor sport and refuses
-		 *           to lose arbitration, it will continue indefinately
+		 *           to lose arbitration, it will continue indefinitely
 		 *           trying to arbitrate for the bus and can only be
 		 *           stopped via a chip reset or SCSI bus reset.
 		 *           Therefore _no_ disconnects for SCSI1 targets
diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
--- a/drivers/scsi/fdomain.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/scsi/fdomain.c	Mon Jan 13 10:18:06 2003
@@ -301,7 +301,7 @@
 
 /* START OF USER DEFINABLE OPTIONS */
 
-#define DEBUG            1	/* Enable debugging output */
+#define DEBUG            0	/* Enable debugging output */
 #define ENABLE_PARITY    1	/* Enable SCSI Parity */
 #define FIFO_COUNT       2	/* Number of 512 byte blocks before INTR */
 #define DO_DETECT        0	/* Do device detection here (see scsi.c) */
diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
--- a/drivers/scsi/g_NCR5380.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/scsi/g_NCR5380.c	Mon Jan 13 10:18:05 2003
@@ -314,30 +314,34 @@
 		overrides[0].board = BOARD_DTC3181E;
 
 	if (!current_override && isapnp_present()) {
-		struct pci_dev *dev = NULL;
+		struct pnp_dev *dev = NULL;
 		count = 0;
-		while ((dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) {
+		while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) {
 			if (count >= NO_OVERRIDES)
 				break;
-			if (!dev->active && dev->prepare(dev) < 0) {
-				printk(KERN_ERR "dtc436e probe: prepare failed\n");
+			if (pnp_device_attach(dev) < 0) {
+				printk(KERN_ERR "dtc436e probe: attach failed\n");
 				continue;
 			}
-			if (!(dev->resource[0].flags & IORESOURCE_IO))
-				continue;
-			if (!dev->active && dev->activate(dev) < 0) {
+			if (pnp_activate_dev(dev, NULL) < 0) {
 				printk(KERN_ERR "dtc436e probe: activate failed\n");
+				pnp_device_detach(dev);
+				continue;
+			}
+			if (!pnp_port_valid(dev, 0)) {
+				printk(KERN_ERR "dtc436e probe: no valid port\n");
+				pnp_device_detach(dev);
 				continue;
 			}
-			if (dev->irq_resource[0].flags & IORESOURCE_IRQ)
-				overrides[count].irq = dev->irq_resource[0].start;
+			if (pnp_irq_valid(dev, 0))
+				overrides[count].irq = pnp_irq(dev, 0);
 			else
 				overrides[count].irq = IRQ_NONE;
-			if (dev->dma_resource[0].flags & IORESOURCE_DMA)
-				overrides[count].dma = dev->dma_resource[0].start;
+			if (pnp_dma_valid(dev, 0))
+				overrides[count].dma = pnp_dma(dev, 0);
 			else
 				overrides[count].dma = DMA_NONE;
-			overrides[count].NCR5380_map_name = (NCR5380_map_type) dev->resource[0].start;
+			overrides[count].NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0);
 			overrides[count].board = BOARD_DTC3181E;
 			count++;
 		}
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/scsi/ips.c	Mon Jan 13 10:18:05 2003
@@ -186,7 +186,6 @@
 #ifdef MODULE
    static char *ips = NULL;
    MODULE_PARM(ips, "s");
-   MODULE_LICENSE("GPL");
 #endif
 
 /*
@@ -6974,9 +6973,7 @@
 }
 
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,9)
 MODULE_LICENSE("GPL");
-#endif
 
 /*
  * Overrides for Emacs so that we almost follow Linus's tabbing style.
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/scsi/scsi_sysfs.c	Mon Jan 13 10:18:05 2003
@@ -23,20 +23,16 @@
  * Return:
  *     number of bytes written into page.
  **/
-static ssize_t scsi_host_class_name_show(struct device *dev, char *page,
-	size_t count, loff_t off)
+static ssize_t scsi_host_class_name_show(struct device *dev, char *page)
 {
 	struct Scsi_Host *shost;
 
-	if (off)
-		return 0;
-
 	shost = to_scsi_host(dev);
 
 	if (!shost)
 		return 0;
 	
-	return snprintf(page, count, "scsi%d\n", shost->host_no);
+	return snprintf(page, 20, "scsi%d\n", shost->host_no);
 }
 
 DEVICE_ATTR(class_name, S_IRUGO, scsi_host_class_name_show, NULL);
@@ -138,13 +134,11 @@
  */
 #define show_function(field, format_string)				\
 static ssize_t								\
-show_##field (struct device *dev, char *buf, size_t count, loff_t off)	\
+show_##field (struct device *dev, char *buf)				\
 {									\
 	struct scsi_device *sdev;					\
-	if (off)							\
-		return 0;						\
 	sdev = to_scsi_device(dev);					\
-	return snprintf (buf, count, format_string, sdev->field);	\
+	return snprintf (buf, 20, format_string, sdev->field);		\
 }									\
 
 /*
@@ -164,14 +158,12 @@
 	show_function(field, format_string)				\
 									\
 static ssize_t								\
-store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\
+store_##field (struct device *dev, const char *buf)			\
 {									\
 	struct scsi_device *sdev;					\
-									\
-	if (off)							\
-		return 0;						\
 	sdev = to_scsi_device(dev);					\
-	return snscanf (buf, count, format_string, &sdev->field);	\
+	snscanf (buf, 20, format_string, &sdev->field);			\
+	return strlen(buf);						\
 }									\
 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, store_##field)
 
@@ -183,18 +175,15 @@
 	show_function(field, "%d\n")					\
 									\
 static ssize_t								\
-store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\
+store_##field (struct device *dev, const char *buf)			\
 {									\
 	int ret;							\
 	struct scsi_device *sdev;					\
-									\
-	if (off)							\
-		return 0;						\
 	ret = scsi_sdev_check_buf_bit(buf);				\
 	if (ret >= 0)	{						\
 		sdev = to_scsi_device(dev);				\
 		sdev->field = ret;					\
-		ret = count;						\
+		ret = strlen(buf);					\
 	}								\
 	return ret;							\
 }									\
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/scsi/sg.c	Mon Jan 13 10:18:06 2003
@@ -1350,20 +1350,18 @@
 
 /* Driverfs file support */
 static ssize_t
-sg_device_kdev_read(struct device *driverfs_dev, char *page,
-		    size_t count, loff_t off)
+sg_device_kdev_read(struct device *driverfs_dev, char *page)
 {
 	Sg_device *sdp = list_entry(driverfs_dev, Sg_device, sg_driverfs_dev);
-	return off ? 0 : sprintf(page, "%x\n", MKDEV(sdp->disk->major,
-						     sdp->disk->first_minor));
+	return sprintf(page, "%x\n", MKDEV(sdp->disk->major,
+					   sdp->disk->first_minor));
 }
 static DEVICE_ATTR(kdev,S_IRUGO,sg_device_kdev_read,NULL);
 
 static ssize_t
-sg_device_type_read(struct device *driverfs_dev, char *page,
-		    size_t count, loff_t off)
+sg_device_type_read(struct device *driverfs_dev, char *page)
 {
-	return off ? 0 : sprintf(page, "CHR\n");
+	return sprintf(page, "CHR\n");
 }
 
 static DEVICE_ATTR(type,S_IRUGO,sg_device_type_read,NULL);
diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
--- a/drivers/scsi/sym53c416.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/scsi/sym53c416.c	Mon Jan 13 10:18:05 2003
@@ -635,7 +635,7 @@
 	struct Scsi_Host * shpnt = NULL;
 	int i;
 	int count;
-	struct pci_dev *idev = NULL;
+	struct pnp_dev *idev = NULL;
 	
 #ifdef MODULE
 	int ints[3];
@@ -669,26 +669,27 @@
 	printk(KERN_INFO "sym53c416.c: %s\n", VERSION_STRING);
 
 	for (i=0; id_table[i].vendor != 0; i++) {
-		while((idev=isapnp_find_dev(NULL, id_table[i].vendor,
+		while((idev=pnp_find_dev(NULL, id_table[i].vendor,
 					id_table[i].function, idev))!=NULL)
 		{
 			int i[3];
 
-			if(idev->prepare(idev)<0)
+			if(pnp_device_attach(idev)<0)
 			{
-				printk(KERN_WARNING "sym53c416: unable to prepare PnP card.\n");
+				printk(KERN_WARNING "sym53c416: unable to attach PnP device.\n");
 				continue;
 			}
-			if(idev->activate(idev)<0)
+			if(pnp_activate_dev(idev, NULL)<0)
 			{
-				printk(KERN_WARNING "sym53c416: unable to activate PnP card.\n");
+				printk(KERN_WARNING "sym53c416: unable to activate PnP device.\n");
+				pnp_device_detach(idev);
 				continue;
 			
 			}
 
 			i[0] = 2;
-			i[1] = idev->resource[0].start;
- 			i[2] = idev->irq_resource[0].start;
+			i[1] = pnp_port_start(idev, 0);
+ 			i[2] = pnp_irq(idev, 0);
 
 			printk(KERN_INFO "sym53c416: ISAPnP card found and configured at 0x%X, IRQ %d.\n",
 				i[1], i[2]);
diff -Nru a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
--- a/drivers/serial/sunzilog.c	Mon Jan 13 10:18:07 2003
+++ b/drivers/serial/sunzilog.c	Mon Jan 13 10:18:07 2003
@@ -112,10 +112,7 @@
 
 #define ZILOG_CHANNEL_FROM_PORT(PORT)	((struct zilog_channel *)((PORT)->membase))
 #define UART_ZILOG(PORT)		((struct uart_sunzilog_port *)(PORT))
-#define SUNZILOG_GET_CURR_REG(PORT, REGNUM)		\
-	(UART_ZILOG(PORT)->curregs[REGNUM])
-#define SUNZILOG_SET_CURR_REG(PORT, REGNUM, REGVAL)	\
-	((UART_ZILOG(PORT)->curregs[REGNUM]) = (REGVAL))
+
 #define ZS_IS_KEYB(UP)	((UP)->flags & SUNZILOG_FLAG_CONS_KEYB)
 #define ZS_IS_MOUSE(UP)	((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE)
 #define ZS_IS_CONS(UP)	((UP)->flags & SUNZILOG_FLAG_IS_CONS)
@@ -278,8 +275,7 @@
 	up->cflag &= ~CBAUD;
 	up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud);
 
-	brg = BPS_TO_BRG(new_baud,
-			 (ZS_CLOCK / ZS_CLOCK_DIVISOR));
+	brg = BPS_TO_BRG(new_baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 	up->curregs[R12] = (brg & 0xff);
 	up->curregs[R13] = (brg >> 8) & 0xff;
 	sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(&up->port));
@@ -332,7 +328,7 @@
 				   struct zilog_channel *channel,
 				   struct pt_regs *regs)
 {
-	struct tty_struct *tty = up->port.info->tty;
+	struct tty_struct *tty = up->port.info->tty;	/* XXX info==NULL? */
 
 	while (1) {
 		unsigned char ch, r1;
@@ -340,7 +336,7 @@
 		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
 			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return;
+				return;		/* XXX Ignores SysRq when we need it most. Fix. */
 		}
 
 		r1 = read_zsreg(channel, R1);
@@ -474,7 +470,7 @@
 static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
 				    struct zilog_channel *channel)
 {
-	struct circ_buf *xmit = &up->port.info->xmit;
+	struct circ_buf *xmit;
 
 	if (ZS_IS_CONS(up)) {
 		unsigned char status = sbus_readb(&channel->control);
@@ -499,7 +495,12 @@
 
 	if (ZS_TX_STOPPED(up)) {
 		up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
-		goto disable_tx_int;
+
+		sbus_writeb(RES_Tx_P, &channel->control);
+		ZSDELAY();
+		ZS_WSYNC(channel);
+
+		return;
 	}
 
 	if (up->port.x_char) {
@@ -512,8 +513,11 @@
 		return;
 	}
 
+	if (up->port.info == NULL)
+		goto ack_tx_int;
+	xmit = &up->port.info->xmit;
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port))
-		goto disable_tx_int;
+		goto ack_tx_int;
 
 	sbus_writeb(xmit->buf[xmit->tail], &channel->data);
 	ZSDELAY();
@@ -525,12 +529,15 @@
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&up->port);
 
-	if (!uart_circ_empty(xmit))
-		return;
+	if (uart_circ_empty(xmit))
+		goto ack_tx_int;
 
-disable_tx_int:
-	up->curregs[R5] &= ~TxENAB;
-	write_zsreg(ZILOG_CHANNEL_FROM_PORT(&up->port), R5, up->curregs[R5]);
+	return;
+
+ack_tx_int:
+	sbus_writeb(RES_Tx_P, &channel->control);
+	ZSDELAY();
+	ZS_WSYNC(channel);
 }
 
 static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -543,7 +550,7 @@
 		unsigned char r3;
 
 		spin_lock(&up->port.lock);
-		r3 = read_zsreg(channel, 3);
+		r3 = read_zsreg(channel, R3);
 
 		/* Channel A */
 		if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
@@ -679,13 +686,6 @@
 	up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
 	up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
 
-	/* Enable the transmitter.  */
-	if (!(up->curregs[R5] & TxENAB)) {
-		/* NOTE: Not subject to 'transmitter active' rule.  */ 
-		up->curregs[R5] |= TxENAB;
-		write_zsreg(channel, R5, up->curregs[R5]);
-	}
-
 	status = sbus_readb(&channel->control);
 	ZSDELAY();
 
@@ -785,39 +785,69 @@
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static int sunzilog_startup(struct uart_port *port)
+static void __sunzilog_startup(struct uart_sunzilog_port *up)
 {
-	struct uart_sunzilog_port *up = UART_ZILOG(port);
 	struct zilog_channel *channel;
-	unsigned long flags;
 
-	spin_lock_irqsave(&port->lock, flags);
-
-	channel = ZILOG_CHANNEL_FROM_PORT(port);
+	channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
 	up->prev_status = sbus_readb(&channel->control);
 
 	/* Enable receiver and transmitter.  */
 	up->curregs[R3] |= RxENAB;
 	up->curregs[R5] |= TxENAB;
 
-	/* Enable RX and status interrupts.  TX interrupts are enabled
-	 * as needed.
-	 */
-	up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx;
-	up->curregs[R9] |= MIE;
+	up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
 	sunzilog_maybe_update_regs(up, channel);
+}
 
-	spin_unlock_irqrestore(&port->lock, flags);
+static int sunzilog_startup(struct uart_port *port)
+{
+	struct uart_sunzilog_port *up = UART_ZILOG(port);
+	unsigned long flags;
 
+	if (ZS_IS_CONS(up))
+		return 0;
+
+	spin_lock_irqsave(&port->lock, flags);
+	__sunzilog_startup(up);
+	spin_unlock_irqrestore(&port->lock, flags);
 	return 0;
 }
 
+/*
+ * The test for ZS_IS_CONS is explained by the following e-mail:
+ *****
+ * From: Russell King <rmk@arm.linux.org.uk>
+ * Date: Sun, 8 Dec 2002 10:18:38 +0000
+ *
+ * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote:
+ * > I boot my 2.5 boxes using "console=ttyS0,9600" argument,
+ * > and I noticed that something is not right with reference
+ * > counting in this case. It seems that when the console
+ * > is open by kernel initially, this is not accounted
+ * > as an open, and uart_startup is not called.
+ *
+ * That is correct.  We are unable to call uart_startup when the serial
+ * console is initialised because it may need to allocate memory (as
+ * request_irq does) and the memory allocators may not have been
+ * initialised.
+ *
+ * 1. initialise the port into a state where it can send characters in the
+ *    console write method.
+ *
+ * 2. don't do the actual hardware shutdown in your shutdown() method (but
+ *    do the normal software shutdown - ie, free irqs etc)
+ *****
+ */
 static void sunzilog_shutdown(struct uart_port *port)
 {
 	struct uart_sunzilog_port *up = UART_ZILOG(port);
 	struct zilog_channel *channel;
 	unsigned long flags;
 
+	if (ZS_IS_CONS(up))
+		return;
+
 	spin_lock_irqsave(&port->lock, flags);
 
 	channel = ZILOG_CHANNEL_FROM_PORT(port);
@@ -829,7 +859,6 @@
 	/* Disable all interrupts and BRK assertion.  */
 	up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
 	up->curregs[R5] &= ~SND_BRK;
-	up->curregs[R9] &= ~MIE;
 	sunzilog_maybe_update_regs(up, channel);
 
 	spin_unlock_irqrestore(&port->lock, flags);
@@ -843,18 +872,15 @@
 		       unsigned int iflag, int brg)
 {
 
-	/* Don't modify MIE. */
-	up->curregs[R9] |= NV;
-
 	up->curregs[R10] = NRZ;
-	up->curregs[11] = TCBR | RCBR;
+	up->curregs[R11] = TCBR | RCBR;
 
 	/* Program BAUD and clock source. */
-	up->curregs[4] &= ~XCLK_MASK;
-	up->curregs[4] |= X16CLK;
-	up->curregs[12] = brg & 0xff;
-	up->curregs[13] = (brg >> 8) & 0xff;
-	up->curregs[14] = BRSRC | BRENAB;
+	up->curregs[R4] &= ~XCLK_MASK;
+	up->curregs[R4] |= X16CLK;
+	up->curregs[R12] = brg & 0xff;
+	up->curregs[R13] = (brg >> 8) & 0xff;
+	up->curregs[R14] = BRSRC | BRENAB;
 
 	/* Character size, stop bits, and parity. */
 	up->curregs[3] &= ~RxN_MASK;
@@ -1027,7 +1053,7 @@
 		alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout *));
 
 	if (sunzilog_port_table == NULL || sunzilog_chip_regs == NULL) {
-		prom_printf("sunzilog_init: Cannot alloc SunZilog tables.\n");
+		prom_printf("SunZilog: Cannot allocate tables.\n");
 		prom_halt();
 	}
 }
@@ -1333,7 +1359,7 @@
 	unsigned long flags;
 	int baud, brg;
 
-	printk("Console: ttyS%d (Zilog8530)\n",
+	printk("Console: ttyS%d (SunZilog)\n",
 	       (sunzilog_reg.minor - 64) + con->index);
 
 	/* Get firmware console settings.  */
@@ -1356,21 +1382,15 @@
 
 	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 
-	/*
-	 * Temporary fix.
-	 */
-	spin_lock_init(&up->port.lock);
-
 	spin_lock_irqsave(&up->port.lock, flags);
 
 	up->curregs[R15] = BRKIE;
-
 	sunzilog_convert_to_zs(up, con->cflag, 0, brg);
 
-	spin_unlock_irqrestore(&up->port.lock, flags);
-
 	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
-	sunzilog_startup(&up->port);
+	__sunzilog_startup(up);
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
 
 	return 0;
 }
@@ -1401,6 +1421,7 @@
 		return 0;
 
 	sunzilog_console.index = i;
+	sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
 	register_console(&sunzilog_console);
 	return 0;
 }
@@ -1457,6 +1478,12 @@
 	struct zilog_layout *rp;
 	int channel, chip;
 
+	/*
+	 * Temporary fix.
+	 */
+	for (channel = 0; channel < NUM_CHANNELS - 1; channel++)
+		spin_lock_init(&sunzilog_port_table[channel].port.lock);
+
 	sunzilog_irq_chain = up = &sunzilog_port_table[0];
 	for (channel = 0; channel < NUM_CHANNELS - 1; channel++)
 		up[channel].next = &up[channel + 1];
@@ -1504,7 +1531,7 @@
 		up->cflag = B4800 | CS8 | CLOCAL | CREAD;
 		baud = 4800;
 	}
-	printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a Zilog8530\n",
+	printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a SunZilog\n",
 	       channel, up->port.membase, __irq_itoa(zilog_irq));
 
 	up->curregs[R15] = BRKIE;
@@ -1534,10 +1561,8 @@
 	serio_register_port(&up->serio);
 #endif
 
-	spin_unlock(&up->port.lock);
 	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
-	sunzilog_startup(&up->port);
-	spin_lock(&up->port.lock);
+	__sunzilog_startup(up);
 }
 
 static void __init sunzilog_init_hw(void)
@@ -1560,8 +1585,6 @@
 
 		if (i == KEYBOARD_LINE || i == MOUSE_LINE) {
 			sunzilog_init_kbdms(up, i);
-		} else if (ZS_IS_CONS(up)) {
-			/* sunzilog_console_setup takes care of this */
 		} else {
 			/* Normal serial TTY. */
 			up->parity_mask = 0xff;
@@ -1572,11 +1595,12 @@
 			up->curregs[R10] = NRZ;
 			up->curregs[R11] = TCBR | RCBR;
 			baud = 9600;
-			brg = BPS_TO_BRG(baud, (ZS_CLOCK / ZS_CLOCK_DIVISOR));
+			brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 			up->curregs[R12] = (brg & 0xff);
 			up->curregs[R13] = (brg >> 8) & 0xff;
 			up->curregs[R14] = BRSRC | BRENAB;
-			sunzilog_maybe_update_regs(up, channel);
+			__load_zsregs(channel, up->curregs);
+			write_zsreg(channel, R9, up->curregs[R9]);
 		}
 
 		spin_unlock_irqrestore(&up->port.lock, flags);
diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
--- a/drivers/telephony/ixj.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/telephony/ixj.c	Mon Jan 13 10:18:05 2003
@@ -7574,8 +7574,8 @@
 				kfree(j->read_buffer);
 			if (j->write_buffer)
 				kfree(j->write_buffer);
-			if (j->dev && j->dev->deactivate)
-				j->dev->deactivate(j->dev);
+			if (j->dev)
+				pnp_device_detach(j->dev);
 			if (ixjdebug & 0x0002)
 				printk(KERN_INFO "IXJ: Unregistering /dev/phone%d from LTAPI\n", cnt);
 			phone_unregister_device(&j->p);
@@ -7700,7 +7700,7 @@
 {               
 	int probe = 0;
 	int func = 0x110;
-        struct pci_dev *dev = NULL, *old_dev = NULL;
+        struct pnp_dev *dev = NULL, *old_dev = NULL;
 
 	while (1) {
 		do {
@@ -7708,30 +7708,29 @@
 			int result;
 
 			old_dev = dev;
-			dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'),
+			dev = pnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'),
 					 ISAPNP_FUNCTION(func), old_dev);
-			if (!dev)
+			if (!dev || !dev->card)
 				break;
-			result = dev->prepare(dev);
+			result = pnp_device_attach(dev);
 			if (result < 0) {
-				printk("preparing failed %d \n", result);
+				printk("pnp attach failed %d \n", result);
 				break;
 			}
+			if (pnp_activate_dev(dev, NULL) < 0) {
+				printk("pnp activate failed (out of resources?)\n");
+				pnp_device_detach(dev);
+				return -ENOMEM;
+			}
 
-			if (!(dev->resource[0].flags & IORESOURCE_IO))
+			if (!pnp_port_valid(dev, 0)) {
+				pnp_device_detach(dev);
 				return -ENODEV;
-
-			dev->resource[0].flags |= IORESOURCE_AUTO;
-			if (func != 0x110)
-				dev->resource[1].flags |= IORESOURCE_AUTO;
-			if (dev->activate(dev) < 0) {
-				printk("isapnp configure failed (out of resources?)\n");
-				return -ENOMEM;
 			}
 
-			result = check_region(dev->resource[0].start, 16);
+			result = check_region(pnp_port_start(dev, 0), 16);
 			if (result) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", dev->resource[0].start);
+				printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", pnp_port_start(dev, 0));
 				break;
 			}
 
@@ -7739,7 +7738,7 @@
 			request_region(j->DSPbase, 16, "ixj DSP");
 
 			if (func != 0x110)
-				j->XILINXbase = dev->resource[1].start;	/* get real port */
+				j->XILINXbase = pnp_port_start(dev, 1);	/* get real port */
 
 			switch (func) {
 			case (0x110):
@@ -7755,7 +7754,7 @@
 			j->board = *cnt;
 			probe = ixj_selfprobe(j);
 			if(!probe) {
-				j->serial = dev->bus->serial;
+				j->serial = dev->card->serial;
 				j->dev = dev;
 				switch (func) {
 				case 0x110:
diff -Nru a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h
--- a/drivers/telephony/ixj.h	Mon Jan 13 10:18:07 2003
+++ b/drivers/telephony/ixj.h	Mon Jan 13 10:18:07 2003
@@ -1182,11 +1182,7 @@
 	atomic_t DSPWrite;
 	struct phone_capability caplist[30];
 	unsigned int caps;
-#if LINUX_VERSION_CODE < 0x020400
 	struct pnp_dev *dev;
-#else
-	struct pci_dev *dev;
-#endif
 	unsigned int cardtype;
 	unsigned int rec_codec;
 	unsigned int cid_rec_codec;
diff -Nru a/drivers/usb/core/driverfs.c b/drivers/usb/core/driverfs.c
--- a/drivers/usb/core/driverfs.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/usb/core/driverfs.c	Mon Jan 13 10:18:05 2003
@@ -25,13 +25,10 @@
 /* Active configuration fields */
 #define usb_actconfig_attr(field, format_string)			\
 static ssize_t								\
-show_##field (struct device *dev, char *buf, size_t count, loff_t off)	\
+show_##field (struct device *dev, char *buf)				\
 {									\
 	struct usb_device *udev;					\
 									\
-	if (off)							\
-		return 0;						\
-									\
 	udev = to_usb_device (dev);					\
 	return sprintf (buf, format_string, udev->actconfig->desc.field); \
 }									\
@@ -43,13 +40,11 @@
 usb_actconfig_attr (bMaxPower, "%3dmA\n")
 
 /* String fields */
-static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off)
+static ssize_t show_product (struct device *dev, char *buf)
 {
 	struct usb_device *udev;
 	int len;
 
-	if (off)
-		return 0;
 	udev = to_usb_device (dev);
 
 	len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
@@ -62,13 +57,11 @@
 static DEVICE_ATTR(product,S_IRUGO,show_product,NULL);
 
 static ssize_t
-show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
+show_manufacturer (struct device *dev, char *buf)
 {
 	struct usb_device *udev;
 	int len;
 
-	if (off)
-		return 0;
 	udev = to_usb_device (dev);
 
 	len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
@@ -81,13 +74,11 @@
 static DEVICE_ATTR(manufacturer,S_IRUGO,show_manufacturer,NULL);
 
 static ssize_t
-show_serial (struct device *dev, char *buf, size_t count, loff_t off)
+show_serial (struct device *dev, char *buf)
 {
 	struct usb_device *udev;
 	int len;
 
-	if (off)
-		return 0;
 	udev = to_usb_device (dev);
 
 	len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
@@ -100,13 +91,11 @@
 static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL);
 
 static ssize_t
-show_speed (struct device *dev, char *buf, size_t count, loff_t off)
+show_speed (struct device *dev, char *buf)
 {
 	struct usb_device *udev;
 	char *speed;
 
-	if (off)
-		return 0;
 	udev = to_usb_device (dev);
 
 	switch (udev->speed) {
@@ -130,13 +119,10 @@
 /* Descriptor fields */
 #define usb_descriptor_attr(field, format_string)			\
 static ssize_t								\
-show_##field (struct device *dev, char *buf, size_t count, loff_t off)	\
+show_##field (struct device *dev, char *buf)				\
 {									\
 	struct usb_device *udev;					\
 									\
-	if (off)							\
-		return 0;						\
-									\
 	udev = to_usb_device (dev);					\
 	return sprintf (buf, format_string, udev->descriptor.field);	\
 }									\
@@ -185,13 +171,10 @@
 /* Interface fields */
 #define usb_intf_attr(field, format_string)				\
 static ssize_t								\
-show_##field (struct device *dev, char *buf, size_t count, loff_t off)	\
+show_##field (struct device *dev, char *buf)				\
 {									\
 	struct usb_interface *intf;					\
 	int alt;							\
-									\
-	if (off)							\
-		return 0;						\
 									\
 	intf = to_usb_interface (dev);					\
 	alt = intf->act_altsetting;					\
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Mon Jan 13 10:18:06 2003
+++ b/drivers/usb/host/ohci-sa1111.c	Mon Jan 13 10:18:06 2003
@@ -185,7 +185,6 @@
 		goto err1;
 	}
 
-	set_irq_type(hcd->irq, IRQT_RISING);
 	retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
 			      hcd->description, hcd);
 	if (retval != 0) {
@@ -399,7 +398,7 @@
 
 static struct sa1111_driver ohci_hcd_sa1111_driver = {
 	.drv = {
-		.name		= "SA1111 OHCI",
+		.name		= "sa1111-ohci",
 		.bus		= &sa1111_bus_type,
 		.probe		= ohci_hcd_sa1111_drv_probe,
 		.remove		= ohci_hcd_sa1111_drv_remove,
diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
--- a/drivers/video/sa1100fb.c	Mon Jan 13 10:18:05 2003
+++ b/drivers/video/sa1100fb.c	Mon Jan 13 10:18:05 2003
@@ -170,10 +170,11 @@
 #include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
-#include <linux/pm.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -183,12 +184,6 @@
 #include <asm/arch/assabet.h>
 #include <asm/arch/shannon.h>
 
-#include <video/fbcon.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-
 /*
  * debugging?
  */
@@ -806,15 +801,9 @@
 {
 	int ret = 0;
 	switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB4
 	case 4:  ret = 0 << 12;	break;
-#endif
-#ifdef FBCON_HAS_CFB8
 	case 8:  ret = 1 << 12; break;
-#endif
-#ifdef FBCON_HAS_CFB16
 	case 16: ret = 2 << 12; break;
-#endif
 	}
 	return ret;
 }
@@ -875,7 +864,7 @@
 		 * according to the RGB bitfield information.
 		 */
 		if (regno < 16) {
-			u16 *pal = fbi->fb.pseudo_palette;
+			u32 *pal = fbi->fb.pseudo_palette;
 
 			val  = chan_to_field(red, &fbi->fb.var.red);
 			val |= chan_to_field(green, &fbi->fb.var.green);
@@ -935,21 +924,15 @@
 
 	DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
 	switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB4
 	case 4:
 		rgbidx = RGB_8;
 		break;
-#endif
-#ifdef FBCON_HAS_CFB8
 	case 8:
 		rgbidx = RGB_8;
 		break;
-#endif
-#ifdef FBCON_HAS_CFB16
 	case 16:
 		rgbidx = RGB_16;
 		break;
-#endif
 	default:
 		return -EINVAL;
 	}
@@ -1023,6 +1006,8 @@
 		fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
 	}
 
+	fbi->fb.fix.line_length = var->xres_virtual *
+				  var->bits_per_pixel / 8;
 	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
 
 	palette_mem_size = fbi->palette_size * sizeof(u16);
@@ -1048,46 +1033,22 @@
 	return 0;
 }
 
-/*
- * sa1100fb_set_var():
- *	Set the user defined part of the display for the specified console
- */
-static int
-sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-	int ret, act;
-
-	act = var->activate & FB_ACTIVATE_MASK;
-
-	ret = gen_set_var(var, con, info);
-
-	if (ret == 0 && act & FB_ACTIVATE_NOW) {
-		struct display *display = (con < 0) ? info->disp : fb_display + con;
-
-		/*
-		 * fbcon assumes too much.
-		 */
-		display->can_soft_blank = 1;
-	}
-
-	return ret;
-}
-
+#if 0
 static int
 sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 		  struct fb_info *info)
 {
 	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-	struct display *disp = (con < 0) ? info->disp : (fb_display + con);
 
 	/*
 	 * Make sure the user isn't doing something stupid.
 	 */
-	if (!kspc && (disp->var.bits_per_pixel == 16 || fbi->cmap_static))
+	if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->cmap_static))
 		return -EINVAL;
 
 	return gen_set_cmap(cmap, kspc, con, info);
 }
+#endif
 
 /*
  * Formal definition of the VESA spec:
@@ -1129,8 +1090,7 @@
 	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
 	int i;
 
-	DPRINTK("sa1100fb_blank: blank=%d info->modename=%s\n", blank,
-		fbi->fb.modename);
+	DPRINTK("sa1100fb_blank: blank=%d\n", blank);
 
 	switch (blank) {
 	case VESA_POWERDOWN:
@@ -1156,19 +1116,14 @@
 	.owner		= THIS_MODULE,
 	.fb_check_var	= sa1100fb_check_var,
 	.fb_set_par	= sa1100fb_set_par,
-	.fb_set_var	= sa1100fb_set_var,
-	.fb_get_cmap	= gen_get_cmap,
-	.fb_set_cmap	= sa1100fb_set_cmap,
+//	.fb_set_cmap	= sa1100fb_set_cmap,
 	.fb_setcolreg	= sa1100fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
 	.fb_blank	= sa1100fb_blank,
 };
 
-static int sa1100fb_updatevar(int con, struct fb_info *info)
-{
-	/* we don't support panning nor scrolling */
-	return 0;
-}
-
 /*
  * Calculate the PCD value from the clock rate (in picoseconds).
  * We take account of the PPCR clock setting.
@@ -1259,10 +1214,10 @@
 		(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
 		(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
 
-	DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
-	DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
-	DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
-	DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3);
+	DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0);
+	DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1);
+	DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2);
+	DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3);
 
 	half_screen_size = var->bits_per_pixel;
 	half_screen_size = half_screen_size * var->xres * var->yres / 16;
@@ -1382,8 +1337,8 @@
 		GPSR |= SHANNON_GPIO_DISP_EN;
 	}	
 
-	DPRINTK("DBAR1 = %p\n", DBAR1);
-	DPRINTK("DBAR2 = %p\n", DBAR2);
+	DPRINTK("DBAR1 = 0x%08x\n", DBAR1);
+	DPRINTK("DBAR2 = 0x%08x\n", DBAR2);
 	DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
 	DPRINTK("LCCR1 = 0x%08x\n", LCCR1);
 	DPRINTK("LCCR2 = 0x%08x\n", LCCR2);
@@ -1465,6 +1420,12 @@
 
 	old_state = fbi->state;
 
+	/*
+	 * Hack around fbcon initialisation.
+	 */
+	if (old_state == C_STARTUP && state == C_REENABLE)
+		state = C_ENABLE;
+
 	switch (state) {
 	case C_DISABLE_CLKCHANGE:
 		/*
@@ -1563,6 +1524,7 @@
  */
 static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
 {
+#if 0
 	unsigned int min_period = (unsigned int)-1;
 	int i;
 
@@ -1585,6 +1547,12 @@
 	}
 
 	return min_period;
+#else
+	/*
+	 * FIXME: we need to verify _all_ consoles.
+	 */
+	return sa1100fb_display_dma_period(&fbi->fb.var);
+#endif
 }
 
 /*
@@ -1633,30 +1601,29 @@
 
 #ifdef CONFIG_PM
 /*
- * Power management hook.  Note that we won't be called from IRQ context,
+ * Power management hooks.  Note that we won't be called from IRQ context,
  * unlike the blank functions above, so we may sleep.
  */
-static int
-sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
+static int sa1100fb_suspend(struct device *dev, u32 state, u32 level)
 {
-	struct sa1100fb_info *fbi = pm_dev->data;
+	struct sa1100fb_info *fbi = dev_get_drvdata(dev);
 
-	DPRINTK("pm_callback: %d\n", req);
+	if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
+		set_ctrlr_state(fbi, C_DISABLE_PM);
+	return 0;
+}
 
-	if (req == PM_SUSPEND || req == PM_RESUME) {
-		int state = (int)data;
+static int sa1100fb_resume(struct device *dev, u32 level)
+{
+	struct sa1100fb_info *fbi = dev_get_drvdata(dev);
 
-		if (state == 0) {
-			/* Enter D0. */
-			set_ctrlr_state(fbi, C_ENABLE_PM);
-		} else {
-			/* Enter D1-D3.  Disable the LCD controller.  */
-			set_ctrlr_state(fbi, C_DISABLE_PM);
-		}
-	}
-	DPRINTK("done\n");
+	if (level == RESUME_ENABLE)
+		set_ctrlr_state(fbi, C_ENABLE_PM);
 	return 0;
 }
+#else
+#define sa1100fb_suspend	NULL
+#define sa1100fb_resume		NULL
 #endif
 
 /*
@@ -1675,7 +1642,7 @@
 	 */
 	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
 	fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
-					&fbi->map_dma);
+					&fbi->map_dma, PTE_BUFFERABLE);
 
 	if (fbi->map_cpu) {
 		fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
@@ -1697,12 +1664,12 @@
 	struct sa1100fb_mach_info *inf;
 	struct sa1100fb_info *fbi;
 
-	fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(struct display) +
-		      sizeof(u16) * 16, GFP_KERNEL);
+	fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
+		      GFP_KERNEL);
 	if (!fbi)
 		return NULL;
 
-	memset(fbi, 0, sizeof(struct sa1100fb_info) + sizeof(struct display));
+	memset(fbi, 0, sizeof(struct sa1100fb_info));
 
 	strcpy(fbi->fb.fix.id, SA1100_NAME);
 
@@ -1711,7 +1678,6 @@
 	fbi->fb.fix.xpanstep	= 0;
 	fbi->fb.fix.ypanstep	= 0;
 	fbi->fb.fix.ywrapstep	= 0;
-	fbi->fb.fix.line_length	= 0;
 	fbi->fb.fix.accel	= FB_ACCEL_NONE;
 
 	fbi->fb.var.nonstd	= 0;
@@ -1721,19 +1687,12 @@
 	fbi->fb.var.accel_flags	= 0;
 	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
 
-	strcpy(fbi->fb.modename, SA1100_NAME);
-	strcpy(fbi->fb.fontname, "Acorn8x8");
-
 	fbi->fb.fbops		= &sa1100fb_ops;
-	fbi->fb.changevar	= NULL;
-	fbi->fb.switch_con	= gen_switch;
-	fbi->fb.updatevar	= sa1100fb_updatevar;
 	fbi->fb.flags		= FBINFO_FLAG_DEFAULT;
 	fbi->fb.node		= NODEV;
 	fbi->fb.monspecs	= monspecs;
 	fbi->fb.currcon		= -1;
-	fbi->fb.disp		= (struct display *)(fbi + 1);
-	fbi->fb.pseudo_palette	= (void *)(fbi->fb.disp + 1);
+	fbi->fb.pseudo_palette	= (fbi + 1);
 
 	fbi->rgb[RGB_8]		= &rgb_8;
 	fbi->rgb[RGB_16]	= &def_rgb_16;
@@ -1771,11 +1730,10 @@
 	fbi->cmap_static		= inf->cmap_static;
 	fbi->lccr0			= inf->lccr0;
 	fbi->lccr3			= inf->lccr3;
-	fbi->state			= C_DISABLE;
+	fbi->state			= C_STARTUP;
 	fbi->task_state			= (u_char)-1;
 	fbi->fb.fix.smem_len		= fbi->max_xres * fbi->max_yres *
 					  fbi->max_bpp / 8;
-	fbi->fb.disp->inverse		= inf->cmap_inverse;
 
 	init_waitqueue_head(&fbi->ctrlr_wait);
 	INIT_WORK(&fbi->task, sa1100fb_task, fbi);
@@ -1784,6 +1742,24 @@
 	return fbi;
 }
 
+static struct device_driver sa1100fb_driver = {
+	.name		= "sa1100fb",
+	.bus		= &system_bus_type,
+	.suspend	= sa1100fb_suspend,
+	.resume		= sa1100fb_resume,
+};
+
+static struct sys_device sa1100fb_dev = {
+	.name	= "LCD",
+	.id	= 0,
+	.root	= NULL,
+	.dev	= {
+		.name	= "Intel Corporation SA11x0 [LCD]",
+		.bus_id	= "b0100000",
+		.driver	= &sa1100fb_driver,
+	},
+};
+
 int __init sa1100fb_init(void)
 {
 	struct sa1100fb_info *fbi;
@@ -1792,11 +1768,16 @@
 	if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
 		return -EBUSY;
 
+	driver_register(&sa1100fb_driver);
+	sys_device_register(&sa1100fb_dev);
+
 	fbi = sa1100fb_init_fbinfo();
 	ret = -ENOMEM;
 	if (!fbi)
 		goto failed;
 
+	dev_set_drvdata(&sa1100fb_dev.dev, fbi);
+
 	/* Initialize video memory */
 	ret = sa1100fb_map_video_memory(fbi);
 	if (ret)
@@ -1824,21 +1805,16 @@
 	}
 #endif
 
-	sa1100fb_set_var(&fbi->fb.var, -1, &fbi->fb);
+	/*
+	 * This makes sure that our colour bitfield
+	 * descriptors are correctly initialised.
+	 */
+	sa1100fb_check_var(&fbi->fb.var, &fbi->fb);
 
 	ret = register_framebuffer(&fbi->fb);
 	if (ret < 0)
 		goto failed;
 
-#ifdef CONFIG_PM
-	/*
-	 * Note that the console registers this as well, but we want to
-	 * power down the display prior to sleeping.
-	 */
-	fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, sa1100fb_pm_callback);
-	if (fbi->pm)
-		fbi->pm->data = fbi;
-#endif
 #ifdef CONFIG_CPU_FREQ
 	fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
 	fbi->freq_policy.notifier_call = sa1100fb_freq_policy;
@@ -1846,17 +1822,14 @@
 	cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
 #endif
 
-	/*
-	 * Ok, now enable the LCD controller
-	 */
-	set_ctrlr_state(fbi, C_ENABLE);
-
 	/* This driver cannot be unloaded at the moment */
 	MOD_INC_USE_COUNT;
 
 	return 0;
 
 failed:
+	sys_device_unregister(&sa1100fb_dev);
+	driver_unregister(&sa1100fb_driver);
 	if (fbi)
 		kfree(fbi);
 	release_mem_region(0xb0100000, 0x10000);
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	Mon Jan 13 10:18:06 2003
+++ b/fs/bio.c	Mon Jan 13 10:18:06 2003
@@ -538,6 +538,8 @@
  *	Unmap a bio previously mapped by bio_map_user(). The @write_to_vm
  *	must be the same as passed into bio_map_user(). Must be called with
  *	a process context.
+ *
+ *	bio_unmap_user() may sleep.
  */
 void bio_unmap_user(struct bio *bio, int write_to_vm)
 {
@@ -561,7 +563,7 @@
 	 */
 	__bio_for_each_segment(bvec, bio, i, 0) {
 		if (write_to_vm)
-			set_page_dirty(bvec->bv_page);
+			set_page_dirty_lock(bvec->bv_page);
 
 		page_cache_release(bvec->bv_page);
 	}
@@ -601,7 +603,7 @@
 		struct page *page = bvec[i].bv_page;
 
 		if (page)
-			set_page_dirty(bvec[i].bv_page);
+			set_page_dirty_lock(bvec[i].bv_page);
 	}
 }
 
diff -Nru a/fs/compat.c b/fs/compat.c
--- a/fs/compat.c	Mon Jan 13 10:18:06 2003
+++ b/fs/compat.c	Mon Jan 13 10:18:06 2003
@@ -17,6 +17,9 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/fcntl.h>
+#include <linux/namei.h>
+#include <linux/file.h>
+#include <linux/vfs.h>
 
 #include <asm/uaccess.h>
 
@@ -100,4 +103,59 @@
 	err |= __put_user(kfl->l_len, &ufl->l_len);
 	err |= __put_user(kfl->l_pid, &ufl->l_pid);
 	return err;
+}
+
+static int put_compat_statfs(struct compat_statfs *ubuf, struct statfs *kbuf)
+{
+	if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
+	    __put_user(kbuf->f_type, &ubuf->f_type) ||
+	    __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
+	    __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
+	    __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
+	    __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
+	    __put_user(kbuf->f_files, &ubuf->f_files) ||
+	    __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
+	    __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
+	    __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
+	    __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ * The following statfs calls are copies of code from fs/open.c and
+ * should be checked against those from time to time
+ */
+asmlinkage long compat_sys_statfs(const char *path, struct compat_statfs *buf)
+{
+	struct nameidata nd;
+	int error;
+
+	error = user_path_walk(path, &nd);
+	if (!error) {
+		struct statfs tmp;
+		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
+		if (!error && put_compat_statfs(buf, &tmp))
+			error = -EFAULT;
+		path_release(&nd);
+	}
+	return error;
+}
+
+asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs *buf)
+{
+	struct file * file;
+	struct statfs tmp;
+	int error;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+	if (!error && put_compat_statfs(buf, &tmp))
+		error = -EFAULT;
+	fput(file);
+out:
+	return error;
 }
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	Mon Jan 13 10:18:06 2003
+++ b/fs/direct-io.c	Mon Jan 13 10:18:06 2003
@@ -343,7 +343,7 @@
 			struct page *page = bvec[page_no].bv_page;
 
 			if (dio->rw == READ)
-				set_page_dirty(page);
+				set_page_dirty_lock(page);
 			page_cache_release(page);
 		}
 		bio_put(bio);
diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
--- a/fs/hugetlbfs/inode.c	Mon Jan 13 10:18:07 2003
+++ b/fs/hugetlbfs/inode.c	Mon Jan 13 10:18:07 2003
@@ -297,7 +297,7 @@
 		goto do_expand;
 
 	inode->i_size = offset;
-	spin_lock(&mapping->i_shared_lock);
+	down(&mapping->i_shared_sem);
 	if (list_empty(&mapping->i_mmap) && list_empty(&mapping->i_mmap_shared))
 		goto out_unlock;
 	if (!list_empty(&mapping->i_mmap))
@@ -306,7 +306,7 @@
 		hugetlb_vmtruncate_list(&mapping->i_mmap_shared, pgoff);
 
 out_unlock:
-	spin_unlock(&mapping->i_shared_lock);
+	up(&mapping->i_shared_sem);
 	truncate_hugepages(mapping, offset);
 	return 0;
 
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Mon Jan 13 10:18:07 2003
+++ b/fs/inode.c	Mon Jan 13 10:18:07 2003
@@ -171,7 +171,7 @@
 	sema_init(&inode->i_sem, 1);
 	INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
 	rwlock_init(&inode->i_data.page_lock);
-	spin_lock_init(&inode->i_data.i_shared_lock);
+	init_MUTEX(&inode->i_data.i_shared_sem);
 	INIT_LIST_HEAD(&inode->i_data.private_list);
 	spin_lock_init(&inode->i_data.private_lock);
 	INIT_LIST_HEAD(&inode->i_data.i_mmap);
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Mon Jan 13 10:18:05 2003
+++ b/fs/namei.c	Mon Jan 13 10:18:05 2003
@@ -2128,8 +2128,10 @@
 	 * bloody create() on broken symlinks. Furrfu...
 	 */
 	name = __getname();
-	if (!name)
+	if (unlikely(!name)) {
+		path_release(nd);
 		return -ENOMEM;
+	}
 	strcpy(name, nd->last.name);
 	nd->last.name = name;
 	return 0;
diff -Nru a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
--- a/fs/nfsd/nfsproc.c	Mon Jan 13 10:18:05 2003
+++ b/fs/nfsd/nfsproc.c	Mon Jan 13 10:18:05 2003
@@ -250,11 +250,11 @@
 					/* this is probably a permission check..
 					 * at least IRIX implements perm checking on
 					 *   echo thing > device-special-file-or-pipe
-					 * by does a CREATE with type==0
+					 * by doing a CREATE with type==0
 					 */
 					nfserr = nfsd_permission(newfhp->fh_export,
 								 newfhp->fh_dentry,
-								 MAY_WRITE);
+								 MAY_WRITE|MAY_LOCAL_ACCESS);
 					if (nfserr && nfserr != nfserr_rofs)
 						goto out_unlock;
 				}
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Mon Jan 13 10:18:05 2003
+++ b/fs/nfsd/vfs.c	Mon Jan 13 10:18:05 2003
@@ -1515,11 +1515,11 @@
 		inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
 #endif
 
-	/* only care about readonly exports for files and
-	 * directories. links don't have meaningful write access,
-	 * and all else is local to the client
+	/* Normally we reject any write/sattr etc access on a read-only file
+	 * system.  But if it is IRIX doing check on write-access for a 
+	 * device special file, we ignore rofs.
 	 */
-	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) 
+	if (!(acc & MAY_LOCAL_ACCESS))
 		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
 			if (EX_RDONLY(exp) || IS_RDONLY(inode))
 				return nfserr_rofs;
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Mon Jan 13 10:18:07 2003
+++ b/fs/partitions/check.c	Mon Jan 13 10:18:07 2003
@@ -274,17 +274,17 @@
 
 struct part_attribute {
 	struct attribute attr;
-	ssize_t (*show)(struct hd_struct *,char *,size_t,loff_t);
+	ssize_t (*show)(struct hd_struct *,char *);
 };
 
-static ssize_t part_attr_show(struct kobject * kobj, struct attribute * attr,
-			      char * page, size_t count, loff_t off)
+static ssize_t 
+part_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
 {
 	struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
 	struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
 	ssize_t ret = 0;
 	if (part_attr->show)
-		ret = part_attr->show(p,page,count,off);
+		ret = part_attr->show(p,page);
 	return ret;
 }
 
@@ -292,30 +292,26 @@
 	.show	=	part_attr_show,
 };
 
-static ssize_t part_dev_read(struct hd_struct * p,
-			     char *page, size_t count, loff_t off)
+static ssize_t part_dev_read(struct hd_struct * p, char *page)
 {
 	struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
 	int part = p - disk->part + 1;
 	dev_t base = MKDEV(disk->major, disk->first_minor); 
-	return off ? 0 : sprintf(page, "%04x\n",base + part);
+	return sprintf(page, "%04x\n",base + part);
 }
-static ssize_t part_start_read(struct hd_struct * p,
-			       char *page, size_t count, loff_t off)
+static ssize_t part_start_read(struct hd_struct * p, char *page)
 {
-	return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
+	return sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
 }
-static ssize_t part_size_read(struct hd_struct * p,
-			      char *page, size_t count, loff_t off)
+static ssize_t part_size_read(struct hd_struct * p, char *page)
 {
-	return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
+	return sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
 }
-static ssize_t part_stat_read(struct hd_struct * p,
-			      char *page, size_t count, loff_t off)
+static ssize_t part_stat_read(struct hd_struct * p, char *page)
 {
-	return off ? 0 : sprintf(page, "%8u %8llu %8u %8llu\n",
-				p->reads, (unsigned long long)p->read_sectors,
-				p->writes, (unsigned long long)p->write_sectors);
+	return sprintf(page, "%8u %8llu %8u %8llu\n",
+		       p->reads, (unsigned long long)p->read_sectors,
+		       p->writes, (unsigned long long)p->write_sectors);
 }
 static struct part_attribute part_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
--- a/fs/sysfs/inode.c	Mon Jan 13 10:18:07 2003
+++ b/fs/sysfs/inode.c	Mon Jan 13 10:18:07 2003
@@ -72,6 +72,7 @@
 			init_special_inode(inode, mode, dev);
 			break;
 		case S_IFREG:
+			inode->i_size = PAGE_SIZE;
 			inode->i_fop = &sysfs_file_operations;
 			break;
 		case S_IFDIR:
@@ -153,27 +154,27 @@
  * These operations allow subsystems to have files that can be 
  * read/written. 
  */
-ssize_t subsys_attr_show(struct kobject * kobj, struct attribute * attr, 
-			 char * page, size_t count, loff_t off)
+static ssize_t 
+subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
 {
 	struct subsystem * s = to_subsys(kobj);
 	struct subsys_attribute * sattr = to_sattr(attr);
 	ssize_t ret = 0;
 
 	if (sattr->show)
-		ret = sattr->show(s,page,count,off);
+		ret = sattr->show(s,page);
 	return ret;
 }
 
-ssize_t subsys_attr_store(struct kobject * kobj, struct attribute * attr,
-			  const char * page, size_t count, loff_t off)
+static ssize_t 
+subsys_attr_store(struct kobject * kobj, struct attribute * attr, const char * page)
 {
 	struct subsystem * s = to_subsys(kobj);
 	struct subsys_attribute * sattr = to_sattr(attr);
 	ssize_t ret = 0;
 
 	if (sattr->store)
-		ret = sattr->store(s,page,count,off);
+		ret = sattr->store(s,page);
 	return ret;
 }
 
@@ -182,6 +183,73 @@
 	.store	= subsys_attr_store,
 };
 
+
+struct sysfs_buffer {
+	size_t			count;
+	loff_t			pos;
+	char			* page;
+	struct sysfs_ops	* ops;
+};
+
+
+/**
+ *	fill_read_buffer - allocate and fill buffer from object.
+ *	@file:		file pointer.
+ *	@buffer:	data buffer for file.
+ *
+ *	Allocate @buffer->page, if it hasn't been already, then call the
+ *	kobject's show() method to fill the buffer with this attribute's 
+ *	data. 
+ *	This is called only once, on the file's first read. 
+ */
+static int fill_read_buffer(struct file * file, struct sysfs_buffer * buffer)
+{
+	struct attribute * attr = file->f_dentry->d_fsdata;
+	struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
+	struct sysfs_ops * ops = buffer->ops;
+	int ret = 0;
+	size_t count;
+
+	if (!buffer->page)
+		buffer->page = (char *) __get_free_page(GFP_KERNEL);
+	if (!buffer->page)
+		return -ENOMEM;
+
+	count = ops->show(kobj,attr,buffer->page);
+	if (count >= 0)
+		buffer->count = count;
+	else
+		ret = count;
+	return ret;
+}
+
+
+/**
+ *	flush_read_buffer - push buffer to userspace.
+ *	@buffer:	data buffer for file.
+ *	@userbuf:	user-passed buffer.
+ *	@count:		number of bytes requested.
+ *	@ppos:		file position.
+ *
+ *	Copy the buffer we filled in fill_read_buffer() to userspace.
+ *	This is done at the reader's leisure, copying and advancing 
+ *	the amount they specify each time.
+ *	This may be called continuously until the buffer is empty.
+ */
+static int flush_read_buffer(struct sysfs_buffer * buffer, char * buf, 
+			     size_t count, loff_t * ppos)
+{
+	int error;
+
+	if (count > (buffer->count - *ppos))
+		count = buffer->count - *ppos;
+
+	error = copy_to_user(buf,buffer->page + *ppos,count);
+	if (!error)
+		*ppos += count;
+	return error ? error : count;
+}
+
 /**
  *	sysfs_read_file - read an attribute. 
  *	@file:	file pointer.
@@ -191,55 +259,79 @@
  *
  *	Userspace wants to read an attribute file. The attribute descriptor
  *	is in the file's ->d_fsdata. The target object is in the directory's
- *	->d_fsdata. 
+ *	->d_fsdata.
  *
- *	We allocate a %PAGE_SIZE buffer, and pass it to the object's ->show()
- *	method (along with the object). We loop doing this until @count is 
- *	satisfied, or ->show() returns %0. 
+ *	We call fill_read_buffer() to allocate and fill the buffer from the
+ *	object's show() method exactly once (if the read is happening from
+ *	the beginning of the file). That should fill the entire buffer with
+ *	all the data the object has to offer for that attribute.
+ *	We then call flush_read_buffer() to copy the buffer to userspace
+ *	in the increments specified.
  */
 
 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 sysfs_ops * ops = file->private_data;
-	struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
-	unsigned char *page;
+	struct sysfs_buffer * buffer = file->private_data;
 	ssize_t retval = 0;
 
-	if (count > PAGE_SIZE)
-		count = PAGE_SIZE;
+	if (!*ppos) {
+		if ((retval = fill_read_buffer(file,buffer)))
+			return retval;
+	}
+	pr_debug("%s: count = %d, ppos = %lld, buf = %s\n",
+		 __FUNCTION__,count,*ppos,buffer->page);
+	return flush_read_buffer(buffer,buf,count,ppos);
+}
+
+
+/**
+ *	fill_write_buffer - copy buffer from userspace.
+ *	@buffer:	data buffer for file.
+ *	@userbuf:	data from user.
+ *	@count:		number of bytes in @userbuf.
+ *
+ *	Allocate @buffer->page if it hasn't been already, then
+ *	copy the user-supplied buffer into it.
+ */
 
-	page = (unsigned char*)__get_free_page(GFP_KERNEL);
-	if (!page)
+static int 
+fill_write_buffer(struct sysfs_buffer * buffer, const char * buf, size_t count)
+{
+	int error;
+
+	if (!buffer->page)
+		buffer->page = (char *)__get_free_page(GFP_KERNEL);
+	if (!buffer->page)
 		return -ENOMEM;
 
-	while (count > 0) {
-		ssize_t len;
+	if (count >= PAGE_SIZE)
+		count = PAGE_SIZE - 1;
+	error = copy_from_user(buffer->page,buf,count);
+	return error ? error : count;
+}
 
-		len = ops->show(kobj,attr,page,count,*ppos);
 
-		if (len <= 0) {
-			if (len < 0)
-				retval = len;
-			break;
-		} else if (len > count)
-			len = count;
+/**
+ *	flush_write_buffer - push buffer to kobject.
+ *	@file:		file pointer.
+ *	@buffer:	data buffer for file.
+ *
+ *	Get the correct pointers for the kobject and the attribute we're
+ *	dealing with, then call the store() method for the attribute, 
+ *	passing the buffer that we acquired in fill_write_buffer().
+ */
 
-		if (copy_to_user(buf,page,len)) {
-			retval = -EFAULT;
-			break;
-		}
+static int flush_write_buffer(struct file * file, struct sysfs_buffer * buffer)
+{
+	struct attribute * attr = file->f_dentry->d_fsdata;
+	struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
+	struct sysfs_ops * ops = buffer->ops;
 
-		*ppos += len;
-		count -= len;
-		buf += len;
-		retval += len;
-	}
-	free_page((unsigned long)page);
-	return retval;
+	return ops->store(kobj,attr,buffer->page);
 }
 
+
 /**
  *	sysfs_write_file - write an attribute.
  *	@file:	file pointer
@@ -247,56 +339,34 @@
  *	@count:	number of bytes
  *	@ppos:	starting offset
  *
- *	Identical to sysfs_read_file(), though going the opposite direction.
- *	We allocate a %PAGE_SIZE buffer and copy in the userspace buffer. We
- *	pass that to the object's ->store() method until we reach @count or 
- *	->store() returns %0 or less.
+ *	Similar to sysfs_read_file(), though working in the opposite direction.
+ *	We allocate and fill the data from the user in fill_write_buffer(),
+ *	then push it to the kobject in flush_write_buffer().
+ *	There is no easy way for us to know if userspace is only doing a partial
+ *	write, so we don't support them. We expect the entire buffer to come
+ *	on the first write. 
+ *	Hint: if you're writing a value, first read the file, modify only the
+ *	the value you're changing, then write entire buffer back. 
  */
 
 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 sysfs_ops * ops = file->private_data;
-	struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
-	ssize_t retval = 0;
-	char * page;
-
-
-	page = (char *)__get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
+	struct sysfs_buffer * buffer = file->private_data;
 
-	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 = ops->store(kobj,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;
+	count = fill_write_buffer(buffer,buf,count);
+	if (count > 0)
+		count = flush_write_buffer(file,buffer);
+	if (count > 0)
+		*ppos += count;
+	return count;
 }
 
 static int check_perm(struct inode * inode, struct file * file)
 {
 	struct kobject * kobj = kobject_get(file->f_dentry->d_parent->d_fsdata);
 	struct attribute * attr = file->f_dentry->d_fsdata;
+	struct sysfs_buffer * buffer;
 	struct sysfs_ops * ops = NULL;
 	int error = 0;
 
@@ -325,9 +395,7 @@
 	 */
 	if (file->f_mode & FMODE_WRITE) {
 
-		if (!(inode->i_mode & S_IWUGO))
-			goto Eperm;
-		if (!ops->store)
+		if (!(inode->i_mode & S_IWUGO) || !ops->store)
 			goto Eaccess;
 
 	}
@@ -337,16 +405,20 @@
 	 * must be a show method for it.
 	 */
 	if (file->f_mode & FMODE_READ) {
-		if (!(inode->i_mode & S_IRUGO))
-			goto Eperm;
-		if (!ops->show)
+		if (!(inode->i_mode & S_IRUGO) || !ops->show)
 			goto Eaccess;
 	}
 
-	/* No error? Great, store the ops in file->private_data
-	 * for easy access in the read/write functions.
+	/* No error? Great, allocate a buffer for the file, and store it
+	 * it in file->private_data for easy access.
 	 */
-	file->private_data = ops;
+	buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL);
+	if (buffer) {
+		memset(buffer,0,sizeof(struct sysfs_buffer));
+		buffer->ops = ops;
+		file->private_data = buffer;
+	} else
+		error = -ENOMEM;
 	goto Done;
 
  Einval:
@@ -354,10 +426,9 @@
 	goto Done;
  Eaccess:
 	error = -EACCES;
-	goto Done;
- Eperm:
-	error = -EPERM;
  Done:
+	if (error && kobj)
+		kobject_put(kobj);
 	return error;
 }
 
@@ -369,8 +440,16 @@
 static int sysfs_release(struct inode * inode, struct file * filp)
 {
 	struct kobject * kobj = filp->f_dentry->d_parent->d_fsdata;
+	struct sysfs_buffer * buffer = filp->private_data;
+
 	if (kobj) 
 		kobject_put(kobj);
+
+	if (buffer) {
+		if (buffer->page)
+			free_page((unsigned long)buffer->page);
+		kfree(buffer);
+	}
 	return 0;
 }
 
@@ -618,7 +697,19 @@
 		    (victim->d_parent->d_inode == dir->d_inode)) {
 			simple_unlink(dir->d_inode,victim);
 			d_delete(victim);
+
+			pr_debug("sysfs: Removing %s (%d)\n", victim->d_name.name,
+				 atomic_read(&victim->d_count));
+			/**
+			 * Drop reference from initial get_dentry().
+			 */
+			dput(victim);
 		}
+		
+		/**
+		 * Drop the reference acquired from get_dentry() above.
+		 */
+		dput(victim);
 	}
 	up(&dir->d_inode->i_sem);
 }
@@ -662,29 +753,60 @@
 void sysfs_remove_dir(struct kobject * kobj)
 {
 	struct list_head * node, * next;
-	struct dentry * dentry = kobj->dentry;
+	struct dentry * dentry = dget(kobj->dentry);
 	struct dentry * parent;
 
 	if (!dentry)
 		return;
 
+	pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
 	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 */
+		struct dentry * d = dget(list_entry(node,struct dentry,d_child));
+		/** 
+		 * Make sure dentry is still there 
+		 */
+		pr_debug(" o %s: ",d->d_name.name);
 		if (d->d_inode) {
+
+			pr_debug("removing");
+			/**
+			 * Unlink and unhash.
+			 */
 			simple_unlink(dentry->d_inode,d);
-			d_delete(dentry);
+			d_delete(d);
+
+			/**
+			 * Drop reference from initial get_dentry().
+			 */
+			dput(d);
 		}
+		pr_debug(" done (%d)\n",atomic_read(&d->d_count));
+		/**
+		 * drop reference from dget() above.
+		 */
+		dput(d);
 	}
 
 	up(&dentry->d_inode->i_sem);
 	d_invalidate(dentry);
 	simple_rmdir(parent->d_inode,dentry);
 	d_delete(dentry);
+
+	pr_debug(" o %s removing done (%d)\n",dentry->d_name.name,
+		 atomic_read(&dentry->d_count));
+	/**
+	 * Drop reference from initial get_dentry().
+	 */
+	dput(dentry);
+
+	/**
+	 * Drop reference from dget() on entrance.
+	 */
+	dput(dentry);
 	up(&parent->d_inode->i_sem);
 	dput(parent);
 }
diff -Nru a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
--- a/include/asm-arm/dma-mapping.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-arm/dma-mapping.h	Mon Jan 13 10:18:05 2003
@@ -14,7 +14,7 @@
  * devices.  This is the "generic" version.  The PCI specific version
  * is in pci.h
  */
-extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, unsigned long flags);
 extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
 extern void consistent_sync(void *kaddr, size_t size, int rw);
 
@@ -84,12 +84,12 @@
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle)
 {
-	int gfp = GFP_KERNEL;
+	int gfp = GFP_ATOMIC;
 
 	if (dev == NULL || dmadev_is_sa1111(dev) || *dev->dma_mask != 0xffffffff)
 		gfp |= GFP_DMA;
 
-	return consistent_alloc(gfp, size, handle);
+	return consistent_alloc(gfp, size, handle, 0);
 }
 
 /**
diff -Nru a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
--- a/include/asm-arm/ecard.h	Mon Jan 13 10:18:07 2003
+++ b/include/asm-arm/ecard.h	Mon Jan 13 10:18:07 2003
@@ -160,6 +160,7 @@
 	const char		*card_desc;	/* Card description		*/
 	CONST unsigned int	podaddr;	/* Base Linux address for card	*/
 	CONST loader_t		loader;		/* loader program */
+	u64			dma_mask;
 };
 
 struct in_chunk_dir {
diff -Nru a/include/asm-arm/pci.h b/include/asm-arm/pci.h
--- a/include/asm-arm/pci.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-arm/pci.h	Mon Jan 13 10:18:05 2003
@@ -40,13 +40,13 @@
 static inline void *
 pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handle)
 {
-	int gfp = GFP_KERNEL;
+	int gfp = GFP_ATOMIC;
 
 	if (hwdev == NULL || pcidev_is_sa1111(hwdev) ||
 	    hwdev->dma_mask != 0xffffffff)
 		gfp |= GFP_DMA;
 
-	return consistent_alloc(gfp, size, handle);
+	return consistent_alloc(gfp, size, handle, 0);
 }
 
 static inline void
diff -Nru a/include/asm-arm/proc-armv/uaccess.h b/include/asm-arm/proc-armv/uaccess.h
--- a/include/asm-arm/proc-armv/uaccess.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-arm/proc-armv/uaccess.h	Mon Jan 13 10:18:05 2003
@@ -12,7 +12,7 @@
  * Note that this is actually 0x1,0000,0000
  */
 #define KERNEL_DS	0x00000000
-#define USER_DS		PAGE_OFFSET
+#define USER_DS		TASK_SIZE
 
 static inline void set_fs (mm_segment_t fs)
 {
@@ -50,8 +50,8 @@
 	"	.align	3\n"					\
 	"	.long	1b, 3b\n"				\
 	"	.previous"					\
-	: "=r" (err)						\
-	: "r" (x), "r" (__pu_addr), "i" (-EFAULT), "0" (err)	\
+	: "+r" (err)						\
+	: "r" (x), "r" (__pu_addr), "i" (-EFAULT)		\
 	: "cc")
 
 #ifndef __ARMEB__
@@ -83,19 +83,18 @@
 	"	.align	3\n"					\
 	"	.long	1b, 3b\n"				\
 	"	.previous"					\
-	: "=r" (err)						\
-	: "r" (x), "r" (__pu_addr), "i" (-EFAULT), "0" (err))
+	: "+r" (err)						\
+	: "r" (x), "r" (__pu_addr), "i" (-EFAULT)		\
+	: "cc")
 
 #define __put_user_asm_dword(x,__pu_addr,err)			\
-({								\
-	unsigned long long __temp = (unsigned long long)x;	\
 	__asm__ __volatile__(					\
-	"1:	strt	%1, [%2], #0\n"				\
-	"2:	strt	%3, [%4], #0\n"				\
+	"1:	strt	%Q2, [%1], #4\n"			\
+	"2:	strt	%R2, [%1], #0\n"			\
 	"3:\n"							\
 	"	.section .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
-	"4:	mov	%0, %5\n"				\
+	"4:	mov	%0, %3\n"				\
 	"	b	3b\n"					\
 	"	.previous\n"					\
 	"	.section __ex_table,\"a\"\n"			\
@@ -103,12 +102,9 @@
 	"	.long	1b, 4b\n"				\
 	"	.long	2b, 4b\n"				\
 	"	.previous"					\
-	: "=r" (err)						\
-	: "r" (__temp), "r" (__pu_addr),			\
-	  "r" (__temp >> 32), "r" (__pu_addr + 4),		\
-	  "i" (-EFAULT), "0" (err)				\
-	: "cc");						\
-})
+	: "+r" (err), "+r" (__pu_addr)				\
+	: "r" (x), "i" (-EFAULT)				\
+	: "cc")
 
 #define __get_user_asm_byte(x,addr,err)				\
 	__asm__ __volatile__(					\
@@ -124,23 +120,24 @@
 	"	.align	3\n"					\
 	"	.long	1b, 3b\n"				\
 	"	.previous"					\
-	: "=r" (err), "=&r" (x)					\
-	: "r" (addr), "i" (-EFAULT), "0" (err))
+	: "+r" (err), "=&r" (x)					\
+	: "r" (addr), "i" (-EFAULT)				\
+	: "cc")
 
 #ifndef __ARMEB__
-#define __get_user_asm_half(x,addr,err)				\
+#define __get_user_asm_half(x,__gu_addr,err)			\
 ({								\
-	unsigned long __b1, __b2, __ptr = (unsigned long)addr;	\
-	__get_user_asm_byte(__b1, __ptr, err);			\
-	__get_user_asm_byte(__b2, __ptr + 1, err);		\
+	unsigned long __b1, __b2;				\
+	__get_user_asm_byte(__b1, __gu_addr, err);		\
+	__get_user_asm_byte(__b2, __gu_addr + 1, err);		\
 	(x) = __b1 | (__b2 << 8);				\
 })
 #else
-#define __get_user_asm_half(x,addr,err)				\
+#define __get_user_asm_half(x,__gu_addr,err)			\
 ({								\
 	unsigned long __b1, __b2;				\
-	__get_user_asm_byte(__b1, addr, err);			\
-	__get_user_asm_byte(__b2, (int)(addr) + 1, err);	\
+	__get_user_asm_byte(__b1, __gu_addr, err);		\
+	__get_user_asm_byte(__b2, __gu_addr + 1, err);		\
 	(x) = (__b1 << 8) | __b2;				\
 })
 #endif
@@ -159,8 +156,9 @@
 	"	.align	3\n"					\
 	"	.long	1b, 3b\n"				\
 	"	.previous"					\
-	: "=r" (err), "=&r" (x)					\
-	: "r" (addr), "i" (-EFAULT), "0" (err))
+	: "+r" (err), "=&r" (x)					\
+	: "r" (addr), "i" (-EFAULT)				\
+	: "cc")
 
 extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n);
 #define __do_copy_from_user(to,from,n)				\
diff -Nru a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
--- a/include/asm-arm/procinfo.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-arm/procinfo.h	Mon Jan 13 10:18:05 2003
@@ -16,11 +16,6 @@
 struct cpu_user_fns;
 struct processor;
 
-struct proc_info_item {
-	const char	 *manufacturer;
-	const char	 *cpu_name;
-};
-
 /*
  * Note!  struct processor is always defined if we're
  * using MULTI_CPU, otherwise this entry is unused,
@@ -38,7 +33,7 @@
 	const char		*arch_name;
 	const char		*elf_name;
 	unsigned int		elf_hwcap;
-	struct proc_info_item	*info;
+	const char		*cpu_name;
 	struct processor	*proc;
 	struct cpu_tlb_fns	*tlb;
 	struct cpu_user_fns	*user;
diff -Nru a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
--- a/include/asm-arm/tlb.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-arm/tlb.h	Mon Jan 13 10:18:05 2003
@@ -23,20 +23,21 @@
  * TLB handling.  This allows us to remove pages from the page
  * tables, and efficiently handle the TLB issues.
  */
-typedef struct free_pte_ctx {
+struct mmu_gather {
 	struct mm_struct	*mm;
 	unsigned int		freed;
 
 	unsigned int		flushes;
 	unsigned int		avoided_flushes;
-} mmu_gather_t;
+};
 
-extern mmu_gather_t mmu_gathers[NR_CPUS];
+extern struct mmu_gather mmu_gathers[NR_CPUS];
 
-static inline mmu_gather_t *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
+static inline struct mmu_gather *
+tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
 	int cpu = smp_processor_id();
-	mmu_gather_t *tlb = &mmu_gathers[cpu];
+	struct mmu_gather *tlb = &mmu_gathers[cpu];
 
 	tlb->mm = mm;
 	tlb->freed = 0;
@@ -44,7 +45,8 @@
 	return tlb;
 }
 
-static inline void tlb_finish_mmu(mmu_gather_t *tlb, unsigned long start, unsigned long end)
+static inline void
+tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
 	struct mm_struct *mm = tlb->mm;
 	unsigned long freed = tlb->freed;
diff -Nru a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
--- a/include/asm-arm/uaccess.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-arm/uaccess.h	Mon Jan 13 10:18:06 2003
@@ -74,7 +74,7 @@
 	   __asm__ __volatile__ ("bl	__get_user_" #__s		\
 		: "=&r" (__e), "=r" (__r1)				\
 		: "0" (__p)						\
-		: __i)
+		: __i, "cc")
 
 #define get_user(x,p)							\
 	({								\
@@ -100,8 +100,31 @@
 		__e;							\
 	})
 
-#define __get_user(x,p)		__get_user_nocheck((x),(p),sizeof(*(p)))
-#define __get_user_error(x,p,e)	__get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
+#define __get_user(x,ptr)						\
+({									\
+	long __gu_err = 0;						\
+	__get_user_err((x),(ptr),__gu_err);				\
+	__gu_err;							\
+})
+
+#define __get_user_error(x,ptr,err)					\
+({									\
+	__get_user_err((x),(ptr),err);					\
+	(void) 0;							\
+})
+
+#define __get_user_err(x,ptr,err)					\
+do {									\
+	unsigned long __gu_addr = (unsigned long)(ptr);			\
+	unsigned long __gu_val;						\
+	switch (sizeof(*(ptr))) {					\
+	case 1:	__get_user_asm_byte(__gu_val,__gu_addr,err);	break;	\
+	case 2:	__get_user_asm_half(__gu_val,__gu_addr,err);	break;	\
+	case 4:	__get_user_asm_word(__gu_val,__gu_addr,err);	break;	\
+	default: (__gu_val) = __get_user_bad();				\
+	}								\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+} while (0)
 
 extern int __put_user_1(void *, unsigned int);
 extern int __put_user_2(void *, unsigned int);
@@ -113,7 +136,7 @@
 	   __asm__ __volatile__ ("bl	__put_user_" #__s		\
 		: "=&r" (__e)						\
 		: "0" (__p), "r" (__r1)					\
-		: __i)
+		: __i, "cc")
 
 #define put_user(x,p)							\
 	({								\
@@ -138,8 +161,31 @@
 		__e;							\
 	})
 
-#define __put_user(x,p)		__put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
-#define __put_user_error(x,p,e)	__put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
+#define __put_user(x,ptr)						\
+({									\
+	long __pu_err = 0;						\
+	__put_user_err((x),(ptr),__pu_err);				\
+	__pu_err;							\
+})
+
+#define __put_user_error(x,ptr,err)					\
+({									\
+	__put_user_err((x),(ptr),err);					\
+	(void) 0;							\
+})
+
+#define __put_user_err(x,ptr,err)					\
+do {									\
+	unsigned long __pu_addr = (unsigned long)(ptr);			\
+	__typeof__(*(ptr)) __pu_val = (x);				\
+	switch (sizeof(*(ptr))) {					\
+	case 1: __put_user_asm_byte(__pu_val,__pu_addr,err);	break;	\
+	case 2: __put_user_asm_half(__pu_val,__pu_addr,err);	break;	\
+	case 4: __put_user_asm_word(__pu_val,__pu_addr,err);	break;	\
+	case 8:	__put_user_asm_dword(__pu_val,__pu_addr,err);	break;	\
+	default: __put_user_bad();					\
+	}								\
+} while (0)
 
 static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
 {
@@ -208,86 +254,5 @@
 
 	return res;
 }
-
-/*
- * These are the work horses of the get/put_user functions
- */
-#if 0
-#define __get_user_check(x,ptr,size)					\
-({									\
-	long __gu_err = -EFAULT, __gu_val = 0;				\
-	const __typeof__(*(ptr)) *__gu_addr = (ptr);			\
-	if (access_ok(VERIFY_READ,__gu_addr,size)) {			\
-		__gu_err = 0;						\
-		__get_user_size(__gu_val,__gu_addr,(size),__gu_err);	\
-	}								\
-	(x) = (__typeof__(*(ptr)))__gu_val;				\
-	__gu_err;							\
-})
-#endif
-
-#define __get_user_nocheck(x,ptr,size)					\
-({									\
-	long __gu_err = 0, __gu_val;					\
-	__get_user_size(__gu_val,(ptr),(size),__gu_err);		\
-	(x) = (__typeof__(*(ptr)))__gu_val;				\
-	__gu_err;							\
-})
-
-#define __get_user_nocheck_error(x,ptr,size,err)			\
-({									\
-	long __gu_val;							\
-	__get_user_size(__gu_val,(ptr),(size),(err));			\
-	(x) = (__typeof__(*(ptr)))__gu_val;				\
-	(void) 0;							\
-})
-
-#define __put_user_check(x,ptr,size)					\
-({									\
-	long __pu_err = -EFAULT;					\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);				\
-	if (access_ok(VERIFY_WRITE,__pu_addr,size)) {			\
-		__pu_err = 0;						\
-		__put_user_size((x),__pu_addr,(size),__pu_err);		\
-	}								\
-	__pu_err;							\
-})
-
-#define __put_user_nocheck(x,ptr,size)					\
-({									\
-	long __pu_err = 0;						\
-	unsigned long __pu_addr = (unsigned long)(ptr);			\
-	__put_user_size((x),__pu_addr,(size),__pu_err);			\
-	__pu_err;							\
-})
-
-#define __put_user_nocheck_error(x,ptr,size,err)			\
-({									\
-	unsigned long __pu_addr = (unsigned long)(ptr);			\
-	__put_user_size((x),__pu_addr,(size),err);			\
-	(void) 0;							\
-})
-
-#define __get_user_size(x,ptr,size,retval)				\
-do {									\
-	switch (size) {							\
-	case 1:	__get_user_asm_byte(x,ptr,retval);	break;		\
-	case 2:	__get_user_asm_half(x,ptr,retval);	break;		\
-	case 4:	__get_user_asm_word(x,ptr,retval);	break;		\
-	case 8:	__get_user_asm_dword(x,ptr,retval);	break;		\
-	default: (x) = __get_user_bad();				\
-	}								\
-} while (0)
-
-#define __put_user_size(x,ptr,size,retval)				\
-do {									\
-	switch (size) {							\
-	case 1: __put_user_asm_byte(x,ptr,retval);	break;		\
-	case 2: __put_user_asm_half(x,ptr,retval);	break;		\
-	case 4: __put_user_asm_word(x,ptr,retval);	break;		\
-	case 8:	__put_user_asm_dword(x,ptr,retval);	break;		\
-	default: __put_user_bad();					\
-	}								\
-} while (0)
 
 #endif /* _ASMARM_UACCESS_H */
diff -Nru a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
--- a/include/asm-generic/tlb.h	Mon Jan 13 10:18:04 2003
+++ b/include/asm-generic/tlb.h	Mon Jan 13 10:18:04 2003
@@ -28,29 +28,30 @@
   #define tlb_fast_mode(tlb) 1
 #endif
 
-/* mmu_gather_t is an opaque type used by the mm code for passing around any
- * data needed by arch specific code for tlb_remove_page.  This structure can
- * be per-CPU or per-MM as the page table lock is held for the duration of TLB
- * shootdown.
+/* struct mmu_gather is an opaque type used by the mm code for passing around
+ * any data needed by arch specific code for tlb_remove_page.  This structure
+ * can be per-CPU or per-MM as the page table lock is held for the duration of
+ * TLB shootdown.
  */
-typedef struct free_pte_ctx {
+struct mmu_gather {
 	struct mm_struct	*mm;
 	unsigned int		nr;	/* set to ~0U means fast mode */
 	unsigned int		need_flush;/* Really unmapped some ptes? */
 	unsigned int		fullmm; /* non-zero means full mm flush */
 	unsigned long		freed;
 	struct page *		pages[FREE_PTE_NR];
-} mmu_gather_t;
+};
 
 /* Users of the generic TLB shootdown code must declare this storage space. */
-extern mmu_gather_t	mmu_gathers[NR_CPUS];
+extern struct mmu_gather	mmu_gathers[NR_CPUS];
 
 /* tlb_gather_mmu
- *	Return a pointer to an initialized mmu_gather_t.
+ *	Return a pointer to an initialized struct mmu_gather.
  */
-static inline mmu_gather_t *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
+static inline struct mmu_gather *
+tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
-	mmu_gather_t *tlb = &mmu_gathers[smp_processor_id()];
+	struct mmu_gather *tlb = &mmu_gathers[smp_processor_id()];
 
 	tlb->mm = mm;
 
@@ -63,7 +64,8 @@
 	return tlb;
 }
 
-static inline void tlb_flush_mmu(mmu_gather_t *tlb, unsigned long start, unsigned long end)
+static inline void
+tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
 	if (!tlb->need_flush)
 		return;
@@ -79,7 +81,8 @@
  *	Called at the end of the shootdown operation to free up any resources
  *	that were required.  The page table lock is still held at this point.
  */
-static inline void tlb_finish_mmu(mmu_gather_t *tlb, unsigned long start, unsigned long end)
+static inline void
+tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
 	int freed = tlb->freed;
 	struct mm_struct *mm = tlb->mm;
@@ -95,12 +98,12 @@
 }
 
 
-/* void tlb_remove_page(mmu_gather_t *tlb, pte_t *ptep, unsigned long addr)
+/* void tlb_remove_page(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
  *	Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)), while
  *	handling the additional races in SMP caused by other CPUs caching valid
  *	mappings in their TLBs.
  */
-static inline void tlb_remove_page(mmu_gather_t *tlb, struct page *page)
+static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
 	tlb->need_flush = 1;
 	if (tlb_fast_mode(tlb)) {
diff -Nru a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
--- a/include/asm-i386/ptrace.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-i386/ptrace.h	Mon Jan 13 10:18:05 2003
@@ -51,6 +51,9 @@
 
 #define PTRACE_OLDSETOPTIONS         21
 
+#define PTRACE_GET_THREAD_AREA    25
+#define PTRACE_SET_THREAD_AREA    26
+
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
diff -Nru a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
--- a/include/asm-i386/uaccess.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-i386/uaccess.h	Mon Jan 13 10:18:05 2003
@@ -92,6 +92,8 @@
 	unsigned long insn, fixup;
 };
 
+extern int fixup_exception(struct pt_regs *regs);
+
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
@@ -144,21 +146,21 @@
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
-#define __put_user_nocheck(x,ptr,size)			\
-({							\
-	long __pu_err;					\
-	__put_user_size((x),(ptr),(size),__pu_err);	\
-	__pu_err;					\
+#define __put_user_nocheck(x,ptr,size)				\
+({								\
+	long __pu_err;						\
+	__put_user_size((x),(ptr),(size),__pu_err,-EFAULT);	\
+	__pu_err;						\
 })
 
 
-#define __put_user_check(x,ptr,size)			\
-({							\
+#define __put_user_check(x,ptr,size)					\
+({									\
 	long __pu_err = -EFAULT;					\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);		\
-	if (access_ok(VERIFY_WRITE,__pu_addr,size))	\
-		__put_user_size((x),__pu_addr,(size),__pu_err);	\
-	__pu_err;					\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);				\
+	if (access_ok(VERIFY_WRITE,__pu_addr,size))			\
+		__put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT);	\
+	__pu_err;							\
 })							
 
 #define __put_user_u64(x, addr, err)				\
@@ -178,14 +180,14 @@
 		: "=r"(err)					\
 		: "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
 
-#define __put_user_size(x,ptr,size,retval)				\
+#define __put_user_size(x,ptr,size,retval,errret)			\
 do {									\
 	retval = 0;							\
 	switch (size) {							\
-	  case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break;	\
-	  case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break;	\
-	  case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break;	\
-	  case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;	\
+	case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break;	\
+	case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \
+	case 4: __put_user_asm(x,ptr,retval,"l","","ir",errret); break;	\
+	case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
 	  default: __put_user_bad();					\
 	}								\
 } while (0)
@@ -198,64 +200,126 @@
  * we do not write to any memory gcc knows about, so there are no
  * aliasing issues.
  */
-#define __put_user_asm(x, addr, err, itype, rtype, ltype)	\
-	__asm__ __volatile__(					\
-		"1:	mov"itype" %"rtype"1,%2\n"		\
-		"2:\n"						\
-		".section .fixup,\"ax\"\n"			\
-		"3:	movl %3,%0\n"				\
-		"	jmp 2b\n"				\
-		".previous\n"					\
-		".section __ex_table,\"a\"\n"			\
-		"	.align 4\n"				\
-		"	.long 1b,3b\n"				\
-		".previous"					\
-		: "=r"(err)					\
-		: ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
+#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
+	__asm__ __volatile__(						\
+		"1:	mov"itype" %"rtype"1,%2\n"			\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"3:	movl %3,%0\n"					\
+		"	jmp 2b\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.align 4\n"					\
+		"	.long 1b,3b\n"					\
+		".previous"						\
+		: "=r"(err)						\
+		: ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
 
 
 #define __get_user_nocheck(x,ptr,size)				\
 ({								\
 	long __gu_err, __gu_val;				\
-	__get_user_size(__gu_val,(ptr),(size),__gu_err);	\
+	__get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\
 	(x) = (__typeof__(*(ptr)))__gu_val;			\
 	__gu_err;						\
 })
 
 extern long __get_user_bad(void);
 
-#define __get_user_size(x,ptr,size,retval)				\
+#define __get_user_size(x,ptr,size,retval,errret)			\
 do {									\
 	retval = 0;							\
 	switch (size) {							\
-	  case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break;	\
-	  case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break;	\
-	  case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break;	\
-	  default: (x) = __get_user_bad();				\
+	case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break;	\
+	case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break;	\
+	case 4: __get_user_asm(x,ptr,retval,"l","","=r",errret);break;	\
+	default: (x) = __get_user_bad();				\
 	}								\
 } while (0)
 
-#define __get_user_asm(x, addr, err, itype, rtype, ltype)	\
-	__asm__ __volatile__(					\
-		"1:	mov"itype" %2,%"rtype"1\n"		\
-		"2:\n"						\
-		".section .fixup,\"ax\"\n"			\
-		"3:	movl %3,%0\n"				\
-		"	xor"itype" %"rtype"1,%"rtype"1\n"	\
-		"	jmp 2b\n"				\
-		".previous\n"					\
-		".section __ex_table,\"a\"\n"			\
-		"	.align 4\n"				\
-		"	.long 1b,3b\n"				\
-		".previous"					\
-		: "=r"(err), ltype (x)				\
-		: "m"(__m(addr)), "i"(-EFAULT), "0"(err))
+#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
+	__asm__ __volatile__(						\
+		"1:	mov"itype" %2,%"rtype"1\n"			\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"3:	movl %3,%0\n"					\
+		"	xor"itype" %"rtype"1,%"rtype"1\n"		\
+		"	jmp 2b\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.align 4\n"					\
+		"	.long 1b,3b\n"					\
+		".previous"						\
+		: "=r"(err), ltype (x)					\
+		: "m"(__m(addr)), "i"(errret), "0"(err))
+
 
+unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n);
+unsigned long __copy_from_user_ll(void *to, const void *from, unsigned long n);
 
-unsigned long copy_to_user(void *to, const void *from, unsigned long n);
-unsigned long copy_from_user(void *to, const void *from, unsigned long n);
-unsigned long __copy_to_user(void *to, const void *from, unsigned long n);
-unsigned long __copy_from_user(void *to, const void *from, unsigned long n);
+/*
+ * Here we special-case 1, 2 and 4-byte copy_*_user invokations.  On a fault
+ * we return the initial request size (1, 2 or 4), as copy_*_user should do.
+ * If a store crosses a page boundary and gets a fault, the x86 will not write
+ * anything, so this is accurate.
+ */
+static inline unsigned long
+__copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if (__builtin_constant_p(n)) {
+		unsigned long ret;
+
+		switch (n) {
+		case 1:
+			__put_user_size(*(u8 *)from, (u8 *)to, 1, ret, 1);
+			return ret;
+		case 2:
+			__put_user_size(*(u16 *)from, (u16 *)to, 2, ret, 2);
+			return ret;
+		case 4:
+			__put_user_size(*(u32 *)from, (u32 *)to, 4, ret, 4);
+			return ret;
+		}
+	}
+	return __copy_to_user_ll(to, from, n);
+}
+
+static inline unsigned long
+__copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if (__builtin_constant_p(n)) {
+		unsigned long ret;
+
+		switch (n) {
+		case 1:
+			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			return ret;
+		case 2:
+			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			return ret;
+		case 4:
+			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			return ret;
+		}
+	}
+	return __copy_from_user_ll(to, from, n);
+}
+
+static inline unsigned long
+copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		n = __copy_to_user(to, from, n);
+	return n;
+}
+
+static inline unsigned long
+copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		n = __copy_from_user(to, from, n);
+	return n;
+}
 
 long strncpy_from_user(char *dst, const char *src, long count);
 long __strncpy_from_user(char *dst, const char *src, long count);
diff -Nru a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
--- a/include/asm-ia64/tlb.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-ia64/tlb.h	Mon Jan 13 10:18:06 2003
@@ -51,7 +51,7 @@
 # define tlb_fast_mode(tlb)	(1)
 #endif
 
-typedef struct {
+struct mmu_gather {
 	struct mm_struct	*mm;
 	unsigned int		nr;		/* == ~0U => fast mode */
 	unsigned char		fullmm;		/* non-zero means full mm flush */
@@ -60,17 +60,18 @@
 	unsigned long		start_addr;
 	unsigned long		end_addr;
 	struct page 		*pages[FREE_PTE_NR];
-} mmu_gather_t;
+};
 
 /* Users of the generic TLB shootdown code must declare this storage space. */
-extern mmu_gather_t	mmu_gathers[NR_CPUS];
+extern struct mmu_gather	mmu_gathers[NR_CPUS];
 
 /*
  * Flush the TLB for address range START to END and, if not in fast mode, release the
  * freed pages that where gathered up to this point.
  */
 static inline void
-ia64_tlb_flush_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end)
+ia64_tlb_flush_mmu(struct mmu_gather *tlb,
+		unsigned long start, unsigned long end)
 {
 	unsigned int nr;
 
@@ -120,12 +121,12 @@
 }
 
 /*
- * Return a pointer to an initialized mmu_gather_t.
+ * Return a pointer to an initialized struct mmu_gather.
  */
-static inline mmu_gather_t *
+static inline struct mmu_gather *
 tlb_gather_mmu (struct mm_struct *mm, unsigned int full_mm_flush)
 {
-	mmu_gather_t *tlb = &mmu_gathers[smp_processor_id()];
+	struct mmu_gather *tlb = &mmu_gathers[smp_processor_id()];
 
 	tlb->mm = mm;
 	/*
@@ -153,7 +154,7 @@
  * collected.  The page table lock is still held at this point.
  */
 static inline void
-tlb_finish_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end)
+tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
 	unsigned long freed = tlb->freed;
 	struct mm_struct *mm = tlb->mm;
@@ -178,7 +179,7 @@
  * this file).
  */
 static inline void
-tlb_remove_page (mmu_gather_t *tlb, struct page *page)
+tlb_remove_page (struct mmu_gather *tlb, struct page *page)
 {
 	tlb->need_flush = 1;
 
@@ -196,7 +197,8 @@
  * PTE, not just those pointing to (normal) physical memory.
  */
 static inline void
-__tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address)
+__tlb_remove_tlb_entry(struct mmu_gather *tlb,
+			pte_t *ptep, unsigned long address)
 {
 	if (tlb->start_addr == ~0UL)
 		tlb->start_addr = address;
diff -Nru a/include/asm-m68k/motorola_pgalloc.h b/include/asm-m68k/motorola_pgalloc.h
--- a/include/asm-m68k/motorola_pgalloc.h	Mon Jan 13 10:18:07 2003
+++ b/include/asm-m68k/motorola_pgalloc.h	Mon Jan 13 10:18:07 2003
@@ -55,7 +55,7 @@
 	__free_page(page);
 }
 
-static inline void __pte_free_tlb(mmu_gather_t *tlb, struct page *page)
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *page)
 {
 	cache_page(kmap(page));
 	kunmap(page);
@@ -73,7 +73,7 @@
 	return free_pointer_table(pmd);
 }
 
-static inline int __pmd_free_tlb(mmu_gather_t *tlb, pmd_t *pmd)
+static inline int __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
 	return free_pointer_table(pmd);
 }
diff -Nru a/include/asm-m68k/sun3_pgalloc.h b/include/asm-m68k/sun3_pgalloc.h
--- a/include/asm-m68k/sun3_pgalloc.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-m68k/sun3_pgalloc.h	Mon Jan 13 10:18:06 2003
@@ -31,7 +31,7 @@
         __free_page(page);
 }
 
-static inline void __pte_free_tlb(mmu_gather_t *tlb, struct page *page)
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *page)
 {
 	tlb_remove_page(tlb, page);
 }
diff -Nru a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
--- a/include/asm-ppc/mpc10x.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-ppc/mpc10x.h	Mon Jan 13 10:18:06 2003
@@ -164,5 +164,6 @@
 		       uint phys_eumb_base);
 unsigned long mpc10x_get_mem_size(uint mem_map);
 int mpc10x_enable_store_gathering(struct pci_controller *hose);
+int mpc10x_disable_store_gathering(struct pci_controller *hose);
 
 #endif	/* __PPC_KERNEL_MPC10X_H */
diff -Nru a/include/asm-ppc/tlb.h b/include/asm-ppc/tlb.h
--- a/include/asm-ppc/tlb.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-ppc/tlb.h	Mon Jan 13 10:18:06 2003
@@ -21,8 +21,8 @@
 #ifdef CONFIG_PPC_STD_MMU
 /* Classic PPC with hash-table based MMU... */
 
-struct free_pte_ctx;
-extern void tlb_flush(struct free_pte_ctx *tlb);
+struct mmu_gather;
+extern void tlb_flush(struct mmu_gather *tlb);
 
 /* Get the generic bits... */
 #include <asm-generic/tlb.h>
@@ -34,7 +34,7 @@
 extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep,
 			     unsigned long address);
 
-static inline void __tlb_remove_tlb_entry(mmu_gather_t *tlb, pte_t *ptep,
+static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
 					unsigned long address)
 {
 	if (pte_val(*ptep) & _PAGE_HASHPTE)
@@ -44,10 +44,6 @@
 #else
 /* Embedded PPC with software-loaded TLB, very simple... */
 
-struct flush_tlb_arch { };
-
-#define tlb_init_arch(tlb, full_flush)	do { } while (0)
-#define tlb_finish_arch(tlb)		do { } while (0)
 #define tlb_start_vma(tlb, vma)		do { } while (0)
 #define tlb_end_vma(tlb, vma)		do { } while (0)
 #define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
diff -Nru a/include/asm-ppc64/cacheflush.h b/include/asm-ppc64/cacheflush.h
--- a/include/asm-ppc64/cacheflush.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-ppc64/cacheflush.h	Mon Jan 13 10:18:05 2003
@@ -14,10 +14,10 @@
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr)		do { } while (0)
 #define flush_page_to_ram(page)			do { } while (0)
+#define flush_icache_page(vma, page)		do { } while (0)
 
 extern void flush_dcache_page(struct page *page);
 extern void flush_icache_range(unsigned long, unsigned long);
-extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
 extern void flush_icache_user_range(struct vm_area_struct *vma,
 				    struct page *page, unsigned long addr,
 				    int len);
diff -Nru a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h
--- a/include/asm-ppc64/compat.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-ppc64/compat.h	Mon Jan 13 10:18:05 2003
@@ -64,4 +64,17 @@
 	short		__unused;
 };
 
+struct compat_statfs {
+	int		f_type;
+	int		f_bsize;
+	int		f_blocks;
+	int		f_bfree;
+	int		f_bavail;
+	int		f_files;
+	int		f_ffree;
+	compat_fsid_t	f_fsid;
+	int		f_namelen;	/* SunOS ignores this field. */
+	int		f_spare[6];
+};
+
 #endif /* _ASM_PPC64_COMPAT_H */
diff -Nru a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
--- a/include/asm-ppc64/ppc32.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-ppc64/ppc32.h	Mon Jan 13 10:18:06 2003
@@ -40,19 +40,6 @@
 
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
 
-struct statfs32 {
-	int f_type;
-	int f_bsize;
-	int f_blocks;
-	int f_bfree;
-	int f_bavail;
-	int f_files;
-	int f_ffree;
-	compat_fsid_t f_fsid;
-	int f_namelen;  /* SunOS ignores this field. */
-	int f_spare[6];
-};
-
 typedef union sigval32 {
 	int sival_int;
 	unsigned int sival_ptr;
diff -Nru a/include/asm-ppc64/tlb.h b/include/asm-ppc64/tlb.h
--- a/include/asm-ppc64/tlb.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-ppc64/tlb.h	Mon Jan 13 10:18:05 2003
@@ -17,8 +17,7 @@
 #include <asm/page.h>
 #include <asm/mmu.h>
 
-struct free_pte_ctx;
-static inline void tlb_flush(struct free_pte_ctx *tlb);
+static inline void tlb_flush(struct mmu_gather *tlb);
 
 /* Avoid pulling in another include just for this */
 #define check_pgt_cache()	do { } while (0)
@@ -43,7 +42,7 @@
 
 extern struct ppc64_tlb_batch ppc64_tlb_batch[NR_CPUS];
 
-static inline void __tlb_remove_tlb_entry(mmu_gather_t *tlb, pte_t *ptep,
+static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
 					unsigned long address)
 {
 	int cpu = smp_processor_id();
@@ -74,7 +73,7 @@
 	batch->index = i;
 }
 
-static inline void tlb_flush(struct free_pte_ctx *tlb)
+static inline void tlb_flush(struct mmu_gather *tlb)
 {
 	int cpu = smp_processor_id();
 	struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[cpu];
diff -Nru a/include/asm-s390x/compat.h b/include/asm-s390x/compat.h
--- a/include/asm-s390x/compat.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-s390x/compat.h	Mon Jan 13 10:18:06 2003
@@ -67,4 +67,17 @@
 	short		__unused;
 };
 
+struct compat_statfs {
+	s32		f_type;
+	s32		f_bsize;
+	s32		f_blocks;
+	s32		f_bfree;
+	s32		f_bavail;
+	s32		f_files;
+	s32		f_ffree;
+	compat_fsid_t	f_fsid;
+	s32		f_namelen;  
+	s32		f_spare[6];
+};
+
 #endif /* _ASM_S390X_COMPAT_H */
diff -Nru a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
--- a/include/asm-sparc64/compat.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-sparc64/compat.h	Mon Jan 13 10:18:06 2003
@@ -64,4 +64,17 @@
 	short		__unused;
 };
 
+struct compat_statfs {
+	int		f_type;
+	int		f_bsize;
+	int		f_blocks;
+	int		f_bfree;
+	int		f_bavail;
+	int		f_files;
+	int		f_ffree;
+	compat_fsid_t	f_fsid;
+	int		f_namelen;	/* SunOS ignores this field. */
+	int		f_spare[6];
+};
+
 #endif /* _ASM_SPARC64_COMPAT_H */
diff -Nru a/include/asm-sparc64/statfs.h b/include/asm-sparc64/statfs.h
--- a/include/asm-sparc64/statfs.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-sparc64/statfs.h	Mon Jan 13 10:18:06 2003
@@ -5,24 +5,10 @@
 #ifndef __KERNEL_STRICT_NAMES
 
 #include <linux/types.h>
-#include <linux/compat.h>	/* for compat_fsid_t */
 
 typedef __kernel_fsid_t	fsid_t;
 
 #endif
-
-struct statfs32 {
-	int f_type;
-	int f_bsize;
-	int f_blocks;
-	int f_bfree;
-	int f_bavail;
-	int f_files;
-	int f_ffree;
-	compat_fsid_t f_fsid;
-	int f_namelen;  /* SunOS ignores this field. */
-	int f_spare[6];
-};
 
 struct statfs {
 	long f_type;
diff -Nru a/include/asm-v850/module.h b/include/asm-v850/module.h
--- a/include/asm-v850/module.h	Mon Jan 13 10:18:05 2003
+++ b/include/asm-v850/module.h	Mon Jan 13 10:18:05 2003
@@ -1,9 +1,9 @@
 /*
  * include/asm-v850/module.h -- Architecture-specific module hooks
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *  Copyright (C) 2001  Rusty Russell
+ *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,03  Rusty Russell
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -27,16 +27,28 @@
 
 struct mod_arch_specific
 {
-	/* How much of the core is actually taken up with core (then
-           we know the rest is for the PLT).  */
-	unsigned int core_plt_offset;
-
-	/* Same for init.  */
-	unsigned int init_plt_offset;
+	/* Indices of PLT sections within module. */
+	unsigned int core_plt_section, init_plt_section;
 };
 
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Sym Elf32_Sym
 #define Elf_Ehdr Elf32_Ehdr
+
+/* Make empty sections for module_frob_arch_sections to expand. */
+#ifdef MODULE
+asm(".section .plt,\"ax\",@nobits; .align 3; .previous");
+asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous");
+#endif
+
+/* We don't do exception tables.  */
+struct exception_table_entry;
+static inline const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+	       const struct exception_table_entry *last,
+	       unsigned long value)
+{
+	return 0;
+}
 
 #endif /* __V850_MODULE_H__ */
diff -Nru a/include/asm-v850/stat.h b/include/asm-v850/stat.h
--- a/include/asm-v850/stat.h	Mon Jan 13 10:18:06 2003
+++ b/include/asm-v850/stat.h	Mon Jan 13 10:18:06 2003
@@ -1,5 +1,20 @@
+/*
+ * include/asm-v850/stat.h -- v850 stat structure
+ *
+ *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
 #ifndef __V850_STAT_H__
 #define __V850_STAT_H__
+
+#include <asm/posix_types.h>
 
 struct stat {
 	__kernel_dev_t	st_dev;
diff -Nru a/include/asm-v850/system.h b/include/asm-v850/system.h
--- a/include/asm-v850/system.h	Mon Jan 13 10:18:07 2003
+++ b/include/asm-v850/system.h	Mon Jan 13 10:18:07 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/system.h -- Low-level interrupt/thread ops
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -67,6 +67,7 @@
 #define mb()			__asm__ __volatile__ ("" ::: "memory")
 #define rmb()			mb ()
 #define wmb()			mb ()
+#define read_barrier_depends()	((void)0)
 #define set_rmb(var, value)	do { xchg (&var, value); } while (0)
 #define set_mb(var, value)	set_rmb (var, value)
 #define set_wmb(var, value)	do { var = value; wmb (); } while (0)
diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h
--- a/include/linux/cpufreq.h	Mon Jan 13 10:18:06 2003
+++ b/include/linux/cpufreq.h	Mon Jan 13 10:18:06 2003
@@ -241,4 +241,27 @@
 
 #endif /* CONFIG_CPU_FREQ_24_API */
 
+/*********************************************************************
+ *                     FREQUENCY TABLE HELPERS                       *
+ *********************************************************************/
+
+#define CPUFREQ_ENTRY_INVALID ~0
+#define CPUFREQ_TABLE_END     ~1
+
+struct cpufreq_frequency_table {
+	unsigned int	index;     /* any */
+	unsigned int	frequency; /* kHz - doesn't need to be in ascending
+				    * order */
+};
+
+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+				    struct cpufreq_frequency_table *table);
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+				   struct cpufreq_frequency_table *table);
+
+int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
+				      struct cpufreq_frequency_table *table,
+				      unsigned int *index);
+
 #endif /* _LINUX_CPUFREQ_H */
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Mon Jan 13 10:18:07 2003
+++ b/include/linux/device.h	Mon Jan 13 10:18:07 2003
@@ -97,8 +97,8 @@
 
 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);
+	ssize_t (*show)(struct bus_type *, char * buf);
+	ssize_t (*store)(struct bus_type *, const char * buf);
 };
 
 #define BUS_ATTR(_name,_mode,_show,_store)	\
@@ -140,8 +140,8 @@
 
 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);
+	ssize_t (*show)(struct device_driver *, char * buf);
+	ssize_t (*store)(struct device_driver *, const char * buf);
 };
 
 #define DRIVER_ATTR(_name,_mode,_show,_store)	\
@@ -181,8 +181,8 @@
 
 struct devclass_attribute {
 	struct attribute	attr;
-	ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);
-	ssize_t (*store)(struct device_class *, const char * buf, size_t count, loff_t off);
+	ssize_t (*show)(struct device_class *, char * buf);
+	ssize_t (*store)(struct device_class *, const char * buf);
 };
 
 #define DEVCLASS_ATTR(_name,_str,_mode,_show,_store)	\
@@ -319,8 +319,8 @@
 
 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);
+	ssize_t (*show)(struct device * dev, char * buf);
+	ssize_t (*store)(struct device * dev, const char * buf);
 };
 
 #define DEVICE_ATTR(_name,_mode,_show,_store) \
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/fs.h	Mon Jan 13 10:18:05 2003
@@ -319,7 +319,7 @@
 	struct address_space_operations *a_ops;	/* methods */
 	struct list_head	i_mmap;		/* list of private mappings */
 	struct list_head	i_mmap_shared;	/* list of private mappings */
-	spinlock_t		i_shared_lock;  /* and spinlock protecting it */
+	struct semaphore	i_shared_sem;	/* and sem protecting it */
 	unsigned long		dirtied_when;	/* jiffies of first page dirtying */
 	int			gfp_mask;	/* how to allocate the pages */
 	struct backing_dev_info *backing_dev_info; /* device readahead, etc */
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/ide.h	Mon Jan 13 10:18:05 2003
@@ -916,6 +916,8 @@
 
 	struct pci_dev  *pci_dev;	/* for pci chipsets */
 	struct ide_pci_device_s	*cds;	/* chipset device struct */
+	
+	struct pnp_dev  *pnp_dev;	/* for PnP devices */
 
 #if 0
 	ide_hwif_ops_t	*hwifops;
diff -Nru a/include/linux/isapnp.h b/include/linux/isapnp.h
--- a/include/linux/isapnp.h	Mon Jan 13 10:18:07 2003
+++ b/include/linux/isapnp.h	Mon Jan 13 10:18:07 2003
@@ -122,6 +122,15 @@
 /* init/main.c */
 int isapnp_init(void);
 
+/* 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 /* !CONFIG_ISAPNP */
 
 /* lowlevel configuration */
@@ -138,6 +147,14 @@
 static inline void isapnp_device(unsigned char device) { ; }
 static inline void isapnp_activate(unsigned char device) { ; }
 static inline void isapnp_deactivate(unsigned char device) { ; }
+
+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_ISAPNP */
 
diff -Nru a/include/linux/ixjuser.h b/include/linux/ixjuser.h
--- a/include/linux/ixjuser.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/ixjuser.h	Mon Jan 13 10:18:05 2003
@@ -312,8 +312,8 @@
 * must be set to the number of IXJ_CADENCE_ELEMENTS in the array.  The
 * termination variable defines what to do at the end of a cadence, the
 * options are to play the cadence once and stop, to repeat the last
-* element of the cadence indefinatly, or to repeat the entire cadence
-* indefinatly.  The ce variable is a pointer to the array of IXJ_TONE
+* element of the cadence indefinitely, or to repeat the entire cadence
+* indefinitely.  The ce variable is a pointer to the array of IXJ_TONE
 * structures.  If the freq0 variable is non-zero, the tone table contents
 * for the tone_index are updated to the frequencies and gains defined.  It
 * should be noted that DTMF tones cannot be reassigned, so if DTMF tone
diff -Nru a/include/linux/kobject.h b/include/linux/kobject.h
--- a/include/linux/kobject.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/kobject.h	Mon Jan 13 10:18:05 2003
@@ -165,8 +165,8 @@
 
 struct subsys_attribute {
 	struct attribute attr;
-	ssize_t (*show)(struct subsystem *, char *, size_t, loff_t);
-	ssize_t (*store)(struct subsystem *, const char *, size_t, loff_t); 
+	ssize_t (*show)(struct subsystem *, char *);
+	ssize_t (*store)(struct subsystem *, const char *); 
 };
 
 extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/mm.h	Mon Jan 13 10:18:05 2003
@@ -141,6 +141,7 @@
 
 /* forward declaration; pte_chain is meant to be internal to rmap.c */
 struct pte_chain;
+struct mmu_gather;
 
 /*
  * Each physical page in the system has a struct page associated with
@@ -357,15 +358,26 @@
 
 extern void show_free_areas(void);
 
-struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused);
+struct page *shmem_nopage(struct vm_area_struct * vma,
+			unsigned long address, int unused);
 struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags);
-extern void shmem_lock(struct file * file, int lock);
-extern int shmem_zero_setup(struct vm_area_struct *);
+void shmem_lock(struct file * file, int lock);
+int shmem_zero_setup(struct vm_area_struct *);
 
-extern void zap_page_range(struct vm_area_struct *vma, unsigned long address, unsigned long size);
-extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma);
-extern int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
-extern int zeromap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long size, pgprot_t prot);
+void zap_page_range(struct vm_area_struct *vma, unsigned long address,
+			unsigned long size);
+int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm,
+		struct vm_area_struct *start_vma, unsigned long start_addr,
+		unsigned long end_addr, unsigned long *nr_accounted);
+void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
+			unsigned long address, unsigned long size);
+void clear_page_tables(struct mmu_gather *tlb, unsigned long first, int nr);
+int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
+			struct vm_area_struct *vma);
+int remap_page_range(struct vm_area_struct *vma, unsigned long from,
+			unsigned long to, unsigned long size, pgprot_t prot);
+int zeromap_page_range(struct vm_area_struct *vma, unsigned long from,
+			unsigned long size, pgprot_t prot);
 
 extern int vmtruncate(struct inode * inode, loff_t offset);
 extern pmd_t *FASTCALL(__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address));
@@ -384,6 +396,7 @@
 
 int __set_page_dirty_buffers(struct page *page);
 int __set_page_dirty_nobuffers(struct page *page);
+int set_page_dirty_lock(struct page *page);
 
 /*
  * Prototype to add a shrinker callback for ageable caches.
@@ -529,7 +542,6 @@
 					     struct vm_area_struct **pprev);
 extern int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
 		     unsigned long addr, int new_below);
-extern void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area);
 
 /* Look up the first VMA which intersects the interval start_addr..end_addr-1,
    NULL if none.  Assume start_addr < end_addr. */
diff -Nru a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h	Mon Jan 13 10:18:07 2003
+++ b/include/linux/module.h	Mon Jan 13 10:18:07 2003
@@ -61,6 +61,8 @@
   __attribute__ ((unused, alias(__stringify(name))))
 
 #define THIS_MODULE (&__this_module)
+#define MOD_INC_USE_COUNT _MOD_INC_USE_COUNT(THIS_MODULE)
+#define MOD_DEC_USE_COUNT __MOD_DEC_USE_COUNT(THIS_MODULE)
 
 /*
  * The following license idents are currently accepted as indicating free
@@ -96,6 +98,8 @@
 
 #define MODULE_GENERIC_TABLE(gtype,name)
 #define THIS_MODULE ((struct module *)0)
+#define MOD_INC_USE_COUNT	do { } while (0)
+#define MOD_DEC_USE_COUNT	do { } while (0)
 #define MODULE_LICENSE(license)
 #endif
 
@@ -426,10 +430,6 @@
 	try_module_get(module);
 #endif
 }
-#define MOD_INC_USE_COUNT \
-	_MOD_INC_USE_COUNT(THIS_MODULE)
-#define MOD_DEC_USE_COUNT \
-	__MOD_DEC_USE_COUNT(THIS_MODULE)
 #define EXPORT_NO_SYMBOLS
 extern int module_dummy_usage;
 #define GET_USE_COUNT(module) (module_dummy_usage)
diff -Nru a/include/linux/msg.h b/include/linux/msg.h
--- a/include/linux/msg.h	Mon Jan 13 10:18:06 2003
+++ b/include/linux/msg.h	Mon Jan 13 10:18:06 2003
@@ -69,6 +69,7 @@
 	long  m_type;          
 	int m_ts;           /* message text size */
 	struct msg_msgseg* next;
+	void *security;
 	/* the actual message follows immediately */
 };
 
diff -Nru a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
--- a/include/linux/nfsd/nfsd.h	Mon Jan 13 10:18:07 2003
+++ b/include/linux/nfsd/nfsd.h	Mon Jan 13 10:18:07 2003
@@ -38,7 +38,8 @@
 #define MAY_TRUNC		16
 #define MAY_LOCK		32
 #define MAY_OWNER_OVERRIDE	64
-#if (MAY_SATTR | MAY_TRUNC | MAY_LOCK | MAX_OWNER_OVERRIDE) & (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_OWNER_OVERRIDE)
+#define	MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
+#if (MAY_SATTR | MAY_TRUNC | MAY_LOCK | MAX_OWNER_OVERRIDE | MAY_LOCAL_ACCESS) & (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_OWNER_OVERRIDE)
 # error "please use a different value for MAY_SATTR or MAY_TRUNC or MAY_LOCK or MAY_OWNER_OVERRIDE."
 #endif
 #define MAY_CREATE		(MAY_EXEC|MAY_WRITE)
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/pci_ids.h	Mon Jan 13 10:18:05 2003
@@ -137,6 +137,7 @@
 #define PCI_DEVICE_ID_COMPAQ_SMART2P	0xae10
 #define PCI_DEVICE_ID_COMPAQ_NETEL100	0xae32
 #define PCI_DEVICE_ID_COMPAQ_NETEL10	0xae34
+#define PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE 0xae33
 #define PCI_DEVICE_ID_COMPAQ_NETFLEX3I	0xae35
 #define PCI_DEVICE_ID_COMPAQ_NETEL100D	0xae40
 #define PCI_DEVICE_ID_COMPAQ_NETEL100PI	0xae43
@@ -960,6 +961,7 @@
 #define PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
 #define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
 #define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
 #define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
@@ -984,6 +986,7 @@
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL	0x017B
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL	0x017C
 #define PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE		0x01bc
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3		0x0200
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1		0x0201
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2		0x0202
@@ -1878,6 +1881,7 @@
 #define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
+#define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
 #define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
 
 #define PCI_VENDOR_ID_COMPUTONE		0x8e0e
diff -Nru a/include/linux/pnp.h b/include/linux/pnp.h
--- a/include/linux/pnp.h	Mon Jan 13 10:18:07 2003
+++ b/include/linux/pnp.h	Mon Jan 13 10:18:07 2003
@@ -20,7 +20,8 @@
 
 #define DEVICE_COUNT_IRQ	2
 #define DEVICE_COUNT_DMA	2
-#define DEVICE_COUNT_RESOURCE	12
+#define DEVICE_COUNT_IO		8
+#define DEVICE_COUNT_MEM	4
 #define MAX_DEVICES		8
 
 struct pnp_resource;
@@ -30,6 +31,7 @@
 
 struct pnp_card {
 	char name[80];
+	int status;			/* status of the card */
 	unsigned char number;		/* card number */
 	struct list_head global_list;	/* node in global list of cards */
 	struct list_head protocol_list;	/* node in protocol's list of cards */
@@ -84,6 +86,9 @@
 struct pnp_dev {
 	char name[80];			/* device name */
 	int active;			/* status of the device */
+	int capabilities;
+	int status;
+
 	struct list_head global_list;	/* node in global list of devices */
 	struct list_head protocol_list;	/* node in list of device's protocol */
 	struct list_head card_list;	/* node in card's list of devices */
@@ -98,7 +103,8 @@
 	
 	struct pnp_resources *res;	/* possible resource information */
 	int lock_resources;		/* resources are locked */
-	struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
+	struct resource io_resource[DEVICE_COUNT_IO];   /* port regions */
+	struct resource mem_resource[DEVICE_COUNT_MEM]; /* memory regions + expansion ROMs */
 	struct resource dma_resource[DEVICE_COUNT_DMA];
 	struct resource irq_resource[DEVICE_COUNT_IRQ];
 
@@ -116,13 +122,10 @@
 	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))
-
-static inline int pnp_dev_has_driver(struct pnp_dev *pdev)
-{
-	if (pdev->driver || (pdev->card && pdev->card->driver))
-		return 1;
-	return 0;
-} 
+#define card_for_each_dev(card,dev) \
+	for((dev) = card_to_pnp_dev((card)->devices.next); \
+	(dev) != card_to_pnp_dev(&(card)->devices); \
+	(dev) = card_to_pnp_dev((dev)->card_list.next))
 
 static inline void *pnp_get_drvdata (struct pnp_dev *pdev)
 {
@@ -149,6 +152,28 @@
 	void (*quirk_function)(struct pnp_dev *dev);	/* fixup function */
 };
 
+/* capabilities */
+#define PNP_READ		0x0001
+#define PNP_WRITE		0x0002
+#define PNP_DISABLE		0x0004
+#define PNP_CONFIGURABLE	0x0008
+#define PNP_REMOVABLE		0x0010
+
+#define pnp_can_read(dev)	(((dev)->protocol) && ((dev)->protocol->get) && \
+				 ((dev)->capabilities & PNP_READ))
+#define pnp_can_write(dev)	(((dev)->protocol) && ((dev)->protocol->set) && \
+				 ((dev)->capabilities & PNP_WRITE))
+#define pnp_can_disable(dev)	(((dev)->protocol) && ((dev)->protocol->disable) && \
+				 ((dev)->capabilities & PNP_DISABLE))
+#define pnp_can_configure(dev)	((!(dev)->active) && ((dev)->capabilities & PNP_CONFIGURABLE))
+
+/* status */
+#define PNP_INIT		0x0000
+#define PNP_READY		0x0001
+#define PNP_ATTACHED		0x0002
+#define PNP_BUSY		0x0004
+#define PNP_FAULTY		0x0008
+
 
 /*
  * Driver Management
@@ -205,10 +230,14 @@
  * Resource Management
  */
 
+#define pnp_flags_valid(resrc)	(((resrc)->flags & IORESOURCE_UNSET) == 0 && \
+				 ((resrc)->flags & (IORESOURCE_IO|IORESOURCE_MEM|IORESOURCE_IRQ|IORESOURCE_DMA)) != 0)
+
 /* Use these instead of directly reading pnp_dev to get resource information */
-#define pnp_port_start(dev,bar)   ((dev)->resource[(bar)].start)
-#define pnp_port_end(dev,bar)     ((dev)->resource[(bar)].end)
-#define pnp_port_flags(dev,bar)   ((dev)->resource[(bar)].flags)
+#define pnp_port_start(dev,bar)	((dev)->io_resource[(bar)].start)
+#define pnp_port_end(dev,bar)	((dev)->io_resource[(bar)].end)
+#define pnp_port_flags(dev,bar)	((dev)->io_resource[(bar)].flags)
+#define pnp_port_valid(dev,bar)	pnp_flags_valid(&(dev)->io_resource[(bar)])
 #define pnp_port_len(dev,bar) \
 	((pnp_port_start((dev),(bar)) == 0 &&	\
 	  pnp_port_end((dev),(bar)) ==		\
@@ -217,9 +246,10 @@
 	 (pnp_port_end((dev),(bar)) -		\
 	  pnp_port_start((dev),(bar)) + 1))
 
-#define pnp_mem_start(dev,bar)   ((dev)->resource[(bar+8)].start)
-#define pnp_mem_end(dev,bar)     ((dev)->resource[(bar+8)].end)
-#define pnp_mem_flags(dev,bar)   ((dev)->resource[(bar+8)].flags)
+#define pnp_mem_start(dev,bar)	((dev)->mem_resource[(bar)].start)
+#define pnp_mem_end(dev,bar)	((dev)->mem_resource[(bar)].end)
+#define pnp_mem_flags(dev,bar)	((dev)->mem_resource[(bar)].flags)
+#define pnp_mem_valid(dev,bar)	pnp_flags_valid(&(dev)->mem_resource[(bar)])
 #define pnp_mem_len(dev,bar) \
 	((pnp_mem_start((dev),(bar)) == 0 &&	\
 	  pnp_mem_end((dev),(bar)) ==		\
@@ -228,11 +258,13 @@
 	 (pnp_mem_end((dev),(bar)) -		\
 	  pnp_mem_start((dev),(bar)) + 1))
 
-#define pnp_irq(dev,bar)	 ((dev)->irq_resource[(bar)].start)
-#define pnp_irq_flags(dev,bar)	 ((dev)->irq_resource[(bar)].flags)
-
-#define pnp_dma(dev,bar)	 ((dev)->dma_resource[(bar)].start)
-#define pnp_dma_flags(dev,bar)	 ((dev)->dma_resource[(bar)].flags)
+#define pnp_irq(dev,bar)	((dev)->irq_resource[(bar)].start)
+#define pnp_irq_flags(dev,bar)	((dev)->irq_resource[(bar)].flags)
+#define pnp_irq_valid(dev,bar)	pnp_flags_valid(&(dev)->irq_resource[(bar)])
+
+#define pnp_dma(dev,bar)	((dev)->dma_resource[(bar)].start)
+#define pnp_dma_flags(dev,bar)	((dev)->dma_resource[(bar)].flags)
+#define pnp_dma_valid(dev,bar)	pnp_flags_valid(&(dev)->dma_resource[(bar)])
 
 #define PNP_PORT_FLAG_16BITADDR	(1<<0)
 #define PNP_PORT_FLAG_FIXED	(1<<1)
@@ -298,14 +330,12 @@
 };
 
 struct pnp_res_cfg {
-	struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
+	struct resource io_resource[DEVICE_COUNT_IO];	/* I/O ports */
+	struct resource mem_resource[DEVICE_COUNT_MEM]; /* memory regions + expansion ROMs */
 	struct resource dma_resource[DEVICE_COUNT_DMA];
 	struct resource irq_resource[DEVICE_COUNT_IRQ];
 };
 
-#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];
@@ -325,7 +355,7 @@
 
 	/* functions */
 	int (*get)(struct pnp_dev *dev);
-	int (*set)(struct pnp_dev *dev, struct pnp_cfg *config, char flags);
+	int (*set)(struct pnp_dev *dev, struct pnp_cfg *config);
 	int (*disable)(struct pnp_dev *dev);
 
 	/* used by pnp layer only (look but don't touch) */
@@ -367,7 +397,7 @@
 int pnp_init_res_cfg(struct pnp_res_cfg *template);
 int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template);
 int pnp_disable_dev(struct pnp_dev *dev);
-int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template, int mode);
+int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template);
 void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size);
 
 /* driver */
@@ -375,6 +405,8 @@
 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);
+int pnp_device_attach(struct pnp_dev *pnp_dev);
+void pnp_device_detach(struct pnp_dev *pnp_dev);
 
 #else
 
@@ -395,12 +427,16 @@
 static inline int pnp_init_res_cfg(struct pnp_res_cfg *template) { return -ENODEV; }
 static inline int pnp_activate_dev(struct pnp_dev *dev, struct pnp_res_cfg *template) { 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, struct pnp_res_cfg *template, int mode) { return -ENODEV; }
+static inline int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template) { return -ENODEV; }
+static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { ; }
 static inline int compare_pnp_id(struct list_head * id_list, const char * id) { 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 int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
+static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
+
 #endif /* CONFIG_PNP */
 
 
@@ -417,6 +453,8 @@
 void pnpc_unregister_driver(struct pnpc_driver *drv);
 int pnpc_add_id(struct pnp_id *id, struct pnp_card *card);
 extern struct list_head pnp_cards;
+int pnpc_attach(struct pnp_card *card);
+void pnpc_detach(struct pnp_card *card);
 
 #else
 
@@ -429,32 +467,10 @@
 static inline int pnpc_register_driver(struct pnpc_driver *drv) { return -ENODEV; }
 static inline void pnpc_unregister_driver(struct pnpc_driver *drv) { ; }
 static inline int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
+static inline int pnpc_attach(struct pnp_card *card) { return -ENODEV; }
+static inline void pnpc_detach(struct pnp_card *card) { ; }
 
 #endif /* CONFIG_PNP_CARD */
-
-
-#if defined(CONFIG_ISAPNP)
-
-/* 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
-
-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_ISAPNP */
 
 
 #ifdef DEBUG
diff -Nru a/include/linux/pnpbios.h b/include/linux/pnpbios.h
--- a/include/linux/pnpbios.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/pnpbios.h	Mon Jan 13 10:18:05 2003
@@ -78,15 +78,15 @@
 /*
  * Plug and Play BIOS flags
  */
-#define PNP_NO_DISABLE		0x0001
-#define PNP_NO_CONFIG		0x0002
-#define PNP_OUTPUT		0x0004
-#define PNP_INPUT		0x0008
-#define PNP_BOOTABLE		0x0010
-#define PNP_DOCK		0x0020
-#define PNP_REMOVABLE		0x0040
-#define pnp_is_static(x) (x->flags & 0x0100) == 0x0000
-#define pnp_is_dynamic(x) x->flags & 0x0080
+#define PNPBIOS_NO_DISABLE		0x0001
+#define PNPBIOS_NO_CONFIG		0x0002
+#define PNPBIOS_OUTPUT			0x0004
+#define PNPBIOS_INPUT			0x0008
+#define PNPBIOS_BOOTABLE		0x0010
+#define PNPBIOS_DOCK			0x0020
+#define PNPBIOS_REMOVABLE		0x0040
+#define pnpbios_is_static(x) ((x)->flags & 0x0100) == 0x0000
+#define pnpbios_is_dynamic(x) (x)->flags & 0x0080
 
 /* 0x8000 through 0xffff are OEM defined */
 
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/sched.h	Mon Jan 13 10:18:05 2003
@@ -724,33 +724,23 @@
 		__cond_resched();
 }
 
-#ifdef CONFIG_PREEMPT
-
 /*
  * cond_resched_lock() - if a reschedule is pending, drop the given lock,
  * call schedule, and on return reacquire the lock.
  *
- * Note: this does not assume the given lock is the _only_ lock held.
- * The kernel preemption counter gives us "free" checking that we are
- * atomic -- let's use it.
+ * This works OK both with and without CONFIG_PREEMPT.  We do strange low-level
+ * operations here to prevent schedule() from being called twice (once via
+ * spin_unlock(), once by hand).
  */
 static inline void cond_resched_lock(spinlock_t * lock)
 {
-	if (need_resched() && preempt_count() == 1) {
+	if (need_resched()) {
 		_raw_spin_unlock(lock);
 		preempt_enable_no_resched();
 		__cond_resched();
 		spin_lock(lock);
 	}
 }
-
-#else
-
-static inline void cond_resched_lock(spinlock_t * lock)
-{
-}
-
-#endif
 
 /* Reevaluate whether the task has signals pending delivery.
    This is required every time the blocked sigset_t changes.
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Mon Jan 13 10:18:06 2003
+++ b/include/linux/security.h	Mon Jan 13 10:18:06 2003
@@ -594,6 +594,17 @@
  *	@flag contains the desired (requested) permission set
  *	Return 0 if permission is granted.
  *
+ * Security hooks for individual messages held in System V IPC message queues
+ * @msg_msg_alloc_security:
+ *	Allocate and attach a security structure to the msg->security field.
+ *	The security field is initialized to NULL when the structure is first
+ *	created.
+ *	@msg contains the message structure to be modified.
+ *	Return 0 if operation was successful and permission is granted.
+ * @msg_msg_free_security:
+ *	Deallocate the security structure for this message.
+ *	@msg contains the message structure to be modified.
+ *
  * Security hooks for System V IPC Message Queues
  *
  * @msg_queue_alloc_security:
@@ -605,6 +616,39 @@
  * @msg_queue_free_security:
  *	Deallocate security structure for this message queue.
  *	@msq contains the message queue structure to be modified.
+ * @msg_queue_associate:
+ *	Check permission when a message queue is requested through the
+ *	msgget system call.  This hook is only called when returning the
+ *	message queue identifier for an existing message queue, not when a
+ *	new message queue is created.
+ *	@msq contains the message queue to act upon.
+ *	@msqflg contains the operation control flags.
+ *	Return 0 if permission is granted.
+ * @msg_queue_msgctl:
+ *	Check permission when a message control operation specified by @cmd
+ *	is to be performed on the message queue @msq.
+ *	The @msq may be NULL, e.g. for IPC_INFO or MSG_INFO.
+ *	@msq contains the message queue to act upon.  May be NULL.
+ *	@cmd contains the operation to be performed.
+ *	Return 0 if permission is granted.  
+ * @msg_queue_msgsnd:
+ *	Check permission before a message, @msg, is enqueued on the message
+ *	queue, @msq.
+ *	@msq contains the message queue to send message to.
+ *	@msg contains the message to be enqueued.
+ *	@msqflg contains operational flags.
+ *	Return 0 if permission is granted.
+ * @msg_queue_msgrcv:
+ *	Check permission before a message, @msg, is removed from the message
+ *	queue, @msq.  The @target task structure contains a pointer to the 
+ *	process that will be receiving the message (not equal to the current 
+ *	process when inline receives are being performed).
+ *	@msq contains the message queue to retrieve message from.
+ *	@msg contains the message destination.
+ *	@target contains the task structure for recipient process.
+ *	@type contains the type of message requested.
+ *	@mode contains the operational flags.
+ *	Return 0 if permission is granted.
  *
  * Security hooks for System V Shared Memory Segments
  *
@@ -617,6 +661,29 @@
  * @shm_free_security:
  *	Deallocate the security struct for this memory segment.
  *	@shp contains the shared memory structure to be modified.
+ * @shm_associate:
+ *	Check permission when a shared memory region is requested through the
+ *	shmget system call.  This hook is only called when returning the shared
+ *	memory region identifier for an existing region, not when a new shared
+ *	memory region is created.
+ *	@shp contains the shared memory structure to be modified.
+ *	@shmflg contains the operation control flags.
+ *	Return 0 if permission is granted.
+ * @shm_shmctl:
+ *	Check permission when a shared memory control operation specified by
+ *	@cmd is to be performed on the shared memory region @shp.
+ *	The @shp may be NULL, e.g. for IPC_INFO or SHM_INFO.
+ *	@shp contains shared memory structure to be modified.
+ *	@cmd contains the operation to be performed.
+ *	Return 0 if permission is granted.
+ * @shm_shmat:
+ *	Check permissions prior to allowing the shmat system call to attach the
+ *	shared memory segment @shp to the data segment of the calling process.
+ *	The attaching address is specified by @shmaddr.
+ *	@shp contains the shared memory structure to be modified.
+ *	@shmaddr contains the address to attach memory region to.
+ *	@shmflg contains the operational flags.
+ *	Return 0 if permission is granted.
  *
  * Security hooks for System V Semaphores
  *
@@ -629,6 +696,30 @@
  * @sem_free_security:
  *	deallocate security struct for this semaphore
  *	@sma contains the semaphore structure.
+ * @sem_associate:
+ *	Check permission when a semaphore is requested through the semget
+ *	system call.  This hook is only called when returning the semaphore
+ *	identifier for an existing semaphore, not when a new one must be
+ *	created.
+ *	@sma contains the semaphore structure.
+ *	@semflg contains the operation control flags.
+ *	Return 0 if permission is granted.
+ * @sem_semctl:
+ *	Check permission when a semaphore operation specified by @cmd is to be
+ *	performed on the semaphore @sma.  The @sma may be NULL, e.g. for 
+ *	IPC_INFO or SEM_INFO.
+ *	@sma contains the semaphore structure.  May be NULL.
+ *	@cmd contains the operation to be performed.
+ *	Return 0 if permission is granted.
+ * @sem_semop
+ *	Check permissions before performing operations on members of the
+ *	semaphore set @sma.  If the @alter flag is nonzero, the semaphore set 
+ *      may be modified.
+ *	@sma contains the semaphore structure.
+ *	@sops contains the operations to perform.
+ *	@nsops contains the number of operations to perform.
+ *	@alter contains the flag indicating whether changes are to be made.
+ *	Return 0 if permission is granted.
  *
  * @ptrace:
  *	Check permission before allowing the @parent process to trace the
@@ -828,14 +919,33 @@
 
 	int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
 
+	int (*msg_msg_alloc_security) (struct msg_msg * msg);
+	void (*msg_msg_free_security) (struct msg_msg * msg);
+
 	int (*msg_queue_alloc_security) (struct msg_queue * msq);
 	void (*msg_queue_free_security) (struct msg_queue * msq);
+	int (*msg_queue_associate) (struct msg_queue * msq, int msqflg);
+	int (*msg_queue_msgctl) (struct msg_queue * msq, int cmd);
+	int (*msg_queue_msgsnd) (struct msg_queue * msq,
+				 struct msg_msg * msg, int msqflg);
+	int (*msg_queue_msgrcv) (struct msg_queue * msq,
+				 struct msg_msg * msg,
+				 struct task_struct * target,
+				 long type, int mode);
 
 	int (*shm_alloc_security) (struct shmid_kernel * shp);
 	void (*shm_free_security) (struct shmid_kernel * shp);
+	int (*shm_associate) (struct shmid_kernel * shp, int shmflg);
+	int (*shm_shmctl) (struct shmid_kernel * shp, int cmd);
+	int (*shm_shmat) (struct shmid_kernel * shp, 
+			  char *shmaddr, int shmflg);
 
 	int (*sem_alloc_security) (struct sem_array * sma);
 	void (*sem_free_security) (struct sem_array * sma);
+	int (*sem_associate) (struct sem_array * sma, int semflg);
+	int (*sem_semctl) (struct sem_array * sma, int cmd);
+	int (*sem_semop) (struct sem_array * sma, 
+			  struct sembuf * sops, unsigned nsops, int alter);
 
 	/* allow module stacking */
 	int (*register_security) (const char *name,
@@ -1334,6 +1444,16 @@
 	return security_ops->ipc_permission (ipcp, flag);
 }
 
+static inline int security_msg_msg_alloc (struct msg_msg * msg)
+{
+	return security_ops->msg_msg_alloc_security (msg);
+}
+
+static inline void security_msg_msg_free (struct msg_msg * msg)
+{
+	security_ops->msg_msg_free_security(msg);
+}
+
 static inline int security_msg_queue_alloc (struct msg_queue *msq)
 {
 	return security_ops->msg_queue_alloc_security (msq);
@@ -1344,6 +1464,31 @@
 	security_ops->msg_queue_free_security (msq);
 }
 
+static inline int security_msg_queue_associate (struct msg_queue * msq, 
+						int msqflg)
+{
+	return security_ops->msg_queue_associate (msq, msqflg);
+}
+
+static inline int security_msg_queue_msgctl (struct msg_queue * msq, int cmd)
+{
+	return security_ops->msg_queue_msgctl (msq, cmd);
+}
+
+static inline int security_msg_queue_msgsnd (struct msg_queue * msq,
+					     struct msg_msg * msg, int msqflg)
+{
+	return security_ops->msg_queue_msgsnd (msq, msg, msqflg);
+}
+
+static inline int security_msg_queue_msgrcv (struct msg_queue * msq,
+					     struct msg_msg * msg,
+					     struct task_struct * target,
+					     long type, int mode)
+{
+	return security_ops->msg_queue_msgrcv (msq, msg, target, type, mode);
+}
+
 static inline int security_shm_alloc (struct shmid_kernel *shp)
 {
 	return security_ops->shm_alloc_security (shp);
@@ -1354,6 +1499,23 @@
 	security_ops->shm_free_security (shp);
 }
 
+static inline int security_shm_associate (struct shmid_kernel * shp, 
+					  int shmflg)
+{
+	return security_ops->shm_associate(shp, shmflg);
+}
+
+static inline int security_shm_shmctl (struct shmid_kernel * shp, int cmd)
+{
+	return security_ops->shm_shmctl (shp, cmd);
+}
+
+static inline int security_shm_shmat (struct shmid_kernel * shp, 
+				      char *shmaddr, int shmflg)
+{
+	return security_ops->shm_shmat(shp, shmaddr, shmflg);
+}
+
 static inline int security_sem_alloc (struct sem_array *sma)
 {
 	return security_ops->sem_alloc_security (sma);
@@ -1364,6 +1526,22 @@
 	security_ops->sem_free_security (sma);
 }
 
+static inline int security_sem_associate (struct sem_array * sma, int semflg)
+{
+	return security_ops->sem_associate (sma, semflg);
+}
+
+static inline int security_sem_semctl (struct sem_array * sma, int cmd)
+{
+	return security_ops->sem_semctl(sma, cmd);
+}
+
+static inline int security_sem_semop (struct sem_array * sma, 
+				      struct sembuf * sops, unsigned nsops, 
+				      int alter)
+{
+	return security_ops->sem_semop(sma, sops, nsops, alter);
+}
 
 /* prototypes */
 extern int security_scaffolding_startup	(void);
@@ -1835,6 +2013,14 @@
 	return 0;
 }
 
+static inline int security_msg_msg_alloc (struct msg_msg * msg)
+{
+	return 0;
+}
+
+static inline void security_msg_msg_free (struct msg_msg * msg)
+{ }
+
 static inline int security_msg_queue_alloc (struct msg_queue *msq)
 {
 	return 0;
@@ -1843,6 +2029,31 @@
 static inline void security_msg_queue_free (struct msg_queue *msq)
 { }
 
+static inline int security_msg_queue_associate (struct msg_queue * msq, 
+						int msqflg)
+{
+	return 0;
+}
+
+static inline int security_msg_queue_msgctl (struct msg_queue * msq, int cmd)
+{
+	return 0;
+}
+
+static inline int security_msg_queue_msgsnd (struct msg_queue * msq,
+					     struct msg_msg * msg, int msqflg)
+{
+	return 0;
+}
+
+static inline int security_msg_queue_msgrcv (struct msg_queue * msq,
+					     struct msg_msg * msg,
+					     struct task_struct * target,
+					     long type, int mode)
+{
+	return 0;
+}
+
 static inline int security_shm_alloc (struct shmid_kernel *shp)
 {
 	return 0;
@@ -1851,6 +2062,23 @@
 static inline void security_shm_free (struct shmid_kernel *shp)
 { }
 
+static inline int security_shm_associate (struct shmid_kernel * shp, 
+					  int shmflg)
+{
+	return 0;
+}
+
+static inline int security_shm_shmctl (struct shmid_kernel * shp, int cmd)
+{
+	return 0;
+}
+
+static inline int security_shm_shmat (struct shmid_kernel * shp, 
+				      char *shmaddr, int shmflg)
+{
+	return 0;
+}
+
 static inline int security_sem_alloc (struct sem_array *sma)
 {
 	return 0;
@@ -1859,6 +2087,22 @@
 static inline void security_sem_free (struct sem_array *sma)
 { }
 
+static inline int security_sem_associate (struct sem_array * sma, int semflg)
+{
+	return 0;
+}
+
+static inline int security_sem_semctl (struct sem_array * sma, int cmd)
+{
+	return 0;
+}
+
+static inline int security_sem_semop (struct sem_array * sma, 
+				      struct sembuf * sops, unsigned nsops, 
+				      int alter)
+{
+	return 0;
+}
 
 #endif	/* CONFIG_SECURITY */
 
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	Mon Jan 13 10:18:06 2003
+++ b/include/linux/skbuff.h	Mon Jan 13 10:18:06 2003
@@ -287,6 +287,7 @@
 extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
 				       int newheadroom, int newtailroom,
 				       int priority);
+extern struct sk_buff *		skb_pad(struct sk_buff *skb, int pad);
 #define dev_kfree_skb(a)	kfree_skb(a)
 extern void	      skb_over_panic(struct sk_buff *skb, int len,
 				     void *here);
@@ -1085,6 +1086,26 @@
 	if (delta || skb_cloned(skb))
 		return pskb_expand_head(skb, (delta + 15) & ~15, 0, GFP_ATOMIC);
 	return 0;
+}
+
+/**
+ *	skb_padto	- pad an skbuff up to a minimal size
+ *	@skb: buffer to pad
+ *	@len: minimal length
+ *
+ *	Pads up a buffer to ensure the trailing bytes exist and are
+ *	blanked. If the buffer already contains sufficient data it
+ *	is untouched. Returns the buffer, which may be a replacement
+ *	for the original, or NULL for out of memory - in which case
+ *	the original buffer is still freed.
+ */
+ 
+static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len)
+{
+	unsigned int size = skb->len + skb->data_len;
+	if (likely(size >= len))
+		return skb;
+	return skb_pad(skb, len-size);
 }
 
 /**
diff -Nru a/include/linux/spinlock.h b/include/linux/spinlock.h
--- a/include/linux/spinlock.h	Mon Jan 13 10:18:06 2003
+++ b/include/linux/spinlock.h	Mon Jan 13 10:18:06 2003
@@ -85,31 +85,37 @@
  * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
  * methods are defined as nops in the case they are not required.
  */
-#define spin_lock(lock)	\
-do { \
-	preempt_disable(); \
-	_raw_spin_lock(lock); \
-} while(0)
-
 #define spin_trylock(lock)	({preempt_disable(); _raw_spin_trylock(lock) ? \
 				1 : ({preempt_enable(); 0;});})
 
-#define spin_unlock(lock) \
+#define write_trylock(lock)	({preempt_disable();_raw_write_trylock(lock) ? \
+				1 : ({preempt_enable(); 0;});})
+
+/* Where's read_trylock? */
+
+#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
+void __preempt_spin_lock(spinlock_t *lock);
+void __preempt_write_lock(rwlock_t *lock);
+
+#define spin_lock(lock) \
 do { \
-	_raw_spin_unlock(lock); \
-	preempt_enable(); \
+	preempt_disable(); \
+	if (unlikely(!_raw_spin_trylock(lock))) \
+		__preempt_spin_lock(lock); \
 } while (0)
 
-#define read_lock(lock)	\
+#define write_lock(lock) \
 do { \
 	preempt_disable(); \
-	_raw_read_lock(lock); \
-} while(0)
+	if (unlikely(!_raw_write_trylock(lock))) \
+		__preempt_write_lock(lock); \
+} while (0)
 
-#define read_unlock(lock) \
+#else
+#define spin_lock(lock)	\
 do { \
-	_raw_read_unlock(lock); \
-	preempt_enable(); \
+	preempt_disable(); \
+	_raw_spin_lock(lock); \
 } while(0)
 
 #define write_lock(lock) \
@@ -117,6 +123,19 @@
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while(0)
+#endif
+
+#define read_lock(lock)	\
+do { \
+	preempt_disable(); \
+	_raw_read_lock(lock); \
+} while(0)
+
+#define spin_unlock(lock) \
+do { \
+	_raw_spin_unlock(lock); \
+	preempt_enable(); \
+} while (0)
 
 #define write_unlock(lock) \
 do { \
@@ -124,8 +143,11 @@
 	preempt_enable(); \
 } while(0)
 
-#define write_trylock(lock)	({preempt_disable();_raw_write_trylock(lock) ? \
-				1 : ({preempt_enable(); 0;});})
+#define read_unlock(lock) \
+do { \
+	_raw_read_unlock(lock); \
+	preempt_enable(); \
+} while(0)
 
 #define spin_lock_irqsave(lock, flags) \
 do { \
diff -Nru a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
--- a/include/linux/sunrpc/svcauth.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/sunrpc/svcauth.h	Mon Jan 13 10:18:05 2003
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/cache.h>
-#include <linux/string.h>
+#include <linux/hash.h>
 
 struct svc_cred {
 	uid_t			cr_uid;
@@ -83,7 +83,7 @@
 struct auth_ops {
 	char *	name;
 	int	flavour;
-	int	(*accept)(struct svc_rqst *rq, u32 *authp, int proc);
+	int	(*accept)(struct svc_rqst *rq, u32 *authp);
 	int	(*release)(struct svc_rqst *rq);
 	void	(*domain_release)(struct auth_domain *);
 };
@@ -99,7 +99,7 @@
 #define	SVC_PENDING	8
 
 
-extern int	svc_authenticate(struct svc_rqst *rqstp, u32 *statp, u32 *authp, int proc);
+extern int	svc_authenticate(struct svc_rqst *rqstp, u32 *authp);
 extern int	svc_authorise(struct svc_rqst *rqstp);
 extern int	svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
 extern void	svc_auth_unregister(rpc_authflavor_t flavor);
@@ -113,10 +113,41 @@
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 
-extern int hash_mem(char *buf, int len, int bits);
-static inline int hash_str(char *name, int bits)
+static inline unsigned long hash_str(char *name, int bits)
 {
-	return hash_mem(name, strlen(name), bits);
+	unsigned long hash = 0;
+	unsigned long l = 0;
+	int len = 0;
+	unsigned char c;
+	do {
+		if (unlikely(!(c = *name++))) {
+			c = (char)len; len = -1;
+		}
+		l = (l << 8) | c;
+		len++;
+		if ((len & (BITS_PER_LONG/8-1))==0)
+			hash = hash_long(hash^l, BITS_PER_LONG);
+	} while (len);
+	return hash >> (BITS_PER_LONG - bits);
+}
+
+static inline unsigned long hash_mem(char *buf, int length, int bits)
+{
+	unsigned long hash = 0;
+	unsigned long l = 0;
+	int len = 0;
+	unsigned char c;
+	do {
+		if (len == length) {
+			c = (char)len; len = -1;
+		} else
+			c = *buf++;
+		l = (l << 8) | c;
+		len++;
+		if ((len & (BITS_PER_LONG/8-1))==0)
+			hash = hash_long(hash^l, BITS_PER_LONG);
+	} while (len);
+	return hash >> (BITS_PER_LONG - bits);
 }
 
 extern struct cache_detail auth_domain_cache, ip_map_cache;
diff -Nru a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
--- a/include/linux/sunrpc/svcsock.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/sunrpc/svcsock.h	Mon Jan 13 10:18:05 2003
@@ -28,7 +28,6 @@
 #define	SK_CLOSE	2			/* dead or dying */
 #define	SK_DATA		3			/* data pending */
 #define	SK_TEMP		4			/* temp (TCP) socket */
-#define	SK_QUED		5			/* on serv->sk_sockets */
 #define	SK_DEAD		6			/* socket closed */
 #define	SK_CHNGBUF	7			/* need to change snd/rcv buffer sizes */
 #define	SK_DEFERRED	8			/* request on sk_deferred */
diff -Nru a/include/linux/sysfs.h b/include/linux/sysfs.h
--- a/include/linux/sysfs.h	Mon Jan 13 10:18:05 2003
+++ b/include/linux/sysfs.h	Mon Jan 13 10:18:05 2003
@@ -17,8 +17,8 @@
 };
 
 struct sysfs_ops {
-	ssize_t	(*show)(struct kobject *, struct attribute *,char *, size_t, loff_t);
-	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t, loff_t);
+	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
+	ssize_t	(*store)(struct kobject *,struct attribute *,const char *);
 };
 
 extern int
diff -Nru a/include/linux/videodev.h b/include/linux/videodev.h
--- a/include/linux/videodev.h	Mon Jan 13 10:18:07 2003
+++ b/include/linux/videodev.h	Mon Jan 13 10:18:07 2003
@@ -395,7 +395,7 @@
 #define VID_HARDWARE_MEYE	32	/* Sony Vaio MotionEye cameras */
 #define VID_HARDWARE_CPIA2	33
 #define VID_HARDWARE_VICAM      34
-
+#define VID_HARDWARE_SF16FMR2	35
 #endif /* __LINUX_VIDEODEV_H */
 
 /*
diff -Nru a/ipc/msg.c b/ipc/msg.c
--- a/ipc/msg.c	Mon Jan 13 10:18:04 2003
+++ b/ipc/msg.c	Mon Jan 13 10:18:04 2003
@@ -132,6 +132,9 @@
 static void free_msg(struct msg_msg* msg)
 {
 	struct msg_msgseg* seg;
+
+	security_msg_msg_free(msg);
+
 	seg = msg->next;
 	kfree(msg);
 	while(seg != NULL) {
@@ -157,6 +160,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	msg->next = NULL;
+	msg->security = NULL;
 
 	if (copy_from_user(msg+1, src, alen)) {
 		err = -EFAULT;
@@ -186,6 +190,11 @@
 		len -= alen;
 		src = ((char*)src)+alen;
 	}
+	
+	err = security_msg_msg_alloc(msg);
+	if (err)
+		goto out_err;
+
 	return msg;
 
 out_err:
@@ -308,8 +317,12 @@
 			BUG();
 		if (ipcperms(&msq->q_perm, msgflg))
 			ret = -EACCES;
-		else
-			ret = msg_buildid(id, msq->q_perm.seq);
+		else {
+			int qid = msg_buildid(id, msq->q_perm.seq);
+		    	ret = security_msg_queue_associate(msq, msgflg);
+			if (!ret)
+				ret = qid;
+		}
 		msg_unlock(msq);
 	}
 	up(&msg_ids.sem);
@@ -431,6 +444,11 @@
 		 * due to padding, it's not enough
 		 * to set all member fields.
 		 */
+
+		err = security_msg_queue_msgctl(NULL, cmd);
+		if (err)
+			return err;
+
 		memset(&msginfo,0,sizeof(msginfo));	
 		msginfo.msgmni = msg_ctlmni;
 		msginfo.msgmax = msg_ctlmax;
@@ -481,6 +499,10 @@
 		if (ipcperms (&msq->q_perm, S_IRUGO))
 			goto out_unlock;
 
+		err = security_msg_queue_msgctl(msq, cmd);
+		if (err)
+			goto out_unlock;
+
 		kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
 		tbuf.msg_stime  = msq->q_stime;
 		tbuf.msg_rtime  = msq->q_rtime;
@@ -523,11 +545,16 @@
 	    /* We _could_ check for CAP_CHOWN above, but we don't */
 		goto out_unlock_up;
 
+	err = security_msg_queue_msgctl(msq, cmd);
+	if (err)
+		goto out_unlock_up;
+
 	switch (cmd) {
 	case IPC_SET:
 	{
 		if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
 			goto out_unlock_up;
+
 		msq->q_qbytes = setbuf.qbytes;
 
 		ipcp->uid = setbuf.uid;
@@ -593,7 +620,8 @@
 		struct msg_receiver* msr;
 		msr = list_entry(tmp,struct msg_receiver,r_list);
 		tmp = tmp->next;
-		if(testmsg(msg,msr->r_msgtype,msr->r_mode)) {
+		if(testmsg(msg,msr->r_msgtype,msr->r_mode) &&
+		   !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) {
 			list_del(&msr->r_list);
 			if(msr->r_maxsize < msg->m_ts) {
 				msr->r_msg = ERR_PTR(-E2BIG);
@@ -644,6 +672,10 @@
 	if (ipcperms(&msq->q_perm, S_IWUGO)) 
 		goto out_unlock_free;
 
+	err = security_msg_queue_msgsnd(msq, msg, msgflg);
+	if (err)
+		goto out_unlock_free;
+
 	if(msgsz + msq->q_cbytes > msq->q_qbytes ||
 		1 + msq->q_qnum > msq->q_qbytes) {
 		struct msg_sender s;
@@ -742,7 +774,8 @@
 	found_msg=NULL;
 	while (tmp != &msq->q_messages) {
 		msg = list_entry(tmp,struct msg_msg,m_list);
-		if(testmsg(msg,msgtyp,mode)) {
+		if(testmsg(msg,msgtyp,mode) &&
+		   !security_msg_queue_msgrcv(msq, msg, current, msgtyp, mode)) {
 			found_msg = msg;
 			if(mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
 				found_msg=msg;
diff -Nru a/ipc/sem.c b/ipc/sem.c
--- a/ipc/sem.c	Mon Jan 13 10:18:05 2003
+++ b/ipc/sem.c	Mon Jan 13 10:18:05 2003
@@ -188,8 +188,12 @@
 			err = -EINVAL;
 		else if (ipcperms(&sma->sem_perm, semflg))
 			err = -EACCES;
-		else
-			err = sem_buildid(id, sma->sem_perm.seq);
+		else {
+			int semid = sem_buildid(id, sma->sem_perm.seq);
+			err = security_sem_associate(sma, semflg);
+			if (!err)
+				err = semid;
+		}
 		sem_unlock(sma);
 	}
 
@@ -466,6 +470,10 @@
 		struct seminfo seminfo;
 		int max_id;
 
+		err = security_sem_semctl(NULL, cmd);
+		if (err)
+			return err;
+		
 		memset(&seminfo,0,sizeof(seminfo));
 		seminfo.semmni = sc_semmni;
 		seminfo.semmns = sc_semmns;
@@ -506,6 +514,11 @@
 		err = -EACCES;
 		if (ipcperms (&sma->sem_perm, S_IRUGO))
 			goto out_unlock;
+
+		err = security_sem_semctl(sma, cmd);
+		if (err)
+			goto out_unlock;
+
 		id = sem_buildid(semid, sma->sem_perm.seq);
 
 		kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
@@ -549,6 +562,11 @@
 	if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
 		goto out_unlock;
 
+	err = security_sem_semctl(sma, cmd);
+	if (err)
+		goto out_unlock;
+
+	err = -EACCES;
 	switch (cmd) {
 	case GETALL:
 	{
@@ -740,6 +758,10 @@
 		goto out_unlock;
 	}
 
+	err = security_sem_semctl(sma, cmd);
+	if (err)
+		goto out_unlock;
+
 	switch(cmd){
 	case IPC_RMID:
 		freeary(semid);
@@ -1035,6 +1057,12 @@
 	error = -EACCES;
 	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
 		goto out_unlock_semundo_free;
+
+	error = security_sem_semop(sma, sops, nsops, alter);
+	if (error)
+		goto out_unlock_semundo_free;
+
+	error = -EACCES;		
 	if (undos) {
 		/* Make sure we have an undo structure
 		 * for this process and this semaphore set.
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	Mon Jan 13 10:18:06 2003
+++ b/ipc/shm.c	Mon Jan 13 10:18:06 2003
@@ -257,8 +257,12 @@
 			err = -EINVAL;
 		else if (ipcperms(&shp->shm_perm, shmflg))
 			err = -EACCES;
-		else
-			err = shm_buildid(id, shp->shm_perm.seq);
+		else {
+			int shmid = shm_buildid(id, shp->shm_perm.seq);
+			err = security_shm_associate(shp, shmflg);
+			if (!err)
+				err = shmid;
+		}
 		shm_unlock(shp);
 	}
 	up(&shm_ids.sem);
@@ -399,6 +403,10 @@
 	{
 		struct shminfo64 shminfo;
 
+		err = security_shm_shmctl(NULL, cmd);
+		if (err)
+			return err;
+
 		memset(&shminfo,0,sizeof(shminfo));
 		shminfo.shmmni = shminfo.shmseg = shm_ctlmni;
 		shminfo.shmmax = shm_ctlmax;
@@ -417,6 +425,10 @@
 	{
 		struct shm_info shm_info;
 
+		err = security_shm_shmctl(NULL, cmd);
+		if (err)
+			return err;
+
 		memset(&shm_info,0,sizeof(shm_info));
 		down(&shm_ids.sem);
 		shm_info.used_ids = shm_ids.in_use;
@@ -458,6 +470,9 @@
 		err=-EACCES;
 		if (ipcperms (&shp->shm_perm, S_IRUGO))
 			goto out_unlock;
+		err = security_shm_shmctl(shp, cmd);
+		if (err)
+			goto out_unlock;
 		kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
 		tbuf.shm_segsz	= shp->shm_segsz;
 		tbuf.shm_atime	= shp->shm_atim;
@@ -495,6 +510,11 @@
 		err = shm_checkid(shp,shmid);
 		if(err)
 			goto out_unlock;
+
+		err = security_shm_shmctl(shp, cmd);
+		if (err)
+			goto out_unlock;
+		
 		if(cmd==SHM_LOCK) {
 			if (!is_file_hugepages(shp->shm_file))
 				shmem_lock(shp->shm_file, 1);
@@ -527,12 +547,18 @@
 		err = shm_checkid(shp, shmid);
 		if(err)
 			goto out_unlock_up;
+
 		if (current->euid != shp->shm_perm.uid &&
 		    current->euid != shp->shm_perm.cuid && 
 		    !capable(CAP_SYS_ADMIN)) {
 			err=-EPERM;
 			goto out_unlock_up;
 		}
+
+		err = security_shm_shmctl(shp, cmd);
+		if (err)
+			goto out_unlock_up;
+
 		if (shp->shm_nattch){
 			shp->shm_flags |= SHM_DEST;
 			/* Do not find it any more */
@@ -565,6 +591,10 @@
 			goto out_unlock_up;
 		}
 
+		err = security_shm_shmctl(shp, cmd);
+		if (err)
+			goto out_unlock_up;
+		
 		shp->shm_perm.uid = setbuf.uid;
 		shp->shm_perm.gid = setbuf.gid;
 		shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO)
@@ -653,6 +683,13 @@
 		err = -EACCES;
 		goto out;
 	}
+
+	err = security_shm_shmat(shp, shmaddr, shmflg);
+	if (err) {
+		shm_unlock(shp);
+		return err;
+	}
+		
 	file = shp->shm_file;
 	size = file->f_dentry->d_inode->i_size;
 	shp->shm_nattch++;
diff -Nru a/kernel/cpufreq.c b/kernel/cpufreq.c
--- a/kernel/cpufreq.c	Mon Jan 13 10:18:05 2003
+++ b/kernel/cpufreq.c	Mon Jan 13 10:18:05 2003
@@ -734,8 +734,8 @@
 }
 
 #else
-#define cpufreq_sysctl_init()
-#define cpufreq_sysctl_exit()
+#define cpufreq_sysctl_init() do {} while(0)
+#define cpufreq_sysctl_exit() do {} while(0)
 #endif /* CONFIG_SYSCTL */
 #endif /* CONFIG_CPU_FREQ_24_API */
 
@@ -946,7 +946,7 @@
 		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
 }
 #else
-#define adjust_jiffies(...)
+#define adjust_jiffies(x...) do {} while (0)
 #endif
 
 
@@ -1131,6 +1131,123 @@
 }
 EXPORT_SYMBOL_GPL(cpufreq_restore);
 #else
-#define cpufreq_restore()
+#define cpufreq_restore() do {} while (0)
 #endif /* CONFIG_PM */
 
+
+/*********************************************************************
+ *                     FREQUENCY TABLE HELPERS                       *
+ *********************************************************************/
+
+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+				    struct cpufreq_frequency_table *table)
+{
+	unsigned int min_freq = ~0;
+	unsigned int max_freq = 0;
+	unsigned int i = 0;
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if (freq < min_freq)
+			min_freq = freq;
+		if (freq > max_freq)
+			max_freq = freq;
+	}
+
+	policy->min = policy->cpuinfo.min_freq = min_freq;
+	policy->max = policy->cpuinfo.max_freq = max_freq;
+
+	if (policy->min == ~0)
+		return -EINVAL;
+	else
+		return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
+
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+				   struct cpufreq_frequency_table *table)
+{
+	unsigned int next_larger = ~0;
+	unsigned int i = 0;
+	unsigned int count = 0;
+
+	if (!cpu_online(policy->cpu))
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if ((freq >= policy->min) && (freq <= policy->max))
+			count++;
+		else if ((next_larger > freq) && (freq > policy->max))
+			next_larger = freq;
+	}
+
+	if (!count)
+		policy->max = next_larger;
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
+
+
+int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
+				      struct cpufreq_frequency_table *table,
+				      unsigned int *index)
+{
+	struct cpufreq_frequency_table optimal = { .index = ~0, };
+	unsigned int i;
+
+	switch (policy->policy) {
+	case CPUFREQ_POLICY_PERFORMANCE:
+		optimal.frequency = 0;
+		break;
+	case CPUFREQ_POLICY_POWERSAVE:
+		optimal.frequency = ~0;
+		break;
+	}
+
+	if (!cpu_online(policy->cpu))
+		return -EINVAL;
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if ((freq < policy->min) || (freq > policy->max))
+			continue;
+		switch(policy->policy) {
+		case CPUFREQ_POLICY_PERFORMANCE:
+			if (optimal.frequency <= freq) {
+				optimal.frequency = freq;
+				optimal.index = i;
+			}
+			break;
+		case CPUFREQ_POLICY_POWERSAVE:
+			if (optimal.frequency >= freq) {
+				optimal.frequency = freq;
+				optimal.index = i;
+			}
+			break;
+		}
+	}
+	if (optimal.index > i)
+		return -EINVAL;
+
+	*index = optimal.index;
+	
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Mon Jan 13 10:18:05 2003
+++ b/kernel/fork.c	Mon Jan 13 10:18:05 2003
@@ -262,9 +262,9 @@
 				atomic_dec(&inode->i_writecount);
       
 			/* insert tmp into the share list, just after mpnt */
-			spin_lock(&inode->i_mapping->i_shared_lock);
+			down(&inode->i_mapping->i_shared_sem);
 			list_add_tail(&tmp->shared, &mpnt->shared);
-			spin_unlock(&inode->i_mapping->i_shared_lock);
+			up(&inode->i_mapping->i_shared_sem);
 		}
 
 		/*
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Mon Jan 13 10:18:05 2003
+++ b/kernel/ksyms.c	Mon Jan 13 10:18:05 2003
@@ -491,6 +491,10 @@
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
 EXPORT_SYMBOL(__might_sleep);
 #endif
+#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
+EXPORT_SYMBOL(__preempt_spin_lock);
+EXPORT_SYMBOL(__preempt_write_lock);
+#endif
 #if !defined(__ia64__)
 EXPORT_SYMBOL(loops_per_jiffy);
 #endif
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Mon Jan 13 10:18:06 2003
+++ b/kernel/module.c	Mon Jan 13 10:18:06 2003
@@ -679,19 +679,19 @@
 	if (!kp)
 		return -ENOMEM;
 
-	DEBUGP("Module %s has %u obsolete params\n", name, num);
-	for (i = 0; i < num; i++)
-		DEBUGP("Param %i: %s type %s\n",
-		       num, obsparm[i].name, obsparm[i].type);
-
 	for (i = 0; i < num; i++) {
+		char sym_name[128 + sizeof(MODULE_SYMBOL_PREFIX)];
+
+		snprintf(sym_name, sizeof(sym_name), "%s%s",
+			 MODULE_SYMBOL_PREFIX, obsparm[i].name);
+
 		kp[i].name = obsparm[i].name;
 		kp[i].perm = 000;
 		kp[i].set = set_obsolete;
 		kp[i].get = NULL;
 		obsparm[i].addr
 			= (void *)find_local_symbol(sechdrs, symindex, strtab,
-						    obsparm[i].name);
+						    sym_name);
 		if (!obsparm[i].addr) {
 			printk("%s: falsely claims to have parameter %s\n",
 			       name, obsparm[i].name);
@@ -1096,17 +1096,17 @@
 	mod = (void *)sechdrs[modindex].sh_addr;
 
 	/* Now copy in args */
-	err = strlen_user(uargs);
-	if (err < 0)
+	arglen = strlen_user(uargs);
+	if (!arglen) {
+		err = -EFAULT;
 		goto free_hdr;
-	arglen = err;
-
-	args = kmalloc(arglen+1, GFP_KERNEL);
+	}
+	args = kmalloc(arglen, GFP_KERNEL);
 	if (!args) {
 		err = -ENOMEM;
 		goto free_hdr;
 	}
-	if (copy_from_user(args, uargs, arglen+1) != 0) {
+	if (copy_from_user(args, uargs, arglen) != 0) {
 		err = -EFAULT;
 		goto free_mod;
 	}
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	Mon Jan 13 10:18:07 2003
+++ b/kernel/ptrace.c	Mon Jan 13 10:18:07 2003
@@ -115,7 +115,7 @@
 	__ptrace_link(task, current);
 	write_unlock_irq(&tasklist_lock);
 
-	send_sig(SIGSTOP, task, 1);
+	force_sig_specific(SIGSTOP, task);
 	return 0;
 
 bad:
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Mon Jan 13 10:18:07 2003
+++ b/kernel/sched.c	Mon Jan 13 10:18:07 2003
@@ -2278,3 +2278,50 @@
 #endif
 }
 #endif
+
+
+#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
+/*
+ * This could be a long-held lock.  If another CPU holds it for a long time,
+ * and that CPU is not asked to reschedule then *this* CPU will spin on the
+ * lock for a long time, even if *this* CPU is asked to reschedule.
+ *
+ * So what we do here, in the slow (contended) path is to spin on the lock by
+ * hand while permitting preemption.
+ *
+ * Called inside preempt_disable().
+ */
+void __preempt_spin_lock(spinlock_t *lock)
+{
+	if (preempt_count() > 1) {
+		_raw_spin_lock(lock);
+		return;
+	}
+
+	while (!_raw_spin_trylock(lock)) {
+		if (need_resched()) {
+			preempt_enable_no_resched();
+			__cond_resched();
+			preempt_disable();
+		}
+		cpu_relax();
+	}
+}
+
+void __preempt_write_lock(rwlock_t *lock)
+{
+	if (preempt_count() > 1) {
+		_raw_write_lock(lock);
+		return;
+	}
+
+	while (!_raw_write_trylock(lock)) {
+		if (need_resched()) {
+			preempt_enable_no_resched();
+			__cond_resched();
+			preempt_disable();
+		}
+		cpu_relax();
+	}
+}
+#endif
diff -Nru a/lib/kobject.c b/lib/kobject.c
--- a/lib/kobject.c	Mon Jan 13 10:18:07 2003
+++ b/lib/kobject.c	Mon Jan 13 10:18:07 2003
@@ -79,6 +79,29 @@
 	kobj->kset = kset_get(kobj->kset);
 }
 
+
+/**
+ *	unlink - remove kobject from kset list.
+ *	@kobj:	kobject.
+ *
+ *	Remove the kobject from the kset list and decrement
+ *	its parent's refcount.
+ *	This is separated out, so we can use it in both 
+ *	kobject_del() and kobject_add() on error.
+ */
+
+static void unlink(struct kobject * kobj)
+{
+	if (kobj->kset) {
+		down_write(&kobj->kset->subsys->rwsem);
+		list_del_init(&kobj->entry);
+		up_write(&kobj->kset->subsys->rwsem);
+	}
+	if (kobj->parent) 
+		kobject_put(kobj->parent);
+	kobject_put(kobj);
+}
+
 /**
  *	kobject_add - add an object to the hierarchy.
  *	@kobj:	object.
@@ -109,8 +132,8 @@
 		up_write(&kobj->kset->subsys->rwsem);
 	}
 	error = create_dir(kobj);
-	if (error && parent)
-		kobject_put(parent);
+	if (error)
+		unlink(kobj);
 	return error;
 }
 
@@ -140,14 +163,7 @@
 void kobject_del(struct kobject * kobj)
 {
 	sysfs_remove_dir(kobj);
-	if (kobj->kset) {
-		down_write(&kobj->kset->subsys->rwsem);
-		list_del_init(&kobj->entry);
-		up_write(&kobj->kset->subsys->rwsem);
-	}
-	if (kobj->parent) 
-		kobject_put(kobj->parent);
-	kobject_put(kobj);
+	unlink(kobj);
 }
 
 /**
@@ -317,7 +333,7 @@
 	int error;
 
 	subsystem_init(s);
-	pr_debug("subsystem %s: registering\n",s->kobj.name);
+	pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
 
 	if (!(error = kset_add(&s->kset))) {
 		if (!s->kset.subsys)
@@ -328,7 +344,7 @@
 
 void subsystem_unregister(struct subsystem * s)
 {
-	pr_debug("subsystem %s: unregistering\n",s->kobj.name);
+	pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
 	kset_unregister(&s->kset);
 }
 
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Mon Jan 13 10:18:05 2003
+++ b/mm/filemap.c	Mon Jan 13 10:18:05 2003
@@ -55,11 +55,14 @@
 /*
  * Lock ordering:
  *
- *  ->i_shared_lock		(vmtruncate)
+ *  ->i_shared_sem		(vmtruncate)
  *    ->private_lock		(__free_pte->__set_page_dirty_buffers)
  *      ->swap_list_lock
  *        ->swap_device_lock	(exclusive_swap_page, others)
  *          ->mapping->page_lock
+ *  ->mmap_sem
+ *    ->i_shared_sem		(various places)
+ *
  *  ->inode_lock
  *    ->sb_lock			(fs/fs-writeback.c)
  *    ->mapping->page_lock	(__sync_single_inode)
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Mon Jan 13 10:18:06 2003
+++ b/mm/memory.c	Mon Jan 13 10:18:06 2003
@@ -82,7 +82,7 @@
  * Note: this doesn't free the actual pages themselves. That
  * has been handled earlier when unmapping all the memory regions.
  */
-static inline void free_one_pmd(mmu_gather_t *tlb, pmd_t * dir)
+static inline void free_one_pmd(struct mmu_gather *tlb, pmd_t * dir)
 {
 	struct page *page;
 
@@ -99,7 +99,7 @@
 	pte_free_tlb(tlb, page);
 }
 
-static inline void free_one_pgd(mmu_gather_t *tlb, pgd_t * dir)
+static inline void free_one_pgd(struct mmu_gather *tlb, pgd_t * dir)
 {
 	int j;
 	pmd_t * pmd;
@@ -124,7 +124,7 @@
  *
  * Must be called with pagetable lock held.
  */
-void clear_page_tables(mmu_gather_t *tlb, unsigned long first, int nr)
+void clear_page_tables(struct mmu_gather *tlb, unsigned long first, int nr)
 {
 	pgd_t * page_dir = tlb->mm->pgd;
 
@@ -369,7 +369,8 @@
 }
 
 static void
-zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, unsigned long size)
+zap_pte_range(struct mmu_gather *tlb, pmd_t * pmd,
+		unsigned long address, unsigned long size)
 {
 	unsigned long offset;
 	pte_t *ptep;
@@ -416,7 +417,9 @@
 	pte_unmap(ptep-1);
 }
 
-static void zap_pmd_range(mmu_gather_t *tlb, pgd_t * dir, unsigned long address, unsigned long size)
+static void
+zap_pmd_range(struct mmu_gather *tlb, pgd_t * dir,
+		unsigned long address, unsigned long size)
 {
 	pmd_t * pmd;
 	unsigned long end;
@@ -439,7 +442,8 @@
 	} while (address < end);
 }
 
-void unmap_page_range(mmu_gather_t *tlb, struct vm_area_struct *vma, unsigned long address, unsigned long end)
+void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
+			unsigned long address, unsigned long end)
 {
 	pgd_t * dir;
 
@@ -450,8 +454,6 @@
 
 	BUG_ON(address >= end);
 
-	lru_add_drain();
-
 	dir = pgd_offset(vma->vm_mm, address);
 	tlb_start_vma(tlb, vma);
 	do {
@@ -462,7 +464,7 @@
 	tlb_end_vma(tlb, vma);
 }
 
-/* Dispose of an entire mmu_gather_t per rescheduling point */
+/* Dispose of an entire struct mmu_gather per rescheduling point */
 #if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
 #define ZAP_BLOCK_SIZE	(FREE_PTE_NR * PAGE_SIZE)
 #endif
@@ -478,16 +480,107 @@
 #endif
 
 /**
+ * unmap_vmas - unmap a range of memory covered by a list of vma's
+ * @tlbp: address of the caller's struct mmu_gather
+ * @mm: the controlling mm_struct
+ * @vma: the starting vma
+ * @start_addr: virtual address at which to start unmapping
+ * @end_addr: virtual address at which to end unmapping
+ * @nr_accounted: Place number of unmapped pages in vm-accountable vma's here
+ *
+ * Returns the number of vma's which were covered by the unmapping.
+ *
+ * Unmap all pages in the vma list.  Called under page_table_lock.
+ *
+ * We aim to not hold page_table_lock for too long (for scheduling latency
+ * reasons).  So zap pages in ZAP_BLOCK_SIZE bytecounts.  This means we need to
+ * return the ending mmu_gather to the caller.
+ *
+ * Only addresses between `start' and `end' will be unmapped.
+ *
+ * The VMA list must be sorted in ascending virtual address order.
+ *
+ * unmap_vmas() assumes that the caller will flush the whole unmapped address
+ * range after unmap_vmas() returns.  So the only responsibility here is to
+ * ensure that any thus-far unmapped pages are flushed before unmap_vmas()
+ * drops the lock and schedules.
+ */
+int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm,
+		struct vm_area_struct *vma, unsigned long start_addr,
+		unsigned long end_addr, unsigned long *nr_accounted)
+{
+	unsigned long zap_bytes = ZAP_BLOCK_SIZE;
+	unsigned long tlb_start;	/* For tlb_finish_mmu */
+	int tlb_start_valid = 0;
+	int ret = 0;
+
+	if (vma) {	/* debug.  killme. */
+		if (end_addr <= vma->vm_start)
+			printk("%s: end_addr(0x%08lx) <= vm_start(0x%08lx)\n",
+				__FUNCTION__, end_addr, vma->vm_start);
+		if (start_addr >= vma->vm_end)
+			printk("%s: start_addr(0x%08lx) <= vm_end(0x%08lx)\n",
+				__FUNCTION__, start_addr, vma->vm_end);
+	}
+
+	for ( ; vma && vma->vm_start < end_addr; vma = vma->vm_next) {
+		unsigned long start;
+		unsigned long end;
+
+		start = max(vma->vm_start, start_addr);
+		if (start >= vma->vm_end)
+			continue;
+		end = min(vma->vm_end, end_addr);
+		if (end <= vma->vm_start)
+			continue;
+
+		if (vma->vm_flags & VM_ACCOUNT)
+			*nr_accounted += (end - start) >> PAGE_SHIFT;
+
+		ret++;
+		while (start != end) {
+			unsigned long block = min(zap_bytes, end - start);
+
+			if (!tlb_start_valid) {
+				tlb_start = start;
+				tlb_start_valid = 1;
+			}
+
+			unmap_page_range(*tlbp, vma, start, start + block);
+			start += block;
+			zap_bytes -= block;
+			if (zap_bytes != 0)
+				continue;
+			if (need_resched()) {
+				tlb_finish_mmu(*tlbp, tlb_start, start);
+				cond_resched_lock(&mm->page_table_lock);
+				*tlbp = tlb_gather_mmu(mm, 0);
+				tlb_start_valid = 0;
+			}
+			zap_bytes = ZAP_BLOCK_SIZE;
+		}
+		if (vma->vm_next && vma->vm_next->vm_start < vma->vm_end)
+			printk("%s: VMA list is not sorted correctly!\n",
+				__FUNCTION__);		
+	}
+	return ret;
+}
+
+/**
  * zap_page_range - remove user pages in a given range
  * @vma: vm_area_struct holding the applicable pages
  * @address: starting address of pages to zap
  * @size: number of bytes to zap
  */
-void zap_page_range(struct vm_area_struct *vma, unsigned long address, unsigned long size)
+void zap_page_range(struct vm_area_struct *vma,
+			unsigned long address, unsigned long size)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	mmu_gather_t *tlb;
-	unsigned long end, block;
+	struct mmu_gather *tlb;
+	unsigned long end = address + size;
+	unsigned long nr_accounted = 0;
+
+	might_sleep();
 
 	if (is_vm_hugetlb_page(vma)) {
 		zap_hugepage_range(vma, address, size);
@@ -495,30 +588,11 @@
 	}
 
 	lru_add_drain();
-
 	spin_lock(&mm->page_table_lock);
-
-  	/*
- 	 * This was once a long-held spinlock.  Now we break the
- 	 * work up into ZAP_BLOCK_SIZE units and relinquish the
- 	 * lock after each interation.  This drastically lowers
- 	 * lock contention and allows for a preemption point.
-  	 */
-	while (size) {
-		block = (size > ZAP_BLOCK_SIZE) ? ZAP_BLOCK_SIZE : size;
- 		end = address + block;
- 
- 		flush_cache_range(vma, address, end);
- 		tlb = tlb_gather_mmu(mm, 0);
- 		unmap_page_range(tlb, vma, address, end);
- 		tlb_finish_mmu(tlb, address, end);
- 
- 		cond_resched_lock(&mm->page_table_lock);
- 
- 		address += block;
- 		size -= block;
- 	}
-
+	flush_cache_range(vma, address, end);
+	tlb = tlb_gather_mmu(mm, 0);
+	unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted);
+	tlb_finish_mmu(tlb, address, end);
 	spin_unlock(&mm->page_table_lock);
 }
 
@@ -968,7 +1042,7 @@
 	if (inode->i_size < offset)
 		goto do_expand;
 	inode->i_size = offset;
-	spin_lock(&mapping->i_shared_lock);
+	down(&mapping->i_shared_sem);
 	if (list_empty(&mapping->i_mmap) && list_empty(&mapping->i_mmap_shared))
 		goto out_unlock;
 
@@ -979,7 +1053,7 @@
 		vmtruncate_list(&mapping->i_mmap_shared, pgoff);
 
 out_unlock:
-	spin_unlock(&mapping->i_shared_lock);
+	up(&mapping->i_shared_sem);
 	truncate_inode_pages(mapping, offset);
 	goto out_truncate;
 
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Mon Jan 13 10:18:06 2003
+++ b/mm/mmap.c	Mon Jan 13 10:18:06 2003
@@ -23,9 +23,6 @@
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
 
-extern void unmap_page_range(mmu_gather_t *,struct vm_area_struct *vma, unsigned long address, unsigned long size);
-extern void clear_page_tables(mmu_gather_t *tlb, unsigned long first, int nr);
-
 /*
  * WARNING: the debugging will use recursive algorithms so never enable this
  * unless you know what you are doing.
@@ -132,7 +129,9 @@
 	return 0;
 }
 
-/* Remove one vm structure from the inode's i_mapping address space. */
+/*
+ * Remove one vm structure from the inode's i_mapping address space.
+ */
 static void remove_shared_vm_struct(struct vm_area_struct *vma)
 {
 	struct file *file = vma->vm_file;
@@ -140,11 +139,11 @@
 	if (file) {
 		struct inode *inode = file->f_dentry->d_inode;
 
-		spin_lock(&inode->i_mapping->i_shared_lock);
+		down(&inode->i_mapping->i_shared_sem);
 		if (vma->vm_flags & VM_DENYWRITE)
 			atomic_inc(&inode->i_writecount);
 		list_del_init(&vma->shared);
-		spin_unlock(&inode->i_mapping->i_shared_lock);
+		up(&inode->i_mapping->i_shared_sem);
 	}
 }
 
@@ -346,12 +345,12 @@
 		mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
 
 	if (mapping)
-		spin_lock(&mapping->i_shared_lock);
+		down(&mapping->i_shared_sem);
 	spin_lock(&mm->page_table_lock);
 	__vma_link(mm, vma, prev, rb_link, rb_parent);
 	spin_unlock(&mm->page_table_lock);
 	if (mapping)
-		spin_unlock(&mapping->i_shared_lock);
+		up(&mapping->i_shared_sem);
 
 	mm->map_count++;
 	validate_mm(mm);
@@ -898,7 +897,7 @@
  * "prev", if it exists, points to a vma before the one
  * we just free'd - but there's no telling how much before.
  */
-static void free_pgtables(mmu_gather_t *tlb, struct vm_area_struct *prev,
+static void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *prev,
 	unsigned long start, unsigned long end)
 {
 	unsigned long first = start & PGDIR_MASK;
@@ -955,7 +954,7 @@
  * By the time this function is called, the area struct has been
  * removed from the process mapping list.
  */
-void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
+static void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
 {
 	size_t len = area->vm_end - area->vm_start;
 
@@ -1001,60 +1000,45 @@
  * Called with the page table lock held.
  */
 static void unmap_region(struct mm_struct *mm,
-	struct vm_area_struct *mpnt,
+	struct vm_area_struct *vma,
 	struct vm_area_struct *prev,
 	unsigned long start,
 	unsigned long end)
 {
-	mmu_gather_t *tlb;
+	struct mmu_gather *tlb;
+	unsigned long nr_accounted = 0;
 
+	lru_add_drain();
 	tlb = tlb_gather_mmu(mm, 0);
-
-	do {
-		unsigned long from, to, len;
-
-		from = start < mpnt->vm_start ? mpnt->vm_start : start;
-		to = end > mpnt->vm_end ? mpnt->vm_end : end;
-
-		unmap_page_range(tlb, mpnt, from, to);
-
-		if (mpnt->vm_flags & VM_ACCOUNT) {
-			len = to - from;
-			vm_unacct_memory(len >> PAGE_SHIFT);
-		}
-	} while ((mpnt = mpnt->vm_next) != NULL);
-
+	unmap_vmas(&tlb, mm, vma, start, end, &nr_accounted);
+	vm_unacct_memory(nr_accounted);
 	free_pgtables(tlb, prev, start, end);
 	tlb_finish_mmu(tlb, start, end);
 }
 
 /*
- * Create a list of vma's touched by the unmap,
- * removing them from the VM lists as we go..
+ * Create a list of vma's touched by the unmap, removing them from the mm's
+ * vma list as we go..
  *
  * Called with the page_table_lock held.
  */
-static struct vm_area_struct *touched_by_munmap(struct mm_struct *mm,
-	struct vm_area_struct *mpnt,
-	struct vm_area_struct *prev,
-	unsigned long end)
+static void
+detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
+	struct vm_area_struct *prev, unsigned long end)
 {
-	struct vm_area_struct **npp, *touched;
+	struct vm_area_struct **insertion_point;
+	struct vm_area_struct *tail_vma = NULL;
 
-	npp = (prev ? &prev->vm_next : &mm->mmap);
-
-	touched = NULL;
+	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
 	do {
-		struct vm_area_struct *next = mpnt->vm_next;
-		mpnt->vm_next = touched;
-		touched = mpnt;
-		rb_erase(&mpnt->vm_rb, &mm->mm_rb);
+		rb_erase(&vma->vm_rb, &mm->mm_rb);
 		mm->map_count--;
-		mpnt = next;
-	} while (mpnt && mpnt->vm_start < end);
-	*npp = mpnt;
-	mm->mmap_cache = NULL;	/* Kill the cache. */
-	return touched;
+		tail_vma = vma;
+		vma = vma->vm_next;
+	} while (vma && vma->vm_start < end);
+	*insertion_point = vma;
+	tail_vma->vm_next = NULL;
+	mm->mmap_cache = NULL;		/* Kill the cache. */
 }
 
 /*
@@ -1150,7 +1134,7 @@
 	 * Remove the vma's, and unmap the actual pages
 	 */
 	spin_lock(&mm->page_table_lock);
-	mpnt = touched_by_munmap(mm, mpnt, prev, end);
+	detach_vmas_to_be_unmapped(mm, mpnt, prev, end);
 	unmap_region(mm, mpnt, prev, start, end);
 	spin_unlock(&mm->page_table_lock);
 
@@ -1273,43 +1257,28 @@
 }
 
 /* Release all mmaps. */
-void exit_mmap(struct mm_struct * mm)
+void exit_mmap(struct mm_struct *mm)
 {
-	mmu_gather_t *tlb;
-	struct vm_area_struct * mpnt;
+	struct mmu_gather *tlb;
+	struct vm_area_struct *vma;
+	unsigned long nr_accounted = 0;
 
 	profile_exit_mmap(mm);
  
+	lru_add_drain();
+
 	spin_lock(&mm->page_table_lock);
 
 	tlb = tlb_gather_mmu(mm, 1);
-
 	flush_cache_mm(mm);
-	mpnt = mm->mmap;
-	while (mpnt) {
-		unsigned long start = mpnt->vm_start;
-		unsigned long end = mpnt->vm_end;
-
-		/*
-		 * If the VMA has been charged for, account for its
-		 * removal
-		 */
-		if (mpnt->vm_flags & VM_ACCOUNT)
-			vm_unacct_memory((end - start) >> PAGE_SHIFT);
-
-		mm->map_count--;
-		unmap_page_range(tlb, mpnt, start, end);
-		mpnt = mpnt->vm_next;
-	}
-
-	/* This is just debugging */
-	if (mm->map_count)
-		BUG();
-
+	mm->map_count -= unmap_vmas(&tlb, mm, mm->mmap, 0,
+					TASK_SIZE, &nr_accounted);
+	vm_unacct_memory(nr_accounted);
+	BUG_ON(mm->map_count);	/* This is just debugging */
 	clear_page_tables(tlb, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
 	tlb_finish_mmu(tlb, 0, TASK_SIZE);
 
-	mpnt = mm->mmap;
+	vma = mm->mmap;
 	mm->mmap = mm->mmap_cache = NULL;
 	mm->mm_rb = RB_ROOT;
 	mm->rss = 0;
@@ -1322,24 +1291,24 @@
 	 * Walk the list again, actually closing and freeing it
 	 * without holding any MM locks.
 	 */
-	while (mpnt) {
-		struct vm_area_struct * next = mpnt->vm_next;
-		remove_shared_vm_struct(mpnt);
-		if (mpnt->vm_ops) {
-			if (mpnt->vm_ops->close)
-				mpnt->vm_ops->close(mpnt);
+	while (vma) {
+		struct vm_area_struct *next = vma->vm_next;
+		remove_shared_vm_struct(vma);
+		if (vma->vm_ops) {
+			if (vma->vm_ops->close)
+				vma->vm_ops->close(vma);
 		}
-		if (mpnt->vm_file)
-			fput(mpnt->vm_file);
-		kmem_cache_free(vm_area_cachep, mpnt);
-		mpnt = next;
+		if (vma->vm_file)
+			fput(vma->vm_file);
+		kmem_cache_free(vm_area_cachep, vma);
+		vma = next;
 	}
 		
 }
 
 /* Insert vm structure into process list sorted by address
  * and into the inode's i_mmap ring.  If vm_file is non-NULL
- * then the i_shared_lock must be held here.
+ * then i_shared_sem is taken here.
  */
 void insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
 {
diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c
--- a/mm/page-writeback.c	Mon Jan 13 10:18:06 2003
+++ b/mm/page-writeback.c	Mon Jan 13 10:18:06 2003
@@ -563,6 +563,26 @@
 EXPORT_SYMBOL(__set_page_dirty_nobuffers);
 
 /*
+ * set_page_dirty() is racy if the caller has no reference against
+ * page->mapping->host, and if the page is unlocked.  This is because another
+ * CPU could truncate the page off the mapping and then free the mapping.
+ *
+ * Usually, the page _is_ locked, or the caller is a user-space process which
+ * holds a reference on the inode by having an open file.
+ *
+ * In other cases, the page should be locked before running set_page_dirty().
+ */
+int set_page_dirty_lock(struct page *page)
+{
+	int ret;
+
+	lock_page(page);
+	ret = set_page_dirty(page);
+	unlock_page(page);
+	return ret;
+}
+
+/*
  * Clear a page's dirty flag, while caring for dirty memory accounting. 
  * Returns true if the page was previously dirty.
  */
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Mon Jan 13 10:18:07 2003
+++ b/mm/slab.c	Mon Jan 13 10:18:07 2003
@@ -502,7 +502,7 @@
 
 #define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg)
 
-static void __slab_error(char *function, kmem_cache_t *cachep, char *msg)
+static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg)
 {
 	printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
 		function, cachep->name, msg);
diff -Nru a/mm/swap.c b/mm/swap.c
--- a/mm/swap.c	Mon Jan 13 10:18:05 2003
+++ b/mm/swap.c	Mon Jan 13 10:18:05 2003
@@ -363,4 +363,5 @@
 	 * Right now other parts of the system means that we
 	 * _really_ don't want to cluster much more
 	 */
+	init_MUTEX(&swapper_space.i_shared_sem);
 }
diff -Nru a/mm/swap_state.c b/mm/swap_state.c
--- a/mm/swap_state.c	Mon Jan 13 10:18:06 2003
+++ b/mm/swap_state.c	Mon Jan 13 10:18:06 2003
@@ -42,7 +42,6 @@
 	.host			= &swapper_inode,
 	.a_ops			= &swap_aops,
 	.backing_dev_info	= &swap_backing_dev_info,
-	.i_shared_lock		= SPIN_LOCK_UNLOCKED,
 	.i_mmap			= LIST_HEAD_INIT(swapper_space.i_mmap),
 	.i_mmap_shared		= LIST_HEAD_INIT(swapper_space.i_mmap_shared),
 	.private_lock		= SPIN_LOCK_UNLOCKED,
diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
--- a/net/bridge/netfilter/ebtables.c	Mon Jan 13 10:18:05 2003
+++ b/net/bridge/netfilter/ebtables.c	Mon Jan 13 10:18:05 2003
@@ -2,7 +2,7 @@
  *  ebtables
  *
  *  Author:
- *  Bart De Schuymer		<bart.de.schuymer@pandora.be>
+ *  Bart De Schuymer		<bdschuym@pandora.be>
  *
  *  ebtables.c,v 2.0, July, 2002
  *
@@ -15,7 +15,7 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-// used for print_string
+/* used for print_string */
 #include <linux/sched.h>
 #include <linux/tty.h>
 
@@ -27,18 +27,20 @@
 #include <asm/uaccess.h>
 #include <linux/smp.h>
 #include <net/sock.h>
-// needed for logical [in,out]-dev filtering
+/* needed for logical [in,out]-dev filtering */
 #include "../br_private.h"
 
-// list_named_find
+/* list_named_find */
 #define ASSERT_READ_LOCK(x)
 #define ASSERT_WRITE_LOCK(x)
 #include <linux/netfilter_ipv4/listhelp.h>
 
-#if 0 // use this for remote debugging
-// Copyright (C) 1998 by Ori Pomerantz
-// Print the string to the appropriate tty, the one
-// the current task uses
+#if 0
+/* use this for remote debugging
+ * Copyright (C) 1998 by Ori Pomerantz
+ * Print the string to the appropriate tty, the one
+ * the current task uses
+ */
 static void print_string(char *str)
 {
 	struct tty_struct *my_tty;
@@ -55,20 +57,22 @@
 #else
 #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
                                          "report to author: "format, ## args)
-// #define BUGPRINT(format, args...)
+/* #define BUGPRINT(format, args...) */
 #endif
 #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
                                          ": out of memory: "format, ## args)
-// #define MEMPRINT(format, args...)
+/* #define MEMPRINT(format, args...) */
 
 
 
-// Each cpu has its own set of counters, so there is no need for write_lock in
-// the softirq
-// For reading or updating the counters, the user context needs to
-// get a write_lock
+/*
+ * Each cpu has its own set of counters, so there is no need for write_lock in
+ * the softirq
+ * For reading or updating the counters, the user context needs to
+ * get a write_lock
+ */
 
-// The size of each set of counters is altered to get cache alignment
+/* The size of each set of counters is altered to get cache alignment */
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 #define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
 #define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
@@ -91,7 +95,7 @@
 {
 	w->u.watcher->watcher(skb, in, out, w->data,
 	   w->watcher_size);
-	// watchers don't give a verdict
+	/* watchers don't give a verdict */
 	return 0;
 }
 
@@ -113,7 +117,7 @@
 }
 
 #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
-// process standard matches
+/* process standard matches */
 static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
    const struct net_device *in, const struct net_device *out)
 {
@@ -156,7 +160,7 @@
 	return 0;
 }
 
-// Do some firewalling
+/* Do some firewalling */
 unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    struct ebt_table *table)
@@ -182,7 +186,7 @@
 	nentries = private->hook_entry[hook]->nentries;
 	point = (struct ebt_entry *)(private->hook_entry[hook]->data);
 	counter_base = cb_base + private->hook_entry[hook]->counter_offset;
-	// base for chain jumps
+	/* base for chain jumps */
 	base = private->entries;
 	i = 0;
 	while (i < nentries) {
@@ -192,18 +196,18 @@
 		if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
 			goto letscontinue;
 
-		// increase counter
+		/* increase counter */
 		(*(counter_base + i)).pcnt++;
 		(*(counter_base + i)).bcnt+=(**pskb).len;
 
-		// these should only watch: not modify, nor tell us
-		// what to do with the packet
+		/* these should only watch: not modify, nor tell us
+		   what to do with the packet */
 		EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, in,
 		   out);
 
 		t = (struct ebt_entry_target *)
 		   (((char *)point) + point->target_offset);
-		// standard target
+		/* standard target */
 		if (!t->u.target->target)
 			verdict = ((struct ebt_standard_target *)t)->verdict;
 		else
@@ -222,12 +226,12 @@
 #ifdef CONFIG_NETFILTER_DEBUG
 			if (sp == 0) {
 				BUGPRINT("RETURN on base chain");
-				// act like this is EBT_CONTINUE
+				/* act like this is EBT_CONTINUE */
 				goto letscontinue;
 			}
 #endif
 			sp--;
-			// put all the local variables right
+			/* put all the local variables right */
 			i = cs[sp].n;
 			chaininfo = cs[sp].chaininfo;
 			nentries = chaininfo->nentries;
@@ -245,7 +249,7 @@
 			return NF_DROP;
 		}
 #endif
-		// jump to a udc
+		/* jump to a udc */
 		cs[sp].n = i + 1;
 		cs[sp].chaininfo = chaininfo;
 		cs[sp].e = (struct ebt_entry *)
@@ -270,7 +274,7 @@
 		i++;
 	}
 
-	// I actually like this :)
+	/* I actually like this :) */
 	if (chaininfo->policy == EBT_RETURN)
 		goto letsreturn;
 	if (chaininfo->policy == EBT_ACCEPT) {
@@ -281,7 +285,7 @@
 	return NF_DROP;
 }
 
-// If it succeeds, returns element and locks mutex
+/* If it succeeds, returns element and locks mutex */
 static inline void *
 find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
    struct semaphore *mutex)
@@ -359,14 +363,15 @@
 	if (!match)
 		return ret;
 	m->u.match = match;
-	if (match->me)
-		__MOD_INC_USE_COUNT(match->me);
+	if (!try_module_get(match->me)) {
+		up(&ebt_mutex);
+		return -EINVAL;
+	}
 	up(&ebt_mutex);
 	if (match->check &&
 	   match->check(name, hookmask, e, m->data, m->match_size) != 0) {
 		BUGPRINT("match->check failed\n");
-		if (match->me)
-			__MOD_DEC_USE_COUNT(match->me);
+		module_put(match->me);
 		return -EINVAL;
 	}
 	(*cnt)++;
@@ -387,22 +392,25 @@
 	if (!watcher)
 		return ret;
 	w->u.watcher = watcher;
-	if (watcher->me)
-		__MOD_INC_USE_COUNT(watcher->me);
+	if (!try_module_get(watcher->me)) {
+		up(&ebt_mutex);
+		return -EINVAL;
+	}
 	up(&ebt_mutex);
 	if (watcher->check &&
 	   watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
 		BUGPRINT("watcher->check failed\n");
-		if (watcher->me)
-			__MOD_DEC_USE_COUNT(watcher->me);
+		module_put(watcher->me);
 		return -EINVAL;
 	}
 	(*cnt)++;
 	return 0;
 }
 
-// this one is very careful, as it is the first function
-// to parse the userspace data
+/*
+ * this one is very careful, as it is the first function
+ * to parse the userspace data
+ */
 static inline int
 ebt_check_entry_size_and_hooks(struct ebt_entry *e,
    struct ebt_table_info *newinfo, char *base, char *limit,
@@ -418,24 +426,24 @@
 		   (char *)e - newinfo->entries)
 			break;
 	}
-	// beginning of a new chain
-	// if i == NF_BR_NUMHOOKS it must be a user defined chain
+	/* beginning of a new chain
+	   if i == NF_BR_NUMHOOKS it must be a user defined chain */
 	if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
 		if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
-			// we make userspace set this right,
-			// so there is no misunderstanding
+			/* we make userspace set this right,
+			   so there is no misunderstanding */
 			BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
 			         "in distinguisher\n");
 			return -EINVAL;
 		}
-		// this checks if the previous chain has as many entries
-		// as it said it has
+		/* this checks if the previous chain has as many entries
+		   as it said it has */
 		if (*n != *cnt) {
 			BUGPRINT("nentries does not equal the nr of entries "
 		                 "in the chain\n");
 			return -EINVAL;
 		}
-		// before we look at the struct, be sure it is not too big
+		/* before we look at the struct, be sure it is not too big */
 		if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
 		   > limit) {
 			BUGPRINT("entries_size too small\n");
@@ -443,14 +451,14 @@
 		}
 		if (((struct ebt_entries *)e)->policy != EBT_DROP &&
 		   ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
-			// only RETURN from udc
+			/* only RETURN from udc */
 			if (i != NF_BR_NUMHOOKS ||
 			   ((struct ebt_entries *)e)->policy != EBT_RETURN) {
 				BUGPRINT("bad policy\n");
 				return -EINVAL;
 			}
 		}
-		if (i == NF_BR_NUMHOOKS) // it's a user defined chain
+		if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
 			(*udc_cnt)++;
 		else
 			newinfo->hook_entry[i] = (struct ebt_entries *)e;
@@ -462,14 +470,14 @@
 		*cnt = 0;
 		return 0;
 	}
-	// a plain old entry, heh
+	/* a plain old entry, heh */
 	if (sizeof(struct ebt_entry) > e->watchers_offset ||
 	   e->watchers_offset > e->target_offset ||
 	   e->target_offset >= e->next_offset) {
 		BUGPRINT("entry offsets not in right order\n");
 		return -EINVAL;
 	}
-	// this is not checked anywhere else
+	/* this is not checked anywhere else */
 	if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
 		BUGPRINT("target size too small\n");
 		return -EINVAL;
@@ -487,8 +495,10 @@
 	unsigned int hookmask;
 };
 
-// we need these positions to check that the jumps to a different part of the
-// entries is a jump to the beginning of a new chain.
+/*
+ * we need these positions to check that the jumps to a different part of the
+ * entries is a jump to the beginning of a new chain.
+ */
 static inline int
 ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
    struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
@@ -496,7 +506,7 @@
 {
 	int i;
 
-	// we're only interested in chain starts
+	/* we're only interested in chain starts */
 	if (e->bitmask & EBT_ENTRY_OR_ENTRIES)
 		return 0;
 	for (i = 0; i < NF_BR_NUMHOOKS; i++) {
@@ -505,12 +515,12 @@
 		if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
 			break;
 	}
-	// only care about udc
+	/* only care about udc */
 	if (i != NF_BR_NUMHOOKS)
 		return 0;
 
 	udc[*n].cs.chaininfo = (struct ebt_entries *)e;
-	// these initialisations are depended on later in check_chainloops()
+	/* these initialisations are depended on later in check_chainloops() */
 	udc[*n].cs.n = 0;
 	udc[*n].hookmask = 0;
 
@@ -525,8 +535,7 @@
 		return 1;
 	if (m->u.match->destroy)
 		m->u.match->destroy(m->data, m->match_size);
-	if (m->u.match->me)
-		__MOD_DEC_USE_COUNT(m->u.match->me);
+	module_put(m->u.match->me);
 
 	return 0;
 }
@@ -538,8 +547,7 @@
 		return 1;
 	if (w->u.watcher->destroy)
 		w->u.watcher->destroy(w->data, w->watcher_size);
-	if (w->u.watcher->me)
-		__MOD_DEC_USE_COUNT(w->u.watcher->me);
+	module_put(w->u.watcher->me);
 
 	return 0;
 }
@@ -551,7 +559,7 @@
 
 	if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
 		return 0;
-	// we're done
+	/* we're done */
 	if (cnt && (*cnt)-- == 0)
 		return 1;
 	EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
@@ -559,8 +567,7 @@
 	t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
 	if (t->u.target->destroy)
 		t->u.target->destroy(t->data, t->target_size);
-	if (t->u.target->me)
-		__MOD_DEC_USE_COUNT(t->u.target->me);
+	module_put(t->u.target->me);
 
 	return 0;
 }
@@ -575,7 +582,7 @@
 	unsigned int i, j, hook = 0, hookmask = 0;
 	int ret;
 
-	// Don't mess with the struct ebt_entries
+	/* don't mess with the struct ebt_entries */
 	if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
 		return 0;
 
@@ -591,7 +598,7 @@
 		BUGPRINT("NOPROTO & 802_3 not allowed\n");
 		return -EINVAL;
 	}
-	// what hook do we belong to?
+	/* what hook do we belong to? */
 	for (i = 0; i < NF_BR_NUMHOOKS; i++) {
 		if ((valid_hooks & (1 << i)) == 0)
 			continue;
@@ -600,8 +607,8 @@
 		else
 			break;
 	}
-	// (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
-	// a base chain
+	/* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
+	   a base chain */
 	if (i < NF_BR_NUMHOOKS)
 		hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
 	else {
@@ -625,8 +632,10 @@
 	target = find_target_lock(t->u.name, &ret, &ebt_mutex);
 	if (!target)
 		goto cleanup_watchers;
-	if (target->me)
-		__MOD_INC_USE_COUNT(target->me);
+	if (!try_module_get(target->me)) {
+		up(&ebt_mutex);
+		goto cleanup_watchers;
+	}
 	up(&ebt_mutex);
 
 	t->u.target = target;
@@ -647,8 +656,7 @@
 	   sizeof(struct ebt_entry_target) > e->next_offset) ||
 	   (t->u.target->check &&
 	   t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
-		if (t->u.target->me)
-			__MOD_DEC_USE_COUNT(t->u.target->me);
+		module_put(t->u.target->me);
 		ret = -EFAULT;
 		goto cleanup_watchers;
 	}
@@ -661,10 +669,12 @@
 	return ret;
 }
 
-// checks for loops and sets the hook mask for udc
-// the hook mask for udc tells us from which base chains the udc can be
-// accessed. This mask is a parameter to the check() functions of the extensions
-int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
+/*
+ * checks for loops and sets the hook mask for udc
+ * the hook mask for udc tells us from which base chains the udc can be
+ * accessed. This mask is a parameter to the check() functions of the extensions
+ */
+static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
    unsigned int udc_cnt, unsigned int hooknr, char *base)
 {
 	int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
@@ -672,9 +682,9 @@
 	struct ebt_entry_target *t;
 
 	while (pos < nentries || chain_nr != -1) {
-		// end of udc, go back one 'recursion' step
+		/* end of udc, go back one 'recursion' step */
 		if (pos == nentries) {
-			// put back values of the time when this chain was called
+			/* put back values of the time when this chain was called */
 			e = cl_s[chain_nr].cs.e;
 			if (cl_s[chain_nr].from != -1)
 				nentries =
@@ -682,7 +692,7 @@
 			else
 				nentries = chain->nentries;
 			pos = cl_s[chain_nr].cs.n;
-			// make sure we won't see a loop that isn't one
+			/* make sure we won't see a loop that isn't one */
 			cl_s[chain_nr].cs.n = 0;
 			chain_nr = cl_s[chain_nr].from;
 			if (pos == nentries)
@@ -698,13 +708,13 @@
 			return -1;
 		}
 		verdict = ((struct ebt_standard_target *)t)->verdict;
-		if (verdict >= 0) { // jump to another chain
+		if (verdict >= 0) { /* jump to another chain */
 			struct ebt_entries *hlp2 =
 			   (struct ebt_entries *)(base + verdict);
 			for (i = 0; i < udc_cnt; i++)
 				if (hlp2 == cl_s[i].cs.chaininfo)
 					break;
-			// bad destination or loop
+			/* bad destination or loop */
 			if (i == udc_cnt) {
 				BUGPRINT("bad destination\n");
 				return -1;
@@ -713,7 +723,7 @@
 				BUGPRINT("loop\n");
 				return -1;
 			}
-			// this can't be 0, so the above test is correct
+			/* this can't be 0, so the above test is correct */
 			cl_s[i].cs.n = pos + 1;
 			pos = 0;
 			cl_s[i].cs.e = ((void *)e + e->next_offset);
@@ -721,7 +731,7 @@
 			nentries = hlp2->nentries;
 			cl_s[i].from = chain_nr;
 			chain_nr = i;
-			// this udc is accessible from the base chain for hooknr
+			/* this udc is accessible from the base chain for hooknr */
 			cl_s[i].hookmask |= (1 << hooknr);
 			continue;
 		}
@@ -732,13 +742,13 @@
 	return 0;
 }
 
-// do the parsing of the table/chains/entries/matches/watchers/targets, heh
+/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
 static int translate_table(struct ebt_replace *repl,
    struct ebt_table_info *newinfo)
 {
 	unsigned int i, j, k, udc_cnt;
 	int ret;
-	struct ebt_cl_stack *cl_s = NULL; // used in the checking for chain loops
+	struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
 
 	i = 0;
 	while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
@@ -751,8 +761,8 @@
 		BUGPRINT("Chains don't start at beginning\n");
 		return -EINVAL;
 	}
-	// make sure chains are ordered after each other in same order
-	// as their corresponding hooks
+	/* make sure chains are ordered after each other in same order
+	   as their corresponding hooks */
 	for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
 		if (!(repl->valid_hooks & (1 << j)))
 			continue;
@@ -769,12 +779,12 @@
 	newinfo->entries_size = repl->entries_size;
 	newinfo->nentries = repl->nentries;
 
-	// do some early checkings and initialize some things
-	i = 0; // holds the expected nr. of entries for the chain
-	j = 0; // holds the up to now counted entries for the chain
-	k = 0; // holds the total nr. of entries, should equal
-	       // newinfo->nentries afterwards
-	udc_cnt = 0; // will hold the nr. of user defined chains (udc)
+	/* do some early checkings and initialize some things */
+	i = 0; /* holds the expected nr. of entries for the chain */
+	j = 0; /* holds the up to now counted entries for the chain */
+	k = 0; /* holds the total nr. of entries, should equal
+	          newinfo->nentries afterwards */
+	udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
 	ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
 	   ebt_check_entry_size_and_hooks, newinfo, repl->entries,
 	   repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
@@ -793,7 +803,7 @@
 		return -EINVAL;
 	}
 
-	// check if all valid hooks have a chain
+	/* check if all valid hooks have a chain */
 	for (i = 0; i < NF_BR_NUMHOOKS; i++) {
 		if (newinfo->hook_entry[i] == NULL &&
 		   (repl->valid_hooks & (1 << i))) {
@@ -802,11 +812,11 @@
 		}
 	}
 
-	// Get the location of the udc, put them in an array
-	// While we're at it, allocate the chainstack
+	/* get the location of the udc, put them in an array
+	   while we're at it, allocate the chainstack */
 	if (udc_cnt) {
-		// this will get free'd in do_replace()/ebt_register_table()
-		// if an error occurs
+		/* this will get free'd in do_replace()/ebt_register_table()
+		   if an error occurs */
 		newinfo->chainstack = (struct ebt_chainstack **)
 		   vmalloc(NR_CPUS * sizeof(struct ebt_chainstack));
 		if (!newinfo->chainstack)
@@ -827,11 +837,11 @@
 		   vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
 		if (!cl_s)
 			return -ENOMEM;
-		i = 0; // the i'th udc
+		i = 0; /* the i'th udc */
 		EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
 		   ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
 		   repl->valid_hooks, cl_s);
-		// sanity check
+		/* sanity check */
 		if (i != udc_cnt) {
 			BUGPRINT("i != udc_cnt\n");
 			vfree(cl_s);
@@ -839,7 +849,7 @@
 		}
 	}
 
-	// Check for loops
+	/* Check for loops */
 	for (i = 0; i < NF_BR_NUMHOOKS; i++)
 		if (repl->valid_hooks & (1 << i))
 			if (check_chainloops(newinfo->hook_entry[i],
@@ -849,17 +859,17 @@
 				return -EINVAL;
 			}
 
-	// we now know the following (along with E=mc²):
-	// - the nr of entries in each chain is right
-	// - the size of the allocated space is right
-	// - all valid hooks have a corresponding chain
-	// - there are no loops
-	// - wrong data can still be on the level of a single entry
-	// - could be there are jumps to places that are not the
-	//   beginning of a chain. This can only occur in chains that
-	//   are not accessible from any base chains, so we don't care.
+	/* we now know the following (along with E=mc²):
+	   - the nr of entries in each chain is right
+	   - the size of the allocated space is right
+	   - all valid hooks have a corresponding chain
+	   - there are no loops
+	   - wrong data can still be on the level of a single entry
+	   - could be there are jumps to places that are not the
+	     beginning of a chain. This can only occur in chains that
+	     are not accessible from any base chains, so we don't care. */
 
-	// used to know what we need to clean up if something goes wrong
+	/* used to know what we need to clean up if something goes wrong */
 	i = 0;
 	ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
 	   ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
@@ -873,17 +883,17 @@
 	return ret;
 }
 
-// called under write_lock
+/* called under write_lock */
 static void get_counters(struct ebt_counter *oldcounters,
    struct ebt_counter *counters, unsigned int nentries)
 {
 	int i, cpu;
 	struct ebt_counter *counter_base;
 
-	// counters of cpu 0
+	/* counters of cpu 0 */
 	memcpy(counters, oldcounters,
 	   sizeof(struct ebt_counter) * nentries);
-	// add other counters to those of cpu 0
+	/* add other counters to those of cpu 0 */
 	for (cpu = 1; cpu < NR_CPUS; cpu++) {
 		counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
 		for (i = 0; i < nentries; i++) {
@@ -893,7 +903,7 @@
 	}
 }
 
-// replace the table
+/* replace the table */
 static int do_replace(void *user, unsigned int len)
 {
 	int ret, i, countersize;
@@ -901,7 +911,7 @@
 	struct ebt_replace tmp;
 	struct ebt_table *t;
 	struct ebt_counter *counterstmp = NULL;
-	// used to be able to unlock earlier
+	/* used to be able to unlock earlier */
 	struct ebt_table_info *table;
 
 	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
@@ -937,8 +947,8 @@
 		goto free_entries;
 	}
 
-	// the user wants counters back
-	// the check on the size is done later, when we have the lock
+	/* the user wants counters back
+	   the check on the size is done later, when we have the lock */
 	if (tmp.num_counters) {
 		counterstmp = (struct ebt_counter *)
 		   vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
@@ -950,7 +960,7 @@
 	else
 		counterstmp = NULL;
 
-	// this can get initialized by translate_table()
+	/* this can get initialized by translate_table() */
 	newinfo->chainstack = NULL;
 	ret = translate_table(&tmp, newinfo);
 
@@ -961,7 +971,7 @@
 	if (!t)
 		goto free_iterate;
 
-	// the table doesn't like it
+	/* the table doesn't like it */
 	if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
 		goto free_unlock;
 
@@ -971,9 +981,9 @@
 		goto free_unlock;
 	}
 
-	// we have the mutex lock, so no danger in reading this pointer
+	/* we have the mutex lock, so no danger in reading this pointer */
 	table = t->private;
-	// we need an atomic snapshot of the counters
+	/* we need an atomic snapshot of the counters */
 	write_lock_bh(&t->lock);
 	if (tmp.num_counters)
 		get_counters(t->private->counters, counterstmp,
@@ -982,10 +992,10 @@
 	t->private = newinfo;
 	write_unlock_bh(&t->lock);
 	up(&ebt_mutex);
-	// So, a user can change the chains while having messed up her counter
-	// allocation. Only reason why this is done is because this way the lock
-	// is held only once, while this doesn't bring the kernel into a
-	// dangerous state.
+	/* so, a user can change the chains while having messed up her counter
+	   allocation. Only reason why this is done is because this way the lock
+	   is held only once, while this doesn't bring the kernel into a
+	   dangerous state. */
 	if (tmp.num_counters &&
 	   copy_to_user(tmp.counters, counterstmp,
 	   tmp.num_counters * sizeof(struct ebt_counter))) {
@@ -995,7 +1005,7 @@
 	else
 		ret = 0;
 
-	// decrease module count and free resources
+	/* decrease module count and free resources */
 	EBT_ENTRY_ITERATE(table->entries, table->entries_size,
 	   ebt_cleanup_entry, NULL);
 
@@ -1019,7 +1029,7 @@
 free_counterstmp:
 	if (counterstmp)
 		vfree(counterstmp);
-	// can be initialized in translate_table()
+	/* can be initialized in translate_table() */
 	if (newinfo->chainstack) {
 		for (i = 0; i < NR_CPUS; i++)
 			vfree(newinfo->chainstack[i]);
@@ -1046,7 +1056,6 @@
 		return -EEXIST;
 	}
 	up(&ebt_mutex);
-	MOD_INC_USE_COUNT;
 
 	return 0;
 }
@@ -1056,7 +1065,6 @@
 	down(&ebt_mutex);
 	LIST_DELETE(&ebt_targets, target);
 	up(&ebt_mutex);
-	MOD_DEC_USE_COUNT;
 }
 
 int ebt_register_match(struct ebt_match *match)
@@ -1071,7 +1079,6 @@
 		return -EEXIST;
 	}
 	up(&ebt_mutex);
-	MOD_INC_USE_COUNT;
 
 	return 0;
 }
@@ -1081,7 +1088,6 @@
 	down(&ebt_mutex);
 	LIST_DELETE(&ebt_matches, match);
 	up(&ebt_mutex);
-	MOD_DEC_USE_COUNT;
 }
 
 int ebt_register_watcher(struct ebt_watcher *watcher)
@@ -1096,7 +1102,6 @@
 		return -EEXIST;
 	}
 	up(&ebt_mutex);
-	MOD_INC_USE_COUNT;
 
 	return 0;
 }
@@ -1106,7 +1111,6 @@
 	down(&ebt_mutex);
 	LIST_DELETE(&ebt_watchers, watcher);
 	up(&ebt_mutex);
-	MOD_DEC_USE_COUNT;
 }
 
 int ebt_register_table(struct ebt_table *table)
@@ -1138,7 +1142,7 @@
 	if (countersize)
 		memset(newinfo->counters, 0, countersize);
 
-	// fill in newinfo and parse the entries
+	/* fill in newinfo and parse the entries */
 	newinfo->chainstack = NULL;
 	ret = translate_table(table->table, newinfo);
 	if (ret != 0) {
@@ -1165,7 +1169,6 @@
 
 	list_prepend(&ebt_tables, table);
 	up(&ebt_mutex);
-	MOD_INC_USE_COUNT;
 	return 0;
 free_unlock:
 	up(&ebt_mutex);
@@ -1202,10 +1205,9 @@
 		vfree(table->private->chainstack);
 	}
 	vfree(table->private);
-	MOD_DEC_USE_COUNT;
 }
 
-// userspace just supplied us with counters
+/* userspace just supplied us with counters */
 static int update_counters(void *user, unsigned int len)
 {
 	int i, ret;
@@ -1244,10 +1246,10 @@
 		goto unlock_mutex;
 	}
 
-	// we want an atomic add of the counters
+	/* we want an atomic add of the counters */
 	write_lock_bh(&t->lock);
 
-	// we add to the counters of the first cpu
+	/* we add to the counters of the first cpu */
 	for (i = 0; i < hlp.num_counters; i++) {
 		t->private->counters[i].pcnt += tmp[i].pcnt;
 		t->private->counters[i].bcnt += tmp[i].bcnt;
@@ -1303,7 +1305,7 @@
 	return 0;
 }
 
-// called with ebt_mutex down
+/* called with ebt_mutex down */
 static int copy_everything_to_user(struct ebt_table *t, void *user,
    int *len, int cmd)
 {
@@ -1345,7 +1347,7 @@
 		return -EINVAL;
 	}
 
-	// userspace might not need the counters
+	/* userspace might not need the counters */
 	if (tmp.num_counters) {
 		if (tmp.num_counters != nentries) {
 			BUGPRINT("Num_counters wrong\n");
@@ -1374,7 +1376,7 @@
 		BUGPRINT("Couldn't copy entries to userspace\n");
 		return -EFAULT;
 	}
-	// set the match/watcher/target names right
+	/* set the match/watcher/target names right */
 	return EBT_ENTRY_ITERATE(entries, entries_size,
 	   ebt_make_names, entries, tmp.entries);
 }
@@ -1465,14 +1467,14 @@
 	if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
 		return ret;
 
-	printk("Ebtables v2.0 registered");
+	printk(KERN_NOTICE "Ebtables v2.0 registered\n");
 	return 0;
 }
 
 static void __exit fini(void)
 {
 	nf_unregister_sockopt(&ebt_sockopts);
-	printk("Ebtables v2.0 unregistered");
+	printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
 }
 
 EXPORT_SYMBOL(ebt_register_table);
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	Mon Jan 13 10:18:06 2003
+++ b/net/core/dev.c	Mon Jan 13 10:18:06 2003
@@ -2520,6 +2520,11 @@
 		if (d == dev || !strcmp(d->name, dev->name))
 			goto out_err;
 	}
+	snprintf(dev->kobj.name,KOBJ_NAME_LEN,dev->name);
+	kobj_set_kset_s(dev,net_subsys);
+	if ((ret = kobject_register(&dev->kobj)))
+		goto out_err;
+	
 	/*
 	 *	nil rebuild_header routine,
 	 *	that should be never called and used as just bug trap.
@@ -2547,10 +2552,7 @@
 	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
 
 	net_run_sbin_hotplug(dev, "register");
-
-	snprintf(dev->kobj.name,KOBJ_NAME_LEN,dev->name);
-	kobj_set_kset_s(dev,net_subsys);
-	ret = kobject_register(&dev->kobj);
+	ret = 0;
 
 out:
 	return ret;
@@ -2676,8 +2678,6 @@
 		goto out;
 	}
 
-	kobject_unregister(&dev->kobj);
-
 	/* Last reference is our one */
 	if (atomic_read(&dev->refcnt) == 1)
 		goto out;
@@ -2738,6 +2738,7 @@
 		}
 	}
 out:
+	kobject_unregister(&dev->kobj);
 	dev_put(dev);
 	return 0;
 }
diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c	Mon Jan 13 10:18:06 2003
+++ b/net/core/skbuff.c	Mon Jan 13 10:18:06 2003
@@ -761,6 +761,35 @@
 	return n;
 }
 
+/**
+ *	skb_pad			-	zero pad the tail of an skb
+ *	@skb: buffer to pad
+ *	@pad: space to pad
+ *
+ *	Ensure that a buffer is followed by a padding area that is zero
+ *	filled. Used by network drivers which may DMA or transfer data
+ *	beyond the buffer end onto the wire.
+ *
+ *	May return NULL in out of memory cases.
+ */
+ 
+struct sk_buff *skb_pad(struct sk_buff *skb, int pad)
+{
+	struct sk_buff *nskb;
+	
+	/* If the skbuff is non linear tailroom is always zero.. */
+	if (skb_tailroom(skb) >= pad) {
+		memset(skb->data+skb->len, 0, pad);
+		return skb;
+	}
+	
+	nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + pad, GFP_ATOMIC);
+	kfree_skb(skb);
+	if (nskb)
+		memset(nskb->data+nskb->len, 0, pad);
+	return nskb;
+}	
+ 
 /* Trims skb to length len. It can change skb pointers, if "realloc" is 1.
  * If realloc==0 and trimming is impossible without change of data,
  * it is BUG().
diff -Nru a/net/ipv4/arp.c b/net/ipv4/arp.c
--- a/net/ipv4/arp.c	Mon Jan 13 10:18:07 2003
+++ b/net/ipv4/arp.c	Mon Jan 13 10:18:07 2003
@@ -1172,6 +1172,7 @@
 		n = n->next;
 		/* Don't confuse "arp -a" w/ magic entries */
 try_again:
+		;
 	} while (n && !(n->nud_state & ~NUD_NOARP));
 
 	if (n)
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	Mon Jan 13 10:18:05 2003
+++ b/net/ipv4/raw.c	Mon Jan 13 10:18:05 2003
@@ -715,6 +715,7 @@
 	do {
 		sk = sk->next;
 try_again:
+		;
 	} while (sk && sk->family != PF_INET);
 
 	if (!sk && ++state->bucket < RAWV4_HTABLE_SIZE) {
diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c
--- a/net/ipv4/route.c	Mon Jan 13 10:18:07 2003
+++ b/net/ipv4/route.c	Mon Jan 13 10:18:07 2003
@@ -2672,11 +2672,13 @@
 					ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
+#ifdef CONFIG_PROC_FS
 	if (rt_cache_proc_init())
 		goto out_enomem;
 	proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info);
 #ifdef CONFIG_NET_CLS_ROUTE
 	create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL);
+#endif
 #endif
 	xfrm_init();
 out:
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	Mon Jan 13 10:18:05 2003
+++ b/net/ipv4/tcp_ipv4.c	Mon Jan 13 10:18:05 2003
@@ -2412,7 +2412,8 @@
 			read_unlock_bh(&tp->syn_wait_lock);
 		}
 	case TCP_SEQ_STATE_LISTENING:
-		tcp_listen_unlock();
+		if (v != (void *)1)
+			tcp_listen_unlock();
 		break;
 	case TCP_SEQ_STATE_TIME_WAIT:
 	case TCP_SEQ_STATE_ESTABLISHED:
diff -Nru a/net/sunrpc/svc.c b/net/sunrpc/svc.c
--- a/net/sunrpc/svc.c	Mon Jan 13 10:18:07 2003
+++ b/net/sunrpc/svc.c	Mon Jan 13 10:18:07 2003
@@ -304,16 +304,21 @@
 	 * We do this before anything else in order to get a decent
 	 * auth verifier.
 	 */
-	if (svc_authenticate(rqstp, &rpc_stat, &auth_stat, proc))
-		/* drop the request, it has probably been deferred */
-		goto dropit;
-
-	if (rpc_stat != rpc_success)
-		goto err_garbage;
-
-	if (auth_stat != rpc_auth_ok)
+	switch (svc_authenticate(rqstp, &auth_stat)) {
+	case SVC_OK:
+		break;
+	case SVC_GARBAGE:
+		rpc_stat = rpc_garbage_args;
+		goto err_bad;
+	case SVC_SYSERR:
+		rpc_stat = rpc_system_err;
+		goto err_bad;
+	case SVC_DENIED:
 		goto err_bad_auth;
-
+	case SVC_DROP:
+		goto dropit;
+	}
+		
 	progp = serv->sv_program;
 	if (prog != progp->pg_prog)
 		goto err_bad_prog;
@@ -458,7 +463,9 @@
 #ifdef RPC_PARANOIA
 	printk("svc: failed to decode args\n");
 #endif
+	rpc_stat = rpc_garbage_args;
+err_bad:
 	serv->sv_stats->rpcbadfmt++;
-	svc_putu32(resv, rpc_garbage_args);
+	svc_putu32(resv, rpc_stat);
 	goto sendit;
 }
diff -Nru a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
--- a/net/sunrpc/svcauth.c	Mon Jan 13 10:18:07 2003
+++ b/net/sunrpc/svcauth.c	Mon Jan 13 10:18:07 2003
@@ -33,12 +33,11 @@
 };
 
 int
-svc_authenticate(struct svc_rqst *rqstp, u32 *statp, u32 *authp, int proc)
+svc_authenticate(struct svc_rqst *rqstp, u32 *authp)
 {
 	rpc_authflavor_t	flavor;
 	struct auth_ops		*aops;
 
-	*statp = rpc_success;
 	*authp = rpc_auth_ok;
 
 	flavor = ntohl(svc_getu32(&rqstp->rq_arg.head[0]));
@@ -46,25 +45,11 @@
 	dprintk("svc: svc_authenticate (%d)\n", flavor);
 	if (flavor >= RPC_AUTH_MAXFLAVOR || !(aops = authtab[flavor])) {
 		*authp = rpc_autherr_badcred;
-		return 0;
+		return SVC_DENIED;
 	}
 
 	rqstp->rq_authop = aops;
-	switch (aops->accept(rqstp, authp, proc)) {
-	case SVC_OK:
-		return 0;
-	case SVC_GARBAGE:
-		*statp = rpc_garbage_args;
-		return 0;
-	case SVC_SYSERR:
-		*statp = rpc_system_err;
-		return 0;
-	case SVC_DENIED:
-		return 0;
-	case SVC_DROP:
-		break;
-	}
-	return 1; /* drop the request */
+	return aops->accept(rqstp, authp);
 }
 
 /* A reqeust, which was authenticated, has now executed.
@@ -111,25 +96,6 @@
  * If it finds the name does exist, but isn't AUTH_UNIX,
  * it will complain.
  */
-
-int hash_mem(char *buf, int len, int bits)
-{
-	int hash = 0;
-	unsigned long l;
-	while (len >= BITS_PER_LONG/8) {
-		l = *(unsigned long *)buf;
-		buf += BITS_PER_LONG/8;
-		len -= BITS_PER_LONG/8;
-		hash ^= hash_long(l, bits);
-	}
-	if (len) {
-		l=0;
-		memcpy((char*)&l, buf, len);
-		hash ^= hash_long(l, bits);
-	}
-	return hash;
-}
-
 
 /*
  * Auth auth_domain cache is somewhat different to other caches,
diff -Nru a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
--- a/net/sunrpc/svcauth_unix.c	Mon Jan 13 10:18:06 2003
+++ b/net/sunrpc/svcauth_unix.c	Mon Jan 13 10:18:06 2003
@@ -321,7 +321,7 @@
 
 
 static int
-svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
+svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
 {
 	struct iovec	*argv = &rqstp->rq_arg.head[0];
 	struct iovec	*resv = &rqstp->rq_res.head[0];
@@ -376,7 +376,7 @@
 		}
 	else rv = SVC_DROP;
 
-	if (rqstp->rq_client == NULL && proc != 0)
+	if (rqstp->rq_client == NULL && rqstp->rq_proc != 0)
 		*authp = rpc_autherr_badcred;
 
 	return rv;
@@ -402,7 +402,7 @@
 
 
 int
-svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
+svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
 {
 	struct iovec	*argv = &rqstp->rq_arg.head[0];
 	struct iovec	*resv = &rqstp->rq_res.head[0];
@@ -470,7 +470,7 @@
 		}
 	else rv = SVC_DROP;
 
-	if (rqstp->rq_client == NULL && proc != 0)
+	if (rqstp->rq_client == NULL && rqstp->rq_proc != 0)
 		goto badcred;
 	return rv;
 
diff -Nru a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
--- a/net/sunrpc/svcsock.c	Mon Jan 13 10:18:05 2003
+++ b/net/sunrpc/svcsock.c	Mon Jan 13 10:18:05 2003
@@ -137,6 +137,12 @@
 		printk(KERN_ERR
 			"svc_sock_enqueue: threads and sockets both waiting??\n");
 
+	if (test_bit(SK_DEAD, &svsk->sk_flags)) {
+		/* Don't enqueue dead sockets */
+		dprintk("svc: socket %p is dead, not enqueued\n", svsk->sk_sk);
+		goto out_unlock;
+	}
+
 	if (test_bit(SK_BUSY, &svsk->sk_flags)) {
 		/* Don't enqueue socket while daemon is receiving */
 		dprintk("svc: socket %p busy, not enqueued\n", svsk->sk_sk);
@@ -179,7 +185,6 @@
 	} else {
 		dprintk("svc: socket %p put into queue\n", svsk->sk_sk);
 		list_add_tail(&svsk->sk_ready, &serv->sv_sockets);
-		set_bit(SK_QUED, &svsk->sk_flags);
 	}
 
 out_unlock:
@@ -199,11 +204,10 @@
 
 	svsk = list_entry(serv->sv_sockets.next,
 			  struct svc_sock, sk_ready);
-	list_del(&svsk->sk_ready);
+	list_del_init(&svsk->sk_ready);
 
 	dprintk("svc: socket %p dequeued, inuse=%d\n",
 		svsk->sk_sk, svsk->sk_inuse);
-	clear_bit(SK_QUED, &svsk->sk_flags);
 
 	return svsk;
 }
@@ -627,7 +631,7 @@
 	return error;
 }
 
-static int
+static void
 svc_udp_init(struct svc_sock *svsk)
 {
 	svsk->sk_sk->data_ready = svc_udp_data_ready;
@@ -643,9 +647,8 @@
 			    3 * svsk->sk_server->sv_bufsz,
 			    3 * svsk->sk_server->sv_bufsz);
 
+	set_bit(SK_DATA, &svsk->sk_flags); /* might have come in before data_ready set up */
 	set_bit(SK_CHNGBUF, &svsk->sk_flags);
-
-	return 0;
 }
 
 /*
@@ -773,19 +776,14 @@
 	dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
 			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
 
-	if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
-		goto failed;
-
 	/* make sure that a write doesn't block forever when
 	 * low on memory
 	 */
 	newsock->sk->sndtimeo = HZ*30;
 
-	/* Precharge. Data may have arrived on the socket before we
-	 * installed the data_ready callback. 
-	 */
-	set_bit(SK_DATA, &newsvsk->sk_flags);
-	svc_sock_enqueue(newsvsk);
+	if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
+		goto failed;
+
 
 	/* make sure that we don't have too many active connections.
 	 * If we have, something must be dropped.
@@ -1006,7 +1004,7 @@
 	return sent;
 }
 
-static int
+static void
 svc_tcp_init(struct svc_sock *svsk)
 {
 	struct sock	*sk = svsk->sk_sk;
@@ -1017,6 +1015,7 @@
 	if (sk->state == TCP_LISTEN) {
 		dprintk("setting up TCP socket for listening\n");
 		sk->data_ready = svc_tcp_listen_data_ready;
+		set_bit(SK_CONN, &svsk->sk_flags);
 	} else {
 		dprintk("setting up TCP socket for reading\n");
 		sk->state_change = svc_tcp_state_change;
@@ -1035,9 +1034,8 @@
 				    3 * svsk->sk_server->sv_bufsz);
 
 		set_bit(SK_CHNGBUF, &svsk->sk_flags);
+		set_bit(SK_DATA, &svsk->sk_flags);
 	}
-
-	return 0;
 }
 
 void
@@ -1182,8 +1180,8 @@
 	if (test_bit(SK_TEMP, &svsk->sk_flags)) {
 		/* push active sockets to end of list */
 		spin_lock_bh(&serv->sv_lock);
-		list_del(&svsk->sk_list);
-		list_add_tail(&svsk->sk_list, &serv->sv_tempsocks);
+		if (!list_empty(&svsk->sk_list))
+			list_move_tail(&svsk->sk_list, &serv->sv_tempsocks);
 		spin_unlock_bh(&serv->sv_lock);
 	}
 
@@ -1258,6 +1256,18 @@
 	memset(svsk, 0, sizeof(*svsk));
 
 	inet = sock->sk;
+
+	/* Register socket with portmapper */
+	if (*errp >= 0 && pmap_register)
+		*errp = svc_register(serv, inet->protocol,
+				     ntohs(inet_sk(inet)->sport));
+
+	if (*errp < 0) {
+		kfree(svsk);
+		return NULL;
+	}
+
+	set_bit(SK_BUSY, &svsk->sk_flags);
 	inet->user_data = svsk;
 	svsk->sk_sock = sock;
 	svsk->sk_sk = inet;
@@ -1267,27 +1277,14 @@
 	svsk->sk_server = serv;
 	svsk->sk_lastrecv = get_seconds();
 	INIT_LIST_HEAD(&svsk->sk_deferred);
+	INIT_LIST_HEAD(&svsk->sk_ready);
 	sema_init(&svsk->sk_sem, 1);
 
 	/* Initialize the socket */
 	if (sock->type == SOCK_DGRAM)
-		*errp = svc_udp_init(svsk);
+		svc_udp_init(svsk);
 	else
-		*errp = svc_tcp_init(svsk);
-if (svsk->sk_sk == NULL)
-	printk(KERN_WARNING "svsk->sk_sk == NULL after svc_prot_init!\n");
-
-	/* Register socket with portmapper */
-	if (*errp >= 0 && pmap_register)
-		*errp = svc_register(serv, inet->protocol,
-				     ntohs(inet_sk(inet)->sport));
-
-	if (*errp < 0) {
-		inet->user_data = NULL;
-		kfree(svsk);
-		return NULL;
-	}
-
+		svc_tcp_init(svsk);
 
 	spin_lock_bh(&serv->sv_lock);
 	if (!pmap_register) {
@@ -1302,6 +1299,9 @@
 
 	dprintk("svc: svc_setup_socket created %p (inet %p)\n",
 				svsk, svsk->sk_sk);
+
+	clear_bit(SK_BUSY, &svsk->sk_flags);
+	svc_sock_enqueue(svsk);
 	return svsk;
 }
 
@@ -1373,14 +1373,11 @@
 
 	spin_lock_bh(&serv->sv_lock);
 
-	list_del(&svsk->sk_list);
-	if (test_bit(SK_TEMP, &svsk->sk_flags))
-		serv->sv_tmpcnt--;
-	if (test_bit(SK_QUED, &svsk->sk_flags))
-		list_del(&svsk->sk_ready);
-
-
-	set_bit(SK_DEAD, &svsk->sk_flags);
+	list_del_init(&svsk->sk_list);
+	list_del_init(&svsk->sk_ready);
+	if (!test_and_set_bit(SK_DEAD, &svsk->sk_flags))
+		if (test_bit(SK_TEMP, &svsk->sk_flags))
+			serv->sv_tmpcnt--;
 
 	if (!svsk->sk_inuse) {
 		spin_unlock_bh(&serv->sv_lock);
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Mon Jan 13 10:18:05 2003
+++ b/security/dummy.c	Mon Jan 13 10:18:05 2003
@@ -501,6 +501,15 @@
 	return 0;
 }
 
+static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
+{
+	return 0;
+}
+
+static void dummy_msg_msg_free_security (struct msg_msg *msg)
+{
+	return;
+}
 
 static int dummy_msg_queue_alloc_security (struct msg_queue *msq)
 {
@@ -512,6 +521,30 @@
 	return;
 }
 
+static int dummy_msg_queue_associate (struct msg_queue *msq, 
+				      int msqflg)
+{
+	return 0;
+}
+
+static int dummy_msg_queue_msgctl (struct msg_queue *msq, int cmd)
+{
+	return 0;
+}
+
+static int dummy_msg_queue_msgsnd (struct msg_queue *msq, struct msg_msg *msg,
+				   int msgflg)
+{
+	return 0;
+}
+
+static int dummy_msg_queue_msgrcv (struct msg_queue *msq, struct msg_msg *msg,
+				   struct task_struct *target, long type,
+				   int mode)
+{
+	return 0;
+}
+
 static int dummy_shm_alloc_security (struct shmid_kernel *shp)
 {
 	return 0;
@@ -522,6 +555,22 @@
 	return;
 }
 
+static int dummy_shm_associate (struct shmid_kernel *shp, int shmflg)
+{
+	return 0;
+}
+
+static int dummy_shm_shmctl (struct shmid_kernel *shp, int cmd)
+{
+	return 0;
+}
+
+static int dummy_shm_shmat (struct shmid_kernel *shp, char *shmaddr,
+			    int shmflg)
+{
+	return 0;
+}
+
 static int dummy_sem_alloc_security (struct sem_array *sma)
 {
 	return 0;
@@ -532,6 +581,22 @@
 	return;
 }
 
+static int dummy_sem_associate (struct sem_array *sma, int semflg)
+{
+	return 0;
+}
+
+static int dummy_sem_semctl (struct sem_array *sma, int cmd)
+{
+	return 0;
+}
+
+static int dummy_sem_semop (struct sem_array *sma, 
+			    struct sembuf *sops, unsigned nsops, int alter)
+{
+	return 0;
+}
+
 static int dummy_register_security (const char *name, struct security_operations *ops)
 {
 	return -EINVAL;
@@ -640,12 +705,24 @@
 	set_to_dummy_if_null(ops, task_kmod_set_label);
 	set_to_dummy_if_null(ops, task_reparent_to_init);
 	set_to_dummy_if_null(ops, ipc_permission);
+	set_to_dummy_if_null(ops, msg_msg_alloc_security);
+	set_to_dummy_if_null(ops, msg_msg_free_security);
 	set_to_dummy_if_null(ops, msg_queue_alloc_security);
 	set_to_dummy_if_null(ops, msg_queue_free_security);
+	set_to_dummy_if_null(ops, msg_queue_associate);
+	set_to_dummy_if_null(ops, msg_queue_msgctl);
+	set_to_dummy_if_null(ops, msg_queue_msgsnd);
+	set_to_dummy_if_null(ops, msg_queue_msgrcv);
 	set_to_dummy_if_null(ops, shm_alloc_security);
 	set_to_dummy_if_null(ops, shm_free_security);
+	set_to_dummy_if_null(ops, shm_associate);
+	set_to_dummy_if_null(ops, shm_shmctl);
+	set_to_dummy_if_null(ops, shm_shmat);
 	set_to_dummy_if_null(ops, sem_alloc_security);
 	set_to_dummy_if_null(ops, sem_free_security);
+	set_to_dummy_if_null(ops, sem_associate);
+	set_to_dummy_if_null(ops, sem_semctl);
+	set_to_dummy_if_null(ops, sem_semop);
 	set_to_dummy_if_null(ops, register_security);
 	set_to_dummy_if_null(ops, unregister_security);
 }
diff -Nru a/sound/oss/ad1848.c b/sound/oss/ad1848.c
--- a/sound/oss/ad1848.c	Mon Jan 13 10:18:06 2003
+++ b/sound/oss/ad1848.c	Mon Jan 13 10:18:06 2003
@@ -2987,7 +2987,7 @@
 	if(dev->active)
 		return(dev);
 
-	if((err = pnp_activate_dev(dev)) < 0) {
+	if((err = pnp_activate_dev(dev,NULL)) < 0) {
 		printk(KERN_ERR "ad1848: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
 
 		pnp_disable_dev(dev);
diff -Nru a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
--- a/sound/oss/opl3sa2.c	Mon Jan 13 10:18:04 2003
+++ b/sound/oss/opl3sa2.c	Mon Jan 13 10:18:04 2003
@@ -836,14 +836,14 @@
 }
 
 #ifdef CONFIG_PNP
-struct pnp_id pnp_opl3sa2_list[] = {
+struct pnp_device_id pnp_opl3sa2_list[] = {
 	{.id = "YMH0021", .driver_data = 0},
 	{.id = ""}
 };
 
 MODULE_DEVICE_TABLE(pnp, pnp_opl3sa2_list);
 
-static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_id *dev_id)
+static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
 	int card = opl3sa2_cards_num;
 	if (opl3sa2_cards_num == OPL3SA2_CARDS_MAX)
diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
--- a/sound/pci/ali5451/ali5451.c	Mon Jan 13 10:18:07 2003
+++ b/sound/pci/ali5451/ali5451.c	Mon Jan 13 10:18:07 2003
@@ -67,7 +67,7 @@
 MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",default:32,allows:{{1,32}}");
 
 /*
- *  Debug part definations
+ *  Debug part definitions
  */
 
 //#define ALI_DEBUG
