## Automatically generated incremental diff
## From:   linux-2.5.2-pre6
## To:     linux-2.5.2-pre7
## Robot:  $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $

diff -urN linux-2.5.2-pre6/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.5.2-pre6/Documentation/Configure.help	Fri Nov 30 13:25:10 2001
+++ linux/Documentation/Configure.help	Thu Jan  3 14:10:35 2002
@@ -12541,6 +12541,30 @@
   If you have an MGE Ellipse UPS, or you see timeouts in HID
   transactions, say Y; otherwise say N.
 
+EHCI (USB 2.0) support
+CONFIG_USB_EHCI_HCD
+  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
+  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
+  If your USB host controller supports USB 2.0, you will likely want to
+  configure this Host Controller Driver.  At this writing, the primary
+  implementation of EHCI is a chip from NEC, widely available in add-on
+  PCI cards, but implementations are in the works from other vendors
+  including Intel and Philips.  Motherboard support is appearing.
+
+  EHCI controllers are packaged with "companion" host controllers (OHCI
+  or UHCI) to handle USB 1.1 devices connected to root hub ports.  Ports
+  will connect to EHCI if it the device is high speed, otherwise they
+  connect to a companion controller.  If you configure EHCI, you should
+  probably configure the OHCI (for NEC and some other vendors) USB Host
+  Controller Driver too.
+
+  You may want to read <file:Documentation/usb/ehci.txt>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ehci-hcd.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 UHCI (Intel PIIX4, VIA, ...) support
 CONFIG_USB_UHCI
   The Universal Host Controller Interface is a standard by Intel for
@@ -12841,6 +12865,17 @@
   The module will be called visor.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+USB Compaq iPAQ Driver
+CONFIG_USB_SERIAL_IPAQ
+  Say Y here if you want to connect to your Compaq iPAQ running
+  Windows CE 3.0 using a USB autosync cable. For information on using
+  the driver, read <file:Documentation/usb/usb-serial.txt>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ipaq.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 USB IR Dongle Serial Driver
 CONFIG_USB_SERIAL_IR
   Say Y here if you want to enable simple serial support for USB IrDA
@@ -13061,6 +13096,22 @@
   The module will be called io_edgeport.o.  If you want to compile it
   as a module, say M here and read <file:Documentation/modules.txt>.
 
+USB PalmConnect (and other KL5KUSB105-based) Single Port Serial Driver
+CONFIG_USB_SERIAL_KLSI
+  Say Y here if you want to use a KL5KUSB105 - based single port
+  serial adapter. The most widely known -- and currently the only
+  tested -- device in this category is the PalmConnect USB Serial
+  adapter sold by Palm Inc. for use with their Palm III and Palm V
+  series PDAs.
+
+  Please read <file:Documentation/usb/usb-serial.txt> for more
+  information.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called kl5kusb105.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
 USB Serial Converter verbose debug
 CONFIG_USB_SERIAL_DEBUG
   Say Y here if you want verbose debug messages from the USB Serial
@@ -13167,6 +13218,54 @@
   The module will be called pwc.o.  If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+USB SE401 Camera support
+CONFIG_USB_SE401
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. See <file:Documentation/usb/se401.txt> for more
+  information and for a list of supported cameras.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called se401.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+USB STV680 (Pencam) Camera support
+CONFIG_USB_STV680
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. This includes the Pencam line of cameras.
+  See <file:Documentation/usb/stv680.txt> for more information and for
+  a list of supported cameras.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called stv680.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+Vicam
+CONFIG_USB_VICAM
+  Say Y here if you have 3com homeconnect camera (vicam).
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called vicam.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+
 Pegasus/Pegasus II based USB-Ethernet device support
 CONFIG_USB_PEGASUS
   Say Y here if you know you have Pegasus or Pegasus II based adapter.
@@ -16960,22 +17059,6 @@
   Note that, even if you say N here, Linux on the x86 architecture
   will issue the hlt instruction if nothing is to be done, thereby
   sending the processor to sleep and saving power.
-
-USB SE401 Camera support
-CONFIG_USB_SE401
-  Say Y here if you want to connect this type of camera to your
-  computer's USB port. See <file:Documentation/usb/se401.txt> for more
-  information and for a list of supported cameras.
-
-  This driver uses the Video For Linux API. You must say Y or M to
-  "Video For Linux" (under Multimedia Devices) to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called se401.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
 
 ACPI support
 CONFIG_ACPI
diff -urN linux-2.5.2-pre6/Documentation/usb/ehci.txt linux/Documentation/usb/ehci.txt
--- linux-2.5.2-pre6/Documentation/usb/ehci.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/usb/ehci.txt	Thu Jan  3 14:10:35 2002
@@ -0,0 +1,164 @@
+18-Dec-2001
+
+The EHCI driver is used to talk to high speed USB 2.0 devices using
+USB 2.0-capable host controller hardware.  The USB 2.0 standard is
+compatible with the USB 1.1 standard. It defines three transfer speeds:
+
+    - "High Speed" 480 Mbit/sec (60 MByte/sec)
+    - "Full Speed" 12 Mbit/sec (1.5 MByte/sec)
+    - "Low Speed" 1.5 Mbit/sec
+
+USB 1.1 only addressed full speed and low speed.  High speed devices
+can be used on USB 1.1 systems, but they slow down to USB 1.1 speeds. 
+
+USB 1.1 devices may also be used on USB 2.0 systems.  When plugged
+into an EHCI controller, they are given to a USB 1.1 "companion"
+controller, which is a OHCI or UHCI controller as normally used with
+such devices.  When USB 1.1 devices plug into USB 2.0 hubs, they
+interact with the EHCI controller through a "Transaction Translator"
+(TT) in the hub, which turns low or full speed transactions into
+high speed "split transactions" that don't waste transfer bandwidth.
+
+At this writing, high speed devices are finally beginning to appear.
+While usb-storage devices have been available for some time (working
+quite speedily on the 2.4 version of this driver), hubs have only
+very recently become available.
+
+Note that USB 2.0 support involves more than just EHCI.  It requires
+other changes to the Linux-USB core APIs, including the hub driver,
+but those changes haven't needed to really change the basic "usbcore"
+APIs exposed to USB device drivers.
+
+- David Brownell
+  <dbrownell@users.sourceforge.net>
+
+
+FUNCTIONALITY
+
+This driver is regularly tested on x86 hardware, and has also been
+used on PPC hardware so big/little endianneess issues should be gone.
+It's believed to do all the right PCI magic so that I/O works even on
+systems with interesting DMA mapping issues.
+
+At this writing the driver should comfortably handle all control and bulk
+transfers, including requests to USB 1.1 devices through transaction
+translators (TTs) in USB 2.0 hubs.  However, there some situations where
+the hub driver needs to clear TT error state, which it doesn't yet do.
+
+Interrupt transfer support is newly functional and not yet as robust as
+control and bulk traffic.  As yet there is no support for split transaction
+scheduling for interrupt transfers, which means among other things that
+connecting USB 1.1 hubs, keyboards, and mice to USB 2.0 hubs won't work.
+Connect them to USB 1.1 hubs, or to a root hub.
+
+Isochronous (ISO) transfer support is not yet working.  No production
+high speed devices are available which would need it (though high quality
+webcams are in the works!).  Note that split transaction support for ISO
+transfers can't share much code with the code for high speed ISO transfers,
+since EHCI represents these with a different data structure.
+
+The EHCI root hub code should hand off USB 1.1 devices to its companion
+controller.  This driver doesn't need to know anything about those
+drivers; a OHCI or UHCI driver that works already doesn't need to change
+just because the EHCI driver is also present.
+
+There are some issues with power management; suspend/resume doesn't
+behave quite right at the moment.
+
+
+USE BY
+
+Assuming you have an EHCI controller (on a PCI card or motherboard)
+and have compiled this driver as a module, load this like:
+
+    # modprobe ehci-hcd
+
+and remove it by:
+
+    # rmmod ehci-hcd
+
+You should also have a driver for a "companion controller", such as
+"ohci-hcd", "usb-ohci", "usb-uhci", or "uhci".  In case of any trouble
+with the EHCI driver, remove its module and then the driver for that
+companion controller will take over (at lower speed) all the devices
+that were previously handled by the EHCI driver.
+
+Module parameters (pass to "modprobe") include:
+
+    log2_irq_thresh (default 0):
+	Log2 of default interrupt delay, in microframes.  The default
+	value is 0, indicating 1 microframe (125 usec).  Maximum value
+	is 6, indicating 2^6 = 64 microframes.  This controls how often
+	the EHCI controller can issue interrupts.
+
+The EHCI interrupt handler just acknowledges interrupts and schedules
+a tasklet to handle whatever needs handling.  That keeps latencies low,
+no matter how often interrupts are issued.
+
+Device drivers shouldn't care whether they're running over EHCI or not,
+but they may want to check for "usb_device->speed == USB_SPEED_HIGH".
+High speed devices can do things that full speed (or low speed) ones
+can't, such as "high bandwidth" periodic (interrupt or ISO) transfers.
+
+
+PERFORMANCE
+
+USB 2.0 throughput is gated by two main factors:  how fast the host
+controller can process requests, and how fast devices can respond to
+them.  The 480 Mbit/sec "raw transfer rate" is obeyed by all devices,
+but aggregate throughput is also affected by issues like delays between
+individual high speed packets, driver intelligence, and of course the
+overall system load.  Latency is also a performance concern.
+
+Bulk transfers are most often used where throughput is an issue.  It's
+good to keep in mind that bulk transfers are always in 512 byte packets,
+and at most 13 of those fit into one USB 2.0 microframe.  Eight USB 2.0
+microframes fit in a USB 1.1 frame; a microframe is 1 msec/8 = 125 usec.
+
+Hardware Performance
+
+At this writing, individual USB 2.0 devices tend to max out at around
+20 MByte/sec transfer rates.  This is of course subject to change;
+and some devices now go faster, while others go slower.
+
+The NEC implementation of EHCI seems to have a hardware bottleneck
+at around 28 MByte/sec aggregate transfer rate.  While this is clearly
+enough for a single device at 20 MByte/sec, putting three such devices
+onto one bus does not get you 60 MByte/sec.  The issue appears to be
+that the controller hardware won't do concurrent USB and PCI access,
+so that it's only trying six (or maybe seven) USB transactions each
+microframe rather than thirteen.  (Seems like a reasonable trade off
+for a product that beat all the others to market by over a year!)
+It's expected that newer implementations will better this, throwing
+more silicon real estate at the problem so that new motherboard chip
+sets will get closer to that 60 MByte/sec target.
+
+There's a minimum latency of one microframe (125 usec) for the host
+to receive interrupts from the EHCI controller indicating completion
+of requests.  That latency is tunable; there's a module option.  By
+default ehci-hcd driver uses the minimum latency, which means that if
+you issue a control or bulk request you can often expect to learn that
+it completed in less than 250 usec (depending on transfer size).
+
+Software Performance
+
+To get even 20 MByte/sec transfer rates, Linux-USB device drivers will
+need to keep the EHCI queue full.  That means issuing large requests,
+or using bulk queuing if a series of small requests needs to be issued.
+When drivers don't do that, their performance results will show it.
+
+In typical situations, a usb_bulk_msg() loop writing out 4 KB chunks is
+going to waste more than half the USB 2.0 bandwidth.  Delays between the
+I/O completion and the driver issuing the next request will take longer
+than the I/O.  If that same loop used 16 KB chunks, it'd be better; a
+sequence of 128 KB chunks would waste a lot less.
+
+But rather than depending on such large I/O buffers to make synchronous
+I/O be efficient, it's better to just queue all several (bulk) requests
+to the HC, and wait for them all to complete (or be canceled on error).
+Such URB queuing should work with all the USB 1.1 HC drivers too.
+
+TBD:  Interrupt and ISO transfer performance issues.  Those periodic
+transfers are fully scheduled, so the main issue is likely to be how
+to trigger "high bandwidth" modes.
+
diff -urN linux-2.5.2-pre6/Documentation/usb/stv680.txt linux/Documentation/usb/stv680.txt
--- linux-2.5.2-pre6/Documentation/usb/stv680.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/usb/stv680.txt	Thu Jan  3 14:10:35 2002
@@ -0,0 +1,55 @@
+Linux driver for STV0680 based USB cameras
+
+Copyright, 2001, Kevin Sisson
+
+
+INTRODUCTION:
+
+STMicroelectronics produces the STV0680B chip, which comes in two 
+types, -001 and -003. The -003 version allows the recording and downloading 
+of sound clips from the camera, and allows a flash attachment. Otherwise, 
+it uses the same commands as the -001 version. Both versions support a 
+variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20 
+CIF pictures. The STV0680 supports either a serial or a usb interface, and 
+video is possible through the usb interface.
+
+The following cameras are known to work with this driver, although any 
+camera with Vendor/Product codes of 0553/0202 should work:
+
+Aiptek Pencam (various models)
+Nisis QuickPix 2
+Radio Shack 'Kid's digital camera' (#60-1207)
+At least one Trust Spycam model
+Several other European brand models
+
+WHAT YOU NEED:
+
+-	USB support
+-	VIDEO4LINUX support
+
+More information about USB support for linux can be found at:
+http://www.linux-usb.org
+
+
+MODULE OPTIONS:
+
+When the driver is compiled as a module, you can set a "swapRGB=1"
+option, if necessary, for those applications that require it 
+(such as xawtv). However, the driver should detect and set this 
+automatically, so this option should not normally be used.
+
+
+KNOWN PROBLEMS:
+
+The driver seems to work better with the usb-ohci than the usb-uhci host 
+controller driver. 
+
+HELP:
+
+The latest info on this driver can be found at:
+http://personal.clt.bellsouth.net/~kjsisson or at
+http://stv0680-usb.sourceforge.net
+
+Any questions to me can be send to:  kjsisson@bellsouth.net
+
+
diff -urN linux-2.5.2-pre6/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- linux-2.5.2-pre6/Documentation/usb/usb-serial.txt	Mon Nov 12 09:50:39 2001
+++ linux/Documentation/usb/usb-serial.txt	Thu Jan  3 14:10:35 2002
@@ -95,6 +95,66 @@
   Kroah-Hartman at greg@kroah.com
 
 
+Compaq iPAQ driver
+
+  This driver can be used to connect to Compaq iPAQ PDAs running
+  Windows CE 3.0 using a USB autosync cable. It has been tested only on
+  the Compaq H3135. It should work with the H3600 and later models too.
+  It may work with other CE based handhelds as well.
+
+  The driver presents a serial interface (usually on /dev/ttyUSB0) over
+  which one may run ppp and establish a TCP/IP link to the iPAQ. Once this
+  is done, you can transfer files, backup, download email etc. The most
+  significant advantage of using USB is speed - you can get 73 to 113
+  kbytes/sec for download/upload to the iPAQ.
+
+  The driver works intermittently with the usb-uhci driver but quite
+  reliably with the uhci driver. Make sure you have the right driver
+  loaded - usb-uhci is often the default.
+
+  You must setup hotplug to invoke pppd as soon as the iPAQ is connected.
+  A ppp script like the one below may be used:
+
+	#!/bin/bash
+
+	MYIP=linux.box.ip
+	REMOTEIP=ipaq.ip
+	MYDNS=my.dns.server
+	killall -9 pppd
+	/usr/sbin/pppd /dev/ttyUSB0 \
+	connect "/usr/sbin/chat -v TIMEOUT 60 CLIENT 'CLIENTSERVER\c'" \
+	nocrtscts local debug passive $MYIP:$REMOTEIP ms-dns $MYDNS noauth \
+	proxyarp
+
+  You must also download and install asyncd from http://synce.sourceforge.net
+  This is required to emulate keep-alive packets which are exchanged by
+  ActiveSync and the iPAQ.
+
+  On connecting the cable, you should see the usual "Device Connected",
+  "User Authenticated" messages flash by on your iPAQ. Once connected,
+  you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ
+  and other synce utilities from the Linux side. Remember to enable IP
+  forwarding. 
+
+  To use Pocket IE, follow the instructions given at
+  http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing
+  on Win98. Omit the proxy server part; Linux is quite capable of forwarding
+  packets unlike Win98. Another modification is required at least for the
+  iPAQ - disable autosync by going to the Start/Settings/Connections menu
+  and unchecking the "Automatically synchronize ..." box. Go to
+  Start/Programs/Connections, connect the cable and select "usbdial" (or
+  whatever you named your new USB connection). You should finally wind
+  up with a "Connected to usbdial" window with status shown as connected.
+  Now start up PIE and browse away.
+
+  If it doesn't work for some reason, load both the usbserial and ipaq module
+  with the module parameter "debug" set to 1 and examine the system log.
+  You can also try soft-resetting your iPAQ before attempting a connection.
+
+  For any questions or problems with the driver, please contact Ganesh
+  Varadarajan <ganesh@veritas.com>
+
+
 Keyspan PDA Serial Adapter
 
   Single port DB-9 serial adapter, pushed as a PDA adapter for iMacs (mostly
@@ -301,6 +361,32 @@
   For any questions or problems with this driver, please contact Greg
   Kroah-Hartman at greg@kroah.com
   
+
+KL5KUSB105 chipset / PalmConnect USB single-port adapter
+  
+Current status:
+  The driver was put together by looking at the usb bus transactions
+  done by Palm's driver under Windows, so a lot of functionality is
+  still missing.  Notably, serial ioctls are sometimes faked or not yet
+  implemented.  Support for finding out about DSR and CTS line status is
+  however implemented (though not nicely), so your favorite autopilot(1)
+  and pilot-manager -daemon calls will work.  Baud rates up to 115200
+  are supported, but handshaking (software or hardware) is not, which is
+  why it is wise to cut down on the rate used is wise for large
+  transfers until this is settled.
+  
+Options supported:
+  If this driver is compiled as a module you can pass the following
+  options to it:
+  debug			- extra verbose debugging info
+  			  (default: 0; nonzero enables)
+  use_lowlatency	- use low_latency flag to speed up tty layer
+			  when reading from from the device.
+			  (default: 0; nonzero enables)
+
+  See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
+  information on this driver.
+
 
 Generic Serial driver
 
diff -urN linux-2.5.2-pre6/Makefile linux/Makefile
--- linux-2.5.2-pre6/Makefile	Thu Jan  3 14:10:32 2002
+++ linux/Makefile	Thu Jan  3 14:10:35 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 2
-EXTRAVERSION =-pre6
+EXTRAVERSION =-pre7
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.5.2-pre6/arch/i386/kernel/cpuid.c linux/arch/i386/kernel/cpuid.c
--- linux-2.5.2-pre6/arch/i386/kernel/cpuid.c	Thu Oct 11 09:04:57 2001
+++ linux/arch/i386/kernel/cpuid.c	Thu Jan  3 14:10:35 2002
@@ -101,7 +101,7 @@
   u32 data[4];
   size_t rv;
   u32 reg = *ppos;
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   
   if ( count % 16 )
     return -EINVAL; /* Invalid chunk size */
@@ -119,7 +119,7 @@
 
 static int cpuid_open(struct inode *inode, struct file *file)
 {
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   struct cpuinfo_x86 *c = &(cpu_data)[cpu];
 
   if ( !(cpu_online_map & (1UL << cpu)) )
diff -urN linux-2.5.2-pre6/arch/i386/kernel/msr.c linux/arch/i386/kernel/msr.c
--- linux-2.5.2-pre6/arch/i386/kernel/msr.c	Thu Oct 11 09:04:57 2001
+++ linux/arch/i386/kernel/msr.c	Thu Jan  3 14:10:35 2002
@@ -181,7 +181,7 @@
   u32 data[2];
   size_t rv;
   u32 reg = *ppos;
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   int err;
 
   if ( count % 8 )
@@ -206,7 +206,7 @@
   u32 data[2];
   size_t rv;
   u32 reg = *ppos;
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   int err;
 
   if ( count % 8 )
@@ -226,7 +226,7 @@
 
 static int msr_open(struct inode *inode, struct file *file)
 {
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   struct cpuinfo_x86 *c = &(cpu_data)[cpu];
   
   if ( !(cpu_online_map & (1UL << cpu)) )
diff -urN linux-2.5.2-pre6/drivers/block/DAC960.h linux/drivers/block/DAC960.h
--- linux-2.5.2-pre6/drivers/block/DAC960.h	Tue Nov 27 09:23:27 2001
+++ linux/drivers/block/DAC960.h	Thu Jan  3 14:10:36 2002
@@ -2054,13 +2054,13 @@
 */
 
 #define DAC960_ControllerNumber(Device) \
-  (MAJOR(Device) - DAC960_MAJOR)
+  (major(Device) - DAC960_MAJOR)
 
 #define DAC960_LogicalDriveNumber(Device) \
-  (MINOR(Device) >> DAC960_MaxPartitionsBits)
+  (minor(Device) >> DAC960_MaxPartitionsBits)
 
 #define DAC960_PartitionNumber(Device) \
-  (MINOR(Device) & (DAC960_MaxPartitions - 1))
+  (minor(Device) & (DAC960_MaxPartitions - 1))
 
 #define DAC960_MajorNumber(ControllerNumber) \
   (DAC960_MAJOR + (ControllerNumber))
diff -urN linux-2.5.2-pre6/drivers/block/cciss.c linux/drivers/block/cciss.c
--- linux-2.5.2-pre6/drivers/block/cciss.c	Thu Jan  3 14:10:32 2002
+++ linux/drivers/block/cciss.c	Thu Jan  3 14:10:36 2002
@@ -317,8 +317,8 @@
  */
 static int cciss_open(struct inode *inode, struct file *filep)
 {
-	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+	int ctlr = major(inode->i_rdev) - MAJOR_NR;
+	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk);
@@ -327,7 +327,7 @@
 	if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
 		return -ENXIO;
 
-	if (!suser() && hba[ctlr]->sizes[ MINOR(inode->i_rdev)] == 0)
+	if (!suser() && hba[ctlr]->sizes[minor(inode->i_rdev)] == 0)
 		return -ENXIO;
 
 	/*
@@ -337,8 +337,8 @@
 	 * for "raw controller".
 	 */
 	if (suser()
-		&& (hba[ctlr]->sizes[MINOR(inode->i_rdev)] == 0) 
-		&& (MINOR(inode->i_rdev)!= 0))
+		&& (hba[ctlr]->sizes[minor(inode->i_rdev)] == 0) 
+		&& (minor(inode->i_rdev)!= 0))
 		return -ENXIO;
 
 	hba[ctlr]->drv[dsk].usage_count++;
@@ -350,8 +350,8 @@
  */
 static int cciss_release(struct inode *inode, struct file *filep)
 {
-	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+	int ctlr = major(inode->i_rdev) - MAJOR_NR;
+	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk);
@@ -370,8 +370,8 @@
 static int cciss_ioctl(struct inode *inode, struct file *filep, 
 		unsigned int cmd, unsigned long arg)
 {
-	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+	int ctlr = major(inode->i_rdev) - MAJOR_NR;
+	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg);
@@ -696,8 +696,8 @@
         unsigned long flags;
         int res;
 
-        target = MINOR(dev) >> NWD_SHIFT;
-        ctlr = MAJOR(dev) - MAJOR_NR;
+        target = minor(dev) >> NWD_SHIFT;
+        ctlr = major(dev) - MAJOR_NR;
         gdev = &(hba[ctlr]->gendisk);
 
         spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
@@ -746,8 +746,8 @@
 	int ctlr, i;
 	unsigned long flags;
 
-	ctlr = MAJOR(dev) - MAJOR_NR;
-        if (MINOR(dev) != 0)
+	ctlr = major(dev) - MAJOR_NR;
+        if (minor(dev) != 0)
                 return -ENXIO;
 
         spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
@@ -781,9 +781,11 @@
         hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_ON);
 
         cciss_geninit(ctlr);
-        for(i=0; i<NWD; i++)
+        for(i=0; i<NWD; i++) {
+		kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
                 if (hba[ctlr]->sizes[ i<<NWD_SHIFT ])
-                        revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
+                        revalidate_logvol(kdev, 2);
+	}
 
         hba[ctlr]->usage_count--;
         return 0;
@@ -1205,7 +1207,6 @@
 	ctlr_info_t *h= q->queuedata; 
 	CommandList_struct *c;
 	int log_unit, start_blk, seg;
-	struct list_head *queue_head = &q->queue_head;
 	struct request *creq;
 	u64bit temp64;
 	struct scatterlist tmp_sg[MAXSGENTRIES];
@@ -1215,17 +1216,17 @@
 		goto startio;
 
 queue:
-	if (list_empty(queue_head))
+	if (blk_queue_empty(q))
 		goto startio;
 
 	creq = elv_next_request(q);
 	if (creq->nr_phys_segments > MAXSGENTRIES)
                 BUG();
 
-        if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR )
+        if (h->ctlr != major(creq->rq_dev)-MAJOR_NR )
         {
                 printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
-                                h->ctlr, creq->rq_dev, creq);
+                                h->ctlr, major(creq->rq_dev), creq);
                 blkdev_dequeue_request(creq);
                 complete_buffers(creq->bio, 0);
 		end_that_request_last(creq);
@@ -1243,7 +1244,7 @@
 	c->rq = creq;
 	
 	/* fill in the request */ 
-	log_unit = MINOR(creq->rq_dev) >> NWD_SHIFT; 
+	log_unit = minor(creq->rq_dev) >> NWD_SHIFT; 
 	c->Header.ReplyQueue = 0;  // unused in simple mode
 	c->Header.Tag.lower = c->busaddr;  // use the physical address the cmd block for tag
 	c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID;
@@ -1896,7 +1897,7 @@
 	cciss_geninit(i);
 	for(j=0; j<NWD; j++)
 		register_disk(&(hba[i]->gendisk),
-			MKDEV(MAJOR_NR+i, j <<4), 
+			mk_kdev(MAJOR_NR+i, j <<4), 
 			MAX_PART, &cciss_fops, 
 			hba[i]->drv[j].nr_blocks);
 
diff -urN linux-2.5.2-pre6/drivers/block/cciss_cmd.h linux/drivers/block/cciss_cmd.h
--- linux-2.5.2-pre6/drivers/block/cciss_cmd.h	Tue Nov 27 09:23:27 2001
+++ linux/drivers/block/cciss_cmd.h	Thu Jan  3 14:10:36 2002
@@ -7,7 +7,7 @@
 
 //general boundary defintions
 #define SENSEINFOBYTES          32//note that this value may vary between host implementations
-#define MAXSGENTRIES            32
+#define MAXSGENTRIES            31
 #define MAXREPLYQS              256
 
 //Command Status value
diff -urN linux-2.5.2-pre6/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- linux-2.5.2-pre6/drivers/block/cpqarray.c	Thu Jan  3 14:10:32 2002
+++ linux/drivers/block/cpqarray.c	Thu Jan  3 14:10:36 2002
@@ -499,7 +499,7 @@
 		ida_geninit(i);
 		for(j=0; j<NWD; j++)	
 			register_disk(&ida_gendisk[i], 
-				MKDEV(MAJOR_NR+i,j<<4),
+				mk_kdev(MAJOR_NR+i,j<<4),
 				16, &ida_fops, hba[i]->drv[j].nr_blks);
 
 	}
@@ -776,15 +776,15 @@
  */
 static int ida_open(struct inode *inode, struct file *filep)
 {
-	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+	int ctlr = major(inode->i_rdev) - MAJOR_NR;
+	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 	DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
 	if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
 		return -ENXIO;
 
 	if (!suser() && ida_sizes[(ctlr << CTLR_SHIFT) +
-						MINOR(inode->i_rdev)] == 0)
+						minor(inode->i_rdev)] == 0)
 		return -ENXIO;
 
 	/*
@@ -794,8 +794,8 @@
 	 * for "raw controller".
 	 */
 	if (suser()
-		&& ida_sizes[(ctlr << CTLR_SHIFT) + MINOR(inode->i_rdev)] == 0 
-		&& MINOR(inode->i_rdev) != 0)
+		&& ida_sizes[(ctlr << CTLR_SHIFT) + minor(inode->i_rdev)] == 0 
+		&& minor(inode->i_rdev) != 0)
 		return -ENXIO;
 
 	hba[ctlr]->drv[dsk].usage_count++;
@@ -808,8 +808,8 @@
  */
 static int ida_release(struct inode *inode, struct file *filep)
 {
-	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+	int ctlr = major(inode->i_rdev) - MAJOR_NR;
+	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 	DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
 
@@ -857,7 +857,6 @@
 {
 	ctlr_info_t *h = q->queuedata;
 	cmdlist_t *c;
-	struct list_head * queue_head = &q->queue_head;
 	struct request *creq;
 	struct scatterlist tmp_sg[SG_MAX];
 	int i, dir, seg;
@@ -866,17 +865,17 @@
 		goto startio;
 
 queue_next:
-	if (list_empty(queue_head))
+	if (blk_queue_empty(q))
 		goto startio;
 
 	creq = elv_next_request(q);
 	if (creq->nr_phys_segments > SG_MAX)
 		BUG();
 
-	if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
+	if (h->ctlr != major(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
 	{
 		printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
-				h->ctlr, creq->rq_dev, creq);
+				h->ctlr, minor(creq->rq_dev), creq);
 		blkdev_dequeue_request(creq);
 		complete_buffers(creq->bio, 0);
 		end_that_request_last(creq);
@@ -891,7 +890,7 @@
 	spin_unlock_irq(q->queue_lock);
 
 	c->ctlr = h->ctlr;
-	c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
+	c->hdr.unit = minor(creq->rq_dev) >> NWD_SHIFT;
 	c->hdr.size = sizeof(rblk_t) >> 2;
 	c->size += sizeof(rblk_t);
 
@@ -1109,8 +1108,8 @@
  */
 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
 {
-	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+	int ctlr = major(inode->i_rdev) - MAJOR_NR;
+	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 	int error;
 	int diskinfo[4];
 	struct hd_geometry *geo = (struct hd_geometry *)arg;
@@ -1492,8 +1491,8 @@
 	int ctlr, i;
 	unsigned long flags;
 
-	ctlr = MAJOR(dev) - MAJOR_NR;
-	if (MINOR(dev) != 0)
+	ctlr = major(dev) - MAJOR_NR;
+	if (minor(dev) != 0)
 		return -ENXIO;
 
 	spin_lock_irqsave(IDA_LOCK(ctlr), flags);
@@ -1526,9 +1525,11 @@
 	hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY);
 
 	ida_geninit(ctlr);
-	for(i=0; i<NWD; i++)
+	for(i=0; i<NWD; i++) {
+		kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
 		if (ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)])
-			revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
+			revalidate_logvol(kdev, 2);
+	}
 
 	hba[ctlr]->usage_count--;
 	return 0;
@@ -1543,7 +1544,7 @@
 	int res;
 
 	target = DEVICE_NR(dev);
-	ctlr = MAJOR(dev) - MAJOR_NR;
+	ctlr = major(dev) - MAJOR_NR;
 	gdev = &ida_gendisk[ctlr];
 	
 	spin_lock_irqsave(IDA_LOCK(ctlr), flags);
diff -urN linux-2.5.2-pre6/drivers/block/elevator.c linux/drivers/block/elevator.c
--- linux-2.5.2-pre6/drivers/block/elevator.c	Thu Jan  3 14:10:32 2002
+++ linux/drivers/block/elevator.c	Thu Jan  3 14:10:36 2002
@@ -121,45 +121,54 @@
 
 inline int elv_try_merge(struct request *__rq, struct bio *bio)
 {
-	unsigned int count = bio_sectors(bio);
 	int ret = ELEVATOR_NO_MERGE;
 
 	/*
 	 * we can merge and sequence is ok, check if it's possible
 	 */
 	if (elv_rq_merge_ok(__rq, bio)) {
-		if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
+		if (__rq->sector + __rq->nr_sectors == bio->bi_sector)
 			ret = ELEVATOR_BACK_MERGE;
-		} else if (__rq->sector - count == bio->bi_sector) {
-			__rq->elevator_sequence -= count;
+		else if (__rq->sector - bio_sectors(bio) == bio->bi_sector)
 			ret = ELEVATOR_FRONT_MERGE;
-		}
 	}
 
 	return ret;
 }
 
-int elevator_linus_merge(request_queue_t *q, struct request **req,
-			 struct bio *bio)
+inline int elv_try_last_merge(request_queue_t *q, struct request **req,
+			      struct bio *bio)
 {
-	struct list_head *entry;
-	struct request *__rq;
-	int ret;
+	int ret = ELEVATOR_NO_MERGE;
 
 	/*
 	 * give a one-shot try to merging with the last touched
 	 * request
 	 */
 	if (q->last_merge) {
-		__rq = list_entry_rq(q->last_merge);
+		struct request *__rq = list_entry_rq(q->last_merge);
 		BUG_ON(__rq->flags & REQ_STARTED);
 
-		if ((ret = elv_try_merge(__rq, bio))) {
+		if ((ret = elv_try_merge(__rq, bio)))
 			*req = __rq;
-			return ret;
-		}
 	}
 
+	return ret;
+}
+
+/*
+ * elevator_linux starts here
+ */
+int elevator_linus_merge(request_queue_t *q, struct request **req,
+			 struct bio *bio)
+{
+	struct list_head *entry;
+	struct request *__rq;
+	int ret;
+
+	if ((ret = elv_try_last_merge(q, req, bio)))
+		return ret;
+
 	entry = &q->queue_head;
 	ret = ELEVATOR_NO_MERGE;
 	while ((entry = entry->prev) != &q->queue_head) {
@@ -171,17 +180,19 @@
 		/*
 		 * simply "aging" of requests in queue
 		 */
-		if (__rq->elevator_sequence-- <= 0)
+		if (elv_linus_sequence(__rq)-- <= 0)
 			break;
 		if (!(__rq->flags & REQ_CMD))
 			continue;
-		if (__rq->elevator_sequence < bio_sectors(bio))
+		if (elv_linus_sequence(__rq) < bio_sectors(bio))
 			break;
 
 		if (!*req && bio_rq_in_between(bio, __rq, &q->queue_head))
 			*req = __rq;
 
 		if ((ret = elv_try_merge(__rq, bio))) {
+			if (ret == ELEVATOR_FRONT_MERGE)
+				elv_linus_sequence(__rq) -= bio_sectors(bio);
 			*req = __rq;
 			q->last_merge = &__rq->queuelist;
 			break;
@@ -204,19 +215,27 @@
 	while ((entry = entry->next) != &q->queue_head) {
 		struct request *tmp;
 		tmp = list_entry_rq(entry);
-		tmp->elevator_sequence -= count;
+		elv_linus_sequence(tmp) -= count;
 	}
 }
 
 void elevator_linus_merge_req(struct request *req, struct request *next)
 {
-	if (next->elevator_sequence < req->elevator_sequence)
-		req->elevator_sequence = next->elevator_sequence;
+	if (elv_linus_sequence(next) < elv_linus_sequence(req))
+		elv_linus_sequence(req) = elv_linus_sequence(next);
 }
 
-void elv_add_request_fn(request_queue_t *q, struct request *rq,
-			       struct list_head *insert_here)
+void elevator_linus_add_request(request_queue_t *q, struct request *rq,
+				struct list_head *insert_here)
 {
+	elevator_t *e = &q->elevator;
+	int lat = 0, *latency = e->elevator_data;
+
+	if (!(rq->flags & REQ_BARRIER))
+		lat = latency[rq_data_dir(rq)];
+
+	elv_linus_sequence(rq) = lat;
+
 	list_add(&rq->queuelist, insert_here);
 
 	/*
@@ -228,24 +247,29 @@
 		q->last_merge = &rq->queuelist;
 }
 
-struct request *elv_next_request_fn(request_queue_t *q)
+int elevator_linus_init(request_queue_t *q, elevator_t *e)
 {
-	if (!blk_queue_empty(q))
-		return list_entry_rq(q->queue_head.next);
+	int *latency;
 
-	return NULL;
-}
+	latency = kmalloc(2 * sizeof(int), GFP_KERNEL);
+	if (!latency)
+		return -ENOMEM;
 
-int elv_linus_init(request_queue_t *q, elevator_t *e)
-{
+	latency[READ] = 8192;
+	latency[WRITE] = 16384;
+
+	e->elevator_data = latency;
 	return 0;
 }
 
-void elv_linus_exit(request_queue_t *q, elevator_t *e)
+void elevator_linus_exit(request_queue_t *q, elevator_t *e)
 {
+	kfree(e->elevator_data);
 }
 
 /*
+ * elevator noop
+ *
  * See if we can find a request that this buffer can be coalesced with.
  */
 int elevator_noop_merge(request_queue_t *q, struct request **req,
@@ -255,15 +279,8 @@
 	struct request *__rq;
 	int ret;
 
-	if (q->last_merge) {
-		__rq = list_entry_rq(q->last_merge);
-		BUG_ON(__rq->flags & REQ_STARTED);
-
-		if ((ret = elv_try_merge(__rq, bio))) {
-			*req = __rq;
-			return ret;
-		}
-	}
+	if ((ret = elv_try_last_merge(q, req, bio)))
+		return ret;
 
 	while ((entry = entry->prev) != &q->queue_head) {
 		__rq = list_entry_rq(entry);
@@ -284,10 +301,31 @@
 	return ELEVATOR_NO_MERGE;
 }
 
-void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {}
+void elevator_noop_add_request(request_queue_t *q, struct request *rq,
+			       struct list_head *insert_here)
+{
+	list_add_tail(&rq->queuelist, &q->queue_head);
+
+	/*
+	 * new merges must not precede this barrier
+	 */
+	if (rq->flags & REQ_BARRIER)
+		q->last_merge = NULL;
+	else if (!q->last_merge)
+		q->last_merge = &rq->queuelist;
+}
+
+struct request *elevator_noop_next_request(request_queue_t *q)
+{
+	if (!blk_queue_empty(q))
+		return list_entry_rq(q->queue_head.next);
 
-void elevator_noop_merge_req(struct request *req, struct request *next) {}
+	return NULL;
+}
 
+/*
+ * general block -> elevator interface starts here
+ */
 int elevator_init(request_queue_t *q, elevator_t *e, elevator_t type)
 {
 	*e = type;
@@ -312,4 +350,77 @@
 	return 0;
 }
 
+void elv_merge_cleanup(request_queue_t *q, struct request *rq,
+		       int nr_sectors)
+{
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_merge_cleanup_fn)
+		e->elevator_merge_cleanup_fn(q, rq, nr_sectors);
+}
+
+int elv_merge(request_queue_t *q, struct request **rq, struct bio *bio)
+{
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_merge_fn)
+		return e->elevator_merge_fn(q, rq, bio);
+
+	return ELEVATOR_NO_MERGE;
+}
+
+void elv_merge_requests(request_queue_t *q, struct request *rq,
+			     struct request *next)
+{
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_merge_req_fn)
+		e->elevator_merge_req_fn(rq, next);
+}
+
+/*
+ * add_request and next_request are required to be supported, naturally
+ */
+void __elv_add_request(request_queue_t *q, struct request *rq,
+			  struct list_head *insert_here)
+{
+	q->elevator.elevator_add_req_fn(q, rq, insert_here);
+}
+
+struct request *__elv_next_request(request_queue_t *q)
+{
+	return q->elevator.elevator_next_req_fn(q);
+}
+
+void elv_remove_request(request_queue_t *q, struct request *rq)
+{
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_remove_req_fn)
+		e->elevator_remove_req_fn(q, rq);
+}
+
+elevator_t elevator_linus = {
+	elevator_merge_fn:		elevator_linus_merge,
+	elevator_merge_cleanup_fn:	elevator_linus_merge_cleanup,
+	elevator_merge_req_fn:		elevator_linus_merge_req,
+	elevator_next_req_fn:		elevator_noop_next_request,
+	elevator_add_req_fn:		elevator_linus_add_request,
+	elevator_init_fn:		elevator_linus_init,
+	elevator_exit_fn:		elevator_linus_exit,
+};
+
+elevator_t elevator_noop = {
+	elevator_merge_fn:		elevator_noop_merge,
+	elevator_next_req_fn:		elevator_noop_next_request,
+	elevator_add_req_fn:		elevator_noop_add_request,
+};
+
 module_init(elevator_global_init);
+
+EXPORT_SYMBOL(elevator_linus);
+EXPORT_SYMBOL(elevator_noop);
+
+EXPORT_SYMBOL(__elv_add_request);
+EXPORT_SYMBOL(__elv_next_request);
+EXPORT_SYMBOL(elv_remove_request);
diff -urN linux-2.5.2-pre6/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-2.5.2-pre6/drivers/block/ll_rw_blk.c	Thu Jan  3 14:10:32 2002
+++ linux/drivers/block/ll_rw_blk.c	Thu Jan  3 14:10:36 2002
@@ -530,8 +530,10 @@
 				    struct bio *bio)
 {
 	int nr_hw_segs = bio_hw_segments(q, bio);
+	int nr_phys_segs = bio_phys_segments(q, bio);
 
-	if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments) {
+	if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments
+	    || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
 		req->flags |= REQ_NOMERGE;
 		q->last_merge = NULL;
 		return 0;
@@ -542,7 +544,7 @@
 	 * counters.
 	 */
 	req->nr_hw_segments += nr_hw_segs;
-	req->nr_phys_segments += bio_phys_segments(q, bio);
+	req->nr_phys_segments += nr_phys_segs;
 	return 1;
 }
 
@@ -801,7 +803,7 @@
 	if (blk_init_free_list(q))
 		return -ENOMEM;
 
-	if ((ret = elevator_init(q, &q->elevator, ELEVATOR_LINUS))) {
+	if ((ret = elevator_init(q, &q->elevator, elevator_linus))) {
 		blk_cleanup_queue(q);
 		return ret;
 	}
@@ -822,6 +824,9 @@
 
 	blk_queue_make_request(q, __make_request);
 	blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
+
+	blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
+	blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
 	return 0;
 }
 
@@ -968,7 +973,7 @@
 	 * elevator indicated where it wants this request to be
 	 * inserted at elevator_merge time
 	 */
-	q->elevator.elevator_add_req_fn(q, req, insert_here);
+	__elv_add_request(q, req, insert_here);
 }
 
 /*
@@ -1028,7 +1033,7 @@
 	 * counts here.
 	 */
 	if (q->merge_requests_fn(q, req, next)) {
-		q->elevator.elevator_merge_req_fn(req, next);
+		elv_merge_requests(q, req, next);
 
 		blkdev_dequeue_request(next);
 
@@ -1082,9 +1087,8 @@
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
 	struct request *req, *freereq = NULL;
-	int el_ret, latency = 0, rw, nr_sectors, cur_nr_sectors, barrier;
+	int el_ret, rw, nr_sectors, cur_nr_sectors, barrier;
 	struct list_head *insert_here;
-	elevator_t *elevator = &q->elevator;
 	sector_t sector;
 
 	sector = bio->bi_sector;
@@ -1101,7 +1105,6 @@
 
 	spin_lock_prefetch(q->queue_lock);
 
-	latency = elevator_request_latency(elevator, rw);
 	barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
 
 	spin_lock_irq(q->queue_lock);
@@ -1114,14 +1117,14 @@
 		goto get_rq;
 	}
 
-	el_ret = elevator->elevator_merge_fn(q, &req, bio);
+	el_ret = elv_merge(q, &req, bio);
 	switch (el_ret) {
 		case ELEVATOR_BACK_MERGE:
 			BUG_ON(!rq_mergeable(req));
 			if (!q->back_merge_fn(q, req, bio))
 				break;
 
-			elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+			elv_merge_cleanup(q, req, nr_sectors);
 
 			req->biotail->bi_next = bio;
 			req->biotail = bio;
@@ -1135,7 +1138,7 @@
 			if (!q->front_merge_fn(q, req, bio))
 				break;
 
-			elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+			elv_merge_cleanup(q, req, nr_sectors);
 
 			bio->bi_next = req->bio;
 			req->bio = bio;
@@ -1195,11 +1198,6 @@
 		spin_lock_irq(q->queue_lock);
 		goto again;
 	}
-
-	/*
-	 * fill up the request-info, and add it to the queue
-	 */
-	req->elevator_sequence = latency;
 
 	/*
 	 * first three bits are identical in rq->flags and bio->bi_rw,
diff -urN linux-2.5.2-pre6/drivers/block/loop.c linux/drivers/block/loop.c
--- linux-2.5.2-pre6/drivers/block/loop.c	Thu Jan  3 14:10:32 2002
+++ linux/drivers/block/loop.c	Thu Jan  3 14:10:36 2002
@@ -155,8 +155,8 @@
 {
 	if (S_ISREG(lo_dentry->d_inode->i_mode))
 		return (lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS;
-	if (blk_size[MAJOR(lodev)])
-		return blk_size[MAJOR(lodev)][MINOR(lodev)] -
+	if (blk_size[major(lodev)])
+		return blk_size[major(lodev)][minor(lodev)] -
                                 (lo->lo_offset >> BLOCK_SIZE_BITS);
 	return MAX_DISK_SIZE;
 }
@@ -379,12 +379,11 @@
  */
 static int loop_end_io_transfer(struct bio *bio, int nr_sectors)
 {
-	struct loop_device *lo = &loop_dev[MINOR(bio->bi_dev)];
+	struct bio *rbh = bio->bi_private;
+	struct loop_device *lo = &loop_dev[minor(rbh->bi_dev)];
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 
 	if (!uptodate || bio_rw(bio) == WRITE) {
-		struct bio *rbh = bio->bi_private;
-
 		bio_endio(rbh, uptodate, nr_sectors);
 		if (atomic_dec_and_test(&lo->lo_pending))
 			up(&lo->lo_bh_mutex);
@@ -429,10 +428,10 @@
 	unsigned long IV;
 	int rw = bio_rw(rbh);
 
-	if (MINOR(rbh->bi_dev) >= max_loop)
+	if (minor(rbh->bi_dev) >= max_loop)
 		goto out;
 
-	lo = &loop_dev[MINOR(rbh->bi_dev)];
+	lo = &loop_dev[minor(rbh->bi_dev)];
 	spin_lock_irq(&lo->lo_lock);
 	if (lo->lo_state != Lo_bound)
 		goto inactive;
@@ -615,7 +614,7 @@
 
 	if (S_ISBLK(inode->i_mode)) {
 		lo_device = inode->i_rdev;
-		if (lo_device == dev) {
+		if (kdev_same(lo_device, dev)) {
 			error = -EBUSY;
 			goto out;
 		}
@@ -725,7 +724,7 @@
 	loop_release_xfer(lo);
 	lo->transfer = NULL;
 	lo->ioctl = NULL;
-	lo->lo_device = 0;
+	lo->lo_device = NODEV;
 	lo->lo_encrypt_type = 0;
 	lo->lo_offset = 0;
 	lo->lo_encrypt_key_size = 0;
@@ -818,12 +817,12 @@
 
 	if (!inode)
 		return -EINVAL;
-	if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+	if (major(inode->i_rdev) != MAJOR_NR) {
 		printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n",
 		       MAJOR_NR);
 		return -ENODEV;
 	}
-	dev = MINOR(inode->i_rdev);
+	dev = minor(inode->i_rdev);
 	if (dev >= max_loop)
 		return -ENODEV;
 	lo = &loop_dev[dev];
@@ -873,11 +872,11 @@
 
 	if (!inode)
 		return -EINVAL;
-	if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+	if (major(inode->i_rdev) != MAJOR_NR) {
 		printk(KERN_WARNING "lo_open: pseudo-major != %d\n", MAJOR_NR);
 		return -ENODEV;
 	}
-	dev = MINOR(inode->i_rdev);
+	dev = minor(inode->i_rdev);
 	if (dev >= max_loop)
 		return -ENODEV;
 
@@ -900,12 +899,12 @@
 
 	if (!inode)
 		return 0;
-	if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+	if (major(inode->i_rdev) != MAJOR_NR) {
 		printk(KERN_WARNING "lo_release: pseudo-major != %d\n",
 		       MAJOR_NR);
 		return 0;
 	}
-	dev = MINOR(inode->i_rdev);
+	dev = minor(inode->i_rdev);
 	if (dev >= max_loop)
 		return 0;
 
@@ -1016,7 +1015,7 @@
 	blk_size[MAJOR_NR] = loop_sizes;
 	blksize_size[MAJOR_NR] = loop_blksizes;
 	for (i = 0; i < max_loop; i++)
-		register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &lo_fops, 0);
+		register_disk(NULL, mk_kdev(MAJOR_NR, i), 1, &lo_fops, 0);
 
 	printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
 	return 0;
diff -urN linux-2.5.2-pre6/drivers/block/rd.c linux/drivers/block/rd.c
--- linux-2.5.2-pre6/drivers/block/rd.c	Thu Jan  3 14:10:32 2002
+++ linux/drivers/block/rd.c	Thu Jan  3 14:10:36 2002
@@ -246,7 +246,7 @@
 	unsigned long offset, len;
 	int rw = sbh->bi_rw;
 
-	minor = MINOR(sbh->bi_dev);
+	minor = minor(sbh->bi_dev);
 
 	if (minor >= NUM_RAMDISKS)
 		goto fail;
@@ -280,10 +280,10 @@
 	int error = -EINVAL;
 	unsigned int minor;
 
-	if (!inode || !inode->i_rdev) 	
+	if (!inode || kdev_none(inode->i_rdev))
 		goto out;
 
-	minor = MINOR(inode->i_rdev);
+	minor = minor(inode->i_rdev);
 
 	switch (cmd) {
 		case BLKFLSBUF:
@@ -407,7 +407,7 @@
 		rd_bdev[i] = NULL;
 		if (bdev)
 			blkdev_put(bdev, BDEV_FILE);
-		destroy_buffers(MKDEV(MAJOR_NR, i));
+		destroy_buffers(mk_kdev(MAJOR_NR, i));
 	}
 
 	devfs_unregister (devfs_handle);
@@ -449,7 +449,7 @@
 			       &rd_bd_op, NULL);
 
 	for (i = 0; i < NUM_RAMDISKS; i++)
-		register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
+		register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* We ought to separate initrd operations here */
diff -urN linux-2.5.2-pre6/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- linux-2.5.2-pre6/drivers/cdrom/sonycd535.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/cdrom/sonycd535.c	Thu Jan  3 14:10:36 2002
@@ -217,6 +217,8 @@
 static unsigned short read_status_reg;
 static unsigned short data_reg;
 
+static spinlock_t sonycd535_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
+
 static int initialized;			/* Has the drive been initialized? */
 static int sony_disc_changed = 1;	/* Has the disk been changed
 					   since the last check? */
@@ -815,123 +817,124 @@
 			end_request(0);
 			continue;
 		}
-		switch (CURRENT->cmd) {
-		case READ:
-			/*
-			 * If the block address is invalid or the request goes beyond the end of
-			 * the media, return an error.
-			 */
-
-			if (sony_toc->lead_out_start_lba <= (block / 4)) {
-				end_request(0);
-				return;
-			}
-			if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
-				end_request(0);
-				return;
-			}
-			while (0 < nsect) {
+		if(CURRENT->flags & REQ_CMD) {
+			switch (rq_data_dir(CURRENT)) {
+			case READ:
 				/*
-				 * If the requested sector is not currently in the read-ahead buffer,
-				 * it must be read in.
+				 * If the block address is invalid or the request goes beyond the end of
+				 * the media, return an error.
 				 */
-				if ((block < sony_first_block) || (sony_last_block < block)) {
-					sony_first_block = (block / 4) * 4;
-					log_to_msf(block / 4, params);
-
-					/*
-					 * If the full read-ahead would go beyond the end of the media, trim
-					 * it back to read just till the end of the media.
-					 */
-					if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
-						sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
-						read_size = sony_toc->lead_out_start_lba - (block / 4);
-					} else {
-						sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
-						read_size = sony_buffer_sectors;
-					}
-					size_to_buf(read_size, &params[3]);
-
+				
+				if (sony_toc->lead_out_start_lba <= (block / 4)) {
+					end_request(0);
+					return;
+				}
+				if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
+					end_request(0);
+					return;
+				}
+				while (0 < nsect) {
 					/*
-					 * Read the data.  If the drive was not spinning,
-					 * spin it up and try some more.
+					 * If the requested sector is not currently in the read-ahead buffer,
+					 * it must be read in.
 					 */
-					for (spin_up_retry=0 ;; ++spin_up_retry) {
-						/* This loop has been modified to support the Sony
-						 * CDU-510/515 series, thanks to Claudio Porfiri 
-						 * <C.Porfiri@nisms.tei.ericsson.se>.
-						 */
+					if ((block < sony_first_block) || (sony_last_block < block)) {
+						sony_first_block = (block / 4) * 4;
+						log_to_msf(block / 4, params);
+						
 						/*
-						 * This part is to deal with very slow hardware.  We
-						 * try at most MAX_SPINUP_RETRY times to read the same
-						 * block.  A check for seek_and_read_N_blocks' result is
-						 * performed; if the result is wrong, the CDROM's engine
-						 * is restarted and the operation is tried again.
+						 * If the full read-ahead would go beyond the end of the media, trim
+						 * it back to read just till the end of the media.
 						 */
+						if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
+							sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
+							read_size = sony_toc->lead_out_start_lba - (block / 4);
+						} else {
+							sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
+							read_size = sony_buffer_sectors;
+						}
+						size_to_buf(read_size, &params[3]);
+						
 						/*
-						 * 1995-06-01: The system got problems when downloading
-						 * from Slackware CDROM, the problem seems to be:
-						 * seek_and_read_N_blocks returns BAD_STATUS and we
-						 * should wait for a while before retrying, so a new
-						 * part was added to discriminate the return value from
-						 * seek_and_read_N_blocks for the various cases.
+						 * Read the data.  If the drive was not spinning,
+						 * spin it up and try some more.
 						 */
-						int readStatus = seek_and_read_N_blocks(params, read_size,
-									status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
-						if (0 <= readStatus)	/* Good data; common case, placed first */
-							break;
-						if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
-							/* give up */
-							if (readStatus == NO_ROOM)
-								printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
-							else
-								printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
-										status[0]);
-							sony_first_block = -1;
-							sony_last_block = -1;
-							end_request(0);
-							return;
-						}
-						if (readStatus == BAD_STATUS) {
-							/* Sleep for a while, then retry */
-							current->state = TASK_INTERRUPTIBLE;
-							schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
-						}
+						for (spin_up_retry=0 ;; ++spin_up_retry) {
+							/* This loop has been modified to support the Sony
+							 * CDU-510/515 series, thanks to Claudio Porfiri 
+							 * <C.Porfiri@nisms.tei.ericsson.se>.
+							 */
+							/*
+							 * This part is to deal with very slow hardware.  We
+							 * try at most MAX_SPINUP_RETRY times to read the same
+							 * block.  A check for seek_and_read_N_blocks' result is
+							 * performed; if the result is wrong, the CDROM's engine
+							 * is restarted and the operation is tried again.
+							 */
+							/*
+							 * 1995-06-01: The system got problems when downloading
+							 * from Slackware CDROM, the problem seems to be:
+							 * seek_and_read_N_blocks returns BAD_STATUS and we
+							 * should wait for a while before retrying, so a new
+							 * part was added to discriminate the return value from
+							 * seek_and_read_N_blocks for the various cases.
+							 */
+							int readStatus = seek_and_read_N_blocks(params, read_size,
+												status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
+							if (0 <= readStatus)	/* Good data; common case, placed first */
+								break;
+							if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
+								/* give up */
+								if (readStatus == NO_ROOM)
+									printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
+								else
+									printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
+									       status[0]);
+								sony_first_block = -1;
+								sony_last_block = -1;
+								end_request(0);
+								return;
+							}
+							if (readStatus == BAD_STATUS) {
+								/* Sleep for a while, then retry */
+								current->state = TASK_INTERRUPTIBLE;
+								schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
+							}
 #if DEBUG > 0
-						printk(CDU535_MESSAGE_NAME
-							" debug: calling spin up when reading data!\n");
+							printk(CDU535_MESSAGE_NAME
+							       " debug: calling spin up when reading data!\n");
 #endif
-						cmd[0] = SONY535_SPIN_UP;
-						do_sony_cmd(cmd, 1, status, NULL, 0, 0);
+							cmd[0] = SONY535_SPIN_UP;
+							do_sony_cmd(cmd, 1, status, NULL, 0, 0);
+						}
 					}
+					/*
+					 * The data is in memory now, copy it to the buffer and advance to the
+					 * next block to read.
+					 */
+					copyoff = block - sony_first_block;
+					memcpy(CURRENT->buffer,
+					       sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
+					
+					block += 1;
+					nsect -= 1;
+					CURRENT->buffer += 512;
 				}
-				/*
-				 * The data is in memory now, copy it to the buffer and advance to the
-				 * next block to read.
-				 */
-				copyoff = block - sony_first_block;
-				memcpy(CURRENT->buffer,
-					   sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-
-				block += 1;
-				nsect -= 1;
-				CURRENT->buffer += 512;
-			}
-
-			end_request(1);
-			break;
 
-		case WRITE:
-			end_request(0);
-			break;
-
-		default:
-			panic("Unknown SONY CD cmd");
+				end_request(1);
+				break;
+				
+			case WRITE:
+				end_request(0);
+				break;
+				
+			default:
+				panic("Unknown SONY CD cmd");
+			}
 		}
 	}
 }
 
-
 /*
  * Read the table of contents from the drive and set sony_toc_read if
  * successful.
@@ -1593,7 +1596,7 @@
 							MAJOR_NR, CDU535_MESSAGE_NAME);
 					return -EIO;
 				}
-				blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+				blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST, &sonycd535_lock);
 				blksize_size[MAJOR_NR] = &sonycd535_block_size;
 				read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read-ahead */
 
diff -urN linux-2.5.2-pre6/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- linux-2.5.2-pre6/drivers/char/acquirewdt.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/acquirewdt.c	Thu Jan  3 14:10:36 2002
@@ -117,7 +117,7 @@
 
 static int acq_open(struct inode *inode, struct file *file)
 {
-	switch(MINOR(inode->i_rdev))
+	switch(minor(inode->i_rdev))
 	{
 		case WATCHDOG_MINOR:
 			spin_lock(&acq_lock);
@@ -141,7 +141,7 @@
 
 static int acq_close(struct inode *inode, struct file *file)
 {
-	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 		spin_lock(&acq_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	
diff -urN linux-2.5.2-pre6/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c
--- linux-2.5.2-pre6/drivers/char/advantechwdt.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/advantechwdt.c	Thu Jan  3 14:10:36 2002
@@ -128,7 +128,7 @@
 static int
 advwdt_open(struct inode *inode, struct file *file)
 {
-	switch (MINOR(inode->i_rdev)) {
+	switch (minor(inode->i_rdev)) {
 		case WATCHDOG_MINOR:
 			spin_lock(&advwdt_lock);
 			if (advwdt_is_open) {
@@ -151,7 +151,7 @@
 static int
 advwdt_close(struct inode *inode, struct file *file)
 {
-	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&advwdt_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	
 		inb_p(WDT_STOP);
diff -urN linux-2.5.2-pre6/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- linux-2.5.2-pre6/drivers/char/busmouse.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/busmouse.c	Thu Jan  3 14:10:36 2002
@@ -51,7 +51,7 @@
 
 #define NR_MICE			15
 #define FIRST_MOUSE		0
-#define DEV_TO_MOUSE(dev)	MINOR_TO_MOUSE(MINOR(dev))
+#define DEV_TO_MOUSE(dev)	MINOR_TO_MOUSE(minor(dev))
 #define MINOR_TO_MOUSE(minor)	((minor) - FIRST_MOUSE)
 
 /*
diff -urN linux-2.5.2-pre6/drivers/char/eurotechwdt.c linux/drivers/char/eurotechwdt.c
--- linux-2.5.2-pre6/drivers/char/eurotechwdt.c	Thu Oct 25 13:53:47 2001
+++ linux/drivers/char/eurotechwdt.c	Thu Jan  3 14:10:36 2002
@@ -280,7 +280,7 @@
  
 static int eurwdt_open(struct inode *inode, struct file *file)
 {
-   switch (MINOR(inode->i_rdev)) {
+   switch (minor(inode->i_rdev)) {
       case WATCHDOG_MINOR:
          spin_lock(&eurwdt_lock);
          if (eurwdt_is_open) {
@@ -322,7 +322,7 @@
  
 static int eurwdt_release(struct inode *inode, struct file *file)
 {
-   if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+   if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
       eurwdt_disable_timer();
 #endif
diff -urN linux-2.5.2-pre6/drivers/char/ib700wdt.c linux/drivers/char/ib700wdt.c
--- linux-2.5.2-pre6/drivers/char/ib700wdt.c	Thu Oct 11 09:07:00 2001
+++ linux/drivers/char/ib700wdt.c	Thu Jan  3 14:10:36 2002
@@ -155,7 +155,7 @@
 static int
 ibwdt_open(struct inode *inode, struct file *file)
 {
-	switch (MINOR(inode->i_rdev)) {
+	switch (minor(inode->i_rdev)) {
 		case WATCHDOG_MINOR:
 			spin_lock(&ibwdt_lock);
 			if (ibwdt_is_open) {
@@ -179,7 +179,7 @@
 ibwdt_close(struct inode *inode, struct file *file)
 {
 	lock_kernel();
-	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&ibwdt_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
 		outb_p(WD_TIMO, WDT_STOP);
diff -urN linux-2.5.2-pre6/drivers/char/joystick/serport.c linux/drivers/char/joystick/serport.c
--- linux-2.5.2-pre6/drivers/char/joystick/serport.c	Wed Sep 12 15:34:06 2001
+++ linux/drivers/char/joystick/serport.c	Thu Jan  3 14:10:36 2002
@@ -149,9 +149,9 @@
 	char name[32];
 
 #ifdef CONFIG_DEVFS_FS
-	sprintf(name, tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
+	sprintf(name, tty->driver.name, minor(tty->device) - tty->driver.minor_start);
 #else
-	sprintf(name, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
+	sprintf(name, "%s%d", tty->driver.name, minor(tty->device) - tty->driver.minor_start);
 #endif
 
 	serio_register_port(&serport->serio);
diff -urN linux-2.5.2-pre6/drivers/char/lp.c linux/drivers/char/lp.c
--- linux-2.5.2-pre6/drivers/char/lp.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/lp.c	Thu Jan  3 14:10:36 2002
@@ -294,7 +294,7 @@
 static ssize_t lp_write(struct file * file, const char * buf,
 		        size_t count, loff_t *ppos)
 {
-	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
 	struct parport *port = lp_table[minor].dev->port;
 	char *kbuf = lp_table[minor].lp_buffer;
 	ssize_t retv = 0;
@@ -403,7 +403,7 @@
 static ssize_t lp_read(struct file * file, char * buf,
 		       size_t count, loff_t *ppos)
 {
-	unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
+	unsigned int minor=minor(file->f_dentry->d_inode->i_rdev);
 	struct parport *port = lp_table[minor].dev->port;
 	ssize_t retval = 0;
 	char *kbuf = lp_table[minor].lp_buffer;
@@ -430,7 +430,7 @@
 
 static int lp_open(struct inode * inode, struct file * file)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 
 	if (minor >= LP_NO)
 		return -ENXIO;
@@ -488,7 +488,7 @@
 
 static int lp_release(struct inode * inode, struct file * file)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 
 	lp_claim_parport_or_block (&lp_table[minor]);
 	parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
@@ -503,7 +503,7 @@
 static int lp_ioctl(struct inode *inode, struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	int status;
 	int retval = 0;
 
diff -urN linux-2.5.2-pre6/drivers/char/machzwd.c linux/drivers/char/machzwd.c
--- linux-2.5.2-pre6/drivers/char/machzwd.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/machzwd.c	Thu Jan  3 14:10:36 2002
@@ -378,7 +378,7 @@
 
 static int zf_open(struct inode *inode, struct file *file)
 {
-	switch(MINOR(inode->i_rdev)){
+	switch(minor(inode->i_rdev)){
 		case WATCHDOG_MINOR:
 			spin_lock(&zf_lock);
 			if(zf_is_open){
@@ -403,7 +403,7 @@
 
 static int zf_close(struct inode *inode, struct file *file)
 {
-	if(MINOR(inode->i_rdev) == WATCHDOG_MINOR){
+	if(minor(inode->i_rdev) == WATCHDOG_MINOR){
 
 		if(zf_expect_close){
 			zf_timer_off();
diff -urN linux-2.5.2-pre6/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- linux-2.5.2-pre6/drivers/char/pcwd.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/pcwd.c	Thu Jan  3 14:10:36 2002
@@ -400,7 +400,7 @@
 
 static int pcwd_open(struct inode *ino, struct file *filep)
 {
-        switch (MINOR(ino->i_rdev))
+        switch (minor(ino->i_rdev))
         {
                 case WATCHDOG_MINOR:
                     if ( !atomic_dec_and_test(&open_allowed) )
@@ -433,7 +433,7 @@
 	/*  Can't seek (pread) on this device  */
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
-	switch(MINOR(file->f_dentry->d_inode->i_rdev)) 
+	switch(minor(file->f_dentry->d_inode->i_rdev)) 
 	{
 		case TEMP_MINOR:
 			/*
@@ -453,7 +453,7 @@
 
 static int pcwd_close(struct inode *ino, struct file *filep)
 {
-	if (MINOR(ino->i_rdev)==WATCHDOG_MINOR)
+	if (minor(ino->i_rdev)==WATCHDOG_MINOR)
 	{
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
 		/*  Disable the board  */
diff -urN linux-2.5.2-pre6/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- linux-2.5.2-pre6/drivers/char/ppdev.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/ppdev.c	Thu Jan  3 14:10:36 2002
@@ -103,7 +103,7 @@
 static ssize_t pp_read (struct file * file, char * buf, size_t count,
 			loff_t * ppos)
 {
-	unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev);
+	unsigned int minor = minor (file->f_dentry->d_inode->i_rdev);
 	struct pp_struct *pp = file->private_data;
 	char * kbuffer;
 	ssize_t bytes_read = 0;
@@ -183,7 +183,7 @@
 static ssize_t pp_write (struct file * file, const char * buf, size_t count,
 			 loff_t * ppos)
 {
-	unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev);
+	unsigned int minor = minor (file->f_dentry->d_inode->i_rdev);
 	struct pp_struct *pp = file->private_data;
 	char * kbuffer;
 	ssize_t bytes_written = 0;
@@ -315,7 +315,7 @@
 static int pp_ioctl(struct inode *inode, struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct pp_struct *pp = file->private_data;
 	struct parport * port;
 
@@ -613,7 +613,7 @@
 
 static int pp_open (struct inode * inode, struct file * file)
 {
-	unsigned int minor = MINOR (inode->i_rdev);
+	unsigned int minor = minor (inode->i_rdev);
 	struct pp_struct *pp;
 
 	if (minor >= PARPORT_MAX)
@@ -642,7 +642,7 @@
 
 static int pp_release (struct inode * inode, struct file * file)
 {
-	unsigned int minor = MINOR (inode->i_rdev);
+	unsigned int minor = minor (inode->i_rdev);
 	struct pp_struct *pp = file->private_data;
 	int compat_negot;
 
diff -urN linux-2.5.2-pre6/drivers/char/sysrq.c linux/drivers/char/sysrq.c
--- linux-2.5.2-pre6/drivers/char/sysrq.c	Mon Dec 10 13:52:53 2001
+++ linux/drivers/char/sysrq.c	Thu Jan  3 14:10:36 2002
@@ -105,7 +105,7 @@
 /* Guesses if the device is a local hard drive */
 static int is_local_disk(kdev_t dev) {
 	unsigned int major;
-	major = MAJOR(dev);
+	major = major(dev);
 
 	switch (major) {
 	case IDE0_MAJOR:
@@ -206,7 +206,7 @@
 	for (sb = sb_entry(super_blocks.next);
 	     sb != sb_entry(&super_blocks); 
 	     sb = sb_entry(sb->s_list.next))
-		if (!is_local_disk(sb->s_dev) && MAJOR(sb->s_dev))
+		if (!is_local_disk(sb->s_dev) && major(sb->s_dev))
 			go_sync(sb, remount_flag);
 
 	unlock_kernel();
diff -urN linux-2.5.2-pre6/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.5.2-pre6/drivers/char/tty_io.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/char/tty_io.c	Thu Jan  3 14:10:36 2002
@@ -2006,15 +2006,11 @@
 	int idx = minor - driver->minor_start;
 	char buf[32];
 
-	switch (device) {
-		case TTY_DEV:
-		case PTMX_DEV:
+	if (IS_TTY_DEV(device) || IS_PTMX_DEV(device)) 
+		mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+	else {
+		if (driver->major == PTY_MASTER_MAJOR)
 			mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-			break;
-		default:
-			if (driver->major == PTY_MASTER_MAJOR)
-				mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-			break;
 	}
 	if ( (minor <  driver->minor_start) || 
 	     (minor >= driver->minor_start + driver->num) ) {
diff -urN linux-2.5.2-pre6/drivers/char/wdt.c linux/drivers/char/wdt.c
--- linux-2.5.2-pre6/drivers/char/wdt.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/wdt.c	Thu Jan  3 14:10:36 2002
@@ -265,7 +265,7 @@
 	if (ptr != &file->f_pos)
 		return -ESPIPE;
 
-	switch(MINOR(file->f_dentry->d_inode->i_rdev))
+	switch(minor(file->f_dentry->d_inode->i_rdev))
 	{
 		case TEMP_MINOR:
 			c*=11;
@@ -334,7 +334,7 @@
  
 static int wdt_open(struct inode *inode, struct file *file)
 {
-	switch(MINOR(inode->i_rdev))
+	switch(minor(inode->i_rdev))
 	{
 		case WATCHDOG_MINOR:
 			if(test_and_set_bit(0, &wdt_is_open))
@@ -373,7 +373,7 @@
  
 static int wdt_release(struct inode *inode, struct file *file)
 {
-	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	
 		inb_p(WDT_DC);		/* Disable counters */
diff -urN linux-2.5.2-pre6/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c
--- linux-2.5.2-pre6/drivers/char/wdt_pci.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/char/wdt_pci.c	Thu Jan  3 14:10:36 2002
@@ -281,7 +281,7 @@
 	if (ptr != &file->f_pos)
 		return -ESPIPE;
 
-	switch(MINOR(file->f_dentry->d_inode->i_rdev))
+	switch(minor(file->f_dentry->d_inode->i_rdev))
 	{
 		case TEMP_MINOR:
 			c*=11;
@@ -350,7 +350,7 @@
  
 static int wdtpci_open(struct inode *inode, struct file *file)
 {
-	switch(MINOR(inode->i_rdev))
+	switch(minor(inode->i_rdev))
 	{
 		case WATCHDOG_MINOR:
 			if( test_and_set_bit(0,&wdt_is_open) ) 
@@ -410,7 +410,7 @@
  
 static int wdtpci_release(struct inode *inode, struct file *file)
 {
-	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	
 		inb_p(WDT_DC);		/* Disable counters */
diff -urN linux-2.5.2-pre6/drivers/i2c/i2c-dev.c linux/drivers/i2c/i2c-dev.c
--- linux-2.5.2-pre6/drivers/i2c/i2c-dev.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/i2c/i2c-dev.c	Thu Jan  3 14:10:36 2002
@@ -382,7 +382,7 @@
 
 int i2cdev_open (struct inode *inode, struct file *file)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct i2c_client *client;
 
 	if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
@@ -415,7 +415,7 @@
 
 static int i2cdev_release (struct inode *inode, struct file *file)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	kfree(file->private_data);
 	file->private_data=NULL;
 #ifdef DEBUG
diff -urN linux-2.5.2-pre6/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- linux-2.5.2-pre6/drivers/ide/ide-disk.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/ide/ide-disk.c	Thu Jan  3 14:10:36 2002
@@ -30,7 +30,7 @@
  * Version 1.11		Highmem I/O support, Jens Axboe <axboe@suse.de>
  */
 
-#define IDEDISK_VERSION	"1.10"
+#define IDEDISK_VERSION	"1.11"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
@@ -70,7 +70,7 @@
 	}
 }
 
-static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
 	ide_input_data(drive, buffer, wcount);
 	if (drive->bswap)
diff -urN linux-2.5.2-pre6/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c
--- linux-2.5.2-pre6/drivers/ide/ide-probe.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/ide/ide-probe.c	Thu Jan  3 14:10:37 2002
@@ -595,17 +595,18 @@
 {
 	request_queue_t *q = &drive->queue;
 	int max_sectors;
+#ifdef CONFIG_BLK_DEV_PDC4030
+	int is_pdc4030_chipset = (HWIF(drive)->chipset == ide_pdc4030);
+#else
+	const int is_pdc4030_chipset = 0;
+#endif
 
 	q->queuedata = HWGROUP(drive);
 	blk_init_queue(q, do_ide_request, &ide_lock);
 	blk_queue_segment_boundary(q, 0xffff);
 
 	/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
-#ifdef CONFIG_BLK_DEV_PDC4030
-	max_sectors = 127;
-#else
-	max_sectors = 255;
-#endif
+	max_sectors = (is_pdc4030_chipset ? 127 : 255);
 	blk_queue_max_sectors(q, max_sectors);
 
 	/* IDE DMA can do PRD_ENTRIES number of segments. */
diff -urN linux-2.5.2-pre6/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.5.2-pre6/drivers/ide/ide.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/ide/ide.c	Thu Jan  3 14:10:37 2002
@@ -1241,12 +1241,6 @@
 		printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
 		goto kill_rq;
 	}
-#ifdef DEBUG
-	if (rq->bh && !buffer_locked(rq->bh)) {
-		printk("%s: block not locked\n", drive->name);
-		goto kill_rq;
-	}
-#endif
 	block    = rq->sector;
 
 	/* Strange disk manager remap */
diff -urN linux-2.5.2-pre6/drivers/ide/pdc4030.c linux/drivers/ide/pdc4030.c
--- linux-2.5.2-pre6/drivers/ide/pdc4030.c	Tue Jul 17 18:53:55 2001
+++ linux/drivers/ide/pdc4030.c	Thu Jan  3 14:10:37 2002
@@ -66,8 +66,10 @@
  * some technical information which has shed a glimmer of light on some of the
  * problems I was having, especially with writes. 
  *
- * There are still problems with the robustness and efficiency of this driver
- * because I still don't understand what the card is doing with interrupts.
+ * There are still potential problems with the robustness and efficiency of
+ * this driver because I still don't understand what the card is doing with
+ * interrupts, however, it has been stable for a while with no reports of ill
+ * effects.
  */
 
 #define DEBUG_READ
@@ -308,7 +310,9 @@
 	byte stat;
 	int total_remaining;
 	unsigned int sectors_left, sectors_avail, nsect;
+	unsigned long flags;
 	struct request *rq;
+	char *to;
 
 	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
 		return ide_error(drive, "promise_read_intr", stat);
@@ -330,15 +334,15 @@
 	if (nsect > sectors_avail)
 		nsect = sectors_avail;
 	sectors_avail -= nsect;
-	ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
+	to = ide_map_buffer(rq, &flags);
+	idedisk_input_data(drive, to, nsect * SECTOR_WORDS);
 #ifdef DEBUG_READ
 	printk(KERN_DEBUG "%s:  promise_read: sectors(%ld-%ld), "
 	       "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector,
-	       rq->sector+nsect-1, (unsigned long) rq->buffer,
-	       rq->nr_sectors-nsect);
+	       rq->sector+nsect-1, (unsigned long) to, rq->nr_sectors-nsect);
 #endif
+	ide_unmap_buffer(to, &flags);
 	rq->sector += nsect;
-	rq->buffer += nsect<<9;
 	rq->errors = 0;
 	rq->nr_sectors -= nsect;
 	total_remaining = rq->nr_sectors;
@@ -406,10 +410,7 @@
 #ifdef DEBUG_WRITE
 	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
 #endif
-	for (i = rq->nr_sectors; i > 0; ) {
-		i -= rq->current_nr_sectors;
-		ide_end_request(1, hwgroup);
-	}
+	__ide_end_request(hwgroup, 1, rq->nr_sectors);
 	return ide_stopped;
 }
 
@@ -498,7 +499,15 @@
 	unsigned long timeout;
 	byte stat;
 
-	if (rq->cmd == READ) {
+/* Check that it's a regular command. If not, bomb out early. */
+	if (!(rq->flags & REQ_CMD)) {
+		blk_dump_rq_flags(rq, "pdc4030 bad flags");
+		ide_end_request(0, HWGROUP(drive));
+		return ide_stopped;
+	}
+
+	switch (rq_data_dir(rq)) {
+	case READ:
 		OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
 /*
  * The card's behaviour is odd at this point. If the data is
@@ -531,9 +540,18 @@
 		printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n",
 			drive->name);
 		return ide_stopped;
-	} else if (rq->cmd == WRITE) {
+		break;
+
+	case WRITE:
 		ide_startstop_t startstop;
 		OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
+/*
+ * Strategy on write is:
+ *	look for the DRQ that should have been immediately asserted
+ *	copy the request into the hwgroup's scratchpad
+ *	call the promise_write function to deal with writing the data out
+ * NOTE: No interrupts are generated on writes. Write completion must be polled
+ */
 		if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
 			printk(KERN_ERR "%s: no DRQ after issuing "
 			       "PROMISE_WRITE\n", drive->name);
@@ -543,11 +561,11 @@
 			__cli();	/* local CPU only */
 		HWGROUP(drive)->wrq = *rq; /* scratchpad */
 		return promise_write(drive);
+		break;
 
-	} else {
-		printk("KERN_WARNING %s: bad command: %d\n",
-		       drive->name, rq->cmd);
+	default:
+		printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n");
 		ide_end_request(0, HWGROUP(drive));
-		return ide_stopped;
+		break;
 	}
 }
diff -urN linux-2.5.2-pre6/drivers/input/evdev.c linux/drivers/input/evdev.c
--- linux-2.5.2-pre6/drivers/input/evdev.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/input/evdev.c	Thu Jan  3 14:10:37 2002
@@ -119,7 +119,7 @@
 static int evdev_open(struct inode * inode, struct file * file)
 {
 	struct evdev_list *list;
-	int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE;
+	int i = minor(inode->i_rdev) - EVDEV_MINOR_BASE;
 
 	if (i >= EVDEV_MINORS || !evdev_table[i])
 		return -ENODEV;
diff -urN linux-2.5.2-pre6/drivers/input/input.c linux/drivers/input/input.c
--- linux-2.5.2-pre6/drivers/input/input.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/input/input.c	Thu Jan  3 14:10:37 2002
@@ -368,7 +368,7 @@
 
 static int input_open_file(struct inode *inode, struct file *file)
 {
-	struct input_handler *handler = input_table[MINOR(inode->i_rdev) >> 5];
+	struct input_handler *handler = input_table[minor(inode->i_rdev) >> 5];
 	struct file_operations *old_fops, *new_fops = NULL;
 	int err;
 
diff -urN linux-2.5.2-pre6/drivers/input/joydev.c linux/drivers/input/joydev.c
--- linux-2.5.2-pre6/drivers/input/joydev.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/input/joydev.c	Thu Jan  3 14:10:37 2002
@@ -189,7 +189,7 @@
 static int joydev_open(struct inode *inode, struct file *file)
 {
 	struct joydev_list *list;
-	int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE;
+	int i = minor(inode->i_rdev) - JOYDEV_MINOR_BASE;
 
 	if (i >= JOYDEV_MINORS || !joydev_table[i])
 		return -ENODEV;
diff -urN linux-2.5.2-pre6/drivers/input/mousedev.c linux/drivers/input/mousedev.c
--- linux-2.5.2-pre6/drivers/input/mousedev.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/input/mousedev.c	Thu Jan  3 14:10:37 2002
@@ -214,7 +214,7 @@
 static int mousedev_open(struct inode * inode, struct file * file)
 {
 	struct mousedev_list *list;
-	int i = MINOR(inode->i_rdev) - MOUSEDEV_MINOR_BASE;
+	int i = minor(inode->i_rdev) - MOUSEDEV_MINOR_BASE;
 
 	if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
 		return -ENODEV;
diff -urN linux-2.5.2-pre6/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- linux-2.5.2-pre6/drivers/isdn/Config.in	Fri Nov 30 09:48:32 2001
+++ linux/drivers/isdn/Config.in	Thu Jan  3 14:10:37 2002
@@ -42,6 +42,7 @@
    fi
    bool '  HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
    bool '  HiSax Support for US NI1' CONFIG_HISAX_NI1
+   int  '  Maximum number of cards supported by HiSax' CONFIG_HISAX_MAX_CARDS 8
    comment '  HiSax supported cards'
    bool '  Teles 16.0/8.0' CONFIG_HISAX_16_0
    bool '  Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
@@ -81,7 +82,7 @@
    dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
    dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
    dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
-   dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
+   dep_tristate 'AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
 fi
 endmenu
 
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/avmcard.h linux/drivers/isdn/avmb1/avmcard.h
--- linux-2.5.2-pre6/drivers/isdn/avmb1/avmcard.h	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/avmcard.h	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: avmcard.h,v 1.8.6.4 2001/09/23 22:24:33 kai Exp $
+/* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  *
  * Copyright 1999 by Carsten Paeth <calle@calle.de>
  *
@@ -39,13 +39,21 @@
 	avm_c2
 };
 
+typedef struct avmcard_dmabuf {
+    long        size;
+    __u8       *dmabuf;
+    dma_addr_t  dmaaddr;
+} avmcard_dmabuf;
+
 typedef struct avmcard_dmainfo {
-	__u32 recvlen;   
-	__u8  recvbuf[128+2048];
-	struct sk_buff_head send_queue;
-	__u8  sendbuf[128+2048];
-} avmcard_dmainfo;
+	__u32                recvlen;
+        avmcard_dmabuf       recvbuf;
+
+        avmcard_dmabuf       sendbuf;
+	struct sk_buff_head  send_queue;
 
+	struct pci_dev      *pcidev;
+} avmcard_dmainfo;
 
 typedef struct avmcard {
 	char name[32];
@@ -543,6 +551,11 @@
 
 int b1ctl_read_proc(char *page, char **start, off_t off,
         		int count, int *eof, struct capi_ctr *ctrl);
+
+avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *,
+				   long rsize, long ssize);
+void avmcard_dma_free(avmcard_dmainfo *);
+
 
 /* b1dma.c */
 int b1pciv4_detect(avmcard *card);
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c
--- linux-2.5.2-pre6/drivers/isdn/avmb1/b1.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/b1.c	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: b1.c,v 1.20.6.7 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Common module for AVM B1 cards.
  * 
@@ -11,6 +11,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/pci.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
@@ -27,7 +28,7 @@
 #include "capicmd.h"
 #include "capiutil.h"
 
-static char *revision = "$Revision: 1.20.6.7 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 /* ------------------------------------------------------------- */
 
@@ -638,6 +639,65 @@
 }
 
 /* ------------------------------------------------------------- */
+
+#ifdef CONFIG_PCI
+
+avmcard_dmainfo *
+avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
+{
+	avmcard_dmainfo *p;
+	void *buf;
+
+	p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
+	if (!p) {
+		printk(KERN_WARNING "%s: no memory.\n", name);
+		goto err;
+	}
+	memset(p, 0, sizeof(avmcard_dmainfo));
+
+	p->recvbuf.size = rsize;
+	buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
+	if (!buf) {
+		printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name);
+		goto err_kfree;
+	}
+	p->recvbuf.dmabuf = buf;
+
+	p->sendbuf.size = ssize;
+	buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr);
+	if (!buf) {
+		printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name);
+		goto err_free_consistent;
+	}
+
+	p->sendbuf.dmabuf = buf;
+	skb_queue_head_init(&p->send_queue);
+
+	return p;
+
+ err_free_consistent:
+	pci_free_consistent(p->pcidev, p->recvbuf.size,
+			    p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
+ err_kfree:
+	kfree(p);
+ err:
+	return 0;
+}
+
+void avmcard_dma_free(avmcard_dmainfo *p)
+{
+	pci_free_consistent(p->pcidev, p->recvbuf.size,
+			    p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
+	pci_free_consistent(p->pcidev, p->sendbuf.size,
+			    p->sendbuf.dmabuf, p->sendbuf.dmaaddr);
+	skb_queue_purge(&p->send_queue);
+	kfree(p);
+}
+
+EXPORT_SYMBOL(avmcard_dma_alloc);
+EXPORT_SYMBOL(avmcard_dma_free);
+
+#endif
 
 EXPORT_SYMBOL(b1_irq_table);
 
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c
--- linux-2.5.2-pre6/drivers/isdn/avmb1/b1dma.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/b1dma.c	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: b1dma.c,v 1.11.6.8 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1dma.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Common module for AVM B1 cards that support dma with AMCC
  * 
@@ -32,7 +32,7 @@
 #error FIXME: driver requires 32-bit platform
 #endif
 
-static char *revision = "$Revision: 1.11.6.8 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 /* ------------------------------------------------------------- */
 
@@ -388,7 +388,7 @@
 		cmd = CAPIMSG_COMMAND(skb->data);
 		subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 
-		p = dma->sendbuf;
+		p = dma->sendbuf.dmabuf;
 
 		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
 			__u16 dlen = CAPIMSG_DATALEN(skb->data);
@@ -399,7 +399,7 @@
 			_put_byte(&p, SEND_MESSAGE);
 			_put_slice(&p, skb->data, len);
 		}
-		txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+		txlen = (__u8 *)p - (__u8 *)dma->sendbuf.dmabuf;
 #ifdef CONFIG_B1DMA_DEBUG
 		printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
 				inint, txlen);
@@ -414,11 +414,11 @@
 		printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
 				inint, skb->data[2], txlen);
 #endif
-		memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+		memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
 	}
 	txlen = (txlen + 3) & ~3;
 
-	b1dmaoutmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
+	b1dmaoutmeml(card->mbase+AMCC_TXPTR, dma->sendbuf.dmaaddr);
 	b1dmaoutmeml(card->mbase+AMCC_TXLEN, txlen);
 
 	card->csr |= EN_TX_TC_INT;
@@ -461,7 +461,7 @@
 	avmcard_dmainfo *dma = card->dma;
 	struct capi_ctr *ctrl = cinfo->capi_ctrl;
 	struct sk_buff *skb;
-	void *p = dma->recvbuf+4;
+	void *p = dma->recvbuf.dmabuf+4;
 	__u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
 	__u8 b1cmd =  _get_byte(&p);
 
@@ -597,18 +597,19 @@
 	b1dmaoutmeml(card->mbase+AMCC_INTCSR, newcsr);
 
 	if ((status & RX_TC_INT) != 0) {
-		__u8 *recvbuf = card->dma->recvbuf;
+		struct avmcard_dmainfo *dma = card->dma;
 		__u32 rxlen;
 	   	if (card->dma->recvlen == 0) {
-			card->dma->recvlen = *((__u32 *)recvbuf);
-			rxlen = (card->dma->recvlen + 3) & ~3;
+			dma->recvlen = *((__u32 *)dma->recvbuf.dmabuf);
+			rxlen = (dma->recvlen + 3) & ~3;
 			b1dmaoutmeml(card->mbase+AMCC_RXPTR,
-					virt_to_phys(recvbuf+4));
+					dma->recvbuf.dmaaddr+4);
 			b1dmaoutmeml(card->mbase+AMCC_RXLEN, rxlen);
 		} else {
 			b1dma_handle_rx(card);
-	   		card->dma->recvlen = 0;
-			b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf));
+	   		dma->recvlen = 0;
+			b1dmaoutmeml(card->mbase+AMCC_RXPTR,
+					dma->recvbuf.dmaaddr);
 			b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
 		}
 	}
@@ -744,7 +745,7 @@
 	t1outp(card->port, 0x10, 0xF0);
 
 	card->dma->recvlen = 0;
-	b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf));
+	b1dmaoutmeml(card->mbase+AMCC_RXPTR, card->dma->recvbuf.dmaaddr);
 	b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
 	card->csr |= EN_RX_TC_INT;
 	b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
@@ -855,7 +856,7 @@
 	__u8 flag;
 	int len = 0;
 	char *s;
-	__u32 txaddr, txlen, rxaddr, rxlen, csr;
+	__u32 txoff, txlen, rxoff, rxlen, csr;
 
 	len += sprintf(page+len, "%-16s %s\n", "name", card->name);
 	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
@@ -911,13 +912,11 @@
 	save_flags(flags);
 	cli();
 
-	txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
-	txaddr -= (__u32)card->dma->sendbuf;
-	txlen  = b1dmainmeml(card->mbase+0x30);
-
-	rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24));
-	rxaddr -= (__u32)card->dma->recvbuf;
-	rxlen  = b1dmainmeml(card->mbase+0x28);
+	txoff = (dma_addr_t)b1dmainmeml(card->mbase+0x2c)-card->dma->sendbuf.dmaaddr;
+	txlen = b1dmainmeml(card->mbase+0x30);
+
+	rxoff = (dma_addr_t)b1dmainmeml(card->mbase+0x24)-card->dma->recvbuf.dmaaddr;
+	rxlen = b1dmainmeml(card->mbase+0x28);
 
 	csr  = b1dmainmeml(card->mbase+AMCC_INTCSR);
 
@@ -928,11 +927,11 @@
         len += sprintf(page+len, "%-16s 0x%lx\n",
 				"csr", (unsigned long)csr);
         len += sprintf(page+len, "%-16s %lu\n",
-				"txoff", (unsigned long)txaddr);
+				"txoff", (unsigned long)txoff);
         len += sprintf(page+len, "%-16s %lu\n",
 				"txlen", (unsigned long)txlen);
         len += sprintf(page+len, "%-16s %lu\n",
-				"rxoff", (unsigned long)rxaddr);
+				"rxoff", (unsigned long)rxoff);
         len += sprintf(page+len, "%-16s %lu\n",
 				"rxlen", (unsigned long)rxlen);
 
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c
--- linux-2.5.2-pre6/drivers/isdn/avmb1/b1pci.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/b1pci.c	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: b1pci.c,v 1.29.6.5 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Module for AVM B1 PCI-card.
  * 
@@ -26,7 +26,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.29.6.5 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 /* ------------------------------------------------------------- */
 
@@ -108,7 +108,9 @@
 
 /* ------------------------------------------------------------- */
 
-static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int b1pci_add_card(struct capi_driver *driver,
+                          struct capicardparams *p,
+			  struct pci_dev *dev)
 {
 	avmcard *card;
 	avmctrl_info *cinfo;
@@ -237,7 +239,7 @@
 	release_region(card->port, AVMB1_PORTLEN);
 	ctrl->driverdata = 0;
 	kfree(card->ctrlinfo);
-	kfree(card->dma);
+        avmcard_dma_free(card->dma);
 	kfree(card);
 
 	MOD_DEC_USE_COUNT;
@@ -262,7 +264,9 @@
 
 /* ------------------------------------------------------------- */
 
-static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int b1pciv4_add_card(struct capi_driver *driver,
+                            struct capicardparams *p,
+			    struct pci_dev *dev)
 {
 	avmcard *card;
 	avmctrl_info *cinfo;
@@ -278,18 +282,17 @@
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
-	card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+        card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
 	if (!card->dma) {
-		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		printk(KERN_WARNING "%s: dma alloc.\n", driver->name);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
-	memset(card->dma, 0, sizeof(avmcard_dmainfo));
         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
 	if (!cinfo) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
@@ -308,7 +311,7 @@
 		       "%s: ports 0x%03x-0x%03x in use.\n",
 		       driver->name, card->port, card->port + AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
@@ -319,7 +322,7 @@
 		printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
 					driver->name, card->membase);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EIO;
@@ -332,7 +335,7 @@
 					driver->name, card->port, retval);
                 iounmap(card->mbase);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EIO;
@@ -349,7 +352,7 @@
                 iounmap(card->mbase);
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
@@ -362,15 +365,13 @@
 		free_irq(card->irq, card);
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 	card->cardnr = cinfo->capi_ctrl->cnr;
 
-	skb_queue_head_init(&card->dma->send_queue);
-
 	printk(KERN_INFO
 		"%s: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
 		driver->name, card->port, card->irq,
@@ -429,9 +430,9 @@
 		"%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
 		driver->name, param.port, param.irq, param.membase);
 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
-		retval = b1pciv4_add_card(driver, &param);
+		retval = b1pciv4_add_card(driver, &param, dev);
 #else
-		retval = b1pci_add_card(driver, &param);
+		retval = b1pci_add_card(driver, &param, dev);
 #endif
 		if (retval != 0) {
 		        printk(KERN_ERR
@@ -445,7 +446,7 @@
 		printk(KERN_INFO
 		"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
 		driver->name, param.port, param.irq);
-		retval = b1pci_add_card(driver, &param);
+		retval = b1pci_add_card(driver, &param, dev);
 		if (retval != 0) {
 		        printk(KERN_ERR
 			"%s: no AVM-B1 at i/o %#x, irq %d detected\n",
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c
--- linux-2.5.2-pre6/drivers/isdn/avmb1/c4.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/c4.c	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: c4.c,v 1.20.6.11 2001/09/23 22:24:33 kai Exp $
+/* $Id: c4.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Module for AVM C4 & C2 card.
  * 
@@ -29,7 +29,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.20.6.11 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 #undef CONFIG_C4_DEBUG
 #undef CONFIG_C4_POLLDEBUG
@@ -439,7 +439,7 @@
 		cmd = CAPIMSG_COMMAND(skb->data);
 		subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 
-		p = dma->sendbuf;
+		p = dma->sendbuf.dmabuf;
 
 		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
 			__u16 dlen = CAPIMSG_DATALEN(skb->data);
@@ -450,7 +450,7 @@
 			_put_byte(&p, SEND_MESSAGE);
 			_put_slice(&p, skb->data, len);
 		}
-		txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+		txlen = (__u8 *)p - (__u8 *)dma->sendbuf.dmabuf;
 #ifdef CONFIG_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
 #endif
@@ -464,11 +464,11 @@
 		printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
 				card->name, skb->data[2], txlen);
 #endif
-		memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+		memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
 	}
 	txlen = (txlen + 3) & ~3;
 
-	c4outmeml(card->mbase+MBOX_DOWN_ADDR, virt_to_phys(dma->sendbuf));
+	c4outmeml(card->mbase+MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr);
 	c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);
 
 	card->csr |= DBELL_DOWN_ARM;
@@ -510,7 +510,7 @@
 	struct capi_ctr *ctrl;
 	avmctrl_info *cinfo;
 	struct sk_buff *skb;
-	void *p = dma->recvbuf;
+	void *p = dma->recvbuf.dmabuf;
 	__u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
 	__u8 b1cmd =  _get_byte(&p);
 	__u32 cidx;
@@ -702,7 +702,7 @@
 		c4outmeml(card->mbase+MBOX_UP_LEN, 0);
 		c4_handle_rx(card);
 		card->dma->recvlen = 0;
-		c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+		c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
 		c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
 	}
 
@@ -885,8 +885,8 @@
 	c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08);
 
 	card->dma->recvlen = 0;
-	c4outmeml(card->mbase+MBOX_UP_ADDR, virt_to_phys(card->dma->recvbuf));
-	c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+	c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr);
+	c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
 	c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
 	restore_flags(flags);
 
@@ -944,7 +944,7 @@
 	release_region(card->port, AVMB1_PORTLEN);
 	ctrl->driverdata = 0;
 	kfree(card->ctrlinfo);
-	kfree(card->dma);
+        avmcard_dma_free(card->dma);
 	kfree(card);
 
 	MOD_DEC_USE_COUNT;
@@ -1123,6 +1123,7 @@
 
 static int c4_add_card(struct capi_driver *driver,
 		       struct capicardparams *p,
+                       struct pci_dev *dev,
 		       int nr)
 {
 	avmctrl_info *cinfo;
@@ -1140,18 +1141,17 @@
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
-	card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+        card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
 	if (!card->dma) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
-	memset(card->dma, 0, sizeof(avmcard_dmainfo));
         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC);
 	if (!cinfo) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
@@ -1173,7 +1173,7 @@
 		       "%s: ports 0x%03x-0x%03x in use.\n",
 		       driver->name, card->port, card->port + AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
@@ -1184,7 +1184,7 @@
 		printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
 					driver->name, card->membase);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EIO;
@@ -1195,7 +1195,7 @@
 					driver->name, card->port, retval);
                 iounmap(card->mbase);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EIO;
@@ -1211,7 +1211,7 @@
                 iounmap(card->mbase);
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+                avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
@@ -1231,7 +1231,7 @@
                 	iounmap(card->mbase);
 			free_irq(card->irq, card);
 			release_region(card->port, AVMB1_PORTLEN);
-	        	kfree(card->dma);
+                        avmcard_dma_free(card->dma);
 	        	kfree(card->ctrlinfo);
 			kfree(card);
 	        	MOD_DEC_USE_COUNT;
@@ -1241,8 +1241,6 @@
 			card->cardnr = cinfo->capi_ctrl->cnr;
 	}
 
-	skb_queue_head_init(&card->dma->send_queue);
-
 	printk(KERN_INFO
 		"%s: AVM C%d at i/o %#x, irq %d, mem %#lx\n",
 		driver->name, nr, card->port, card->irq, card->membase);
@@ -1335,7 +1333,7 @@
 		printk(KERN_INFO
 			"%s: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
 			driver->name, nr, param.port, param.irq, param.membase);
-		retval = c4_add_card(driver, &param, nr);
+		retval = c4_add_card(driver, &param, dev, nr);
 		if (retval != 0) {
 		        printk(KERN_ERR
 			"%s: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- linux-2.5.2-pre6/drivers/isdn/avmb1/capi.c	Thu Dec  6 14:01:17 2001
+++ linux/drivers/isdn/avmb1/capi.c	Thu Jan  3 14:10:37 2002
@@ -129,11 +129,9 @@
 };
 
 struct capidev {
-	struct capidev *next;
-	struct file    *file;
+	struct list_head list;
 	u16		applid;
 	u16		errcode;
-	unsigned int    minor;
 	unsigned        userflags;
 
 	struct sk_buff_head recvqueue;
@@ -150,17 +148,18 @@
 
 /* -------- global variables ---------------------------------------- */
 
-static struct capi_interface *capifuncs = 0;
-static struct capidev *capidev_openlist = 0;
+static struct capi_interface *capifuncs;
+static rwlock_t capidev_list_lock;
+static LIST_HEAD(capidev_list);
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-static struct capiminor *minors = 0;
+static struct capiminor *minors;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
-static kmem_cache_t *capidev_cachep = 0;
-static kmem_cache_t *capincci_cachep = 0;
+static kmem_cache_t *capidev_cachep;
+static kmem_cache_t *capincci_cachep;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-static kmem_cache_t *capiminor_cachep = 0;
-static kmem_cache_t *capidh_cachep = 0;
+static kmem_cache_t *capiminor_cachep;
+static kmem_cache_t *capidh_cachep;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -318,9 +317,9 @@
 		printk(KERN_DEBUG "set mp->nccip\n");
 #endif
 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
-		kdev = MKDEV(capi_rawmajor, mp->minor);
+		kdev = mk_kdev(capi_rawmajor, mp->minor);
 		capifs_new_ncci('r', mp->minor, kdev);
-		kdev = MKDEV(capi_ttymajor, mp->minor);
+		kdev = mk_kdev(capi_ttymajor, mp->minor);
 		capifs_new_ncci(0, mp->minor, kdev);
 #endif
 	}
@@ -391,48 +390,52 @@
 static struct capidev *capidev_alloc(struct file *file)
 {
 	struct capidev *cdev;
-	struct capidev **pp;
+	unsigned long flags;
 
 	cdev = (struct capidev *)kmem_cache_alloc(capidev_cachep, GFP_KERNEL);
 	if (!cdev)
 		return 0;
 	memset(cdev, 0, sizeof(struct capidev));
-	cdev->file = file;
-	cdev->minor = MINOR(file->f_dentry->d_inode->i_rdev);
 
 	skb_queue_head_init(&cdev->recvqueue);
 	init_waitqueue_head(&cdev->recvwait);
-	pp=&capidev_openlist;
-	while (*pp) pp = &(*pp)->next;
-	*pp = cdev;
+	write_lock_irqsave(&capidev_list_lock, flags);
+	list_add_tail(&cdev->list, &capidev_list);
+	write_unlock_irqrestore(&capidev_list_lock, flags);
         return cdev;
 }
 
 static void capidev_free(struct capidev *cdev)
 {
-	struct capidev **pp;
+	unsigned long flags;
 
 	if (cdev->applid)
 		(*capifuncs->capi_release) (cdev->applid);
 	cdev->applid = 0;
-
 	skb_queue_purge(&cdev->recvqueue);
-	
-	pp=&capidev_openlist;
-	while (*pp && *pp != cdev) pp = &(*pp)->next;
-	if (*pp)
-		*pp = cdev->next;
-
+	write_lock_irqsave(&capidev_list_lock, flags);
+	list_del(&cdev->list);
+	write_unlock_irqrestore(&capidev_list_lock, flags);
 	kmem_cache_free(capidev_cachep, cdev);
 }
 
 static struct capidev *capidev_find(u16 applid)
 {
-	struct capidev *p;
-	for (p=capidev_openlist; p; p = p->next) {
+	// FIXME this doesn't guarantee that the device won't go away shortly
+	struct list_head *l;
+	struct capidev *p = NULL;
+
+	read_lock(&capidev_list_lock);
+	list_for_each(l, &capidev_list) {
+		p = list_entry(l, struct capidev, list);
 		if (p->applid == applid)
 			break;
 	}
+	read_unlock(&capidev_list_lock);
+	
+	if (l == &capidev_list)
+		return NULL;
+	
 	return p;
 }
 
@@ -1088,7 +1091,7 @@
 
 	if (file->private_data)
 		return -EEXIST;
-	if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
+	if ((mp = capiminor_find(minor(file->f_dentry->d_inode->i_rdev))) == 0)
 		return -ENXIO;
 	if (mp->nccip == 0)
 		return -ENXIO;
@@ -1272,7 +1275,7 @@
 {
 	struct capiminor *mp;
 
-	if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
+	if ((mp = capiminor_find(minor(file->f_dentry->d_inode->i_rdev))) == 0)
 		return -ENXIO;
 	if (mp->nccip == 0)
 		return -ENXIO;
@@ -1662,11 +1665,13 @@
                                        int count, int *eof, void *data)
 {
         struct capidev *cdev;
+	struct list_head *l;
 	int len = 0;
 
-	for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
-		len += sprintf(page+len, "%d %d %lu %lu %lu %lu\n",
-			cdev->minor,
+	read_lock(&capidev_list_lock);
+	list_for_each(l, &capidev_list) {
+		cdev = list_entry(l, struct capidev, list);
+		len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n",
 			cdev->applid,
 			cdev->nrecvctlpkt,
 			cdev->nrecvdatapkt,
@@ -1680,11 +1685,13 @@
 				goto endloop;
 		}
 	}
+
 endloop:
+	read_unlock(&capidev_list_lock);
 	if (len < count)
 		*eof = 1;
-	if (len>count) len = count;
-	if (len<0) len = 0;
+	if (len > count) len = count;
+	if (len < 0) len = 0;
 	return len;
 }
 
@@ -1697,9 +1704,12 @@
 {
         struct capidev *cdev;
         struct capincci *np;
+	struct list_head *l;
 	int len = 0;
 
-	for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
+	read_lock(&capidev_list_lock);
+	list_for_each(l, &capidev_list) {
+		cdev = list_entry(l, struct capidev, list);
 		for (np=cdev->nccis; np; np = np->next) {
 			len += sprintf(page+len, "%d 0x%x%s\n",
 				cdev->applid,
@@ -1719,6 +1729,7 @@
 		}
 	}
 endloop:
+	read_unlock(&capidev_list_lock);
 	*start = page+off;
 	if (len < count)
 		*eof = 1;
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/capifs.c linux/drivers/isdn/avmb1/capifs.c
--- linux-2.5.2-pre6/drivers/isdn/avmb1/capifs.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/capifs.c	Thu Jan  3 14:10:37 2002
@@ -430,7 +430,7 @@
 			inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
 			inode->i_nlink = 1;
 			inode->i_ino = ino + 2;
-			init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
+			init_special_inode(inode, sbi->mode|S_IFCHR, kdev_t_to_nr(np->kdev));
 		}
 	}
 }
diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c
--- linux-2.5.2-pre6/drivers/isdn/avmb1/t1pci.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/t1pci.c	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: t1pci.c,v 1.13.6.6 2001/09/23 22:24:34 kai Exp $
+/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Module for AVM T1 PCI-card.
  * 
@@ -26,7 +26,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.13.6.6 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 #undef CONFIG_T1PCI_DEBUG
 #undef CONFIG_T1PCI_POLLDEBUG
@@ -62,7 +62,7 @@
 	release_region(card->port, AVMB1_PORTLEN);
 	ctrl->driverdata = 0;
 	kfree(card->ctrlinfo);
-	kfree(card->dma);
+	avmcard_dma_free(card->dma);
 	kfree(card);
 
 	MOD_DEC_USE_COUNT;
@@ -70,7 +70,9 @@
 
 /* ------------------------------------------------------------- */
 
-static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int t1pci_add_card(struct capi_driver *driver,
+                          struct capicardparams *p,
+	                  struct pci_dev *dev)
 {
 	avmcard *card;
 	avmctrl_info *cinfo;
@@ -86,18 +88,17 @@
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
-	card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+        card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
 	if (!card->dma) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
-	memset(card->dma, 0, sizeof(avmcard_dmainfo));
         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
 	if (!cinfo) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
-		kfree(card->dma);
+		avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
@@ -116,7 +117,7 @@
 		       "%s: ports 0x%03x-0x%03x in use.\n",
 		       driver->name, card->port, card->port + AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+		avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
@@ -127,7 +128,7 @@
 		printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
 					driver->name, card->membase);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+		avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EIO;
@@ -144,7 +145,7 @@
 					driver->name, card->port, retval);
                 iounmap(card->mbase);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+		avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EIO;
@@ -160,7 +161,7 @@
                 iounmap(card->mbase);
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+		avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
@@ -173,15 +174,13 @@
 		free_irq(card->irq, card);
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
-		kfree(card->dma);
+		avmcard_dma_free(card->dma);
 		kfree(card);
 	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 	card->cardnr = cinfo->capi_ctrl->cnr;
 
-	skb_queue_head_init(&card->dma->send_queue);
-
 	printk(KERN_INFO
 		"%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
 		driver->name, card->port, card->irq, card->membase);
@@ -271,7 +270,7 @@
 		printk(KERN_INFO
 			"%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
 			driver->name, param.port, param.irq, param.membase);
-		retval = t1pci_add_card(driver, &param);
+		retval = t1pci_add_card(driver, &param, dev);
 		if (retval != 0) {
 		        printk(KERN_ERR
 			"%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
diff -urN linux-2.5.2-pre6/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile
--- linux-2.5.2-pre6/drivers/isdn/hisax/Makefile	Fri Nov 30 09:48:32 2001
+++ linux/drivers/isdn/hisax/Makefile	Thu Jan  3 14:10:37 2002
@@ -4,6 +4,10 @@
 
 O_TARGET	  := vmlinux-obj.o
 
+# Define maximum number of cards
+
+EXTRA_CFLAGS      += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+
 # Objects that export symbols.
 
 export-objs	  := config.o fsm.o hisax_isac.o
diff -urN linux-2.5.2-pre6/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- linux-2.5.2-pre6/drivers/isdn/hisax/config.c	Fri Nov 30 09:48:32 2001
+++ linux/drivers/isdn/hisax/config.c	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 2.57.6.20 2001/09/23 22:24:47 kai Exp $
+/* $Id: config.c,v 1.1.4.2.2.1 2001/12/09 20:18:40 kai Exp $
  *
  * Author       Karsten Keil
  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
@@ -336,27 +336,19 @@
 	NULL, \
 }
 
-#define EMPTY_CARD	{0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
-
-struct IsdnCard cards[] = {
+struct IsdnCard cards[HISAX_MAX_CARDS] = {
 	FIRST_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
 };
 
-static char HiSaxID[64] __devinitdata = { 0, };
+#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
+static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, };
 
 char *HiSax_id __devinitdata = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
-static int type[8] __devinitdata = { 0, };
-static int protocol[8] __devinitdata = { 0, };
-static int io[8] __devinitdata = { 0, };
+static int type[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int io[HISAX_MAX_CARDS] __devinitdata = { 0, };
 #undef IO0_IO1
 #ifdef CONFIG_HISAX_16_3
 #define IO0_IO1
@@ -366,25 +358,27 @@
 #define IO0_IO1
 #endif
 #ifdef IO0_IO1
-static int io0[8] __devinitdata = { 0, };
-static int io1[8] __devinitdata = { 0, };
+static int io0[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int io1[HISAX_MAX_CARDS] __devinitdata = { 0, };
 #endif
-static int irq[8] __devinitdata = { 0, };
-static int mem[8] __devinitdata = { 0, };
+static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
 static char *id __devinitdata = HiSaxID;
 
+#define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i"
+
 MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
 MODULE_AUTHOR("Karsten Keil");
 MODULE_LICENSE("GPL");
-MODULE_PARM(type, "1-8i");
-MODULE_PARM(protocol, "1-8i");
-MODULE_PARM(io, "1-8i");
-MODULE_PARM(irq, "1-8i");
-MODULE_PARM(mem, "1-8i");
+MODULE_PARM(type, PARM_PARA);
+MODULE_PARM(protocol, PARM_PARA);
+MODULE_PARM(io, PARM_PARA);
+MODULE_PARM(irq, PARM_PARA);
+MODULE_PARM(mem, PARM_PARA);
 MODULE_PARM(id, "s");
 #ifdef IO0_IO1
-MODULE_PARM(io0, "1-8i");
-MODULE_PARM(io1, "1-8i");
+MODULE_PARM(io0, PARM_PARA);
+MODULE_PARM(io1, PARM_PARA);
 #endif
 #endif /* MODULE */
 
@@ -448,6 +442,7 @@
 	i = 0;
 	j = 1;
 	while (argc && (i < HISAX_MAX_CARDS)) {
+		cards[i].protocol = DEFAULT_PROTO;
 		if (argc) {
 			cards[i].typ = ints[j];
 			j++;
@@ -475,13 +470,15 @@
 		}
 		i++;
 	}
-	if (str && *str) {
-		strcpy(HiSaxID, str);
-		HiSax_id = HiSaxID;
-	} else {
+  	if (str && *str) {
+		if (strlen(str) < HISAX_IDSIZE)
+			strcpy(HiSaxID, str);
+		else
+			printk(KERN_WARNING "HiSax: ID too long!");
+	} else
 		strcpy(HiSaxID, "HiSax");
-		HiSax_id = HiSaxID;
-	}
+
+	HiSax_id = HiSaxID;
 	return 1;
 }
 
@@ -1396,6 +1393,8 @@
 		if (protocol[i]) {
 			cards[j].protocol = protocol[i];
 			nzproto++;
+		} else {
+			cards[j].protocol = DEFAULT_PROTO;
 		}
 		switch (type[i]) {
 		case ISDN_CTYPE_16_0:
@@ -1473,15 +1472,22 @@
 			} else {
 				/* QUADRO is a 4 BRI card */
 				cards[j++].para[0] = 1;
-				cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
-				cards[j].protocol = protocol[i];
-				cards[j++].para[0] = 2;
-				cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
-				cards[j].protocol = protocol[i];
-				cards[j++].para[0] = 3;
-				cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
-				cards[j].protocol = protocol[i];
-				cards[j].para[0] = 4;
+				/* we need to check if further cards can be added */
+				if (j < HISAX_MAX_CARDS) {
+					cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+					cards[j].protocol = protocol[i];
+					cards[j++].para[0] = 2;
+				}
+				if (j < HISAX_MAX_CARDS) {
+					cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+					cards[j].protocol = protocol[i];
+					cards[j++].para[0] = 3;
+				}
+				if (j < HISAX_MAX_CARDS) {
+					cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+					cards[j].protocol = protocol[i];
+					cards[j].para[0] = 4;
+				}
 			}
 			break;
 		}
@@ -1554,6 +1560,8 @@
 		cards[i].typ = type[i];
 		if (protocol[i]) {
 			cards[i].protocol = protocol[i];
+		} else {
+			cards[i].protocol = DEFAULT_PROTO;
 		}
 	}
 	cards[0].para[0] = pcm_irq;
@@ -1594,6 +1602,8 @@
 		cards[i].typ = type[i];
 		if (protocol[i]) {
 			cards[i].protocol = protocol[i];
+		} else {
+			cards[i].protocol = DEFAULT_PROTO;
 		}
 	}
 	cards[0].para[0] = pcm_irq;
@@ -1634,6 +1644,8 @@
 		cards[i].typ = type[i];
 		if (protocol[i]) {
 			cards[i].protocol = protocol[i];
+		} else {
+			cards[i].protocol = DEFAULT_PROTO;
 		}
 	}
 	cards[0].para[0] = pcm_irq;
@@ -1674,6 +1686,8 @@
 		cards[i].typ = type[i];
 		if (protocol[i]) {
 			cards[i].protocol = protocol[i];
+		} else {
+			cards[i].protocol = DEFAULT_PROTO;
 		}
 	}
 	cards[0].para[0] = pcm_irq;
diff -urN linux-2.5.2-pre6/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- linux-2.5.2-pre6/drivers/isdn/hisax/hisax.h	Thu Jan  3 14:10:33 2002
+++ linux/drivers/isdn/hisax/hisax.h	Thu Jan  3 14:10:37 2002
@@ -1,4 +1,4 @@
-/* $Id: hisax.h,v 2.52.6.9 2001/09/23 22:24:48 kai Exp $
+/* $Id: hisax.h,v 1.1.4.1.2.1 2001/12/09 20:18:40 kai Exp $
  *
  * Basic declarations, defines and prototypes
  *
@@ -948,8 +948,6 @@
 #define  MON1_RX	2
 #define  MON0_TX	4
 #define  MON1_TX	8
-
-#define	 HISAX_MAX_CARDS	8
 
 #define  ISDN_CTYPE_16_0	1
 #define  ISDN_CTYPE_8_0		2
diff -urN linux-2.5.2-pre6/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- linux-2.5.2-pre6/drivers/isdn/isdn_common.c	Fri Nov  9 13:41:41 2001
+++ linux/drivers/isdn/isdn_common.c	Thu Jan  3 14:10:37 2002
@@ -963,7 +963,7 @@
 static ssize_t
 isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
 {
-	uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	uint minor = minor(file->f_dentry->d_inode->i_rdev);
 	int len = 0;
 	ulong flags;
 	int drvidx;
@@ -1077,7 +1077,7 @@
 static ssize_t
 isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
 {
-	uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	uint minor = minor(file->f_dentry->d_inode->i_rdev);
 	int drvidx;
 	int chidx;
 	int retval;
@@ -1143,7 +1143,7 @@
 isdn_poll(struct file *file, poll_table * wait)
 {
 	unsigned int mask = 0;
-	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
 	int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
 
 	lock_kernel();
@@ -1184,7 +1184,7 @@
 static int
 isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 {
-	uint minor = MINOR(inode->i_rdev);
+	uint minor = minor(inode->i_rdev);
 	isdn_ctrl c;
 	int drvidx;
 	int chidx;
@@ -1635,7 +1635,7 @@
 static int
 isdn_open(struct inode *ino, struct file *filep)
 {
-	uint minor = MINOR(ino->i_rdev);
+	uint minor = minor(ino->i_rdev);
 	int drvidx;
 	int chidx;
 	int retval = -ENODEV;
@@ -1696,7 +1696,7 @@
 static int
 isdn_close(struct inode *ino, struct file *filep)
 {
-	uint minor = MINOR(ino->i_rdev);
+	uint minor = minor(ino->i_rdev);
 
 	lock_kernel();
 	if (minor == ISDN_MINOR_STATUS) {
diff -urN linux-2.5.2-pre6/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- linux-2.5.2-pre6/drivers/isdn/isdn_ppp.c	Fri Nov  9 13:41:41 2001
+++ linux/drivers/isdn/isdn_ppp.c	Thu Jan  3 14:10:37 2002
@@ -586,7 +586,7 @@
 
 	if (is->debug & 0x2)
 		printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
-				MINOR(file->f_dentry->d_inode->i_rdev));
+				minor(file->f_dentry->d_inode->i_rdev));
 
 	/* just registers wait_queue hook. This doesn't really wait. */
 	poll_wait(file, &is->wq, wait);
diff -urN linux-2.5.2-pre6/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- linux-2.5.2-pre6/drivers/isdn/isdn_tty.c	Fri Nov  9 13:41:41 2001
+++ linux/drivers/isdn/isdn_tty.c	Thu Jan  3 14:10:37 2002
@@ -1019,12 +1019,12 @@
 #ifdef MODEM_PARANOIA_CHECK
 	if (!info) {
 		printk(KERN_WARNING "isdn_tty: null info_struct for (%d, %d) in %s\n",
-		       MAJOR(device), MINOR(device), routine);
+		       major(device), minor(device), routine);
 		return 1;
 	}
 	if (info->magic != ISDN_ASYNC_MAGIC) {
 		printk(KERN_WARNING "isdn_tty: bad magic for modem struct (%d, %d) in %s\n",
-		       MAJOR(device), MINOR(device), routine);
+		       major(device), minor(device), routine);
 		return 1;
 	}
 #endif
@@ -1740,7 +1740,7 @@
 	int retval,
 	 line;
 
-	line = MINOR(tty->device) - tty->driver.minor_start;
+	line = minor(tty->device) - tty->driver.minor_start;
 	if (line < 0 || line > ISDN_MAX_CHANNELS)
 		return -ENODEV;
 	info = &dev->mdm.info[line];
diff -urN linux-2.5.2-pre6/drivers/media/video/cpia.c linux/drivers/media/video/cpia.c
--- linux-2.5.2-pre6/drivers/media/video/cpia.c	Thu Oct 25 13:53:47 2001
+++ linux/drivers/media/video/cpia.c	Thu Jan  3 14:10:37 2002
@@ -2386,7 +2386,7 @@
 		goto_high_power(cam);
 		do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
 		if (goto_low_power(cam))
-			return -NODEV;
+			return -ENODEV;
 	}
 	
 	/* procedure described in developer's guide p3-28 */
diff -urN linux-2.5.2-pre6/drivers/media/video/videodev.c linux/drivers/media/video/videodev.c
--- linux-2.5.2-pre6/drivers/media/video/videodev.c	Thu Oct 11 09:14:32 2001
+++ linux/drivers/media/video/videodev.c	Thu Jan  3 14:10:37 2002
@@ -70,7 +70,7 @@
 static ssize_t video_read(struct file *file,
 	char *buf, size_t count, loff_t *ppos)
 {
-	struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+	struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
 	if(vfl->read)
 		return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
 	else
@@ -86,7 +86,7 @@
 static ssize_t video_write(struct file *file, const char *buf, 
 	size_t count, loff_t *ppos)
 {
-	struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+	struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
 	if(vfl->write)
 		return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
 	else
@@ -100,7 +100,7 @@
 
 static unsigned int video_poll(struct file *file, poll_table * wait)
 {
-	struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+	struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
 	if(vfl->poll)
 		return vfl->poll(vfl, file, wait);
 	else
@@ -114,7 +114,7 @@
 
 static int video_open(struct inode *inode, struct file *file)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	int err, retval = 0;
 	struct video_device *vfl;
 	
@@ -170,7 +170,7 @@
 {
 	struct video_device *vfl;
 	lock_kernel();
-	vfl=video_device[MINOR(inode->i_rdev)];
+	vfl=video_device[minor(inode->i_rdev)];
 	if(vfl->close)
 		vfl->close(vfl);
 	vfl->busy=0;
@@ -183,7 +183,7 @@
 static int video_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
-	struct video_device *vfl=video_device[MINOR(inode->i_rdev)];
+	struct video_device *vfl=video_device[minor(inode->i_rdev)];
 	int err=vfl->ioctl(vfl, cmd, (void *)arg);
 
 	if(err!=-ENOIOCTLCMD)
@@ -203,7 +203,7 @@
 int video_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	int ret = -EINVAL;
-	struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+	struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
 	if(vfl->mmap) {
 		lock_kernel();
 		ret = vfl->mmap(vfl, (char *)vma->vm_start, 
diff -urN linux-2.5.2-pre6/drivers/net/de2104x.c linux/drivers/net/de2104x.c
--- linux-2.5.2-pre6/drivers/net/de2104x.c	Mon Dec 10 11:17:40 2001
+++ linux/drivers/net/de2104x.c	Thu Jan  3 14:10:37 2002
@@ -28,8 +28,8 @@
  */
 
 #define DRV_NAME		"de2104x"
-#define DRV_VERSION		"0.5.1"
-#define DRV_RELDATE		"Nov 20, 2001"
+#define DRV_VERSION		"0.5.4"
+#define DRV_RELDATE		"Jan 1, 2002"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -45,6 +45,7 @@
 #include <linux/rtnetlink.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
+#include <asm/unaligned.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __initdata =
@@ -99,6 +100,7 @@
 #define DE_DUMMY_SKB		((struct sk_buff *) 2)
 #define DE_SETUP_FRAME_WORDS	96
 #define DE_EEPROM_WORDS		256
+#define DE_EEPROM_SIZE		(DE_EEPROM_WORDS * sizeof(u16))
 #define DE_MAX_MEDIA		5
 
 #define DE_MEDIA_TP_AUTO	0
@@ -109,6 +111,8 @@
 #define DE_MEDIA_INVALID	DE_MAX_MEDIA
 #define DE_MEDIA_FIRST		0
 #define DE_MEDIA_LAST		(DE_MAX_MEDIA - 1)
+#define DE_AUI_BNC		(SUPPORTED_AUI | SUPPORTED_BNC)
+
 #define DE_TIMER_LINK		(60 * HZ)
 #define DE_TIMER_NO_LINK	(5 * HZ)
 
@@ -117,7 +121,9 @@
 #define DE_REGS_VER		1
 
 /* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (6*HZ)
+#define TX_TIMEOUT		(6*HZ)
+
+#define DE_UNALIGNED_16(a)	(u16)(get_unaligned((u16 *)(a)))
 
 /* This is a mysterious value that can be written to CSR11 in the 21040 (only)
    to support a pre-NWay full-duplex signaling mechanism using short frames.
@@ -254,7 +260,6 @@
 	u16			default_media;
 	u8			n_blocks;
 	u8			unused;
-	struct de_srom_media_block	media[0];
 } __attribute__((packed));
 
 struct de_desc {
@@ -307,6 +312,7 @@
 	struct media_info	media[DE_MAX_MEDIA];
 	struct timer_list	media_timer;
 
+	u8			*ee_data;
 	unsigned		board_idx;
 	unsigned		de21040 : 1;
 	unsigned		media_lock : 1;
@@ -319,6 +325,7 @@
 static void de_media_interrupt (struct de_private *de, u32 status);
 static void de21040_media_timer (unsigned long data);
 static void de21041_media_timer (unsigned long data);
+static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media);
 
 
 static struct pci_device_id de_pci_tbl[] __initdata = {
@@ -918,7 +925,6 @@
 
 	dw32(MacStatus, dr32(MacStatus));
 
-	synchronize_irq();
 	udelay(10);
 
 	de->rx_tail = 0;
@@ -968,15 +974,29 @@
 	else
 		de->macmode &= ~FullDuplex;
 	
-	if (netif_msg_link(de))
-		printk(KERN_INFO "%s: set link %s, mode %x, sia %x,%x,%x,%x\n"
-		       KERN_INFO "                 set mode %x, set sia %x,%x,%x\n",
+	if (netif_msg_link(de)) {
+		printk(KERN_INFO "%s: set link %s\n"
+		       KERN_INFO "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
+		       KERN_INFO "%s:    set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
 		       de->dev->name, media_name[media],
-		       dr32(MacMode), dr32(SIAStatus), dr32(CSR13),
-		       dr32(CSR14), dr32(CSR15), de->macmode,
-			de->media[media].csr13,
-			de->media[media].csr14,
-			de->media[media].csr15);
+		       de->dev->name, dr32(MacMode), dr32(SIAStatus),
+		       dr32(CSR13), dr32(CSR14), dr32(CSR15),
+		       de->dev->name, de->macmode, de->media[media].csr13,
+		       de->media[media].csr14, de->media[media].csr15);
+	}
+}
+
+static void de_next_media (struct de_private *de, u32 *media,
+			   unsigned int n_media)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_media; i++) {
+		if (de_ok_to_advertise(de, media[i])) {
+			de->media_type = media[i];
+			return;
+		}
+	}
 }
 
 static void de21040_media_timer (unsigned long data)
@@ -985,6 +1005,7 @@
 	struct net_device *dev = de->dev;
 	u32 status = dr32(SIAStatus);
 	unsigned int carrier;
+	unsigned long flags;
 	
 	carrier = (status & NetCxnErr) ? 0 : 1;
 		
@@ -1009,12 +1030,17 @@
 	if (de->media_lock)
 		return;
 
-	if (de->media_type == DE_MEDIA_AUI)
-		de->media_type = DE_MEDIA_TP;
-	else
-		de->media_type = DE_MEDIA_AUI;
+	if (de->media_type == DE_MEDIA_AUI) {
+		u32 next_state = DE_MEDIA_TP;
+		de_next_media(de, &next_state, 1);
+	} else {
+		u32 next_state = DE_MEDIA_AUI;
+		de_next_media(de, &next_state, 1);
+	}
 
+	spin_lock_irqsave(&de->lock, flags);
 	de_stop_rxtx(de);
+	spin_unlock_irqrestore(&de->lock, flags);
 	de_set_media(de);
 	de_start_rxtx(de);
 
@@ -1061,8 +1087,9 @@
 {
 	struct de_private *de = (struct de_private *) data;
 	struct net_device *dev = de->dev;
-	u32 status = dr32(SIAStatus), new_media;
+	u32 status = dr32(SIAStatus);
 	unsigned int carrier;
+	unsigned long flags;
 	
 	carrier = (status & NetCxnErr) ? 0 : 1;
 		
@@ -1093,27 +1120,55 @@
 
 	/* if activity detected, use that as hint for new media type */
 	if (status & NonselPortActive) {
-		if (de->media_type == DE_MEDIA_AUI)
-			de->media_type = DE_MEDIA_TP;
-		else
+		unsigned int have_media = 1;
+
+		/* if AUI/BNC selected, then activity is on TP port */
+		if (de->media_type == DE_MEDIA_AUI ||
+		    de->media_type == DE_MEDIA_BNC) {
+			if (de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))
+				de->media_type = DE_MEDIA_TP_AUTO;
+			else
+				have_media = 0;
+		}
+
+		/* TP selected.  If there is only TP and BNC, then it's BNC */
+		else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_BNC) &&
+			 de_ok_to_advertise(de, DE_MEDIA_BNC))
+			de->media_type = DE_MEDIA_BNC;
+
+		/* TP selected.  If there is only TP and AUI, then it's AUI */
+		else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_AUI) &&
+			 de_ok_to_advertise(de, DE_MEDIA_AUI))
 			de->media_type = DE_MEDIA_AUI;
-		goto set_media;
-	}
 
-	/* move to next advertised media */
-	new_media = de->media_type;
-	do {
-		if (new_media == DE_MEDIA_LAST)
-			new_media = DE_MEDIA_FIRST;
+		/* otherwise, ignore the hint */
 		else
-			new_media++;
-	} while ((!de_ok_to_advertise(de, new_media)) &&
-	         (new_media != de->media_type));
+			have_media = 0;
 
-	de->media_type = new_media;
+		if (have_media)
+			goto set_media;
+	}
+
+	/*
+	 * Absent or ambiguous activity hint, move to next advertised
+	 * media state.  If de->media_type is left unchanged, this
+	 * simply resets the PHY and reloads the current media settings.
+	 */
+	if (de->media_type == DE_MEDIA_AUI) {
+		u32 next_states[] = { DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+		de_next_media(de, next_states, ARRAY_SIZE(next_states));
+	} else if (de->media_type == DE_MEDIA_BNC) {
+		u32 next_states[] = { DE_MEDIA_TP_AUTO, DE_MEDIA_AUI };
+		de_next_media(de, next_states, ARRAY_SIZE(next_states));
+	} else {
+		u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+		de_next_media(de, next_states, ARRAY_SIZE(next_states));
+	}
 	
 set_media:
+	spin_lock_irqsave(&de->lock, flags);
 	de_stop_rxtx(de);
+	spin_unlock_irqrestore(&de->lock, flags);
 	de_set_media(de);
 	de_start_rxtx(de);
 
@@ -1145,20 +1200,21 @@
 
 static int de_reset_mac (struct de_private *de)
 {
-	unsigned tmp;
-	u32 status;
+	u32 status, tmp;
 
 	/*
 	 * Reset MAC.  Copied from de4x5.c.
 	 */
 
-	dr32 (BusMode);
+	tmp = dr32 (BusMode);
+	if (tmp == 0xffffffff)
+		return -ENODEV;
 	mdelay (1);
 
-	dw32 (BusMode, de_bus_mode | CmdReset);
+	dw32 (BusMode, tmp | CmdReset);
 	mdelay (1);
 
-	dw32 (BusMode, de_bus_mode);
+	dw32 (BusMode, tmp);
 	mdelay (1);
 
 	for (tmp = 0; tmp < 5; tmp++) {
@@ -1309,12 +1365,20 @@
 	}
 
 	for (i = 0; i < DE_TX_RING_SIZE; i++) {
-		if (de->tx_skb[i].skb) {
-			struct sk_buff *skb = de->tx_skb[i].skb;
-			pci_unmap_single(de->pdev, de->tx_skb[i].mapping,
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(skb);
-			de->net_stats.tx_dropped++;
+		struct sk_buff *skb = de->tx_skb[i].skb;
+		if ((skb) && (skb != DE_DUMMY_SKB)) {
+			if (skb != DE_SETUP_SKB) {
+				dev_kfree_skb(skb);
+				de->net_stats.tx_dropped++;
+				pci_unmap_single(de->pdev,
+					de->tx_skb[i].mapping,
+					skb->len, PCI_DMA_TODEVICE);
+			} else {
+				pci_unmap_single(de->pdev,
+					de->tx_skb[i].mapping,
+					sizeof(de->setup_frame),
+					PCI_DMA_TODEVICE);
+			}
 		}
 	}
 
@@ -1334,6 +1398,7 @@
 {
 	struct de_private *de = dev->priv;
 	int rc;
+	unsigned long flags;
 
 	if (netif_msg_ifup(de))
 		printk(KERN_DEBUG "%s: enabling interface\n", dev->name);
@@ -1362,11 +1427,15 @@
 	}
 
 	netif_start_queue(dev);
+	mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
 
 	return 0;
 
 err_out_hw:
+	spin_lock_irqsave(&de->lock, flags);
 	de_stop_hw(de);
+	spin_unlock_irqrestore(&de->lock, flags);
+
 err_out_free:
 	de_free_rings(de);
 	return rc;
@@ -1375,15 +1444,21 @@
 static int de_close (struct net_device *dev)
 {
 	struct de_private *de = dev->priv;
+	unsigned long flags;
 
 	if (netif_msg_ifdown(de))
 		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
 
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
 	del_timer_sync(&de->media_timer);
+
+	spin_lock_irqsave(&de->lock, flags);
 	de_stop_hw(de);
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+	spin_unlock_irqrestore(&de->lock, flags);
+	
 	free_irq(dev->irq, dev);
+
 	de_free_rings(de);
 	de_adapter_sleep(de);
 	pci_disable_device(de->pdev);
@@ -1558,6 +1633,7 @@
 		strcpy (info.driver, DRV_NAME);
 		strcpy (info.version, DRV_VERSION);
 		strcpy (info.bus_info, de->pdev->slot_name);
+		info.eedump_len = DE_EEPROM_SIZE;
 		info.regdump_len = DE_REGS_SIZE;
 		if (copy_to_user (useraddr, &info, sizeof (info)))
 			return -EFAULT;
@@ -1658,6 +1734,23 @@
 		return 0;
 	}
 
+	/* get SROM dump */
+	case ETHTOOL_GEEPROM: {
+		struct ethtool_eeprom eeprom;
+
+		if (!de->ee_data)
+			break;
+		if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+			return -EFAULT;
+		if ((eeprom.offset != 0) || (eeprom.magic != 0) ||
+		    (eeprom.len != DE_EEPROM_SIZE))
+			return -EINVAL;
+
+		useraddr += offsetof(struct ethtool_regs, data);
+		if (copy_to_user(useraddr, de->ee_data, DE_EEPROM_SIZE))
+			return -EFAULT;
+	}
+
 	default:
 		break;
 	}
@@ -1703,7 +1796,31 @@
 	}
 }
 
-/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
+static void __init de21040_get_media_info(struct de_private *de)
+{
+	unsigned int i;
+
+	de->media_type = DE_MEDIA_TP;
+	de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full |
+			       SUPPORTED_10baseT_Half | SUPPORTED_AUI;
+	de->media_advertise = de->media_supported;
+
+	for (i = 0; i < DE_MAX_MEDIA; i++) {
+		switch (i) {
+		case DE_MEDIA_AUI:
+		case DE_MEDIA_TP:
+		case DE_MEDIA_TP_FD:
+			de->media[i].type = i;
+			de->media[i].csr13 = t21040_csr13[i];
+			de->media[i].csr14 = t21040_csr14[i];
+			de->media[i].csr15 = t21040_csr15[i];
+			break;
+		default:
+			de->media[i].type = DE_MEDIA_INVALID;
+			break;
+		}
+	}
+}
 
 /* Note: this routine returns extra data bits for size detection. */
 static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len)
@@ -1741,15 +1858,16 @@
 	return retval;
 }
 
-static void __init tulip_get_srom_info (struct de_private *de)
+static void __init de21041_get_srom_info (struct de_private *de)
 {
 	unsigned i, sa_offset = 0, ofs;
-	u8 ee_data[DE_EEPROM_WORDS * sizeof(u16)];
+	u8 ee_data[DE_EEPROM_SIZE + 6] = {};
 	unsigned ee_addr_size = tulip_read_eeprom(de->regs, 0xff, 8) & 0x40000 ? 8 : 6;
 	struct de_srom_info_leaf *il;
+	void *bufp;
 
 	/* download entire eeprom */
-	for (i = 0; i < sizeof(ee_data)/2; i++)
+	for (i = 0; i < DE_EEPROM_WORDS; i++)
 		((u16 *)ee_data)[i] =
 			le16_to_cpu(tulip_read_eeprom(de->regs, i, ee_addr_size));
 
@@ -1780,13 +1898,18 @@
 		goto bad_srom;
 
 	/* get default media type */
-	switch (il->default_media) {
+	switch (DE_UNALIGNED_16(&il->default_media)) {
 	case 0x0001:  de->media_type = DE_MEDIA_BNC; break;
 	case 0x0002:  de->media_type = DE_MEDIA_AUI; break;
 	case 0x0204:  de->media_type = DE_MEDIA_TP_FD; break;
 	default: de->media_type = DE_MEDIA_TP_AUTO; break;
 	}
 	
+	if (netif_msg_probe(de))
+		printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n",
+		       de->board_idx, ofs,
+		       media_name[de->media_type]);
+
 	/* init SIA register values to defaults */
 	for (i = 0; i < DE_MAX_MEDIA; i++) {
 		de->media[i].type = DE_MEDIA_INVALID;
@@ -1798,8 +1921,9 @@
 	/* parse media blocks to see what medias are supported,
 	 * and if any custom CSR values are provided
 	 */
+	bufp = ((void *)il) + sizeof(*il);
 	for (i = 0; i < il->n_blocks; i++) {
-		struct de_srom_media_block *ib = &il[i].media[0];
+		struct de_srom_media_block *ib = bufp;
 		unsigned idx;
 
 		/* index based on media type in media block */
@@ -1828,16 +1952,37 @@
 			goto bad_srom;
 		}
 
+		de->media[idx].type = idx;
+
+		if (netif_msg_probe(de))
+			printk(KERN_INFO "de%d:   media block #%u: %s",
+			       de->board_idx, i,
+			       media_name[de->media[idx].type]);
+
+		bufp += sizeof (ib->opts);
+
 		if (ib->opts & MediaCustomCSRs) {
-			de->media[idx].csr13 = ib->csr13;
-			de->media[idx].csr14 = ib->csr14;
-			de->media[idx].csr15 = ib->csr15;
-		}
+			de->media[idx].csr13 = DE_UNALIGNED_16(&ib->csr13);
+			de->media[idx].csr14 = DE_UNALIGNED_16(&ib->csr14);
+			de->media[idx].csr15 = DE_UNALIGNED_16(&ib->csr15);
+			bufp += sizeof(ib->csr13) + sizeof(ib->csr14) +
+				sizeof(ib->csr15);
+
+			if (netif_msg_probe(de))
+				printk(" (%x,%x,%x)\n",
+				       de->media[idx].csr13,
+				       de->media[idx].csr14,
+				       de->media[idx].csr15);
+				       
+		} else if (netif_msg_probe(de))
+			printk("\n");
 
-		de->media[idx].type = idx;
-		de->media_advertise |= de->media_supported;
+		if (bufp > ((void *)&ee_data[DE_EEPROM_SIZE - 3]))
+			break;
 	}
 
+	de->media_advertise = de->media_supported;
+
 fill_defaults:
 	/* fill in defaults, for cases where custom CSRs not used */
 	for (i = 0; i < DE_MAX_MEDIA; i++) {
@@ -1849,12 +1994,9 @@
 			de->media[i].csr15 = t21041_csr15[i];
 	}
 
-	if (netif_msg_link(de))
-		printk(KERN_INFO "de%d: SROM-listed ports: %s%s%s\n",
-		       de->board_idx,
-		       de->media_supported & SUPPORTED_TP ? "TP " : "",
-		       de->media_supported & SUPPORTED_BNC ? "BNC " : "",
-		       de->media_supported & SUPPORTED_AUI ? "AUI" : "");
+	de->ee_data = kmalloc(DE_EEPROM_SIZE, GFP_KERNEL);
+	if (de->ee_data)
+		memcpy(de->ee_data, &ee_data[0], DE_EEPROM_SIZE);
 
 	return;
 
@@ -1970,35 +2112,21 @@
 	de_adapter_wake(de);
 
 	/* make sure hardware is not running */
-	de_stop_hw(de);
+	rc = de_reset_mac(de);
+	if (rc) {
+		printk(KERN_ERR PFX "Cannot reset MAC, pci dev %s\n",
+		       pdev->slot_name);
+		goto err_out_iomap;
+	}
 
-	/* get MAC address, and some register values related to media types */
+	/* get MAC address, initialize default media type and
+	 * get list of supported media
+	 */
 	if (de->de21040) {
-		unsigned i;
-		
 		de21040_get_mac_address(de);
-
-		de->media_type = DE_MEDIA_TP;
-		de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full |
-				  SUPPORTED_10baseT_Half | SUPPORTED_AUI;
-		de->media_advertise = de->media_supported;
-		for (i = 0; i < DE_MAX_MEDIA; i++) {
-			switch (i) {
-			case DE_MEDIA_AUI:
-			case DE_MEDIA_TP:
-			case DE_MEDIA_TP_FD:
-				de->media[i].type = i;
-				de->media[i].csr13 = t21040_csr13[i];
-				de->media[i].csr14 = t21040_csr14[i];
-				de->media[i].csr15 = t21040_csr15[i];
-				break;
-			default:
-				de->media[i].type = DE_MEDIA_INVALID;
-				break;
-			}
-		}
+		de21040_get_media_info(de);
 	} else {
-		tulip_get_srom_info(de);
+		de21041_get_srom_info(de);
 	}
 
 	/* register new network interface with kernel */
@@ -2029,6 +2157,8 @@
 	return 0;
 
 err_out_iomap:
+	if (de->ee_data)
+		kfree(de->ee_data);
 	iounmap(regs);
 err_out_res:
 	pci_release_regions(pdev);
@@ -2047,6 +2177,8 @@
 	if (!dev)
 		BUG();
 	unregister_netdev(dev);
+	if (de->ee_data)
+		kfree(de->ee_data);
 	iounmap(de->regs);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff -urN linux-2.5.2-pre6/drivers/net/defxx.c linux/drivers/net/defxx.c
--- linux-2.5.2-pre6/drivers/net/defxx.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/defxx.c	Thu Jan  3 14:10:37 2002
@@ -500,7 +500,7 @@
 
 static int __init dfx_eisa_init(void)
 {
-	int rc = -NODEV;
+	int rc = -ENODEV;
 	int i;			/* used in for loops */
 	u16 port;		/* temporary I/O (port) address */
 	u32 slot_id;		/* EISA hardware (slot) ID read from adapter */
diff -urN linux-2.5.2-pre6/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- linux-2.5.2-pre6/drivers/net/irda/irtty.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/net/irda/irtty.c	Thu Jan  3 14:10:37 2002
@@ -172,7 +172,7 @@
 
 	/* Give self a name */
 	sprintf(name, "%s%d", tty->driver.name,
-		MINOR(tty->device) - tty->driver.minor_start +
+		minor(tty->device) - tty->driver.minor_start +
 		tty->driver.name_base);
 
 	hashbin_insert(irtty, (irda_queue_t *) self, (int) self, NULL);
@@ -910,7 +910,7 @@
 
 	/* Give self a hardware name */
 	sprintf(hwname, "%s%d", tty->driver.name,
-		MINOR(tty->device) - tty->driver.minor_start +
+		minor(tty->device) - tty->driver.minor_start +
 		tty->driver.name_base);
 
 	/* 
diff -urN linux-2.5.2-pre6/drivers/net/slip.c linux/drivers/net/slip.c
--- linux-2.5.2-pre6/drivers/net/slip.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/net/slip.c	Thu Jan  3 14:10:37 2002
@@ -739,7 +739,7 @@
 			break;
 
 		if (slp->ctrl.leased) {
-			if (slp->ctrl.line != line)
+			if (!kdev_same(slp->ctrl.line, line))
 				continue;
 			if (slp->ctrl.tty)
 				return NULL;
@@ -753,7 +753,7 @@
 			continue;
 
 		if (current->pid == slp->ctrl.pid) {
-			if (slp->ctrl.line == line && score < 3) {
+			if (kdev_same(slp->ctrl.line, line) && score < 3) {
 				sel = i;
 				score = 3;
 				continue;
@@ -764,7 +764,7 @@
 			}
 			continue;
 		}
-		if (slp->ctrl.line == line && score < 1) {
+		if (kdev_same(slp->ctrl.line, line) && score < 1) {
 			sel = i;
 			score = 1;
 			continue;
@@ -944,7 +944,7 @@
 	tty->disc_data = 0;
 	sl->tty = NULL;
 	if (!sl->leased)
-		sl->line = 0;
+		sl->line = NODEV;
 
 	/* VSV = very important to remove timers */
 #ifdef CONFIG_SLIP_SMART
diff -urN linux-2.5.2-pre6/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c
--- linux-2.5.2-pre6/drivers/net/wan/cosa.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/net/wan/cosa.c	Thu Jan  3 14:10:37 2002
@@ -940,12 +940,12 @@
 	unsigned long flags;
 	int n;
 
-	if ((n=MINOR(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
+	if ((n=minor(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
 		>= nr_cards)
 		return -ENODEV;
 	cosa = cosa_cards+n;
 
-	if ((n=MINOR(file->f_dentry->d_inode->i_rdev)
+	if ((n=minor(file->f_dentry->d_inode->i_rdev)
 		& ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
 		return -ENODEV;
 	chan = cosa->chan + n;
diff -urN linux-2.5.2-pre6/drivers/net/wan/sdla_chdlc.c linux/drivers/net/wan/sdla_chdlc.c
--- linux-2.5.2-pre6/drivers/net/wan/sdla_chdlc.c	Thu Sep 13 16:04:43 2001
+++ linux/drivers/net/wan/sdla_chdlc.c	Thu Jan  3 14:10:37 2002
@@ -3933,7 +3933,7 @@
 	
 	if (!tty->driver_data){
 		int port;
-		port = MINOR(tty->device) - tty->driver.minor_start;
+		port = minor(tty->device) - tty->driver.minor_start;
 		if ((port < 0) || (port >= NR_PORTS)) 
 			return -ENODEV;
 		
diff -urN linux-2.5.2-pre6/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h
--- linux-2.5.2-pre6/drivers/scsi/BusLogic.h	Thu Jul 19 21:07:57 2001
+++ linux/drivers/scsi/BusLogic.h	Thu Jan  3 14:10:37 2002
@@ -1531,7 +1531,7 @@
 void BusLogic_AcquireHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
 				       ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+  spin_lock_irqsave(&HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1544,7 +1544,7 @@
 void BusLogic_ReleaseHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
 				       ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
diff -urN linux-2.5.2-pre6/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- linux-2.5.2-pre6/drivers/scsi/advansys.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/advansys.c	Thu Jan  3 14:10:37 2002
@@ -3610,36 +3610,6 @@
 #define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif /* CONFIG_PROC_FS */
 
-/*
- * XXX - Release and acquire the io_request_lock. These macros are needed
- * because the 2.4 kernel SCSI mid-level driver holds the 'io_request_lock'
- * on entry to SCSI low-level drivers.
- *
- * These definitions and all code that uses code should be removed when the
- * SCSI mid-level driver no longer holds the 'io_request_lock' on entry to
- * SCSI low-level driver detect, queuecommand, and reset entrypoints.
- *
- * The interrupt flags values doesn't matter in the macros because the
- * SCSI mid-level will save and restore the flags values before and after
- * calling advansys_detect, advansys_queuecommand, and advansys_reset where
- * these macros are used. We do want interrupts enabled after the lock is
- * released so an explicit sti() is done. The driver only needs interrupts
- * disabled when it acquires the per board lock.
- */
-#define ASC_UNLOCK_IO_REQUEST_LOCK \
-    { \
-        ulong flags; /* flags value not needed, cf. comment above. */ \
-        save_flags(flags); \
-        spin_unlock_irqrestore(&io_request_lock, flags); \
-        sti(); /* enable interrupts */ \
-    }
-
-#define ASC_LOCK_IO_REQUEST_LOCK \
-    { \
-        ulong flags; /* flags value not needed, cf. comment above. */ \
-        spin_lock_irqsave(&io_request_lock, flags); \
-    }
-
 /* Asc Library return codes */
 #define ASC_TRUE        1
 #define ASC_FALSE       0
@@ -4084,7 +4054,6 @@
         ADVEEP_38C1600_CONFIG adv_38C1600_eep;  /* 38C1600 EEPROM config. */
     } eep_config;
     ulong                last_reset;            /* Saved last reset time */
-    spinlock_t lock;                            /* Board spinlock */
 #ifdef CONFIG_PROC_FS
     /* /proc/scsi/advansys/[0...] */
     char                 *prtbuf;               /* /proc print buffer */
@@ -4604,13 +4573,6 @@
 
     ASC_DBG(1, "advansys_detect: begin\n");
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level detect entrypoint.
-     */
-    ASC_UNLOCK_IO_REQUEST_LOCK
-
 #if ASC_LINUX_KERNEL24
     tpnt->proc_name = "advansys";
 #elif ASC_LINUX_KERNEL22
@@ -4837,9 +4799,6 @@
             memset(boardp, 0, sizeof(asc_board_t));
             boardp->id = asc_board_count - 1;
 
-            /* Initialize spinlock. */
-            boardp->lock = SPIN_LOCK_UNLOCKED;
-
             /*
              * Handle both narrow and wide boards.
              *
@@ -5723,13 +5682,6 @@
         }
     }
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level detect entrypoint.
-     */
-    ASC_LOCK_IO_REQUEST_LOCK
-
     ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
     return asc_board_count;
 }
@@ -5893,14 +5845,7 @@
     boardp = ASC_BOARDP(shp);
     ASC_STATS(shp, queuecommand);
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level queuecommand entrypoint.
-     */
-    ASC_UNLOCK_IO_REQUEST_LOCK
-
-    spin_lock_irqsave(&boardp->lock, flags);
+    spin_lock_irqsave(&shp->host_lock, flags);
 
     /*
      * Block new commands while handling a reset or abort request.
@@ -5917,7 +5862,7 @@
          * handling.
          */
         asc_enqueue(&boardp->done, scp, ASC_BACK);
-        spin_unlock_irqrestore(&boardp->lock, flags);
+        spin_unlock_irqrestore(&shp->host_lock, flags);
         return 0;
     }
 
@@ -5961,15 +5906,7 @@
         break;
     }
 
-    spin_unlock_irqrestore(&boardp->lock, flags);
-
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level queuecommand entrypoint.
-     */
-    ASC_LOCK_IO_REQUEST_LOCK
-
+    spin_unlock_irqrestore(&shp->host_lock, flags);
     return 0;
 }
 
@@ -6015,20 +5952,13 @@
     /*
      * Check for re-entrancy.
      */
-    spin_lock_irqsave(&boardp->lock, flags);
+    spin_lock_irqsave(&shp->host_lock, flags);
     if (boardp->flags & ASC_HOST_IN_RESET) {
-        spin_unlock_irqrestore(&boardp->lock, flags);
+        spin_unlock_irqrestore(&shp->host_lock, flags);
         return FAILED;
     }
     boardp->flags |= ASC_HOST_IN_RESET;
-    spin_unlock_irqrestore(&boardp->lock, flags);
-
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level reset entrypoint.
-     */
-    ASC_UNLOCK_IO_REQUEST_LOCK
+    spin_unlock_irqrestore(&shp->host_lock, flags);
 
     if (ASC_NARROW_BOARD(boardp)) {
         /*
@@ -6063,7 +5993,7 @@
         /*
          * Acquire the board lock.
          */
-        spin_lock_irqsave(&boardp->lock, flags);
+        spin_lock_irqsave(&shp->host_lock, flags);
 
     } else {
         /*
@@ -6094,7 +6024,7 @@
          * Acquire the board lock and ensure all requests completed by the
          * microcode have been processed by calling AdvISR().
          */
-        spin_lock_irqsave(&boardp->lock, flags);
+        spin_lock_irqsave(&shp->host_lock, flags);
         (void) AdvISR(adv_dvc_varp);
     }
 
@@ -6160,7 +6090,7 @@
     boardp->flags &= ~ASC_HOST_IN_RESET;
 
     /* Release the board. */
-    spin_unlock_irqrestore(&boardp->lock, flags);
+    spin_unlock_irqrestore(&shp->host_lock, flags);
 
     /*
      * Complete all the 'done_scp' requests.
@@ -6169,13 +6099,6 @@
         asc_scsi_done_list(done_scp);
     }
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level reset entrypoint.
-     */
-    ASC_LOCK_IO_REQUEST_LOCK
-
     ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
 
     return ret;
@@ -6344,10 +6267,11 @@
      * AscISR() will call asc_isr_callback().
      */
     for (i = 0; i < asc_board_count; i++) {
-        boardp = ASC_BOARDP(asc_host[i]);
+	struct Scsi_Host *shp = asc_host[i];
+        boardp = ASC_BOARDP(shp);
         ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n",
             i, (ulong) boardp);
-        spin_lock_irqsave(&boardp->lock, flags);
+        spin_lock_irqsave(&shp->host_lock, flags);
         if (ASC_NARROW_BOARD(boardp)) {
             /*
              * Narrow Board
@@ -6403,7 +6327,7 @@
                 }
             }
         }
-        spin_unlock_irqrestore(&boardp->lock, flags);
+        spin_unlock_irqrestore(&shp->host_lock, flags);
     }
 
     /*
diff -urN linux-2.5.2-pre6/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- linux-2.5.2-pre6/drivers/scsi/aha152x.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/aha152x.c	Thu Jan  3 14:10:37 2002
@@ -1349,9 +1349,9 @@
 
 		printk(KERN_INFO "aha152x%d: trying software interrupt, ", HOSTNO);
 		SETPORT(DMACNTRL0, SWINT|INTEN);
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&shpnt->host_lock);
 		mdelay(1000);
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&shpnt->host_lock);
 		free_irq(shpnt->irq, shpnt);
 
 		if (!HOSTDATA(shpnt)->swint) {
diff -urN linux-2.5.2-pre6/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- linux-2.5.2-pre6/drivers/scsi/aha1740.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/scsi/aha1740.c	Thu Jan  3 14:10:37 2002
@@ -213,6 +213,7 @@
 /* A "high" level interrupt handler */
 void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
 {
+    struct Scsi_Host *host = aha_host[irq - 9];
     void (*my_done)(Scsi_Cmnd *);
     int errstatus, adapstat;
     int number_serviced;
@@ -221,11 +222,10 @@
     unsigned int base;
     unsigned long flags;
 
-    spin_lock_irqsave(&io_request_lock, flags);
-
-    if (!aha_host[irq - 9])
+    if (!host)
 	panic("aha1740.c: Irq from unknown host!\n");
-    base = aha_host[irq - 9]->io_port;
+    spin_lock_irqsave(&host->host_lock, flags);
+    base = host->io_port;
     number_serviced = 0;
 
     while(inb(G2STAT(base)) & G2STAT_INTPEND)
@@ -299,7 +299,7 @@
 	number_serviced++;
     }
 
-    spin_unlock_irqrestore(&io_request_lock, flags);
+    spin_unlock_irqrestore(&host->host_lock, flags);
 }
 
 int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
diff -urN linux-2.5.2-pre6/drivers/scsi/dpt_i2o.c linux/drivers/scsi/dpt_i2o.c
--- linux-2.5.2-pre6/drivers/scsi/dpt_i2o.c	Wed Nov 28 10:22:27 2001
+++ linux/drivers/scsi/dpt_i2o.c	Thu Jan  3 14:10:37 2002
@@ -1157,17 +1157,13 @@
 	msg[2] |= 0x80000000 | ((u32)wait_data->id);
 	timeout *= HZ;
 	if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){
-		if(!timeout){
-			set_current_state(TASK_INTERRUPTIBLE);
-			spin_unlock_irq(&io_request_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irq(&pHba->host->host_lock);
+		if (!timeout)
 			schedule();
-			spin_lock_irq(&io_request_lock);
-		} else {
-			set_current_state(TASK_INTERRUPTIBLE);
-			spin_unlock_irq(&io_request_lock);
+		else
 			schedule_timeout(timeout*HZ);
-			spin_lock_irq(&io_request_lock);
-		}
+		spin_lock_irq(&pHba->host->host_lock);
 	}
 	wq_write_lock_irq(&adpt_wq_i2o_post.lock);
 	__remove_wait_queue(&adpt_wq_i2o_post, &wait);
@@ -1560,7 +1556,7 @@
 
 	//TODO check for root access
 	//
-	minor = MINOR(inode->i_rdev);
+	minor = minor(inode->i_rdev);
 	if (minor >= hba_count) {
 		return -ENXIO;
 	}
@@ -1591,7 +1587,7 @@
 	int minor;
 	adpt_hba* pHba;
 
-	minor = MINOR(inode->i_rdev);
+	minor = minor(inode->i_rdev);
 	if (minor >= hba_count) {
 		return -ENXIO;
 	}
@@ -1705,7 +1701,7 @@
 	}
 
 	do {
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&pHba->host->host_lock, flags);
 		// This state stops any new commands from enterring the
 		// controller while processing the ioctl
 //		pHba->state |= DPTI_STATE_IOCTL;
@@ -1713,7 +1709,7 @@
 //		the queue empties and stops.  We need a way to restart the queue
 		rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
 //		pHba->state &= ~DPTI_STATE_IOCTL;
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&pHba->host->host_lock, flags);
 	} while(rcode == -ETIMEDOUT);  
 
 	if(rcode){
@@ -1887,7 +1883,7 @@
 	adpt_hba* pHba;
 	ulong flags;
 
-	minor = MINOR(inode->i_rdev);
+	minor = minor(inode->i_rdev);
 	if (minor >= DPTI_MAX_HBA){
 		return -ENXIO;
 	}
@@ -1951,9 +1947,9 @@
 		break;
 		}
 	case I2ORESETCMD:
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&pHba->host->host_lock, flags);
 		adpt_hba_reset(pHba);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&pHba->host->host_lock, flags);
 		break;
 	case I2ORESCANCMD:
 		adpt_rescan(pHba);
@@ -1989,19 +1985,18 @@
 static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	Scsi_Cmnd* cmd;
-	adpt_hba* pHba=NULL;
+	adpt_hba* pHba = dev_id;
 	u32 m;
 	ulong reply;
 	u32 status=0;
 	u32 context;
 	ulong flags = 0;
 
-	pHba = dev_id;
 	if (pHba == NULL ){
 		printk(KERN_WARNING"adpt_isr: NULL dev_id\n");
 		return;
 	}
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&pHba->host->host_lock, flags);
 	while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {
 		m = readl(pHba->reply_port);
 		if(m == EMPTY_QUEUE){
@@ -2011,8 +2006,7 @@
 			if(m == EMPTY_QUEUE){ 
 				// This really should not happen
 				printk(KERN_ERR"dpti: Could not get reply frame\n");
-				spin_unlock_irqrestore(&io_request_lock,flags);
-				return;
+				goto out;
 			}
 		}
 		reply = (ulong)bus_to_virt(m);
@@ -2067,9 +2061,7 @@
 		wmb();
 		rmb();
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
-	return;
-
+out:	spin_unlock_irqrestore(&pHba->host->host_lock, flags);
 }
 
 static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d)
@@ -2342,18 +2334,14 @@
 	s32 rcode;
 	ulong flags;
 
-	spin_lock_irqsave(&io_request_lock, flags);
-	if ((rcode=adpt_i2o_lct_get(pHba)) < 0){
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return rcode;
-	}
-
-	if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return rcode;
-	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
-	return 0;
+	spin_lock_irqsave(&pHba->host->host_lock, flags);
+	if ((rcode=adpt_i2o_lct_get(pHba)) < 0)
+		goto out;
+	if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0)
+		goto out;
+	rcode = 0;
+out:	spin_unlock_irqrestore(&pHba->host->host_lock, flags);
+	return rcode;
 }
 
 
diff -urN linux-2.5.2-pre6/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- linux-2.5.2-pre6/drivers/scsi/eata.c	Wed Dec 12 09:20:22 2001
+++ linux/drivers/scsi/eata.c	Thu Jan  3 14:10:37 2002
@@ -1,6 +1,13 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      01 Jan 2002 Rev. 7.20 for linux 2.5.1
+ *        + Use the dynamic DMA mapping API.
+ *
+ *      19 Dec 2001 Rev. 7.02 for linux 2.5.1
+ *        + Use SCpnt->sc_data_direction if set.
+ *        + Use sglist.page instead of sglist.address.
+ *
  *      11 Dec 2001 Rev. 7.00 for linux 2.5.1
  *        + Use host->host_lock instead of io_request_lock.
  *
@@ -223,7 +230,7 @@
  *          This driver is based on the CAM (Common Access Method Committee)
  *          EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
  *
- *  Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
+ *  Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com)
  *
  *  Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
  *
@@ -634,7 +641,7 @@
    u_int32_t data_len;   /* If sg=0 Data Length, if sg=1 sglist length */
    u_int32_t cpp_index;  /* Index of address to be returned in sp */
    u_int32_t data_address; /* If sg=0 Data Address, if sg=1 sglist address */
-   u_int32_t sp_addr;    /* Address where sp is DMA'ed when cp completes */
+   u_int32_t sp_dma_addr;  /* Address where sp is DMA'ed when cp completes */
    u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */
    /* Additional fields begin here. */
    Scsi_Cmnd *SCpnt;
@@ -656,7 +663,11 @@
    unsigned long last_retried_pid;      /* Pid of last retried command */
    unsigned char subversion;            /* Bus type, either ISA or EISA/PCI */
    unsigned char protocol_rev;          /* EATA 2.0 rev., 'A' or 'B' or 'C' */
-   struct mssp sp[2];                   /* Returned status for this board */
+   unsigned char is_pci;                /* TRUE is bus type is PCI */
+   struct pci_dev *pdev;                /* pdev for PCI bus, NULL otherwise */
+   struct mssp *sp_cpu_addr;            /* cpu addr for DMA buffer sp */
+   dma_addr_t sp_dma_addr;              /* dma handle for DMA buffer sp */
+   struct mssp sp;                      /* Local copy of sp buffer */
    };
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
@@ -693,10 +704,11 @@
 #define HD(board) ((struct hostdata *) &sh[board]->hostdata)
 #define BN(board) (HD(board)->board_name)
 
-#define H2DEV(x) htonl(x)
-#define DEV2H(x) H2DEV(x)
+/* Device is Big Endian */
+#define H2DEV(x) cpu_to_be32(x)
+#define DEV2H(x) be32_to_cpu(x)
+
 #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
 
 static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
@@ -855,7 +867,7 @@
 
 static inline int port_detect \
       (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) {
-   unsigned char irq, dma_channel, subversion, i;
+   unsigned char irq, dma_channel, subversion, i, is_pci = FALSE;
    unsigned char protocol_rev;
    struct eata_info info;
    char *bus_type, dma_name[16], tag_type;
@@ -907,10 +919,12 @@
 
    if (!setup_done && j > 0 && j <= MAX_PCI) {
       bus_type = "PCI";
+      is_pci = TRUE;
       subversion = ESA;
       }
    else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) {
       bus_type = "PCI";
+      is_pci = TRUE;
       subversion = ESA;
       }
    else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) {
@@ -923,6 +937,7 @@
       }
    else if (port_base > MAX_ISA_ADDR) {
       bus_type = "PCI";
+      is_pci = TRUE;
       subversion = ESA;
       }
    else {
@@ -963,7 +978,13 @@
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
              name, irq);
 
-   pdev = get_pci_dev(port_base);
+   if (is_pci) {
+      pdev = get_pci_dev(port_base);
+      if (!pdev) 
+         printk("%s: warning, failed to get pci_dev structure.\n", name);
+      }
+   else
+      pdev = NULL;
 
    if (pdev && (irq != pdev->irq)) {
       printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, pdev->irq);
@@ -993,7 +1014,7 @@
 
    /* Set board configuration */
    memset((char *)&config, 0, sizeof(struct eata_config));
-   config.len = (ushort) htons((ushort)510);
+   config.len = (ushort) cpu_to_be16((ushort)510);
    config.ocena = TRUE;
 
    if (do_dma(port_base, (unsigned long)&config, SET_CONFIG_DMA)) {
@@ -1022,14 +1043,16 @@
    sh[j]->n_io_port = REGION_SIZE;
    sh[j]->dma_channel = dma_channel;
    sh[j]->irq = irq;
-   sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size);
+   sh[j]->sg_tablesize = (ushort) be16_to_cpu(info.scatt_size);
    sh[j]->this_id = (ushort) info.host_addr[3];
-   sh[j]->can_queue = (ushort) ntohs(info.queue_size);
+   sh[j]->can_queue = (ushort) be16_to_cpu(info.queue_size);
    sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;
    sh[j]->select_queue_depths = select_queue_depths;
    memset(HD(j), 0, sizeof(struct hostdata));
    HD(j)->subversion = subversion;
    HD(j)->protocol_rev = protocol_rev;
+   HD(j)->is_pci = is_pci;
+   HD(j)->pdev = pdev;
    HD(j)->board_number = j;
 
    if (HD(j)->subversion == ESA)
@@ -1038,14 +1061,14 @@
       unsigned long flags;
       scsi_register_blocked_host(sh[j]);
       sh[j]->unchecked_isa_dma = TRUE;
-      
+
       flags=claim_dma_lock();
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
       set_dma_mode(dma_channel, DMA_MODE_CASCADE);
       enable_dma(dma_channel);
       release_dma_lock(flags);
-      
+
       }
 
    strcpy(BN(j), name);
@@ -1094,6 +1117,13 @@
          return FALSE;
          }
 
+   if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev, 
+         sizeof(struct mssp), &HD(j)->sp_dma_addr))) {
+      printk("%s: pci_alloc_consistent failed, detaching.\n", BN(j));
+      eata2x_release(sh[j]);
+      return FALSE;
+      }
+
    if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
        max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
 
@@ -1108,7 +1138,7 @@
    else                                 tag_type = 'n';
 
    if (j == 0) {
-      printk("EATA/DMA 2.0x: Copyright (C) 1994-2001 Dario Ballabio.\n");
+      printk("EATA/DMA 2.0x: Copyright (C) 1994-2002 Dario Ballabio.\n");
       printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c.\n",
              driver_name, tag_type, YESNO(linked_comm), max_queue_depth,
              YESNO(rev_scan), YESNO(ext_tran));
@@ -1144,7 +1174,11 @@
              info.pci, info.eisa, info.raidnum);
 #endif
 
-   if (pdev) pci_set_master(pdev);
+   if (HD(j)->pdev) {
+      pci_set_master(HD(j)->pdev);
+      if (pci_set_dma_mask(HD(j)->pdev, 0xffffffff))
+         printk("%s: warning, pci_set_dma_mask failed.\n", BN(j));
+      }
 
    return TRUE;
 }
@@ -1271,25 +1305,92 @@
    return j;
 }
 
-static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
-   unsigned int k;
+static inline void map_dma(unsigned int i, unsigned int j) {
+   unsigned int k, count, pci_dir;
    struct scatterlist *sgpnt;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (SCpnt->sense_buffer)
+      cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer,
+                           sizeof SCpnt->sense_buffer, PCI_DMA_FROMDEVICE));
+
+   cpp->sense_len = sizeof SCpnt->sense_buffer;
+
+   if (!SCpnt->use_sg) {
+
+      if (!SCpnt->request_bufflen)
+         cpp->data_address = V2DEV(SCpnt->request_buffer);
+
+      else if (SCpnt->request_buffer)
+         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
+                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
+
+      cpp->data_len = H2DEV(SCpnt->request_bufflen);
+      return;
+      }
 
    sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
 
-   for (k = 0; k < SCpnt->use_sg; k++) {
-      cpp->sglist[k].address = V2DEV(sgpnt[k].address);
-      cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
+   for (k = 0; k < count; k++) {
+      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
+      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
       }
 
+   cpp->sg = TRUE;
    cpp->data_address = V2DEV(cpp->sglist);
    cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
 }
 
-static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
-   unsigned int i, j, k;
+static void unmap_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
    struct mscp *cpp;
-   struct mssp *spp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                       DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                       DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static void sync_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                          DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, 
+                         SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                          DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
+   unsigned int k;
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
@@ -1300,9 +1401,53 @@
    static const unsigned char data_none_cmds[] = {
       0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e,
       0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47,
-      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5
+      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00
       };
 
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i];
+   SCpnt = cpp->SCpnt;
+
+   if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
+      cpp->din  = TRUE;
+      cpp->dout = FALSE;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {
+      cpp->din  = FALSE;
+      cpp->dout = TRUE;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) {
+      cpp->din  = FALSE;
+      cpp->dout = FALSE;
+      return;
+      }
+
+   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) 
+      panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
+
+   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
+      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
+         cpp->dout = TRUE;
+         break;
+         }
+
+   if ((cpp->din = !cpp->dout))
+      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
+         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
+            cpp->din = FALSE;
+            break;
+            }
+
+}
+
+static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
+   unsigned int i, j, k;
+   struct mscp *cpp;
+
    /* j is the board number */
    j = ((struct hostdata *) SCpnt->host->hostdata)->board_number;
 
@@ -1334,11 +1479,8 @@
 
    memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
 
-   /* Set pointer to status packet structure */
-   spp = &HD(j)->sp[0];
-
-   /* The EATA protocol uses Big Endian format */
-   cpp->sp_addr = V2DEV(spp);
+   /* Set pointer to status packet structure, Big Endian format */
+   cpp->sp_dma_addr = H2DEV(HD(j)->sp_dma_addr);
 
    SCpnt->scsi_done = done;
    cpp->cpp_index = i;
@@ -1348,19 +1490,6 @@
                         BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
-   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
-     if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-        cpp->dout = TRUE;
-        break;
-        }
-
-   if ((cpp->din = !cpp->dout))
-      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
-        if (SCpnt->cmnd[0] == data_none_cmds[k]) {
-           cpp->din = FALSE;
-           break;
-           }
-
    cpp->reqsen = TRUE;
    cpp->dispri = TRUE;
 #if 0
@@ -1371,8 +1500,13 @@
    cpp->target = SCpnt->target;
    cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
-   cpp->sense_len = sizeof SCpnt->sense_buffer;
+   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+   /* Use data transfer direction SCpnt->sc_data_direction */
+   scsi_to_dev_dir(i, j);
+
+   /* Map DMA buffers and SG list */
+   map_dma(i, j);
 
    if (SCpnt->device->tagged_queue) {
 
@@ -1392,17 +1526,6 @@
       cpp->mess[1] = SCpnt->device->current_tag++;
       }
 
-   if (SCpnt->use_sg) {
-      cpp->sg = TRUE;
-      build_sg_list(cpp, SCpnt);
-      }
-   else {
-      cpp->data_address = V2DEV(SCpnt->request_buffer);
-      cpp->data_len = H2DEV(SCpnt->request_bufflen);
-      }
-
-   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
-
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type)) {
       HD(j)->cp_stat[i] = READY;
@@ -1412,6 +1535,7 @@
 
    /* Send control packet to the board */
    if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) {
+      unmap_dma(i, j);
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
@@ -1468,6 +1592,7 @@
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
 
       if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {
+         unmap_dma(i, j);
          SCarg->host_scribble = NULL;
          HD(j)->cp_stat[i] = FREE;
          printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",
@@ -1489,6 +1614,7 @@
       }
 
    if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+      unmap_dma(i, j);
       SCarg->result = DID_ABORT << 16;
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
@@ -1597,6 +1723,7 @@
 
       if (HD(j)->cp_stat[i] == IN_RESET) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1609,6 +1736,7 @@
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1821,7 +1949,7 @@
 static inline void ihdlr(int irq, unsigned int j) {
    Scsi_Cmnd *SCpnt;
    unsigned int i, k, c, status, tstatus, reg;
-   struct mssp *dspp, *spp;
+   struct mssp *spp;
    struct mscp *cpp;
 
    if (sh[j]->irq != irq)
@@ -1843,14 +1971,13 @@
       return;
       }
 
-   dspp = &HD(j)->sp[0];
-   spp  = &HD(j)->sp[1];
+   spp  = &HD(j)->sp;
 
    /* Make a local copy just before clearing the interrupt indication */
-   memcpy(spp, dspp, sizeof(struct mssp));
+   memcpy(spp, HD(j)->sp_cpu_addr, sizeof(struct mssp));
 
    /* Clear the completion flag and cp pointer on the dynamic copy of sp */
-   memset(dspp, 0, sizeof(struct mssp));
+   memset(HD(j)->sp_cpu_addr, 0, sizeof(struct mssp));
 
    /* Read the status register to clear the interrupt indication */
    reg = inb(sh[j]->io_port + REG_STATUS);
@@ -1908,6 +2035,8 @@
       panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
             BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
+   sync_dma(i, j);
+
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type))
       flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
@@ -1985,6 +2114,7 @@
 #else
             status = DID_BUS_BUSY << 16;
 #endif
+
             HD(j)->retries++;
             HD(j)->last_retried_pid = SCpnt->pid;
             }
@@ -2021,6 +2151,8 @@
              SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
              reg, HD(j)->iocount);
 
+   unmap_dma(i, j);
+
    /* Set the command state to inactive */
    SCpnt->host_scribble = NULL;
 
@@ -2052,13 +2184,15 @@
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   if( sh[j]->unchecked_isa_dma ) {
-	   scsi_deregister_blocked_host(sh[j]);
-   }
+   if(sh[j]->unchecked_isa_dma) scsi_deregister_blocked_host(sh[j]);
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
+   if (HD(j)->sp_cpu_addr) 
+      pci_free_consistent(HD(j)->pdev, sizeof(struct mssp),
+                          HD(j)->sp_cpu_addr, HD(j)->sp_dma_addr);
+                       
    free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
diff -urN linux-2.5.2-pre6/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- linux-2.5.2-pre6/drivers/scsi/eata.h	Wed Dec 12 09:20:22 2001
+++ linux/drivers/scsi/eata.h	Thu Jan  3 14:10:37 2002
@@ -13,7 +13,7 @@
 int eata2x_reset(Scsi_Cmnd *);
 int eata2x_biosparam(Disk *, kdev_t, int *);
 
-#define EATA_VERSION "7.00.00"
+#define EATA_VERSION "7.20.00"
 
 #define EATA {                                                               \
                 name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
diff -urN linux-2.5.2-pre6/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- linux-2.5.2-pre6/drivers/scsi/fdomain.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/scsi/fdomain.c	Thu Jan  3 14:10:37 2002
@@ -382,22 +382,23 @@
    Write_FIFO       = 12
 };
 
-static int               port_base         = 0;
-static unsigned long     bios_base         = 0;
-static int               bios_major        = 0;
-static int               bios_minor        = 0;
-static int               PCI_bus           = 0;
-static int               Quantum           = 0;	/* Quantum board variant */
-static int               interrupt_level   = 0;
-static volatile int      in_command        = 0;
-static Scsi_Cmnd         *current_SC       = NULL;
+/* .bss will zero all the static variables below */
+static int               port_base;
+static unsigned long     bios_base;
+static int               bios_major;
+static int               bios_minor;
+static int               PCI_bus;
+static int               Quantum;	/* Quantum board variant */
+static int               interrupt_level;
+static volatile int      in_command;
+static Scsi_Cmnd         *current_SC;
 static enum chip_type    chip              = unknown;
-static int               adapter_mask      = 0;
-static int               this_id           = 0;
-static int               setup_called      = 0;
+static int               adapter_mask;
+static int               this_id;
+static int               setup_called;
 
 #if DEBUG_RACE
-static volatile int      in_interrupt_flag = 0;
+static volatile int      in_interrupt_flag;
 #endif
 
 static int               SCSI_Mode_Cntl_port;
@@ -1265,9 +1266,9 @@
 #if EVERY_ACCESS
 	 printk( " AFAIL " );
 #endif
-         spin_lock_irqsave(&io_request_lock, flags);
+         spin_lock_irqsave(&current_SC->host->host_lock, flags);
 	 my_done( DID_BUS_BUSY << 16 );
-         spin_unlock_irqrestore(&io_request_lock, flags);
+         spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
 	 return;
       }
       current_SC->SCp.phase = in_selection;
@@ -1291,9 +1292,9 @@
 #if EVERY_ACCESS
 	    printk( " SFAIL " );
 #endif
-            spin_lock_irqsave(&io_request_lock, flags);
+            spin_lock_irqsave(&current_SC->host->host_lock, flags);
 	    my_done( DID_NO_CONNECT << 16 );
-            spin_unlock_irqrestore(&io_request_lock, flags);
+            spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
 	    return;
 	 } else {
 #if EVERY_ACCESS
@@ -1638,10 +1639,10 @@
 #if EVERY_ACCESS
       printk( "BEFORE MY_DONE. . ." );
 #endif
-      spin_lock_irqsave(&io_request_lock, flags);
+      spin_lock_irqsave(&current_SC->host->host_lock, flags);
       my_done( (current_SC->SCp.Status & 0xff)
 	       | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
-      spin_unlock_irqrestore(&io_request_lock, flags);
+      spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
 #if EVERY_ACCESS
       printk( "RETURNING.\n" );
 #endif
@@ -1932,11 +1933,11 @@
       0x0a bytes long.  Heads are one less than we need to report.
     */
 
-   if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
+   if (major(dev) != SCSI_DISK0_MAJOR) {
       printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");
       return 0;
    }
-   drive = MINOR(dev) >> 4;
+   drive = minor(dev) >> 4;
 
    if (bios_major == 2) {
       switch (Quantum) {
diff -urN linux-2.5.2-pre6/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- linux-2.5.2-pre6/drivers/scsi/ide-scsi.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/scsi/ide-scsi.c	Thu Jan  3 14:10:37 2002
@@ -747,7 +747,7 @@
 {
 	idescsi_scsi_t *scsi = drive->driver_data;
 
-	if (MAJOR(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR)
+	if (major(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR)
 		return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 	return test_bit(IDESCSI_TRANSFORM, &scsi->transform);
 }
diff -urN linux-2.5.2-pre6/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
--- linux-2.5.2-pre6/drivers/scsi/in2000.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/scsi/in2000.c	Thu Jan  3 14:10:37 2002
@@ -855,7 +855,7 @@
 
 /* Get the spin_lock and disable further ints, for SMP */
 
-   CLISPIN_LOCK(flags);
+   CLISPIN_LOCK(instance, flags);
 
 #ifdef PROC_STATISTICS
    hostdata->int_cnt++;
@@ -993,7 +993,7 @@
       write1_io(0, IO_LED_OFF);
 
 /* release the SMP spin_lock and restore irq state */
-      CLISPIN_UNLOCK(flags);
+      CLISPIN_UNLOCK(instance, flags);
       return;
       }
 
@@ -1011,7 +1011,7 @@
       write1_io(0, IO_LED_OFF);
 
 /* release the SMP spin_lock and restore irq state */
-      CLISPIN_UNLOCK(flags);
+      CLISPIN_UNLOCK(instance, flags);
       return;
       }
 
@@ -1433,7 +1433,7 @@
             hostdata->state = S_UNCONNECTED;
 
 /* release the SMP spin_lock and restore irq state */
-            CLISPIN_UNLOCK(flags);
+            CLISPIN_UNLOCK(instance, flags);
             return;
             }
 DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
@@ -1609,7 +1609,7 @@
 DB(DB_INTR,printk("} "))
 
 /* release the SMP spin_lock and restore irq state */
-   CLISPIN_UNLOCK(flags);
+   CLISPIN_UNLOCK(instance, flags);
 
 }
 
diff -urN linux-2.5.2-pre6/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h
--- linux-2.5.2-pre6/drivers/scsi/in2000.h	Wed Nov 28 10:22:27 2001
+++ linux/drivers/scsi/in2000.h	Thu Jan  3 14:10:37 2002
@@ -393,8 +393,9 @@
 # define in2000__INITFUNC(function) __initfunc(function)
 # define in2000__INIT __init
 # define in2000__INITDATA __initdata
-# define CLISPIN_LOCK(flags)   spin_lock_irqsave(&io_request_lock, flags)
-# define CLISPIN_UNLOCK(flags) spin_unlock_irqrestore(&io_request_lock, flags)
+# define CLISPIN_LOCK(host,flags)   spin_lock_irqsave(&host->host_lock, flags)
+# define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(&host->host_lock, \
+							   flags)
 
 int in2000_detect(Scsi_Host_Template *) in2000__INIT;
 int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
diff -urN linux-2.5.2-pre6/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- linux-2.5.2-pre6/drivers/scsi/ips.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/ips.c	Thu Jan  3 14:10:37 2002
@@ -1769,14 +1769,13 @@
       char      *kern_area;
       u_int32_t  datasize;
 
-      /* free io_request_lock */
-      spin_unlock_irq(&io_request_lock);
+      spin_unlock_irq(&SC->host->host_lock);
 
       /* wait for the command to finish */
       down(&ha->ioctl_sem);
 
       /* reobtain the lock */
-      spin_lock_irq(&io_request_lock);
+      spin_lock_irq(&SC->host->host_lock);
 
       /* command finished -- copy back */
       user_area = *((char **) &SC->cmnd[4]);
@@ -1911,31 +1910,30 @@
 /****************************************************************************/
 void
 do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
-   ips_ha_t         *ha;
+   ips_ha_t         *ha = (ips_ha_t *) dev_id;
    unsigned long     cpu_flags;
+   struct Scsi_Host *host = ips_sh[ha->host_num];
 
    METHOD_TRACE("do_ipsintr", 2);
 
-   ha = (ips_ha_t *) dev_id;
-
-   spin_lock_irqsave(&io_request_lock, cpu_flags);
+   spin_lock_irqsave(&host->host_lock, cpu_flags);
 
    if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {
-      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+      spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
       return ;
    }
 
    if (!ha) {
       clear_bit(IPS_IN_INTR, &ha->flags);
-      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+      spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
       return;
    }
 
    if (!ha->active) {
       clear_bit(IPS_IN_INTR, &ha->flags);
-      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+      spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
       return;
    }
@@ -1944,10 +1942,11 @@
 
    clear_bit(IPS_IN_INTR, &ha->flags);
 
-   spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+   spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
    /* start the next command */
    ips_next(ha, IPS_INTR_ON);
+   return;
 }
 
 /****************************************************************************/
@@ -2487,8 +2486,8 @@
             task.routine = ips_scheduled_flash_bios;
             task.data = (void *) &flash_data;
 
-            /* Unlock the master lock */
-            spin_unlock_irq(&io_request_lock);
+            /* Unlock the per-board lock */
+            spin_unlock_irq(&SC->host->host_lock);
 
             queue_task(&task, &tq_immediate);
             mark_bh(IMMEDIATE_BH);
@@ -2496,8 +2495,8 @@
             /* Wait for the flash to complete */
             down(&ha->flash_ioctl_sem);
 
-            /* Obtain the master lock */
-            spin_lock_irq(&io_request_lock);
+            /* Obtain the per-board lock */
+            spin_lock_irq(&SC->host->host_lock);
 
             return (flash_data.retcode);
          }
@@ -2604,8 +2603,8 @@
             task.routine = ips_flash_bios_section;
             task.data = (void *) &flash_data;
 
-            /* Unlock the master lock */
-            spin_unlock_irq(&io_request_lock);
+            /* Unlock the per-board lock */
+            spin_unlock_irq(&SC->host->host_lock);
 
             queue_task(&task, &tq_immediate);
             mark_bh(IMMEDIATE_BH);
@@ -2613,8 +2612,8 @@
             /* Wait for the flash to complete */
             down(&ha->flash_ioctl_sem);
 
-            /* Obtain the master lock */
-            spin_lock_irq(&io_request_lock);
+            /* Obtain the per-board lock */
+            spin_lock_irq(&SC->host->host_lock);
 
             return (flash_data.retcode);
          }
@@ -3572,18 +3571,21 @@
    int                   intr_status;
    unsigned long         cpu_flags;
    unsigned long         cpu_flags2;
+   struct Scsi_Host *host;
 
    METHOD_TRACE("ips_next", 1);
 
    if (!ha)
       return ;
 
+   host = ips_sh[ha->host_num];
+
    /*
     * Block access to the queue function so
     * this command won't time out
     */
    if (intr == IPS_INTR_ON) {
-       spin_lock_irqsave(&io_request_lock, cpu_flags2);
+       spin_lock_irqsave(&host->host_lock, cpu_flags2);
        intr_status = IPS_INTR_IORL;
    } else {
        intr_status = intr;
@@ -3608,7 +3610,7 @@
    }
 
    if (intr == IPS_INTR_ON)
-       spin_unlock_irqrestore(&io_request_lock, cpu_flags2);
+       spin_unlock_irqrestore(&host->host_lock, cpu_flags2);
 
 #ifndef NO_IPS_CMDLINE
    /*
@@ -6604,6 +6606,8 @@
 
          clear_bit(IPS_IN_INTR, &ha->flags);
       } else if (intr == IPS_INTR_HAL) {
+	 struct Scsi_Host *host = ips_sh[ha->host_num];
+
          if (ha->waitflag == FALSE) {
             /*
              * controller generated an interrupt to
@@ -6621,7 +6625,7 @@
           * We were called under the HA lock so we can assume that interrupts
           * are masked.
           */
-         spin_lock(&io_request_lock);
+         spin_lock(&host->host_lock);
 
          while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
             udelay(1000);
@@ -6630,7 +6634,7 @@
 
          clear_bit(IPS_IN_INTR, &ha->flags);
 
-         spin_unlock(&io_request_lock);
+         spin_unlock(&host->host_lock);
       }
 
       udelay(1000); /* 1 milisecond */
diff -urN linux-2.5.2-pre6/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c
--- linux-2.5.2-pre6/drivers/scsi/pci2000.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/pci2000.c	Thu Jan  3 14:10:37 2002
@@ -275,11 +275,6 @@
 	int					z;
     unsigned long		flags;
 
-    /*
-     * Disable interrupts, if they aren't already disabled and acquire
-     * the I/O spinlock.
-     */
-    spin_lock_irqsave (&io_request_lock, flags);
 
 	DEB(printk ("\npci2000 received interrupt "));
 	for ( z = 0; z < NumAdapters;  z++ )										// scan for interrupt to process
@@ -298,9 +293,10 @@
 	if ( !shost )
 		{
 		DEB (printk ("\npci2000: not my interrupt"));
-		goto irq_return;
+		goto out;
 		}
 
+	spin_lock_irqsave(&shost->host_lock, flags);
 	padapter = HOSTDATA(shost);
 
 	tag0 = tag & 0x7F;															// mask off the error bit
@@ -392,14 +388,10 @@
 	outb_p (CMD_DONE, padapter->cmd);										// complete the op
 	OpDone (SCpnt, DID_OK << 16);
 
-irq_return:;
-    /*
-     * Release the I/O spinlock and restore the original flags
-     * which will enable interrupts if and only if they were
-     * enabled on entry.
-     */
-    spin_unlock_irqrestore (&io_request_lock, flags);
-	}
+irq_return:
+    spin_unlock_irqrestore(&shost->host_flag, flags);
+out:;
+}
 /****************************************************************
  *	Name:	Pci2000_QueueCommand
  *
diff -urN linux-2.5.2-pre6/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- linux-2.5.2-pre6/drivers/scsi/pci2220i.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/pci2220i.c	Thu Jan  3 14:10:37 2002
@@ -1152,6 +1152,7 @@
 static void TimerExpiry (unsigned long data)
 	{
 	PADAPTER2220I	padapter = (PADAPTER2220I)data;
+	struct Scsi_Host *host = padapter->SCpnt->host;
 	POUR_DEVICE		pdev = padapter->pdev;
 	UCHAR			status = IDE_STATUS_BUSY;
 	UCHAR			temp, temp1;
@@ -1161,7 +1162,7 @@
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
-    spin_lock_irqsave (&io_request_lock, flags);
+    spin_lock_irqsave (&host->host_lock, flags);
 	DEB (printk ("\nPCI2220I: Timeout expired "));
 
 	if ( padapter->failinprog )
@@ -1295,7 +1296,7 @@
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
-    spin_unlock_irqrestore (&io_request_lock, flags);
+    spin_unlock_irqrestore (&host->host_lock, flags);
 	}
 /****************************************************************
  *	Name:			SetReconstruct	:LOCAL
@@ -1328,7 +1329,8 @@
  ****************************************************************/
 static void ReconTimerExpiry (unsigned long data)
 	{
-	PADAPTER2220I	padapter;
+	PADAPTER2220I	padapter = (PADAPTER2220I)data;
+	struct Scsi_Host *host = padapter->SCpnt->host;
 	POUR_DEVICE		pdev;
 	ULONG			testsize = 0;
 	PIDENTIFY_DATA	pid;
@@ -1342,9 +1344,8 @@
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
-    spin_lock_irqsave (&io_request_lock, flags);
+    spin_lock_irqsave(&host->host_lock, flags);
 
-	padapter = (PADAPTER2220I)data;
 	if ( padapter->SCpnt )
 		goto reconTimerExpiry;
 
@@ -1567,7 +1568,7 @@
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
-    spin_unlock_irqrestore (&io_request_lock, flags);
+    spin_unlock_irqrestore(&host->host_lock, flags);
 	}
 /****************************************************************
  *	Name:	Irq_Handler	:LOCAL
@@ -1596,12 +1597,6 @@
 	ULONG				zl;
     unsigned long		flags;
 
-    /*
-     * Disable interrupts, if they aren't already disabled and acquire
-     * the I/O spinlock.
-     */
-    spin_lock_irqsave (&io_request_lock, flags);
-
 //	DEB (printk ("\npci2220i received interrupt\n"));
 
 	for ( z = 0; z < NumAdapters;  z++ )								// scan for interrupt to process
@@ -1619,9 +1614,10 @@
 	if ( !shost )
 		{
 		DEB (printk ("\npci2220i: not my interrupt"));
-		goto irq_return;
+		goto out;
 		}
 
+	spin_lock_irqsave(&shost->host_lock, flags);
 	padapter = HOSTDATA(shost);
 	pdev = padapter->pdev;
 	SCpnt = padapter->SCpnt;
@@ -2023,13 +2019,9 @@
 		zl = DID_OK << 16;
 
 	OpDone (padapter, zl);
-irq_return:;
-    /*
-     * Release the I/O spinlock and restore the original flags
-     * which will enable interrupts if and only if they were
-     * enabled on entry.
-     */
-    spin_unlock_irqrestore (&io_request_lock, flags);
+irq_return:
+    spin_unlock_irqrestore(&shost->host_lock, flags);
+out:;
 	}
 /****************************************************************
  *	Name:	Pci2220i_QueueCommand
diff -urN linux-2.5.2-pre6/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- linux-2.5.2-pre6/drivers/scsi/scsi.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/scsi/scsi.c	Thu Jan  3 14:10:37 2002
@@ -200,13 +200,10 @@
 
 	/* Hardware imposed limit. */
 	blk_queue_max_hw_segments(q, SHpnt->sg_tablesize);
-
-	/*
-	 * When we remove scsi_malloc soonish, this can die too
-	 */
-	blk_queue_max_phys_segments(q, PAGE_SIZE / sizeof(struct scatterlist));
-
 	blk_queue_max_sectors(q, SHpnt->max_sectors);
+
+	/* scsi_alloc_sgtable max */
+	blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
 
 	if (!SHpnt->use_clustering)
 		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
diff -urN linux-2.5.2-pre6/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- linux-2.5.2-pre6/drivers/scsi/scsi_lib.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/scsi/scsi_lib.c	Thu Jan  3 14:10:37 2002
@@ -83,7 +83,6 @@
 	rq->q = NULL;
 	rq->bio = rq->biotail = NULL;
 	rq->nr_phys_segments = 0;
-	rq->elevator_sequence = 0;
 
 	/*
 	 * We have the option of inserting the head or the tail of the queue.
@@ -92,7 +91,7 @@
 	 * device, or a host that is unable to accept a particular command.
 	 */
 	spin_lock_irqsave(q->queue_lock, flags);
-	__elv_add_request(q, rq, !at_head, 0);
+	_elv_add_request(q, rq, !at_head, 0);
 	q->request_fn(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
@@ -262,7 +261,7 @@
 		 * the bad sector.
 		 */
 		SCpnt->request.special = (void *) SCpnt;
-		__elv_add_request(q, &SCpnt->request, 0, 0);
+		_elv_add_request(q, &SCpnt->request, 0, 0);
 	}
 
 	/*
diff -urN linux-2.5.2-pre6/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- linux-2.5.2-pre6/drivers/scsi/sg.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/scsi/sg.c	Thu Jan  3 14:10:37 2002
@@ -254,7 +254,7 @@
 
 static int sg_open(struct inode * inode, struct file * filp)
 {
-    int dev = MINOR(inode->i_rdev);
+    int dev = minor(inode->i_rdev);
     int flags = filp->f_flags;
     Sg_device * sdp;
     Sg_fd * sfp;
@@ -340,7 +340,7 @@
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) {
         return -ENXIO;
     }
-    SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
+    SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", minor(sdp->i_rdev)));
     sg_fasync(-1, filp, 0);   /* remove filp from async notification list */
     if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
         if (! sdp->detached) {
@@ -369,7 +369,7 @@
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n",
-                               MINOR(sdp->i_rdev), (int)count));
+                               minor(sdp->i_rdev), (int)count));
     if (ppos != &filp->f_pos)
         ; /* FIXME: Hmm.  Seek to the right place, or fail?  */
     if ((k = verify_area(VERIFY_WRITE, buf, count)))
@@ -514,7 +514,7 @@
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n",
-                               MINOR(sdp->i_rdev), (int)count));
+                               minor(sdp->i_rdev), (int)count));
     if (sdp->detached)
     	return -ENODEV;
     if (! ((filp->f_flags & O_NONBLOCK) ||
@@ -731,7 +731,7 @@
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n",
-                               MINOR(sdp->i_rdev), (int)cmd_in));
+                               minor(sdp->i_rdev), (int)cmd_in));
     read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
 
     switch(cmd_in)
@@ -1011,7 +1011,7 @@
     else if (count < SG_MAX_QUEUE)
         res |= POLLOUT | POLLWRNORM;
     SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n",
-                        MINOR(sdp->i_rdev), (int)res));
+                        minor(sdp->i_rdev), (int)res));
     return res;
 }
 
@@ -1024,7 +1024,7 @@
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n",
-                               MINOR(sdp->i_rdev), mode));
+                               minor(sdp->i_rdev), mode));
 
     retval = fasync_helper(fd, filp, mode, &sfp->async_qp);
     return (retval < 0) ? retval : 0;
@@ -1035,7 +1035,7 @@
 static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
 {
     Scsi_Request * SRpnt = SCpnt->sc_request;
-    int dev = MINOR(SRpnt->sr_request.rq_dev);
+    int dev = minor(SRpnt->sr_request.rq_dev);
     Sg_device * sdp = NULL;
     Sg_fd * sfp;
     Sg_request * srp = NULL;
@@ -1278,7 +1278,7 @@
     sdp->sgdebug = 0;
     sdp->detached = 0;
     sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
-    sdp->i_rdev = MKDEV(SCSI_GENERIC_MAJOR, k);
+    sdp->i_rdev = mk_kdev(SCSI_GENERIC_MAJOR, k);
     sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT,
                              SCSI_GENERIC_MAJOR, k,
                              S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
@@ -2415,7 +2415,7 @@
     SRpnt->sr_bufflen = 0;
     SRpnt->sr_buffer = NULL;
     SRpnt->sr_underflow = 0;
-    SRpnt->sr_request.rq_dev = MKDEV(0, 0);  /* "sg" _disowns_ command blk */
+    SRpnt->sr_request.rq_dev = mk_kdev(0, 0);  /* "sg" _disowns_ command blk */
 }
 
 static int sg_ms_to_jif(unsigned int msecs)
@@ -2694,7 +2694,7 @@
 		PRINT_PROC("device %d detached ??\n", j);
 		continue;
 	    }
-	    dev = MINOR(sdp->i_rdev);
+	    dev = minor(sdp->i_rdev);
 
 	    if (sg_get_nth_sfp(sdp, 0)) {
 		PRINT_PROC(" >>> device=sg%d ", dev);
diff -urN linux-2.5.2-pre6/drivers/scsi/sim710.c linux/drivers/scsi/sim710.c
--- linux-2.5.2-pre6/drivers/scsi/sim710.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/scsi/sim710.c	Thu Jan  3 14:10:37 2002
@@ -904,11 +904,12 @@
 static void
 do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
+    struct Scsi_Host *host = dev_id;
     unsigned long flags;
 
-    spin_lock_irqsave(&io_request_lock, flags);
-    sim710_intr_handle(irq, dev_id, regs);
-    spin_unlock_irqrestore(&io_request_lock, flags);
+    spin_lock_irqsave(&host->host_lock, flags);
+    sim710_intr_handle(irq, host, regs);
+    spin_unlock_irqrestore(&host->host_lock, flags);
 }
 
 
diff -urN linux-2.5.2-pre6/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- linux-2.5.2-pre6/drivers/scsi/sr.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/scsi/sr.c	Thu Jan  3 14:10:37 2002
@@ -99,11 +99,11 @@
 
 static void sr_release(struct cdrom_device_info *cdi)
 {
-	if (scsi_CDs[MINOR(cdi->dev)].device->sector_size > 2048)
-		sr_set_blocklength(MINOR(cdi->dev), 2048);
-	scsi_CDs[MINOR(cdi->dev)].device->access_count--;
-	if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)
-		__MOD_DEC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);
+	if (scsi_CDs[minor(cdi->dev)].device->sector_size > 2048)
+		sr_set_blocklength(minor(cdi->dev), 2048);
+	scsi_CDs[minor(cdi->dev)].device->access_count--;
+	if (scsi_CDs[minor(cdi->dev)].device->host->hostt->module)
+		__MOD_DEC_USE_COUNT(scsi_CDs[minor(cdi->dev)].device->host->hostt->module);
 	if (sr_template.module)
 		__MOD_DEC_USE_COUNT(sr_template.module);
 }
@@ -150,7 +150,7 @@
 		/* no changer support */
 		return -EINVAL;
 	}
-	retval = scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+	retval = scsi_ioctl(scsi_CDs[minor(cdi->dev)].device,
 			    SCSI_IOCTL_TEST_UNIT_READY, 0);
 
 	if (retval) {
@@ -159,13 +159,13 @@
 		 * and we will figure it out later once the drive is
 		 * available again.  */
 
-		scsi_CDs[MINOR(cdi->dev)].device->changed = 1;
+		scsi_CDs[minor(cdi->dev)].device->changed = 1;
 		return 1;	/* This will force a flush, if called from
 				 * check_disk_change */
 	};
 
-	retval = scsi_CDs[MINOR(cdi->dev)].device->changed;
-	scsi_CDs[MINOR(cdi->dev)].device->changed = 0;
+	retval = scsi_CDs[minor(cdi->dev)].device->changed;
+	scsi_CDs[minor(cdi->dev)].device->changed = 0;
 	/* If the disk changed, the capacity will now be different,
 	 * so we force a re-read of this information */
 	if (retval) {
@@ -179,9 +179,9 @@
 		 * be trying to use something that is too small if the disc
 		 * has changed.
 		 */
-		scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
+		scsi_CDs[minor(cdi->dev)].needs_sector_size = 1;
 
-		scsi_CDs[MINOR(cdi->dev)].device->sector_size = 2048;
+		scsi_CDs[minor(cdi->dev)].device->sector_size = 2048;
 	}
 	return retval;
 }
@@ -253,17 +253,17 @@
 	/*
 	 * No such device
 	 */
-	if (MINOR(dev) >= sr_template.dev_max || !scsi_CDs[MINOR(dev)].device)
+	if (minor(dev) >= sr_template.dev_max || !scsi_CDs[minor(dev)].device)
 		return NULL;
 
-	return &scsi_CDs[MINOR(dev)].device->request_queue;
+	return &scsi_CDs[minor(dev)].device->request_queue;
 }
 
 static int sr_init_command(Scsi_Cmnd * SCpnt)
 {
 	int dev, devm, block=0, this_count, s_size;
 
-	devm = MINOR(SCpnt->request.rq_dev);
+	devm = minor(SCpnt->request.rq_dev);
 	dev = DEVICE_NR(SCpnt->request.rq_dev);
 
 	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
@@ -399,20 +399,20 @@
 {
 	check_disk_change(cdi->dev);
 
-	if (MINOR(cdi->dev) >= sr_template.dev_max
-	    || !scsi_CDs[MINOR(cdi->dev)].device) {
+	if (minor(cdi->dev) >= sr_template.dev_max
+	    || !scsi_CDs[minor(cdi->dev)].device) {
 		return -ENXIO;	/* No such device */
 	}
 	/*
 	 * If the device is in error recovery, wait until it is done.
 	 * If the device is offline, then disallow any access to it.
 	 */
-	if (!scsi_block_when_processing_errors(scsi_CDs[MINOR(cdi->dev)].device)) {
+	if (!scsi_block_when_processing_errors(scsi_CDs[minor(cdi->dev)].device)) {
 		return -ENXIO;
 	}
-	scsi_CDs[MINOR(cdi->dev)].device->access_count++;
-	if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)
-		__MOD_INC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);
+	scsi_CDs[minor(cdi->dev)].device->access_count++;
+	if (scsi_CDs[minor(cdi->dev)].device->host->hostt->module)
+		__MOD_INC_USE_COUNT(scsi_CDs[minor(cdi->dev)].device->host->hostt->module);
 	if (sr_template.module)
 		__MOD_INC_USE_COUNT(sr_template.module);
 
@@ -421,8 +421,8 @@
 	 * this is the case, and try again.
 	 */
 
-	if (scsi_CDs[MINOR(cdi->dev)].needs_sector_size)
-		get_sectorsize(MINOR(cdi->dev));
+	if (scsi_CDs[minor(cdi->dev)].needs_sector_size)
+		get_sectorsize(minor(cdi->dev));
 
 	return 0;
 }
@@ -671,13 +671,13 @@
  */
 static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
 {
-	Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
+	Scsi_Device *device = scsi_CDs[minor(cdi->dev)].device;
 
 	/* set the LUN */
 	if (device->scsi_level <= SCSI_2)
 		cgc->cmd[1] |= device->lun << 5;
 
-	cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
+	cgc->stat = sr_do_ioctl(minor(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
 
 	return cgc->stat;
 }
@@ -766,7 +766,7 @@
 
 		scsi_CDs[i].cdi.ops = &sr_dops;
 		scsi_CDs[i].cdi.handle = &scsi_CDs[i];
-		scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR, i);
+		scsi_CDs[i].cdi.dev = mk_kdev(MAJOR_NR, i);
 		scsi_CDs[i].cdi.mask = 0;
 		scsi_CDs[i].cdi.capacity = 1;
 		/*
@@ -809,7 +809,7 @@
 			 * the device.
 			 * We should be kind to our buffer cache, however.
 			 */
-			invalidate_device(MKDEV(MAJOR_NR, i), 0);
+			invalidate_device(mk_kdev(MAJOR_NR, i), 0);
 
 			/*
 			 * Reset things back to a sane state so that one can
diff -urN linux-2.5.2-pre6/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- linux-2.5.2-pre6/drivers/scsi/sr_ioctl.c	Sun Dec 16 12:20:21 2001
+++ linux/drivers/scsi/sr_ioctl.c	Thu Jan  3 14:10:37 2002
@@ -68,7 +68,7 @@
 	sr_cmd[6] = trk1_te.cdte_addr.msf.minute;
 	sr_cmd[7] = trk1_te.cdte_addr.msf.second;
 	sr_cmd[8] = trk1_te.cdte_addr.msf.frame;
-	return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+	return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
 }
 
 /* We do our own retries because we want to know what the specific
@@ -206,17 +206,17 @@
 	u_char sr_cmd[10];
 
 	sr_cmd[0] = GPCMD_START_STOP_UNIT;
-	sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
-	            ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+	sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+	            ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
 	sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
 	sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
 
-	return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+	return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
 }
 
 int sr_lock_door(struct cdrom_device_info *cdi, int lock)
 {
-	return scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+	return scsi_ioctl(scsi_CDs[minor(cdi->dev)].device,
 		      lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
 			  0);
 }
@@ -227,7 +227,7 @@
 		/* we have no changer support */
 		return -EINVAL;
 	}
-	if (0 == test_unit_ready(MINOR(cdi->dev)))
+	if (0 == test_unit_ready(minor(cdi->dev)))
 		return CDS_DISC_OK;
 
 	return CDS_TRAY_OPEN;
@@ -256,7 +256,7 @@
 	if (!have_datatracks)
 		return CDS_AUDIO;
 
-	if (scsi_CDs[MINOR(cdi->dev)].xa_flag)
+	if (scsi_CDs[minor(cdi->dev)].xa_flag)
 		return CDS_XA_2_1;
 	else
 		return CDS_DATA_1;
@@ -265,9 +265,9 @@
 int sr_get_last_session(struct cdrom_device_info *cdi,
 			struct cdrom_multisession *ms_info)
 {
-	ms_info->addr.lba = scsi_CDs[MINOR(cdi->dev)].ms_offset;
-	ms_info->xa_flag = scsi_CDs[MINOR(cdi->dev)].xa_flag ||
-	    (scsi_CDs[MINOR(cdi->dev)].ms_offset > 0);
+	ms_info->addr.lba = scsi_CDs[minor(cdi->dev)].ms_offset;
+	ms_info->xa_flag = scsi_CDs[minor(cdi->dev)].xa_flag ||
+	    (scsi_CDs[minor(cdi->dev)].ms_offset > 0);
 
 	return 0;
 }
@@ -279,8 +279,8 @@
 	int result;
 
 	sr_cmd[0] = GPCMD_READ_SUBCHANNEL;
-	sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
-	            ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+	sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+	            ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
 	sr_cmd[2] = 0x40;	/* I do want the subchannel info */
 	sr_cmd[3] = 0x02;	/* Give me medium catalog number info */
 	sr_cmd[4] = sr_cmd[5] = 0;
@@ -289,7 +289,7 @@
 	sr_cmd[8] = 24;
 	sr_cmd[9] = 0;
 
-	result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
+	result = sr_do_ioctl(minor(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
 
 	memcpy(mcn->medium_catalog_number, buffer + 9, 13);
 	mcn->medium_catalog_number[13] = 0;
@@ -314,12 +314,12 @@
 
 	memset(sr_cmd, 0, MAX_COMMAND_SIZE);
 	sr_cmd[0] = GPCMD_SET_SPEED;	/* SET CD SPEED */
-	sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
-	            ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+	sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+	            ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
 	sr_cmd[2] = (speed >> 8) & 0xff;	/* MSB for speed (in kbytes/sec) */
 	sr_cmd[3] = speed & 0xff;	/* LSB */
 
-	if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
+	if (sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
 		return -EIO;
 	return 0;
 }
@@ -333,7 +333,7 @@
 int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 {
 	u_char sr_cmd[10];
-	int result, target = MINOR(cdi->dev);
+	int result, target = minor(cdi->dev);
 	unsigned char buffer[32];
 
 	memset(sr_cmd, 0, sizeof(sr_cmd));
@@ -541,7 +541,7 @@
 {
 	int target;
 
-	target = MINOR(cdi->dev);
+	target = minor(cdi->dev);
 
 	switch (cmd) {
 	case BLKGETSIZE:
diff -urN linux-2.5.2-pre6/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c
--- linux-2.5.2-pre6/drivers/scsi/sr_vendor.c	Sun Dec 16 12:20:21 2001
+++ linux/drivers/scsi/sr_vendor.c	Thu Jan  3 14:10:37 2002
@@ -158,7 +158,7 @@
 	unsigned char cmd[MAX_COMMAND_SIZE];	/* the scsi-command */
 	int rc, no_multi, minor;
 
-	minor = MINOR(cdi->dev);
+	minor = minor(cdi->dev);
 	if (scsi_CDs[minor].cdi.mask & CDC_MULTI_SESSION)
 		return 0;
 
diff -urN linux-2.5.2-pre6/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- linux-2.5.2-pre6/drivers/scsi/u14-34f.c	Wed Dec 12 09:20:22 2001
+++ linux/drivers/scsi/u14-34f.c	Thu Jan  3 14:10:37 2002
@@ -1,6 +1,13 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      01 Jan 2002 Rev. 7.20 for linux 2.5.1
+ *        + Use the dynamic DMA mapping API.
+ *
+ *      19 Dec 2001 Rev. 7.02 for linux 2.5.1
+ *        + Use SCpnt->sc_data_direction if set.
+ *        + Use sglist.page instead of sglist.address.
+ *
  *      11 Dec 2001 Rev. 7.00 for linux 2.5.1
  *        + Use host->host_lock instead of io_request_lock.
  *
@@ -186,7 +193,7 @@
  *
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *  Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
+ *  Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com)
  *
  *  Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
  *
@@ -377,6 +384,7 @@
 #include "u14-34f.h"
 #include <linux/stat.h>
 #include <linux/config.h>
+#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
@@ -483,13 +491,13 @@
    unsigned char clink_id;              /* identifies command in chain */
    unsigned char use_sg;                /* (if sg is set) 8 bytes per list */
    unsigned char sense_len;
-   unsigned char scsi_cdbs_len;         /* 6, 10, or 12 */
-   unsigned char scsi_cdbs[12];         /* SCSI commands */
+   unsigned char cdb_len;               /* 6, 10, or 12 */
+   unsigned char cdb[12];               /* SCSI Command Descriptor Block */
    unsigned char adapter_status;        /* non-zero indicates HA error */
    unsigned char target_status;         /* non-zero indicates target error */
    unsigned int sense_addr PACKED;
    Scsi_Cmnd *SCpnt;
-   unsigned int index;                  /* cp index */
+   unsigned int cpp_index;              /* cp index */
    struct sg_list *sglist;
    };
 
@@ -507,6 +515,7 @@
    unsigned int retries;                /* Number of internal retries */
    unsigned long last_retried_pid;      /* Pid of last retried command */
    unsigned char subversion;            /* Bus type, either ISA or ESA */
+   struct pci_dev *pdev;                /* Always NULL */
    unsigned char heads;
    unsigned char sectors;
 
@@ -537,21 +546,11 @@
 #define HD(board) ((struct hostdata *) &sh[board]->hostdata)
 #define BN(board) (HD(board)->board_name)
 
-#define SWAP_BYTE(x) ((unsigned long)( \
-        (((unsigned long)(x) & 0x000000ffU) << 24) | \
-        (((unsigned long)(x) & 0x0000ff00U) <<  8) | \
-        (((unsigned long)(x) & 0x00ff0000U) >>  8) | \
-        (((unsigned long)(x) & 0xff000000U) >> 24)))
+/* Device is Little Endian */
+#define H2DEV(x) cpu_to_le32(x)
+#define DEV2H(x) le32_to_cpu(x)
 
-#if defined(__BIG_ENDIAN)
-#define H2DEV(x) SWAP_BYTE(x)
-#else
-#define H2DEV(x) (x)
-#endif
-
-#define DEV2H(x) H2DEV(x)
 #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
 
 static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
@@ -653,8 +652,8 @@
    cpp->xdir = DTD_IN;
    cpp->data_address = V2DEV(HD(j)->board_id);
    cpp->data_len = H2DEV(sizeof(HD(j)->board_id));
-   cpp->scsi_cdbs_len = 6;
-   cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;
+   cpp->cdb_len = 6;
+   cpp->cdb[0] = HA_CMD_INQUIRY;
 
    if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
       printk("%s: board_inquiry, adapter busy.\n", BN(j));
@@ -832,14 +831,14 @@
       unsigned long flags;
       scsi_register_blocked_host(sh[j]);
       sh[j]->unchecked_isa_dma = TRUE;
-      
+
       flags=claim_dma_lock();
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
       set_dma_mode(dma_channel, DMA_MODE_CASCADE);
       enable_dma(dma_channel);
       release_dma_lock(flags);
-      
+
       sh[j]->dma_channel = dma_channel;
       sprintf(BN(j), "U14F%d", j);
       bus_type = "ISA";
@@ -879,7 +878,7 @@
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
 
    if (j == 0) {
-      printk("UltraStor 14F/34F: Copyright (C) 1994-2001 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994-2002 Dario Ballabio.\n");
       printk("%s config options -> of:%c, lc:%c, mq:%d, et:%c.\n",
              driver_name, YESNO(have_old_firmware), YESNO(linked_comm),
              max_queue_depth, YESNO(ext_tran));
@@ -949,8 +948,7 @@
    return 1;
 }
 
-int u14_34f_detect(Scsi_Host_Template *tpnt)
-{
+int u14_34f_detect(Scsi_Host_Template *tpnt) {
    unsigned int j = 0, k;
 
    tpnt->proc_name = "u14-34f";
@@ -978,26 +976,95 @@
    return j;
 }
 
-static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
-   unsigned int k, data_len = 0;
+static inline void map_dma(unsigned int i, unsigned int j) {
+   unsigned int data_len = 0;
+   unsigned int k, count, pci_dir;
    struct scatterlist *sgpnt;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (SCpnt->sense_buffer)
+      cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer,
+                           sizeof SCpnt->sense_buffer, PCI_DMA_FROMDEVICE));
+
+   cpp->sense_len = sizeof SCpnt->sense_buffer;
+
+   if (!SCpnt->use_sg) {
+
+      if (!SCpnt->request_bufflen)
+         cpp->data_address = V2DEV(SCpnt->request_buffer);
+
+      else if (SCpnt->request_buffer)
+         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
+                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
+
+      cpp->data_len = H2DEV(SCpnt->request_bufflen);
+      return;
+      }
 
    sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
 
-   for (k = 0; k < SCpnt->use_sg; k++) {
-      cpp->sglist[k].address = V2DEV(sgpnt[k].address);
-      cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
+   for (k = 0; k < count; k++) {
+      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
+      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
       data_len += sgpnt[k].length;
       }
 
+   cpp->sg = TRUE;
    cpp->use_sg = SCpnt->use_sg;
    cpp->data_address = V2DEV(cpp->sglist);
    cpp->data_len = H2DEV(data_len);
 }
 
-static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
-   unsigned int i, j, k;
+static void unmap_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                       DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                       DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static void sync_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
    struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                          DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, 
+                         SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                          DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
+   unsigned int k;
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
@@ -1008,9 +1075,51 @@
    static const unsigned char data_none_cmds[] = {
       0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e,
       0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47,
-      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5
+      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00
       };
 
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+
+   if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
+      cpp->xdir = DTD_IN;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {
+      cpp->xdir = DTD_OUT;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) {
+      cpp->xdir = DTD_NONE;
+      return;
+      }
+
+   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) 
+      panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
+
+   cpp->xdir = DTD_IN;
+
+   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
+      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
+         cpp->xdir = DTD_OUT;
+         break;
+         }
+
+   if (cpp->xdir == DTD_IN)
+      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
+         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
+            cpp->xdir = DTD_NONE;
+            break;
+            }
+
+}
+
+static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
+   unsigned int i, j, k;
+   struct mscp *cpp;
+
    /* j is the board number */
    j = ((struct hostdata *) SCpnt->host->hostdata)->board_number;
 
@@ -1042,47 +1151,26 @@
 
    memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
    SCpnt->scsi_done = done;
-   cpp->index = i;
-   SCpnt->host_scribble = (unsigned char *) &cpp->index;
+   cpp->cpp_index = i;
+   SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
                         BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
-   cpp->xdir = DTD_IN;
-
-   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
-      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-         cpp->xdir = DTD_OUT;
-         break;
-         }
-
-   if (cpp->xdir == DTD_IN)
-      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
-         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
-            cpp->xdir = DTD_NONE;
-            break;
-            }
-
    cpp->opcode = OP_SCSI;
    cpp->channel = SCpnt->channel;
    cpp->target = SCpnt->target;
    cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
-   cpp->sense_len = sizeof SCpnt->sense_buffer;
+   cpp->cdb_len = SCpnt->cmd_len;
+   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
-   if (SCpnt->use_sg) {
-      cpp->sg = TRUE;
-      build_sg_list(cpp, SCpnt);
-      }
-   else {
-      cpp->data_address = V2DEV(SCpnt->request_buffer);
-      cpp->data_len = H2DEV(SCpnt->request_bufflen);
-      }
+   /* Use data transfer direction SCpnt->sc_data_direction */
+   scsi_to_dev_dir(i, j);
 
-   cpp->scsi_cdbs_len = SCpnt->cmd_len;
-   memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len);
+   /* Map DMA buffers and SG list */
+   map_dma(i, j);
 
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type)) {
@@ -1092,6 +1180,7 @@
       }
 
    if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+      unmap_dma(i, j);
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
@@ -1154,6 +1243,7 @@
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
 
       if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {
+         unmap_dma(i, j);
          SCarg->host_scribble = NULL;
          HD(j)->cp_stat[i] = FREE;
          printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",
@@ -1175,6 +1265,7 @@
       }
 
    if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+      unmap_dma(i, j);
       SCarg->result = DID_ABORT << 16;
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
@@ -1272,18 +1363,19 @@
 #endif
 
    HD(j)->in_reset = TRUE;
-   
+
    spin_unlock_irq(&sh[j]->host_lock);
    time = jiffies;
    while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
    spin_lock_irq(&sh[j]->host_lock);
-   
+
    printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
 
    for (i = 0; i < sh[j]->can_queue; i++) {
 
       if (HD(j)->cp_stat[i] == IN_RESET) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1296,6 +1388,7 @@
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1536,23 +1629,25 @@
       return;
       }
 
-   spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
-   cpp = spp;
+   ret = inl(sh[j]->io_port + REG_ICM);
 
    /* Clear interrupt pending flag */
    outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
 
-#if defined(DEBUG_GENERATE_ABORTS)
-   if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;
-#endif
-
    /* Find the mailbox to be serviced on this board */
-   i = cpp - HD(j)->cp;
+   for (i = 0; i < sh[j]->can_queue; i++)
+      if (V2DEV(&(HD(j)->cp[i])) == ret) break;
 
-   if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
-                                     || i >= sh[j]->can_queue)
+   if (i >= sh[j]->can_queue)
       panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
-            (void *)ret, HD(j)->cp);
+            (void *)ret, (void *)V2DEV(HD(j)->cp));
+
+   cpp = &(HD(j)->cp[i]);
+   spp = cpp;
+
+#if defined(DEBUG_GENERATE_ABORTS)
+   if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;
+#endif
 
    if (HD(j)->cp_stat[i] == IGNORE) {
       HD(j)->cp_stat[i] = FREE;
@@ -1588,6 +1683,8 @@
       panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
             BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
+   sync_dma(i, j);
+
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type))
       flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
@@ -1705,6 +1802,8 @@
              SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
              reg, HD(j)->iocount);
 
+   unmap_dma(i, j);
+
    /* Set the command state to inactive */
    SCpnt->host_scribble = NULL;
 
@@ -1736,9 +1835,7 @@
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   if( sh[j]->unchecked_isa_dma ) {
-	   scsi_deregister_blocked_host(sh[j]);
-   }
+   if(sh[j]->unchecked_isa_dma) scsi_deregister_blocked_host(sh[j]);
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
diff -urN linux-2.5.2-pre6/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- linux-2.5.2-pre6/drivers/scsi/u14-34f.h	Wed Dec 12 09:20:22 2001
+++ linux/drivers/scsi/u14-34f.h	Thu Jan  3 14:10:37 2002
@@ -13,7 +13,7 @@
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "7.00.00"
+#define U14_34F_VERSION "7.20.00"
 
 #define ULTRASTOR_14_34F {                                                   \
                 name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
diff -urN linux-2.5.2-pre6/drivers/sound/cs4281/cs4281m.c linux/drivers/sound/cs4281/cs4281m.c
--- linux-2.5.2-pre6/drivers/sound/cs4281/cs4281m.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/cs4281/cs4281m.c	Thu Jan  3 14:10:37 2002
@@ -2569,7 +2569,7 @@
 
 static int cs4281_open_mixdev(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct cs4281_state *s=NULL;
 	struct list_head *entry;
 
@@ -3625,7 +3625,7 @@
 
 static int cs4281_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct cs4281_state *s=NULL;
 	struct list_head *entry;
 
@@ -3966,7 +3966,7 @@
 static int cs4281_midi_open(struct inode *inode, struct file *file)
 {
 	unsigned long flags, temp1;
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct cs4281_state *s=NULL;
 	struct list_head *entry;
 	list_for_each(entry, &cs4281_devs)
diff -urN linux-2.5.2-pre6/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c
--- linux-2.5.2-pre6/drivers/sound/cs46xx.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/cs46xx.c	Thu Jan  3 14:10:37 2002
@@ -1835,7 +1835,7 @@
 
 static int cs_midi_open(struct inode *inode, struct file *file)
 {
-        int minor = MINOR(inode->i_rdev);
+        unsigned int minor = minor(inode->i_rdev);
         struct cs_card *card=NULL;
         unsigned long flags;
 	struct list_head *entry;
@@ -3198,7 +3198,7 @@
 	struct cs_state *state = NULL;
 	struct dmabuf *dmabuf = NULL;
 	struct list_head *entry;
-        int minor = MINOR(inode->i_rdev);
+        unsigned int minor = minor(inode->i_rdev);
 	int ret=0;
 	unsigned int tmp;
 
@@ -4047,7 +4047,7 @@
 static int cs_open_mixdev(struct inode *inode, struct file *file)
 {
 	int i=0;
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct cs_card *card=NULL;
 	struct list_head *entry;
 	unsigned int tmp;
@@ -4094,7 +4094,7 @@
 
 static int cs_release_mixdev(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct cs_card *card=NULL;
 	struct list_head *entry;
 	int i;
diff -urN linux-2.5.2-pre6/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- linux-2.5.2-pre6/drivers/sound/es1370.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/es1370.c	Thu Jan  3 14:10:37 2002
@@ -1029,7 +1029,7 @@
 
 static int es1370_open_mixdev(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct list_head *list;
 	struct es1370_state *s;
 
@@ -1729,7 +1729,7 @@
 
 static int es1370_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	struct list_head *list;
@@ -2165,7 +2165,7 @@
 
 static int es1370_open_dac(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	struct list_head *list;
@@ -2408,7 +2408,7 @@
 
 static int es1370_midi_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	struct list_head *list;
diff -urN linux-2.5.2-pre6/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- linux-2.5.2-pre6/drivers/sound/esssolo1.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/esssolo1.c	Thu Jan  3 14:10:37 2002
@@ -913,7 +913,7 @@
 
 static int solo1_open_mixdev(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct solo1_state *s = NULL;
 	struct pci_dev *pci_dev;
 
@@ -1590,7 +1590,7 @@
 
 static int solo1_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = NULL;
 	struct pci_dev *pci_dev;
@@ -1879,7 +1879,7 @@
 
 static int solo1_midi_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	struct solo1_state *s = NULL;
@@ -2105,7 +2105,7 @@
 
 static int solo1_dmfm_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	struct solo1_state *s = NULL;
 	struct pci_dev *pci_dev;
diff -urN linux-2.5.2-pre6/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c
--- linux-2.5.2-pre6/drivers/sound/i810_audio.c	Fri Nov  9 14:07:41 2001
+++ linux/drivers/sound/i810_audio.c	Thu Jan  3 14:10:37 2002
@@ -2345,7 +2345,7 @@
 static int i810_open_mixdev(struct inode *inode, struct file *file)
 {
 	int i;
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct i810_card *card = devs;
 
 	for (card = devs; card != NULL; card = card->next)
diff -urN linux-2.5.2-pre6/drivers/sound/maestro.c linux/drivers/sound/maestro.c
--- linux-2.5.2-pre6/drivers/sound/maestro.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/maestro.c	Thu Jan  3 14:10:37 2002
@@ -2126,7 +2126,7 @@
 /* --------------------------------------------------------------------- */
 static int ess_open_mixdev(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct ess_card *card = NULL;
 	struct pci_dev *pdev;
 	struct pci_driver *drvr;
@@ -2967,7 +2967,7 @@
 static int 
 ess_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct ess_state *s = NULL;
 	unsigned char fmtm = ~0, fmts = 0;
 	struct pci_dev *pdev;
diff -urN linux-2.5.2-pre6/drivers/sound/maestro3.c linux/drivers/sound/maestro3.c
--- linux-2.5.2-pre6/drivers/sound/maestro3.c	Sun Nov 25 10:17:47 2001
+++ linux/drivers/sound/maestro3.c	Thu Jan  3 14:10:37 2002
@@ -1969,7 +1969,7 @@
 
 static int m3_open(struct inode *inode, struct file *file)
 {
-    int minor = MINOR(inode->i_rdev);
+    unsigned int minor = minor(inode->i_rdev);
     struct m3_card *c;
     struct m3_state *s = NULL;
     int i;
@@ -2137,7 +2137,7 @@
 /* OSS /dev/mixer file operation methods */
 static int m3_open_mixdev(struct inode *inode, struct file *file)
 {
-    int minor = MINOR(inode->i_rdev);
+    unsigned int minor = minor(inode->i_rdev);
     struct m3_card *card = devs;
 
     for (card = devs; card != NULL; card = card->next) {
diff -urN linux-2.5.2-pre6/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- linux-2.5.2-pre6/drivers/sound/soundcard.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/sound/soundcard.c	Thu Jan  3 14:10:37 2002
@@ -144,7 +144,7 @@
 
 static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+	int dev = minor(file->f_dentry->d_inode->i_rdev);
 	int ret = -EINVAL;
 
 	/*
@@ -177,7 +177,7 @@
 
 static ssize_t sound_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
-	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+	int dev = minor(file->f_dentry->d_inode->i_rdev);
 	int ret = -EINVAL;
 	
 	lock_kernel();
@@ -204,7 +204,7 @@
 
 static int sound_open(struct inode *inode, struct file *file)
 {
-	int dev = MINOR(inode->i_rdev);
+	int dev = minor(inode->i_rdev);
 	int retval;
 
 	DEB(printk("sound_open(dev=%d)\n", dev));
@@ -255,7 +255,7 @@
 
 static int sound_release(struct inode *inode, struct file *file)
 {
-	int dev = MINOR(inode->i_rdev);
+	int dev = minor(inode->i_rdev);
 
 	lock_kernel();
 	DEB(printk("sound_release(dev=%d)\n", dev));
@@ -341,7 +341,7 @@
 		       unsigned int cmd, unsigned long arg)
 {
 	int err, len = 0, dtype;
-	int dev = MINOR(inode->i_rdev);
+	int dev = minor(inode->i_rdev);
 
 	if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) {
 		/*
@@ -404,7 +404,7 @@
 static unsigned int sound_poll(struct file *file, poll_table * wait)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	int dev = MINOR(inode->i_rdev);
+	int dev = minor(inode->i_rdev);
 
 	DEB(printk("sound_poll(dev=%d)\n", dev));
 	switch (dev & 0x0f) {
@@ -428,7 +428,7 @@
 	int dev_class;
 	unsigned long size;
 	struct dma_buffparms *dmap = NULL;
-	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+	int dev = minor(file->f_dentry->d_inode->i_rdev);
 
 	dev_class = dev & 0x0f;
 	dev >>= 4;
diff -urN linux-2.5.2-pre6/drivers/usb/Config.in linux/drivers/usb/Config.in
--- linux-2.5.2-pre6/drivers/usb/Config.in	Sat Dec  8 20:28:44 2001
+++ linux/drivers/usb/Config.in	Thu Jan  3 14:10:37 2002
@@ -18,7 +18,8 @@
    bool '  Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
 fi
 
-comment 'USB Controllers'
+comment 'USB Host Controller Drivers'
+source drivers/usb/hcd/Config.in
 if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
    dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
 fi
@@ -72,6 +73,8 @@
    dep_tristate '  USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
+   dep_tristate '  USB STV680 (Pencam) Camera support' CONFIG_USB_STV680 $CONFIG_USB $CONFIG_VIDEO_DEV
+   dep_tristate '  USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
    dep_tristate '  D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
 fi
diff -urN linux-2.5.2-pre6/drivers/usb/Makefile linux/drivers/usb/Makefile
--- linux-2.5.2-pre6/drivers/usb/Makefile	Fri Oct  5 12:04:51 2001
+++ linux/drivers/usb/Makefile	Thu Jan  3 14:10:37 2002
@@ -10,19 +10,13 @@
 
 # Objects that export symbols.
 
-export-objs		:= usb.o
+export-objs		:= usb.o hcd.o ov511.o pwc-uncompress.o
 
 # Multipart objects.
 
-list-multi		:= usbcore.o hid.o
-usbcore-objs		:= usb.o usb-debug.o hub.o
+list-multi		:= usbcore.o hid.o pwc.o
+usbcore-objs		:= usb.o usb-debug.o hub.o hcd.o
 hid-objs		:= hid-core.o hid-input.o
-
-ifneq ($(CONFIG_USB_PWC),n)
-	export-objs		+= pwc-uncompress.o
-	list-multi		+= pwc.o
-endif
-
 pwc-objs		:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
 
 
@@ -65,8 +59,10 @@
 obj-$(CONFIG_USB_MDC800)	+= mdc800.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
 obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
+obj-$(CONFIG_USB_VICAM)		+= vicam.o
 obj-$(CONFIG_USB_OV511)		+= ov511.o
 obj-$(CONFIG_USB_SE401)		+= se401.o
+obj-$(CONFIG_USB_STV680)	+= stv680.o
 obj-$(CONFIG_USB_PEGASUS)	+= pegasus.o
 obj-$(CONFIG_USB_CATC)		+= catc.o
 obj-$(CONFIG_USB_KAWETH)        += kaweth.o
@@ -79,9 +75,15 @@
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
 
 # Object files in subdirectories
+mod-subdirs	:= serial hcd
 
+subdir-$(CONFIG_USB_EHCI_HCD)	+= hcd
 subdir-$(CONFIG_USB_SERIAL)	+= serial
 subdir-$(CONFIG_USB_STORAGE)	+= storage
+
+ifeq ($(CONFIG_USB_EHCI_HCD),y)
+	obj-y += hcd/ehci-hcd.o
+endif
 
 ifeq ($(CONFIG_USB_SERIAL),y)
 	obj-y += serial/usb-serial.o
diff -urN linux-2.5.2-pre6/drivers/usb/acm.c linux/drivers/usb/acm.c
--- linux-2.5.2-pre6/drivers/usb/acm.c	Fri Oct  5 12:06:08 2001
+++ linux/drivers/usb/acm.c	Thu Jan  3 14:10:37 2002
@@ -297,7 +297,7 @@
 
 static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 {
-	struct acm *acm = acm_table[MINOR(tty->device)];
+	struct acm *acm = acm_table[minor(tty->device)];
 
 	if (!acm || !acm->dev) return -EINVAL;
 
diff -urN linux-2.5.2-pre6/drivers/usb/audio.c linux/drivers/usb/audio.c
--- linux-2.5.2-pre6/drivers/usb/audio.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/usb/audio.c	Thu Jan  3 14:10:37 2002
@@ -1947,7 +1947,7 @@
 
 static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct list_head *devs, *mdevs;
 	struct usb_mixerdev *ms;
 	struct usb_audio_state *s;
@@ -2621,7 +2621,7 @@
 
 static int usb_audio_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	struct list_head *devs, *adevs;
 	struct usb_audiodev *as;
diff -urN linux-2.5.2-pre6/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c
--- linux-2.5.2-pre6/drivers/usb/bluetooth.c	Sat Dec  8 20:28:44 2001
+++ linux/drivers/usb/bluetooth.c	Thu Jan  3 14:10:37 2002
@@ -360,7 +360,7 @@
 	tty->driver_data = NULL;
 
 	/* get the bluetooth object associated with this tty pointer */
-	bluetooth = get_bluetooth_by_minor (MINOR(tty->device));
+	bluetooth = get_bluetooth_by_minor (minor(tty->device));
 
 	if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
 		return -ENODEV;
diff -urN linux-2.5.2-pre6/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- linux-2.5.2-pre6/drivers/usb/dabusb.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/usb/dabusb.c	Thu Jan  3 14:10:37 2002
@@ -579,7 +579,7 @@
 
 static int dabusb_open (struct inode *inode, struct file *file)
 {
-	int devnum = MINOR (inode->i_rdev);
+	int devnum = minor (inode->i_rdev);
 	pdabusb_t s;
 
 	if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
diff -urN linux-2.5.2-pre6/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c
--- linux-2.5.2-pre6/drivers/usb/dc2xx.c	Sat Dec  8 20:28:45 2001
+++ linux/drivers/usb/dc2xx.c	Thu Jan  3 14:10:37 2002
@@ -298,7 +298,7 @@
 	int			value = 0;
 
 	down (&state_table_mutex);
-	subminor = MINOR (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
+	subminor = minor (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
 	if (subminor < 0 || subminor >= MAX_CAMERAS
 			|| !(camera = minor_data [subminor])) {
 		up (&state_table_mutex);
diff -urN linux-2.5.2-pre6/drivers/usb/hcd/Config.in linux/drivers/usb/hcd/Config.in
--- linux-2.5.2-pre6/drivers/usb/hcd/Config.in	Thu Jan  3 14:10:33 2002
+++ linux/drivers/usb/hcd/Config.in	Thu Jan  3 14:10:37 2002
@@ -1,7 +1,7 @@
 #
 # USB Host Controller Drivers
 #
-dep_tristate '  EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
-# dep_tristate '  OHCI HCD support (EXPERIMENTAL)' CONFIG_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
-# dep_tristate '  UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate '  EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+# dep_tristate '  OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+# dep_tristate '  UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
 
diff -urN linux-2.5.2-pre6/drivers/usb/hiddev.c linux/drivers/usb/hiddev.c
--- linux-2.5.2-pre6/drivers/usb/hiddev.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/usb/hiddev.c	Thu Jan  3 14:10:38 2002
@@ -218,7 +218,7 @@
 static int hiddev_open(struct inode * inode, struct file * file) {
 	struct hiddev_list *list;
 
-	int i = MINOR(inode->i_rdev) - HIDDEV_MINOR_BASE;
+	int i = minor(inode->i_rdev) - HIDDEV_MINOR_BASE;
 
 	if (i >= HIDDEV_MINORS || !hiddev_table[i])
 		return -ENODEV;
diff -urN linux-2.5.2-pre6/drivers/usb/printer.c linux/drivers/usb/printer.c
--- linux-2.5.2-pre6/drivers/usb/printer.c	Tue Oct  9 15:15:02 2001
+++ linux/drivers/usb/printer.c	Thu Jan  3 14:10:38 2002
@@ -201,7 +201,7 @@
 
 static int usblp_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev) - USBLP_MINOR_BASE;
+	int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
 	struct usblp *usblp;
 	int retval;
 
diff -urN linux-2.5.2-pre6/drivers/usb/scanner.c linux/drivers/usb/scanner.c
--- linux-2.5.2-pre6/drivers/usb/scanner.c	Sat Dec  8 20:28:44 2001
+++ linux/drivers/usb/scanner.c	Thu Jan  3 14:10:38 2002
@@ -365,7 +365,7 @@
 	struct scn_usb_data *scn;
 	struct usb_device *dev;
 
-	kdev_t scn_minor;
+	int scn_minor;
 
 	int err=0;
 
@@ -432,7 +432,7 @@
 {
 	struct scn_usb_data *scn;
 
-	kdev_t scn_minor;
+	int scn_minor;
 
 	scn_minor = USB_SCN_MINOR (inode);
 
@@ -469,7 +469,7 @@
 	ssize_t bytes_written = 0; /* Overall count of bytes written */
 	ssize_t ret = 0;
 
-	kdev_t scn_minor;
+	int scn_minor;
 
 	int this_write;		/* Number of bytes to write */
 	int partial;		/* Number of bytes successfully written */
@@ -556,8 +556,7 @@
 	ssize_t bytes_read;	/* Overall count of bytes_read */
 	ssize_t ret;
 
-	kdev_t scn_minor;
-
+	int scn_minor;
 	int partial;		/* Number of bytes successfully read */
 	int this_read;		/* Max number of bytes to read */
 	int result;
@@ -671,7 +670,7 @@
 {
 	struct usb_device *dev;
 
-	kdev_t scn_minor;
+	int scn_minor;
 
 	scn_minor = USB_SCN_MINOR(inode);
 
@@ -810,8 +809,7 @@
 
 	int ep_cnt;
 	int ix;
-
-	kdev_t scn_minor;
+	int scn_minor;
 
 	char valid_device = 0;
 	char have_bulk_in, have_bulk_out, have_intr;
diff -urN linux-2.5.2-pre6/drivers/usb/scanner.h linux/drivers/usb/scanner.h
--- linux-2.5.2-pre6/drivers/usb/scanner.h	Sat Dec  8 20:28:44 2001
+++ linux/drivers/usb/scanner.h	Thu Jan  3 14:10:38 2002
@@ -203,7 +203,7 @@
 #define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
 #define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
 
-#define USB_SCN_MINOR(X) MINOR((X)->i_rdev) - SCN_BASE_MNR
+#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
 
 #ifdef DEBUG
 #define SCN_DEBUG(X) X
@@ -243,7 +243,7 @@
 	devfs_handle_t devfs;	/* devfs device */
 	struct urb scn_irq;
 	unsigned int ifnum;	/* Interface number of the USB device */
-	kdev_t scn_minor;	/* Scanner minor - used in disconnect() */
+	int scn_minor;		/* Scanner minor - used in disconnect() */
 	unsigned char button;	/* Front panel buffer */
 	char isopen;		/* Not zero if the device is open */
 	char present;		/* Not zero if device is present */
diff -urN linux-2.5.2-pre6/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in
--- linux-2.5.2-pre6/drivers/usb/serial/Config.in	Wed Oct 17 14:35:17 2001
+++ linux/drivers/usb/serial/Config.in	Thu Jan  3 14:10:38 2002
@@ -15,6 +15,7 @@
 dep_tristate '  USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+dep_tristate '  USB Compaq iPAQ Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
 dep_tristate '  USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
@@ -28,6 +29,7 @@
    dep_mbool '    USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W $CONFIG_USB_SERIAL_KEYSPAN
    dep_mbool '    USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W $CONFIG_USB_SERIAL_KEYSPAN
 dep_tristate '  USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KLSI $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
diff -urN linux-2.5.2-pre6/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile
--- linux-2.5.2-pre6/drivers/usb/serial/Makefile	Tue Oct  9 15:15:02 2001
+++ linux/drivers/usb/serial/Makefile	Thu Jan  3 14:10:38 2002
@@ -8,6 +8,7 @@
 
 obj-$(CONFIG_USB_SERIAL)                        += usbserial.o
 obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o
+obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o
 obj-$(CONFIG_USB_SERIAL_FTDI_SIO)		+= ftdi_sio.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)		+= keyspan_pda.o
@@ -22,7 +23,8 @@
 obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
 obj-$(CONFIG_USB_SERIAL_CYBERJACK)		+= cyberjack.o
 obj-$(CONFIG_USB_SERIAL_IR)			+= ir-usb.o
- 
+obj-$(CONFIG_USB_SERIAL_KLSI)			+= kl5kusb105.o
+
 # Objects that export symbols.
 export-objs	:= usbserial.o
 
diff -urN linux-2.5.2-pre6/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- linux-2.5.2-pre6/drivers/usb/serial/usbserial.c	Sat Dec  8 20:28:45 2001
+++ linux/drivers/usb/serial/usbserial.c	Thu Jan  3 14:10:38 2002
@@ -397,16 +397,16 @@
 static LIST_HEAD(usb_serial_driver_list);
 
 
-static struct usb_serial *get_serial_by_minor (int minor)
+static struct usb_serial *get_serial_by_minor (unsigned int minor)
 {
 	return serial_table[minor];
 }
 
 
-static struct usb_serial *get_free_serial (int num_ports, int *minor)
+static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor)
 {
 	struct usb_serial *serial = NULL;
-	int i, j;
+	unsigned int i, j;
 	int good_spot;
 
 	dbg(__FUNCTION__ " %d", num_ports);
@@ -505,7 +505,7 @@
 {
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
-	int portNumber;
+	unsigned int portNumber;
 	
 	dbg(__FUNCTION__);
 
@@ -513,14 +513,14 @@
 	tty->driver_data = NULL;
 
 	/* get the serial object associated with this tty pointer */
-	serial = get_serial_by_minor (MINOR(tty->device));
+	serial = get_serial_by_minor (minor(tty->device));
 
 	if (serial_paranoia_check (serial, __FUNCTION__)) {
 		return -ENODEV;
 	}
 
 	/* set up our port structure making the tty driver remember our port object, and us it */
-	portNumber = MINOR(tty->device) - serial->minor;
+	portNumber = minor(tty->device) - serial->minor;
 	port = &serial->port[portNumber];
 	tty->driver_data = port;
 	port->tty = tty;
diff -urN linux-2.5.2-pre6/drivers/usb/stv680.c linux/drivers/usb/stv680.c
--- linux-2.5.2-pre6/drivers/usb/stv680.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/stv680.c	Thu Jan  3 14:10:38 2002
@@ -0,0 +1,1633 @@
+/*
+ *  STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
+ *  
+ * Thanks to STMicroelectronics for information on the usb commands, and 
+ * to Steve Miller at STM for his help and encouragement while I was 
+ * writing this driver.
+ *
+ * This driver is based heavily on the 
+ * Endpoints (formerly known as AOX) se401 USB Camera Driver
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * Still somewhat based on the Linux ov511 driver.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * History: 
+ * ver 0.1 October, 2001. Initial attempt. 
+ *
+ * ver 0.2 November, 2001. Fixed asbility to resize, added brightness
+ *                         function, made more stable (?)
+ *
+ * ver 0.21 Nov, 2001.     Added gamma correction and white balance, 
+ *                         due to Alexander Schwartz. Still trying to 
+ *                         improve stablility. Moved stuff into stv680.h
+ *
+ * ver 0.22 Nov, 2001.	   Added sharpen function (by Michael Sweet, 
+ *                         mike@easysw.com) from GIMP, also used in pencam. 
+ *                         Simple, fast, good integer math routine.
+ *
+ * ver 0.23 Dec, 2001 (gkh)
+ * 			   Took out sharpen function, ran code through
+ * 			   Lindent, and did other minor tweaks to get
+ * 			   things to work properly with 2.5.1
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/wrapper.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/videodev.h>
+#include <linux/usb.h>
+
+#include "stv680.h"
+
+static int video_nr = -1;
+static int swapRGB = 0;
+
+static unsigned int debug = 0;
+
+#define PDEBUG(level, fmt, args...) \
+	do { \
+	if (debug >= level)	\
+		info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args);	\
+	} while (0)
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.23"
+#define DRIVER_AUTHOR "Kevin Sisson <kjsisson@bellsouth.net>"
+#define DRIVER_DESC "STV0680 USB Camera Driver"
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_LICENSE ("GPL");
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "Debug enabled or not");
+MODULE_PARM (swapRGB, "i");
+MODULE_PARM_DESC (swapRGB, "Swap red and blue, e.g., for xawtv");
+MODULE_PARM (video_nr, "i");
+EXPORT_NO_SYMBOLS;
+
+/********************************************************************
+ *
+ * Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the ov511 driver -claudio
+ *
+ * Same for the se401 driver -Jeroen
+ *
+ * And the STV0680 driver - Kevin
+ ********************************************************************/
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva (pgd_t * pgd, unsigned long adr)
+{
+	unsigned long ret = 0UL;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	if (!pgd_none (*pgd)) {
+		pmd = pmd_offset (pgd, adr);
+		if (!pmd_none (*pmd)) {
+			ptep = pte_offset (pmd, adr);
+			pte = *ptep;
+			if (pte_present (pte)) {
+				ret = (unsigned long) page_address (pte_page (pte));
+				ret |= (adr & (PAGE_SIZE - 1));
+			}
+		}
+	}
+	return ret;
+}
+
+/* Here we want the physical address of the memory. This is used when 
+ * initializing the contents of the area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa (unsigned long adr)
+{
+	unsigned long va, kva, ret;
+
+	va = VMALLOC_VMADDR (adr);
+	kva = uvirt_to_kva (pgd_offset_k (va), va);
+	ret = __pa (kva);
+	return ret;
+}
+
+static void *rvmalloc (unsigned long size)
+{
+	void *mem;
+	unsigned long adr, page;
+
+	/* Round it off to PAGE_SIZE */
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	mem = vmalloc_32 (size);
+	if (!mem)
+		return NULL;
+
+	memset (mem, 0, size);	/* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		page = kvirt_to_pa (adr);
+		mem_map_reserve (virt_to_page (__va (page)));
+		adr += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	return mem;
+}
+
+static void rvfree (void *mem, unsigned long size)
+{
+	unsigned long adr, page;
+
+	if (!mem)
+		return;
+
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		page = kvirt_to_pa (adr);
+		mem_map_unreserve (virt_to_page (__va (page)));
+		adr += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	vfree (mem);
+}
+
+
+/*********************************************************************
+ * pencam read/write functions
+ ********************************************************************/
+
+static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size)
+{
+	int ret = -1;
+
+	switch (set) {
+	case 0:		/*  0xc1  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_rcvctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	case 1:		/*  0x41  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_sndctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	case 2:		/*  0x80  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_rcvctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_IN | USB_RECIP_DEVICE),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	case 3:		/*  0x40  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_sndctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	}
+	if ((ret < 0) && (req != 0x0a)) {
+		PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret);
+	}
+	return ret;
+}
+
+static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate)
+{
+
+	if (usb_set_configuration (dev->udev, configuration) < 0) {
+		PDEBUG (1, "STV(e): FAILED to set configuration %i", configuration);
+		return -1;
+	}
+	if (usb_set_interface (dev->udev, interface, alternate) < 0) {
+		PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate);
+		return -1;
+	}
+	return 0;
+}
+
+static int stv_stop_video (struct usb_stv *dev)
+{
+	int i;
+	unsigned char *buf;
+
+	buf = kmalloc (40, GFP_KERNEL);
+	if (buf == NULL) {
+		PDEBUG (0, "STV(e): Out of (small buf) memory");
+		return -1;
+	}
+
+	/* this is a high priority command; it stops all lower order commands */
+	if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) {
+		i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02);	/* Get Last Error; 2 = busy */
+		PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buf[0], buf[1]);
+	} else {
+		PDEBUG (1, "STV(i): Camera reset to idle mode.");
+	}
+
+	if ((i = stv_set_config (dev, 1, 0, 0)) < 0)
+		PDEBUG (1, "STV(e): Reset config during exit failed");
+
+	/*  get current mode  */
+	buf[0] = 0xf0;
+	if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08)	/* get mode */
+		PDEBUG (0, "STV(e): Stop_video: problem setting original mode");
+	if (dev->origMode != buf[0]) {
+		memset (buf, 0, 8);
+		buf[0] = (unsigned char) dev->origMode;
+		if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) {
+			PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed");
+			i = -1;
+		}
+		buf[0] = 0xf0;
+		i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08);
+		if ((i != 0x08) || (buf[0] != dev->origMode)) {
+			PDEBUG (0, "STV(e): camera NOT set to original resolution.");
+			i = -1;
+		} else
+			PDEBUG (0, "STV(i): Camera set to original resolution");
+	}
+	/* origMode */
+	kfree (buf);
+	return i;
+}
+
+static int stv_set_video_mode (struct usb_stv *dev)
+{
+	int i, stop_video = 1;
+	unsigned char *buf;
+
+	buf = kmalloc (40, GFP_KERNEL);
+	if (buf == NULL) {
+		PDEBUG (0, "STV(e): Out of (small buf) memory");
+		return -1;
+	}
+
+	if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
+		kfree (buf);
+		return i;
+	}
+
+	i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12);
+	if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) {
+		PDEBUG (1, "STV(e): Could not get descriptor 0100.");
+		goto error;
+	}
+
+	/*  set alternate interface 1 */
+	if ((i = stv_set_config (dev, 1, 0, 1)) < 0)
+		goto error;
+
+	if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10)
+		goto error;
+	PDEBUG (1, "STV(i): Setting video mode.");
+	/*  Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240)  */
+	if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) {
+		stop_video = 0;
+		goto error;
+	}
+	goto exit;
+
+error:
+	kfree (buf);
+	if (stop_video == 1)
+		stv_stop_video (dev);
+	return -1;
+
+exit:
+	kfree (buf);
+	return 0;
+}
+
+static int stv_init (struct usb_stv *stv680)
+{
+	int i = 0;
+	unsigned char *buffer;
+	unsigned long int bufsize;
+
+	buffer = kmalloc (40, GFP_KERNEL);
+	if (buffer == NULL) {
+		PDEBUG (0, "STV(e): Out of (small buf) memory");
+		return -1;
+	}
+	memset (buffer, 0, 40);
+	udelay (100);
+
+	/* set config 1, interface 0, alternate 0 */
+	if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
+		kfree (buffer);
+		PDEBUG (0, "STV(e): set config 1,0,0 failed");
+		return -1;
+	}
+	/* ping camera to be sure STV0680 is present */
+	if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02)
+		goto error;
+	if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) {
+		PDEBUG (1, "STV(e): camera ping failed!!");
+		goto error;
+	}
+
+	/* get camera descriptor */
+	if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09)
+		goto error;
+	i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22);
+	if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) {
+		PDEBUG (1, "STV(e): Could not get descriptor 0200.");
+		goto error;
+	}
+	if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02)
+		goto error;
+	if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24)
+		goto error;
+	if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+		goto error;
+
+	stv680->SupportedModes = buffer[7];
+	i = stv680->SupportedModes;
+	stv680->CIF = 0;
+	stv680->VGA = 0;
+	stv680->QVGA = 0;
+	if (i & 1)
+		stv680->CIF = 1;
+	if (i & 2)
+		stv680->VGA = 1;
+	if (i & 8)
+		stv680->QVGA = 1;
+	if (stv680->SupportedModes == 0) {
+		PDEBUG (0, "STV(e): There are NO supported STV680 modes!!");
+		i = -1;
+		goto error;
+	} else {
+		if (stv680->CIF)
+			PDEBUG (0, "STV(i): CIF is supported");
+		if (stv680->QVGA)
+			PDEBUG (0, "STV(i): QVGA is supported");
+	}
+	/* FW rev, ASIC rev, sensor ID  */
+	PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]);
+	PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]);
+	PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4));
+
+	/*  set alternate interface 1 */
+	if ((i = stv_set_config (stv680, 1, 0, 1)) < 0)
+		goto error;
+
+	if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+		goto error;
+	if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08)
+		goto error;
+	i = buffer[3];
+	PDEBUG (0, "STV(i): Camera has %i pictures.", i);
+
+	/*  get current mode */
+	if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08)
+		goto error;
+	stv680->origMode = buffer[0];	/* 01 = VGA, 03 = QVGA, 00 = CIF */
+
+	/* This will attemp CIF mode, if supported. If not, set to QVGA  */
+	memset (buffer, 0, 8);
+	if (stv680->CIF)
+		buffer[0] = 0x00;
+	else if (stv680->QVGA)
+		buffer[0] = 0x03;
+	if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) {
+		PDEBUG (0, "STV(i): Set_Camera_Mode failed");
+		i = -1;
+		goto error;
+	}
+	buffer[0] = 0xf0;
+	stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08);
+	if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) {
+		PDEBUG (0, "STV(e): Error setting camera video mode!");
+		i = -1;
+		goto error;
+	} else {
+		if (buffer[0] == 0) {
+			stv680->VideoMode = 0x0000;
+			PDEBUG (0, "STV(i): Video Mode set to CIF");
+		}
+		if (buffer[0] == 0x03) {
+			stv680->VideoMode = 0x0300;
+			PDEBUG (0, "STV(i): Video Mode set to QVGA");
+		}
+	}
+	if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10)
+		goto error;
+	bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]);
+	stv680->cwidth = (buffer[4] << 8) | (buffer[5]);	/* ->camera = 322, 356, 644  */
+	stv680->cheight = (buffer[6] << 8) | (buffer[7]);	/* ->camera = 242, 292, 484  */
+	stv680->origGain = buffer[12];
+
+	goto exit;
+
+error:
+	i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02);	/* Get Last Error */
+	PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buffer[0], buffer[1]);
+	kfree (buffer);
+	return -1;
+
+exit:
+	kfree (buffer);
+
+	/* video = 320x240, 352x288 */
+	if (stv680->CIF == 1) {
+		stv680->maxwidth = 352;
+		stv680->maxheight = 288;
+		stv680->vwidth = 352;
+		stv680->vheight = 288;
+	}
+	if (stv680->QVGA == 1) {
+		stv680->maxwidth = 320;
+		stv680->maxheight = 240;
+		stv680->vwidth = 320;
+		stv680->vheight = 240;
+	}
+
+	stv680->rawbufsize = bufsize;	/* must be ./. by 8 */
+	stv680->maxframesize = bufsize * 3;	/* RGB size */
+	PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight);
+	PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize);
+
+	/* some default values */
+	stv680->bulk_in_endpointAddr = 0x82;
+	stv680->dropped = 0;
+	stv680->error = 0;
+	stv680->framecount = 0;
+	stv680->readcount = 0;
+	stv680->streaming = 0;
+	/* bright, white, colour, hue, contrast are set by software, not in stv0680 */
+	stv680->brightness = 32767;
+	stv680->chgbright = 0;
+	stv680->whiteness = 0;	/* only for greyscale */
+	stv680->colour = 32767;
+	stv680->contrast = 32767;
+	stv680->hue = 32767;
+	stv680->palette = STV_VIDEO_PALETTE;
+	stv680->depth = 24;	/* rgb24 bits */
+	swapRGB = 0;
+	PDEBUG (1, "STV(i): swapRGB is OFF");
+
+	if (stv_set_video_mode (stv680) < 0) {
+		PDEBUG (0, "STV(e): Could not set video mode in stv_init");
+		return -1;
+	}
+
+	return 0;
+}
+
+/***************** last of pencam  routines  *******************/
+
+/********************************************************************
+ * /proc interface
+ *******************************************************************/
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+static struct proc_dir_entry *stv680_proc_entry = NULL;
+extern struct proc_dir_entry *video_proc_entry;
+
+#define YES_NO(x) ((x) ? "yes" : "no")
+
+static int stv680_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	char *out = page;
+	int len;
+	struct usb_stv *stv680 = data;
+
+	/* Stay under PAGE_SIZE or else bla bla bla.... */
+
+	out += sprintf (out, "driver_version  : %s\n", DRIVER_VERSION);
+	out += sprintf (out, "model           : %s\n", stv680->camera_name);
+	out += sprintf (out, "in use          : %s\n", YES_NO (stv680->user));
+	out += sprintf (out, "streaming       : %s\n", YES_NO (stv680->streaming));
+	out += sprintf (out, "num_frames      : %d\n", STV680_NUMFRAMES);
+
+	out += sprintf (out, "Current size    : %ix%i\n", stv680->vwidth, stv680->vheight);
+	out += sprintf (out, "swapRGB         : %s\n", YES_NO (swapRGB));
+	out += sprintf (out, "Palette         : %i", stv680->palette);
+
+	out += sprintf (out, "\n");
+
+	out += sprintf (out, "Frames total    : %d\n", stv680->readcount);
+	out += sprintf (out, "Frames read     : %d\n", stv680->framecount);
+	out += sprintf (out, "Packets dropped : %d\n", stv680->dropped);
+	out += sprintf (out, "Decoding Errors : %d\n", stv680->error);
+
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0)
+			return 0;
+	} else
+		len = count;
+
+	*start = page + off;
+	return len;
+}
+
+static int create_proc_stv680_cam (struct usb_stv *stv680)
+{
+	char name[9];
+	struct proc_dir_entry *ent;
+
+	if (!stv680_proc_entry || !stv680)
+		return -1;
+
+	sprintf (name, "video%d", stv680->vdev.minor);
+
+	ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR, stv680_proc_entry);
+	if (!ent)
+		return -1;
+
+	ent->data = stv680;
+	ent->read_proc = stv680_read_proc;
+	stv680->proc_entry = ent;
+	return 0;
+}
+
+static void destroy_proc_stv680_cam (struct usb_stv *stv680)
+{
+	/* One to much, just to be sure :) */
+	char name[9];
+
+	if (!stv680 || !stv680->proc_entry)
+		return;
+
+	sprintf (name, "video%d", stv680->vdev.minor);
+	remove_proc_entry (name, stv680_proc_entry);
+	stv680->proc_entry = NULL;
+}
+
+static int proc_stv680_create (void)
+{
+	if (video_proc_entry == NULL) {
+		PDEBUG (0, "STV(e): /proc/video/ doesn't exist!");
+		return -1;
+	}
+	stv680_proc_entry = create_proc_entry ("stv680", S_IFDIR, video_proc_entry);
+
+	if (stv680_proc_entry) {
+		stv680_proc_entry->owner = THIS_MODULE;
+	} else {
+		PDEBUG (0, "STV(e): Unable to initialize /proc/video/stv680");
+		return -1;
+	}
+	return 0;
+}
+
+static void proc_stv680_destroy (void)
+{
+	if (stv680_proc_entry == NULL)
+		return;
+
+	remove_proc_entry ("stv", video_proc_entry);
+}
+#endif				/* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+
+/********************************************************************
+ * Camera control
+ *******************************************************************/
+
+static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+	/* This sets values for v4l interface. max/min = 65535/0  */
+
+	p->brightness = stv680->brightness;
+	p->whiteness = stv680->whiteness;	/* greyscale */
+	p->colour = stv680->colour;
+	p->contrast = stv680->contrast;
+	p->hue = stv680->hue;
+	p->palette = stv680->palette;
+	p->depth = stv680->depth;
+	return 0;
+}
+
+static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+	/* See above stv680_get_pict  */
+
+	if (p->palette != STV_VIDEO_PALETTE) {
+		PDEBUG (2, "STV(e): Palette set error in _set_pic");
+		return 1;
+	}
+
+	if (stv680->brightness != p->brightness) {
+		stv680->chgbright = 1;
+		stv680->brightness = p->brightness;
+	} else {
+		stv680->chgbright = 0;
+	}
+
+	stv680->whiteness = p->whiteness;	/* greyscale */
+	stv680->colour = p->colour;
+	stv680->contrast = p->contrast;
+	stv680->hue = p->hue;
+	stv680->palette = p->palette;
+	stv680->depth = p->depth;
+
+	return 0;
+}
+
+static void stv680_video_irq (struct urb *urb)
+{
+	struct usb_stv *stv680 = urb->context;
+	int length = urb->actual_length;
+
+	if (length < stv680->rawbufsize)
+		PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length);
+
+	/* ohoh... */
+	if (!stv680->streaming)
+		return;
+
+	if (!stv680->udev) {
+		PDEBUG (0, "STV(e): device vapourished in video_irq");
+		return;
+	}
+
+	/* 0 sized packets happen if we are to fast, but sometimes the camera
+	   keeps sending them forever...
+	 */
+	if (length && !urb->status) {
+		stv680->nullpackets = 0;
+		switch (stv680->scratch[stv680->scratch_next].state) {
+		case BUFFER_READY:
+		case BUFFER_BUSY:
+			stv680->dropped++;
+			break;
+
+		case BUFFER_UNUSED:
+			memcpy (stv680->scratch[stv680->scratch_next].data,
+			        (unsigned char *) urb->transfer_buffer, length);
+			stv680->scratch[stv680->scratch_next].state = BUFFER_READY;
+			stv680->scratch[stv680->scratch_next].length = length;
+			if (waitqueue_active (&stv680->wq)) {
+				wake_up_interruptible (&stv680->wq);
+			}
+			stv680->scratch_overflow = 0;
+			stv680->scratch_next++;
+			if (stv680->scratch_next >= STV680_NUMSCRATCH)
+				stv680->scratch_next = 0;;
+			break;
+		}		/* switch  */
+	} else {
+		stv680->nullpackets++;
+		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+			if (waitqueue_active (&stv680->wq)) {
+				wake_up_interruptible (&stv680->wq);
+			}
+		}
+	}			/*  if - else */
+
+	/* Resubmit urb for new data */
+	urb->status = 0;
+	urb->dev = stv680->udev;
+	if (usb_submit_urb (urb))
+		PDEBUG (0, "STV(e): urb burned down in video irq");
+	return;
+}				/*  _video_irq  */
+
+static int stv680_start_stream (struct usb_stv *stv680)
+{
+	urb_t *urb;
+	int err = 0, i;
+
+	stv680->streaming = 1;
+
+	/* Do some memory allocation */
+	for (i = 0; i < STV680_NUMFRAMES; i++) {
+		stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize;
+		stv680->frame[i].curpix = 0;
+	}
+	/* packet size = 4096  */
+	for (i = 0; i < STV680_NUMSBUF; i++) {
+		stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+		if (stv680->sbuf[i].data == NULL) {
+			PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
+			return -1;
+		}
+	}
+
+	stv680->scratch_next = 0;
+	stv680->scratch_use = 0;
+	stv680->scratch_overflow = 0;
+	for (i = 0; i < STV680_NUMSCRATCH; i++) {
+		stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+		if (stv680->scratch[i].data == NULL) {
+			PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
+			return -1;
+		}
+		stv680->scratch[i].state = BUFFER_UNUSED;
+	}
+
+	for (i = 0; i < STV680_NUMSBUF; i++) {
+		urb = usb_alloc_urb (0);
+		if (!urb)
+			return ENOMEM;
+
+		/* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
+		usb_fill_bulk_urb (urb, stv680->udev,
+				   usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
+				   stv680->sbuf[i].data, stv680->rawbufsize,
+				   stv680_video_irq, stv680);
+		urb->timeout = PENCAM_TIMEOUT * 2;
+		urb->transfer_flags |= USB_QUEUE_BULK;
+		stv680->urb[i] = urb;
+		err = usb_submit_urb (stv680->urb[i]);
+		if (err)
+			PDEBUG (0, "STV(e): urb burned down in start stream");
+	}			/* i STV680_NUMSBUF */
+
+	stv680->framecount = 0;
+	return 0;
+}
+
+static int stv680_stop_stream (struct usb_stv *stv680)
+{
+	int i;
+
+	if (!stv680->streaming || !stv680->udev)
+		return 1;
+
+	stv680->streaming = 0;
+
+	for (i = 0; i < STV680_NUMSBUF; i++)
+		if (stv680->urb[i]) {
+			stv680->urb[i]->next = NULL;
+			usb_unlink_urb (stv680->urb[i]);
+			usb_free_urb (stv680->urb[i]);
+			stv680->urb[i] = NULL;
+			kfree (stv680->sbuf[i].data);
+		}
+	for (i = 0; i < STV680_NUMSCRATCH; i++) {
+		kfree (stv680->scratch[i].data);
+		stv680->scratch[i].data = NULL;
+	}
+
+	return 0;
+}
+
+static int stv680_set_size (struct usb_stv *stv680, int width, int height)
+{
+	int wasstreaming = stv680->streaming;
+
+	/* Check to see if we need to change */
+	if ((stv680->vwidth == width) && (stv680->vheight == height))
+		return 0;
+
+	PDEBUG (1, "STV(i): size request for %i x %i", width, height);
+	/* Check for a valid mode */
+	if ((!width || !height) || ((width & 1) || (height & 1))) {
+		PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
+		return 1;
+	}
+
+	if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) {
+		width = stv680->maxwidth / 2;
+		height = stv680->maxheight / 2;
+	} else if ((width >= 158) && (width <= 166)) {
+		width = 160;
+		height = 120;
+	} else if ((width >= 172) && (width <= 180)) {
+		width = 176;
+		height = 144;
+	} else if ((width >= 318) && (width <= 350)) {
+		width = 320;
+		height = 240;
+	} else if ((width >= 350) && (width <= 358)) {
+		width = 352;
+		height = 288;
+	}
+
+	/* Stop a current stream and start it again at the new size */
+	if (wasstreaming)
+		stv680_stop_stream (stv680);
+	stv680->vwidth = width;
+	stv680->vheight = height;
+	PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight);
+	if (wasstreaming)
+		stv680_start_stream (stv680);
+
+	return 0;
+}
+
+/**********************************************************************
+ * Video Decoding
+ **********************************************************************/
+
+/*******  routines from the pencam program; hey, they work!  ********/
+
+/*
+ * STV0680 Vision Camera Chipset Driver
+ * Copyright (C) 2000 Adam Harrison <adam@antispin.org> 
+*/
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define AD(x, y, w) (((y)*(w)+(x))*3)
+
+static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer)
+{
+	int x, y, i;
+	int w = stv680->cwidth;
+	int vw = stv680->cwidth, vh = stv680->cheight, vstep = 1;
+	unsigned int p = 0;
+	int colour = 0, bayer = 0;
+	unsigned char *raw = buffer->data;
+	struct stv680_frame *frame = &stv680->frame[stv680->curframe];
+	unsigned char *output = frame->data;
+	unsigned char *temp = frame->data;
+	int offset = buffer->offset;
+
+	if (frame->curpix == 0) {
+		if (frame->grabstate == FRAME_READY) {
+			frame->grabstate = FRAME_GRABBING;
+		}
+	}
+	if (offset != frame->curpix) {	/* Regard frame as lost :( */
+		frame->curpix = 0;
+		stv680->error++;
+		return;
+	}
+
+	if ((stv680->vwidth == 322) || (stv680->vwidth == 320)) {
+		vw = 320;
+		vh = 240;
+		vstep = 1;
+	}
+	if ((stv680->vwidth == 352)) {
+		vw = 352;
+		vh = 288;
+		vstep = 1;
+	}
+	if ((stv680->vwidth == 160)) {
+		vw = 160;
+		vh = 120;
+		vstep = 2;
+	}
+	if ((stv680->vwidth == 176)) {
+		vw = 176;
+		vh = 144;
+		vstep = 2;
+	}
+	memset (output, 0, 3 * vw * vh);	/* clear output matrix. Maybe not necessary. */
+
+	for (y = 0; y < vh; y++) {
+		for (x = 0; x < vw; x++) {
+
+			switch (vstep) {
+			case 1:
+				if (x & 1)
+					p = *(raw + y * w + (x >> 1));
+				else
+					p = *(raw + y * w + (x >> 1) + (w >> 1));
+				break;
+
+			case 2:
+				if (x & 1)
+					p = *(raw + ((y * w) << 1) + x);
+				else
+					p = *(raw + ((y * w) << 1) + x + (w >> 1));
+				break;
+			}
+
+			if (y & 1)
+				bayer = 2;
+			else
+				bayer = 0;
+			if (x & 1)
+				bayer++;
+
+			switch (bayer) {
+			case 0:
+			case 3:
+				colour = 1;
+				break;
+			case 1:
+				colour = 0;
+				break;
+			case 2:
+				colour = 2;
+				break;
+			}
+			i = (y * vw + x) * 3;	/* output already zeroed out with memset */
+			*(output + i + colour) = (unsigned char) p;
+		}		/* for x */
+	}			/* for y */
+
+	/****** gamma correction plus hardcoded white balance */
+	/* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.
+	   Correction values red[], green[], blue[], are generated by 
+	   (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255. 
+	   White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and 
+	   converted to unsigned char. Values are in stv680.h  */
+	for (y = 0; y < vh; y++) {
+		for (x = 0; x < vw; x++) {
+			i = (y * vw + x) * 3;
+			*(output + i) = red[*(output + i)];
+			*(output + i + 1) = green[*(output + i + 1)];
+			*(output + i + 2) = blue[*(output + i + 2)];
+		}
+	}
+
+	/******  bayer demosaic  ******/
+	for (y = 1; y < (vh - 1); y++) {
+		for (x = 1; x < (vw - 1); x++) {	/* work out pixel type */
+			if (y & 1)
+				bayer = 0;
+			else
+				bayer = 2;
+			if (!(x & 1))
+				bayer++;
+
+			switch (bayer) {
+			case 0:	/* green. blue lr, red tb */
+				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y, vw) + BLUE) + (int) *(output + AD (x + 1, y, vw) + BLUE)) >> 1;
+				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1;
+				break;
+
+			case 1:	/* blue. green lrtb, red diagonals */
+				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2;
+				break;
+
+			case 2:	/* red. green lrtb, blue diagonals */
+				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2;
+				break;
+
+			case 3:	/* green. red lr, blue tb */
+				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1;
+				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1;
+				break;
+			}	/* switch */
+		}		/* for x */
+	}			/* for y  - end demosaic  */
+
+	/* output is RGB; some programs want BGR  */
+	if (swapRGB == 1) {
+		for (y = 0; y < vh; y++) {
+			for (x = 0; x < vw; x++) {
+				i = (y * vw + x) * 3;
+				*(temp) = *(output + i);
+				*(output + i) = *(output + i + 2);
+				*(output + i + 2) = *(temp);
+			}
+		}
+	}
+	/* brightness */
+	if (stv680->chgbright == 1) {
+		if (stv680->brightness >= 32767) {
+			p = (stv680->brightness - 32767) / 256;
+			for (x = 0; x < (vw * vh * 3); x++) {
+				if ((*(output + x) + (unsigned char) p) > 255)
+					*(output + x) = 255;
+				else
+					*(output + x) += (unsigned char) p;
+			}	/* for */
+		} else {
+			p = (32767 - stv680->brightness) / 256;
+			for (x = 0; x < (vw * vh * 3); x++) {
+				if ((unsigned char) p > *(output + x))
+					*(output + x) = 0;
+				else
+					*(output + x) -= (unsigned char) p;
+			}	/* for */
+		}		/* else */
+	}
+	/* if */
+	frame->curpix = 0;
+	frame->curlinepix = 0;
+	frame->grabstate = FRAME_DONE;
+	stv680->framecount++;
+	stv680->readcount++;
+	if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) {
+		stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1);
+	}
+
+}				/* bayer_unshuffle */
+
+/*******  end routines from the pencam program  *********/
+
+static int stv680_newframe (struct usb_stv *stv680, int framenr)
+{
+	int errors = 0;
+
+	while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) {
+		if (!stv680->frame[framenr].curpix) {
+			errors++;
+		}
+		wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY));
+
+		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+			stv680->nullpackets = 0;
+			PDEBUG (2, "STV(i): too many null length packets, restarting capture");
+			stv680_stop_stream (stv680);
+			stv680_start_stream (stv680);
+		} else {
+			if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) {
+				stv680->frame[framenr].grabstate = FRAME_ERROR;
+				PDEBUG (2, "STV(e): FRAME_ERROR in _newframe");
+				return -EIO;
+			}
+			stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY;
+
+			bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]);
+
+			stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED;
+			stv680->scratch_use++;
+			if (stv680->scratch_use >= STV680_NUMSCRATCH)
+				stv680->scratch_use = 0;
+			if (errors > STV680_MAX_ERRORS) {
+				errors = 0;
+				PDEBUG (2, "STV(i): too many errors, restarting capture");
+				stv680_stop_stream (stv680);
+				stv680_start_stream (stv680);
+			}
+		}		/* else */
+	}			/* while */
+	return 0;
+}
+
+/*********************************************************************
+ * Video4Linux
+ *********************************************************************/
+
+static int stv_open (struct video_device *dev, int flags)
+{
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	int err = 0;
+
+	/* we are called with the BKL held */
+	MOD_INC_USE_COUNT;
+	stv680->user = 1;
+	err = stv_init (stv680);	/* main initialization routine for camera */
+
+	if (err >= 0) {
+		stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);
+		if (!stv680->fbuf) {
+			PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");
+			err = -ENOMEM;
+		}
+	}
+	if (err) {
+		MOD_DEC_USE_COUNT;
+		stv680->user = 0;
+	}
+
+	return err;
+}
+
+static void stv_close (struct video_device *dev)
+{
+	/* called with BKL held */
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	int i;
+
+	for (i = 0; i < STV680_NUMFRAMES; i++)
+		stv680->frame[i].grabstate = FRAME_UNUSED;
+	if (stv680->streaming)
+		stv680_stop_stream (stv680);
+
+	if ((i = stv_stop_video (stv680)) < 0)
+		PDEBUG (1, "STV(e): stop_video failed in stv_close");
+
+	rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);
+	stv680->user = 0;
+
+	if (stv680->removed) {
+		video_unregister_device (&stv680->vdev);
+		kfree (stv680);
+		stv680 = NULL;
+		PDEBUG (0, "STV(i): device unregistered");
+	}
+	MOD_DEC_USE_COUNT;
+}
+
+static long stv680_write (struct video_device *dev, const char *buf, unsigned long count, int noblock)
+{
+	return -EINVAL;
+}
+
+static int stv680_ioctl (struct video_device *vdev, unsigned int cmd, void *arg)
+{
+	struct usb_stv *stv680 = (struct usb_stv *) vdev;
+
+	if (!stv680->udev)
+		return -EIO;
+
+	switch (cmd) {
+	case VIDIOCGCAP:{
+			struct video_capability b;
+
+			strcpy (b.name, stv680->camera_name);
+			b.type = VID_TYPE_CAPTURE;
+			b.channels = 1;
+			b.audios = 0;
+			b.maxwidth = stv680->maxwidth;
+			b.maxheight = stv680->maxheight;
+			b.minwidth = stv680->maxwidth / 2;
+			b.minheight = stv680->maxheight / 2;
+
+			if (copy_to_user (arg, &b, sizeof (b))) {
+				PDEBUG (2, "STV(e): VIDIOCGGAP failed");
+				return -EFAULT;
+			}
+			return 0;
+		}
+	case VIDIOCGCHAN:{
+			struct video_channel v;
+
+			if (copy_from_user (&v, arg, sizeof (v)))
+				return -EFAULT;
+			if (v.channel != 0)
+				return -EINVAL;
+
+			v.flags = 0;
+			v.tuners = 0;
+			v.type = VIDEO_TYPE_CAMERA;
+			strcpy (v.name, "STV Camera");
+
+			if (copy_to_user (arg, &v, sizeof (v))) {
+				PDEBUG (2, "STV(e): VIDIOCGCHAN failed");
+				return -EFAULT;
+			}
+			return 0;
+		}
+	case VIDIOCSCHAN:{
+			int v;
+
+			if (copy_from_user (&v, arg, sizeof (v))) {
+				PDEBUG (2, "STV(e): VIDIOCSCHAN failed");
+				return -EFAULT;
+			}
+			if (v != 0)
+				return -EINVAL;
+
+			return 0;
+		}
+	case VIDIOCGPICT:{
+			struct video_picture p;
+
+			stv680_get_pict (stv680, &p);
+			if (copy_to_user (arg, &p, sizeof (p))) {
+				PDEBUG (2, "STV(e): VIDIOCGPICT failed");
+				return -EFAULT;
+			}
+			return 0;
+		}
+	case VIDIOCSPICT:{
+			struct video_picture p;
+
+			if (copy_from_user (&p, arg, sizeof (p))) {
+				PDEBUG (2, "STV(e): VIDIOCSPICT failed");
+				return -EFAULT;
+			}
+			copy_from_user (&p, arg, sizeof (p));
+			PDEBUG (2, "STV(i): palette set to RGB in VIDIOSPICT");
+
+			if (stv680_set_pict (stv680, &p))
+				return -EINVAL;
+			return 0;
+		}
+	case VIDIOCSWIN:{
+			struct video_window vw;
+
+			if (copy_from_user (&vw, arg, sizeof (vw)))
+				return -EFAULT;
+			if (vw.flags)
+				return -EINVAL;
+			if (vw.clipcount)
+				return -EINVAL;
+			if (vw.width != stv680->vwidth) {
+				if (stv680_set_size (stv680, vw.width, vw.height)) {
+					PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN");
+					return -EINVAL;
+				}
+			}
+			return 0;
+		}
+	case VIDIOCGWIN:{
+			struct video_window vw;
+
+			vw.x = 0;	/* FIXME */
+			vw.y = 0;
+			vw.chromakey = 0;
+			vw.flags = 0;
+			vw.clipcount = 0;
+			vw.width = stv680->vwidth;
+			vw.height = stv680->vheight;
+
+			if (copy_to_user (arg, &vw, sizeof (vw))) {
+				PDEBUG (2, "STV(e): VIDIOCGWIN failed");
+				return -EFAULT;
+			}
+			return 0;
+		}
+	case VIDIOCGMBUF:{
+			struct video_mbuf vm;
+			int i;
+
+			memset (&vm, 0, sizeof (vm));
+			vm.size = STV680_NUMFRAMES * stv680->maxframesize;
+			vm.frames = STV680_NUMFRAMES;
+			for (i = 0; i < STV680_NUMFRAMES; i++)
+				vm.offsets[i] = stv680->maxframesize * i;
+
+			if (copy_to_user ((void *) arg, (void *) &vm, sizeof (vm))) {
+				PDEBUG (2, "STV(e): VIDIOCGMBUF failed");
+				return -EFAULT;
+			}
+
+			return 0;
+		}
+	case VIDIOCMCAPTURE:{
+			struct video_mmap vm;
+
+			if (copy_from_user (&vm, arg, sizeof (vm))) {
+				PDEBUG (2, "STV(e): VIDIOCMCAPTURE failed");
+				return -EFAULT;
+			}
+			if (vm.format != STV_VIDEO_PALETTE) {
+				PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)",
+					vm.format, STV_VIDEO_PALETTE);
+				if (vm.format == 3) {
+					PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is ON");
+					/* this may fix those apps (e.g., xawtv) that want BGR */
+					swapRGB = 1;
+				}
+				return -EINVAL;
+			}
+			if (vm.frame >= STV680_NUMFRAMES) {
+				PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES");
+				return -EINVAL;
+			}
+			if (stv680->frame[vm.frame].grabstate != FRAME_UNUSED) {
+				PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate != FRAME_UNUSED");
+				return -EBUSY;
+			}
+			/* Is this according to the v4l spec??? */
+			if (stv680->vwidth != vm.width) {
+				if (stv680_set_size (stv680, vm.width, vm.height)) {
+					PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed");
+					return -EINVAL;
+				}
+			}
+			stv680->frame[vm.frame].grabstate = FRAME_READY;
+
+			if (!stv680->streaming)
+				stv680_start_stream (stv680);
+
+			return 0;
+		}
+	case VIDIOCSYNC:{
+			int frame, ret = 0;
+
+			if (copy_from_user ((void *) &frame, arg, sizeof (int))) {
+				PDEBUG (2, "STV(e): VIDIOCSYNC failed");
+				return -EFAULT;
+			}
+			if (frame < 0 || frame >= STV680_NUMFRAMES) {
+				PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC");
+				return -EINVAL;
+			}
+			ret = stv680_newframe (stv680, frame);
+			stv680->frame[frame].grabstate = FRAME_UNUSED;
+			return ret;
+		}
+	case VIDIOCGFBUF:{
+			struct video_buffer vb;
+
+			memset (&vb, 0, sizeof (vb));
+			vb.base = NULL;	/* frame buffer not supported, not used */
+
+			if (copy_to_user ((void *) arg, (void *) &vb, sizeof (vb))) {
+				PDEBUG (2, "STV(e): VIDIOCSYNC failed");
+				return -EFAULT;
+			}
+			return 0;
+		}
+	case VIDIOCKEY:
+		return 0;
+	case VIDIOCCAPTURE:
+		{
+			PDEBUG (2, "STV(e): VIDIOCCAPTURE failed");
+			return -EINVAL;
+		}
+	case VIDIOCSFBUF:
+		return -EINVAL;
+	case VIDIOCGTUNER:
+	case VIDIOCSTUNER:
+		return -EINVAL;
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+		return -EINVAL;
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+		return -EINVAL;
+	default:
+		return -ENOIOCTLCMD;
+	}			/* end switch */
+
+	return 0;
+}
+
+static int stv680_mmap (struct video_device *dev, const char *adr, unsigned long size)
+{
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	unsigned long start = (unsigned long) adr;
+	unsigned long page, pos;
+
+	down (&stv680->lock);
+
+	if (stv680->udev == NULL) {
+		up (&stv680->lock);
+		return -EIO;
+	}
+	if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
+		    & ~(PAGE_SIZE - 1))) {
+		up (&stv680->lock);
+		return -EINVAL;
+	}
+	pos = (unsigned long) stv680->fbuf;
+	while (size > 0) {
+		page = kvirt_to_pa (pos);
+		if (remap_page_range (start, page, PAGE_SIZE, PAGE_SHARED)) {
+			up (&stv680->lock);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	up (&stv680->lock);
+
+	return 0;
+}
+
+static long stv680_read (struct video_device *dev, char *buf, unsigned long count, int noblock)
+{
+	unsigned long int realcount = count;
+	int ret = 0;
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	unsigned long int i;
+
+	if (STV680_NUMFRAMES != 2) {
+		PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!");
+		return -1;
+	}
+	if (stv680->udev == NULL)
+		return -EIO;
+	if (realcount > (stv680->vwidth * stv680->vheight * 3))
+		realcount = stv680->vwidth * stv680->vheight * 3;
+
+	/* Shouldn't happen: */
+	if (stv680->frame[0].grabstate == FRAME_GRABBING) {
+		PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read");
+		return -EBUSY;
+	}
+	stv680->frame[0].grabstate = FRAME_READY;
+	stv680->frame[1].grabstate = FRAME_UNUSED;
+	stv680->curframe = 0;
+
+	if (!stv680->streaming)
+		stv680_start_stream (stv680);
+
+	if (!stv680->streaming) {
+		ret = stv680_newframe (stv680, 0);	/* ret should = 0 */
+	}
+
+	ret = stv680_newframe (stv680, 0);
+
+	if (!ret) {
+		if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) {
+			PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i);
+			return -EFAULT;
+		}
+	} else {
+		realcount = ret;
+	}
+	stv680->frame[0].grabstate = FRAME_UNUSED;
+	return realcount;
+}				/* stv680_read */
+
+static int stv_init_done (struct video_device *dev)
+{
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	if (create_proc_stv680_cam ((struct usb_stv *) dev) < 0)
+		return -1;
+#endif
+	return 0;
+}
+
+static struct video_device stv680_template = {
+	owner:		THIS_MODULE,
+	name:		"STV0680 USB camera",
+	type:		VID_TYPE_CAPTURE,
+	hardware:	VID_HARDWARE_SE401,
+	open:		stv_open,
+	close:		stv_close,
+	read:		stv680_read,
+	write:		stv680_write,
+	ioctl:		stv680_ioctl,
+	mmap:		stv680_mmap,
+	initialize:	stv_init_done,
+};
+
+static void *__devinit stv680_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+{
+	struct usb_interface_descriptor *interface;
+	struct usb_stv *stv680;
+	char *camera_name = NULL;
+
+	/* We don't handle multi-config cameras */
+	if (dev->descriptor.bNumConfigurations != 1) {
+		PDEBUG (0, "STV(e): Number of Configurations != 1");
+		return NULL;
+	}
+
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+	/* Is it a STV680? */
+	if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) {
+		camera_name = "STV0680";
+		PDEBUG (0, "STV(i): STV0680 camera found.");
+	} else {
+		PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values.");
+		PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer.");
+		return NULL;
+	}
+	/* We found one */
+	if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {
+		PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");
+		return NULL;
+	}
+
+	memset (stv680, 0, sizeof (*stv680));
+
+	stv680->udev = dev;
+	stv680->camera_name = camera_name;
+
+	memcpy (&stv680->vdev, &stv680_template, sizeof (stv680_template));
+	memcpy (stv680->vdev.name, stv680->camera_name, strlen (stv680->camera_name));
+	init_waitqueue_head (&stv680->wq);
+	init_MUTEX (&stv680->lock);
+	wmb ();
+
+	if (video_register_device (&stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+		kfree (stv680);
+		PDEBUG (0, "STV(e): video_register_device failed");
+		return NULL;
+	}
+	PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor);
+
+	return stv680;
+}
+
+static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
+{
+	int i;
+
+	stv680->udev = NULL;
+	stv680->frame[0].grabstate = FRAME_ERROR;
+	stv680->frame[1].grabstate = FRAME_ERROR;
+	stv680->streaming = 0;
+
+	wake_up_interruptible (&stv680->wq);
+
+	for (i = 0; i < STV680_NUMSBUF; i++)
+		if (stv680->urb[i]) {
+			stv680->urb[i]->next = NULL;
+			usb_unlink_urb (stv680->urb[i]);
+			usb_free_urb (stv680->urb[i]);
+			stv680->urb[i] = NULL;
+			kfree (stv680->sbuf[i].data);
+		}
+	for (i = 0; i < STV680_NUMSCRATCH; i++)
+		if (stv680->scratch[i].data) {
+			kfree (stv680->scratch[i].data);
+		}
+	PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	destroy_proc_stv680_cam (stv680);
+#endif
+	/* Free the memory */
+	kfree (stv680);
+}
+
+static void stv680_disconnect (struct usb_device *dev, void *ptr)
+{
+	struct usb_stv *stv680 = (struct usb_stv *) ptr;
+
+	lock_kernel ();
+	/* We don't want people trying to open up the device */
+	if (!stv680->user) {
+		video_unregister_device (&stv680->vdev);
+		usb_stv680_remove_disconnected (stv680);
+	} else {
+		stv680->removed = 1;
+	}
+	unlock_kernel ();
+}
+
+static struct usb_driver stv680_driver = {
+	name:		"stv680",
+	probe:		stv680_probe,
+	disconnect:	stv680_disconnect,
+	id_table:	device_table
+};
+
+/********************************************************************
+ *  Module routines
+ ********************************************************************/
+
+static int __init usb_stv680_init (void)
+{
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	if (proc_stv680_create () < 0)
+		return -1;
+#endif
+	if (usb_register (&stv680_driver) < 0) {
+		PDEBUG (0, "STV(e): Could not setup STV0680 driver");
+		return -1;
+	}
+	PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);
+
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	return 0;
+}
+
+static void __exit usb_stv680_exit (void)
+{
+	usb_deregister (&stv680_driver);
+	PDEBUG (0, "STV(i): driver deregistered");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	proc_stv680_destroy ();
+#endif
+}
+
+module_init (usb_stv680_init);
+module_exit (usb_stv680_exit);
diff -urN linux-2.5.2-pre6/drivers/usb/stv680.h linux/drivers/usb/stv680.h
--- linux-2.5.2-pre6/drivers/usb/stv680.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/stv680.h	Thu Jan  3 14:10:38 2002
@@ -0,0 +1,222 @@
+/****************************************************************************
+ *
+ *  Filename: stv680.h
+ *
+ *  Description:
+ *     This is a USB driver for STV0680 based usb video cameras.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************************/
+
+/* size of usb transfers */
+#define STV680_PACKETSIZE	4096
+
+/* number of queued bulk transfers to use, may have problems if > 1 */
+#define STV680_NUMSBUF		1
+
+/* number of frames supported by the v4l part */
+#define STV680_NUMFRAMES	2
+
+/* scratch buffers for passing data to the decoders: 2 or 4 are good */
+#define STV680_NUMSCRATCH	2
+
+/* number of nul sized packets to receive before kicking the camera */
+#define STV680_MAX_NULLPACKETS	200
+
+/* number of decoding errors before kicking the camera */
+#define STV680_MAX_ERRORS	100
+
+#define USB_PENCAM_VENDOR_ID	0x0553
+#define USB_PENCAM_PRODUCT_ID	0x0202
+#define PENCAM_TIMEOUT          1000
+/* fmt 4 */
+#define STV_VIDEO_PALETTE    VIDEO_PALETTE_RGB24
+
+static __devinitdata struct usb_device_id device_table[] = {
+	{USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)},
+	{}
+};
+MODULE_DEVICE_TABLE (usb, device_table);
+
+struct stv680_sbuf {
+	unsigned char *data;
+};
+
+enum {
+	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
+	FRAME_READY,		/* Ready to start grabbing */
+	FRAME_GRABBING,		/* In the process of being grabbed into */
+	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
+	FRAME_ERROR,		/* Something bad happened while processing */
+};
+
+enum {
+	BUFFER_UNUSED,
+	BUFFER_READY,
+	BUFFER_BUSY,
+	BUFFER_DONE,
+};
+
+/* raw camera data <- sbuf (urb transfer buf) */
+struct stv680_scratch {
+	unsigned char *data;
+	volatile int state;
+	int offset;
+	int length;
+};
+
+/* processed data for display ends up here, after bayer */
+struct stv680_frame {
+	unsigned char *data;	/* Frame buffer */
+	volatile int grabstate;	/* State of grabbing */
+	unsigned char *curline;
+	int curlinepix;
+	int curpix;
+};
+
+/* this is almost the video structure uvd_t, with extra parameters for stv */
+struct usb_stv {
+	struct video_device vdev;
+
+	struct usb_device *udev;
+
+	unsigned char bulk_in_endpointAddr;	/* __u8  the address of the bulk in endpoint */
+	char *camera_name;
+
+	unsigned int VideoMode;	/* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */
+	int SupportedModes;
+	int CIF;
+	int VGA;
+	int QVGA;
+	int cwidth;		/* camera width */
+	int cheight;		/* camera height */
+	int maxwidth;		/* max video width */
+	int maxheight;		/* max video height */
+	int vwidth;		/* current width for video window */
+	int vheight;		/* current height for video window */
+	unsigned long int rawbufsize;
+	unsigned long int maxframesize;	/* rawbufsize * 3 for RGB */
+
+	int origGain;
+	int origMode;		/* original camera mode */
+
+	struct semaphore lock;	/* to lock the structure */
+	int user;		/* user count for exclusive use */
+	int removed;		/* device disconnected */
+	int streaming;		/* Are we streaming video? */
+	char *fbuf;		/* Videodev buffer area */
+	urb_t *urb[STV680_NUMSBUF];	/* # of queued bulk transfers */
+	int curframe;		/* Current receiving frame */
+	struct stv680_frame frame[STV680_NUMFRAMES];	/* # frames supported by v4l part */
+	int readcount;
+	int framecount;
+	int error;
+	int dropped;
+	int scratch_next;
+	int scratch_use;
+	int scratch_overflow;
+	struct stv680_scratch scratch[STV680_NUMSCRATCH];	/* for decoders */
+	struct stv680_sbuf sbuf[STV680_NUMSBUF];
+
+	unsigned int brightness;
+	unsigned int chgbright;
+	unsigned int whiteness;
+	unsigned int colour;
+	unsigned int contrast;
+	unsigned int hue;
+	unsigned int palette;
+	unsigned int depth;	/* rgb24 in bits */
+
+	wait_queue_head_t wq;	/* Processes waiting */
+
+	struct proc_dir_entry *proc_entry;	/* /proc/stv680/videoX */
+	int nullpackets;
+};
+
+unsigned char red[256] = {
+	0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
+	50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
+	79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,
+	98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,
+	114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,
+	127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+	139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
+	150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
+	160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
+	169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,
+	177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,
+	186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,
+	193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,
+	201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,
+	208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,
+	214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,
+	221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
+	227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
+	233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+	239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,
+	245, 245, 246, 246
+};
+
+unsigned char green[256] = {
+	0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	24, 24, 24, 24, 24, 24, 24, 32, 39, 45, 50, 54,
+	58, 62, 65, 69, 71, 74, 77, 79, 83, 85, 87, 90,
+	92, 93, 95, 98, 100, 101, 104, 106, 107, 109, 111, 113,
+	114, 116, 118, 119, 121, 122, 124, 126, 127, 128, 129, 132,
+	133, 134, 135, 136, 138, 140, 141, 142, 143, 145, 146, 147,
+	148, 149, 150, 152, 153, 154, 155, 156, 157, 159, 160, 161,
+	162, 163, 164, 166, 167, 168, 168, 169, 170, 171, 173, 174,
+	175, 176, 176, 177, 179, 180, 181, 182, 182, 183, 184, 186,
+	187, 187, 188, 189, 190, 191, 191, 193, 194, 195, 195, 196,
+	197, 198, 198, 200, 201, 201, 202, 203, 204, 204, 205, 207,
+	207, 208, 209, 209, 210, 211, 212, 212, 214, 215, 215, 216,
+	217, 217, 218, 218, 219, 221, 221, 222, 223, 223, 224, 225,
+	225, 226, 226, 228, 229, 229, 230, 231, 231, 232, 232, 233,
+	235, 235, 236, 236, 237, 238, 238, 239, 239, 241, 241, 242,
+	243, 243, 244, 244, 245, 245, 246, 248, 248, 249, 249, 250,
+	250, 251, 251, 252, 253, 253, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255
+};
+
+unsigned char blue[256] = {
+	0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+	31, 31, 31, 31, 31, 31, 31, 41, 50, 57, 63, 69,
+	74, 78, 82, 87, 90, 94, 97, 100, 105, 108, 111, 113,
+	116, 118, 121, 124, 127, 128, 131, 134, 136, 139, 140, 143,
+	145, 148, 149, 150, 153, 155, 156, 159, 161, 162, 164, 167,
+	168, 170, 171, 173, 174, 177, 179, 180, 182, 183, 185, 186,
+	187, 189, 190, 192, 193, 195, 196, 198, 199, 201, 202, 204,
+	205, 207, 208, 210, 211, 213, 213, 214, 216, 217, 219, 220,
+	222, 223, 223, 224, 226, 227, 229, 230, 230, 232, 233, 235,
+	236, 236, 238, 239, 241, 242, 242, 244, 245, 247, 247, 248,
+	250, 251, 251, 253, 254, 254, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+	255, 255, 255, 255
+};
diff -urN linux-2.5.2-pre6/drivers/usb/vicam.c linux/drivers/usb/vicam.c
--- linux-2.5.2-pre6/drivers/usb/vicam.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/vicam.c	Thu Jan  3 14:10:38 2002
@@ -0,0 +1,986 @@
+/* -*- linux-c -*-
+ * USB ViCAM driver
+ *
+ * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
+ * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ *
+ * This driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
+ *
+ * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
+ *
+ * TODO:
+ *	- find out the ids for the Vista Imaging ViCAM
+ *
+ * History:
+ *
+ * 2001_07_07 - 0.1 - christopher: first version
+ * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try 
+ 			while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
+		      yep, moving pictures.
+ * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
+ 			get gqcam-0.9, compile it and run. Better than dd ;-).
+ * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
+ 			kill update_params if it does not seem to work for you.
+ * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
+
+ *
+ * FIXME: It crashes on rmmod with camera plugged.
+ */
+#define DEBUG 1
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/usb.h>
+
+#include <asm/io.h>
+#include <linux/wrapper.h>
+#include <linux/vmalloc.h>
+
+#include <linux/videodev.h>
+
+#include "vicam.h"
+#include "vicamurbs.h"
+
+/* Version Information */
+#define DRIVER_VERSION "v0"
+#define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
+#define DRIVER_DESC "USB ViCAM Driver"
+
+/* Define these values to match your device */
+#define USB_VICAM_VENDOR_ID	0x04C1
+#define USB_VICAM_PRODUCT_ID	0x009D
+
+/* table of devices that work with this driver */
+static struct usb_device_id vicam_table [] = {
+	{ USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, vicam_table);
+
+static int video_nr = -1; 		/* next avail video device */
+static struct usb_driver vicam_driver;
+
+static char *buf, *buf2;
+static int change_pending = 0; 
+
+static int vicam_parameters(struct usb_vicam *vicam);
+
+/******************************************************************************
+ *
+ *  Memory management functions
+ *
+ *  Taken from bttv-drivers.c 2.4.7-pre3
+ *
+ ******************************************************************************/
+
+/* [DaveM] I've recoded most of this so that:
+ * 1) It's easier to tell what is happening
+ * 2) It's more portable, especially for translating things
+ *    out of vmalloc mapped areas in the kernel.
+ * 3) Less unnecessary translations happen.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guarenteed.  We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+	unsigned long ret = 0UL;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	if (!pgd_none(*pgd)) {
+		pmd = pmd_offset(pgd, adr);
+		if (!pmd_none(*pmd)) {
+			ptep = pte_offset(pmd, adr);
+			pte = *ptep;
+			if(pte_present(pte)) {
+				ret  = (unsigned long) page_address(pte_page(pte));
+				ret |= (adr & (PAGE_SIZE - 1));
+
+			}
+		}
+	}
+	return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+	ret = virt_to_bus((void *)kva);
+	return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr)
+{
+	unsigned long va, kva, ret;
+
+	va = VMALLOC_VMADDR(adr);
+	kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = virt_to_bus((void *)kva);
+	return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+	unsigned long va, kva, ret;
+
+	va = VMALLOC_VMADDR(adr);
+	kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = __pa(kva);
+	return ret;
+}
+
+static void * rvmalloc(signed long size)
+{
+	void * mem;
+	unsigned long adr, page;
+
+	mem=vmalloc_32(size);
+	if (mem)
+	{
+		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+		adr=(unsigned long) mem;
+		while (size > 0)
+		{
+			page = kvirt_to_pa(adr);
+			mem_map_reserve(virt_to_page(__va(page)));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, signed long size)
+{
+	unsigned long adr, page;
+
+	if (mem)
+	{
+		adr=(unsigned long) mem;
+		while (size > 0)
+		{
+			page = kvirt_to_pa(adr);
+			mem_map_unreserve(virt_to_page(__va(page)));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+		vfree(mem);
+	}
+}
+
+/******************************************************************************
+ *
+ *  Foo Bar
+ *
+ ******************************************************************************/
+
+/**
+ *	usb_vicam_debug_data
+ */
+static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
+{
+	int i;
+
+	if (!debug)
+		return;
+
+	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
+		function, size);
+	for (i = 0; i < size; ++i) {
+		printk ("%.2x ", data[i]);
+	}
+	printk ("\n");
+}
+
+/*****************************************************************************
+ *
+ *  Send command to vicam
+ *
+ *****************************************************************************/
+
+static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
+	unsigned short value, unsigned char *cp, int size)
+{
+	int ret;
+	unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
+
+	/* Needs to return data I think, works for sending though */
+	memcpy(transfer_buffer, cp, size);
+	
+	ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ);
+
+	kfree(transfer_buffer);
+	if (ret)
+		printk("vicam: error: %d\n", ret);
+	mdelay(100);
+	return ret;
+}
+
+
+/*****************************************************************************
+ *
+ *  Video4Linux Helpers
+ * 
+ *****************************************************************************/
+
+static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
+{
+	dbg("vicam_get_capability");
+
+	strcpy(b->name, vicam->camera_name);
+	b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
+	b->channels = 1;
+	b->audios = 0;
+
+	b->maxwidth = vicam->width[vicam->sizes-1];
+	b->maxheight = vicam->height[vicam->sizes-1];
+	b->minwidth = vicam->width[0];
+	b->minheight = vicam->height[0];
+
+	return 0;
+}
+		
+static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+	dbg("vicam_get_channel");
+
+	if (v->channel != 0)
+		return -EINVAL;
+ 
+	v->flags = 0;
+	v->tuners = 0;
+	v->type = VIDEO_TYPE_CAMERA;
+	strcpy(v->name, "Camera");
+
+	return 0;
+} 
+		
+static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+	dbg("vicam_set_channel");
+
+	if (v->channel != 0)
+		return -EINVAL;
+	
+	return 0;
+}
+		
+static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
+{
+	int i;
+
+	dbg("vicam_get_mmapbuffer");
+
+	memset(vm, 0, sizeof(vm));
+	vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
+	vm->frames = VICAM_NUMFRAMES;
+
+	for (i=0; i<VICAM_NUMFRAMES; i++)
+		vm->offsets[i] = vicam->maxframesize * i;
+
+	return 0;
+}
+
+static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+	dbg("vicam_get_picture");
+
+	/* This is probably where that weird 0x56 call goes */
+	p->brightness = vicam->win.brightness;
+	p->hue = vicam->win.hue;
+	p->colour = vicam->win.colour;
+	p->contrast = vicam->win.contrast;
+	p->whiteness = vicam->win.whiteness;
+	p->depth = vicam->win.depth;
+	p->palette = vicam->win.palette;
+
+	return 0;
+}
+
+static void synchronize(struct usb_vicam *vicam)
+{
+	change_pending = 1;
+	interruptible_sleep_on(&vicam->wait);
+	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+	mdelay(10);
+	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+	mdelay(10);
+}
+
+static void params_changed(struct usb_vicam *vicam)
+{
+#if 1
+	synchronize(vicam);
+	mdelay(10);
+	vicam_parameters(vicam);
+	printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+#endif
+}
+
+static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+	int changed = 0;
+	info("vicam_set_picture (%d)", p->brightness);
+
+
+#define SET(x) \
+	if (vicam->win.x != p->x) \
+		vicam->win.x = p->x, changed = 1;
+	SET(brightness);
+	SET(hue);
+	SET(colour);
+	SET(contrast);
+	SET(whiteness);
+	SET(depth);
+	SET(palette);
+	if (changed)
+		params_changed(vicam);
+
+	return 0;
+	/* Investigate what should be done maybe 0x56 type call */
+	if (p->depth != 8) return 1;
+	if (p->palette != VIDEO_PALETTE_GREY) return 1;
+
+	return 0;
+}
+
+/* FIXME - vicam_sync_frame - important */
+static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
+{
+	dbg("vicam_sync_frame");
+
+	if(frame <0 || frame >= VICAM_NUMFRAMES)
+		return -EINVAL;
+
+	/* Probably need to handle various cases */
+/*	ret=vicam_newframe(vicam, frame);
+	vicam->frame[frame].grabstate=FRAME_UNUSED;
+*/
+	return 0;
+}
+	
+static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+	dbg("vicam_get_window");
+
+	vw->x = 0;
+	vw->y = 0;
+	vw->chromakey = 0;
+	vw->flags = 0;
+	vw->clipcount = 0;
+	vw->width = vicam->win.width;
+	vw->height = vicam->win.height;
+
+	return 0;
+}
+
+static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+	info("vicam_set_window");
+		
+	if (vw->flags)
+		return -EINVAL;
+	if (vw->clipcount)
+		return -EINVAL;
+
+	if (vicam->win.width == vw->width && vicam->win.height == vw->height)
+		return 0;
+
+	/* Pick largest mode that is smaller than specified res */
+	/* If specified res is too small reject                 */
+
+	/* Add urb send to device... */
+
+	vicam->win.width = vw->width;
+	vicam->win.height = vw->height;
+	params_changed(vicam);
+
+	return 0;
+}
+
+/* FIXME - vicam_mmap_capture - important */
+static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
+{
+	dbg("vicam_mmap_capture");
+
+	/* usbvideo.c looks good for using here */
+
+	/* 
+	if (vm->frame >= VICAM_NUMFRAMES)
+		return -EINVAL;
+	if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
+		return -EBUSY;
+	vicam->frame[vm->frame].grabstate=FRAME_READY;
+	*/
+
+	/* No need to vicam_set_window here according to Alan */
+
+	/*
+	if (!vicam->streaming)
+		vicam_start_stream(vicam);
+	*/
+
+	/* set frame as ready */
+
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ *  Video4Linux
+ * 
+ *****************************************************************************/
+
+static int vicam_v4l_open(struct video_device *vdev, int flags)
+{
+	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+	int err = 0;
+	
+	dbg("vicam_v4l_open");
+
+	MOD_INC_USE_COUNT; 
+	down(&vicam->sem);
+
+	if (vicam->open_count)		/* Maybe not needed? */
+		err = -EBUSY;
+	else {
+		vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
+		if (!vicam->fbuf)
+			err=-ENOMEM;
+		else {
+			vicam->open_count = 1;
+		}
+#ifdef BLINKING
+		vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+		info ("led on");
+		vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+#endif
+	}
+
+	up(&vicam->sem);
+	if (err)
+		MOD_DEC_USE_COUNT;
+	return err;
+}
+
+static void vicam_v4l_close(struct video_device *vdev)
+{
+	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+	dbg("vicam_v4l_close");
+	
+	down(&vicam->sem);
+
+#ifdef BLINKING
+	info ("led off");
+	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+//	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
+#endif
+
+	rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
+	vicam->fbuf = 0;
+	vicam->open_count=0;
+
+	up(&vicam->sem);
+	/* Why does se401.c have a usbdevice check here? */
+	/* If device is unplugged while open, I guess we only may unregister now */
+	MOD_DEC_USE_COUNT;
+}
+
+static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock)
+{
+	//struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+	dbg("vicam_v4l_read(%ld)", buflen);
+
+	if (!vdev || !buf)
+		return -EFAULT;
+
+	if (copy_to_user(user_buf, buf2, buflen))
+		return -EFAULT;
+	return buflen;
+}
+
+static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
+{
+	info("vicam_v4l_write");
+	return -EINVAL;
+}
+
+static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+	int ret = -EL3RST;
+
+	if (!vicam->udev)
+		return -EIO;
+
+	down(&vicam->sem);
+
+	switch (cmd) {
+	case VIDIOCGCAP:
+	{
+		struct video_capability b;
+		ret = vicam_get_capability(vicam,&b);
+		dbg("name %s",b.name);
+		if (copy_to_user(arg, &b, sizeof(b)))
+			ret = -EFAULT;
+	}
+	case VIDIOCGFBUF:
+	{
+		struct video_buffer vb;
+		info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
+		/* frame buffer not supported, not used */
+		memset(&vb, 0, sizeof(vb));
+		vb.base = NULL;
+		
+		/* FIXME - VIDIOCGFBUF - why the void */
+		if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
+			ret = -EFAULT;
+		ret = 0;
+	}
+	case VIDIOCGWIN:
+	{
+		struct video_window vw;
+		ret = vicam_get_window(vicam, &vw);
+		if (copy_to_user(arg, &vw, sizeof(vw)))
+			ret = -EFAULT;
+	}
+	case VIDIOCSWIN:
+	{
+		struct video_window vw;
+		if (copy_from_user(&vw, arg, sizeof(vw)))
+			ret = -EFAULT;
+		else
+			ret = vicam_set_window(vicam, &vw);
+		return ret;
+	}
+	case VIDIOCGCHAN:
+	{
+		struct video_channel v;
+
+		if (copy_from_user(&v, arg, sizeof(v)))
+			ret = -EFAULT;
+		else {
+			ret = vicam_get_channel(vicam,&v);
+			if (copy_to_user(arg, &v, sizeof(v)))
+				ret = -EFAULT;
+		}
+	}
+	case VIDIOCSCHAN:
+	{
+		struct video_channel v;
+		if (copy_from_user(&v, arg, sizeof(v)))
+			ret = -EFAULT;
+		else
+			ret = vicam_set_channel(vicam,&v);
+ 	}
+	case VIDIOCGPICT:
+	{
+		struct video_picture p;
+		ret = vicam_get_picture(vicam, &p);
+		if (copy_to_user(arg, &p, sizeof(p)))
+			ret = -EFAULT;
+	}
+	case VIDIOCSPICT:
+	{
+		struct video_picture p;
+		if (copy_from_user(&p, arg, sizeof(p)))
+			ret = -EFAULT;
+		else
+			ret = vicam_set_picture(vicam, &p);
+	}
+	case VIDIOCGMBUF:
+	{
+		struct video_mbuf vm;
+		ret = vicam_get_mmapbuffer(vicam,&vm);
+		/* FIXME - VIDIOCGMBUF - why the void */
+		if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+			ret = -EFAULT;
+	}
+	case VIDIOCMCAPTURE:
+	{
+		struct video_mmap vm;
+		ret = vicam_mmap_capture(vicam, &vm);
+		/* FIXME: This is probably not right */
+	}
+	case VIDIOCSYNC:
+	{
+		int frame;
+		/* FIXME - VIDIOCSYNC - why the void */
+		if (copy_from_user((void *)&frame, arg, sizeof(int)))
+			ret = -EFAULT;
+		else
+			ret = vicam_sync_frame(vicam,frame);
+	}
+
+	case VIDIOCKEY:
+		ret = 0;
+ 
+	case VIDIOCCAPTURE:
+	case VIDIOCSFBUF:
+	case VIDIOCGTUNER:
+	case VIDIOCSTUNER:
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+	case VIDIOCGUNIT:
+		ret = -EINVAL;
+
+	default:
+	{
+		info("vicam_v4l_ioctl - %ui",cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	} /* end switch */
+
+	up(&vicam->sem);
+        return ret;
+}
+
+static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size)
+{
+	struct usb_vicam *vicam = (struct usb_vicam *)dev;
+	unsigned long start = (unsigned long)adr;
+	unsigned long page, pos;
+
+	down(&vicam->sem);
+	
+	if (vicam->udev == NULL) {
+		up(&vicam->sem);
+		return -EIO;
+	}
+#if 0
+	if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+		up(&vicam->sem);
+		return -EINVAL;
+	}
+#endif
+	pos = (unsigned long)vicam->fbuf;
+	while (size > 0) {
+		page = kvirt_to_pa(pos);
+		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
+			up(&vicam->sem);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	up(&vicam->sem);
+
+        return 0;
+}
+
+/* FIXME - vicam_v4l_init */
+static int vicam_v4l_init(struct video_device *dev)
+{
+	/* stick proc fs stuff in here if wanted */
+	dbg("vicam_v4l_init");
+	return 0;
+}
+
+/* FIXME - vicam_template - important */
+static struct video_device vicam_template = {
+	name:		"vicam USB camera",
+	type:		VID_TYPE_CAPTURE,
+	hardware:	VID_HARDWARE_SE401, /* need to ask for own id */
+	open:		vicam_v4l_open,
+	close:		vicam_v4l_close,
+	read:		vicam_v4l_read,
+	write:		vicam_v4l_write,
+	ioctl:		vicam_v4l_ioctl,
+	mmap:		vicam_v4l_mmap,
+	initialize:	vicam_v4l_init,
+};
+
+/******************************************************************************
+ *
+ *  Some Routines
+ *
+ ******************************************************************************/
+
+/*
+Flash the led
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+info ("led on");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+info ("led off");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+*/
+
+static void vicam_bulk(struct urb *urb)
+{
+	struct usb_vicam *vicam = urb->context;
+
+	/*	if (!vicam || !vicam->dev || !vicam->used)
+		return;
+	*/
+
+	if (urb->status)
+		printk("vicam%d: nonzero read/write bulk status received: %d",
+			0, urb->status);
+
+	urb->actual_length = 0;
+	urb->dev = vicam->udev;
+
+	memcpy(buf2, buf+64, 0x1e480);
+	if (vicam->fbuf)
+		memcpy(vicam->fbuf, buf+64, 0x1e480);
+
+	if (!change_pending) {
+		if (usb_submit_urb(urb))
+			dbg("failed resubmitting read urb");
+	} else {
+		change_pending = 0;
+		wake_up_interruptible(&vicam->wait);
+	}
+}
+
+static int vicam_parameters(struct usb_vicam *vicam)
+{
+	unsigned char req[0x10];
+	unsigned int shutter;
+	shutter = 10;
+
+	switch (vicam->win.width) {
+	case 512:
+	default:
+		memcpy(req, s512x242bw, 0x10);
+		break;
+	case 256:
+		memcpy(req, s256x242bw, 0x10);
+		break;
+	case 128:
+		memcpy(req, s128x122bw, 0x10);
+		break;
+	}
+
+
+	mdelay(10);
+	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+	info ("led on");
+	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+
+	mdelay(10);
+
+	shutter = vicam->win.contrast / 256;
+	if (shutter == 0)
+		shutter = 1;
+	printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter );
+	req[0] = vicam->win.brightness /256;
+	shutter = 15600/shutter - 1;
+	req[6] = shutter & 0xff;
+	req[7] = (shutter >> 8) & 0xff;
+	vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
+	mdelay(10);
+	vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
+	mdelay(10);
+
+	return 0;
+}
+
+static int vicam_init(struct usb_vicam *vicam)
+{
+	int width[] = {128, 256, 512};
+	int height[] = {122, 242, 242};
+
+	dbg("vicam_init");
+	buf = kmalloc(0x1e480, GFP_KERNEL);
+	buf2 = kmalloc(0x1e480, GFP_KERNEL);
+	if ((!buf) || (!buf2)) {
+		printk("Not enough memory for vicam!\n");
+		goto error;
+	}
+
+	/* do we do aspect correction in kernel or not? */
+	vicam->sizes = 3;
+	vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+	vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+	memcpy(vicam->width, &width, sizeof(width));
+	memcpy(vicam->height, &height, sizeof(height));
+	vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
+
+	/* Download firmware to camera */
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+
+	vicam_parameters(vicam);
+
+	FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
+		      buf, 0x1e480, vicam_bulk, vicam);
+	printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+
+	return 0;
+error:
+	if (buf)
+		kfree(buf);
+	if (buf2)
+		kfree(buf2);
+	return 1;
+}
+
+static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
+	const struct usb_device_id *id)
+{
+	struct usb_vicam *vicam;
+	char *camera_name=NULL;
+
+	dbg("vicam_probe");
+
+	/* See if the device offered us matches what we can accept */
+	if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
+	    (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
+		return NULL;
+	}
+	
+	camera_name="3Com HomeConnect USB";
+	info("ViCAM camera found: %s", camera_name);
+	
+	vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
+	if (vicam == NULL) {
+		err ("couldn't kmalloc vicam struct");
+		return NULL;
+	}
+	memset(vicam, 0, sizeof(*vicam));
+	
+	vicam->udev = udev;
+	vicam->camera_name = camera_name;
+	vicam->win.brightness = 128;
+	vicam->win.contrast = 10;
+
+	/* FIXME */
+	if (vicam_init(vicam))
+		return NULL;
+	memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
+	memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
+	
+	if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+		err("video_register_device");
+		return NULL;
+	}
+
+	info("registered new video device: video%d", vicam->vdev.minor);
+	
+	init_MUTEX (&vicam->sem);
+	init_waitqueue_head(&vicam->wait);
+	
+	return vicam;
+}
+
+
+/* FIXME - vicam_disconnect - important */
+static void vicam_disconnect(struct usb_device *udev, void *ptr)
+{
+	struct usb_vicam *vicam;
+
+	vicam = (struct usb_vicam *) ptr;
+
+	if (!vicam->open_count)
+		video_unregister_device(&vicam->vdev);
+	vicam->udev = NULL;
+/*
+	vicam->frame[0].grabstate = FRAME_ERROR;
+	vicam->frame[1].grabstate = FRAME_ERROR;
+*/
+
+	/* Free buffers and shit */
+
+	info("%s disconnected", vicam->camera_name);
+	synchronize(vicam);
+
+	if (!vicam->open_count) {
+		/* Other random junk */
+		kfree(vicam);
+		vicam = NULL;
+	}
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vicam_driver = {
+	name:		"vicam",
+	probe:		vicam_probe,
+	disconnect:	vicam_disconnect,
+	id_table:	vicam_table,
+};
+
+/******************************************************************************
+ *
+ *  Module Routines
+ *
+ ******************************************************************************/
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Module paramaters */
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+static int __init usb_vicam_init(void)
+{
+	int result;
+
+	printk("VICAM: initializing\n");
+	/* register this driver with the USB subsystem */
+	result = usb_register(&vicam_driver);
+	if (result < 0) {
+		err("usb_register failed for the "__FILE__" driver. Error number %d",
+		    result);
+		return -1;
+	}
+
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+	return 0;
+}
+
+static void __exit usb_vicam_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&vicam_driver);
+}
+
+module_init(usb_vicam_init);
+module_exit(usb_vicam_exit);
diff -urN linux-2.5.2-pre6/drivers/usb/vicam.h linux/drivers/usb/vicam.h
--- linux-2.5.2-pre6/drivers/usb/vicam.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/vicam.h	Thu Jan  3 14:10:38 2002
@@ -0,0 +1,81 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ * 
+ */
+
+#ifndef __LINUX_VICAM_H
+#define __LINUX_VICAM_H
+
+
+#ifdef CONFIG_USB_DEBUG
+	static int debug = 1;
+#else
+	static int debug;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+
+#define VICAM_NUMFRAMES 30
+#define VICAM_NUMSBUF 1
+
+/* USB REQUEST NUMBERS */
+#define VICAM_REQ_VENDOR	0xff
+#define VICAM_REQ_CAMERA_POWER	0x50
+#define VICAM_REQ_CAPTURE	0x51
+#define VICAM_REQ_LED_CONTROL	0x55
+#define VICAM_REQ_GET_SOMETHIN	0x56
+ 
+/* not required but lets you know camera is on */
+/* camera must be on to turn on led */
+/* 0x01 always on  0x03 on when picture taken (flashes) */
+
+struct picture_parm
+{
+	int width;
+	int height;
+	int brightness;
+	int hue;
+	int colour;
+	int contrast;
+	int whiteness;
+	int depth;
+	int palette;
+};
+
+struct vicam_scratch {
+        unsigned char *data;
+        volatile int state;
+        int offset;
+        int length;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct usb_vicam
+{
+	struct video_device vdev;
+	struct usb_device *udev;
+
+	int open_count;	/* number of times this port has been opened */
+	struct semaphore sem;			/* locks this structure */
+	wait_queue_head_t wait;			/* Processes waiting */ 
+
+	int streaming;
+
+	/* v4l stuff */
+	char *camera_name;
+	char *fbuf;
+	urb_t *urb[VICAM_NUMSBUF];
+	int sizes;
+	int *width;
+	int *height;
+	int maxframesize;
+	struct picture_parm win;
+	struct proc_dir_entry *proc_entry;      /* /proc/se401/videoX */
+	struct urb readurb;
+};
+
+#endif
diff -urN linux-2.5.2-pre6/drivers/usb/vicamurbs.h linux/drivers/usb/vicamurbs.h
--- linux-2.5.2-pre6/drivers/usb/vicamurbs.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/vicamurbs.h	Thu Jan  3 14:10:38 2002
@@ -0,0 +1,330 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ * 
+ */
+
+
+#ifndef __LINUX_VICAMURBS_H
+#define __LINUX_VICAMURBS_H
+
+/* -------------------------------------------------------------------------- */
+
+/* FIXME - Figure out transfers so that this doesn't need to be here
+ *
+ * Notice: in pieces below, "0" means other code will fill it while "0x00" means this is zero */
+
+/* Request 0x51 Image Setup */
+
+/* 128x98 ? 0x3180 size */
+static unsigned char s128x98bw[] = {
+  0,    0x34, 0xC4, 0x00, 0x00, 0x00, 0,    0,
+  0x18, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 128x122 3D80 size */
+static unsigned char s128x122bw[] = {
+  0,    0x34, 0xF4, 0x00, 0x00, 0x00, 0,    0,
+  0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 256x242 ? 0xF280 size */
+static unsigned char s256x242bw[] = {
+  0,    0x03, 0xC8, 0x03, 0x00, 0x00, 0,    0,
+  0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 512x242 0x1E480 size */
+static unsigned char s512x242bw[] = {
+  0,    0x05, 0x90, 0x07, 0x00, 0x00, 0,    0,
+  0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* In s512x242:
+   byte 0: gain -- higher number means brighter image
+   byte 6, 7: shutter speed, little-endian; set this to 15600 * (shutter speed) - 1. (Where shutter speed is something like 1/1000).
+*/
+
+/* -------------------------------------------------------------------------- */
+
+static unsigned char fsetup[] = {
+  0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64,
+
+  0x00, 0x00
+};
+
+static unsigned char firmware1[] = {
+  0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64,
+
+  0xE7, 0x67, 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09,
+  0xDE, 0x00, 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03,
+  0xC0, 0x17, 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07,
+  0x00, 0x00, 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
+};
+
+static unsigned char findex1[] = {
+  0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64,
+
+  0x18, 0x00, 0x00, 0x00
+};
+
+static unsigned char firmware2[] = {
+  0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64,
+
+  0xE7, 0x07, 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07,
+  0x00, 0x00, 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01,
+  0xAA, 0x00, 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00,
+  0xE7, 0x07, 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07,
+  0x7C, 0x00, 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00,
+  0x18, 0x00, 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0,
+  0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07,
+  0xFF, 0xFF, 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00,
+  0x24, 0xC0, 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0,
+  0xE7, 0x07, 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87,
+  0x01, 0x00, 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09,
+  0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0,
+  0x09, 0xC1, 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01,
+  0xE7, 0x09, 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07,
+  0x07, 0x00, 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0,
+  0xC0, 0xDF, 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00,
+  0x17, 0x02, 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77,
+  0x01, 0x00, 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57,
+  0xFF, 0xFF, 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57,
+  0x00, 0x00, 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF,
+  0xC6, 0x00, 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05,
+  0xC1, 0x05, 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF,
+  0x27, 0xDA, 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00,
+  0x0B, 0x06, 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01,
+  0x9F, 0xAF, 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09,
+  0xFC, 0x05, 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06,
+  0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0,
+  0xE7, 0x09, 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09,
+  0x02, 0x06, 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06,
+  0xFC, 0x05, 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06,
+  0x27, 0xDA, 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00,
+  0xFA, 0x05, 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF,
+  0x9F, 0xAF, 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07,
+  0x40, 0x00, 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05,
+  0x9F, 0xAF, 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17,
+  0x02, 0x00, 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06,
+  0x9F, 0xA0, 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00,
+  0x09, 0x06, 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57,
+  0x01, 0x00, 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03,
+  0xE7, 0x07, 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF,
+  0x47, 0xAF, 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07,
+  0x2E, 0x00, 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00,
+  0x09, 0x06, 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00,
+  0xC0, 0x57, 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02,
+  0xC0, 0x57, 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57,
+  0x55, 0x00, 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00,
+  0x9F, 0xC0, 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02,
+  0xC1, 0x0B, 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90,
+  0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B,
+  0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF,
+  0x2F, 0x0E, 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07,
+  0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF,
+  0x28, 0x05, 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E,
+  0x02, 0x00, 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00,
+  0x09, 0x06, 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67,
+  0x7F, 0xFF, 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD,
+  0x22, 0xC0, 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0,
+  0xE7, 0x87, 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF,
+  0xB8, 0x05, 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0,
+  0x9F, 0xAF, 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00,
+  0x24, 0xC0, 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0,
+  0xC8, 0x07, 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00,
+  0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0x9F, 0xAF, 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00,
+  0x9F, 0xAF, 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+  0x00, 0x01, 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02,
+  0x0F, 0xC1, 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0,
+  0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+  0x08, 0x00, 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1,
+  0xEF, 0x07, 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF,
+  0xEF, 0x07, 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF,
+  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07,
+  0x00, 0x00, 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF,
+  0x09, 0x06, 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06,
+  0xE7, 0x67, 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67,
+  0x17, 0xD8, 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00,
+  0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0,
+  0x97, 0xCF, 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF,
+  0xDA, 0x02, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+  0x0E, 0x06, 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02,
+  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+  0x00, 0x80, 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C,
+  0x02, 0x00, 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00,
+  0x06, 0x06, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+  0xE2, 0x05, 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02,
+  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+  0x00, 0x80, 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF,
+  0x66, 0x04, 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF,
+  0x97, 0xCF, 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B,
+  0x0C, 0x06, 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+  0x68, 0x00, 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF,
+  0x44, 0x05, 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00,
+  0xE0, 0x07, 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06,
+  0xE8, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02,
+  0xE0, 0x07, 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF,
+  0x97, 0xCF, 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05,
+  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07,
+  0x0E, 0x06, 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06,
+  0xFE, 0x05, 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01,
+  0xE7, 0x07, 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07,
+  0x07, 0x00, 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07,
+  0x02, 0x00, 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01,
+  0xEF, 0x77, 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0,
+  0x14, 0x04, 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06,
+  0x37, 0xC0, 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06,
+  0x0F, 0xC1, 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06,
+  0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00,
+  0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0xC8, 0x07, 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05,
+  0xC0, 0x07, 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+  0xC1, 0x77, 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA,
+  0x75, 0xC1, 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1,
+  0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00,
+  0x06, 0x06, 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00,
+  0xC1, 0x07, 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0xEF, 0x07, 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF,
+  0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57,
+  0x01, 0x00, 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07,
+  0x01, 0x00, 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
+  0x30, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
+  0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
+  0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67,
+  0x03, 0x00, 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0,
+  0x08, 0xDA, 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00,
+  0xC1, 0x07, 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00,
+  0x06, 0x06, 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00,
+  0xC1, 0x0B, 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05,
+  0xE7, 0x09, 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8,
+  0xFA, 0x05, 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05,
+  0xE7, 0x07, 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07,
+  0x40, 0x00, 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05,
+  0x9F, 0xAF, 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B,
+  0xE2, 0x05, 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17,
+  0x23, 0x00, 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07,
+  0x04, 0x00, 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09,
+  0xE6, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x07, 0x00, 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00,
+  0xC1, 0x09, 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05,
+  0xC1, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x0D, 0x00, 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07,
+  0x32, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x0F, 0x00, 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9,
+  0x24, 0xC0, 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00,
+  0xC0, 0x67, 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0,
+  0xE7, 0x87, 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67,
+  0xFF, 0xF9, 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA,
+  0x72, 0xC1, 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0,
+  0x97, 0xCF, 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87,
+  0xFF, 0x00, 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF,
+  0x24, 0xC0, 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0,
+  0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF,
+  0x9F, 0xAF, 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0,
+  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+  0x40, 0x00, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+  0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05,
+  0xE7, 0x67, 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67,
+  0xFF, 0xFE, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+  0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07,
+  0x40, 0x00, 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67,
+  0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0,
+  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA,
+  0xE8, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+  0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
+  0x00, 0xDA, 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1,
+  0xE7, 0x87, 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF,
+  0xE7, 0x07, 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77,
+  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+  0xE7, 0x07, 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77,
+  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+  0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80,
+  0x96, 0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char findex2[] = {
+  0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64,
+
+  0x0E, 0x00, 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00,
+  0x26, 0x00, 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00,
+  0x92, 0x00, 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00,
+  0xB8, 0x00, 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00,
+  0xCE, 0x00, 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00,
+  0xE0, 0x00, 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00,
+  0xEC, 0x00, 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01,
+  0x0A, 0x01, 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01,
+  0x22, 0x01, 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01,
+  0x36, 0x01, 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01,
+  0x72, 0x01, 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01,
+  0x88, 0x01, 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01,
+  0xA0, 0x01, 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01,
+  0xB4, 0x01, 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01,
+  0xF6, 0x01, 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02,
+  0x3C, 0x02, 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02,
+  0x56, 0x02, 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02,
+  0x84, 0x02, 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02,
+  0x8E, 0x02, 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02,
+  0xAE, 0x02, 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02,
+  0xC0, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02,
+  0xD4, 0x02, 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02,
+  0xF8, 0x02, 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03,
+  0x24, 0x03, 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03,
+  0x3C, 0x03, 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03,
+  0x58, 0x03, 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03,
+  0x7A, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03,
+  0xB2, 0x03, 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03,
+  0xD4, 0x03, 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03,
+  0xFC, 0x03, 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04,
+  0x32, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04,
+  0x42, 0x04, 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04,
+  0x54, 0x04, 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04,
+  0x62, 0x04, 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04,
+  0x80, 0x04, 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04,
+  0x9A, 0x04, 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04,
+  0xB4, 0x04, 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04,
+  0x2A, 0x05, 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
+};
+
+#endif
diff -urN linux-2.5.2-pre6/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- linux-2.5.2-pre6/drivers/video/fbcon.c	Mon Oct 15 13:47:13 2001
+++ linux/drivers/video/fbcon.c	Thu Jan  3 14:10:38 2002
@@ -271,10 +271,10 @@
                 /* XXX Should report error here? */
                 return fgc;
 
-        if (MINOR(current->tty->device) < 1)
+        if (minor(current->tty->device) < 1)
                 return fgc;
 
-        return MINOR(current->tty->device) - 1;
+        return minor(current->tty->device) - 1;
 }
 
 
diff -urN linux-2.5.2-pre6/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- linux-2.5.2-pre6/drivers/video/fbmem.c	Thu Jan  3 14:10:33 2002
+++ linux/drivers/video/fbmem.c	Thu Jan  3 14:10:38 2002
@@ -625,7 +625,7 @@
 #if 1 /* to go away in 2.5.0 */
 int GET_FB_IDX(kdev_t rdev)
 {
-    int fbidx = MINOR(rdev);
+    int fbidx = minor(rdev);
     if (fbidx >= 32) {
 	int newfbidx = fbidx >> 5;
 	static int warned;
@@ -719,7 +719,7 @@
 	for (i = 0 ; i < FB_MAX; i++)
 		if (!registered_fb[i])
 			break;
-	fb_info->node = MKDEV(FB_MAJOR, i);
+	fb_info->node = mk_kdev(FB_MAJOR, i);
 	registered_fb[i] = fb_info;
 	if (!fb_ever_opened[i]) {
 		struct module *owner = fb_info->fbops->owner;
diff -urN linux-2.5.2-pre6/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- linux-2.5.2-pre6/drivers/video/vesafb.c	Wed Nov 14 14:52:20 2001
+++ linux/drivers/video/vesafb.c	Thu Jan  3 14:10:38 2002
@@ -648,7 +648,7 @@
 	
 	strcpy(fb_info.modename, "VESA VGA");
 	fb_info.changevar = NULL;
-	fb_info.node = -1;
+	fb_info.node = NODEV;
 	fb_info.fbops = &vesafb_ops;
 	fb_info.disp=&disp;
 	fb_info.switch_con=&vesafb_switch;
diff -urN linux-2.5.2-pre6/fs/affs/super.c linux/fs/affs/super.c
--- linux-2.5.2-pre6/fs/affs/super.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/affs/super.c	Thu Jan  3 14:10:38 2002
@@ -262,7 +262,7 @@
 	 * blocks, we will have to change it.
 	 */
 
-	blocks = blk_size[MAJOR(dev)] ? blk_size[MAJOR(dev)][MINOR(dev)] : 0;
+	blocks = blk_size[major(dev)] ? blk_size[major(dev)][minor(dev)] : 0;
 	if (!blocks) {
 		printk(KERN_ERR "AFFS: Could not determine device size\n");
 		goto out_error;
diff -urN linux-2.5.2-pre6/fs/coda/inode.c linux/fs/coda/inode.c
--- linux-2.5.2-pre6/fs/coda/inode.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/coda/inode.c	Thu Jan  3 14:10:38 2002
@@ -70,7 +70,7 @@
 		inode = file->f_dentry->d_inode;
 	
 	if(!inode || !S_ISCHR(inode->i_mode) ||
-	   MAJOR(inode->i_rdev) != CODA_PSDEV_MAJOR) {
+	   major(inode->i_rdev) != CODA_PSDEV_MAJOR) {
 		if(file)
 			fput(file);
 
@@ -78,7 +78,7 @@
 		return -1;
 	}
 
-	idx = MINOR(inode->i_rdev);
+	idx = minor(inode->i_rdev);
 	fput(file);
 
 	if(idx < 0 || idx >= MAX_CODADEVS) {
diff -urN linux-2.5.2-pre6/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- linux-2.5.2-pre6/fs/cramfs/inode.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/cramfs/inode.c	Thu Jan  3 14:10:38 2002
@@ -115,7 +115,7 @@
 	struct buffer_head * read_array[BLKS_PER_BUF];
 	unsigned i, blocknr, buffer, unread;
 	unsigned long devsize;
-	int major, minor;
+	unsigned int major, minor;
 	
 	char *data;
 
@@ -140,8 +140,8 @@
 	}
 
 	devsize = ~0UL;
-	major = MAJOR(sb->s_dev);
-	minor = MINOR(sb->s_dev);
+	major = major(sb->s_dev);
+	minor = minor(sb->s_dev);
 
 	if (blk_size[major])
 		devsize = blk_size[major][minor] >> 2;
diff -urN linux-2.5.2-pre6/fs/devfs/base.c linux/fs/devfs/base.c
--- linux-2.5.2-pre6/fs/devfs/base.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/devfs/base.c	Thu Jan  3 14:10:38 2002
@@ -1063,16 +1063,16 @@
     if ( ( new = _devfs_alloc_entry (".devfsd", 0, S_IFCHR |S_IRUSR |S_IWUSR) )
 	 == NULL ) return NULL;
     devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
-    new->u.fcb.u.device.major = MAJOR (devnum);
-    new->u.fcb.u.device.minor = MINOR (devnum);
+    new->u.fcb.u.device.major = major (devnum);
+    new->u.fcb.u.device.minor = minor (devnum);
     new->u.fcb.ops = &devfsd_fops;
     _devfs_append_entry (root_entry, new, FALSE, NULL);
 #ifdef CONFIG_DEVFS_DEBUG
     if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )
 	 == NULL ) return NULL;
     devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
-    new->u.fcb.u.device.major = MAJOR (devnum);
-    new->u.fcb.u.device.minor = MINOR (devnum);
+    new->u.fcb.u.device.major = major (devnum);
+    new->u.fcb.u.device.minor = minor (devnum);
     new->u.fcb.ops = &stat_fops;
     _devfs_append_entry (root_entry, new, FALSE, NULL);
 #endif
@@ -1558,8 +1558,8 @@
 		    name, S_ISCHR (mode) ? "char" : "block");
 	    return NULL;
 	}
-	major = MAJOR (devnum);
-	minor = MINOR (devnum);
+	major = major (devnum);
+	minor = minor (devnum);
     }
     if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL )
     {
diff -urN linux-2.5.2-pre6/fs/devfs/util.c linux/fs/devfs/util.c
--- linux-2.5.2-pre6/fs/devfs/util.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/devfs/util.c	Thu Jan  3 14:10:38 2002
@@ -320,8 +320,8 @@
 	semaphore = &block_semaphore;
 	list = &block_list;
     }
-    major = MAJOR (devnum);
-    minor = MINOR (devnum);
+    major = major (devnum);
+    minor = minor (devnum);
     down (semaphore);
     for (entry = list->first; entry != NULL; entry = entry->next)
     {
diff -urN linux-2.5.2-pre6/fs/dquot.c linux/fs/dquot.c
--- linux-2.5.2-pre6/fs/dquot.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/dquot.c	Thu Jan  3 14:10:38 2002
@@ -1483,7 +1483,7 @@
 			goto out;
 	}
 
-	ret = -NODEV;
+	ret = -ENODEV;
 	if (sb && sb_has_quota_enabled(sb, type))
 		ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr);
 out:
diff -urN linux-2.5.2-pre6/fs/ext3/ialloc.c linux/fs/ext3/ialloc.c
--- linux-2.5.2-pre6/fs/ext3/ialloc.c	Sun Dec 16 12:23:00 2001
+++ linux/fs/ext3/ialloc.c	Thu Jan  3 14:10:38 2002
@@ -189,7 +189,7 @@
 	struct ext3_super_block * es;
 	int fatal = 0, err;
 
-	if (!inode->i_dev) {
+	if (kdev_none(inode->i_dev)) {
 		printk ("ext3_free_inode: inode has no device\n");
 		return;
 	}
diff -urN linux-2.5.2-pre6/fs/ext3/super.c linux/fs/ext3/super.c
--- linux-2.5.2-pre6/fs/ext3/super.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/ext3/super.c	Thu Jan  3 14:10:38 2002
@@ -389,8 +389,8 @@
 	list_for_each(l, &sbi->s_orphan) {
 		struct inode *inode = orphan_list_entry(l);
 		printk(KERN_ERR "  "
-		       "inode 0x%04x:%ld at %p: mode %o, nlink %d, next %d\n",
-		       inode->i_dev, inode->i_ino, inode,
+		       "inode 0x%04x.0x%04x:%ld at %p: mode %o, nlink %d, next %d\n",
+		       major(inode->i_dev), minor(inode->i_dev), inode->i_ino, inode,
 		       inode->i_mode, inode->i_nlink, 
 		       le32_to_cpu(NEXT_ORPHAN(inode)));
 	}
@@ -430,7 +430,7 @@
 	J_ASSERT(list_empty(&sbi->s_orphan));
 
 	invalidate_buffers(sb->s_dev);
-	if (j_dev != sb->s_dev) {
+	if (!kdev_same(j_dev, sb->s_dev)) {
 		/*
 		 * Invalidate the journal device's buffers.  We don't want them
 		 * floating about in memory - the physical journal device may
@@ -917,7 +917,7 @@
 	sbi->s_resuid = EXT3_DEF_RESUID;
 	sbi->s_resgid = EXT3_DEF_RESGID;
 	if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
-		sb->s_dev = 0;
+		sb->s_dev = NODEV;
 		goto out_fail;
 	}
 
@@ -1259,7 +1259,7 @@
 }
 
 static journal_t *ext3_get_dev_journal(struct super_block *sb,
-				       int dev)
+				       kdev_t j_dev)
 {
 	struct buffer_head * bh;
 	journal_t *journal;
@@ -1268,16 +1268,15 @@
 	int hblock, blocksize;
 	unsigned long sb_block;
 	unsigned long offset;
-	kdev_t journal_dev = to_kdev_t(dev);
 	struct ext3_super_block * es;
 	struct block_device *bdev;
 
-	bdev = ext3_blkdev_get(journal_dev);
+	bdev = ext3_blkdev_get(j_dev);
 	if (bdev == NULL)
 		return NULL;
 
 	blocksize = sb->s_blocksize;
-	hblock = get_hardsect_size(journal_dev);
+	hblock = get_hardsect_size(j_dev);
 	if (blocksize < hblock) {
 		printk(KERN_ERR
 			"EXT3-fs: blocksize too small for journal device.\n");
@@ -1286,8 +1285,8 @@
 	
 	sb_block = EXT3_MIN_BLOCK_SIZE / blocksize;
 	offset = EXT3_MIN_BLOCK_SIZE % blocksize;
-	set_blocksize(dev, blocksize);
-	if (!(bh = bread(dev, sb_block, blocksize))) {
+	set_blocksize(j_dev, blocksize);
+	if (!(bh = bread(j_dev, sb_block, blocksize))) {
 		printk(KERN_ERR "EXT3-fs: couldn't read superblock of "
 		       "external journal\n");
 		goto out_bdev;
@@ -1313,7 +1312,7 @@
 	start = sb_block + 1;
 	brelse(bh);	/* we're done with the superblock */
 
-	journal = journal_init_dev(journal_dev, sb->s_dev, 
+	journal = journal_init_dev(j_dev, sb->s_dev,
 					start, len, blocksize);
 	if (!journal) {
 		printk(KERN_ERR "EXT3-fs: failed to create device journal\n");
@@ -1345,7 +1344,7 @@
 {
 	journal_t *journal;
 	int journal_inum = le32_to_cpu(es->s_journal_inum);
-	int journal_dev = le32_to_cpu(es->s_journal_dev);
+	kdev_t journal_dev = to_kdev_t(le32_to_cpu(es->s_journal_dev));
 	int err = 0;
 	int really_read_only;
 
@@ -1371,7 +1370,7 @@
 		}
 	}
 
-	if (journal_inum && journal_dev) {
+	if (journal_inum && !kdev_none(journal_dev)) {
 		printk(KERN_ERR "EXT3-fs: filesystem has both journal "
 		       "and inode journals!\n");
 		return -EINVAL;
diff -urN linux-2.5.2-pre6/fs/hfs/file.c linux/fs/hfs/file.c
--- linux-2.5.2-pre6/fs/hfs/file.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/hfs/file.c	Thu Jan  3 14:10:38 2002
@@ -310,8 +310,8 @@
 
 	bhb = bhe = buflist;
 	if (reada) {
-		if (blocks < read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9)) {
-			blocks = read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9);
+		if (blocks < read_ahead[major(dev)] / (HFS_SECTOR_SIZE>>9)) {
+			blocks = read_ahead[major(dev)] / (HFS_SECTOR_SIZE>>9);
 		}
 		if (block + blocks > size) {
 			blocks = size - block;
diff -urN linux-2.5.2-pre6/fs/intermezzo/psdev.c linux/fs/intermezzo/psdev.c
--- linux-2.5.2-pre6/fs/intermezzo/psdev.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/intermezzo/psdev.c	Thu Jan  3 14:10:38 2002
@@ -78,12 +78,12 @@
 {
         int minor;
 
-        if ( MAJOR(file->f_dentry->d_inode->i_rdev) != PRESTO_PSDEV_MAJOR ) {
+        if ( major(file->f_dentry->d_inode->i_rdev) != PRESTO_PSDEV_MAJOR ) {
                 EXIT;
                 return NULL;
         }
 
-        minor = MINOR(file->f_dentry->d_inode->i_rdev);
+        minor = minor(file->f_dentry->d_inode->i_rdev);
         if ( minor < 0 || minor >= MAX_PRESTODEV ) {
                 EXIT;
                 return NULL;
diff -urN linux-2.5.2-pre6/fs/intermezzo/super.c linux/fs/intermezzo/super.c
--- linux-2.5.2-pre6/fs/intermezzo/super.c	Sun Nov 11 10:20:21 2001
+++ linux/fs/intermezzo/super.c	Thu Jan  3 14:10:38 2002
@@ -159,7 +159,7 @@
 {
         struct nameidata nd;
         struct dentry *dentry;
-        kdev_t devno = 0;
+        kdev_t devno = NODEV;
         int error; 
         ENTRY;
 
@@ -188,19 +188,19 @@
 	}
 
         devno = dentry->d_inode->i_rdev;
-        if ( MAJOR(devno) != PRESTO_PSDEV_MAJOR ) { 
+        if ( major(devno) != PRESTO_PSDEV_MAJOR ) { 
 		EXIT;
 		goto out;
 	}
 
-        if ( MINOR(devno) >= MAX_PRESTODEV ) {
+        if ( minor(devno) >= MAX_PRESTODEV ) {
 		EXIT;
 		goto out;
 	}
 
 	EXIT;
  out:
-        *minor = MINOR(devno);
+        *minor = minor(devno);
         path_release(&nd);
         return 0;
 }
diff -urN linux-2.5.2-pre6/fs/jffs/inode-v23.c linux/fs/jffs/inode-v23.c
--- linux-2.5.2-pre6/fs/jffs/inode-v23.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/jffs/inode-v23.c	Thu Jan  3 14:10:38 2002
@@ -81,7 +81,7 @@
 	D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
 		  kdevname(dev)));
 
-	if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
+	if (major(dev) != MTD_BLOCK_MAJOR) {
 		printk(KERN_WARNING "JFFS: Trying to mount a "
 		       "non-mtd device.\n");
 		return 0;
diff -urN linux-2.5.2-pre6/fs/jffs2/dir.c linux/fs/jffs2/dir.c
--- linux-2.5.2-pre6/fs/jffs2/dir.c	Fri Sep 14 14:04:07 2001
+++ linux/fs/jffs2/dir.c	Thu Jan  3 14:10:38 2002
@@ -795,7 +795,7 @@
 	
 	if ((mode & S_IFMT) == S_IFBLK ||
 	    (mode & S_IFMT) == S_IFCHR) {
-		dev = (MAJOR(to_kdev_t(rdev)) << 8) | MINOR(to_kdev_t(rdev));
+		dev = (MAJOR(rdev) << 8) | MINOR(rdev);
 		devlen = sizeof(dev);
 	}
 	
diff -urN linux-2.5.2-pre6/fs/jffs2/file.c linux/fs/jffs2/file.c
--- linux-2.5.2-pre6/fs/jffs2/file.c	Thu Oct  4 15:13:18 2001
+++ linux/fs/jffs2/file.c	Thu Jan  3 14:10:38 2002
@@ -105,8 +105,8 @@
 	if ((inode->i_mode & S_IFMT) == S_IFBLK ||
 	    (inode->i_mode & S_IFMT) == S_IFCHR) {
 		/* For these, we don't actually need to read the old node */
-		dev =  (MAJOR(to_kdev_t(dentry->d_inode->i_rdev)) << 8) | 
-			MINOR(to_kdev_t(dentry->d_inode->i_rdev));
+		dev =  (major(dentry->d_inode->i_rdev) << 8) | 
+			minor(dentry->d_inode->i_rdev);
 		mdata = (char *)&dev;
 		mdatalen = sizeof(dev);
 		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
diff -urN linux-2.5.2-pre6/fs/jffs2/gc.c linux/fs/jffs2/gc.c
--- linux-2.5.2-pre6/fs/jffs2/gc.c	Thu Oct  4 15:13:18 2001
+++ linux/fs/jffs2/gc.c	Thu Jan  3 14:10:38 2002
@@ -269,8 +269,8 @@
 	if ((inode->i_mode & S_IFMT) == S_IFBLK ||
 	    (inode->i_mode & S_IFMT) == S_IFCHR) {
 		/* For these, we don't actually need to read the old node */
-		dev =  (MAJOR(to_kdev_t(inode->i_rdev)) << 8) | 
-			MINOR(to_kdev_t(inode->i_rdev));
+		dev =  (major(inode->i_rdev) << 8) | 
+			minor(inode->i_rdev);
 		mdata = (char *)&dev;
 		mdatalen = sizeof(dev);
 		D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
diff -urN linux-2.5.2-pre6/fs/jffs2/super.c linux/fs/jffs2/super.c
--- linux-2.5.2-pre6/fs/jffs2/super.c	Thu Oct  4 15:14:35 2001
+++ linux/fs/jffs2/super.c	Thu Jan  3 14:10:38 2002
@@ -199,7 +199,7 @@
 
 	D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev)));
 
-	if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
+	if (major(sb->s_dev) != MTD_BLOCK_MAJOR) {
 		if (!silent)
 			printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev));
 		return NULL;
diff -urN linux-2.5.2-pre6/fs/namei.c linux/fs/namei.c
--- linux-2.5.2-pre6/fs/namei.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/namei.c	Thu Jan  3 14:10:38 2002
@@ -1589,7 +1589,7 @@
 		goto exit_lock;
 
 	error = -EXDEV;
-	if (!kdev_same(dir->i_dev, inode->i_dev))
+	if (dir->i_sb != inode->i_sb)
 		goto exit_lock;
 
 	/*
@@ -1707,7 +1707,7 @@
 	if (error)
 		return error;
 
-	if (!kdev_same(new_dir->i_dev, old_dir->i_dev))
+	if (new_dir->i_sb != old_dir->i_sb)
 		return -EXDEV;
 
 	if (!new_dentry->d_inode)
@@ -1787,7 +1787,7 @@
 	if (error)
 		return error;
 
-	if (!kdev_same(new_dir->i_dev, old_dir->i_dev))
+	if (new_dir->i_sb != old_dir->i_sb)
 		return -EXDEV;
 
 	if (!new_dentry->d_inode)
diff -urN linux-2.5.2-pre6/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- linux-2.5.2-pre6/fs/ncpfs/inode.c	Sun Sep 30 12:26:08 2001
+++ linux/fs/ncpfs/inode.c	Thu Jan  3 14:10:38 2002
@@ -181,7 +181,7 @@
 	inode->i_nlink = 1;
 	inode->i_uid = server->m.uid;
 	inode->i_gid = server->m.gid;
-	inode->i_rdev = 0;
+	inode->i_rdev = NODEV;
 	inode->i_blksize = NCP_BLOCK_SIZE;
 
 	inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
diff -urN linux-2.5.2-pre6/fs/nfs/write.c linux/fs/nfs/write.c
--- linux-2.5.2-pre6/fs/nfs/write.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/nfs/write.c	Thu Jan  3 14:10:38 2002
@@ -1201,8 +1201,9 @@
 		req = nfs_list_entry(data->pages.next);
 		nfs_list_remove_request(req);
 
-		dprintk("NFS: commit (%x/%Ld %d@%Ld)",
-			req->wb_inode->i_dev,
+		dprintk("NFS: commit (%02x:%02x/%Ld %d@%Ld)",
+			major(req->wb_inode->i_dev),
+			minor(req->wb_inode->i_dev),
 			(long long)NFS_FILEID(req->wb_inode),
 			req->wb_bytes,
 			(long long)(page_offset(req->wb_page) + req->wb_offset));
diff -urN linux-2.5.2-pre6/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c
--- linux-2.5.2-pre6/fs/nfsd/nfs3xdr.c	Wed Oct  3 22:27:48 2001
+++ linux/fs/nfsd/nfs3xdr.c	Thu Jan  3 14:10:38 2002
@@ -173,9 +173,9 @@
 		p = xdr_encode_hyper(p, (u64)(inode->i_size +511)& ~511);
 	else
 		p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
-	*p++ = htonl((u32) MAJOR(inode->i_rdev));
-	*p++ = htonl((u32) MINOR(inode->i_rdev));
-	p = xdr_encode_hyper(p, (u64) inode->i_dev);
+	*p++ = htonl((u32) major(inode->i_rdev));
+	*p++ = htonl((u32) minor(inode->i_rdev));
+	p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
 	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, inode->i_atime);
 	p = encode_time3(p, lease_get_mtime(inode));
@@ -203,9 +203,9 @@
 		p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
 	}
 	p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
-	*p++ = htonl((u32) MAJOR(fhp->fh_post_rdev));
-	*p++ = htonl((u32) MINOR(fhp->fh_post_rdev));
-	p = xdr_encode_hyper(p, (u64) inode->i_dev);
+	*p++ = htonl((u32) major(fhp->fh_post_rdev));
+	*p++ = htonl((u32) minor(fhp->fh_post_rdev));
+	p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
 	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, fhp->fh_post_atime);
 	p = encode_time3(p, fhp->fh_post_mtime);
diff -urN linux-2.5.2-pre6/fs/partitions/acorn.c linux/fs/partitions/acorn.c
--- linux-2.5.2-pre6/fs/partitions/acorn.c	Tue Dec 11 09:44:13 2001
+++ linux/fs/partitions/acorn.c	Thu Jan  3 14:10:38 2002
@@ -28,7 +28,7 @@
 	extern void xd_set_geometry(kdev_t dev, unsigned char, unsigned char,
 				    unsigned long, unsigned int);
 
-	if (MAJOR(dev) == MFM_ACORN_MAJOR) {
+	if (major(dev) == MFM_ACORN_MAJOR) {
 		unsigned long totalblocks = hd->part[MINOR(dev)].nr_sects;
 		xd_set_geometry(dev, secspertrack, heads, totalblocks, 1);
 	}
diff -urN linux-2.5.2-pre6/fs/partitions/ibm.c linux/fs/partitions/ibm.c
--- linux-2.5.2-pre6/fs/partitions/ibm.c	Mon Oct  1 20:03:26 2001
+++ linux/fs/partitions/ibm.c	Thu Jan  3 14:10:38 2002
@@ -125,7 +125,7 @@
 		return 0;
 	if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
 		return 0;
-	blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
+	blocksize = hardsect_size[major(dev)][minor(dev)];
 	if ( blocksize <= 0 ) {
 		return 0;
 	}
diff -urN linux-2.5.2-pre6/fs/romfs/inode.c linux/fs/romfs/inode.c
--- linux-2.5.2-pre6/fs/romfs/inode.c	Thu Jan  3 14:10:33 2002
+++ linux/fs/romfs/inode.c	Thu Jan  3 14:10:38 2002
@@ -518,7 +518,9 @@
 		default:
 			/* depending on MBZ for sock/fifos */
 			nextfh = ntohl(ri.spec);
-			nextfh = kdev_t_to_nr(MKDEV(nextfh>>16,nextfh&0xffff));
+			/* convert back and forth for typechecking and
+			 * source tagging */
+			nextfh = kdev_t_to_nr(mk_kdev(nextfh>>16,nextfh&0xffff));
 			init_special_inode(i, ino, nextfh);
 	}
 }
diff -urN linux-2.5.2-pre6/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog
--- linux-2.5.2-pre6/fs/smbfs/ChangeLog	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/ChangeLog	Thu Jan  3 14:10:38 2002
@@ -1,5 +1,15 @@
 ChangeLog for smbfs.
 
+2001-12-31 René Scharfe <l.s.r@web.de>
+
+	* inode.c: added smb_show_options to show mount options in /proc/mounts
+	* inode.c, getopt.c, getopt.h: merged flag and has_arg in struct option
+	* inode.c: use S_IRWXUGO where appropriate
+
+2001-12-22 Urban Widmark <urban@teststation.com>
+
+	* file.c, proc.c: Fix problems triggered by the "fsx test"
+
 2001-09-17 Urban Widmark <urban@teststation.com>
 
 	* proc.c: Use 4096 (was 512) as the blocksize for better write
diff -urN linux-2.5.2-pre6/fs/smbfs/file.c linux/fs/smbfs/file.c
--- linux-2.5.2-pre6/fs/smbfs/file.c	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/file.c	Thu Jan  3 14:10:38 2002
@@ -270,7 +270,6 @@
 static int smb_prepare_write(struct file *file, struct page *page, 
 			     unsigned offset, unsigned to)
 {
-	kmap(page);
 	return 0;
 }
 
@@ -283,7 +282,6 @@
 	lock_kernel();
 	status = smb_updatepage(file, page, offset, to-offset);
 	unlock_kernel();
-	kunmap(page);
 	return status;
 }
 
@@ -349,8 +347,14 @@
 smb_file_release(struct inode *inode, struct file * file)
 {
 	lock_kernel();
-	if (!--inode->u.smbfs_i.openers)
+	if (!--inode->u.smbfs_i.openers) {
+		/* We must flush any dirty pages now as we won't be able to
+		   write anything after close. mmap can trigger this.
+		   "openers" should perhaps include mmap'ers ... */
+		filemap_fdatasync(inode->i_mapping);
+		filemap_fdatawait(inode->i_mapping);
 		smb_close(inode);
+	}
 	unlock_kernel();
 	return 0;
 }
diff -urN linux-2.5.2-pre6/fs/smbfs/getopt.c linux/fs/smbfs/getopt.c
--- linux-2.5.2-pre6/fs/smbfs/getopt.c	Fri Apr 27 14:10:32 2001
+++ linux/fs/smbfs/getopt.c	Thu Jan  3 14:10:38 2002
@@ -46,7 +46,7 @@
 
 	for (i = 0; opts[i].name != NULL; i++) {
 		if (!strcmp(opts[i].name, token)) {
-			if (opts[i].has_arg && (!val || !*val)) {
+			if (!opts[i].flag && (!val || !*val)) {
 				printk("%s: the %s option requires an argument\n",
 				       caller, token);
 				return -1;
diff -urN linux-2.5.2-pre6/fs/smbfs/getopt.h linux/fs/smbfs/getopt.h
--- linux-2.5.2-pre6/fs/smbfs/getopt.h	Mon Aug 14 13:31:10 2000
+++ linux/fs/smbfs/getopt.h	Thu Jan  3 14:10:38 2002
@@ -3,7 +3,6 @@
 
 struct option {
 	const char *name;
-	int has_arg;
 	unsigned long flag;
 	int val;
 };
diff -urN linux-2.5.2-pre6/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- linux-2.5.2-pre6/fs/smbfs/inode.c	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/inode.c	Thu Jan  3 14:10:38 2002
@@ -22,6 +22,7 @@
 #include <linux/dcache.h>
 #include <linux/smp_lock.h>
 #include <linux/nls.h>
+#include <linux/seq_file.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
@@ -41,9 +42,12 @@
 #define SMB_NLS_REMOTE ""
 #endif
 
+#define SMB_TTL_DEFAULT 1000
+
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
 static int  smb_statfs(struct super_block *, struct statfs *);
+static int  smb_show_options(struct seq_file *, struct vfsmount *);
 
 static struct super_operations smb_sops =
 {
@@ -51,6 +55,7 @@
 	delete_inode:	smb_delete_inode,
 	put_super:	smb_put_super,
 	statfs:		smb_statfs,
+	show_options:	smb_show_options,
 };
 
 
@@ -259,21 +264,20 @@
 	clear_inode(ino);
 }
 
-/* FIXME: flags and has_arg could probably be merged. */
 static struct option opts[] = {
-	{ "version",	1, 0, 'v' },
-	{ "win95",	0, SMB_MOUNT_WIN95, 1 },
-	{ "oldattr",	0, SMB_MOUNT_OLDATTR, 1 },
-	{ "dirattr",	0, SMB_MOUNT_DIRATTR, 1 },
-	{ "case",	0, SMB_MOUNT_CASE, 1 },
-	{ "uid",	1, 0, 'u' },
-	{ "gid",	1, 0, 'g' },
-	{ "file_mode",	1, 0, 'f' },
-	{ "dir_mode",	1, 0, 'd' },
-	{ "iocharset",	1, 0, 'i' },
-	{ "codepage",	1, 0, 'c' },
-	{ "ttl",	1, 0, 't' },
-	{ NULL,		0, 0, 0}
+	{ "version",	0, 'v' },
+	{ "win95",	SMB_MOUNT_WIN95, 1 },
+	{ "oldattr",	SMB_MOUNT_OLDATTR, 1 },
+	{ "dirattr",	SMB_MOUNT_DIRATTR, 1 },
+	{ "case",	SMB_MOUNT_CASE, 1 },
+	{ "uid",	0, 'u' },
+	{ "gid",	0, 'g' },
+	{ "file_mode",	0, 'f' },
+	{ "dir_mode",	0, 'd' },
+	{ "iocharset",	0, 'i' },
+	{ "codepage",	0, 'c' },
+	{ "ttl",	0, 't' },
+	{ NULL,		0, 0}
 };
 
 static int
@@ -310,12 +314,10 @@
 			mnt->gid = value;
 			break;
 		case 'f':
-			mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-			mnt->file_mode |= S_IFREG;
+			mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
 			break;
 		case 'd':
-			mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-			mnt->dir_mode |= S_IFDIR;
+			mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
 			break;
 		case 'i':
 			strncpy(mnt->codepage.local_name, optarg, 
@@ -338,6 +340,45 @@
 	return c;
 }
 
+/*
+ * smb_show_options() is for displaying mount options in /proc/mounts.
+ * It tries to avoid showing settings that were not changed from their
+ * defaults.
+ */
+static int
+smb_show_options(struct seq_file *s, struct vfsmount *m)
+{
+	struct smb_mount_data_kernel *mnt = m->mnt_sb->u.smbfs_sb.mnt;
+	int i;
+
+	for (i = 0; opts[i].name != NULL; i++)
+		if (mnt->flags & opts[i].flag)
+			seq_printf(s, ",%s", opts[i].name);
+
+	if (mnt->uid != 0)
+		seq_printf(s, ",uid=%d", mnt->uid);
+	if (mnt->gid != 0)
+		seq_printf(s, ",gid=%d", mnt->gid);
+	if (mnt->mounted_uid != 0)
+		seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
+
+	/* 
+	 * Defaults for file_mode and dir_mode are unknown to us; they
+	 * depend on the current umask of the user doing the mount.
+	 */
+	seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
+	seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
+
+	if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
+		seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
+	if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
+		seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
+
+	if (mnt->ttl != SMB_TTL_DEFAULT)
+		seq_printf(s, ",ttl=%d", mnt->ttl);
+
+	return 0;
+}
 
 static void
 smb_put_super(struct super_block *sb)
@@ -425,7 +466,7 @@
 	strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
 		SMB_NLS_MAXNAMELEN);
 
-	mnt->ttl = 1000;
+	mnt->ttl = SMB_TTL_DEFAULT;
 	if (ver == SMB_MOUNT_OLDVERSION) {
 		mnt->version = oldmnt->version;
 
@@ -434,12 +475,8 @@
 		mnt->uid = oldmnt->uid;
 		mnt->gid = oldmnt->gid;
 
-		mnt->file_mode =
-			oldmnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-		mnt->dir_mode =
-			oldmnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-		mnt->file_mode |= S_IFREG;
-		mnt->dir_mode  |= S_IFDIR;
+		mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
+		mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
 
 		mnt->flags = (oldmnt->file_mode >> 9);
 	} else {
@@ -510,7 +547,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	struct smb_sb_info *server = server_from_dentry(dentry);
-	unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
+	unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
 	int error, changed, refresh = 0;
 	struct smb_fattr fattr;
 
@@ -535,6 +572,10 @@
 		VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
 			DENTRY_PATH(dentry),
 			(long) inode->i_size, (long) attr->ia_size);
+
+		filemap_fdatasync(inode->i_mapping);
+		filemap_fdatawait(inode->i_mapping);
+
 		error = smb_open(dentry, O_WRONLY);
 		if (error)
 			goto out;
diff -urN linux-2.5.2-pre6/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- linux-2.5.2-pre6/fs/umsdos/inode.c	Sun Sep 30 12:26:08 2001
+++ linux/fs/umsdos/inode.c	Thu Jan  3 14:10:38 2002
@@ -49,7 +49,7 @@
 void UMSDOS_put_super (struct super_block *sb)
 {
 	Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
-	if (saved_root && pseudo_root && sb->s_dev == ROOT_DEV) {
+	if (saved_root && pseudo_root && kdev_same(sb->s_dev, ROOT_DEV)) {
 		shrink_dcache_parent(saved_root);
 		dput(saved_root);
 		saved_root = NULL;
@@ -414,7 +414,7 @@
 	 * must check like this, because we can be used with initrd
 	 */
 		
-	if (sb->s_dev != ROOT_DEV)
+	if (!kdev_same(sb->s_dev, ROOT_DEV))
 		goto out_noroot;
 
 	/* 
diff -urN linux-2.5.2-pre6/include/linux/blk.h linux/include/linux/blk.h
--- linux-2.5.2-pre6/include/linux/blk.h	Thu Jan  3 14:10:33 2002
+++ linux/include/linux/blk.h	Thu Jan  3 14:10:38 2002
@@ -2,6 +2,7 @@
 #define _BLK_H
 
 #include <linux/blkdev.h>
+#include <linux/elevator.h>
 #include <linux/locks.h>
 #include <linux/config.h>
 #include <linux/spinlock.h>
@@ -43,9 +44,10 @@
 static inline void blkdev_dequeue_request(struct request *req)
 {
 	list_del(&req->queuelist);
-}
 
-#define __elv_next_request(q)	(q)->elevator.elevator_next_req_fn((q))
+	if (req->q)
+		elv_remove_request(req->q, req);
+}
 
 extern inline struct request *elv_next_request(request_queue_t *q)
 {
@@ -79,21 +81,21 @@
 	return rq;
 }
 
-#define __elv_add_request_core(q, rq, where, plug)			\
+#define _elv_add_request_core(q, rq, where, plug)			\
 	do {								\
 		if ((plug))						\
 			blk_plug_device((q));				\
 		(q)->elevator.elevator_add_req_fn((q), (rq), (where));	\
 	} while (0)
 
-#define __elv_add_request(q, rq, back, p) do {				      \
+#define _elv_add_request(q, rq, back, p) do {				      \
 	if ((back))							      \
-		__elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
+		_elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
 	else								      \
-		__elv_add_request_core((q), (rq), &(q)->queue_head, 0);	      \
+		_elv_add_request_core((q), (rq), &(q)->queue_head, 0);	      \
 } while (0)
 
-#define elv_add_request(q, rq, back) __elv_add_request((q), (rq), (back), 1)
+#define elv_add_request(q, rq, back) _elv_add_request((q), (rq), (back), 1)
 	
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
diff -urN linux-2.5.2-pre6/include/linux/blkdev.h linux/include/linux/blkdev.h
--- linux-2.5.2-pre6/include/linux/blkdev.h	Thu Jan  3 14:10:33 2002
+++ linux/include/linux/blkdev.h	Thu Jan  3 14:10:38 2002
@@ -25,7 +25,7 @@
 	struct list_head queuelist; /* looking for ->queue? you must _not_
 				     * access it directly, use
 				     * blkdev_dequeue_request! */
-	int elevator_sequence;
+	void *elevator_private;
 
 	unsigned char cmd[16];
 
diff -urN linux-2.5.2-pre6/include/linux/elevator.h linux/include/linux/elevator.h
--- linux-2.5.2-pre6/include/linux/elevator.h	Thu Jan  3 14:10:33 2002
+++ linux/include/linux/elevator.h	Thu Jan  3 14:10:38 2002
@@ -11,36 +11,53 @@
 typedef struct request *(elevator_next_req_fn) (request_queue_t *);
 
 typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *);
+typedef int (elevator_queue_empty_fn) (request_queue_t *);
+typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
 
 typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
 typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *);
 
 struct elevator_s
 {
-	int latency[2];
-
 	elevator_merge_fn *elevator_merge_fn;
 	elevator_merge_cleanup_fn *elevator_merge_cleanup_fn;
 	elevator_merge_req_fn *elevator_merge_req_fn;
 
 	elevator_next_req_fn *elevator_next_req_fn;
 	elevator_add_req_fn *elevator_add_req_fn;
+	elevator_remove_req_fn *elevator_remove_req_fn;
+
+	elevator_queue_empty_fn *elevator_queue_empty_fn;
 
 	elevator_init_fn *elevator_init_fn;
 	elevator_exit_fn *elevator_exit_fn;
+
+	void *elevator_data;
 };
 
-int elevator_noop_merge(request_queue_t *, struct request **, struct bio *);
-void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int);
-void elevator_noop_merge_req(struct request *, struct request *);
-
-int elevator_linus_merge(request_queue_t *, struct request **, struct bio *);
-void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int);
-void elevator_linus_merge_req(struct request *, struct request *);
-int elv_linus_init(request_queue_t *, elevator_t *);
-void elv_linus_exit(request_queue_t *, elevator_t *);
-struct request *elv_next_request_fn(request_queue_t *);
-void elv_add_request_fn(request_queue_t *, struct request *,struct list_head *);
+/*
+ * block elevator interface
+ */
+extern void __elv_add_request(request_queue_t *, struct request *,
+			      struct list_head *);
+extern struct request *__elv_next_request(request_queue_t *);
+extern void elv_merge_cleanup(request_queue_t *, struct request *, int);
+extern int elv_merge(request_queue_t *, struct request **, struct bio *);
+extern void elv_merge_requests(request_queue_t *, struct request *,
+			       struct request *);
+extern void elv_remove_request(request_queue_t *, struct request *);
+
+/*
+ * noop I/O scheduler. always merges, always inserts new request at tail
+ */
+extern elevator_t elevator_noop;
+
+/*
+ * elevator linus. based on linus ideas of starvation control, using
+ * sequencing to manage inserts and merges.
+ */
+extern elevator_t elevator_linus;
+#define elv_linus_sequence(rq)	((long)(rq)->elevator_private)
 
 /*
  * use the /proc/iosched interface, all the below is history ->
@@ -64,48 +81,10 @@
 #define ELEVATOR_FRONT_MERGE	1
 #define ELEVATOR_BACK_MERGE	2
 
-#define elevator_request_latency(e, rw)	((e)->latency[(rw) & 1])
-
 /*
  * will change once we move to a more complex data structure than a simple
  * list for pending requests
  */
 #define elv_queue_empty(q)	list_empty(&(q)->queue_head)
-
-/*
- * elevator private data
- */
-struct elv_linus_data {
-	unsigned long flags;
-};
-
-#define ELV_DAT(e) ((struct elv_linus_data *)(e)->elevator_data)
-
-#define ELV_LINUS_BACK_MERGE	1
-#define ELV_LINUS_FRONT_MERGE	2
-
-#define ELEVATOR_NOOP							\
-((elevator_t) {								\
-	{ 0, 0},							\
-	elevator_noop_merge,		/* elevator_merge_fn */		\
-	elevator_noop_merge_cleanup,	/* elevator_merge_cleanup_fn */	\
-	elevator_noop_merge_req,	/* elevator_merge_req_fn */	\
-	elv_next_request_fn,						\
-	elv_add_request_fn,						\
-	elv_linus_init,							\
-	elv_linus_exit,							\
-	})
-
-#define ELEVATOR_LINUS							\
-((elevator_t) {								\
-	{ 8192, 16384 },						\
-	elevator_linus_merge,		/* elevator_merge_fn */		\
-	elevator_linus_merge_cleanup,	/* elevator_merge_cleanup_fn */	\
-	elevator_linus_merge_req,	/* elevator_merge_req_fn */	\
-	elv_next_request_fn,						\
-	elv_add_request_fn,						\
-	elv_linus_init,							\
-	elv_linus_exit,							\
-	})
 
 #endif
diff -urN linux-2.5.2-pre6/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.5.2-pre6/include/linux/ide.h	Thu Jan  3 14:10:33 2002
+++ linux/include/linux/ide.h	Thu Jan  3 14:10:38 2002
@@ -917,6 +917,12 @@
 int ide_multwrite (ide_drive_t *drive, unsigned int mcount);
 
 /*
+ * idedisk_input_data() is a wrapper around ide_input_data() which copes
+ * with byte-swapping the input data if required.
+ */
+inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+
+/*
  * ide_stall_queue() can be used by a drive to give excess bandwidth back
  * to the hwgroup by sleeping for timeout jiffies.
  */
diff -urN linux-2.5.2-pre6/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.5.2-pre6/include/linux/sched.h	Thu Jan  3 14:10:33 2002
+++ linux/include/linux/sched.h	Thu Jan  3 14:10:38 2002
@@ -302,7 +302,7 @@
  * all fields in a single cacheline that are needed for
  * the goodness() loop in schedule().
  */
-	long dyn_prio;
+	unsigned long dyn_prio;
 	long nice;
 	unsigned long policy;
 	struct mm_struct *mm;
@@ -322,7 +322,6 @@
 	 */
 	struct list_head run_list;
 	long time_slice;
-	unsigned long sleep_time;
 	/* recalculation loop checkpoint */
 	unsigned long rcl_last;
 
@@ -453,7 +452,7 @@
  */
 #define _STK_LIM	(8*1024*1024)
 
-#define MAX_DYNPRIO	100
+#define MAX_DYNPRIO	40
 #define DEF_TSLICE	(6 * HZ / 100)
 #define MAX_TSLICE	(20 * HZ / 100)
 #define DEF_NICE	(0)
@@ -886,7 +885,6 @@
 static inline void del_from_runqueue(struct task_struct * p)
 {
 	nr_running--;
-	p->sleep_time = jiffies;
 	list_del(&p->run_list);
 	p->run_list.next = NULL;
 }
diff -urN linux-2.5.2-pre6/kernel/device.c linux/kernel/device.c
--- linux-2.5.2-pre6/kernel/device.c	Mon Dec 10 14:15:12 2001
+++ linux/kernel/device.c	Thu Jan  3 14:10:38 2002
@@ -732,15 +732,10 @@
 
 	error = -EINVAL;
 
-	if (!num_args) {
-		printk("have no arguments\n");
+	if (!num_args)
 		goto done;
-	}
 
 	if (!strnicmp(str_command,"suspend",7)) {
-
-		printk("%s: we know it's a suspend action\n",__FUNCTION__);
-
 		if (num_args != 3)
 			goto done;
 		if (!strnicmp(str_stage,"notify",6))
@@ -775,8 +770,7 @@
 			error = dev->driver->resume(dev,int_stage);
 		else
 			error = 0;
-	} else
-		printk("%s: couldn't find any thing to do\n",__FUNCTION__);
+	}
  done:
 	put_device(dev);
 
diff -urN linux-2.5.2-pre6/kernel/sched.c linux/kernel/sched.c
--- linux-2.5.2-pre6/kernel/sched.c	Thu Jan  3 14:10:33 2002
+++ linux/kernel/sched.c	Thu Jan  3 14:10:38 2002
@@ -51,11 +51,11 @@
  * NOTE! The unix "nice" value influences how long a process
  * gets. The nice value ranges from -20 to +19, where a -20
  * is a "high-priority" task, and a "+10" is a low-priority
- * task. The default time slice for zero-nice tasks will be 43ms.
+ * task. The default time slice for zero-nice tasks will be 37ms.
  */
 #define NICE_RANGE	40
-#define MIN_NICE_TSLICE	10000
-#define MAX_NICE_TSLICE	80000
+#define MIN_NICE_TSLICE	5000
+#define MAX_NICE_TSLICE	70000
 #define TASK_TIMESLICE(p)	((int) ts_table[19 - (p)->nice])
 
 static unsigned char ts_table[NICE_RANGE];
@@ -538,7 +538,7 @@
 		goto need_resched;
 
 	if (!--p->time_slice) {
-		if (p->dyn_prio > 0) {
+		if (p->dyn_prio) {
 			p->time_slice--;
 			p->dyn_prio--;
 		}
@@ -1070,7 +1070,8 @@
 		current->need_resched = 1;
 
 		current->time_slice = 0;
-		current->dyn_prio++;
+		if (++current->dyn_prio > MAX_DYNPRIO)
+			current->dyn_prio = MAX_DYNPRIO;
 	}
 	return 0;
 }
@@ -1323,9 +1324,12 @@
 {
 	int i;
 
-	for (i = 0; i < NICE_RANGE; i++)
+	for (i = 0; i < NICE_RANGE; i++) {
 		ts_table[i] = ((MIN_NICE_TSLICE +
-						((MAX_NICE_TSLICE - MIN_NICE_TSLICE) / NICE_RANGE) * i) * HZ) / 1000000;
+						((MAX_NICE_TSLICE -
+						  MIN_NICE_TSLICE) / (NICE_RANGE - 1)) * i) * HZ) / 1000000;
+		if (!ts_table[i]) ts_table[i] = 1;
+	}
 }
 
 void __init sched_init(void)
diff -urN linux-2.5.2-pre6/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c
--- linux-2.5.2-pre6/net/irda/ircomm/ircomm_tty.c	Thu Jan  3 14:10:33 2002
+++ linux/net/irda/ircomm/ircomm_tty.c	Thu Jan  3 14:10:38 2002
@@ -386,13 +386,13 @@
 static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
 {
 	struct ircomm_tty_cb *self;
-	int line;
+	unsigned int line;
 	int ret;
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	MOD_INC_USE_COUNT;
-	line = MINOR(tty->device) - tty->driver.minor_start;
+	line = minor(tty->device) - tty->driver.minor_start;
 	if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
 		MOD_DEC_USE_COUNT;
 		return -ENODEV;
diff -urN linux-2.5.2-pre6/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c
--- linux-2.5.2-pre6/net/netlink/netlink_dev.c	Fri Nov  9 14:12:55 2001
+++ linux/net/netlink/netlink_dev.c	Thu Jan  3 14:10:38 2002
@@ -41,7 +41,7 @@
  
 static unsigned int netlink_poll(struct file *file, poll_table * wait)
 {
-	struct socket *sock = netlink_user[MINOR(file->f_dentry->d_inode->i_rdev)];
+	struct socket *sock = netlink_user[minor(file->f_dentry->d_inode->i_rdev)];
 
 	if (sock->ops->poll==NULL)
 		return 0;
@@ -56,7 +56,7 @@
 			     size_t count, loff_t *pos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct socket *sock = netlink_user[MINOR(inode->i_rdev)];
+	struct socket *sock = netlink_user[minor(inode->i_rdev)];
 	struct msghdr msg;
 	struct iovec iov;
 
@@ -80,7 +80,7 @@
 			    size_t count, loff_t *pos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct socket *sock = netlink_user[MINOR(inode->i_rdev)];
+	struct socket *sock = netlink_user[minor(inode->i_rdev)];
 	struct msghdr msg;
 	struct iovec iov;
 
@@ -105,7 +105,7 @@
 
 static int netlink_open(struct inode * inode, struct file * file)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct socket *sock;
 	struct sockaddr_nl nladdr;
 	int err;
@@ -137,7 +137,7 @@
 
 static int netlink_release(struct inode * inode, struct file * file)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	struct socket *sock;
 
 	sock = netlink_user[minor];
@@ -151,7 +151,7 @@
 static int netlink_ioctl(struct inode *inode, struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
-	unsigned int minor = MINOR(inode->i_rdev);
+	unsigned int minor = minor(inode->i_rdev);
 	int retval = 0;
 
 	if (minor >= MAX_LINKS)
