diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Sun Feb 10 19:58:04 2002
+++ b/CREDITS	Sun Feb 10 19:58:04 2002
@@ -990,8 +990,8 @@
 
 N: Nigel Gamble
 E: nigel@nrg.org
-E: nigel@sgi.com
 D: Interrupt-driven printer driver
+D: Preemptible kernel
 S: 120 Alley Way
 S: Mountain View, California 94040
 S: USA
diff -Nru a/Documentation/Changes b/Documentation/Changes
--- a/Documentation/Changes	Sun Feb 10 19:58:05 2002
+++ b/Documentation/Changes	Sun Feb 10 19:58:05 2002
@@ -106,8 +106,8 @@
 your kernel.  This change does, however, mean that you need a recent
 release of binutils.
 
-System utililities
-==================
+System utilities
+================
 
 Architectural changes
 ---------------------
diff -Nru a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
--- a/Documentation/filesystems/Locking	Sun Feb 10 19:58:05 2002
+++ b/Documentation/filesystems/Locking	Sun Feb 10 19:58:05 2002
@@ -237,7 +237,10 @@
 
 ->llseek() locking has moved from llseek to the individual llseek
 implementations.  If your fs is not using generic_file_llseek, you
-need to acquire and release the BKL in your ->llseek().
+need to acquire and release the appropriate locks in your ->llseek().
+For many filesystems, it is probably safe to acquire the inode
+semaphore.  Note some filesystems (i.e. remote ones) provide no
+protection for i_size so you will need to use the BKL.
 
 ->open() locking is in-transit: big lock partially moved into the methods.
 The only exception is ->open() in the instances of file_operations that never
diff -Nru a/Documentation/networking/8139too.txt b/Documentation/networking/8139too.txt
--- a/Documentation/networking/8139too.txt	Sun Feb 10 19:58:04 2002
+++ b/Documentation/networking/8139too.txt	Sun Feb 10 19:58:04 2002
@@ -96,7 +96,10 @@
 KTI KF-230TX
 KTI KF-230TX/2
 Lantech FastNet TX
+Ovislink Fast Ethernet
+Planet ENW-9504 (V.4) 10/100
 SMC EZNET 10/100
+UNEX NexNIC ND012C
 
 (please add your adapter model to this list)
 
@@ -181,11 +184,18 @@
 Change History
 --------------
 
+Version 0.9.23 - In progress
+
+* New, compile-time conditional for testing better RX reset
+* Only account specific RX errors if rx_status is !OK
+
+
 Version 0.9.22 - November 8, 2001
 
 * Additional retries before aborting Tx
 * Do not write other TxConfig bits when writing clear-abort bit.
 * Ack TxErr intr status after each Tx abort, too.
+* Fix oops in interface restart
 
 
 Version 0.9.21 - November 1, 2001
diff -Nru a/Documentation/networking/dl2k.txt b/Documentation/networking/dl2k.txt
--- a/Documentation/networking/dl2k.txt	Sun Feb 10 19:58:04 2002
+++ b/Documentation/networking/dl2k.txt	Sun Feb 10 19:58:04 2002
@@ -1,7 +1,7 @@
 
     D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
-    Nov 12, 2001
+    Jan 02, 2002
 
 Contents
 ========
@@ -182,7 +182,7 @@
 mtu=packet_size			- Specifies the maximum packet size. default
 				  is 1500.
 
-media=xxxxxxxxx			- Specifies the media type the NIC operates at.
+media=media_type		- Specifies the media type the NIC operates at.
 				  autosense	Autosensing active media.
 				  10mbps_hd	10Mbps half duplex.
 				  10mbps_fd	10Mbps full duplex.
@@ -195,28 +195,41 @@
 				  2		10Mbps full duplex.
 				  3		100Mbps half duplex.
 				  4		100Mbps full duplex.
-				  5          	1000Mbps full duplex.
-				  6          	1000Mbps half duplex.
+				  5          	1000Mbps half duplex.
+				  6          	1000Mbps full duplex.
 
 				  By default, the NIC operates at autosense.
 				  Note that only 1000mbps_fd and 1000mbps_hd
 				  types are available for fiber adapter.
 
-vlan=x				- Specifies the VLAN ID. If vlan=0, the
+vlan=[0|1]			- Specifies the VLAN ID. If vlan=0, the
 				  Virtual Local Area Network (VLAN) function is
 				  disable.
 
-jumbo=x				- Specifies the jumbo frame support. If jumbo=1,
+jumbo=[0|1]			- Specifies the jumbo frame support. If jumbo=1,
 				  the NIC accept jumbo frames. By default, this
 				  function is disabled.
 				  Jumbo frame usually improve the performance
 				  int gigabit.
 				  
-int_count			- Rx frame count each interrupt.
-int_timeout			- Rx DMA wait time for an interrupt. Proper 
-				  values of int_count and int_timeout bring 
-				  a conspicuous performance in the fast machine. 
-				  Ex. int_count=5 and int_timeout=750 
+rx_coalesce=n			- Rx frame count each interrupt.
+rx_timeout=n			- Rx DMA wait time for an interrupt. Proper 
+				  values of rx_coalesce and rx_timeout bring 
+				  a conspicuous performance in the fast machine.
+				  Ex. rx_coalesce=5 and rx_timeout=750 
+
+tx_coalesce=n			- Tx transmit count each TxComp interrupt.
+				  Setting value larger than 1 will improve 
+				  performance, but this is possible to lower 
+				  stability in slow UP machines. By default, 
+				  tx_coalesce=1. (dl2k)
+				  
+tx_flow=[1|0]			- Specifies the Tx flow control. If tx_flow=1, 
+				  the Tx flow control enable.
+				  
+rx_flow=[1|0]			- Specifies the Rx flow control. If rx_flow=1, 
+				  the Rx flow control enable.
+
 
 Configuration Script Sample
 ===========================
diff -Nru a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
--- a/Documentation/oops-tracing.txt	Sun Feb 10 19:58:05 2002
+++ b/Documentation/oops-tracing.txt	Sun Feb 10 19:58:05 2002
@@ -219,6 +219,11 @@
   2: 'F' if any module was force loaded by insmod -f, ' ' if all
      modules were loaded normally.
 
+  3: 'S' if the oops occured on an SMP kernel running on hardware that
+      hasn't been certified as safe to run multiprocessor.
+	  Currently this occurs only on various Athlons that are not
+	  SMP capable.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent, even if an offending module is
diff -Nru a/Documentation/preempt-locking.txt b/Documentation/preempt-locking.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/preempt-locking.txt	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,104 @@
+		  Proper Locking Under a Preemptible Kernel:
+		       Keeping Kernel Code Preempt-Safe
+			  Robert Love <rml@tech9.net>
+			   Last Updated: 22 Jan 2002
+
+
+INTRODUCTION
+
+
+A preemptible kernel creates new locking issues.  The issues are the same as
+those under SMP: concurrency and reentrancy.  Thankfully, the Linux preemptible
+kernel model leverages existing SMP locking mechanisms.  Thus, the kernel
+requires explicit additional locking for very few additional situations.
+
+This document is for all kernel hackers.  Developing code in the kernel
+requires protecting these situations.
+ 
+
+RULE #1: Per-CPU data structures need explicit protection
+
+
+Two similar problems arise. An example code snippet:
+
+	struct this_needs_locking tux[NR_CPUS];
+	tux[smp_processor_id()] = some_value;
+	/* task is preempted here... */
+	something = tux[smp_processor_id()];
+
+First, since the data is per-CPU, it may not have explicit SMP locking, but
+require it otherwise.  Second, when a preempted task is finally rescheduled,
+the previous value of smp_processor_id may not equal the current.  You must
+protect these situations by disabling preemption around them.
+
+
+RULE #2: CPU state must be protected.
+
+
+Under preemption, the state of the CPU must be protected.  This is arch-
+dependent, but includes CPU structures and state not preserved over a context
+switch.  For example, on x86, entering and exiting FPU mode is now a critical
+section that must occur while preemption is disabled.  Think what would happen
+if the kernel is executing a floating-point instruction and is then preempted.
+Remember, the kernel does not save FPU state except for user tasks.  Therefore,
+upon preemption, the FPU registers will be sold to the lowest bidder.  Thus,
+preemption must be disabled around such regions.
+
+Note, some FPU functions are already explicitly preempt safe.  For example,
+kernel_fpu_begin and kernel_fpu_end will disable and enable preemption.
+However, math_state_restore must be called with preemption disabled.
+
+
+RULE #3: Lock acquire and release must be performed by same task
+
+
+A lock acquired in one task must be released by the same task.  This
+means you can't do oddball things like acquire a lock and go off to
+play while another task releases it.  If you want to do something
+like this, acquire and release the task in the same code path and
+have the caller wait on an event by the other task.
+
+
+SOLUTION
+
+
+Data protection under preemption is achieved by disabling preemption for the
+duration of the critical region.
+
+preempt_enable()		decrement the preempt counter
+preempt_disable()		increment the preempt counter
+preempt_enable_no_resched()	decrement, but do not immediately preempt
+preempt_get_count()		return the preempt counter
+
+The functions are nestable.  In other words, you can call preempt_disable
+n-times in a code path, and preemption will not be reenabled until the n-th
+call to preempt_enable.  The preempt statements define to nothing if
+preemption is not enabled.
+
+Note that you do not need to explicitly prevent preemption if you are holding
+any locks or interrupts are disabled, since preemption is implicitly disabled
+in those cases.
+
+Example:
+
+	cpucache_t *cc; /* this is per-CPU */
+	preempt_disable();
+	cc = cc_data(searchp);
+	if (cc && cc->avail) {
+		__free_block(searchp, cc_entry(cc), cc->avail);
+		cc->avail = 0;
+	}
+	preempt_enable();
+	return 0;
+
+Notice how the preemption statements must encompass every reference of the
+critical variables.  Another example:
+
+	int buf[NR_CPUS];
+	set_cpu_val(buf);
+	if (buf[smp_processor_id()] == -1) printf(KERN_INFO "wee!\n");
+	spin_lock(&buf_lock);
+	/* ... */
+
+This code is not preempt-safe, but see how easily we can fix it by simply
+moving the spin_lock up two lines.
diff -Nru a/Documentation/usb/ibmcam.txt b/Documentation/usb/ibmcam.txt
--- a/Documentation/usb/ibmcam.txt	Sun Feb 10 19:58:06 2002
+++ b/Documentation/usb/ibmcam.txt	Sun Feb 10 19:58:06 2002
@@ -25,12 +25,19 @@
 
 SUPPORTED CAMERAS:
 
-IBM "C-It" camera, also known as "Xirlink PC Camera"
+Xirlink "C-It" camera, also known as "IBM PC Camera".
 The device uses proprietary ASIC (and compression method);
 it is manufactured by Xirlink. See http://www.xirlink.com/
 http://www.ibmpccamera.com or http://www.c-itnow.com/ for
 details and pictures.
 
+This very chipset ("X Chip", as marked at the factory)
+is used in several other cameras, and they are supported
+as well:
+
+- IBM NetCamera
+- Veo Stingray
+
 The Linux driver was developed with camera with following
 model number (or FCC ID): KSX-XVP510. This camera has three
 interfaces, each with one endpoint (control, iso, iso). This
@@ -50,12 +57,30 @@
 Such type of cameras is referred to as "model 2". They are supported
 (with exception of 352x288 native mode).
 
+Some IBM NetCameras (Model 4) are made to generate only compressed
+video streams. This is great for performance, but unfortunately
+nobody knows how to decompress the stream :-( Therefore, these
+cameras are *unsupported* and if you try to use one of those, all
+you get is random colored horizontal streaks, not the image!
+If you have one of those cameras, you probably should return it
+to the store and get something that is supported.
+
+Tell me more about all that "model" business
+--------------------------------------------
+
+I just invented model numbers to uniquely identify flavors of the
+hardware/firmware that were sold. It was very confusing to use
+brand names or some other internal numbering schemes. So I found
+by experimentation that all Xirlink chipsets fall into four big
+classes, and I called them "models". Each model is programmed in
+its own way, and each model sends back the video in its own way.
+
 Quirks of Model 2 cameras:
 -------------------------
 
 Model 2 does not have hardware contrast control. Corresponding V4L
-control is not used at the moment. It may be possible to implement
-contrast control in software, at cost of extra processor cycles.
+control is implemented in software, which is not very nice to your
+CPU, but at least it works.
 
 This driver provides 352x288 mode by switching the camera into
 quasi-352x288 RGB mode (800 Kbits per frame) essentially limiting
@@ -67,17 +92,24 @@
 the frame rate at slowest setting, but I had to move it pretty much down
 the scale (so that framerate option barely matters). I also noticed that
 camera after first powering up produces frames slightly faster than during
-consecutive uses. All this means that if you use videosize=2 (which is
+consecutive uses. All this means that if you use 352x288 (which is
 default), be warned - you may encounter broken picture on first connect;
 try to adjust brightness - brighter image is slower, so USB will be able
 to send all data. However if you regularly use Model 2 cameras you may
-prefer videosize=1 which makes perfectly good I420, with no scaling and
+prefer 176x144 which makes perfectly good I420, with no scaling and
 lesser demands on USB (300 Kbits per second, or 26 frames per second).
 
+Another strange effect of 352x288 mode is the fine vertical grid visible
+on some colored surfaces. I am sure it is caused by me not understanding
+what the camera is trying to say. Blame trade secrets for that.
+
 The camera that I had also has a hardware quirk: if disconnected,
 it needs few minutes to "relax" before it can be plugged in again
 (poorly designed USB processor reset circuit?)
 
+[Veo Stingray with Product ID 0x800C is also Model 2, but I haven't
+observed this particular flaw in it.]
+
 Model 2 camera can be programmed for very high sensitivity (even starlight
 may be enough), this makes it convenient for tinkering with. The driver
 code has enough comments to help a programmer to tweak the camera
@@ -98,12 +130,14 @@
 precompile all modules, so you can go directly to the next
 section "HOW TO USE THE DRIVER".
 
-The driver consists of two files in usb/ directory:
-ibmcam.c and ibmcam.h These files are included into the
-Linux kernel build process if you configure the kernel
-for CONFIG_USB_IBMCAM. Run "make xconfig" and in USB section
-you will find the IBM camera driver. Select it, save the
-configuration and recompile.
+The ibmcam driver uses usbvideo helper library (module),
+so if you are studying the ibmcam code you will be led there.
+
+The driver itself consists of only one file in usb/ directory:
+ibmcam.c. This file is included into the Linux kernel build
+process if you configure the kernel for CONFIG_USB_IBMCAM.
+Run "make xconfig" and in USB section you will find the IBM
+camera driver. Select it, save the configuration and recompile.
 
 HOW TO USE THE DRIVER:
 
@@ -112,6 +146,13 @@
 settings than V4L can operate, so some settings are done using
 module options.
 
+To begin with, on most modern Linux distributions the driver
+will be automatically loaded whenever you plug the supported
+camera in. Therefore, you don't need to do anything. However
+if you want to experiment with some module parameters then
+you can load and unload the driver manually, with camera
+plugged in or unplugged.
+
 Typically module is installed with command 'modprobe', like this:
 
 # modprobe ibmcam framerate=1
@@ -138,7 +179,7 @@
 init_hue        Integer         0-255 [128]     init_hue=115
 lighting        Integer         0-2* [1]        lighting=2
 sharpness       Integer         0-6* [4]        sharpness=3
-videosize       Integer         0-2* [2]        videosize=1
+size            Integer         0-2* [2]        size=1
 
 Options for Model 2 only:
 
@@ -181,6 +222,11 @@
                                            this is a little faster but may
                                            produce flicker if frame rate is
                                            too high and Isoc data gets lost.
+                FLAGS_NO_DECODING      128 This flag turns the video stream
+                                           decoder off, and dumps the raw
+                                           Isoc data from the camera into
+                                           the reading process. Useful to
+                                           developers, but not to users.
 
 framerate       This setting controls frame rate of the camera. This is
                 an approximate setting (in terms of "worst" ... "best")
@@ -227,35 +273,38 @@
                 be greeted with "snowy" image. Default is 4. Model 2
                 cameras do not support this feature.
 
-videosize       This setting chooses one if three image sizes that are
-                supported by this driver. Camera supports more, but
+size            This setting chooses one of several image sizes that are
+                supported by this driver. Cameras may support more, but
                 it's difficult to reverse-engineer all formats.
                 Following video sizes are supported:
 
-                videosize=0     128x96  (Model 1 only)
-                videosize=1     176x144
-                videosize=2     352x288
-                videosize=3     320x240 (Model 2 only)
-                videosize=4     352x240 (Model 2 only)
+                size=0     128x96  (Model 1 only)
+                size=1     160x120
+                size=2     176x144
+                size=3     320x240 (Model 2 only)
+                size=4     352x240 (Model 2 only)
+                size=5     352x288
+                size=6     640x480 (Model 3 only)
 
-                The last one (352x288) is the native size of the sensor
-                array, so it's the best resolution camera (Model 1) can
+                The 352x288 is the native size of the Model 1 sensor
+                array, so it's the best resolution the camera can
                 yield. The best resolution of Model 2 is 176x144, and
                 larger images are produced by stretching the bitmap.
+                Model 3 has sensor with 640x480 grid, and it works too,
+                but the frame rate will be exceptionally low (1-2 FPS);
+                it may be still OK for some applications, like security.
                 Choose the image size you need. The smaller image can
                 support faster frame rate. Default is 352x288.
 
+For more information and the Troubleshooting FAQ visit this URL:
+
+                http://www.linux-usb.org/ibmcam/
+
 WHAT NEEDS TO BE DONE:
 
-- The box freezes if camera is unplugged after being used (OHCI).
-  Workaround: remove usb-ohci module first.
-- On occasion camera (model 1) does not start properly (xawtv reports
-  errors), or camera produces negative image (funny colors.)
-  Workaround: reload the driver module. Reason: [1].
 - The button on the camera is not used. I don't know how to get to it.
   I know now how to read button on Model 2, but what to do with it?
 
-[1]
 - Camera reports its status back to the driver; however I don't know
   what returned data means. If camera fails at some initialization
   stage then something should be done, and I don't do that because
@@ -263,26 +312,13 @@
   concern because Model 2 uses different commands which do not return
   status (and seem to complete successfully every time).
 
-VIDEO SIZE AND IMAGE SIZE
-
-Camera produces picture X by Y pixels. This is camera-specific and can be
-altered by programming the camera accordingly. This image is placed onto
-larger (or equal) area W by H, this is V4L image. At this time the driver
-uses V4L image size (W by H) 352x288 pixels because many programs (such
-as xawtv) expect quite specific sizes and don't want to deal with arbitrary,
-camera-specific sizes. However this approach "hides" real image size, and
-application always sees the camera as producing only 352x288 image. It is
-possible to change the V4L image size to 128x96, and then if camera is
-switched to 128x96 mode then xawtv will correctly accept this image size. But
-many other popular sizes (such as 176x144) will not be welcomed. This is the
-reason why all camera images are at this time placed onto 352x288 "canvas",
-and size of that canvas (V4L) is reported to applications. It will be easy
-to add options to control the canvas size, but it will be application-
-specific because not all applications are ready to work with variety of
-camera-specific sizes.
+- Some flavors of Model 4 NetCameras produce only compressed video
+  streams, and I don't know how to decode them.
 
 CREDITS:
 
 The code is based in no small part on the CPiA driver by Johannes Erdfelt,
 Randy Dunlap, and others. Big thanks to them for their pioneering work on that
 and the USB stack.
+
+I also thank John Lightsey for his donation of the Veo Stingray camera.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Sun Feb 10 19:58:04 2002
+++ b/MAINTAINERS	Sun Feb 10 19:58:04 2002
@@ -1239,6 +1239,14 @@
 M:	mostrows@styx.uwaterloo.ca
 S:	Maintained
 
+PREEMPTIBLE KERNEL
+P:	Robert Love
+M:	rml@tech9.net
+L:	linux-kernel@vger.kernel.org
+L:	kpreempt-tech@lists.sourceforge.net
+W:	ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
+S:	Supported
+
 PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
 P:	Peter Denison
 M:	promise@pnd-pc.demon.co.uk
@@ -1581,8 +1589,8 @@
 S:	Maintained
 
 USB KAWASAKI LSI DRIVER
-P:	Brad Hards
-M:	bradh@frogmouth.net
+P:	Oliver Neukum
+M:	drivers@neukum.org
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Sun Feb 10 19:58:04 2002
+++ b/Makefile	Sun Feb 10 19:58:04 2002
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 3
+SUBLEVEL = 4
 EXTRAVERSION =
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
@@ -140,7 +140,6 @@
 DRIVERS-$(CONFIG_AGP) += drivers/char/agp/agp.o
 DRIVERS-$(CONFIG_DRM) += drivers/char/drm/drm.o
 DRIVERS-$(CONFIG_NUBUS) += drivers/nubus/nubus.a
-DRIVERS-$(CONFIG_ISDN) += drivers/isdn/isdn.a
 DRIVERS-$(CONFIG_NET_FC) += drivers/net/fc/fc.o
 DRIVERS-$(CONFIG_APPLETALK) += drivers/net/appletalk/appletalk.o
 DRIVERS-$(CONFIG_TR) += drivers/net/tokenring/tr.o
@@ -178,6 +177,8 @@
 DRIVERS-$(CONFIG_TC) += drivers/tc/tc.a
 DRIVERS-$(CONFIG_USB) += drivers/usb/usbdrv.o
 DRIVERS-$(CONFIG_INPUT) += drivers/input/inputdrv.o
+DRIVERS-$(CONFIG_GAMEPORT) += drivers/input/gameport/gamedrv.o
+DRIVERS-$(CONFIG_SERIO) += drivers/input/serio/seriodrv.o
 DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o
 DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
 DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
@@ -185,6 +186,7 @@
 DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
 DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o
 DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
+DRIVERS-$(CONFIG_ISDN) += drivers/isdn/vmlinux-obj.o
 
 DRIVERS := $(DRIVERS-y)
 
@@ -205,7 +207,7 @@
 	drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \
 	drivers/scsi/aic7xxx/aicasm/y.tab.h \
 	drivers/scsi/aic7xxx/aicasm/aicasm \
-	drivers/scsi/53c700-mem.c \
+	drivers/scsi/53c700_d.h \
 	net/khttpd/make_times_h \
 	net/khttpd/times.h \
 	submenu*
@@ -330,11 +332,13 @@
 	@echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver
 	@mv -f .ver $@
 
+comma	:= ,
+
 init/version.o: init/version.c include/linux/compile.h include/config/MARKER
-	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
+	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(ARCH)"' -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o init/version.o init/version.c
 
 init/main.o: init/main.c include/config/MARKER
-	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
+	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o $*.o $<
 
 init/do_mounts.o: init/do_mounts.c include/config/MARKER
 	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
diff -Nru a/Rules.make b/Rules.make
--- a/Rules.make	Sun Feb 10 19:58:05 2002
+++ b/Rules.make	Sun Feb 10 19:58:05 2002
@@ -31,6 +31,8 @@
 unexport subdir-n
 unexport subdir-
 
+comma	:= ,
+
 #
 # Get things started.
 #
@@ -54,7 +56,7 @@
 	$(CPP) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) $< > $@
 
 %.o: %.c
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -c -o $@ $<
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
 	@ ( \
 	    echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@))))' ; \
 	    echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
@@ -270,7 +272,7 @@
 
 ifneq "$(strip $(export-objs))" ""
 $(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
 	@ ( \
 	    echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \
 	    echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
diff -Nru a/arch/alpha/Config.help b/arch/alpha/Config.help
--- a/arch/alpha/Config.help	Sun Feb 10 19:58:04 2002
+++ b/arch/alpha/Config.help	Sun Feb 10 19:58:04 2002
@@ -597,31 +597,6 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_SRM_ENV
   If you enable this option, a subdirectory called srm_environment
   will give you access to the most important SRM environment
diff -Nru a/arch/alpha/defconfig b/arch/alpha/defconfig
--- a/arch/alpha/defconfig	Sun Feb 10 19:58:06 2002
+++ b/arch/alpha/defconfig	Sun Feb 10 19:58:06 2002
@@ -12,6 +12,14 @@
 CONFIG_EXPERIMENTAL=y
 
 #
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
 # Loadable module support
 #
 CONFIG_MODULES=y
@@ -63,10 +71,6 @@
 CONFIG_PCI_NAMES=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
 CONFIG_KCORE_ELF=y
 # CONFIG_KCORE_AOUT is not set
 # CONFIG_BINFMT_AOUT is not set
@@ -89,6 +93,7 @@
 #
 CONFIG_PNP=y
 CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
 
 #
 # Block devices
@@ -98,6 +103,7 @@
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_NBD is not set
@@ -121,7 +127,7 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK is not set
+CONFIG_NETLINK_DEV=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 # CONFIG_FILTER is not set
@@ -133,6 +139,7 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
 CONFIG_INET_ECN=y
 # CONFIG_SYN_COOKIES is not set
 
@@ -142,12 +149,14 @@
 CONFIG_IP_NF_CONNTRACK=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 # CONFIG_IP_NF_MATCH_LIMIT is not set
 # CONFIG_IP_NF_MATCH_MAC is not set
 # CONFIG_IP_NF_MATCH_MARK is not set
 # CONFIG_IP_NF_MATCH_MULTIPORT is not set
 # CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
 # CONFIG_IP_NF_MATCH_LENGTH is not set
 # CONFIG_IP_NF_MATCH_TTL is not set
 # CONFIG_IP_NF_MATCH_TCPMSS is not set
@@ -166,6 +175,7 @@
 CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
 # CONFIG_IP_NF_TARGET_TCPMSS is not set
 CONFIG_IP_NF_COMPAT_IPCHAINS=y
 CONFIG_IP_NF_NAT_NEEDED=y
@@ -212,6 +222,7 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
 # CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
 # CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
 # CONFIG_BLK_DEV_IDEDISK_IBM is not set
@@ -226,6 +237,7 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
 
 #
 # IDE chipset support/bugfixes
@@ -237,12 +249,15 @@
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_AEC62XX_TUNING is not set
 CONFIG_BLK_DEV_ALI15X3=y
@@ -257,6 +272,7 @@
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC_ADMA is not set
 # CONFIG_BLK_DEV_PDC202XX is not set
 # CONFIG_PDC202XX_BURST is not set
 # CONFIG_PDC202XX_FORCE is not set
@@ -294,7 +310,6 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -331,6 +346,7 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
 CONFIG_SCSI_NCR53C8XX=y
 CONFIG_SCSI_SYM53C8XX=y
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
@@ -356,6 +372,15 @@
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_BOOT is not set
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LAN is not set
+
+#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -368,6 +393,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
 #
@@ -378,7 +404,6 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNBMAC is not set
 # CONFIG_SUNQE is not set
-# CONFIG_SUNLANCE is not set
 # CONFIG_SUNGEM is not set
 CONFIG_NET_VENDOR_3COM=y
 # CONFIG_EL1 is not set
@@ -403,23 +428,32 @@
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
-# CONFIG_DE4X5 is not set
+CONFIG_DE2104X=m
 CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_DE4X5 is not set
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139CP is not set
 # CONFIG_8139TOO is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_NEW_RX_RESET is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_NET_POCKET is not set
 
@@ -497,19 +531,6 @@
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-
-#
-# Input core support is needed for gameports
-#
-
-#
-# Input core support is needed for joysticks
-#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -543,11 +564,15 @@
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_REISERFS_FS=m
 # CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 # CONFIG_UMSDOS_FS is not set
@@ -557,7 +582,7 @@
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 CONFIG_TMPFS=y
-# CONFIG_RAMFS is not set
+CONFIG_RAMFS=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
@@ -585,6 +610,7 @@
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_ROOT_NFS is not set
@@ -604,7 +630,6 @@
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 # CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
 
 #
 # Partition Types
@@ -677,8 +702,10 @@
 # CONFIG_USB is not set
 
 #
-# USB Controllers
+# USB Host Controller Drivers
 #
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
 # CONFIG_USB_UHCI is not set
 # CONFIG_USB_UHCI_ALT is not set
 # CONFIG_USB_OHCI is not set
@@ -750,6 +777,7 @@
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
 # CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
 # CONFIG_USB_SERIAL_IR is not set
 # CONFIG_USB_SERIAL_EDGEPORT is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
@@ -763,6 +791,7 @@
 # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
@@ -772,15 +801,26 @@
 # USB Miscellaneous drivers
 #
 # CONFIG_USB_RIO500 is not set
+# CONFIG_USB_AUERSWALD is not set
 
 #
-# Input core support
+# Input device support
 #
 # CONFIG_INPUT is not set
 # CONFIG_INPUT_KEYBDEV is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_GAMEPORT_PCIGAME is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461x is not set
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_SERPORT is not set
 
 #
 # Bluetooth support
@@ -795,3 +835,13 @@
 CONFIG_MATHEMU=y
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_RWLOCK is not set
+# CONFIG_DEBUG_SEMAPHORE is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
--- a/arch/alpha/kernel/entry.S	Sun Feb 10 19:58:03 2002
+++ b/arch/alpha/kernel/entry.S	Sun Feb 10 19:58:03 2002
@@ -1148,3 +1148,4 @@
 	.quad sys_gettid
 	.quad sys_readahead
 	.quad sys_ni_syscall			/* 380, sys_security */
+	.quad sys_tkill
diff -Nru a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
--- a/arch/alpha/kernel/setup.c	Sun Feb 10 19:58:04 2002
+++ b/arch/alpha/kernel/setup.c	Sun Feb 10 19:58:04 2002
@@ -436,8 +436,8 @@
 
 static kdev_t srm_console_device(struct console *c)
 {
-  /* Huh? */
-        return MKDEV(TTY_MAJOR, 64 + c->index);
+	/* Huh? */
+        return mk_kdev(TTY_MAJOR, 64 + c->index);
 }
 
 static int __init srm_console_setup(struct console *co, char *options)
diff -Nru a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
--- a/arch/alpha/kernel/signal.c	Sun Feb 10 19:58:06 2002
+++ b/arch/alpha/kernel/signal.c	Sun Feb 10 19:58:06 2002
@@ -717,9 +717,7 @@
 
 			default:
 				lock_kernel();
-				sigaddset(&current->pending.signal, signr);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 			continue;
diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
--- a/arch/alpha/mm/fault.c	Sun Feb 10 19:58:05 2002
+++ b/arch/alpha/mm/fault.c	Sun Feb 10 19:58:05 2002
@@ -196,8 +196,7 @@
  */
 out_of_memory:
 	if (current->pid == 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
diff -Nru a/arch/arm/Config.help b/arch/arm/Config.help
--- a/arch/arm/Config.help	Sun Feb 10 19:58:03 2002
+++ b/arch/arm/Config.help	Sun Feb 10 19:58:03 2002
@@ -471,31 +471,6 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_ARCH_ARCA5K
   This selects what ARM system you wish to build the kernel for. It
   also selects to some extent the CPU type. If you are unsure what
diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S	Sun Feb 10 19:58:06 2002
+++ b/arch/arm/kernel/calls.S	Sun Feb 10 19:58:06 2002
@@ -236,6 +236,8 @@
 		.long	SYMBOL_NAME(sys_mincore)
 /* 220 */	.long	SYMBOL_NAME(sys_madvise)
 		.long	SYMBOL_NAME(sys_fcntl64)
+		.long	SYMBOL_NAME(sys_gettid)
+		.long	SYMBOL_NAME(sys_tkill)
 __syscall_end:
 
 		.rept	NR_syscalls - (__syscall_end - __syscall_start) / 4
diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
--- a/arch/arm/kernel/signal.c	Sun Feb 10 19:58:03 2002
+++ b/arch/arm/kernel/signal.c	Sun Feb 10 19:58:03 2002
@@ -637,10 +637,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/arm/mach-clps711x/dma.c b/arch/arm/mach-clps711x/dma.c
--- a/arch/arm/mach-clps711x/dma.c	Sun Feb 10 19:58:06 2002
+++ b/arch/arm/mach-clps711x/dma.c	Sun Feb 10 19:58:06 2002
@@ -18,7 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mman.h>
 #include <linux/init.h>
 
diff -Nru a/arch/cris/Config.help b/arch/cris/Config.help
--- a/arch/cris/Config.help	Sun Feb 10 19:58:04 2002
+++ b/arch/cris/Config.help	Sun Feb 10 19:58:04 2002
@@ -171,31 +171,6 @@
   Kernel patches and supporting utilities to do that are in the pcsp
   package, available at <ftp://ftp.infradead.org/pub/pcsp/>.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_ETRAX100LX
   Support version 1 of the Etrax 100LX.
 
diff -Nru a/arch/cris/cris.ld b/arch/cris/cris.ld
--- a/arch/cris/cris.ld	Sun Feb 10 19:58:06 2002
+++ b/arch/cris/cris.ld	Sun Feb 10 19:58:06 2002
@@ -24,7 +24,6 @@
 		*(.fixup)
 		*(.text.__*)
 	}
-  	.text.lock : { *(.text.lock) }        /* out-of-line lock text */
 
 	_etext = . ;                  /* End of text section */ 
 	__etext = .;
diff -Nru a/arch/cris/drivers/eeprom.c b/arch/cris/drivers/eeprom.c
--- a/arch/cris/drivers/eeprom.c	Sun Feb 10 19:58:05 2002
+++ b/arch/cris/drivers/eeprom.c	Sun Feb 10 19:58:05 2002
@@ -74,6 +74,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include "i2c.h"
 
@@ -448,36 +449,39 @@
  *  orig 1: relative from current position
  *  orig 2: position from last eeprom address
  */
-  
+  loff_t ret;
+
+  lock_kernel();
   switch (orig)
   {
    case 0:
-     file->f_pos = offset;
+     ret = file->f_pos = offset;
      break;
    case 1:
-     file->f_pos += offset;
+     ret = file->f_pos += offset;
      break;
    case 2:
-     file->f_pos = eeprom.size - offset;
+     ret = file->f_pos = eeprom.size - offset;
      break;
    default:
-     return -EINVAL;
+     ret = -EINVAL;
   }
 
   /* truncate position */
   if (file->f_pos < 0)
   {
     file->f_pos = 0;    
-    return(-EOVERFLOW);
+    unlock_kernel();
+    ret = -EOVERFLOW;
   }
   
   if (file->f_pos >= eeprom.size)
   {
     file->f_pos = eeprom.size - 1;
-    return(-EOVERFLOW);
+    ret = -EOVERFLOW;
   }
 
-  return ( file->f_pos );
+  return ( ret );
 }
 
 /* Reads data from eeprom. */
diff -Nru a/arch/cris/drivers/usb-host.c b/arch/cris/drivers/usb-host.c
--- a/arch/cris/drivers/usb-host.c	Sun Feb 10 19:58:05 2002
+++ b/arch/cris/drivers/usb-host.c	Sun Feb 10 19:58:05 2002
@@ -210,12 +210,12 @@
 static void etrax_usb_free_epid(char epid);
 static void cleanup_sb(USB_SB_Desc_t *sb);
 
-static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen);
-static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen);
+static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags);
+static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags);
 
-static int etrax_usb_submit_ctrl_urb(struct urb *urb);
+static int etrax_usb_submit_ctrl_urb(struct urb *urb, int mem_flags);
 
-static int etrax_usb_submit_urb(struct urb *urb);
+static int etrax_usb_submit_urb(struct urb *urb, int mem_flags);
 static int etrax_usb_unlink_urb(struct urb *urb);
 static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
 static int etrax_usb_allocate_dev(struct usb_device *usb_dev);
@@ -512,7 +512,7 @@
 	} while (tmp_ep != first_ep);
 }
 
-static int etrax_usb_submit_intr_urb(struct urb *urb)
+static int etrax_usb_submit_intr_urb(struct urb *urb, mem_flags)
 {
 	USB_EP_Desc_t *tmp_ep;
 	USB_EP_Desc_t *first_ep;
@@ -556,7 +556,7 @@
 	}
 	/* Ok, now we got valid endpoint, lets insert some traffic */
 
-	urb_priv = (etrax_urb_priv_t *)kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);
+	urb_priv = (etrax_urb_priv_t *)kmalloc(sizeof(etrax_urb_priv_t), mem_flags);
 	urb_priv->first_sb = 0;
 	urb_priv->rx_offset = 0;
 	urb_priv->eot = 0;
@@ -591,9 +591,9 @@
 				USB_SB_Desc_t *traffic_sb;
 
 				traffic_ep = (USB_EP_Desc_t *)
-					kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+					kmem_cache_alloc(usb_desc_cache, mem_flags);
 				traffic_sb = (USB_SB_Desc_t *)
-					kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+					kmem_cache_alloc(usb_desc_cache, mem_flags);
 
 				traffic_ep->hw_len = 0;
 				traffic_ep->command = IO_FIELD(USB_EP_command, epid, epid) |
@@ -904,7 +904,7 @@
 	return -1;
 }
 
-static int etrax_usb_submit_bulk_urb(struct urb *urb)
+static int etrax_usb_submit_bulk_urb(struct urb *urb, int mem_flags)
 {
 	char epid;
 	char devnum;
@@ -954,7 +954,7 @@
 		/* If this is the first URB, add the URB and do HW add */
 		URB_List[epid] = urb;
 		restore_flags(flags);
-		etrax_usb_do_bulk_hw_add(urb, epid, maxlen);
+		etrax_usb_do_bulk_hw_add(urb, epid, maxlen, mem_flags);
 	}
 
 	DBFEXIT;
@@ -962,7 +962,7 @@
 	return 0;
 }
 
-static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen)
+static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags)
 {
 	USB_SB_Desc_t *sb_desc_1;
 
@@ -973,8 +973,8 @@
 
 	DBFENTER;
 
-	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);
-	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), mem_flags);
+	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
 
 	if (usb_pipeout(urb->pipe)) {
 
@@ -1135,7 +1135,8 @@
 	if (URB_List[epid]) {
 		etrax_usb_do_bulk_hw_add(URB_List[epid], epid,
 					 usb_maxpacket(URB_List[epid]->dev, URB_List[epid]->pipe,
-						       usb_pipeout(URB_List[epid]->pipe)));
+						       usb_pipeout(URB_List[epid]->pipe)),
+					 GFP_KERNEL);
 	}
 #if 1
 	else {
@@ -1159,7 +1160,7 @@
 
 /* ---------------------------------------------------------------------------- */
 
-static int etrax_usb_submit_ctrl_urb(struct urb *urb)
+static int etrax_usb_submit_ctrl_urb(struct urb *urb, int mem_flags)
 {
 	char epid;
 	char devnum;
@@ -1209,7 +1210,7 @@
 		/* If this is the first URB, add the URB and do HW add */
 		URB_List[epid] = urb;
 		restore_flags(flags);
-		etrax_usb_do_ctrl_hw_add(urb, epid, maxlen);
+		etrax_usb_do_ctrl_hw_add(urb, epid, maxlen, mem_flags);
 	}
 
 	DBFEXIT;
@@ -1217,7 +1218,7 @@
 	return 0;
 }
 
-static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen)
+static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags)
 {
 	USB_SB_Desc_t *sb_desc_1;
 	USB_SB_Desc_t *sb_desc_2;
@@ -1231,9 +1232,9 @@
 
 	DBFENTER;
 
-	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);
-	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
-	sb_desc_2 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), mem_flags);
+	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
+	sb_desc_2 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
 
 	if (!(sb_desc_1 && sb_desc_2)) {
 		panic("kmem_cache_alloc in ctrl_hw_add gave NULL pointers !!!\n");
@@ -1257,7 +1258,7 @@
 		
 		if (urb->transfer_buffer) {
 			dbg_ctrl("This OUT transfer has an extra data stage");
-			sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+			sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
 
 			sb_desc_1->next = virt_to_phys(sb_desc_3);
 			
@@ -1285,7 +1286,7 @@
 		dbg_ctrl("transfer_buffer_length = %d", urb->transfer_buffer_length);
 		dbg_ctrl("rem is calculated to %d", urb->transfer_buffer_length % maxlen);
 
-		sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+		sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
 		
 		sb_desc_2->sw_len = urb->transfer_buffer_length ?
 			(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
@@ -1358,7 +1359,7 @@
 	DBFEXIT;
 }
 
-static int etrax_usb_submit_urb(struct urb *urb)
+static int etrax_usb_submit_urb(struct urb *urb, int mem_flags)
 {
 	etrax_hc_t *hc;
 	int rval = -EINVAL;
@@ -1375,10 +1376,10 @@
 		rval = etrax_rh_submit_urb(urb);
 		
 	} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
-		rval = etrax_usb_submit_ctrl_urb(urb);
+		rval = etrax_usb_submit_ctrl_urb(urb, mem_flags);
 
 	} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-		rval = etrax_usb_submit_bulk_urb(urb);
+		rval = etrax_usb_submit_bulk_urb(urb, mem_flags);
 
 	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
 		int bustime;
@@ -1389,7 +1390,7 @@
 				rval = bustime;
 			} else {
 				usb_claim_bandwidth(urb->dev, urb, bustime, 0);
-				rval = etrax_usb_submit_intr_urb(urb);
+				rval = etrax_usb_submit_intr_urb(urb, mem_flags);
 			}
 			
 		}
@@ -1683,7 +1684,8 @@
 	if (URB_List[epid]) {
 		etrax_usb_do_ctrl_hw_add(URB_List[epid], epid,
 					 usb_maxpacket(URB_List[epid]->dev, URB_List[epid]->pipe,
-						       usb_pipeout(URB_List[epid]->pipe)));
+						       usb_pipeout(URB_List[epid]->pipe)),
+					 GFP_KERNEL);
 	}
 #if 1
 	else {
diff -Nru a/arch/cris/kernel/entry.S b/arch/cris/kernel/entry.S
--- a/arch/cris/kernel/entry.S	Sun Feb 10 19:58:06 2002
+++ b/arch/cris/kernel/entry.S	Sun Feb 10 19:58:06 2002
@@ -1015,6 +1015,7 @@
         .long SYMBOL_NAME(sys_ni_syscall)       /* Reserved for Security */
         .long SYMBOL_NAME(sys_gettid)
         .long SYMBOL_NAME(sys_readahead)        /* 225 */
+        .long SYMBOL_NAME(sys_tkill)
 
         /*
          * NOTE!! This doesn't have to be exact - we just have
diff -Nru a/arch/cris/kernel/signal.c b/arch/cris/kernel/signal.c
--- a/arch/cris/kernel/signal.c	Sun Feb 10 19:58:04 2002
+++ b/arch/cris/kernel/signal.c	Sun Feb 10 19:58:04 2002
@@ -679,10 +679,7 @@
 
 			default:
 				lock_kernel();
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/i386/Config.help b/arch/i386/Config.help
--- a/arch/i386/Config.help	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/Config.help	Sun Feb 10 19:58:04 2002
@@ -25,6 +25,16 @@
 
   If you don't know what to do here, say N.
 
+CONFIG_PREEMPT
+  This option reduces the latency of the kernel when reacting to
+  real-time or interactive events by allowing a low priority process to
+  be preempted even if it is in kernel mode executing a system call.
+  This allows applications to run more reliably even when the system is
+  under load.
+
+  Say Y here if you are building a kernel for a desktop, embedded
+  or real-time system.  Say N if you are unsure.
+
 CONFIG_X86
   This is Linux's home port.  Linux was originally native to the Intel
   386, and runs on all the later x86 processors including the Intel
@@ -386,7 +396,7 @@
      will run on a 386 class machine.
    - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
      SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
-   - "586" for generic Pentium CPUs, possibly lacking the TSC
+   - "586" for generic Pentium CPUs lacking the TSC
      (time stamp counter) register.
    - "Pentium-Classic" for the Intel Pentium.
    - "Pentium-MMX" for the Intel Pentium MMX.
@@ -413,12 +423,69 @@
 CONFIG_M586
   Select this for an x586 or x686 processor such as the AMD K5, the
   Intel 5x86 or 6x86, or the Intel 6x86MX.  This choice does not
-  assume the RDTSC instruction.
+  assume the RDTSC (Read Time Stamp Counter) instruction.
 
 CONFIG_M586TSC
   Select this for a Pentium Classic processor with the RDTSC (Read
   Time Stamp Counter) instruction for benchmarking.
 
+CONFIG_M586MMX
+  Select this for a Pentium with the MMX graphics/multimedia
+  extended instructions.
+
+CONFIG_M686
+  Select this for a Pro/Celeron/Pentium II.  This enables the use of
+  Pentium Pro extended instructions, and disables the init-time guard
+  against the f00f bug found in earlier Pentiums.
+
+CONFIG_MPENTIUMIII
+  Select this for Intel chips based on the Pentium-III and
+  Celeron-Coppermine core.  Enables use of some extended prefetch
+  instructions, in addition to the Pentium II extensions.
+
+CONFIG_MPENTIUM4
+  Select this for Intel Pentium 4 chips.  Presently these are
+  treated almost like Pentium IIIs, but with a different cache
+  shift.
+
+CONFIG_MCRUSOE
+  Select this for Transmeta Crusoe processor.  Treats the processor
+  like a 586 with TSC, and sets some GCC optimization flags (like a
+  Pentium Pro with no alignment requirements).
+
+CONFIG_MK6
+  Select this for an AMD K6-family processor.  Enables use of
+  some extended instructions, and passes appropriate optimization
+  flags to GCC.
+
+CONFIG_MK7
+  Select this for an AMD Athlon K7-family processor.  Enables use of
+  some extended instructions, and passes appropriate optimization
+  flags to GCC.
+
+CONFIG_MCYRIXIII
+  Select this for a Cyrix III or C3 chip.  Presently Linux and GCC
+  treat this chip as a generic 586. Whilst the CPU is 686 class,
+  it lacks the cmov extension which gcc assumes is present when
+  generating 686 code.
+
+CONFIG_MWINCHIPC6
+  Select this for a IDT Winchip C6 chip.  Linux and GCC
+  treat this chip as a 586TSC with some extended instructions
+  and alignment requirements.
+
+CONFIG_MWINCHIP2
+  Select this for a IDT Winchip-2.  Linux and GCC
+  treat this chip as a 586TSC with some extended instructions
+  and alignment requirements.
+
+CONFIG_MWINCHIP3D
+  Select this for a IDT Winchip-2A or 3.  Linux and GCC
+  treat this chip as a 586TSC with some extended instructions
+  and alignment reqirements.  Development kernels also enable
+  out of order memory stores for this CPU, which can increase
+  performance of some operations.
+
 CONFIG_VGA_CONSOLE
   Saying Y here will allow you to use Linux in text mode through a
   display that complies with the generic VGA standard. Virtually
@@ -832,31 +899,6 @@
   send a BREAK and then within 5 seconds a command keypress. The
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
-
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
 
 CONFIG_DEBUG_HIGHMEM
   This options enables addition error checking for high memory systems.
diff -Nru a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
--- a/arch/i386/boot/bootsect.S	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/boot/bootsect.S	Sun Feb 10 19:58:06 2002
@@ -158,9 +158,7 @@
 	movw	$sread, %si		# the boot sector has already been read
 	movw	%ax, (%si)
 
-	xorw	%ax, %ax		# reset FDC
-	xorb	%dl, %dl
-	int	$0x13
+	call	kill_motor		# reset FDC
 	movw	$0x0200, %bx		# address = 512, in INITSEG
 next_step:
 	movb	setup_sects, %al
diff -Nru a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
--- a/arch/i386/boot/compressed/Makefile	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/boot/compressed/Makefile	Sun Feb 10 19:58:04 2002
@@ -32,8 +32,10 @@
 head.o: head.S
 	$(CC) $(AFLAGS) -traditional -c head.S
 
+comma	:= ,
+
 misc.o: misc.c
-	$(CC) $(CFLAGS) -c misc.c
+	$(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c misc.c
 
 piggy.o:	$(SYSTEM)
 	tmppiggy=_tmp_$$$$piggy; \
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	Sun Feb 10 19:58:05 2002
+++ b/arch/i386/config.in	Sun Feb 10 19:58:05 2002
@@ -167,6 +167,7 @@
 bool 'Math emulation' CONFIG_MATH_EMULATION
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 bool 'Symmetric multi-processing support' CONFIG_SMP
+bool 'Preemptible Kernel' CONFIG_PREEMPT
 if [ "$CONFIG_SMP" != "y" ]; then
    bool 'Local APIC support on uniprocessors' CONFIG_X86_UP_APIC
    dep_bool 'IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC $CONFIG_X86_UP_APIC
@@ -180,9 +181,12 @@
    bool 'Multiquad NUMA system' CONFIG_MULTIQUAD
 fi
 
-if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
-   define_bool CONFIG_HAVE_DEC_LOCK y
+if [ "$CONFIG_SMP" = "y" -o "$CONFIG_PREEMPT" = "y" ]; then
+   if [ "$CONFIG_X86_CMPXCHG" = "y" ]; then
+      define_bool CONFIG_HAVE_DEC_LOCK y
+   fi
 fi
+
 endmenu
 
 mainmenu_option next_comment
diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig
--- a/arch/i386/defconfig	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/defconfig	Sun Feb 10 19:58:04 2002
@@ -7,6 +7,11 @@
 CONFIG_UID16=y
 
 #
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+
+#
 # General setup
 #
 CONFIG_NET=y
@@ -15,11 +20,6 @@
 CONFIG_SYSCTL=y
 
 #
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-
-#
 # Loadable module support
 #
 CONFIG_MODULES=y
@@ -68,6 +68,7 @@
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_MTRR is not set
 CONFIG_SMP=y
+# CONFIG_PREEMPT is not set
 # CONFIG_MULTIQUAD is not set
 CONFIG_HAVE_DEC_LOCK=y
 
@@ -404,7 +405,6 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNBMAC is not set
 # CONFIG_SUNQE is not set
-# CONFIG_SUNLANCE is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -437,6 +437,7 @@
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_NEW_RX_RESET is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -518,13 +519,23 @@
 # CONFIG_CD_NO_IDESCSI is not set
 
 #
-# Input core support
+# Input device support
 #
 # CONFIG_INPUT is not set
 # CONFIG_INPUT_KEYBDEV is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_GAMEPORT_PCIGAME is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461x is not set
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_SERPORT is not set
 
 #
 # Character devices
@@ -551,19 +562,6 @@
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-
-#
-# Input core support is needed for gameports
-#
-
-#
-# Input core support is needed for joysticks
-#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -585,7 +583,7 @@
 CONFIG_AGP_INTEL=y
 CONFIG_AGP_I810=y
 CONFIG_AGP_VIA=y
-CONFIG_AGP_AMD=y
+# CONFIG_AGP_AMD is not set
 CONFIG_AGP_SIS=y
 CONFIG_AGP_ALI=y
 # CONFIG_AGP_SWORKS is not set
@@ -721,6 +719,7 @@
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+CONFIG_INPUT_GAMEPORT=y
 
 #
 # USB support
diff -Nru a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
--- a/arch/i386/kernel/cpuid.c	Sun Feb 10 19:58:03 2002
+++ b/arch/i386/kernel/cpuid.c	Sun Feb 10 19:58:03 2002
@@ -35,6 +35,8 @@
 #include <linux/poll.h>
 #include <linux/smp.h>
 #include <linux/major.h>
+#include <linux/smp_lock.h>
+#include <linux/fs.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -82,16 +84,25 @@
 
 static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
 {
+  loff_t ret;
+
+  lock_kernel();
+
   switch (orig) {
   case 0:
     file->f_pos = offset;
-    return file->f_pos;
+    ret = file->f_pos;
+    break;
   case 1:
     file->f_pos += offset;
-    return file->f_pos;
+    ret = file->f_pos;
+    break;
   default:
-    return -EINVAL;	/* SEEK_END not supported */
+    ret = -EINVAL;
   }
+
+  unlock_kernel();
+  return ret;
 }
 
 static ssize_t cpuid_read(struct file * file, char * buf,
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Sun Feb 10 19:58:05 2002
+++ b/arch/i386/kernel/entry.S	Sun Feb 10 19:58:05 2002
@@ -43,6 +43,8 @@
 #include <linux/config.h>
 #include <linux/sys.h>
 #include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
 #include <asm/segment.h>
 #include <asm/smp.h>
 
@@ -67,23 +69,36 @@
 NT_MASK		= 0x00004000
 VM_MASK		= 0x00020000
 
-/*
- * these are offsets into the task-struct.
+/* These are offsets into the irq_stat structure
+ * There is one per cpu and it is aligned to 32
+ * byte boundry (we put that here as a shift count)
  */
-state		=  0
-flags		=  4
-work		=  8
-need_resched	= work+0
-syscall_trace	= work+1
-sigpending	= work+2
-notify_resume	= work+3
-addr_limit	= 12
-exec_domain	= 16
-tsk_ptrace	= 24
-cpu		= 32
-
-ENOSYS = 38
-
+irq_array_shift			= CONFIG_X86_L1_CACHE_SHIFT
+irq_stat_local_irq_count	= 4
+irq_stat_local_bh_count		= 8
+
+#ifdef CONFIG_SMP
+#define GET_CPU_INDX	movl TI_CPU(%ebx),%eax;  \
+                        shll $irq_array_shift,%eax
+#define GET_CURRENT_CPU_INDX GET_THREAD_INFO(%ebx); \
+                             GET_CPU_INDX
+#define CPU_INDX (,%eax)
+#else
+#define GET_CPU_INDX
+#define GET_CURRENT_CPU_INDX GET_THREAD_INFO(%ebx)
+#define CPU_INDX
+#endif
+
+#ifdef CONFIG_PREEMPT
+#define preempt_stop cli
+#define init_ret_intr \
+	cli; \
+	decl TI_PRE_COUNT(%ebx);
+#else
+#define preempt_stop
+#define init_ret_intr
+#define resume_kernel restore_all
+#endif
 
 #define SAVE_ALL \
 	cld; \
@@ -131,10 +146,6 @@
 	.long 3b,6b;	\
 .previous
 
-#define GET_CURRENT(reg) \
-	movl $-8192, reg; \
-	andl %esp, reg
-
 ENTRY(lcall7)
 	pushfl			# We get a different stack layout with call gates,
 	pushl %eax		# which has to be cleaned up later..
@@ -147,8 +158,8 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp,%ebx
 	pushl %ebx
-	andl $-8192,%ebx	# GET_CURRENT
-	movl exec_domain(%ebx),%edx	# Get the execution domain
+	andl $-8192,%ebx	# GET_THREAD_INFO
+	movl TI_EXEC_DOMAIN(%ebx),%edx	# Get the execution domain
 	movl 4(%edx),%edx	# Get the lcall7 handler for the domain
 	pushl $0x7
 	call *%edx
@@ -168,8 +179,8 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp,%ebx
 	pushl %ebx
-	andl $-8192,%ebx	# GET_CURRENT
-	movl exec_domain(%ebx),%edx	# Get the execution domain
+	andl $-8192,%ebx	# GET_THREAD_INFO
+	movl TI_EXEC_DOMAIN(%ebx),%edx	# Get the execution domain
 	movl 4(%edx),%edx	# Get the lcall7 handler for the domain
 	pushl $0x27
 	call *%edx
@@ -182,7 +193,7 @@
 	pushl %ebx
 	call SYMBOL_NAME(schedule_tail)
 	addl $4, %esp
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	jmp syscall_exit
 
 /*
@@ -195,38 +206,55 @@
 	# userspace resumption stub bypassing syscall exit tracing
 	ALIGN
 ENTRY(ret_from_intr)
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
+	init_ret_intr
 ret_from_exception:
 	movl EFLAGS(%esp),%eax		# mix EFLAGS and CS
 	movb CS(%esp),%al
 	testl $(VM_MASK | 3),%eax
-	jz restore_all			# returning to kernel-space or vm86-space
+	jz resume_kernel		# returning to kernel or vm86-space
 ENTRY(resume_userspace)
-	cli				# make sure need_resched and sigpending don't change
-					# between sampling and the iret
-	movl work(%ebx),%ecx
-	andl $0xffff00ff,%ecx		# current->work (ignoring syscall_trace)
+ 	cli				# make sure we don't miss an interrupt setting need_resched
+ 					# or sigpending between sampling and the iret
+	movl TI_FLAGS(%ebx),%ecx
+	andl $_TIF_WORK_MASK,%ecx	# is there any work to be done on int/excp return?
 	jne work_pending
 	jmp restore_all
 
+#ifdef CONFIG_PREEMPT
+ENTRY(resume_kernel)
+	cmpl $0,TI_PRE_COUNT(%ebx)
+	jnz restore_all
+	movl TI_FLAGS(%ebx),%ecx
+	testb $_TIF_NEED_RESCHED,%cl
+	jz restore_all
+	movl SYMBOL_NAME(irq_stat)+irq_stat_local_bh_count CPU_INDX,%ecx
+	addl SYMBOL_NAME(irq_stat)+irq_stat_local_irq_count CPU_INDX,%ecx
+	jnz restore_all
+	incl TI_PRE_COUNT(%ebx)
+	sti
+	call SYMBOL_NAME(preempt_schedule)
+	jmp ret_from_intr
+#endif
+
 	# system call handler stub
 	ALIGN
 ENTRY(system_call)
 	pushl %eax			# save orig_eax
 	SAVE_ALL
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	cmpl $(NR_syscalls),%eax
 	jae syscall_badsys
-	testb $0xff,syscall_trace(%ebx)	# system call tracing in operation
+	testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebx)	# system call tracing in operation
 	jnz syscall_trace_entry
-syscall_traced:
+syscall_call:
 	call *SYMBOL_NAME(sys_call_table)(,%eax,4)
 	movl %eax,EAX(%esp)		# store the return value
 syscall_exit:
-	cli				# make sure need_resched and sigpending don't change
-					# between sampling and the iret
-	movl work(%ebx),%ecx
-	testl %ecx,%ecx			# current->work
+ 	cli				# make sure we don't miss an interrupt setting need_resched
+ 					# or sigpending between sampling and the iret
+	movl TI_FLAGS(%ebx),%ecx
+	testw $_TIF_ALLWORK_MASK,%cx	# current->work
 	jne syscall_exit_work
 restore_all:
 	RESTORE_ALL
@@ -234,16 +262,16 @@
 	# perform work that needs to be done immediately before resumption
 	ALIGN
 work_pending:
-	testb %cl,%cl			# current->work.need_resched
+	testb $_TIF_NEED_RESCHED,%cl
 	jz work_notifysig
 work_resched:
 	call SYMBOL_NAME(schedule)
-	cli				# make sure need_resched and sigpending don't change
-					# between sampling and the iret
-	movl work(%ebx),%ecx
-	andl $0xffff00ff,%ecx		# ignore the syscall trace counter
+ 	cli				# make sure we don't miss an interrupt setting need_resched
+ 					# or sigpending between sampling and the iret
+	movl TI_FLAGS(%ebx),%ecx
+	andl $_TIF_WORK_MASK,%ecx	# is there any work to be done other than syscall tracing?
 	jz restore_all
-	testb %cl,%cl			# current->work.need_resched
+	testb $_TIF_NEED_RESCHED,%cl
 	jnz work_resched
 
 work_notifysig:				# deal with pending signals and notify-resume requests
@@ -273,13 +301,13 @@
 	call SYMBOL_NAME(do_syscall_trace)
 	movl ORIG_EAX(%esp),%eax
 	cmpl $(NR_syscalls),%eax
-	jnae syscall_traced
+	jnae syscall_call
 	jmp syscall_exit
 
 	# perform syscall exit tracing
 	ALIGN
 syscall_exit_work:
-	testb %ch,%ch			# current->work.syscall_trace
+	testb $_TIF_SYSCALL_TRACE,%cl
 	jz work_pending
 	sti				# could let do_syscall_trace() call schedule() instead
 	movl %esp,%eax
@@ -319,9 +347,10 @@
 	movl $(__KERNEL_DS),%edx
 	movl %edx,%ds
 	movl %edx,%es
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	call *%edi
 	addl $8,%esp
+	preempt_stop
 	jmp ret_from_exception
 
 ENTRY(coprocessor_error)
@@ -337,16 +366,18 @@
 ENTRY(device_not_available)
 	pushl $-1		# mark this as an int
 	SAVE_ALL
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	movl %cr0,%eax
 	testl $0x4,%eax			# EM (math emulation bit)
 	jne device_not_available_emulate
+	preempt_stop
 	call SYMBOL_NAME(math_state_restore)
 	jmp ret_from_exception
 device_not_available_emulate:
 	pushl $0		# temporary storage for ORIG_EIP
 	call  SYMBOL_NAME(math_emulate)
 	addl $4,%esp
+	preempt_stop
 	jmp ret_from_exception
 
 ENTRY(debug)
@@ -667,6 +698,7 @@
 	.long SYMBOL_NAME(sys_removexattr)	/* 235 */
 	.long SYMBOL_NAME(sys_lremovexattr)
 	.long SYMBOL_NAME(sys_fremovexattr)
+ 	.long SYMBOL_NAME(sys_tkill)
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long SYMBOL_NAME(sys_ni_syscall)
diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
--- a/arch/i386/kernel/head.S	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/kernel/head.S	Sun Feb 10 19:58:04 2002
@@ -320,7 +320,7 @@
 	ret
 
 ENTRY(stack_start)
-	.long SYMBOL_NAME(init_task_union)+8192
+	.long SYMBOL_NAME(init_thread_union)+8192
 	.long __KERNEL_DS
 
 /* This is the default interrupt "handler" :-) */
@@ -456,12 +456,3 @@
 	.quad 0x0000000000000000	/* 0x98 not used */
 	/* Per CPU segments */
 	.fill NR_CPUS*4,8,0		/* space for TSS's and LDT's */
-		
-/*
- * This is to aid debugging, the various locking macros will be putting
- * code fragments here.  When an oops occurs we'd rather know that it's
- * inside the .text.lock section rather than as some offset from whatever
- * function happens to be last in the .text segment.
- */
-.section .text.lock
-ENTRY(stext_lock)
diff -Nru a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
--- a/arch/i386/kernel/i387.c	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/kernel/i387.c	Sun Feb 10 19:58:06 2002
@@ -10,6 +10,7 @@
 
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/math_emu.h>
@@ -52,7 +53,7 @@
 		asm volatile( "fnsave %0 ; fwait"
 			      : "=m" (tsk->thread.i387.fsave) );
 	}
-	tsk->flags &= ~PF_USEDFPU;
+	clear_tsk_thread_flag(tsk, TIF_USEDFPU);
 }
 
 void save_init_fpu( struct task_struct *tsk )
@@ -63,10 +64,9 @@
 
 void kernel_fpu_begin(void)
 {
-	struct task_struct *tsk = current;
-
-	if (tsk->flags & PF_USEDFPU) {
-		__save_init_fpu(tsk);
+	preempt_disable();
+	if (test_thread_flag(TIF_USEDFPU)) {
+		__save_init_fpu(current);
 		return;
 	}
 	clts();
diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
--- a/arch/i386/kernel/init_task.c	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/kernel/init_task.c	Sun Feb 10 19:58:06 2002
@@ -2,6 +2,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/init_task.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -13,15 +14,22 @@
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
- * Initial task structure.
+ * Initial thread structure.
  *
  * We need to make sure that this is 8192-byte aligned due to the
  * way process stacks are handled. This is done by having a special
  * "init_task" linker map entry..
  */
-union task_union init_task_union 
+union thread_union init_thread_union 
 	__attribute__((__section__(".data.init_task"))) =
-		{ INIT_TASK(init_task_union.task) };
+		{ INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
 
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/kernel/irq.c	Sun Feb 10 19:58:04 2002
@@ -220,7 +220,7 @@
 			continue;
 		}
 		esp &= ~(THREAD_SIZE-1);
-		esp += sizeof(struct task_struct);
+		esp += sizeof(struct thread_info);
 		show_stack((void*)esp);
  	}
 	printk("\nCPU %d:",cpu);
diff -Nru a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
--- a/arch/i386/kernel/msr.c	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/kernel/msr.c	Sun Feb 10 19:58:06 2002
@@ -33,7 +33,9 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/smp.h>
+#include <linux/smp_lock.h>
 #include <linux/major.h>
+#include <linux/fs.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -162,16 +164,19 @@
 
 static loff_t msr_seek(struct file *file, loff_t offset, int orig)
 {
+  loff_t ret = -EINVAL;
+  lock_kernel();
   switch (orig) {
   case 0:
     file->f_pos = offset;
-    return file->f_pos;
+    ret = file->f_pos;
+    break;
   case 1:
     file->f_pos += offset;
-    return file->f_pos;
-  default:
-    return -EINVAL;	/* SEEK_END not supported */
+    ret = file->f_pos;
   }
+  unlock_kernel();
+  return ret;
 }
 
 static ssize_t msr_read(struct file * file, char * buf,
diff -Nru a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
--- a/arch/i386/kernel/nmi.c	Sun Feb 10 19:58:03 2002
+++ b/arch/i386/kernel/nmi.c	Sun Feb 10 19:58:03 2002
@@ -263,8 +263,9 @@
 {
 
 	/*
-	 * Since current-> is always on the stack, and we always switch
-	 * the stack NMI-atomically, it's safe to use smp_processor_id().
+	 * Since current_thread_info()-> is always on the stack, and we
+	 * always switch the stack NMI-atomically, it's safe to use
+	 * smp_processor_id().
 	 */
 	int sum, cpu = smp_processor_id();
 
diff -Nru a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
--- a/arch/i386/kernel/pci-dma.c	Sun Feb 10 19:58:05 2002
+++ b/arch/i386/kernel/pci-dma.c	Sun Feb 10 19:58:05 2002
@@ -25,7 +25,7 @@
 
 	if (ret != NULL) {
 		memset(ret, 0, size);
-		*dma_handle = virt_to_bus(ret);
+		*dma_handle = virt_to_phys(ret);
 	}
 	return ret;
 }
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	Sun Feb 10 19:58:03 2002
+++ b/arch/i386/kernel/process.c	Sun Feb 10 19:58:03 2002
@@ -16,6 +16,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -47,6 +48,7 @@
 #endif
 
 #include <linux/irq.h>
+#include <linux/err.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -102,15 +104,21 @@
 	 * Deal with another CPU just having chosen a thread to
 	 * run here:
 	 */
-	oldval = xchg(&current->work.need_resched, -1);
+	oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
 
-	if (!oldval)
+	if (!oldval) {
+		set_thread_flag(TIF_POLLING_NRFLAG);
 		asm volatile(
 			"2:"
-			"cmpb $-1, %0;"
+			"testl %0, %1;"
 			"rep; nop;"
 			"je 2b;"
-				: :"m" (current->work.need_resched));
+			: : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
+
+		clear_thread_flag(TIF_POLLING_NRFLAG);
+	} else {
+		set_need_resched();
+	}
 }
 
 /*
@@ -576,7 +584,7 @@
 {
 	struct pt_regs * childregs;
 
-	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
+	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
 	struct_cpy(childregs, regs);
 	childregs->eax = 0;
 	childregs->esp = esp;
@@ -674,6 +682,8 @@
 				 *next = &next_p->thread;
 	struct tss_struct *tss = init_tss + smp_processor_id();
 
+	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
+
 	unlazy_fpu(prev_p);
 
 	/*
@@ -800,7 +810,7 @@
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
-	stack_page = (unsigned long)p;
+	stack_page = (unsigned long)p->thread_info;
 	esp = p->thread.esp;
 	if (!stack_page || esp < stack_page || esp > 8188+stack_page)
 		return 0;
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	Sun Feb 10 19:58:05 2002
+++ b/arch/i386/kernel/ptrace.c	Sun Feb 10 19:58:05 2002
@@ -278,16 +278,10 @@
 		if ((unsigned long) data > _NSIG)
 			break;
 		if (request == PTRACE_SYSCALL) {
-			if (!(child->ptrace & PT_SYSCALLTRACE)) {
-				child->ptrace |= PT_SYSCALLTRACE;
-				child->work.syscall_trace++;
-			}
+			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		}
 		else {
-			if (child->ptrace & PT_SYSCALLTRACE) {
-				child->ptrace &= ~PT_SYSCALLTRACE;
-				child->work.syscall_trace--;
-			}
+			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		}
 		child->exit_code = data;
 	/* make sure the single step bit is not set. */
@@ -323,10 +317,7 @@
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
-		if (child->ptrace & PT_SYSCALLTRACE) {
-			child->ptrace &= ~PT_SYSCALLTRACE;
-			child->work.syscall_trace--;
-		}
+		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		if ((child->ptrace & PT_DTRACE) == 0) {
 			/* Spurious delayed TF traps may occur */
 			child->ptrace |= PT_DTRACE;
@@ -444,7 +435,7 @@
 		break;
 	}
 out_tsk:
-	free_task_struct(child);
+	put_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
@@ -456,8 +447,9 @@
 __attribute__((regparm(3)))
 void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	if ((current->ptrace & (PT_PTRACED|PT_SYSCALLTRACE)) !=
-	    (PT_PTRACED|PT_SYSCALLTRACE))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+	if (!(current->ptrace & PT_PTRACED))
 		return;
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
@@ -475,16 +467,4 @@
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
-}
-
-/* notification of userspace execution resumption
- * - triggered by current->work.notify_resume
- */
-__attribute__((regparm(3)))
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
-		      struct task_work work_pending)
-{
-	/* deal with pending signal delivery */
-	if (work_pending.sigpending)
-		do_signal(regs,oldset);
 }
diff -Nru a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
--- a/arch/i386/kernel/semaphore.c	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/kernel/semaphore.c	Sun Feb 10 19:58:06 2002
@@ -14,6 +14,7 @@
  */
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/err.h>
 #include <asm/semaphore.h>
 
 /*
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/kernel/setup.c	Sun Feb 10 19:58:06 2002
@@ -232,7 +232,7 @@
 
 	/* Video ROM is standard at C000:0000 - C7FF:0000, check signature */
 	for (base = 0xC0000; base < 0xE0000; base += 2048) {
-		romstart = bus_to_virt(base);
+		romstart = isa_bus_to_virt(base);
 		if (!romsignature(romstart))
 			continue;
 		request_resource(&iomem_resource, rom_resources + roms);
@@ -244,7 +244,7 @@
 	for (base = 0xC8000; base < 0xE0000; base += 2048) {
 		unsigned long length;
 
-		romstart = bus_to_virt(base);
+		romstart = isa_bus_to_virt(base);
 		if (!romsignature(romstart))
 			continue;
 		length = romstart[2] * 512;
@@ -273,7 +273,7 @@
 
 	/* Final check for motherboard extension rom at E000:0000 */
 	base = 0xE0000;
-	romstart = bus_to_virt(base);
+	romstart = isa_bus_to_virt(base);
 
 	if (romsignature(romstart)) {
 		rom_resources[roms].start = base;
@@ -692,10 +692,10 @@
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	code_resource.start = virt_to_bus(&_text);
-	code_resource.end = virt_to_bus(&_etext)-1;
-	data_resource.start = virt_to_bus(&_etext);
-	data_resource.end = virt_to_bus(&_edata)-1;
+	code_resource.start = virt_to_phys(&_text);
+	code_resource.end = virt_to_phys(&_etext)-1;
+	data_resource.start = virt_to_phys(&_etext);
+	data_resource.end = virt_to_phys(&_edata)-1;
 
 	parse_mem_cmdline(cmdline_p);
 
@@ -2652,7 +2652,7 @@
 		/* AMD-defined */
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL, NULL, NULL, "mmxext", NULL,
+		NULL, NULL, NULL, "mp", NULL, NULL, "mmxext", NULL,
 		NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
 
 		/* Transmeta-defined */
@@ -2817,7 +2817,7 @@
 	/*
 	 * Force FPU initialization:
 	 */
-	current->flags &= ~PF_USEDFPU;
+	clear_thread_flag(TIF_USEDFPU);
 	current->used_math = 0;
 	stts();
 }
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/kernel/signal.c	Sun Feb 10 19:58:06 2002
@@ -394,10 +394,10 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current->exec_domain
-		           && current->exec_domain->signal_invmap
+	err |= __put_user((current_thread_info()->exec_domain
+		           && current_thread_info()->exec_domain->signal_invmap
 		           && sig < 32
-		           ? current->exec_domain->signal_invmap[sig]
+		           ? current_thread_info()->exec_domain->signal_invmap[sig]
 		           : sig),
 		          &frame->sig);
 	if (err)
@@ -464,10 +464,10 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current->exec_domain
-		    	   && current->exec_domain->signal_invmap
+	err |= __put_user((current_thread_info()->exec_domain
+		    	   && current_thread_info()->exec_domain->signal_invmap
 		    	   && sig < 32
-		    	   ? current->exec_domain->signal_invmap[sig]
+		    	   ? current_thread_info()->exec_domain->signal_invmap[sig]
 			   : sig),
 			  &frame->sig);
 	err |= __put_user(&frame->info, &frame->pinfo);
@@ -683,10 +683,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
@@ -714,4 +711,17 @@
 		}
 	}
 	return 0;
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+__attribute__((regparm(3)))
+void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+		      __u32 thread_info_flags)
+{
+	/* deal with pending signal delivery */
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(regs,oldset);
 }
diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
--- a/arch/i386/kernel/smp.c	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/kernel/smp.c	Sun Feb 10 19:58:04 2002
@@ -497,7 +497,7 @@
 	/*
 	 * The target CPU will unlock the migration spinlock:
 	 */
-	spin_lock(&migration_lock);
+	_raw_spin_lock(&migration_lock);
 	new_task = p;
 	send_IPI_mask(1 << cpu, TASK_MIGRATION_VECTOR);
 }
@@ -511,7 +511,7 @@
 
 	ack_APIC_irq();
 	p = new_task;
-	spin_unlock(&migration_lock);
+	_raw_spin_unlock(&migration_lock);
 	sched_task_migrated(p);
 }
 /*
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	Sun Feb 10 19:58:06 2002
+++ b/arch/i386/kernel/smpboot.c	Sun Feb 10 19:58:06 2002
@@ -30,10 +30,12 @@
  *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
  *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
  *		Martin J. Bligh	: 	Added support for multi-quad systems
+ *		Dave Jones	:	Report invalid combinations of Athlon CPUs.
  */
 
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
@@ -160,6 +162,35 @@
 		 * Remember we have B step Pentia with bugs
 		 */
 		smp_b_stepping = 1;
+
+	/*
+	 * Certain Athlons might work (for various values of 'work') in SMP
+	 * but they are not certified as MP capable.
+	 */
+	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+
+		/* Athlon 660/661 is valid. */	
+		if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
+			goto valid_k7;
+
+		/* Duron 670 is valid */
+		if ((c->x86_model==7) && (c->x86_mask==0))
+			goto valid_k7;
+
+		/* Athlon 662, Duron 671, and Athlon >model 7 have capability bit */
+		if (((c->x86_model==6) && (c->x86_mask>=2)) ||
+		    ((c->x86_model==7) && (c->x86_mask>=1)) ||
+		     (c->x86_model> 7))
+			if (cpu_has_mp)
+				goto valid_k7;
+
+		/* If we get here, it's not a certified SMP capable AMD system. */
+		printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
+		tainted |= TAINT_UNSAFE_SMP;
+		
+	}
+valid_k7:
+
 }
 
 /*
@@ -818,7 +849,7 @@
 
 	/* So we see what's up   */
 	printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
-	stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
+	stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle->thread_info);
 
 	/*
 	 * This grunge runs the startup process for
@@ -1024,7 +1055,7 @@
 	map_cpu_to_boot_apicid(0, boot_cpu_apicid);
 
 	global_irq_holder = NO_PROC_ID;
-	current->cpu = 0;
+	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
 
 	/*
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/kernel/traps.c	Sun Feb 10 19:58:04 2002
@@ -158,7 +158,7 @@
 	unsigned long esp = tsk->thread.esp;
 
 	/* User space on another CPU? */
-	if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
+	if ((esp ^ (unsigned long)tsk->thread_info) & (PAGE_MASK<<1))
 		return;
 	show_trace((unsigned long *)esp);
 }
@@ -208,8 +208,8 @@
 		regs->esi, regs->edi, regs->ebp, esp);
 	printk("ds: %04x   es: %04x   ss: %04x\n",
 		regs->xds & 0xffff, regs->xes & 0xffff, ss);
-	printk("Process %s (pid: %d, stackpage=%08lx)",
-		current->comm, current->pid, 4096+(unsigned long)current);
+	printk("Process %s (pid: %d, threadinfo=%p task=%p)",
+		current->comm, current->pid, current_thread_info(), current);
 	/*
 	 * When in-kernel, we also print out the stack and code at the
 	 * time of the fault..
@@ -710,6 +710,8 @@
  *
  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
  * Don't touch unless you *really* know how it works.
+ *
+ * Must be called with kernel preemption disabled.
  */
 asmlinkage void math_state_restore(struct pt_regs regs)
 {
@@ -720,7 +722,7 @@
 	} else {
 		init_fpu();
 	}
-	current->flags |= PF_USEDFPU;	/* So we fnsave on switch_to() */
+	set_thread_flag(TIF_USEDFPU);	/* So we fnsave on switch_to() */
 }
 
 #ifndef CONFIG_MATH_EMULATION
diff -Nru a/arch/i386/lib/getuser.S b/arch/i386/lib/getuser.S
--- a/arch/i386/lib/getuser.S	Sun Feb 10 19:58:03 2002
+++ b/arch/i386/lib/getuser.S	Sun Feb 10 19:58:03 2002
@@ -8,6 +8,8 @@
  * return an error value in addition to the "real"
  * return value.
  */
+#include <asm/thread_info.h>
+
 
 /*
  * __get_user_X
@@ -21,15 +23,12 @@
  * as they get called from within inline assembly.
  */
 
-addr_limit = 12
-
 .text
 .align 4
 .globl __get_user_1
 __get_user_1:
-	movl %esp,%edx
-	andl $0xffffe000,%edx
-	cmpl addr_limit(%edx),%eax
+	GET_THREAD_INFO(%edx)
+	cmpl TI_ADDR_LIMIT(%edx),%eax
 	jae bad_get_user
 1:	movzbl (%eax),%edx
 	xorl %eax,%eax
@@ -39,10 +38,9 @@
 .globl __get_user_2
 __get_user_2:
 	addl $1,%eax
-	movl %esp,%edx
 	jc bad_get_user
-	andl $0xffffe000,%edx
-	cmpl addr_limit(%edx),%eax
+	GET_THREAD_INFO(%edx)
+	cmpl TI_ADDR_LIMIT(%edx),%eax
 	jae bad_get_user
 2:	movzwl -1(%eax),%edx
 	xorl %eax,%eax
@@ -52,10 +50,9 @@
 .globl __get_user_4
 __get_user_4:
 	addl $3,%eax
-	movl %esp,%edx
 	jc bad_get_user
-	andl $0xffffe000,%edx
-	cmpl addr_limit(%edx),%eax
+	GET_THREAD_INFO(%edx)
+	cmpl TI_ADDR_LIMIT(%edx),%eax
 	jae bad_get_user
 3:	movl -3(%eax),%edx
 	xorl %eax,%eax
diff -Nru a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds
--- a/arch/i386/vmlinux.lds	Sun Feb 10 19:58:04 2002
+++ b/arch/i386/vmlinux.lds	Sun Feb 10 19:58:04 2002
@@ -13,7 +13,6 @@
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
 
   _etext = .;			/* End of text section */
 
diff -Nru a/arch/ia64/Config.help b/arch/ia64/Config.help
--- a/arch/ia64/Config.help	Sun Feb 10 19:58:05 2002
+++ b/arch/ia64/Config.help	Sun Feb 10 19:58:05 2002
@@ -424,31 +424,6 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_ITANIUM
   Select your IA64 processor type.  The default is Intel Itanium.
 
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	Sun Feb 10 19:58:04 2002
+++ b/arch/ia64/ia32/sys_ia32.c	Sun Feb 10 19:58:04 2002
@@ -171,77 +171,65 @@
 }
 
 static inline int
-putstat (struct stat32 *ubuf, struct stat *kbuf)
+putstat (struct stat32 *ubuf, struct kstat *stat)
 {
 	int err;
 
+	if (stat->size > MAX_NON_LFS)
+		return -EOVERFLOW;
+
 	if (clear_user(ubuf, sizeof(*ubuf)))
-		return 1;
+		return -EFAULT;
 
-	err  = __put_user(kbuf->st_dev, &ubuf->st_dev);
-	err |= __put_user(kbuf->st_ino, &ubuf->st_ino);
-	err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
-	err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
-	err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
-	err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
-	err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);
-	err |= __put_user(kbuf->st_size, &ubuf->st_size);
-	err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
-	err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
-	err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
-	err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
-	err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);
+	err  = __put_user(stat->dev, &ubuf->st_dev);
+	err |= __put_user(stat->ino, &ubuf->st_ino);
+	err |= __put_user(stat->mode, &ubuf->st_mode);
+	err |= __put_user(stat->nlink, &ubuf->st_nlink);
+	err |= __put_user(high2lowuid(stat->uid), &ubuf->st_uid);
+	err |= __put_user(high2lowgid(stat->gid), &ubuf->st_gid);
+	err |= __put_user(stat->rdev, &ubuf->st_rdev);
+	err |= __put_user(stat->size, &ubuf->st_size);
+	err |= __put_user(stat->atime, &ubuf->st_atime);
+	err |= __put_user(stat->mtime, &ubuf->st_mtime);
+	err |= __put_user(stat->ctime, &ubuf->st_ctime);
+	err |= __put_user(stat->blksize, &ubuf->st_blksize);
+	err |= __put_user(stat->blocks, &ubuf->st_blocks);
 	return err;
 }
 
-extern asmlinkage long sys_newstat (char * filename, struct stat * statbuf);
-
 asmlinkage long
 sys32_newstat (char *filename, struct stat32 *statbuf)
 {
-	int ret;
-	struct stat s;
-	mm_segment_t old_fs = get_fs();
+	struct kstat stat;
+	int ret = vfs_stat(filename, &stat);
+
+	if (!ret)
+		ret = putstat(statbuf, &stat);
 
-	set_fs(KERNEL_DS);
-	ret = sys_newstat(filename, &s);
-	set_fs(old_fs);
-	if (putstat(statbuf, &s))
-		return -EFAULT;
 	return ret;
 }
 
-extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
-
 asmlinkage long
 sys32_newlstat (char *filename, struct stat32 *statbuf)
 {
-	mm_segment_t old_fs = get_fs();
-	struct stat s;
-	int ret;
+	struct kstat stat;
+	int ret = vfs_lstat(filename, &stat);
+
+	if (!ret)
+		ret = putstat(statbuf, &stat);
 
-	set_fs(KERNEL_DS);
-	ret = sys_newlstat(filename, &s);
-	set_fs(old_fs);
-	if (putstat(statbuf, &s))
-		return -EFAULT;
 	return ret;
 }
 
-extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
-
 asmlinkage long
 sys32_newfstat (unsigned int fd, struct stat32 *statbuf)
 {
-	mm_segment_t old_fs = get_fs();
-	struct stat s;
-	int ret;
+	struct kstat stat;
+	int ret = vfs_fstat(fd, &stat);
+
+	if (!ret)
+		ret = putstat(statbuf, &stat);
 
-	set_fs(KERNEL_DS);
-	ret = sys_newfstat(fd, &s);
-	set_fs(old_fs);
-	if (putstat(statbuf, &s))
-		return -EFAULT;
 	return ret;
 }
 
@@ -3529,74 +3517,59 @@
 }
 
 static int
-putstat64 (struct stat64 *ubuf, struct stat *kbuf)
+putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
 {
 	int err;
 
 	if (clear_user(ubuf, sizeof(*ubuf)))
-		return 1;
+		return -EFAULT;
 
-	err  = __put_user(kbuf->st_dev, &ubuf->st_dev);
-	err |= __put_user(kbuf->st_ino, &ubuf->__st_ino);
-	err |= __put_user(kbuf->st_ino, &ubuf->st_ino_lo);
-	err |= __put_user(kbuf->st_ino >> 32, &ubuf->st_ino_hi);
-	err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
-	err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
-	err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
-	err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
-	err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);
-	err |= __put_user(kbuf->st_size, &ubuf->st_size_lo);
-	err |= __put_user((kbuf->st_size >> 32), &ubuf->st_size_hi);
-	err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
-	err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
-	err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
-	err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
-	err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);
+	err  = __put_user(kbuf->dev, &ubuf->st_dev);
+	err |= __put_user(kbuf->ino, &ubuf->__st_ino);
+	err |= __put_user(kbuf->ino, &ubuf->st_ino_lo);
+	err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi);
+	err |= __put_user(kbuf->mode, &ubuf->st_mode);
+	err |= __put_user(kbuf->nlink, &ubuf->st_nlink);
+	err |= __put_user(kbuf->uid, &ubuf->st_uid);
+	err |= __put_user(kbuf->gid, &ubuf->st_gid);
+	err |= __put_user(kbuf->rdev, &ubuf->st_rdev);
+	err |= __put_user(kbuf->size, &ubuf->st_size_lo);
+	err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi);
+	err |= __put_user(kbuf->atime, &ubuf->st_atime);
+	err |= __put_user(kbuf->mtime, &ubuf->st_mtime);
+	err |= __put_user(kbuf->ctime, &ubuf->st_ctime);
+	err |= __put_user(kbuf->blksize, &ubuf->st_blksize);
+	err |= __put_user(kbuf->blocks, &ubuf->st_blocks);
 	return err;
 }
 
 asmlinkage long
 sys32_stat64 (char *filename, struct stat64 *statbuf)
 {
-	mm_segment_t old_fs = get_fs();
-	struct stat s;
-	long ret;
-
-	set_fs(KERNEL_DS);
-	ret = sys_newstat(filename, &s);
-	set_fs(old_fs);
-	if (putstat64(statbuf, &s))
-		return -EFAULT;
+	struct kstat s;
+	long ret = vfs_stat(filename, &s);
+	if (!ret)
+		ret = putstat64(statbuf, &s);
 	return ret;
 }
 
 asmlinkage long
 sys32_lstat64 (char *filename, struct stat64 *statbuf)
 {
-	mm_segment_t old_fs = get_fs();
-	struct stat s;
-	long ret;
-
-	set_fs(KERNEL_DS);
-	ret = sys_newlstat(filename, &s);
-	set_fs(old_fs);
-	if (putstat64(statbuf, &s))
-		return -EFAULT;
+	struct kstat s;
+	long ret = vfs_lstat(filename, &s);
+	if (!ret)
+		ret = putstat64(statbuf, &s);
 	return ret;
 }
 
 asmlinkage long
 sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
 {
-	mm_segment_t old_fs = get_fs();
-	struct stat s;
-	long ret;
-
-	set_fs(KERNEL_DS);
-	ret = sys_newfstat(fd, &s);
-	set_fs(old_fs);
-	if (putstat64(statbuf, &s))
-		return -EFAULT;
+	struct kstat s;
+	long ret = vfs_fstat(fd, &s);
+	if (!ret)
+		ret = putstat64(statbuf, &s);
 	return ret;
 }
 
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Sun Feb 10 19:58:05 2002
+++ b/arch/ia64/kernel/entry.S	Sun Feb 10 19:58:05 2002
@@ -1130,7 +1130,7 @@
 	data8 sys_getdents64
 	data8 sys_getunwind			// 1215
 	data8 sys_readahead
-	data8 ia64_ni_syscall
+	data8 sys_tkill
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall			// 1220
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	Sun Feb 10 19:58:04 2002
+++ b/arch/ia64/kernel/signal.c	Sun Feb 10 19:58:04 2002
@@ -578,10 +578,7 @@
 				/* FALLTHRU */
 
 			      default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c	Sun Feb 10 19:58:03 2002
+++ b/arch/ia64/kernel/sys_ia64.c	Sun Feb 10 19:58:03 2002
@@ -282,120 +282,64 @@
  * call - it will be removed later once everybody migrates to the new
  * kernel stat structure that matches the glibc one - Jes
  */
-static __inline__ int
-do_revalidate (struct dentry *dentry)
-{
-	struct inode * inode = dentry->d_inode;
-	if (inode->i_op && inode->i_op->revalidate)
-		return inode->i_op->revalidate(dentry);
-	return 0;
-}
 
 static int
-cp_ia64_old_stat (struct inode *inode, struct ia64_oldstat *statbuf)
+cp_ia64_old_stat (struct kstat *stat, struct ia64_oldstat *statbuf)
 {
 	struct ia64_oldstat tmp;
 	unsigned int blocks, indirect;
 
 	memset(&tmp, 0, sizeof(tmp));
-	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
-	tmp.st_ino = inode->i_ino;
-	tmp.st_mode = inode->i_mode;
-	tmp.st_nlink = inode->i_nlink;
-	SET_STAT_UID(tmp, inode->i_uid);
-	SET_STAT_GID(tmp, inode->i_gid);
-	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
-	tmp.st_size = inode->i_size;
-	tmp.st_atime = inode->i_atime;
-	tmp.st_mtime = inode->i_mtime;
-	tmp.st_ctime = inode->i_ctime;
-/*
- * st_blocks and st_blksize are approximated with a simple algorithm if
- * they aren't supported directly by the filesystem. The minix and msdos
- * filesystems don't keep track of blocks, so they would either have to
- * be counted explicitly (by delving into the file itself), or by using
- * this simple algorithm to get a reasonable (although not 100% accurate)
- * value.
- */
-
-/*
- * Use minix fs values for the number of direct and indirect blocks.  The
- * count is now exact for the minix fs except that it counts zero blocks.
- * Everything is in units of BLOCK_SIZE until the assignment to
- * tmp.st_blksize.
- */
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-
-	if (!inode->i_blksize) {
-		blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		if (blocks > D_B) {
-			indirect = (blocks - D_B + I_B - 1) / I_B;
-			blocks += indirect;
-			if (indirect > 1) {
-				indirect = (indirect - 1 + I_B - 1) / I_B;
-				blocks += indirect;
-				if (indirect > 1)
-					blocks++;
-			}
-		}
-		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-		tmp.st_blksize = BLOCK_SIZE;
-	} else {
-		tmp.st_blocks = inode->i_blocks;
-		tmp.st_blksize = inode->i_blksize;
-	}
+	tmp.st_dev = stat->dev;
+	tmp.st_ino = stat->ino;
+	tmp.st_mode = stat->mode;
+	tmp.st_nlink = stat->nlink;
+	SET_STAT_UID(tmp, stat->uid);
+	SET_STAT_GID(tmp, stat->gid);
+	tmp.st_rdev = stat->rdev;
+	tmp.st_size = stat->size;
+	tmp.st_atime = stat->atime;
+	tmp.st_mtime = stat->mtime;
+	tmp.st_ctime = stat->ctime;
+	tmp.st_blocks = stat->i_blocks;
+	tmp.st_blksize = stat->i_blksize;
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
 asmlinkage long
 ia64_oldstat (char *filename, struct ia64_oldstat *statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
+
+	if (!error)
+		error = cp_ia64_old_stat(&stat, statbuf);
 
-	error = user_path_walk(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-		error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
 	return error;
 }
 
-
 asmlinkage long
-ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf) {
-	struct nameidata nd;
-	int error;
-
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
+ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf)
+{
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
+
+	if (!error)
+		error = cp_ia64_old_stat(&stat, statbuf);
+
 	return error;
 }
 
 asmlinkage long
 ia64_oldfstat (unsigned int fd, struct ia64_oldstat *statbuf)
 {
-	struct file * f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
-
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_ia64_old_stat(dentry->d_inode, statbuf);
-		fput(f);
-	}
-	return err;
+	if (!error)
+		error = cp_ia64_old_stat(&stat, statbuf);
+
+	return error;
 }
 
 #endif
diff -Nru a/arch/ia64/sn/fprom/Makefile b/arch/ia64/sn/fprom/Makefile
--- a/arch/ia64/sn/fprom/Makefile	Sun Feb 10 19:58:05 2002
+++ b/arch/ia64/sn/fprom/Makefile	Sun Feb 10 19:58:05 2002
@@ -18,10 +18,12 @@
 fprom: $(OBJ)
 	$(LD) -static -Tfprom.lds -o fprom $(OBJ) $(LIB)
 
+comma	:= ,
+
 .S.o:
 	$(CC)  -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $<
 .c.o:
-	$(CC)  $(CFLAGS) $(CFLAGS_KERNEL) -c -o $*.o $<
+	$(CC)  $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_KERNEL) -c -o $*.o $<
 
 clean:
 	rm -f *.o fprom
diff -Nru a/arch/ia64/tools/Makefile b/arch/ia64/tools/Makefile
--- a/arch/ia64/tools/Makefile	Sun Feb 10 19:58:03 2002
+++ b/arch/ia64/tools/Makefile	Sun Feb 10 19:58:03 2002
@@ -31,8 +31,10 @@
 offsets.h: print_offsets
 	./print_offsets > offsets.h
 
+comma	:= ,
+
 print_offsets: print_offsets.c FORCE_RECOMPILE
-	$(CC) $(CFLAGS) print_offsets.c -o $@
+	$(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) print_offsets.c -o $@
 
 FORCE_RECOMPILE:
 
@@ -42,7 +44,7 @@
 	$(AWK) -f print_offsets.awk $^ > $@
 
 print_offsets.s: print_offsets.c
-	$(CC) $(CFLAGS) -S print_offsets.c -o $@
+	$(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -S print_offsets.c -o $@
 
 endif
 
diff -Nru a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
--- a/arch/m68k/kernel/entry.S	Sun Feb 10 19:58:03 2002
+++ b/arch/m68k/kernel/entry.S	Sun Feb 10 19:58:03 2002
@@ -646,6 +646,8 @@
 	.long SYMBOL_NAME(sys_ni_syscall)
 	.long SYMBOL_NAME(sys_ni_syscall)
 	.long SYMBOL_NAME(sys_getdents64)	/* 220 */
+	.long SYMBOL_NAME(sys_gettid)
+	.long SYMBOL_NAME(sys_tkill)
 
 	.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
 		.long SYMBOL_NAME(sys_ni_syscall)
diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
--- a/arch/m68k/kernel/signal.c	Sun Feb 10 19:58:04 2002
+++ b/arch/m68k/kernel/signal.c	Sun Feb 10 19:58:04 2002
@@ -1135,10 +1135,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
--- a/arch/m68k/vmlinux-sun3.lds	Sun Feb 10 19:58:03 2002
+++ b/arch/m68k/vmlinux-sun3.lds	Sun Feb 10 19:58:03 2002
@@ -10,7 +10,6 @@
 	*(.head)
 	*(.text)
 	*(.fixup)
-	*(.text.lock)		/* out-of-line lock text */
 	*(.gnu.warning)
 	} = 0x4e75
   .kstrtab : { *(.kstrtab) }
diff -Nru a/arch/m68k/vmlinux.lds b/arch/m68k/vmlinux.lds
--- a/arch/m68k/vmlinux.lds	Sun Feb 10 19:58:05 2002
+++ b/arch/m68k/vmlinux.lds	Sun Feb 10 19:58:05 2002
@@ -9,7 +9,6 @@
   .text : {
 	*(.text)
 	*(.fixup)
-	*(.text.lock)		/* out-of-line lock text */
 	*(.gnu.warning)
 	} = 0x4e75
   .rodata : { *(.rodata) *(.rodata.*) }
diff -Nru a/arch/mips/Config.help b/arch/mips/Config.help
--- a/arch/mips/Config.help	Sun Feb 10 19:58:03 2002
+++ b/arch/mips/Config.help	Sun Feb 10 19:58:03 2002
@@ -899,31 +899,6 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_GDB_CONSOLE
   If you are using GDB for remote debugging over a serial port and
   would like kernel messages to be formatted into GDB $O packets so
diff -Nru a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
--- a/arch/mips/kernel/signal.c	Sun Feb 10 19:58:06 2002
+++ b/arch/mips/kernel/signal.c	Sun Feb 10 19:58:06 2002
@@ -661,10 +661,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h
--- a/arch/mips/kernel/syscalls.h	Sun Feb 10 19:58:04 2002
+++ b/arch/mips/kernel/syscalls.h	Sun Feb 10 19:58:04 2002
@@ -235,3 +235,5 @@
 SYS(sys_madvise, 3)
 SYS(sys_getdents64, 3)
 SYS(sys_fcntl64, 3)				/* 4220 */
+SYS(sys_gettid, 0)
+SYS(sys_tkill, 2)
diff -Nru a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
--- a/arch/mips/kernel/sysirix.c	Sun Feb 10 19:58:05 2002
+++ b/arch/mips/kernel/sysirix.c	Sun Feb 10 19:58:05 2002
@@ -1178,7 +1178,7 @@
 	return MAJOR (t) << 18 | MINOR (t);
 }
 
-static inline int irix_xstat32_xlate(struct stat *kb, void *ubuf)
+static inline int irix_xstat32_xlate(struct kstat *stat, void *ubuf)
 {
 	struct xstat32 {
 		u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid;
@@ -1191,28 +1191,32 @@
 		u32 st_pad4[8];
 	} ub;
 
-	ub.st_dev     = linux_to_irix_dev_t (kb->st_dev);
-	ub.st_ino     = kb->st_ino;
-	ub.st_mode    = kb->st_mode;
-	ub.st_nlink   = kb->st_nlink;
-	ub.st_uid     = kb->st_uid;
-	ub.st_gid     = kb->st_gid;
-	ub.st_rdev    = linux_to_irix_dev_t (kb->st_rdev);
-	ub.st_size    = kb->st_size;
-	ub.st_atime0  = kb->st_atime;
+	ub.st_dev     = linux_to_irix_dev_t(stat->dev);
+	ub.st_ino     = stat->ino;
+	ub.st_mode    = stat->mode;
+	ub.st_nlink   = stat->nlink;
+	SET_STAT_UID(ub, stat->uid);
+	SET_STAT_GID(ub, stat->gid);
+	ub.st_rdev    = linux_to_irix_dev_t(stat->rdev);
+#if BITS_PER_LONG == 32
+	if (stat->size > MAX_NON_LFS)
+		return -EOVERFLOW;
+#endif	
+	ub.st_size    = stat->size;
+	ub.st_atime0  = stat->atime;
 	ub.st_atime1  = 0;
-	ub.st_mtime0  = kb->st_mtime;
+	ub.st_mtime0  = stat->mtime;
 	ub.st_mtime1  = 0;
-	ub.st_ctime0  = kb->st_ctime;
+	ub.st_ctime0  = stat->ctime;
 	ub.st_ctime1  = 0;
-	ub.st_blksize = kb->st_blksize;
-	ub.st_blocks  = kb->st_blocks;
+	ub.st_blksize = stat->blksize;
+	ub.st_blocks  = stat->blocks;
 	strcpy (ub.st_fstype, "efs");
 
 	return copy_to_user(ubuf, &ub, sizeof(ub)) ? -EFAULT : 0;
 }
 
-static inline void irix_xstat64_xlate(struct stat *sb)
+static inline void irix_xstat64_xlate(struct kstat *stat, void *ubuf)
 {
 	struct xstat64 {
 		u32 st_dev; s32 st_pad1[3];
@@ -1229,177 +1233,112 @@
 		s32 st_pad4[8];
 	} ks;
 
-	ks.st_dev = linux_to_irix_dev_t (sb->st_dev);
+	ks.st_dev = linux_to_irix_dev_t(stat->dev);
 	ks.st_pad1[0] = ks.st_pad1[1] = ks.st_pad1[2] = 0;
-	ks.st_ino = (unsigned long long) sb->st_ino;
-	ks.st_mode = (u32) sb->st_mode;
-	ks.st_nlink = (u32) sb->st_nlink;
-	ks.st_uid = (s32) sb->st_uid;
-	ks.st_gid = (s32) sb->st_gid;
-	ks.st_rdev = linux_to_irix_dev_t (sb->st_rdev);
+	ks.st_ino = (unsigned long long) stat->ino;
+	ks.st_mode = (u32) stat->mode;
+	ks.st_nlink = (u32) stat->nlink;
+	ks.st_uid = (s32) stat->uid;
+	ks.st_gid = (s32) stat->gid;
+	ks.st_rdev = linux_to_irix_dev_t (stat->rdev);
 	ks.st_pad2[0] = ks.st_pad2[1] = 0;
-	ks.st_size = (long long) sb->st_size;
+	ks.st_size = (long long) stat->size;
 	ks.st_pad3 = 0;
 
 	/* XXX hackety hack... */
-	ks.st_atime.tv_sec = (s32) sb->st_atime; ks.st_atime.tv_nsec = 0;
-	ks.st_mtime.tv_sec = (s32) sb->st_atime; ks.st_mtime.tv_nsec = 0;
-	ks.st_ctime.tv_sec = (s32) sb->st_atime; ks.st_ctime.tv_nsec = 0;
+	ks.st_atime.tv_sec = (s32) stat->atime; ks.st_atime.tv_nsec = 0;
+	ks.st_mtime.tv_sec = (s32) stat->atime; ks.st_mtime.tv_nsec = 0;
+	ks.st_ctime.tv_sec = (s32) stat->atime; ks.st_ctime.tv_nsec = 0;
 
-	ks.st_blksize = (s32) sb->st_blksize;
-	ks.st_blocks = (long long) sb->st_blocks;
+	ks.st_blksize = (s32) stat->blksize;
+	ks.st_blocks = (long long) stat->blocks;
 	memset(ks.st_fstype, 0, 16);
 	ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = 0;
 	ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
 
 	/* Now write it all back. */
-	copy_to_user(sb, &ks, sizeof(struct xstat64));
+	copy_to_user(ubuf, &ks, sizeof(struct xstat64));
 }
 
-extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
-
 asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
 {
 	int retval;
+	struct kstat stat;
 
 #ifdef DEBUG_XSTAT
 	printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
 	       current->comm, current->pid, version, filename, statbuf);
 #endif
-	switch(version) {
-	case 2: {
-		struct stat kb;
-		mm_segment_t old_fs;
-
-		old_fs = get_fs(); set_fs(get_ds());
-		retval = sys_newstat(filename, &kb);
-		set_fs(old_fs);
-#ifdef DEBUG_XSTAT
-		printk("retval[%d]\n", retval);
-#endif
-		if(retval)
-			goto out;
-		retval = irix_xstat32_xlate(&kb, statbuf);
-		goto out;
-	}
-
-	case 3: {
-		retval = sys_newstat(filename, statbuf);
-#ifdef DEBUG_XSTAT
-		printk("retval[%d]\n", retval);
-#endif
-		if(retval)
-			goto out;
 
-		irix_xstat64_xlate(statbuf);
-		retval = 0;
-		break;
+	retval = vfs_stat(filename, &stat);
+	if (!retval) {
+		switch(version) {
+			case 2:
+				retval = irix_xstat32_xlate(&stat, statbuf);
+				break;
+			case 3:
+				irix_xstat64_xlate(&stat, statbuf);
+				retval = 0; /* Really? */
+				break;
+			default:
+				retval = -EINVAL;
+		}
 	}
-
-	default:
-		retval = -EINVAL;
-		break;
-	}
-
-out:
 	return retval;
 }
 
-extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
-
 asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
 {
 	int error;
+	struct kstat stat;
 
 #ifdef DEBUG_XSTAT
 	printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
 	       current->comm, current->pid, version, filename, statbuf);
 #endif
-	switch(version) {
-	case 2: {
-		struct stat kb;
-		mm_segment_t old_fs;
-
-		old_fs = get_fs(); set_fs(get_ds());
-		error = sys_newlstat(filename, &kb);
-		set_fs(old_fs);
-#ifdef DEBUG_XSTAT
-		printk("error[%d]\n", error);
-#endif
-		if(error)
-			goto out;
-		error = irix_xstat32_xlate(&kb, statbuf);
-		goto out;
-	}
 
-	case 3: {
-		error = sys_newlstat(filename, statbuf);
-#ifdef DEBUG_XSTAT
-		printk("error[%d]\n", error);
-#endif
-		if(error)
-			goto out;
-
-		irix_xstat64_xlate(statbuf);
-		error = 0;
-		goto out;
-	}
+	error = vfs_lstat(filename, &stat);
 
-	default:
-		error = -EINVAL;
-		goto out;
+	if (!error) {
+		switch (version) {
+			case 2:
+				error = irix_xstat32_xlate(&stat, statbuf);
+				break;
+			case 3:
+				irix_xstat64_xlate(&stat, statbuf);
+				error = 0;
+				break;
+			default:
+				error = -EINVAL;
+		}
 	}
-
-out:
 	return error;
 }
 
-extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
-
 asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
 {
 	int error;
+	struct kstat stat;
 
 #ifdef DEBUG_XSTAT
 	printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
 	       current->comm, current->pid, version, fd, statbuf);
 #endif
-	switch(version) {
-	case 2: {
-		struct stat kb;
-		mm_segment_t old_fs;
-
-		old_fs = get_fs(); set_fs(get_ds());
-		error = sys_newfstat(fd, &kb);
-		set_fs(old_fs);
-#ifdef DEBUG_XSTAT
-		printk("error[%d]\n", error);
-#endif
-		if(error)
-			goto out;
-		error = irix_xstat32_xlate(&kb, statbuf);
-		goto out;
-	}
-
-	case 3: {
-		error = sys_newfstat(fd, statbuf);
-#ifdef DEBUG_XSTAT
-		printk("error[%d]\n", error);
-#endif
-		if(error)
-			goto out;
 
-		irix_xstat64_xlate(statbuf);
-		error = 0;
-		goto out;
+	error = vfs_fstat(fd, &stat);
+	if (!error) {
+		switch (version) {
+			case 2:
+				error = irix_xstat32_xlate(&stat, statbuf);
+				break;
+			case 3:
+				irix_xstat64_xlate(&stat, statbuf);
+				error = 0;
+				break;
+			default:
+				error = -EINVAL;
+		}
 	}
-
-	default:
-		error = -EINVAL;
-		goto out;
-	}
-
-out:
 	return error;
 }
 
diff -Nru a/arch/mips64/Config.help b/arch/mips64/Config.help
--- a/arch/mips64/Config.help	Sun Feb 10 19:58:05 2002
+++ b/arch/mips64/Config.help	Sun Feb 10 19:58:05 2002
@@ -438,31 +438,6 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_BINFMT_ELF32
   This allows you to run 32-bit Linux/ELF binaries on your Ultra.
   Everybody wants this; say Y.
diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c
--- a/arch/mips64/kernel/linux32.c	Sun Feb 10 19:58:04 2002
+++ b/arch/mips64/kernel/linux32.c	Sun Feb 10 19:58:04 2002
@@ -39,125 +39,59 @@
 /*
  * Revalidate the inode. This is required for proper NFS attribute caching.
  */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-	struct inode * inode = dentry->d_inode;
-
-	if (inode->i_op && inode->i_op->revalidate)
-		return inode->i_op->revalidate(dentry);
-
-	return 0;
-}
 
-static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf)
+static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
 {
 	struct stat32 tmp;
-	unsigned int blocks, indirect;
 
 	memset(&tmp, 0, sizeof(tmp));
-	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
-	tmp.st_ino = inode->i_ino;
-	tmp.st_mode = inode->i_mode;
-	tmp.st_nlink = inode->i_nlink;
-	SET_STAT_UID(tmp, inode->i_uid);
-	SET_STAT_GID(tmp, inode->i_gid);
-	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
-	tmp.st_size = inode->i_size;
-	tmp.st_atime = inode->i_atime;
-	tmp.st_mtime = inode->i_mtime;
-	tmp.st_ctime = inode->i_ctime;
-
-	/*
-	 * st_blocks and st_blksize are approximated with a simple algorithm if
-	 * they aren't supported directly by the filesystem. The minix and msdos
-	 * filesystems don't keep track of blocks, so they would either have to
-	 * be counted explicitly (by delving into the file itself), or by using
-	 * this simple algorithm to get a reasonable (although not 100%
-	 * accurate) value.
-	 */
-
-	/*
-	 * Use minix fs values for the number of direct and indirect blocks.
-	 * The count is now exact for the minix fs except that it counts zero
-	 * blocks.  Everything is in units of BLOCK_SIZE until the assignment
-	 * to tmp.st_blksize.
-	 */
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-
-	if (!inode->i_blksize) {
-		blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		if (blocks > D_B) {
-			indirect = (blocks - D_B + I_B - 1) / I_B;
-			blocks += indirect;
-			if (indirect > 1) {
-				indirect = (indirect - 1 + I_B - 1) / I_B;
-				blocks += indirect;
-				if (indirect > 1)
-					blocks++;
-			}
-		}
-		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-		tmp.st_blksize = BLOCK_SIZE;
-	} else {
-		tmp.st_blocks = inode->i_blocks;
-		tmp.st_blksize = inode->i_blksize;
-	}
-
+	tmp.st_dev = stat->dev;
+	tmp.st_ino = stat->ino;
+	tmp.st_mode = stat->mode;
+	tmp.st_nlink = stat->nlink;
+	SET_STAT_UID(tmp, stat->uid);
+	SET_STAT_GID(tmp, stat->gid);
+	tmp.st_rdev = stat->rdev;
+	tmp.st_size = stat->size;
+	tmp.st_atime = stat->atime;
+	tmp.st_mtime = stat->mtime;
+	tmp.st_ctime = stat->ctime;
+	tmp.st_blocks = stat->blocks;
+	tmp.st_blksize = stat->blksize;
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-	struct nameidata nd;
-	int error;
-
-	error = user_path_walk(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
 
-		path_release(&nd);
-	}
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
 	return error;
 }
 
 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
 
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
-
-		path_release(&nd);
-	}
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
 	return error;
 }
 
 asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
 {
-	struct file * f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
-
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_new_stat32(dentry->d_inode, statbuf);
-		fput(f);
-	}
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
-	return err;
+	return error;
 }
 
 asmlinkage int sys_mmap2(void) {return 0;}
diff -Nru a/arch/mips64/kernel/scall_64.S b/arch/mips64/kernel/scall_64.S
--- a/arch/mips64/kernel/scall_64.S	Sun Feb 10 19:58:04 2002
+++ b/arch/mips64/kernel/scall_64.S	Sun Feb 10 19:58:04 2002
@@ -347,3 +347,5 @@
 	PTR	sys_mincore
 	PTR	sys_madvise
 	PTR	sys_getdents64
+	PTR	sys_gettid
+	PTR	sys_tkill
diff -Nru a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S
--- a/arch/mips64/kernel/scall_o32.S	Sun Feb 10 19:58:05 2002
+++ b/arch/mips64/kernel/scall_o32.S	Sun Feb 10 19:58:05 2002
@@ -454,6 +454,8 @@
 	sys	sys_madvise	3
 	sys	sys_getdents64	3
 	sys	sys32_fcntl64	3			/* 4220 */
+	sys	sys32_gettid	0
+	sys	sys32_tkill	2
 	.endm
 
 	.macro	sys function, nargs
diff -Nru a/arch/mips64/kernel/signal.c b/arch/mips64/kernel/signal.c
--- a/arch/mips64/kernel/signal.c	Sun Feb 10 19:58:05 2002
+++ b/arch/mips64/kernel/signal.c	Sun Feb 10 19:58:05 2002
@@ -685,10 +685,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/mips64/kernel/signal32.c b/arch/mips64/kernel/signal32.c
--- a/arch/mips64/kernel/signal32.c	Sun Feb 10 19:58:06 2002
+++ b/arch/mips64/kernel/signal32.c	Sun Feb 10 19:58:06 2002
@@ -757,10 +757,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
--- a/arch/parisc/hpux/fs.c	Sun Feb 10 19:58:05 2002
+++ b/arch/parisc/hpux/fs.c	Sun Feb 10 19:58:05 2002
@@ -83,42 +83,20 @@
 int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count)
 {
 	struct file * file;
-	struct dentry * dentry;
-	struct inode * inode;
 	struct hpux_dirent * lastdirent;
 	struct getdents_callback buf;
-	int error;
+	int error = -EBADF;
 
-	lock_kernel();
-	error = -EBADF;
 	file = fget(fd);
 	if (!file)
 		goto out;
 
-	dentry = file->f_dentry;
-	if (!dentry)
-		goto out_putf;
-
-	inode = dentry->d_inode;
-	if (!inode)
-		goto out_putf;
-
 	buf.current_dir = dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
 
-	error = -ENOTDIR;
-	if (!file->f_op || !file->f_op->readdir)
-		goto out_putf;
-
-	/*
-	 * Get the inode's semaphore to prevent changes
-	 * to the directory while we read it.
-	 */
-	down(&inode->i_sem);
-	error = file->f_op->readdir(file, &buf, filldir);
-	up(&inode->i_sem);
+	error = vfs_readdir(file, &buf, filldir);
 	if (error < 0)
 		goto out_putf;
 	error = buf.error;
@@ -131,7 +109,6 @@
 out_putf:
 	fput(file);
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -141,110 +118,56 @@
 	return -ENOSYS;
 }
 
-static int cp_hpux_stat(struct inode * inode, struct hpux_stat64 * statbuf)
+static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf)
 {
 	struct hpux_stat64 tmp;
-	unsigned int blocks, indirect;
 
 	memset(&tmp, 0, sizeof(tmp));
-	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
-	tmp.st_ino = inode->i_ino;
-	tmp.st_mode = inode->i_mode;
-	tmp.st_nlink = inode->i_nlink;
-	tmp.st_uid = inode->i_uid;
-	tmp.st_gid = inode->i_gid;
-	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
-	tmp.st_size = inode->i_size;
-	tmp.st_atime = inode->i_atime;
-	tmp.st_mtime = inode->i_mtime;
-	tmp.st_ctime = inode->i_ctime;
-
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-
-	if (!inode->i_blksize) {
-		blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		if (blocks > D_B) {
-			indirect = (blocks - D_B + I_B - 1) / I_B;
-			blocks += indirect;
-			if (indirect > 1) {
-				indirect = (indirect - 1 + I_B - 1) / I_B;
-				blocks += indirect;
-				if (indirect > 1)
-					blocks++;
-			}
-		}
-		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-		tmp.st_blksize = BLOCK_SIZE;
-	} else {
-		tmp.st_blocks = inode->i_blocks;
-		tmp.st_blksize = inode->i_blksize;
-	}
+	tmp.st_dev = stat->dev;
+	tmp.st_ino = stat->ino;
+	tmp.st_mode = stat->mode;
+	tmp.st_nlink = stat->nlink;
+	tmp.st_uid = stat->uid;
+	tmp.st_gid = stat->gid;
+	tmp.st_rdev = stat->rdev;
+	tmp.st_size = stat->size;
+	tmp.st_atime = stat->atime;
+	tmp.st_mtime = stat->mtime;
+	tmp.st_ctime = stat->ctime;
+	tmp.st_blocks = stat->blocks;
+	tmp.st_blksize = stat->blksize;
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-/*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- * Blatently copied wholesale from fs/stat.c
- */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-	struct inode * inode = dentry->d_inode;
-	if (inode->i_op && inode->i_op->revalidate)
-		return inode->i_op->revalidate(dentry);
-	return 0;
-}
-
 long hpux_stat64(const char *path, struct hpux_stat64 *buf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
+
+	if (!error)
+		error = cp_hpux_stat(&stat, statbuf);
 
-	lock_kernel();
-	error = user_path_walk(path, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_hpux_stat(nd.dentry->d_inode, buf);
-		path_release(&nd);
-	}
-	unlock_kernel();
 	return error;
 }
 
 long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
 {
-	struct file * f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	lock_kernel();
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
-
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_hpux_stat(dentry->d_inode, statbuf);
-		fput(f);
-	}
-	unlock_kernel();
-	return err;
+	if (!error)
+		error = cp_hpux_stat(&stat, statbuf);
+
+	return error;
 }
 
 long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
+
+	if (!error)
+		error = cp_hpux_stat(&stat, statbuf);
 
-	lock_kernel();
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_hpux_stat(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
-	unlock_kernel();
 	return error;
 }
diff -Nru a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
--- a/arch/parisc/kernel/signal.c	Sun Feb 10 19:58:06 2002
+++ b/arch/parisc/kernel/signal.c	Sun Feb 10 19:58:06 2002
@@ -581,11 +581,7 @@
 				/* FALLTHRU */
 
 			default:
-				lock_kernel();
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
--- a/arch/parisc/kernel/syscall.S	Sun Feb 10 19:58:06 2002
+++ b/arch/parisc/kernel/syscall.S	Sun Feb 10 19:58:06 2002
@@ -552,6 +552,8 @@
 	ENTRY_UHOH(shmctl)		/* 195 */
 	ENTRY_SAME(ni_syscall)		/* streams1 */
 	ENTRY_SAME(ni_syscall)		/* streams2 */
+	ENTRY_SAME(gettid)
+	ENTRY_SAME(tkill)
 
 .end
 
diff -Nru a/arch/ppc/Config.help b/arch/ppc/Config.help
--- a/arch/ppc/Config.help	Sun Feb 10 19:58:05 2002
+++ b/arch/ppc/Config.help	Sun Feb 10 19:58:05 2002
@@ -551,31 +551,6 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_PROC_HARDWARE
   Say Y here to support the /proc/hardware file, which gives you
   access to information about the machine you're running on,
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Sun Feb 10 19:58:05 2002
+++ b/arch/ppc/kernel/misc.S	Sun Feb 10 19:58:05 2002
@@ -1121,6 +1121,7 @@
 	.long sys_madvise	/* 205 */
 	.long sys_mincore
 	.long sys_gettid
+	.long sys_tkill
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
 	.endr
diff -Nru a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
--- a/arch/ppc/kernel/ppc_htab.c	Sun Feb 10 19:58:04 2002
+++ b/arch/ppc/kernel/ppc_htab.c	Sun Feb 10 19:58:04 2002
@@ -21,6 +21,7 @@
 #include <linux/sysctl.h>
 #include <linux/ctype.h>
 #include <linux/threads.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -430,18 +431,20 @@
 static long long
 ppc_htab_lseek(struct file * file, loff_t offset, int orig)
 {
+    long long ret = -EINVAL;
+
+    lock_kernel();
     switch (orig) {
     case 0:
 	file->f_pos = offset;
-	return(file->f_pos);
+	ret = file->f_pos;
+	break;
     case 1:
 	file->f_pos += offset;
-	return(file->f_pos);
-    case 2:
-	return(-EINVAL);
-    default:
-	return(-EINVAL);
+	ret = file->f_pos;
     }
+    unlock_kernel();
+    return ret;
 }
 
 int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
--- a/arch/ppc/kernel/signal.c	Sun Feb 10 19:58:06 2002
+++ b/arch/ppc/kernel/signal.c	Sun Feb 10 19:58:06 2002
@@ -641,10 +641,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	Sun Feb 10 19:58:04 2002
+++ b/arch/s390/kernel/entry.S	Sun Feb 10 19:58:04 2002
@@ -602,6 +602,8 @@
 	.long  sys_ni_syscall		 /* 224 - reserved for posix_acl */
 	.rept  255-224
 	.long  sys_ni_syscall
+	.long  sys_gettid		/* 226 */
+	.long  sys_tkill		/* 227 */
 	.endr
 
 /*
diff -Nru a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
--- a/arch/s390/kernel/signal.c	Sun Feb 10 19:58:05 2002
+++ b/arch/s390/kernel/signal.c	Sun Feb 10 19:58:05 2002
@@ -563,10 +563,7 @@
                                 /* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/s390/vmlinux-shared.lds b/arch/s390/vmlinux-shared.lds
--- a/arch/s390/vmlinux-shared.lds	Sun Feb 10 19:58:06 2002
+++ b/arch/s390/vmlinux-shared.lds	Sun Feb 10 19:58:06 2002
@@ -13,7 +13,6 @@
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
   .rodata : { *(.rodata) }
   .kstrtab : { *(.kstrtab) }
 
diff -Nru a/arch/s390/vmlinux.lds b/arch/s390/vmlinux.lds
--- a/arch/s390/vmlinux.lds	Sun Feb 10 19:58:05 2002
+++ b/arch/s390/vmlinux.lds	Sun Feb 10 19:58:05 2002
@@ -13,7 +13,6 @@
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
   .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
--- a/arch/s390x/kernel/entry.S	Sun Feb 10 19:58:05 2002
+++ b/arch/s390x/kernel/entry.S	Sun Feb 10 19:58:05 2002
@@ -635,6 +635,8 @@
 	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for posix_acl */
         .rept  255-224
 	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
+	.long  SYSCALL(sys_gettid,sys_gettid)
+	.long  SYSCALL(sys_tkill,sys_tkill)
 	.endr
 
 /*
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	Sun Feb 10 19:58:04 2002
+++ b/arch/s390x/kernel/linux32.c	Sun Feb 10 19:58:04 2002
@@ -1471,140 +1471,62 @@
 	return ret;
 }
 
-static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
+static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
 {
-	unsigned long ino, blksize, blocks;
-	kdev_t dev, rdev;
-	umode_t mode;
-	nlink_t nlink;
-	uid_t uid;
-	gid_t gid;
-	off_t size;
-	time_t atime, mtime, ctime;
-	int err;
-
-	/* Stream the loads of inode data into the load buffer,
-	 * then we push it all into the store buffer below.  This
-	 * should give optimal cache performance.
-	 */
-	ino = inode->i_ino;
-	dev = inode->i_dev;
-	mode = inode->i_mode;
-	nlink = inode->i_nlink;
-	uid = inode->i_uid;
-	gid = inode->i_gid;
-	rdev = inode->i_rdev;
-	size = inode->i_size;
-	atime = inode->i_atime;
-	mtime = inode->i_mtime;
-	ctime = inode->i_ctime;
-	blksize = inode->i_blksize;
-	blocks = inode->i_blocks;
-
-	err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
-	err |= put_user(ino, &statbuf->st_ino);
-	err |= put_user(mode, &statbuf->st_mode);
-	err |= put_user(nlink, &statbuf->st_nlink);
-	err |= put_user(high2lowuid(uid), &statbuf->st_uid);
-	err |= put_user(high2lowgid(gid), &statbuf->st_gid);
-	err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
-	err |= put_user(size, &statbuf->st_size);
-	err |= put_user(atime, &statbuf->st_atime);
+	err  = put_user(stat->dev, &statbuf->st_dev);
+	err |= put_user(stat->ino, &statbuf->st_ino);
+	err |= put_user(stat->mode, &statbuf->st_mode);
+	err |= put_user(stat->nlink, &statbuf->st_nlink);
+	err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
+	err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
+	err |= put_user(stat->rdev, &statbuf->st_rdev);
+	err |= put_user(stat->size, &statbuf->st_size);
+	err |= put_user(stat->atime, &statbuf->st_atime);
 	err |= put_user(0, &statbuf->__unused1);
-	err |= put_user(mtime, &statbuf->st_mtime);
+	err |= put_user(stat->mtime, &statbuf->st_mtime);
 	err |= put_user(0, &statbuf->__unused2);
-	err |= put_user(ctime, &statbuf->st_ctime);
+	err |= put_user(stat->ctime, &statbuf->st_ctime);
 	err |= put_user(0, &statbuf->__unused3);
-	if (blksize) {
-		err |= put_user(blksize, &statbuf->st_blksize);
-		err |= put_user(blocks, &statbuf->st_blocks);
-	} else {
-		unsigned int tmp_blocks;
-
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-		tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		if (tmp_blocks > D_B) {
-			unsigned int indirect;
-
-			indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
-			tmp_blocks += indirect;
-			if (indirect > 1) {
-				indirect = (indirect - 1 + I_B - 1) / I_B;
-				tmp_blocks += indirect;
-				if (indirect > 1)
-					tmp_blocks++;
-			}
-		}
-		err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
-		err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
-#undef D_B
-#undef I_B
-	}
+	err |= put_user(stat->blksize, &statbuf->st_blksize);
+	err |= put_user(stat->blocks, &statbuf->st_blocks);
 /* fixme
 	err |= put_user(0, &statbuf->__unused4[0]);
 	err |= put_user(0, &statbuf->__unused4[1]);
 */
-
 	return err;
 }
 
-/* Perhaps this belongs in fs.h or similar. -DaveM */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-	struct inode * inode = dentry->d_inode;
-	if (inode->i_op && inode->i_op->revalidate)
-		return inode->i_op->revalidate(dentry);
-	return 0;
-}
-
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
+
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
-	error = user_path_walk(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
 	return error;
 }
 
 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
 
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
-		path_release(&nd);
-	}
 	return error;
 }
 
 asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
 {
-	struct file *f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
-
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_new_stat32(dentry->d_inode, statbuf);
-		fput(f);
-	}
-	return err;
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
+
+	return error;
 }
 
 extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
diff -Nru a/arch/s390x/kernel/signal.c b/arch/s390x/kernel/signal.c
--- a/arch/s390x/kernel/signal.c	Sun Feb 10 19:58:04 2002
+++ b/arch/s390x/kernel/signal.c	Sun Feb 10 19:58:04 2002
@@ -569,10 +569,7 @@
                                 /* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/s390x/kernel/signal32.c b/arch/s390x/kernel/signal32.c
--- a/arch/s390x/kernel/signal32.c	Sun Feb 10 19:58:06 2002
+++ b/arch/s390x/kernel/signal32.c	Sun Feb 10 19:58:06 2002
@@ -699,10 +699,7 @@
                                 /* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/s390x/vmlinux-shared.lds b/arch/s390x/vmlinux-shared.lds
--- a/arch/s390x/vmlinux-shared.lds	Sun Feb 10 19:58:05 2002
+++ b/arch/s390x/vmlinux-shared.lds	Sun Feb 10 19:58:05 2002
@@ -13,7 +13,6 @@
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
   .rodata : { *(.rodata) }
   .kstrtab : { *(.kstrtab) }
 
diff -Nru a/arch/s390x/vmlinux.lds b/arch/s390x/vmlinux.lds
--- a/arch/s390x/vmlinux.lds	Sun Feb 10 19:58:05 2002
+++ b/arch/s390x/vmlinux.lds	Sun Feb 10 19:58:05 2002
@@ -13,7 +13,6 @@
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
   .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
diff -Nru a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
--- a/arch/sh/kernel/entry.S	Sun Feb 10 19:58:05 2002
+++ b/arch/sh/kernel/entry.S	Sun Feb 10 19:58:05 2002
@@ -1195,6 +1195,8 @@
 	.long SYMBOL_NAME(sys_madvise)
 	.long SYMBOL_NAME(sys_getdents64)	/* 220 */
 	.long SYMBOL_NAME(sys_fcntl64)
+	.long SYMBOL_NAME(sys_gettid)
+	.long SYMBOL_NAME(sys_tkill)
 
 	/*
 	 * NOTE!! This doesn't have to be exact - we just have
diff -Nru a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
--- a/arch/sh/kernel/signal.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sh/kernel/signal.c	Sun Feb 10 19:58:06 2002
@@ -673,10 +673,7 @@
 				/* FALLTHRU */
 
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOTREACHED */
 			}
 		}
diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
--- a/arch/sh/vmlinux.lds.S	Sun Feb 10 19:58:03 2002
+++ b/arch/sh/vmlinux.lds.S	Sun Feb 10 19:58:03 2002
@@ -23,7 +23,6 @@
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
   .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
diff -Nru a/arch/sparc/Config.help b/arch/sparc/Config.help
--- a/arch/sparc/Config.help	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc/Config.help	Sun Feb 10 19:58:05 2002
@@ -1054,31 +1054,6 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
-CONFIG_ISDN
-  ISDN ("Integrated Services Digital Networks", called RNIS in France)
-  is a special type of fully digital telephone service; it's mostly
-  used to connect to your Internet service provider (with SLIP or
-  PPP).  The main advantage is that the speed is higher than ordinary
-  modem/telephone connections, and that you can have voice
-  conversations while downloading stuff.  It only works if your
-  computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read <http://alumni.caltech.edu/~dank/isdn/> on the WWW.
-
-  This driver allows you to use an ISDN-card for networking
-  connections and as dialin/out device.  The isdn-tty's have a built
-  in AT-compatible modem emulator.  Network devices support autodial,
-  channel-bundling, callback and caller-authentication without having
-  a daemon running.  A reduced T.70 protocol is supported with tty's
-  suitable for German BTX.  On D-Channel, the protocols EDSS1
-  (Euro-ISDN) and 1TR6 (German style) are supported.  See
-  <file:Documentation/isdn/README> for more information.
-
-  If you want to compile the ISDN code as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read <file:Documentation/modules.txt>.  The
-  module will be called isdn.o. If unsure, say N.
-
 CONFIG_SUN4
   Say Y here if, and only if, your machine is a Sun4. Note that
   a kernel compiled with this option will run only on Sun4.
diff -Nru a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
--- a/arch/sparc/kernel/rtrap.S	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc/kernel/rtrap.S	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.57 2001/07/17 16:17:33 anton Exp $
+/* $Id: rtrap.S,v 1.58 2002/01/31 03:30:05 davem Exp $
  * rtrap.S: Return from Sparc trap low-level code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
--- a/arch/sparc/kernel/signal.c	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc/kernel/signal.c	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.109 2001/12/21 01:22:31 davem Exp $
+/*  $Id: signal.c,v 1.110 2002/02/08 03:57:14 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -1280,10 +1280,7 @@
 #endif
 				/* fall through */
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOT REACHED */
 			}
 		}
diff -Nru a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
--- a/arch/sparc/kernel/sys_sunos.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc/kernel/sys_sunos.c	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.136 2002/01/08 16:00:14 davem Exp $
+/* $Id: sys_sunos.c,v 1.137 2002/02/08 03:57:14 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -646,7 +646,7 @@
 
 	inode = file->f_dentry->d_inode;
 
-	socket = &inode->u.socket_i;
+	socket = SOCKET_I(inode);
 	local.sin_family = AF_INET;
 	local.sin_addr.s_addr = INADDR_ANY;
 
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc/kernel/systbls.S	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.101 2001/10/18 08:27:05 davem Exp $
+/* $Id: systbls.S,v 1.103 2002/02/08 03:57:14 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -51,11 +51,11 @@
 /*150*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
 /*155*/	.long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/	.long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
-/*165*/	.long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
-/*170*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
-/*175*/	.long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
-/*185*/	.long sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
+/*165*/	.long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
+/*170*/	.long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
+/*175*/	.long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
+/*180*/	.long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
+/*185*/	.long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
 /*190*/	.long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*195*/	.long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
 /*200*/	.long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
diff -Nru a/arch/sparc64/Config.help b/arch/sparc64/Config.help
--- a/arch/sparc64/Config.help	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/Config.help	Sun Feb 10 19:58:06 2002
@@ -25,6 +25,16 @@
 
   If you don't know what to do here, say N.
 
+CONFIG_PREEMPT
+  This option reduces the latency of the kernel when reacting to
+  real-time or interactive events by allowing a low priority process to
+  be preempted even if it is in kernel mode executing a system call.
+  This allows applications to run more reliably even when the system is
+  under load.
+
+  Say Y here if you are building a kernel for a desktop, embedded
+  or real-time system.  Say N if you are unsure.
+
 CONFIG_SPARC64
   SPARC is a family of RISC microprocessors designed and marketed by
   Sun Microsystems, incorporated.  This port covers the newer 64-bit
diff -Nru a/arch/sparc64/Makefile b/arch/sparc64/Makefile
--- a/arch/sparc64/Makefile	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/Makefile	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.51 2001/11/17 00:15:27 davem Exp $
+# $Id: Makefile,v 1.52 2002/02/09 19:49:31 davem Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -79,12 +79,8 @@
 	rm -f $(TOPDIR)/vmlinux.aout
 
 archmrproper:
-	rm -f $(TOPDIR)/include/asm-sparc64/asm_offsets.h
 
-archdep: check_asm
-
-check_asm: include/linux/version.h
-	$(MAKE) -C arch/sparc64/kernel check_asm
+archdep:
 
 tftpboot.img:
 	$(MAKE) -C arch/sparc64/boot tftpboot.img
diff -Nru a/arch/sparc64/config.in b/arch/sparc64/config.in
--- a/arch/sparc64/config.in	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/config.in	Sun Feb 10 19:58:05 2002
@@ -15,6 +15,7 @@
 define_bool CONFIG_VT_CONSOLE y
 
 bool 'Symmetric multi-processing support' CONFIG_SMP
+bool 'Preemptible kernel' CONFIG_PREEMPT
 
 # Identify this as a Sparc64 build
 define_bool CONFIG_SPARC64 y
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/defconfig	Sun Feb 10 19:58:05 2002
@@ -3,6 +3,11 @@
 #
 
 #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
 # General setup
 #
 CONFIG_NET=y
@@ -11,11 +16,6 @@
 CONFIG_SYSCTL=y
 
 #
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
 # Loadable module support
 #
 CONFIG_MODULES=y
@@ -456,7 +456,6 @@
 CONFIG_HAPPYMEAL=y
 CONFIG_SUNBMAC=m
 CONFIG_SUNQE=m
-CONFIG_SUNLANCE=y
 CONFIG_SUNGEM=y
 CONFIG_NET_VENDOR_3COM=y
 # CONFIG_EL1 is not set
@@ -487,6 +486,7 @@
 # CONFIG_LNE390 is not set
 CONFIG_FEALNX=m
 CONFIG_NATSEMI=m
+# CONFIG_NATSEMI_CABLE_MAGIC is not set
 CONFIG_NE2K_PCI=m
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
@@ -495,6 +495,7 @@
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_NEW_RX_RESET is not set
 CONFIG_SIS900=m
 CONFIG_EPIC100=m
 CONFIG_SUNDANCE=m
@@ -575,7 +576,7 @@
 # CONFIG_DRM_R128 is not set
 
 #
-# Input core support
+# Input device support
 #
 CONFIG_INPUT=y
 CONFIG_INPUT_KEYBDEV=y
@@ -584,6 +585,36 @@
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=y
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_GAMEPORT_PCIGAME is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461x is not set
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE_USB is not set
+# CONFIG_JOYSTICK_IFORCE_232 is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
 
 #
 # File systems
@@ -639,7 +670,7 @@
 # Network File Systems
 #
 CONFIG_CODA_FS=m
-CONFIG_INTERMEZZO_FS=m
+# CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_ROOT_NFS is not set
@@ -659,7 +690,6 @@
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 # CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
 
 #
 # Partition Types
@@ -887,3 +917,5 @@
 # Library routines
 #
 CONFIG_CRC32=y
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
diff -Nru a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
--- a/arch/sparc64/kernel/Makefile	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/kernel/Makefile	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.69 2001/11/19 04:09:53 davem Exp $
+# $Id: Makefile,v 1.70 2002/02/09 19:49:30 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -55,119 +55,5 @@
 else
   CMODEL_CFLAG := -m64 -mcmodel=medlow
 endif
-
-check_asm: dummy
-	@if [ ! -r $(HPATH)/asm/asm_offsets.h ] ; then \
-	  touch $(HPATH)/asm/asm_offsets.h ; \
-	fi
-	@echo "/* Automatically generated. Do not edit. */" > asm_offsets.h
-	@echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
-	@echo -e "#define __ASM_OFFSETS_H__\n" >> asm_offsets.h
-	@echo -e "#include <linux/config.h>\n" >> asm_offsets.h
-	@echo -e "#ifndef CONFIG_SMP\n" >> asm_offsets.h
-	@echo "#include <linux/config.h>" > tmp.c
-	@echo "#undef CONFIG_SMP" >> tmp.c
-	@echo "#include <linux/sched.h>" >> tmp.c
-	$(CPP) $(CPPFLAGS) -P tmp.c -o tmp.i
-	@echo "/* Automatically generated. Do not edit. */" > check_asm_data.c
-	@echo "#include <linux/config.h>" >> check_asm_data.c
-	@echo "#undef CONFIG_SMP" >> check_asm_data.c
-	@echo "#include <linux/sched.h>" >> check_asm_data.c
-	@echo 'unsigned int check_asm_data[] = {' >> check_asm_data.c
-	$(SH) ./check_asm.sh -data task tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c
-	@echo '};' >> check_asm_data.c
-	$(CC) $(CPPFLAGS) $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm_data.s check_asm_data.c
-	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
-	@echo 'extern int printf(const char *fmt, ...);' >>check_asm.c
-	@echo 'unsigned int check_asm_data[] = {' >> check_asm.c
-	$(SH) ./check_asm.sh -ints check_asm_data.s check_asm.c
-	@echo '};' >> check_asm.c
-	@echo 'int main(void) {' >> check_asm.c
-	@echo 'int i = 0;' >> check_asm.c
-	$(SH) ./check_asm.sh -printf task tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf mm tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf thread tmp.i check_asm.c
-	@echo 'return 0; }' >> check_asm.c
-	@rm -f tmp.[ci] check_asm_data.[cs]
-	$(HOSTCC) -o check_asm check_asm.c
-	./check_asm >> asm_offsets.h
-	@rm -f check_asm check_asm.c
-	@echo -e "\n#else /* CONFIG_SMP */\n" >> asm_offsets.h
-	@echo -e "#ifndef CONFIG_DEBUG_SPINLOCK\n" >>asm_offsets.h
-	@echo "#include <linux/config.h>" > tmp.c
-	@echo "#undef CONFIG_SMP" >> tmp.c
-	@echo "#define CONFIG_SMP 1" >> tmp.c
-	@echo "#include <linux/sched.h>" >> tmp.c
-	$(CPP) $(CPPFLAGS) -P tmp.c -o tmp.i
-	@echo "/* Automatically generated. Do not edit. */" > check_asm_data.c
-	@echo "#include <linux/config.h>" >> check_asm_data.c
-	@echo "#undef CONFIG_SMP" >> check_asm_data.c
-	@echo "#define CONFIG_SMP 1" >> check_asm_data.c
-	@echo "#include <linux/sched.h>" >> check_asm_data.c
-	@echo 'unsigned int check_asm_data[] = {' >> check_asm_data.c
-	$(SH) ./check_asm.sh -data task tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c
-	@echo '};' >> check_asm_data.c
-	$(CC) $(CPPFLAGS) $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm_data.s check_asm_data.c
-	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
-	@echo 'extern int printf(const char *fmt, ...);' >>check_asm.c
-	@echo 'unsigned int check_asm_data[] = {' >> check_asm.c
-	$(SH) ./check_asm.sh -ints check_asm_data.s check_asm.c
-	@echo '};' >> check_asm.c
-	@echo 'int main(void) {' >> check_asm.c
-	@echo 'int i = 0;' >> check_asm.c
-	$(SH) ./check_asm.sh -printf task tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf mm tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf thread tmp.i check_asm.c
-	@echo 'return 0; }' >> check_asm.c
-	@rm -f tmp.[ci] check_asm_data.[cs]
-	$(HOSTCC) -o check_asm check_asm.c
-	./check_asm >> asm_offsets.h
-	@rm -f check_asm check_asm.c
-	@echo -e "\n#else /* CONFIG_DEBUG_SPINLOCK */\n" >> asm_offsets.h
-	@echo "#include <linux/sched.h>" > tmp.c
-	$(CPP) $(CPPFLAGS) -P -DCONFIG_DEBUG_SPINLOCK tmp.c -o tmp.i
-	@echo "/* Automatically generated. Do not edit. */" > check_asm_data.c
-	@echo "#include <linux/config.h>" >> check_asm_data.c
-	@echo "#undef CONFIG_SMP" >> check_asm_data.c
-	@echo "#define CONFIG_SMP 1" >> check_asm_data.c
-	@echo "#include <linux/sched.h>" >> check_asm_data.c
-	@echo 'unsigned int check_asm_data[] = {' >> check_asm_data.c
-	$(SH) ./check_asm.sh -data task tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data mm tmp.i check_asm_data.c
-	$(SH) ./check_asm.sh -data thread tmp.i check_asm_data.c
-	@echo '};' >> check_asm_data.c
-	$(CC) $(CPPFLAGS) -DCONFIG_DEBUG_SPINLOCK $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm_data.s check_asm_data.c
-	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
-	@echo 'extern int printf(const char *fmt, ...);' >>check_asm.c
-	@echo 'unsigned int check_asm_data[] = {' >> check_asm.c
-	$(SH) ./check_asm.sh -ints check_asm_data.s check_asm.c
-	@echo '};' >> check_asm.c
-	@echo 'int main(void) {' >> check_asm.c
-	@echo 'int i = 0;' >> check_asm.c
-	$(SH) ./check_asm.sh -printf task tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf mm tmp.i check_asm.c
-	$(SH) ./check_asm.sh -printf thread tmp.i check_asm.c
-	@echo 'return 0; }' >> check_asm.c
-	@rm -f tmp.[ci] check_asm_data.[cs]
-	$(HOSTCC) -o check_asm check_asm.c
-	./check_asm >> asm_offsets.h
-	@rm -f check_asm check_asm.c
-	@echo -e "#endif /* CONFIG_DEBUG_SPINLOCK */\n" >> asm_offsets.h
-	@echo -e "#endif /* CONFIG_SMP */\n" >> asm_offsets.h
-	@echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h
-	@if test -r $(HPATH)/asm/asm_offsets.h; then \
-	  if cmp -s asm_offsets.h $(HPATH)/asm/asm_offsets.h; then \
-	    echo $(HPATH)/asm/asm_offsets.h is unchanged; \
-	    rm -f asm_offsets.h; \
-	  else \
-	    mv -f asm_offsets.h $(HPATH)/asm/asm_offsets.h; \
-	  fi; \
-	else \
-	  mv -f asm_offsets.h $(HPATH)/asm/asm_offsets.h; \
-	fi
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
--- a/arch/sparc64/kernel/binfmt_aout32.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/binfmt_aout32.c	Sun Feb 10 19:58:06 2002
@@ -314,7 +314,7 @@
 
 	current->mm->start_stack =
 		(unsigned long) create_aout32_tables((char *)bprm->p, bprm);
-	if (!(current->thread.flags & SPARC_FLAG_32BIT)) {
+	if (!(test_thread_flag(TIF_32BIT))) {
 		unsigned long pgd_cache;
 
 		pgd_cache = ((unsigned long)current->mm->pgd[0])<<11UL;
@@ -323,7 +323,7 @@
 				     : /* no outputs */
 				     : "r" (pgd_cache),
 				       "r" (TSB_REG), "i" (ASI_DMMU));
-		current->thread.flags |= SPARC_FLAG_32BIT;
+		set_thread_flag(TIF_32BIT);
 	}
 	start_thread32(regs, ex.a_entry, current->mm->start_stack);
 	if (current->ptrace & PT_PTRACED)
diff -Nru a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
--- a/arch/sparc64/kernel/binfmt_elf32.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/binfmt_elf32.c	Sun Feb 10 19:58:05 2002
@@ -149,7 +149,7 @@
 #ifdef CONFIG_BINFMT_ELF32_MODULE
 #define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
 #endif
-#define ELF_FLAGS_INIT	current->thread.flags |= SPARC_FLAG_32BIT
+#define ELF_FLAGS_INIT	set_thread_flag(TIF_32BIT)
 
 MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra");
 MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek");
diff -Nru a/arch/sparc64/kernel/check_asm.sh b/arch/sparc64/kernel/check_asm.sh
--- a/arch/sparc64/kernel/check_asm.sh	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,20 +0,0 @@
-#!/bin/sh
-case $1 in
-  -printf)
-    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
-/g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0	0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0	0x%08x\\n", check_asm_data[i++]);/' >> $4
-    echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4
-  ;;
-  -data)
-    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
-/g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/	((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)),	sizeof(((struct '$2'_struct *)0)->\0),/' >> $4
-    echo "	sizeof(struct $2_struct)," >> $4
-  ;;
-  -ints)
-    sed -n -e '/check_asm_data:/,/\.size/p' <$2 | sed -e 's/check_asm_data://' -e 's/\.size.*//' -e 's/\.long[		]\([0-9]*\)/\1,/' | grep -v '\.ident' >>$3
-  ;;
-  *)
-    exit 1
-  ;;
-esac
-exit 0
diff -Nru a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
--- a/arch/sparc64/kernel/entry.S	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/kernel/entry.S	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.141 2001/12/05 23:56:32 davem Exp $
+/* $Id: entry.S,v 1.144 2002/02/09 19:49:30 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -151,12 +151,12 @@
 	add		%g0, %g0, %g0
 	ba,a,pt		%xcc, rtrap_clr_l6
 
-1:	ldub		[%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g5	! Load	Group
+1:	ldub		[%g6 + TI_FPSAVED], %g5					! Load	Group
 	wr		%g0, FPRS_FEF, %fprs					! LSU	Group+4bubbles
 	andcc		%g5, FPRS_FEF, %g0					! IEU1	Group
 	be,a,pt		%icc, 1f						! CTI
 	 clr		%g7							! IEU0
-	ldx		[%g6 + AOFF_task_thread + AOFF_thread_gsr], %g7		! Load	Group
+	ldx		[%g6 + TI_GSR], %g7					! Load	Group
 1:	andcc		%g5, FPRS_DL, %g0					! IEU1
 	bne,pn		%icc, 2f						! CTI
 	 fzero		%f0							! FPA
@@ -194,11 +194,11 @@
 	b,pt		%xcc, fpdis_exit2
 	 faddd		%f0, %f2, %f60
 1:	mov		SECONDARY_CONTEXT, %g3
-	add		%g6, AOFF_task_fpregs + 0x80, %g1
+	add		%g6, TI_FPREGS + 0x80, %g1
 	faddd		%f0, %f2, %f4
 	fmuld		%f0, %f2, %f6
 	ldxa		[%g3] ASI_DMMU, %g5
-	add		%g6, AOFF_task_fpregs + 0xc0, %g2
+	add		%g6, TI_FPREGS + 0xc0, %g2
 	stxa		%g0, [%g3] ASI_DMMU
 	membar		#Sync
 	faddd		%f0, %f2, %f8
@@ -223,10 +223,10 @@
 	mov		SECONDARY_CONTEXT, %g3
 	fzero		%f34
 	ldxa		[%g3] ASI_DMMU, %g5
-	add		%g6, AOFF_task_fpregs, %g1
+	add		%g6, TI_FPREGS, %g1
 	stxa		%g0, [%g3] ASI_DMMU
 	membar		#Sync
-	add		%g6, AOFF_task_fpregs + 0x40, %g2
+	add		%g6, TI_FPREGS + 0x40, %g2
 	faddd		%f32, %f34, %f36
 	fmuld		%f32, %f34, %f38
 	ldda		[%g1] ASI_BLK_S, %f0	! grrr, where is ASI_BLK_NUCLEUS 8-(
@@ -246,7 +246,7 @@
 	ba,pt		%xcc, fpdis_exit
 	 membar		#Sync
 3:	mov		SECONDARY_CONTEXT, %g3
-	add		%g6, AOFF_task_fpregs, %g1
+	add		%g6, TI_FPREGS, %g1
 	ldxa		[%g3] ASI_DMMU, %g5
 	mov		0x40, %g2
 	stxa		%g0, [%g3] ASI_DMMU
@@ -262,7 +262,7 @@
 	membar		#Sync
 fpdis_exit2:
 	wr		%g7, 0, %gsr
-	ldx		[%g6 + AOFF_task_thread + AOFF_thread_xfsr], %fsr
+	ldx		[%g6 + TI_XFSR], %fsr
 	rdpr		%tstate, %g3
 	or		%g3, %g4, %g3		! anal...
 	wrpr		%g3, %tstate
@@ -285,12 +285,12 @@
 	/* NOTE: Need to preserve %g7 until we fully commit
 	 *       to the fitos fixup.
 	 */
-	stx		%fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
+	stx		%fsr, [%g6 + TI_XFSR]
 	rdpr		%tstate, %g3
 	andcc		%g3, TSTATE_PRIV, %g0
 	bne,pn		%xcc, do_fptrap_after_fsr
 	 nop
-	ldx		[%g6 + AOFF_task_thread + AOFF_thread_xfsr], %g3
+	ldx		[%g6 + TI_XFSR], %g3
 	srlx		%g3, 14, %g1
 	and		%g1, 7, %g1
 	cmp		%g1, 2			! Unfinished FP-OP
@@ -310,7 +310,7 @@
 	cmp		%g1, %g2
 	bne,pn		%xcc, do_fptrap_after_fsr
 	 nop
-	std		%f62, [%g6 + AOFF_task_fpregs + (62 * 4)]
+	std		%f62, [%g6 + TI_FPREGS + (62 * 4)]
 	sethi		%hi(fitos_table_1), %g1
 	and		%g3, 0x1f, %g2
 	or		%g1, %lo(fitos_table_1),  %g1
@@ -396,22 +396,22 @@
 	fdtos		%f62, %f31
 
 fitos_emul_fini:
-	ldd		[%g6 + AOFF_task_fpregs + (62 * 4)], %f62
+	ldd		[%g6 + TI_FPREGS + (62 * 4)], %f62
 	done
 
 	.globl		do_fptrap
 	.align		32
 do_fptrap:
-	stx		%fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
+	stx		%fsr, [%g6 + TI_XFSR]
 do_fptrap_after_fsr:
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3
+	ldub		[%g6 + TI_FPSAVED], %g3
 	rd		%fprs, %g1
 	or		%g3, %g1, %g3
-	stb		%g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
+	stb		%g3, [%g6 + TI_FPSAVED]
 	rd		%gsr, %g3
-	stx		%g3, [%g6 + AOFF_task_thread + AOFF_thread_gsr]
+	stx		%g3, [%g6 + TI_GSR]
 	mov		SECONDARY_CONTEXT, %g3
-	add		%g6, AOFF_task_fpregs, %g2
+	add		%g6, TI_FPREGS, %g2
 	ldxa		[%g3] ASI_DMMU, %g5
 	stxa		%g0, [%g3] ASI_DMMU
 	membar		#Sync
@@ -713,8 +713,8 @@
 	call		sparc_floppy_irq
 	 add		%sp, STACK_BIAS + REGWIN_SZ, %o2
 
-	b,pt		%xcc, rtrap
-	 clr		%l6
+	b,pt		%xcc, rtrap_irq
+	 nop
 
 #endif /* CONFIG_BLK_DEV_FD */
 
@@ -883,7 +883,7 @@
 	mov	%l5, %o1
 	call	cee_log
 	 add	%sp, STACK_BIAS + REGWIN_SZ, %o2
-	ba,a,pt	%xcc, rtrap_clr_l6
+	ba,a,pt	%xcc, rtrap_irq
 
 	/* Capture I/D/E-cache state into per-cpu error scoreboard.
 	 *
@@ -1109,7 +1109,7 @@
 	mov		%l5, %o2
 	call		cheetah_fecc_handler
 	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-	ba,a,pt		%xcc, rtrap_clr_l6
+	ba,a,pt		%xcc, rtrap_irq
 
 	/* Our caller has disabled I-cache and performed membar Sync. */
 	.globl		cheetah_cee
@@ -1135,7 +1135,7 @@
 	mov		%l5, %o2
 	call		cheetah_cee_handler
 	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-	ba,a,pt		%xcc, rtrap_clr_l6
+	ba,a,pt		%xcc, rtrap_irq
 
 	/* Our caller has disabled I-cache+D-cache and performed membar Sync. */
 	.globl		cheetah_deferred_trap
@@ -1161,7 +1161,7 @@
 	mov		%l5, %o2
 	call		cheetah_deferred_handler
 	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-	ba,a,pt		%xcc, rtrap_clr_l6
+	ba,a,pt		%xcc, rtrap_irq
 
 	.globl		__do_privact
 __do_privact:
@@ -1384,8 +1384,8 @@
 		 add		%o7, 1f-.-4, %o7
 		nop
 		.align		32
-1:		ldx		[%curptr + AOFF_task_ptrace], %l5
-		andcc		%l5, 0x02, %g0
+1:		ldx		[%curptr + TI_FLAGS], %l5
+		andcc		%l5, _TIF_SYSCALL_TRACE, %g0
 		be,pt		%icc, rtrap
 		 clr		%l6
 		call		syscall_trace
@@ -1435,14 +1435,14 @@
 		/* Clear SPARC_FLAG_NEWCHILD, switch_to leaves thread.flags in
 		 * %o7 for us.  Check performance counter stuff too.
 		 */
-		andn		%o7, SPARC_FLAG_NEWCHILD, %l0
+		andn		%o7, _TIF_NEWCHILD, %l0
 		mov		%g5, %o0	/* 'prev' */
 		call		schedule_tail
-		 stb		%l0, [%g6 + AOFF_task_thread + AOFF_thread_flags]
-		andcc		%l0, SPARC_FLAG_PERFCTR, %g0
+		 stx		%l0, [%g6 + TI_FLAGS]
+		andcc		%l0, _TIF_PERFCTR, %g0
 		be,pt		%icc, 1f
 		 nop
-		ldx		[%g6 + AOFF_task_thread + AOFF_thread_pcr_reg], %o7
+		ldx		[%g6 + TI_PCR], %o7
 		wr		%g0, %o7, %pcr
 
 		/* Blackbird errata workaround.  See commentary in
@@ -1465,7 +1465,7 @@
 		wrpr		%g0, 0x0, %otherwin
 		wrpr		%g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate
 		ba,pt		%xcc, sys_exit
-		 stb		%g0, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
+		 stb		%g0, [%g6 + TI_WSAVED]
 
 linux_sparc_ni_syscall:
 	sethi		%hi(sys_ni_syscall), %l7
@@ -1510,11 +1510,11 @@
 	mov		%i4, %o4				! IEU1
 	lduw		[%l7 + %l4], %l7			! Load
 	srl		%i1, 0, %o1				! IEU0	Group
-	ldx		[%curptr + AOFF_task_ptrace], %l0	! Load
+	ldx		[%curptr + TI_FLAGS], %l0		! Load
 
 	mov		%i5, %o5				! IEU1
 	srl		%i2, 0, %o2				! IEU0	Group
-	andcc		%l0, 0x02, %g0				! IEU0	Group
+	andcc		%l0, _TIF_SYSCALL_TRACE, %g0		! IEU0	Group
 	bne,pn		%icc, linux_syscall_trace32		! CTI
 	 mov		%i0, %l5				! IEU1
 	call		%l7					! CTI	Group brk forced
@@ -1538,11 +1538,11 @@
 	mov		%i1, %o1				! IEU1
 	lduw		[%l7 + %l4], %l7			! Load
 4:	mov		%i2, %o2				! IEU0	Group
-	ldx		[%curptr + AOFF_task_ptrace], %l0	! Load
+	ldx		[%curptr + TI_FLAGS], %l0		! Load
 
 	mov		%i3, %o3				! IEU1
 	mov		%i4, %o4				! IEU0	Group
-	andcc		%l0, 0x02, %g0				! IEU1	Group+1 bubble
+	andcc		%l0, _TIF_SYSCALL_TRACE, %g0		! IEU1	Group+1 bubble
 	bne,pn		%icc, linux_syscall_trace		! CTI	Group
 	 mov		%i0, %l5				! IEU0
 2:	call		%l7					! CTI	Group brk forced
@@ -1565,7 +1565,7 @@
 	sllx		%g2, 32, %g2
 	bgeu,pn		%xcc, 1f
 
-	 andcc		%l0, 0x02, %l6	
+	 andcc		%l0, _TIF_SYSCALL_TRACE, %l6	
 	andn		%g3, %g2, %g3		/* System call success, clear Carry condition code. */
 	stx		%g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]	
 	bne,pn		%icc, linux_syscall_trace2
diff -Nru a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
--- a/arch/sparc64/kernel/etrap.S	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/etrap.S	Sun Feb 10 19:58:05 2002
@@ -1,10 +1,12 @@
-/* $Id: etrap.S,v 1.45 2001/09/07 21:04:40 kanoj Exp $
+/* $Id: etrap.S,v 1.46 2002/02/09 19:49:30 davem Exp $
  * etrap.S: Preparing for entry into the kernel on Sparc V9.
  *
  * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
  */
 
+#include <linux/config.h>
+
 #include <asm/asi.h>
 #include <asm/pstate.h>
 #include <asm/ptrace.h>
@@ -25,9 +27,17 @@
 		.text		
 		.align	64
 		.globl	etrap, etrap_irq, etraptl1
-
+#ifdef CONFIG_PREEMPT
+etrap_irq:	ldsw	[%g6 + TI_PRE_COUNT], %g1
+		add	%g1, 1, %g1
+		ba,pt	%xcc, etrap_irq2
+		 stw	%g1, [%g6 + TI_PRE_COUNT]
+#endif
 etrap:		rdpr	%pil, %g2						! Single 	Group
-etrap_irq:	rdpr	%tstate, %g1						! Single 	Group
+#ifndef CONFIG_PREEMPT
+etrap_irq:
+#endif
+etrap_irq2:	rdpr	%tstate, %g1						! Single 	Group
 		sllx	%g2, 20, %g3						! IEU0		Group
 		andcc	%g1, TSTATE_PRIV, %g0					! IEU1
 		or	%g1, %g3, %g1						! IEU0		Group
@@ -60,7 +70,7 @@
 		wrpr	%g0, 0, %canrestore					! Single	Group+4bubbles
 		sll	%g2, 3, %g2						! IEU0		Group
 		mov	1, %l5							! IEU1
-		stb	%l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth]	! Store
+		stb	%l5, [%l6 + TI_FPDEPTH]					! Store
 
 		wrpr	%g3, 0, %otherwin					! Single	Group+4bubbles
 		wrpr	%g2, 0, %wstate						! Single	Group+4bubbles
@@ -98,11 +108,11 @@
 		nop
 		nop
 
-3:		ldub	[%l6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5	! Load		Group
-		add	%l6, AOFF_task_thread + AOFF_thread_fpsaved + 1, %l4	! IEU0
+3:		ldub	[%l6 + TI_FPDEPTH], %l5					! Load		Group
+		add	%l6, TI_FPSAVED + 1, %l4				! IEU0
 		srl	%l5, 1, %l3						! IEU0		Group
 		add	%l5, 2, %l5						! IEU1
-		stb	%l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth]	! Store
+		stb	%l5, [%l6 + TI_FPDEPTH]					! Store
 		ba,pt	%xcc, 2b						! CTI
 		 stb	%g0, [%l4 + %l3]					! Store		Group
 		nop
diff -Nru a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
--- a/arch/sparc64/kernel/head.S	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/head.S	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.86 2001/12/05 01:02:16 davem Exp $
+/* $Id: head.S,v 1.87 2002/02/09 19:49:31 davem Exp $
  * head.S: Initial boot code for the Sparc64 port of Linux.
  *
  * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -10,7 +10,7 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/errno.h>
-#include <asm/asm_offsets.h>
+#include <asm/thread_info.h>
 #include <asm/asi.h>
 #include <asm/pstate.h>
 #include <asm/ptrace.h>
@@ -491,8 +491,8 @@
 	stw	%g2, [%g5 + %lo(tlb_type)]
 
 tlb_fixup_done:
-	sethi	%hi(init_task_union), %g6
-	or	%g6, %lo(init_task_union), %g6
+	sethi	%hi(init_thread_union), %g6
+	or	%g6, %lo(init_thread_union), %g6
 	mov	%sp, %l6
 	mov	%o4, %l7
 
diff -Nru a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c
--- a/arch/sparc64/kernel/init_task.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/init_task.c	Sun Feb 10 19:58:06 2002
@@ -12,17 +12,25 @@
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /* .text section in head.S is aligned at 2 page boundry and this gets linked
- * right after that so that the init_task_union is aligned properly as well.
+ * right after that so that the init_thread_union is aligned properly as well.
  * We really don't need this special alignment like the Intel does, but
  * I do it anyways for completeness.
  */
 __asm__ (".text");
-union task_union init_task_union = { INIT_TASK(init_task_union.task) };
+union thread_union init_thread_union = { INIT_THREAD_INFO(init_task) };
 
 /*
- * This is to make the init_task+stack of the right size for >8k pagesize.
- * The definition of task_union in sched.h makes it 16k wide.
+ * This is to make the init_thread+stack be the right size for >8k pagesize.
+ * The definition of thread_union in sched.h makes it 16k wide.
  */
 #if PAGE_SHIFT != 13
-char init_task_stack[THREAD_SIZE - INIT_TASK_SIZE] = { 0 };
+char init_task_stack[THREAD_SIZE - INIT_THREAD_SIZE] = { 0 };
 #endif
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+__asm__(".data");
+struct task_struct init_task = INIT_TASK(init_task);
diff -Nru a/arch/sparc64/kernel/itlb_base.S b/arch/sparc64/kernel/itlb_base.S
--- a/arch/sparc64/kernel/itlb_base.S	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/kernel/itlb_base.S	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: itlb_base.S,v 1.11 2001/08/17 04:55:09 kanoj Exp $
+/* $Id: itlb_base.S,v 1.12 2002/02/09 19:49:30 davem Exp $
  * itlb_base.S:	Front end to ITLB miss replacement strategy.
  *              This is included directly into the trap table.
  *
@@ -51,8 +51,8 @@
 	rdpr		%tpc, %g5			! And load faulting VA
 	mov		FAULT_CODE_ITLB, %g4		! It was read from ITLB
 sparc64_realfault_common:				! Called by TL0 dtlb_miss too
-	stb		%g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code]
-	stx		%g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address]
+	stb		%g4, [%g6 + TI_FAULT_CODE]
+	stx		%g5, [%g6 + TI_FAULT_ADDR]
 	ba,pt		%xcc, etrap			! Save state
 1:	 rd		%pc, %g7			! ...
 	nop
diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
--- a/arch/sparc64/kernel/pci_common.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/pci_common.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.28 2002/01/14 05:47:02 davem Exp $
+/* $Id: pci_common.c,v 1.29 2002/02/01 00:56:03 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -669,6 +669,20 @@
 	unsigned int prom_irq;
 	int prom_node = pcp->prom_node;
 	int err;
+
+	/* If this is an empty EBUS device, sometimes OBP fails to
+	 * give it a valid fully specified interrupts property.
+	 * The EBUS hooked up to SunHME on PCI I/O boards of
+	 * Ex000 systems is one such case.
+	 *
+	 * The interrupt is not important so just ignore it.
+	 */
+	if (pdev->vendor == PCI_VENDOR_ID_SUN &&
+	    pdev->device == PCI_DEVICE_ID_SUN_EBUS &&
+	    !prom_getchild(prom_node)) {
+		pdev->irq = 0;
+		return;
+	}
 
 	err = prom_getproperty(prom_node, "interrupts",
 			       (char *)&prom_irq, sizeof(prom_irq));
diff -Nru a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
--- a/arch/sparc64/kernel/pci_psycho.c	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/kernel/pci_psycho.c	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.32 2002/01/23 11:27:32 davem Exp $
+/* $Id: pci_psycho.c,v 1.33 2002/02/01 00:58:33 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -13,7 +13,6 @@
 #include <linux/slab.h>
 
 #include <asm/pbm.h>
-#include <asm/fhc.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/starfire.h>
@@ -1495,8 +1494,6 @@
 	} else {
 		pbm = &p->pbm_B;
 		pbm->pci_first_slot = 2;
-		if (central_bus != NULL)
-			pbm->pci_first_slot = 1;
 		pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B;
 		pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_B;
 	}
diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
--- a/arch/sparc64/kernel/process.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/process.c	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.129 2002/01/23 11:27:32 davem Exp $
+/*  $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -79,10 +79,13 @@
 #define unidle_me()		(cpu_data[smp_processor_id()].idle_volume = 0)
 int cpu_idle(void)
 {
+	set_thread_flag(TIF_POLLING_NRFLAG);
 	while(1) {
 		if (need_resched()) {
 			unidle_me();
+			clear_thread_flag(TIF_POLLING_NRFLAG);
 			schedule();
+			set_thread_flag(TIF_POLLING_NRFLAG);
 			check_pgt_cache();
 		}
 		idle_me_harder();
@@ -97,6 +100,18 @@
 
 #endif
 
+#ifdef CONFIG_PREEMPT
+void kpreempt_maybe(void)
+{
+	int cpu = smp_processor_id();
+
+	if (local_irq_count(cpu) == 0 &&
+	    local_bh_count(cpu) == 0)
+		preempt_schedule();
+	current_thread_info()->preempt_count--;
+}
+#endif
+
 extern char reboot_command [];
 
 #ifdef CONFIG_SUN_CONSOLE
@@ -176,7 +191,7 @@
 	struct reg_window r_w;
 	mm_segment_t old_fs;
 
-	if ((regs->tstate & TSTATE_PRIV) || !(current->thread.flags & SPARC_FLAG_32BIT)) {
+	if ((regs->tstate & TSTATE_PRIV) || !(test_thread_flag(TIF_32BIT))) {
 		__asm__ __volatile__ ("flushw");
 		rw = (struct reg_window *)(regs->u_regs[14] + STACK_BIAS);
 		if (!(regs->tstate & TSTATE_PRIV)) {
@@ -364,34 +379,29 @@
 	       regs->u_regs[15]);
 }
 
-void show_thread(struct thread_struct *thread)
+unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	int i;
-
-#if 0
-	printk("kregs:             0x%016lx\n", (unsigned long)thread->kregs);
-	show_regs(thread->kregs);
-#endif	
-	printk("ksp:               0x%016lx\n", thread->ksp);
-
-	if (thread->w_saved) {
-		for (i = 0; i < NSWINS; i++) {
-			if (!thread->rwbuf_stkptrs[i])
-				continue;
-			printk("reg_window[%d]:\n", i);
-			printk("stack ptr:         0x%016lx\n", thread->rwbuf_stkptrs[i]);
+	struct thread_info *ti = tsk->thread_info;
+	unsigned long ret = 0xdeadbeefUL;
+	
+	if (ti && ti->ksp) {
+		unsigned long *sp;
+		sp = (unsigned long *)(ti->ksp + STACK_BIAS);
+		if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL &&
+		    sp[14]) {
+			unsigned long *fp;
+			fp = (unsigned long *)(sp[14] + STACK_BIAS);
+			if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL)
+				ret = fp[15];
 		}
-		printk("w_saved:           0x%04x\n", thread->w_saved);
 	}
-
-	printk("flags:             0x%08x\n", thread->flags);
-	printk("current_ds:        0x%x\n", thread->current_ds.seg);
+	return ret;
 }
 
 /* Free current thread data structures etc.. */
 void exit_thread(void)
 {
-	struct thread_struct *t = &current->thread;
+	struct thread_info *t = current_thread_info();
 
 	if (t->utraps) {
 		if (t->utraps[0] < 2)
@@ -400,22 +410,20 @@
 			t->utraps[0]--;
 	}
 
-	/* Turn off performance counters if on. */
-	if (t->flags & SPARC_FLAG_PERFCTR) {
+	if (test_and_clear_thread_flag(TIF_PERFCTR)) {
 		t->user_cntd0 = t->user_cntd1 = NULL;
 		t->pcr_reg = 0;
-		t->flags &= ~(SPARC_FLAG_PERFCTR);
 		write_pcr(0);
 	}
 }
 
 void flush_thread(void)
 {
-	struct thread_struct *t = &current->thread;
+	struct thread_info *t = current_thread_info();
 
-	if (current->mm) {
-		if (t->flags & SPARC_FLAG_32BIT) {
-			struct mm_struct *mm = current->mm;
+	if (t->task->mm) {
+		if (test_thread_flag(TIF_32BIT)) {
+			struct mm_struct *mm = t->task->mm;
 			pgd_t *pgd0 = &mm->pgd[0];
 			unsigned long pgd_cache;
 
@@ -434,24 +442,23 @@
 					       "i" (ASI_DMMU));
 		}
 	}
-	t->w_saved = 0;
+	set_thread_wsaved(0);
 
 	/* Turn off performance counters if on. */
-	if (t->flags & SPARC_FLAG_PERFCTR) {
+	if (test_and_clear_thread_flag(TIF_PERFCTR)) {
 		t->user_cntd0 = t->user_cntd1 = NULL;
 		t->pcr_reg = 0;
-		t->flags &= ~(SPARC_FLAG_PERFCTR);
 		write_pcr(0);
 	}
 
 	/* Clear FPU register state. */
 	t->fpsaved[0] = 0;
 	
-	if (t->current_ds.seg != ASI_AIUS)
+	if (get_thread_current_ds() != ASI_AIUS)
 		set_fs(USER_DS);
 
 	/* Init new signal delivery disposition. */
-	t->flags &= ~SPARC_FLAG_NEWSIGNALS;
+	clear_thread_flag(TIF_NEWSIGNALS);
 }
 
 /* It's a bit more tricky when 64-bit tasks are involved... */
@@ -459,7 +466,7 @@
 {
 	unsigned long fp, distance, rval;
 
-	if (!(current->thread.flags & SPARC_FLAG_32BIT)) {
+	if (!(test_thread_flag(TIF_32BIT))) {
 		csp += STACK_BIAS;
 		psp += STACK_BIAS;
 		__get_user(fp, &(((struct reg_window *)psp)->ins[6]));
@@ -477,7 +484,7 @@
 	rval = (csp - distance);
 	if (copy_in_user(rval, psp, distance))
 		rval = 0;
-	else if (current->thread.flags & SPARC_FLAG_32BIT) {
+	else if (test_thread_flag(TIF_32BIT)) {
 		if (put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6])))
 			rval = 0;
 	} else {
@@ -493,7 +500,7 @@
 
 /* Standard stuff. */
 static inline void shift_window_buffer(int first_win, int last_win,
-				       struct thread_struct *t)
+				       struct thread_info *t)
 {
 	int i;
 
@@ -506,15 +513,15 @@
 
 void synchronize_user_stack(void)
 {
-	struct thread_struct *t = &current->thread;
+	struct thread_info *t = current_thread_info();
 	unsigned long window;
 
 	flush_user_windows();
-	if ((window = t->w_saved) != 0) {
+	if ((window = get_thread_wsaved()) != 0) {
 		int winsize = REGWIN_SZ;
 		int bias = 0;
 
-		if (t->flags & SPARC_FLAG_32BIT)
+		if (test_thread_flag(TIF_32BIT))
 			winsize = REGWIN32_SZ;
 		else
 			bias = STACK_BIAS;
@@ -525,8 +532,8 @@
 			struct reg_window *rwin = &t->reg_window[window];
 
 			if (!copy_to_user((char *)sp, rwin, winsize)) {
-				shift_window_buffer(window, t->w_saved - 1, t);
-				t->w_saved--;
+				shift_window_buffer(window, get_thread_wsaved() - 1, t);
+				set_thread_wsaved(get_thread_wsaved() - 1);
 			}
 		} while (window--);
 	}
@@ -534,18 +541,18 @@
 
 void fault_in_user_windows(void)
 {
-	struct thread_struct *t = &current->thread;
+	struct thread_info *t = current_thread_info();
 	unsigned long window;
 	int winsize = REGWIN_SZ;
 	int bias = 0;
 
-	if (t->flags & SPARC_FLAG_32BIT)
+	if (test_thread_flag(TIF_32BIT))
 		winsize = REGWIN32_SZ;
 	else
 		bias = STACK_BIAS;
 
 	flush_user_windows();
-	window = t->w_saved;
+	window = get_thread_wsaved();
 
 	if (window != 0) {
 		window -= 1;
@@ -557,11 +564,11 @@
 				goto barf;
 		} while (window--);
 	}
-	t->w_saved = 0;
+	set_thread_wsaved(0);
 	return;
 
 barf:
-	t->w_saved = window + 1;
+	set_thread_wsaved(window + 1);
 	do_exit(SIGILL);
 }
 
@@ -581,21 +588,23 @@
 		unsigned long unused,
 		struct task_struct *p, struct pt_regs *regs)
 {
-	struct thread_struct *t = &p->thread;
+	struct thread_info *t = p->thread_info;
 	char *child_trap_frame;
 
 #ifdef CONFIG_DEBUG_SPINLOCK
-	t->smp_lock_count = 0;
-	t->smp_lock_pc = 0;
+	p->thread.smp_lock_count = 0;
+	p->thread.smp_lock_pc = 0;
 #endif
 
 	/* Calculate offset to stack_frame & pt_regs */
-	child_trap_frame = ((char *)p) + (THREAD_SIZE - (TRACEREG_SZ+REGWIN_SZ));
+	child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+REGWIN_SZ));
 	memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ));
+
+	t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
+		_TIF_NEWCHILD |
+		(((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);
 	t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
-	t->flags |= SPARC_FLAG_NEWCHILD;
 	t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
-	t->cwp = (regs->tstate + 1) & TSTATE_CWP;
 	t->fpsaved[0] = 0;
 
 	if (regs->tstate & TSTATE_PRIV) {
@@ -604,25 +613,25 @@
 		 * disable performance counters in the child because the
 		 * address space and protection realm are changing.
 		 */
-		if (t->flags & SPARC_FLAG_PERFCTR) {
+		if (t->flags & _TIF_PERFCTR) {
 			t->user_cntd0 = t->user_cntd1 = NULL;
 			t->pcr_reg = 0;
-			t->flags &= ~(SPARC_FLAG_PERFCTR);
+			t->flags &= ~_TIF_PERFCTR;
 		}
-		t->kregs->u_regs[UREG_FP] = p->thread.ksp;
-		t->current_ds = KERNEL_DS;
+		t->kregs->u_regs[UREG_FP] = t->ksp;
+		t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT);
 		flush_register_windows();
 		memcpy((void *)(t->ksp + STACK_BIAS),
 		       (void *)(regs->u_regs[UREG_FP] + STACK_BIAS),
 		       sizeof(struct reg_window));
-		t->kregs->u_regs[UREG_G6] = (unsigned long) p;
+		t->kregs->u_regs[UREG_G6] = (unsigned long) t;
 	} else {
-		if (t->flags & SPARC_FLAG_32BIT) {
+		if (t->flags & _TIF_32BIT) {
 			sp &= 0x00000000ffffffffUL;
 			regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 		}
 		t->kregs->u_regs[UREG_FP] = sp;
-		t->current_ds = USER_DS;
+		t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT);
 		if (sp != regs->u_regs[UREG_FP]) {
 			unsigned long csp;
 
@@ -688,33 +697,10 @@
  */
 void dump_thread(struct pt_regs * regs, struct user * dump)
 {
-#if 1
 	/* Only should be used for SunOS and ancient a.out
-	 * SparcLinux binaries...  Fixme some day when bored.
-	 * But for now at least plug the security hole :-)
+	 * SparcLinux binaries...  Not worth implementing.
 	 */
 	memset(dump, 0, sizeof(struct user));
-#else
-	unsigned long first_stack_page;
-	dump->magic = SUNOS_CORE_MAGIC;
-	dump->len = sizeof(struct user);
-	dump->regs.psr = regs->psr;
-	dump->regs.pc = regs->pc;
-	dump->regs.npc = regs->npc;
-	dump->regs.y = regs->y;
-	/* fuck me plenty */
-	memcpy(&dump->regs.regs[0], &regs->u_regs[1], (sizeof(unsigned long) * 15));
-	dump->u_tsize = (((unsigned long) current->mm->end_code) -
-		((unsigned long) current->mm->start_code)) & ~(PAGE_SIZE - 1);
-	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1)));
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_dsize &= ~(PAGE_SIZE - 1);
-	first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
-	dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
-	memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
-	dump->fpu.fpstatus.fsr = current->thread.fsr;
-	dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
-#endif	
 }
 
 typedef struct {
@@ -735,10 +721,10 @@
  */
 int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 {
-	unsigned long *kfpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
-	unsigned long fprs = current->thread.fpsaved[0];
+	unsigned long *kfpregs = current_thread_info()->fpregs;
+	unsigned long fprs = current_thread_info()->fpsaved[0];
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs;
 
 		if (fprs & FPRS_DL)
@@ -752,7 +738,7 @@
 		memset(&fpregs32->pr_q[0], 0,
 		       (sizeof(unsigned int) * 64));
 		if (fprs & FPRS_FEF) {
-			fpregs32->pr_fsr = (unsigned int) current->thread.xfsr[0];
+			fpregs32->pr_fsr = (unsigned int) current_thread_info()->xfsr[0];
 			fpregs32->pr_en = 1;
 		} else {
 			fpregs32->pr_fsr = 0;
@@ -772,8 +758,8 @@
 			memset(&fpregs->pr_regs[16], 0,
 			       sizeof(unsigned int) * 32);
 		if(fprs & FPRS_FEF) {
-			fpregs->pr_fsr = current->thread.xfsr[0];
-			fpregs->pr_gsr = current->thread.gsr[0];
+			fpregs->pr_fsr = current_thread_info()->xfsr[0];
+			fpregs->pr_gsr = current_thread_info()->gsr[0];
 		} else {
 			fpregs->pr_fsr = fpregs->pr_gsr = 0;
 		}
@@ -806,8 +792,8 @@
 	putname(filename);
 	if (!error) {
 		fprs_write(0);
-		current->thread.xfsr[0] = 0;
-		current->thread.fpsaved[0] = 0;
+		current_thread_info()->xfsr[0] = 0;
+		current_thread_info()->fpsaved[0] = 0;
 		regs->tstate &= ~TSTATE_PEF;
 	}
 out:
diff -Nru a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
--- a/arch/sparc64/kernel/ptrace.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/ptrace.c	Sun Feb 10 19:58:06 2002
@@ -27,8 +27,6 @@
 #include <asm/visasm.h>
 #include <asm/spitfire.h>
 
-#define MAGIC_CONSTANT 0x80000000
-
 /* Returning from ptrace is a bit tricky because the syscall return
  * low level code assumes any value returned which is negative and
  * is a valid errno will mean setting the condition codes to indicate
@@ -53,7 +51,7 @@
 static inline void
 pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long *addr)
 {
-	if (current->thread.flags & SPARC_FLAG_32BIT) {
+	if (test_thread_flag(TIF_32BIT)) {
 		if (put_user(value, (unsigned int *)addr))
 			return pt_error_return(regs, EFAULT);
 	} else {
@@ -125,7 +123,7 @@
 	unsigned long addr2 = regs->u_regs[UREG_I4];
 	struct task_struct *child;
 
-	if (current->thread.flags & SPARC_FLAG_32BIT) {
+	if (test_thread_flag(TIF_32BIT)) {
 		addr &= 0xffffffffUL;
 		data &= 0xffffffffUL;
 		addr2 &= 0xffffffffUL;
@@ -201,7 +199,7 @@
 		goto out_tsk;
 	}
 
-	if (!(child->thread.flags & SPARC_FLAG_32BIT)	&&
+	if (!(test_thread_flag(TIF_32BIT))	&&
 	    ((request == PTRACE_READDATA64)		||
 	     (request == PTRACE_WRITEDATA64)		||
 	     (request == PTRACE_READTEXT64)		||
@@ -223,7 +221,7 @@
 		int res, copied;
 
 		res = -EIO;
-		if (current->thread.flags & SPARC_FLAG_32BIT) {
+		if (test_thread_flag(TIF_32BIT)) {
 			copied = access_process_vm(child, addr,
 						   &tmp32, sizeof(tmp32), 0);
 			tmp64 = (unsigned long) tmp32;
@@ -248,7 +246,7 @@
 		unsigned int tmp32;
 		int copied, res = -EIO;
 
-		if (current->thread.flags & SPARC_FLAG_32BIT) {
+		if (test_thread_flag(TIF_32BIT)) {
 			tmp32 = data;
 			copied = access_process_vm(child, addr,
 						   &tmp32, sizeof(tmp32), 1);
@@ -270,7 +268,7 @@
 
 	case PTRACE_GETREGS: {
 		struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
-		struct pt_regs *cregs = child->thread.kregs;
+		struct pt_regs *cregs = child->thread_info->kregs;
 		int rval;
 
 		if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
@@ -294,11 +292,11 @@
 
 	case PTRACE_GETREGS64: {
 		struct pt_regs *pregs = (struct pt_regs *) addr;
-		struct pt_regs *cregs = child->thread.kregs;
+		struct pt_regs *cregs = child->thread_info->kregs;
 		unsigned long tpc = cregs->tpc;
 		int rval;
 
-		if ((child->thread.flags & SPARC_FLAG_32BIT) != 0)
+		if ((child->thread_info->flags & _TIF_32BIT) != 0)
 			tpc &= 0xffffffff;
 		if (__put_user(cregs->tstate, (&pregs->tstate)) ||
 		    __put_user(tpc, (&pregs->tpc)) ||
@@ -321,7 +319,7 @@
 
 	case PTRACE_SETREGS: {
 		struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
-		struct pt_regs *cregs = child->thread.kregs;
+		struct pt_regs *cregs = child->thread_info->kregs;
 		unsigned int psr, pc, npc, y;
 		int i;
 
@@ -354,7 +352,7 @@
 
 	case PTRACE_SETREGS64: {
 		struct pt_regs *pregs = (struct pt_regs *) addr;
-		struct pt_regs *cregs = child->thread.kregs;
+		struct pt_regs *cregs = child->thread_info->kregs;
 		unsigned long tstate, tpc, tnpc, y;
 		int i;
 
@@ -368,7 +366,7 @@
 			pt_error_return(regs, EFAULT);
 			goto out_tsk;
 		}
-		if ((child->thread.flags & SPARC_FLAG_32BIT) != 0) {
+		if ((child->thread_info->flags & _TIF_32BIT) != 0) {
 			tpc &= 0xffffffff;
 			tnpc &= 0xffffffff;
 		}
@@ -402,11 +400,11 @@
 				unsigned int insn;
 			} fpq[16];
 		} *fps = (struct fps *) addr;
-		unsigned long *fpregs = (unsigned long *)(((char *)child) + AOFF_task_fpregs);
+		unsigned long *fpregs = child->thread_info->fpregs;
 
 		if (copy_to_user(&fps->regs[0], fpregs,
 				 (32 * sizeof(unsigned int))) ||
-		    __put_user(child->thread.xfsr[0], (&fps->fsr)) ||
+		    __put_user(child->thread_info->xfsr[0], (&fps->fsr)) ||
 		    __put_user(0, (&fps->fpqd)) ||
 		    __put_user(0, (&fps->flags)) ||
 		    __put_user(0, (&fps->extra)) ||
@@ -423,11 +421,11 @@
 			unsigned int regs[64];
 			unsigned long fsr;
 		} *fps = (struct fps *) addr;
-		unsigned long *fpregs = (unsigned long *)(((char *)child) + AOFF_task_fpregs);
+		unsigned long *fpregs = child->thread_info->fpregs;
 
 		if (copy_to_user(&fps->regs[0], fpregs,
 				 (64 * sizeof(unsigned int))) ||
-		    __put_user(child->thread.xfsr[0], (&fps->fsr))) {
+		    __put_user(child->thread_info->xfsr[0], (&fps->fsr))) {
 			pt_error_return(regs, EFAULT);
 			goto out_tsk;
 		}
@@ -447,7 +445,7 @@
 				unsigned int insn;
 			} fpq[16];
 		} *fps = (struct fps *) addr;
-		unsigned long *fpregs = (unsigned long *)(((char *)child) + AOFF_task_fpregs);
+		unsigned long *fpregs = child->thread_info->fpregs;
 		unsigned fsr;
 
 		if (copy_from_user(fpregs, &fps->regs[0],
@@ -456,11 +454,11 @@
 			pt_error_return(regs, EFAULT);
 			goto out_tsk;
 		}
-		child->thread.xfsr[0] &= 0xffffffff00000000UL;
-		child->thread.xfsr[0] |= fsr;
-		if (!(child->thread.fpsaved[0] & FPRS_FEF))
-			child->thread.gsr[0] = 0;
-		child->thread.fpsaved[0] |= (FPRS_FEF | FPRS_DL);
+		child->thread_info->xfsr[0] &= 0xffffffff00000000UL;
+		child->thread_info->xfsr[0] |= fsr;
+		if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
+			child->thread_info->gsr[0] = 0;
+		child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
 		pt_succ_return(regs, 0);
 		goto out_tsk;
 	}
@@ -470,17 +468,17 @@
 			unsigned int regs[64];
 			unsigned long fsr;
 		} *fps = (struct fps *) addr;
-		unsigned long *fpregs = (unsigned long *)(((char *)child) + AOFF_task_fpregs);
+		unsigned long *fpregs = child->thread_info->fpregs;
 
 		if (copy_from_user(fpregs, &fps->regs[0],
 				   (64 * sizeof(unsigned int))) ||
-		    __get_user(child->thread.xfsr[0], (&fps->fsr))) {
+		    __get_user(child->thread_info->xfsr[0], (&fps->fsr))) {
 			pt_error_return(regs, EFAULT);
 			goto out_tsk;
 		}
-		if (!(child->thread.fpsaved[0] & FPRS_FEF))
-			child->thread.gsr[0] = 0;
-		child->thread.fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
+		if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
+			child->thread_info->gsr[0] = 0;
+		child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
 		pt_succ_return(regs, 0);
 		goto out_tsk;
 	}
@@ -523,7 +521,7 @@
 		if (addr != 1) {
 			unsigned long pc_mask = ~0UL;
 
-			if ((child->thread.flags & SPARC_FLAG_32BIT) != 0)
+			if ((child->thread_info->flags & _TIF_32BIT) != 0)
 				pc_mask = 0xffffffff;
 
 			if (addr & 3) {
@@ -531,24 +529,27 @@
 				goto out_tsk;
 			}
 #ifdef DEBUG_PTRACE
-			printk ("Original: %016lx %016lx\n", child->thread.kregs->tpc, child->thread.kregs->tnpc);
+			printk ("Original: %016lx %016lx\n",
+				child->thread_info->kregs->tpc,
+				child->thread_info->kregs->tnpc);
 			printk ("Continuing with %016lx %016lx\n", addr, addr+4);
 #endif
-			child->thread.kregs->tpc = (addr & pc_mask);
-			child->thread.kregs->tnpc = ((addr + 4) & pc_mask);
+			child->thread_info->kregs->tpc = (addr & pc_mask);
+			child->thread_info->kregs->tnpc = ((addr + 4) & pc_mask);
 		}
 
-		if (request == PTRACE_SYSCALL)
-			child->ptrace |= PT_TRACESYS;
-		else
-			child->ptrace &= ~PT_TRACESYS;
+		if (request == PTRACE_SYSCALL) {
+			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		} else {
+			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		}
 
 		child->exit_code = data;
 #ifdef DEBUG_PTRACE
 		printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
 			child->pid, child->exit_code,
-			child->thread.kregs->tpc,
-			child->thread.kregs->tnpc);
+			child->thread_info->kregs->tpc,
+			child->thread_info->kregs->tnpc);
 		       
 #endif
 		wake_up_process(child);
@@ -611,7 +612,7 @@
 	}
 out_tsk:
 	if (child)
-		free_task_struct(child);
+		put_task_struct(child);
 out:
 	unlock_kernel();
 }
@@ -621,12 +622,12 @@
 #ifdef DEBUG_PTRACE
 	printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
 #endif
-	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
-	    != (PT_PTRACED|PT_TRACESYS))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+	if (!(current->ptrace & PT_PTRACED))
 		return;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
-	current->thread.flags ^= MAGIC_CONSTANT;
 	notify_parent(current, SIGCHLD);
 	schedule();
 	/*
diff -Nru a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
--- a/arch/sparc64/kernel/rtrap.S	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/rtrap.S	Sun Feb 10 19:58:06 2002
@@ -1,10 +1,12 @@
-/* $Id: rtrap.S,v 1.59 2002/01/11 08:45:38 davem Exp $
+/* $Id: rtrap.S,v 1.61 2002/02/09 19:49:31 davem Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
+
 #include <asm/asi.h>
 #include <asm/pstate.h>
 #include <asm/ptrace.h>
@@ -20,8 +22,8 @@
 
 		/* Register %l6 keeps track of whether we are returning
 		 * from a system call or not.  It is cleared if we call
-		 * do_signal, and it must not be otherwise modified until
-		 * we fully commit to returning to userspace.
+		 * do_notify_resume, and it must not be otherwise modified
+		 * until we fully commit to returning to userspace.
 		 */
 
 		.text
@@ -42,22 +44,26 @@
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		/* Redo sched+sig checks */
-#error		ldx			[%g6 + AOFF_task_need_resched], %l0
-		brz,pt			%l0, 1f
+		ldx			[%g6 + TI_FLAGS], %l0
+		andcc			%l0, _TIF_NEED_RESCHED, %g0
+
+		be,pt			%xcc, 1f
 		 nop
 		call			schedule
-
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-#error1:		lduw			[%g6 + AOFF_task_sigpending], %l0
-		brz,pt			%l0, __handle_user_windows_continue
+		ldx			[%g6 + TI_FLAGS], %l0
+
+1:		andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+		be,pt			%xcc, __handle_user_windows_continue
 		 nop
 		clr			%o0
 		mov			%l5, %o2
 		mov			%l6, %o3
-
 		add			%sp, STACK_BIAS + REGWIN_SZ, %o1
-		call			do_signal
+		mov			%l0, %o4
+
+		call			do_notify_resume
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		clr			%l6
@@ -67,37 +73,41 @@
 		ldx			[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 		sethi			%hi(0xf << 20), %l4
 		and			%l1, %l4, %l4
-
 		ba,pt			%xcc, __handle_user_windows_continue
+
 		 andn			%l1, %l4, %l1
 __handle_perfctrs:
 		call			update_perfctrs
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-		ldub			[%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2
+		ldub			[%g6 + TI_WSAVED], %o2
 		brz,pt			%o2, 1f
 		 nop
-
 		/* Redo userwin+sched+sig checks */
 		call			fault_in_user_windows
+
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-#error 1:		ldx			[%g6 + AOFF_task_need_resched], %l0
-		brz,pt			%l0, 1f
+		ldx			[%g6 + TI_FLAGS], %l0
+		andcc			%l0, _TIF_NEED_RESCHED, %g0
+		be,pt			%xcc, 1f
+
 		 nop
 		call			schedule
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
-
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-#error 1:		lduw			[%g6 + AOFF_task_sigpending], %l0
-		brz,pt			%l0, __handle_perfctrs_continue
+		ldx			[%g6 + TI_FLAGS], %l0
+1:		andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+
+		be,pt			%xcc, __handle_perfctrs_continue
 		 sethi			%hi(TSTATE_PEF), %o0
 		clr			%o0
 		mov			%l5, %o2
 		mov			%l6, %o3
 		add			%sp, STACK_BIAS + REGWIN_SZ, %o1
+		mov			%l0, %o4
+		call			do_notify_resume
 
-		call			do_signal
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		clr			%l6
@@ -108,8 +118,8 @@
 		sethi			%hi(0xf << 20), %l4
 		and			%l1, %l4, %l4
 		andn			%l1, %l4, %l1
-
 		ba,pt			%xcc, __handle_perfctrs_continue
+
 		 sethi			%hi(TSTATE_PEF), %o0
 __handle_userfpu:
 		rd			%fprs, %l5
@@ -124,7 +134,8 @@
 		mov			%l5, %o2
 		mov			%l6, %o3
 		add			%sp, STACK_BIAS + REGWIN_SZ, %o1
-		call			do_signal
+		mov			%l0, %o4
+		call			do_notify_resume
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		clr			%l6
@@ -139,9 +150,15 @@
 		 andn			%l1, %l4, %l1
 
 		.align			64
-		.globl			rtrap_clr_l6, rtrap, irqsz_patchme
+		.globl			rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme
+rtrap_irq:
+#ifdef CONFIG_PREEMPT
+		ldsw			[%g6 + TI_PRE_COUNT], %l0
+		sub			%l0, 1, %l0
+		stw			%l0, [%g6 + TI_PRE_COUNT]
+#endif
 rtrap_clr_l6:	clr			%l6
-rtrap:		lduw			[%g6 + AOFF_task_cpu], %l0
+rtrap:		ldub			[%g6 + TI_CPU], %l0
 		sethi			%hi(irq_stat), %l2	! &softirq_active
 		or			%l2, %lo(irq_stat), %l2	! &softirq_active
 irqsz_patchme:	sllx			%l0, 0, %l0
@@ -173,26 +190,33 @@
 		 */
 to_user:	wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 __handle_preemption_continue:
-#error		ldx			[%g6 + AOFF_task_need_resched], %l0
-		brnz,pn			%l0, __handle_preemption
-#error		 lduw			[%g6 + AOFF_task_sigpending], %l0
-		brnz,pn			%l0, __handle_signal
-		 nop
+		ldx			[%g6 + TI_FLAGS], %l0
+		sethi			%hi(_TIF_USER_WORK_MASK), %o0
+		or			%o0, %lo(_TIF_USER_WORK_MASK), %o0
+		andcc			%l0, %o0, %g0
+		sethi			%hi(TSTATE_PEF), %o0
+		be,pt			%xcc, user_nowork
+		 andcc			%l1, %o0, %g0
+		andcc			%l0, _TIF_NEED_RESCHED, %g0
+		bne,pn			%xcc, __handle_preemption
+		 andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+		bne,pn			%xcc, __handle_signal
 __handle_signal_continue:
-		ldub			[%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2
+		 ldub			[%g6 + TI_WSAVED], %o2
 		brnz,pn			%o2, __handle_user_windows
 		 nop
 __handle_user_windows_continue:
-		ldub			[%g6 + AOFF_task_thread + AOFF_thread_flags], %l5
-		andcc			%l5, SPARC_FLAG_PERFCTR, %g0
+		ldx			[%g6 + TI_FLAGS], %l5
+		andcc			%l5, _TIF_PERFCTR, %g0
 		sethi			%hi(TSTATE_PEF), %o0
 		bne,pn			%xcc, __handle_perfctrs
 __handle_perfctrs_continue:
 		 andcc			%l1, %o0, %g0
 
 		/* This fpdepth clear is neccessary for non-syscall rtraps only */
+user_nowork:
 		bne,pn			%xcc, __handle_userfpu
-		 stb			%g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
+		 stb			%g0, [%g6 + TI_FPDEPTH]
 __handle_userfpu_continue:
 
 rt_continue:	ldx			[%sp + PTREGS_OFF + PT_V9_G1], %g1
@@ -245,14 +269,25 @@
 
 kern_rtt:	restore
 		retry
-to_kernel:	ldub			[%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5
+to_kernel:
+#ifdef CONFIG_PREEMPT
+		ldsw			[%g6 + TI_PRE_COUNT], %l5
+		brnz			%l5, kern_fpucheck
+		 add			%l5, 1, %l6
+		stw			%l6, [%g6 + TI_PRE_COUNT]
+		call			kpreempt_maybe
+		 wrpr			%g0, RTRAP_PSTATE, %pstate
+		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate		
+		stw			%l5, [%g6 + TI_PRE_COUNT]
+#endif
+kern_fpucheck:	ldub			[%g6 + TI_FPDEPTH], %l5
 		brz,pt			%l5, rt_continue
 		 srl			%l5, 1, %o0
-		add			%g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6
+		add			%g6, TI_FPSAVED, %l6
 		ldub			[%l6 + %o0], %l2
 		sub			%l5, 2, %l5
 
-		add			%g6, AOFF_task_thread + AOFF_thread_gsr, %o1
+		add			%g6, TI_GSR, %o1
 		andcc			%l2, (FPRS_FEF|FPRS_DU), %g0
 		be,pt			%icc, 2f
 		 and			%l2, FPRS_DL, %l6
@@ -263,12 +298,12 @@
 
 		wr			%g5, FPRS_FEF, %fprs
 		ldx			[%o1 + %o5], %g5
-		add			%g6, AOFF_task_thread + AOFF_thread_xfsr, %o1
+		add			%g6, TI_XFSR, %o1
 		membar			#StoreLoad | #LoadLoad
 		sll			%o0, 8, %o2
-		add			%g6, AOFF_task_fpregs, %o3
+		add			%g6, TI_FPREGS, %o3
 		brz,pn			%l6, 1f
-		 add			%g6, AOFF_task_fpregs+0x40, %o4
+		 add			%g6, TI_FPREGS+0x40, %o4
 
 		ldda			[%o3 + %o2] ASI_BLK_P, %f0
 		ldda			[%o4 + %o2] ASI_BLK_P, %f16
@@ -281,20 +316,20 @@
 
 1:		membar			#Sync
 		ldx			[%o1 + %o5], %fsr
-2:		stb			%l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
+2:		stb			%l5, [%g6 + TI_FPDEPTH]
 		ba,pt			%xcc, rt_continue
 		 nop
 5:		wr			%g0, FPRS_FEF, %fprs
 		membar			#StoreLoad | #LoadLoad
 		sll			%o0, 8, %o2
 
-		add			%g6, AOFF_task_fpregs+0x80, %o3
-		add			%g6, AOFF_task_fpregs+0xc0, %o4
+		add			%g6, TI_FPREGS+0x80, %o3
+		add			%g6, TI_FPREGS+0xc0, %o4
 		ldda			[%o3 + %o2] ASI_BLK_P, %f32
 		ldda			[%o4 + %o2] ASI_BLK_P, %f48
 		membar			#Sync
 		wr			%g0, FPRS_DU, %fprs
 		ba,pt			%xcc, rt_continue
-		 stb			%l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
+		 stb			%l5, [%g6 + TI_FPDEPTH]
 
 #undef PTREGS_OFF
diff -Nru a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
--- a/arch/sparc64/kernel/setup.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/setup.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.71 2001/11/13 00:49:28 davem Exp $
+/*  $Id: setup.c,v 1.72 2002/02/09 19:49:30 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -536,7 +536,7 @@
 	rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);	
 #endif
 
-	init_task.thread.kregs = &fake_swapper_regs;
+	init_task.thread_info->kregs = &fake_swapper_regs;
 
 #ifdef CONFIG_IP_PNP
 	if (!ic_set_manually) {
diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
--- a/arch/sparc64/kernel/signal.c	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/kernel/signal.c	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.57 2001/12/11 04:55:51 davem Exp $
+/*  $Id: signal.c,v 1.60 2002/02/09 19:49:31 davem Exp $
  *  arch/sparc64/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -32,8 +32,8 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-			 unsigned long orig_o0, int ret_from_syscall);
+static int do_signal(sigset_t *oldset, struct pt_regs * regs,
+		     unsigned long orig_o0, int ret_from_syscall);
 
 /* This turned off for production... */
 /* #define DEBUG_SIGNALS 1 */
@@ -76,7 +76,6 @@
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 {
 	struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
-	struct thread_struct *tp = &current->thread;
 	mc_gregset_t *grp;
 	unsigned long pc, npc, tstate;
 	unsigned long fp, i7;
@@ -84,16 +83,16 @@
 	int err;
 
 	flush_user_windows();
-	if(tp->w_saved						||
-	   (((unsigned long)ucp) & (sizeof(unsigned long)-1))	||
-	   (!__access_ok((unsigned long)ucp, sizeof(*ucp))))
+	if (get_thread_wsaved()					||
+	    (((unsigned long)ucp) & (sizeof(unsigned long)-1))	||
+	    (!__access_ok((unsigned long)ucp, sizeof(*ucp))))
 		goto do_sigsegv;
 	grp  = &ucp->uc_mcontext.mc_gregs;
 	err  = __get_user(pc, &((*grp)[MC_PC]));
 	err |= __get_user(npc, &((*grp)[MC_NPC]));
-	if(err || ((pc | npc) & 3))
+	if (err || ((pc | npc) & 3))
 		goto do_sigsegv;
-	if(regs->u_regs[UREG_I1]) {
+	if (regs->u_regs[UREG_I1]) {
 		sigset_t set;
 
 		if (_NSIG_WORDS == 1) {
@@ -109,7 +108,7 @@
 		recalc_sigpending(current);
 		spin_unlock_irq(&current->sigmask_lock);
 	}
-	if ((tp->flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		pc &= 0xffffffff;
 		npc &= 0xffffffff;
 	}
@@ -143,8 +142,8 @@
 	      (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
 
 	err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
-	if(fenab) {
-		unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
+	if (fenab) {
+		unsigned long *fpregs = current_thread_info()->fpregs;
 		unsigned long fprs;
 		
 		fprs_write(0);
@@ -157,9 +156,9 @@
 			err |= copy_from_user(fpregs+16,
 			 ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,
 			 (sizeof(unsigned int) * 32));
-		err |= __get_user(current->thread.xfsr[0],
+		err |= __get_user(current_thread_info()->xfsr[0],
 				  &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
-		err |= __get_user(current->thread.gsr[0],
+		err |= __get_user(current_thread_info()->gsr[0],
 				  &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
 		regs->tstate &= ~TSTATE_PEF;
 	}
@@ -174,7 +173,6 @@
 asmlinkage void sparc64_get_context(struct pt_regs *regs)
 {
 	struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
-	struct thread_struct *tp = &current->thread;
 	mc_gregset_t *grp;
 	mcontext_t *mcp;
 	unsigned long fp, i7;
@@ -182,20 +180,20 @@
 	int err;
 
 	synchronize_user_stack();
-	if(tp->w_saved || clear_user(ucp, sizeof(*ucp)))
+	if (get_thread_wsaved() || clear_user(ucp, sizeof(*ucp)))
 		goto do_sigsegv;
 
 #if 1
 	fenab = 0; /* IMO get_context is like any other system call, thus modifies FPU state -jj */
 #else
-	fenab = (current->thread.fpsaved[0] & FPRS_FEF);
+	fenab = (current_thread_info()->fpsaved[0] & FPRS_FEF);
 #endif
 		
 	mcp = &ucp->uc_mcontext;
 	grp = &mcp->mc_gregs;
 
 	/* Skip over the trap instruction, first. */
-	if ((tp->flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc   = (regs->tnpc & 0xffffffff);
 		regs->tnpc  = (regs->tnpc + 4) & 0xffffffff;
 	} else {
@@ -238,11 +236,11 @@
 	err |= __put_user(i7, &(mcp->mc_i7));
 
 	err |= __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab));
-	if(fenab) {
-		unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
+	if (fenab) {
+		unsigned long *fpregs = current_thread_info()->fpregs;
 		unsigned long fprs;
 		
-		fprs = current->thread.fpsaved[0];
+		fprs = current_thread_info()->fpsaved[0];
 		if (fprs & FPRS_DL)
 			err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
 					    (sizeof(unsigned int) * 32));
@@ -250,8 +248,8 @@
 			err |= copy_to_user(
                           ((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16,
 			  (sizeof(unsigned int) * 32));
-		err |= __put_user(current->thread.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));
-		err |= __put_user(current->thread.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));
+		err |= __put_user(current_thread_info()->xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));
+		err |= __put_user(current_thread_info()->gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));
 		err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs));
 	}
 	if (err)
@@ -284,7 +282,7 @@
 	sigset_t saveset;
 
 #ifdef CONFIG_SPARC32_COMPAT
-	if (current->thread.flags & SPARC_FLAG_32BIT) {
+	if (test_thread_flag(TIF_32BIT)) {
 		extern asmlinkage void _sigpause32_common(old_sigset_t32,
 							  struct pt_regs *);
 		_sigpause32_common(set, regs);
@@ -298,7 +296,7 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc = (regs->tnpc & 0xffffffff);
 		regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
 	} else {
@@ -358,7 +356,7 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc = (regs->tnpc & 0xffffffff);
 		regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
 	} else {
@@ -388,7 +386,7 @@
 static inline int
 restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-	unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
+	unsigned long *fpregs = current_thread_info()->fpregs;
 	unsigned long fprs;
 	int err;
 
@@ -401,9 +399,9 @@
 	if (fprs & FPRS_DU)
 		err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
 		       	       (sizeof(unsigned int) * 32));
-	err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr);
-	err |= __get_user(current->thread.gsr[0], &fpu->si_gsr);
-	current->thread.fpsaved[0] |= fprs;
+	err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
+	err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
+	current_thread_info()->fpsaved[0] |= fprs;
 	return err;
 }
 
@@ -426,7 +424,7 @@
 
 	err = get_user(tpc, &sf->regs.tpc);
 	err |= __get_user(tnpc, &sf->regs.tnpc);
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		tpc &= 0xffffffff;
 		tnpc &= 0xffffffff;
 	}
@@ -483,15 +481,15 @@
 	unsigned long fprs;
 	int err = 0;
 	
-	fprs = current->thread.fpsaved[0];
+	fprs = current_thread_info()->fpsaved[0];
 	if (fprs & FPRS_DL)
 		err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
 				    (sizeof(unsigned int) * 32));
 	if (fprs & FPRS_DU)
 		err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
 				    (sizeof(unsigned int) * 32));
-	err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr);
-	err |= __put_user(current->thread.gsr[0], &fpu->si_gsr);
+	err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
+	err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
 	err |= __put_user(fprs, &fpu->si_fprs);
 
 	return err;
@@ -524,7 +522,7 @@
 	save_and_clear_fpu();
 	
 	sigframe_size = RT_ALIGNEDSZ;
-	if (!(current->thread.fpsaved[0] & FPRS_FEF))
+	if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
 		sigframe_size -= sizeof(__siginfo_fpu_t);
 
 	sf = (struct rt_signal_frame *)get_sigframe(ka, regs, sigframe_size);
@@ -532,7 +530,7 @@
 	if (invalid_frame_pointer (sf, sigframe_size))
 		goto sigill;
 
-	if (current->thread.w_saved != 0) {
+	if (get_thread_wsaved() != 0) {
 #ifdef DEBUG_SIGNALS
 		printk ("%s[%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
@@ -543,7 +541,7 @@
 	/* 2. Save the current process state */
 	err = copy_to_user(&sf->regs, regs, sizeof (*regs));
 
-	if (current->thread.fpsaved[0] & FPRS_FEF) {
+	if (current_thread_info()->fpsaved[0] & FPRS_FEF) {
 		err |= save_fpu_state(regs, &sf->fpu_state);
 		err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
@@ -578,7 +576,7 @@
 	/* 5. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
 	regs->tnpc = (regs->tpc + 4);
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -597,9 +595,9 @@
 				 sigset_t *oldset, struct pt_regs *regs)
 {
 	setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
-	if(ka->sa.sa_flags & SA_ONESHOT)
+	if (ka->sa.sa_flags & SA_ONESHOT)
 		ka->sa.sa_handler = SIG_DFL;
-	if(!(ka->sa.sa_flags & SA_NOMASK)) {
+	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sigmask_lock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,signr);
@@ -611,14 +609,14 @@
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
 				     struct sigaction *sa)
 {
-	switch(regs->u_regs[UREG_I0]) {
+	switch (regs->u_regs[UREG_I0]) {
 		case ERESTARTNOHAND:
 		no_system_call_restart:
 			regs->u_regs[UREG_I0] = EINTR;
 			regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
 			break;
 		case ERESTARTSYS:
-			if(!(sa->sa_flags & SA_RESTART))
+			if (!(sa->sa_flags & SA_RESTART))
 				goto no_system_call_restart;
 		/* fallthrough */
 		case ERESTARTNOINTR:
@@ -688,8 +686,8 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-			 unsigned long orig_i0, int restart_syscall)
+static int do_signal(sigset_t *oldset, struct pt_regs * regs,
+		     unsigned long orig_i0, int restart_syscall)
 {
 	unsigned long signr;
 	siginfo_t info;
@@ -699,9 +697,9 @@
 		oldset = &current->blocked;
 
 #ifdef CONFIG_SPARC32_COMPAT
-	if (current->thread.flags & SPARC_FLAG_32BIT) {
-		extern asmlinkage int do_signal32(sigset_t *, struct pt_regs *,
-						  unsigned long, int);
+	if (test_thread_flag(TIF_32BIT)) {
+		extern int do_signal32(sigset_t *, struct pt_regs *,
+				       unsigned long, int);
 		return do_signal32(oldset, regs, orig_i0, restart_syscall);
 	}
 #endif	
@@ -741,8 +739,8 @@
 		
 		ka = &current->sig->action[signr-1];
 		
-		if(ka->sa.sa_handler == SIG_IGN) {
-			if(signr != SIGCHLD)
+		if (ka->sa.sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
 				continue;
 
                         /* sys_wait4() grabs the master kernel lock, so
@@ -750,16 +748,16 @@
                          * threaded and would not be that difficult to
                          * do anyways.
                          */
-                        while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+                        while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
                                 ;
 			continue;
 		}
-		if(ka->sa.sa_handler == SIG_DFL) {
+		if (ka->sa.sa_handler == SIG_DFL) {
 			unsigned long exit_code = signr;
 			
-			if(current->pid == 1)
+			if (current->pid == 1)
 				continue;
-			switch(signr) {
+			switch (signr) {
 			case SIGCONT: case SIGCHLD: case SIGWINCH:
 				continue;
 
@@ -772,8 +770,8 @@
 					continue;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if(!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
-				     SA_NOCLDSTOP))
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
+				      SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
@@ -792,8 +790,8 @@
 					struct reg_window *rw = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
 					unsigned long ins[8];
                                                 
-					while(rw &&
-					      !(((unsigned long) rw) & 0x3)) {
+					while (rw &&
+					       !(((unsigned long) rw) & 0x3)) {
 					        copy_from_user(ins, &rw->ins[0], sizeof(ins));
 						printk("Caller[%016lx](%016lx,%016lx,%016lx,%016lx,%016lx,%016lx)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
 						rw = (struct reg_window *)(unsigned long)(ins[6] + STACK_BIAS);
@@ -807,26 +805,31 @@
 #endif
 				/* fall through */
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOT REACHED */
 			}
 		}
-		if(restart_syscall)
+		if (restart_syscall)
 			syscall_restart(orig_i0, regs, &ka->sa);
 		handle_signal(signr, ka, &info, oldset, regs);
 		return 1;
 	}
-	if(restart_syscall &&
-	   (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
-	    regs->u_regs[UREG_I0] == ERESTARTSYS ||
-	    regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
+	if (restart_syscall &&
+	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
+	     regs->u_regs[UREG_I0] == ERESTARTSYS ||
+	     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
 		/* replay the system call when we are done */
 		regs->u_regs[UREG_I0] = orig_i0;
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
 	}
 	return 0;
+}
+
+void do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
+		      unsigned long orig_i0, int restart_syscall,
+		      unsigned long thread_info_flags)
+{
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(oldset, regs, orig_i0, restart_syscall);
 }
diff -Nru a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
--- a/arch/sparc64/kernel/signal32.c	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/kernel/signal32.c	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.71 2001/12/11 04:55:51 davem Exp $
+/*  $Id: signal32.c,v 1.74 2002/02/09 19:49:30 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -30,8 +30,8 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs,
-			 unsigned long orig_o0, int ret_from_syscall);
+int do_signal32(sigset_t *oldset, struct pt_regs *regs,
+		unsigned long orig_o0, int ret_from_syscall);
 
 /* This turned off for production... */
 /* #define DEBUG_SIGNALS 1 */
@@ -156,7 +156,7 @@
 	
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -211,7 +211,7 @@
 	
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -237,7 +237,7 @@
 
 static inline int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-	unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
+	unsigned long *fpregs = current_thread_info()->fpregs;
 	unsigned long fprs;
 	int err;
 	
@@ -248,9 +248,9 @@
 		err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32));
 	if (fprs & FPRS_DU)
 		err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32));
-	err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr);
-	err |= __get_user(current->thread.gsr[0], &fpu->si_gsr);
-	current->thread.fpsaved[0] |= fprs;
+	err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
+	err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
+	current_thread_info()->fpsaved[0] |= fprs;
 	return err;
 }
 
@@ -277,7 +277,7 @@
 	if ((pc | npc) & 3)
 		goto segv;
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		pc &= 0xffffffff;
 		npc &= 0xffffffff;
 	}
@@ -335,20 +335,20 @@
 	int err;
 
 	synchronize_user_stack();
-	if (current->thread.flags & SPARC_FLAG_NEWSIGNALS)
+	if (test_thread_flag(TIF_NEWSIGNALS))
 		return do_new_sigreturn32(regs);
 
 	scptr = (struct sigcontext32 *)
 		(regs->u_regs[UREG_I0] & 0x00000000ffffffffUL);
 	/* Check sanity of the user arg. */
-	if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
-	   (((unsigned long) scptr) & 3))
+	if (verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
+	    (((unsigned long) scptr) & 3))
 		goto segv;
 
 	err = __get_user(pc, &scptr->sigc_pc);
 	err |= __get_user(npc, &scptr->sigc_npc);
 
-	if((pc | npc) & 3)
+	if ((pc | npc) & 3)
 		goto segv; /* Nice try. */
 
 	err |= __get_user(seta[0], &scptr->sigc_mask);
@@ -368,7 +368,7 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		pc &= 0xffffffff;
 		npc &= 0xffffffff;
 	}
@@ -415,7 +415,7 @@
 	if ((pc | npc) & 3)
 		goto segv;
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		pc &= 0xffffffff;
 		npc &= 0xffffffff;
 	}
@@ -510,7 +510,7 @@
 #endif	
 	unsigned psr;
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		pc &= 0xffffffff;
 		npc &= 0xffffffff;
 	}
@@ -555,20 +555,20 @@
 	err |= __put_user(pc, &sc->sigc_pc);
 	err |= __put_user(npc, &sc->sigc_npc);
 	psr = tstate_to_psr (regs->tstate);
-	if(current->thread.fpsaved[0] & FPRS_FEF)
+	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
 	err |= __put_user(psr, &sc->sigc_psr);
 	err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
 	err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
-	err |= __put_user(current->thread.w_saved, &sc->sigc_oswins);
+	err |= __put_user(get_thread_wsaved(), &sc->sigc_oswins);
 #if 0
 /* w_saved is not currently used... */
-	if(current->thread.w_saved)
-		for(window = 0; window < current->thread.w_saved; window++) {
+	if (get_thread_wsaved())
+		for (window = 0; window < get_thread_wsaved(); window++) {
 			sc->sigc_spbuf[window] =
-				(char *)current->thread.rwbuf_stkptrs[window];
+				(char *) current_thread_info()->rwbuf_stkptrs[window];
 			err |= copy_to_user(&sc->sigc_wbuf[window],
-					    &current->thread.reg_window[window],
+					    &current_thread_info()->reg_window[window],
 					    sizeof(struct reg_window));
 		}
 	else
@@ -577,7 +577,7 @@
 				    (u32 *)(regs->u_regs[UREG_FP]),
 				    sizeof(struct reg_window32));
 		       
-	current->thread.w_saved = 0; /* So process is allowed to execute. */
+	set_thread_wsaved(0); /* So process is allowed to execute. */
 	err |= __put_user(signr, &sframep->sig_num);
 	sig_address = NULL;
 	sig_code = 0;
@@ -641,7 +641,7 @@
 	regs->u_regs[UREG_FP] = (unsigned long) sframep;
 	regs->tpc = (unsigned long) sa->sa_handler;
 	regs->tnpc = (regs->tpc + 4);
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -654,19 +654,19 @@
 
 static inline int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-	unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
+	unsigned long *fpregs = current_thread_info()->fpregs;
 	unsigned long fprs;
 	int err = 0;
 	
-	fprs = current->thread.fpsaved[0];
+	fprs = current_thread_info()->fpsaved[0];
 	if (fprs & FPRS_DL)
 		err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
 				    (sizeof(unsigned int) * 32));
 	if (fprs & FPRS_DU)
 		err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
 				    (sizeof(unsigned int) * 32));
-	err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr);
-	err |= __put_user(current->thread.gsr[0], &fpu->si_gsr);
+	err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
+	err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
 	err |= __put_user(fprs, &fpu->si_fprs);
 
 	return err;
@@ -686,7 +686,7 @@
 	save_and_clear_fpu();
 	
 	sigframe_size = NF_ALIGNEDSZ;
-	if (!(current->thread.fpsaved[0] & FPRS_FEF))
+	if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
 		sigframe_size -= sizeof(__siginfo_fpu_t);
 
 	sf = (struct new_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size);
@@ -699,7 +699,7 @@
 		goto sigill;
 	}
 
-	if (current->thread.w_saved != 0) {
+	if (get_thread_wsaved() != 0) {
 #ifdef DEBUG_SIGNALS
 		printk ("%s[%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
@@ -708,7 +708,7 @@
 	}
 
 	/* 2. Save the current process state */
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -716,7 +716,7 @@
 	err |= __put_user(regs->tnpc, &sf->info.si_regs.npc);
 	err |= __put_user(regs->y, &sf->info.si_regs.y);
 	psr = tstate_to_psr (regs->tstate);
-	if(current->thread.fpsaved[0] & FPRS_FEF)
+	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
 	err |= __put_user(psr, &sf->info.si_regs.psr);
 	for (i = 0; i < 16; i++)
@@ -762,7 +762,7 @@
 	/* 4. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
 	regs->tnpc = (regs->tpc + 4);
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -781,10 +781,10 @@
 	
 		err  = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/
 		err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
-		if(err)
+		if (err)
 			goto sigsegv;
 
-		if(pte_present(*ptep)) {
+		if (pte_present(*ptep)) {
 			unsigned long page = (unsigned long) page_address(pte_page(*ptep));
 
 			__asm__ __volatile__(
@@ -857,14 +857,14 @@
 		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
 	
 	/* Store registers */
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
 	err |= __put_user(regs->tpc, &((*gr) [SVR4_PC]));
 	err |= __put_user(regs->tnpc, &((*gr) [SVR4_NPC]));
 	psr = tstate_to_psr (regs->tstate);
-	if(current->thread.fpsaved[0] & FPRS_FEF)
+	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
 	err |= __put_user(psr, &((*gr) [SVR4_PSR]));
 	err |= __put_user(regs->y, &((*gr) [SVR4_Y]));
@@ -886,7 +886,7 @@
 	err |= __put_user((u32)(long)gw, &mc->gwin);
 	    
 	/* 2. Number of windows to restore at setcontext (): */
-	err |= __put_user(current->thread.w_saved, &gw->count);
+	err |= __put_user(get_thread_wsaved(), &gw->count);
 
 	/* 3. Save each valid window
 	 *    Currently, it makes a copy of the windows from the kernel copy.
@@ -900,18 +900,18 @@
 	 *    to flush the user windows.
 	 */
 #if 0	 
-	for(window = 0; window < current->thread.w_saved; window++) {
-		err |= __put_user((int *) &(gw->win [window]),
-				  (int **)gw->winptr +window );
-		err |= copy_to_user(&gw->win [window],
-				    &current->thread.reg_window [window],
+	for (window = 0; window < get_thread_wsaved(); window++) {
+		err |= __put_user((int *) &(gw->win[window]),
+				  (int **) gw->winptr + window);
+		err |= copy_to_user(&gw->win[window],
+				    &current_thread_info()->reg_window[window],
 				    sizeof (svr4_rwindow_t));
-		err |= __put_user(0, (int *)gw->winptr + window);
+		err |= __put_user(0, (int *) gw->winptr + window);
 	}
 #endif	
 
 	/* 4. We just pay attention to the gw->count field on setcontext */
-	current->thread.w_saved = 0; /* So process is allowed to execute. */
+	set_thread_wsaved(0); /* So process is allowed to execute. */
 
 	/* Setup the signal information.  Solaris expects a bunch of
 	 * information to be passed to the signal handler, we don't provide
@@ -925,7 +925,7 @@
 	regs->u_regs[UREG_FP] = (unsigned long) sfp;
 	regs->tpc = (unsigned long) sa->sa_handler;
 	regs->tnpc = (regs->tpc + 4);
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -966,8 +966,10 @@
 	synchronize_user_stack();
 	save_and_clear_fpu();
 	
-	if (current->thread.w_saved){
-		printk ("Uh oh, w_saved is not zero (%d)\n", (int) current->thread.w_saved);
+	if (get_thread_wsaved()) {
+#ifdef DEBUG_SIGNALS
+		printk ("Uh oh, w_saved is not zero (%d)\n", (int) get_thread_wsaved());
+#endif
 		do_exit (SIGSEGV);
 	}
 	err = clear_user(uc, sizeof (*uc));
@@ -986,7 +988,7 @@
 		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
 
 	/* Store registers */
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -996,7 +998,7 @@
 	err |= __put_user(0, &uc->mcontext.greg [SVR4_PSR]);
 #else
 	i = tstate_to_psr(regs->tstate) & ~PSR_EF;		   
-	if (current->thread.fpsaved[0] & FPRS_FEF)
+	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
 		i |= PSR_EF;
 	err |= __put_user(i, &uc->mcontext.greg [SVR4_PSR]);
 #endif
@@ -1023,7 +1025,6 @@
 /* Set the context for a svr4 application, this is Solaris way to sigreturn */
 asmlinkage int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs)
 {
-	struct thread_struct *tp = &current->thread;
 	svr4_gregset_t  *gr;
 	u32 pc, npc, psr;
 	sigset_t set;
@@ -1036,8 +1037,10 @@
 	 */
 	flush_user_windows();
 	
-	if (tp->w_saved){
-		printk ("Uh oh, w_saved is: 0x%x\n", tp->w_saved);
+	if (get_thread_wsaved()) {
+#ifdef DEBUG_SIGNALS	
+		printk ("Uh oh, w_saved is: 0x%x\n", get_thread_wsaved());
+#endif
 		goto sigsegv;
 	}
 	if (((unsigned long) c) & 3){
@@ -1045,7 +1048,7 @@
 		goto sigsegv;
 	}
 
-	if(!__access_ok((unsigned long)c, sizeof(*c))) {
+	if (!__access_ok((unsigned long)c, sizeof(*c))) {
 		/* Miguel, add nice debugging msg _here_. ;-) */
 		goto sigsegv;
 	}
@@ -1054,7 +1057,7 @@
 	gr = &c->mcontext.greg;
 	err = __get_user(pc, &((*gr)[SVR4_PC]));
 	err |= __get_user(npc, &((*gr)[SVR4_NPC]));
-	if((pc | npc) & 3) {
+	if ((pc | npc) & 3) {
 #ifdef DEBUG_SIGNALS	
 	        printk ("setcontext, PC or nPC were bogus\n");
 #endif
@@ -1087,7 +1090,7 @@
 	spin_unlock_irq(&current->sigmask_lock);
 	regs->tpc = pc;
 	regs->tnpc = npc | 1;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -1096,7 +1099,7 @@
 	regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
 	regs->tstate |= psr_to_tstate_icc(psr);
 #if 0	
-	if(psr & PSR_EF)
+	if (psr & PSR_EF)
 		regs->tstate |= TSTATE_PEF;
 #endif
 	/* Restore g[1..7] and o[0..7] registers */
@@ -1104,7 +1107,7 @@
 		err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
 	for (i = 0; i < 8; i++)
 		err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
-	if(err)
+	if (err)
 		goto sigsegv;
 
 	return -EINTR;
@@ -1127,7 +1130,7 @@
 	save_and_clear_fpu();
 	
 	sigframe_size = RT_ALIGNEDSZ;
-	if (!(current->thread.fpsaved[0] & FPRS_FEF))
+	if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
 		sigframe_size -= sizeof(__siginfo_fpu_t);
 
 	sf = (struct rt_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size);
@@ -1140,7 +1143,7 @@
 		goto sigill;
 	}
 
-	if (current->thread.w_saved != 0) {
+	if (get_thread_wsaved() != 0) {
 #ifdef DEBUG_SIGNALS
 		printk ("%s[%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
@@ -1149,7 +1152,7 @@
 	}
 
 	/* 2. Save the current process state */
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -1157,7 +1160,7 @@
 	err |= __put_user(regs->tnpc, &sf->regs.npc);
 	err |= __put_user(regs->y, &sf->regs.y);
 	psr = tstate_to_psr (regs->tstate);
-	if(current->thread.fpsaved[0] & FPRS_FEF)
+	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
 	err |= __put_user(psr, &sf->regs.psr);
 	for (i = 0; i < 16; i++)
@@ -1208,7 +1211,7 @@
 	/* 4. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
 	regs->tnpc = (regs->tpc + 4);
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -1233,7 +1236,7 @@
 		if (err)
 			goto sigsegv;
 
-		if(pte_present(*ptep)) {
+		if (pte_present(*ptep)) {
 			unsigned long page = (unsigned long) page_address(pte_page(*ptep));
 
 			__asm__ __volatile__(
@@ -1256,19 +1259,19 @@
 				   sigset_t *oldset, struct pt_regs *regs,
 				   int svr4_signal)
 {
-	if(svr4_signal)
+	if (svr4_signal)
 		setup_svr4_frame32(&ka->sa, regs->tpc, regs->tnpc, regs, signr, oldset);
 	else {
 		if (ka->sa.sa_flags & SA_SIGINFO)
 			setup_rt_frame32(ka, regs, signr, oldset, info);
-		else if (current->thread.flags & SPARC_FLAG_NEWSIGNALS)
+		else if (test_thread_flag(TIF_NEWSIGNALS))
 			new_setup_frame32(ka, regs, signr, oldset);
 		else
 			setup_frame32(&ka->sa, regs, signr, oldset, info);
 	}
-	if(ka->sa.sa_flags & SA_ONESHOT)
+	if (ka->sa.sa_flags & SA_ONESHOT)
 		ka->sa.sa_handler = SIG_DFL;
-	if(!(ka->sa.sa_flags & SA_NOMASK)) {
+	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sigmask_lock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,signr);
@@ -1280,14 +1283,14 @@
 static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
 				     struct sigaction *sa)
 {
-	switch(regs->u_regs[UREG_I0]) {
+	switch (regs->u_regs[UREG_I0]) {
 		case ERESTARTNOHAND:
 		no_system_call_restart:
 			regs->u_regs[UREG_I0] = EINTR;
 			regs->tstate |= TSTATE_ICARRY;
 			break;
 		case ERESTARTSYS:
-			if(!(sa->sa_flags & SA_RESTART))
+			if (!(sa->sa_flags & SA_RESTART))
 				goto no_system_call_restart;
 		/* fallthrough */
 		case ERESTARTNOINTR:
@@ -1357,8 +1360,8 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs,
-			   unsigned long orig_i0, int restart_syscall)
+int do_signal32(sigset_t *oldset, struct pt_regs * regs,
+		unsigned long orig_i0, int restart_syscall)
 {
 	unsigned long signr;
 	struct k_sigaction *ka;
@@ -1402,8 +1405,8 @@
 		
 		ka = &current->sig->action[signr-1];
 		
-		if(ka->sa.sa_handler == SIG_IGN) {
-			if(signr != SIGCHLD)
+		if (ka->sa.sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
 				continue;
 
 			/* sys_wait4() grabs the master kernel lock, so
@@ -1411,16 +1414,16 @@
 			 * threaded and would not be that difficult to
 			 * do anyways.
 			 */
-			while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
 				;
 			continue;
 		}
-		if(ka->sa.sa_handler == SIG_DFL) {
+		if (ka->sa.sa_handler == SIG_DFL) {
 			unsigned long exit_code = signr;
 			
-			if(current->pid == 1)
+			if (current->pid == 1)
 				continue;
-			switch(signr) {
+			switch (signr) {
 			case SIGCONT: case SIGCHLD: case SIGWINCH:
 				continue;
 
@@ -1433,8 +1436,8 @@
 					continue;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if(!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
-				     SA_NOCLDSTOP))
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
+				      SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
@@ -1457,15 +1460,15 @@
 					extern void sparc_ultra_dump_dtlb(void);
 					sparc_ultra_dump_dtlb();
 					sparc_ultra_dump_itlb();
-				} while(0);
+				} while (0);
 #endif
 #ifdef DEBUG_SIGNALS_TRACE
 				{
 					struct reg_window32 *rw = (struct reg_window32 *)(regs->u_regs[UREG_FP] & 0xffffffff);
 					unsigned int ins[8];
 
-					while(rw &&
-					      !(((unsigned long) rw) & 0x3)) {
+					while (rw &&
+					       !(((unsigned long) rw) & 0x3)) {
 						copy_from_user(ins, &rw->ins[0], sizeof(ins));
 						printk("Caller[%08x](%08x,%08x,%08x,%08x,%08x,%08x)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
 						rw = (struct reg_window32 *)(unsigned long)ins[6];
@@ -1479,22 +1482,19 @@
 #endif
 				/* fall through */
 			default:
-				sigaddset(&current->pending.signal, signr);
-				recalc_sigpending(current);
-				current->flags |= PF_SIGNALED;
-				do_exit(exit_code);
+				sig_exit(signr, exit_code, &info);
 				/* NOT REACHED */
 			}
 		}
-		if(restart_syscall)
+		if (restart_syscall)
 			syscall_restart32(orig_i0, regs, &ka->sa);
 		handle_signal32(signr, ka, &info, oldset, regs, svr4_signal);
 		return 1;
 	}
-	if(restart_syscall &&
-	   (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
-	    regs->u_regs[UREG_I0] == ERESTARTSYS ||
-	    regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
+	if (restart_syscall &&
+	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
+	     regs->u_regs[UREG_I0] == ERESTARTSYS ||
+	     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
 		/* replay the system call when we are done */
 		regs->u_regs[UREG_I0] = orig_i0;
 		regs->tpc -= 4;
diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
--- a/arch/sparc64/kernel/smp.c	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/kernel/smp.c	Sun Feb 10 19:58:03 2002
@@ -212,18 +212,14 @@
 	/* Clear this or we will die instantly when we
 	 * schedule back to this idler...
 	 */
-	current->thread.flags &= ~(SPARC_FLAG_NEWCHILD);
+	clear_thread_flag(TIF_NEWCHILD);
 
 	/* Attach to the address space of init_task. */
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
 
-	init_idle();
-
 	while (!smp_threads_ready)
 		membar("#LoadLoad");
-
-	idle_startup_done();
 }
 
 void cpu_panic(void)
@@ -240,7 +236,9 @@
  * 32-bits (I think) so to be safe we have it read the pointer
  * contained here so we work on >4GB machines. -DaveM
  */
-static struct task_struct *cpu_new_task = NULL;
+static struct thread_info *cpu_new_thread = NULL;
+
+static void smp_tune_scheduling(void);
 
 void __init smp_boot_cpus(void)
 {
@@ -250,18 +248,20 @@
 	__sti();
 	smp_store_cpu_info(boot_cpu_id);
 
-	if (linux_num_cpus == 1)
+	if (linux_num_cpus == 1) {
+		smp_tune_scheduling();
 		return;
+	}
 
 	for (i = 0; i < NR_CPUS; i++) {
 		if (i == boot_cpu_id)
 			continue;
 
 		if ((cpucount + 1) == max_cpus)
-			break;
+			goto ignorecpu;
 		if (cpu_present_map & (1UL << i)) {
 			unsigned long entry = (unsigned long)(&sparc64_cpu_startup);
-			unsigned long cookie = (unsigned long)(&cpu_new_task);
+			unsigned long cookie = (unsigned long)(&cpu_new_thread);
 			struct task_struct *p;
 			int timeout;
 			int no;
@@ -272,7 +272,7 @@
 
 			p = init_task.prev_task;
 
-			p->cpu = i;
+			init_idle(p, i);
 
 			unhash_process(p);
 
@@ -280,7 +280,7 @@
 			for (no = 0; no < linux_num_cpus; no++)
 				if (linux_cpus[no].mid == i)
 					break;
-			cpu_new_task = p;
+			cpu_new_thread = p->thread_info;
 			prom_startcpu(linux_cpus[no].prom_node,
 				      entry, cookie);
 			for (timeout = 0; timeout < 5000000; timeout++) {
@@ -300,13 +300,15 @@
 			}
 		}
 		if (!callin_flag) {
+ignorecpu:
 			cpu_present_map &= ~(1UL << i);
 			__cpu_number_map[i] = -1;
 		}
 	}
-	cpu_new_task = NULL;
+	cpu_new_thread = NULL;
 	if (cpucount == 0) {
-		printk("Error: only one processor found.\n");
+		if (max_cpus != 1)
+			printk("Error: only one processor found.\n");
 		cpu_present_map = (1UL << smp_processor_id());
 	} else {
 		unsigned long bogosum = 0;
@@ -322,6 +324,12 @@
 		smp_activated = 1;
 		smp_num_cpus = cpucount + 1;
 	}
+
+	/* We want to run this with all the other cpus spinning
+	 * in the kernel.
+	 */
+	smp_tune_scheduling();
+
 	smp_processors_ready = 1;
 	membar("#StoreStore | #StoreLoad");
 }
@@ -894,7 +902,7 @@
 	if (smp_processors_ready && (cpu_present_map & mask) != 0) {
 		u64 data0 = (((u64)&xcall_migrate_task) & 0xffffffff);
 
-		spin_lock(&migration_lock);
+		_raw_spin_lock(&migration_lock);
 		new_task = p;
 
 		if (tlb_type == spitfire)
@@ -915,7 +923,7 @@
 	clear_softint(1 << irq);
 
 	p = new_task;
-	spin_unlock(&migration_lock);
+	_raw_spin_unlock(&migration_lock);
 	sched_task_migrated(p);
 }
 
@@ -1170,27 +1178,94 @@
 	prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
 }
 
-static inline unsigned long find_flush_base(unsigned long size)
+cycles_t cacheflush_time;
+unsigned long cache_decay_ticks;
+
+extern unsigned long cheetah_tune_scheduling(void);
+extern unsigned long timer_ticks_per_usec_quotient;
+
+static void __init smp_tune_scheduling(void)
 {
-	struct page *p = mem_map;
-	unsigned long found, base;
+	unsigned long orig_flush_base, flush_base, flags, *p;
+	unsigned int ecache_size, order;
+	cycles_t tick1, tick2, raw;
 
-	size = PAGE_ALIGN(size);
-	found = size;
-	base = (unsigned long) page_address(p);
-	while (found != 0) {
-		/* Failure. */
-		if (p >= (mem_map + max_mapnr))
-			return 0UL;
-		if (PageReserved(p)) {
-			found = size;
-			base = (unsigned long) page_address(p);
-		} else {
-			found -= PAGE_SIZE;
-		}
-		p++;
+	/* Approximate heuristic for SMP scheduling.  It is an
+	 * estimation of the time it takes to flush the L2 cache
+	 * on the local processor.
+	 *
+	 * The ia32 chooses to use the L1 cache flush time instead,
+	 * and I consider this complete nonsense.  The Ultra can service
+	 * a miss to the L1 with a hit to the L2 in 7 or 8 cycles, and
+	 * L2 misses are what create extra bus traffic (ie. the "cost"
+	 * of moving a process from one cpu to another).
+	 */
+	printk("SMP: Calibrating ecache flush... ");
+	if (tlb_type == cheetah) {
+		cacheflush_time = cheetah_tune_scheduling();
+		goto report;
+	}
+
+	ecache_size = prom_getintdefault(linux_cpus[0].prom_node,
+					 "ecache-size", (512 * 1024));
+	if (ecache_size > (4 * 1024 * 1024))
+		ecache_size = (4 * 1024 * 1024);
+	orig_flush_base = flush_base =
+		__get_free_pages(GFP_KERNEL, order = get_order(ecache_size));
+
+	if (flush_base != 0UL) {
+		__save_and_cli(flags);
+
+		/* Scan twice the size once just to get the TLB entries
+		 * loaded and make sure the second scan measures pure misses.
+		 */
+		for (p = (unsigned long *)flush_base;
+		     ((unsigned long)p) < (flush_base + (ecache_size<<1));
+		     p += (64 / sizeof(unsigned long)))
+			*((volatile unsigned long *)p);
+
+		/* Now the real measurement. */
+		__asm__ __volatile__("
+		b,pt	%%xcc, 1f
+		 rd	%%tick, %0
+
+		.align	64
+1:		ldx	[%2 + 0x000], %%g1
+		ldx	[%2 + 0x040], %%g2
+		ldx	[%2 + 0x080], %%g3
+		ldx	[%2 + 0x0c0], %%g5
+		add	%2, 0x100, %2
+		cmp	%2, %4
+		bne,pt	%%xcc, 1b
+		 nop
+	
+		rd	%%tick, %1"
+		: "=&r" (tick1), "=&r" (tick2), "=&r" (flush_base)
+		: "2" (flush_base), "r" (flush_base + ecache_size)
+		: "g1", "g2", "g3", "g5");
+
+		__restore_flags(flags);
+
+		raw = (tick2 - tick1);
+
+		/* Dampen it a little, considering two processes
+		 * sharing the cache and fitting.
+		 */
+		cacheflush_time = (raw - (raw >> 2));
+
+		free_pages(orig_flush_base, order);
+	} else {
+		cacheflush_time = ((ecache_size << 2) +
+				   (ecache_size << 1));
 	}
-	return base;
+report:
+	/* Convert cpu ticks to jiffie ticks. */
+	cache_decay_ticks = ((long)cacheflush_time * timer_ticks_per_usec_quotient);
+	cache_decay_ticks >>= 32UL;
+	cache_decay_ticks = (cache_decay_ticks * HZ) / 1000;
+
+	printk("Using heuristic of %ld cycles, %ld ticks.\n",
+	       cacheflush_time, cache_decay_ticks);
 }
 
 /* /proc/profile writes can call this, don't __init it please. */
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.120 2001/12/21 04:56:15 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.121 2002/02/09 19:49:31 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -80,6 +80,11 @@
 extern void tl0_solaris(void);
 extern void sys_sigsuspend(void);
 extern int sys_getppid(void);
+extern int sys_getpid(void);
+extern int sys_geteuid(void);
+extern int sys_getuid(void);
+extern int sys_getegid(void);
+extern int sys_getgid(void);
 extern int svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
 extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
 extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
@@ -307,6 +312,11 @@
 EXPORT_SYMBOL(tl0_solaris);
 EXPORT_SYMBOL(sys_sigsuspend);
 EXPORT_SYMBOL(sys_getppid);
+EXPORT_SYMBOL(sys_getpid);
+EXPORT_SYMBOL(sys_geteuid);
+EXPORT_SYMBOL(sys_getuid);
+EXPORT_SYMBOL(sys_getegid);
+EXPORT_SYMBOL(sys_getgid);
 EXPORT_SYMBOL(svr4_getcontext);
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(prom_cpu_nodes);
diff -Nru a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
--- a/arch/sparc64/kernel/sys_sparc.c	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/kernel/sys_sparc.c	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.56 2001/12/21 04:56:15 davem Exp $
+/* $Id: sys_sparc.c,v 1.57 2002/02/09 19:49:30 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -59,7 +59,7 @@
 		return addr;
 	}
 
-	if (current->thread.flags & SPARC_FLAG_32BIT)
+	if (test_thread_flag(TIF_32BIT))
 		task_size = 0xf0000000UL;
 	if (len > task_size || len > -PAGE_OFFSET)
 		return -ENOMEM;
@@ -140,7 +140,7 @@
 asmlinkage unsigned long sparc_brk(unsigned long brk)
 {
 	/* People could try to be nasty and use ta 0x6d in 32bit programs */
-	if ((current->thread.flags & SPARC_FLAG_32BIT) &&
+	if (test_thread_flag(TIF_32BIT) &&
 	    brk >= 0xf0000000UL)
 		return current->mm->brk;
 
@@ -289,7 +289,7 @@
 	len = PAGE_ALIGN(len);
 	retval = -EINVAL;
 
-	if (current->thread.flags & SPARC_FLAG_32BIT) {
+	if (test_thread_flag(TIF_32BIT)) {
 		if (len > 0xf0000000UL ||
 		    ((flags & MAP_FIXED) && addr > 0xf0000000UL - len))
 			goto out_putf;
@@ -334,7 +334,7 @@
 {
 	struct vm_area_struct *vma;
 	unsigned long ret = -EINVAL;
-	if (current->thread.flags & SPARC_FLAG_32BIT)
+	if (test_thread_flag(TIF_32BIT))
 		goto out;
 	if (old_len > -PAGE_OFFSET || new_len > -PAGE_OFFSET)
 		goto out;
@@ -401,7 +401,7 @@
 {
 	siginfo_t info;
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -454,7 +454,7 @@
 
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -474,7 +474,7 @@
 
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -494,11 +494,11 @@
 		return -EINVAL;
 	if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) {
 		if (old_p) {
-			if (!current->thread.utraps) {
+			if (!current_thread_info()->utraps) {
 				if (put_user(NULL, old_p))
 					return -EFAULT;
 			} else {
-				if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p))
+				if (put_user((utrap_handler_t)(current_thread_info()->utraps[type]), old_p))
 					return -EFAULT;
 			}
 		}
@@ -508,39 +508,39 @@
 		}
 		return 0;
 	}
-	if (!current->thread.utraps) {
-		current->thread.utraps =
+	if (!current_thread_info()->utraps) {
+		current_thread_info()->utraps =
 			kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL);
-		if (!current->thread.utraps) return -ENOMEM;
-		current->thread.utraps[0] = 1;
-		memset(current->thread.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long));
+		if (!current_thread_info()->utraps) return -ENOMEM;
+		current_thread_info()->utraps[0] = 1;
+		memset(current_thread_info()->utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long));
 	} else {
-		if ((utrap_handler_t)current->thread.utraps[type] != new_p &&
-		    current->thread.utraps[0] > 1) {
-			long *p = current->thread.utraps;
+		if ((utrap_handler_t)current_thread_info()->utraps[type] != new_p &&
+		    current_thread_info()->utraps[0] > 1) {
+			long *p = current_thread_info()->utraps;
 
-			current->thread.utraps =
+			current_thread_info()->utraps =
 				kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long),
 					GFP_KERNEL);
-			if (!current->thread.utraps) {
-				current->thread.utraps = p;
+			if (!current_thread_info()->utraps) {
+				current_thread_info()->utraps = p;
 				return -ENOMEM;
 			}
 			p[0]--;
-			current->thread.utraps[0] = 1;
-			memcpy(current->thread.utraps+1, p+1,
+			current_thread_info()->utraps[0] = 1;
+			memcpy(current_thread_info()->utraps+1, p+1,
 			       UT_TRAP_INSTRUCTION_31*sizeof(long));
 		}
 	}
 	if (old_p) {
-		if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p))
+		if (put_user((utrap_handler_t)(current_thread_info()->utraps[type]), old_p))
 			return -EFAULT;
 	}
 	if (old_d) {
 		if (put_user(NULL, old_d))
 			return -EFAULT;
 	}
-	current->thread.utraps[type] = (long)new_p;
+	current_thread_info()->utraps[type] = (long)new_p;
 
 	return 0;
 }
@@ -589,10 +589,10 @@
 	unsigned long pic, tmp;
 
 	read_pic(pic);
-	tmp = (current->thread.kernel_cntd0 += (unsigned int)pic);
-	__put_user(tmp, current->thread.user_cntd0);
-	tmp = (current->thread.kernel_cntd1 += (pic >> 32));
-	__put_user(tmp, current->thread.user_cntd1);
+	tmp = (current_thread_info()->kernel_cntd0 += (unsigned int)pic);
+	__put_user(tmp, current_thread_info()->user_cntd0);
+	tmp = (current_thread_info()->kernel_cntd1 += (pic >> 32));
+	__put_user(tmp, current_thread_info()->user_cntd1);
 	reset_pic();
 }
 
@@ -603,24 +603,24 @@
 
 	switch(opcode) {
 	case PERFCTR_ON:
-		current->thread.pcr_reg = arg2;
-		current->thread.user_cntd0 = (u64 *) arg0;
-		current->thread.user_cntd1 = (u64 *) arg1;
-		current->thread.kernel_cntd0 =
-			current->thread.kernel_cntd1 = 0;
+		current_thread_info()->pcr_reg = arg2;
+		current_thread_info()->user_cntd0 = (u64 *) arg0;
+		current_thread_info()->user_cntd1 = (u64 *) arg1;
+		current_thread_info()->kernel_cntd0 =
+			current_thread_info()->kernel_cntd1 = 0;
 		write_pcr(arg2);
 		reset_pic();
-		current->thread.flags |= SPARC_FLAG_PERFCTR;
+		set_thread_flag(TIF_PERFCTR);
 		break;
 
 	case PERFCTR_OFF:
 		err = -EINVAL;
-		if ((current->thread.flags & SPARC_FLAG_PERFCTR) != 0) {
-			current->thread.user_cntd0 =
-				current->thread.user_cntd1 = NULL;
-			current->thread.pcr_reg = 0;
+		if (test_thread_flag(TIF_PERFCTR)) {
+			current_thread_info()->user_cntd0 =
+				current_thread_info()->user_cntd1 = NULL;
+			current_thread_info()->pcr_reg = 0;
 			write_pcr(0);
-			current->thread.flags &= ~(SPARC_FLAG_PERFCTR);
+			clear_thread_flag(TIF_PERFCTR);
 			err = 0;
 		}
 		break;
@@ -628,50 +628,50 @@
 	case PERFCTR_READ: {
 		unsigned long pic, tmp;
 
-		if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
+		if (!test_thread_flag(TIF_PERFCTR)) {
 			err = -EINVAL;
 			break;
 		}
 		read_pic(pic);
-		tmp = (current->thread.kernel_cntd0 += (unsigned int)pic);
-		err |= __put_user(tmp, current->thread.user_cntd0);
-		tmp = (current->thread.kernel_cntd1 += (pic >> 32));
-		err |= __put_user(tmp, current->thread.user_cntd1);
+		tmp = (current_thread_info()->kernel_cntd0 += (unsigned int)pic);
+		err |= __put_user(tmp, current_thread_info()->user_cntd0);
+		tmp = (current_thread_info()->kernel_cntd1 += (pic >> 32));
+		err |= __put_user(tmp, current_thread_info()->user_cntd1);
 		reset_pic();
 		break;
 	}
 
 	case PERFCTR_CLRPIC:
-		if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
+		if (!test_thread_flag(TIF_PERFCTR)) {
 			err = -EINVAL;
 			break;
 		}
-		current->thread.kernel_cntd0 =
-			current->thread.kernel_cntd1 = 0;
+		current_thread_info()->kernel_cntd0 =
+			current_thread_info()->kernel_cntd1 = 0;
 		reset_pic();
 		break;
 
 	case PERFCTR_SETPCR: {
 		u64 *user_pcr = (u64 *)arg0;
-		if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
+		if (!test_thread_flag(TIF_PERFCTR)) {
 			err = -EINVAL;
 			break;
 		}
-		err |= __get_user(current->thread.pcr_reg, user_pcr);
-		write_pcr(current->thread.pcr_reg);
-		current->thread.kernel_cntd0 =
-			current->thread.kernel_cntd1 = 0;
+		err |= __get_user(current_thread_info()->pcr_reg, user_pcr);
+		write_pcr(current_thread_info()->pcr_reg);
+		current_thread_info()->kernel_cntd0 =
+			current_thread_info()->kernel_cntd1 = 0;
 		reset_pic();
 		break;
 	}
 
 	case PERFCTR_GETPCR: {
 		u64 *user_pcr = (u64 *)arg0;
-		if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
+		if (!test_thread_flag(TIF_PERFCTR)) {
 			err = -EINVAL;
 			break;
 		}
-		err |= __put_user(current->thread.pcr_reg, user_pcr);
+		err |= __put_user(current_thread_info()->pcr_reg, user_pcr);
 		break;
 	}
 
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/kernel/sys_sparc32.c	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.182 2001/10/18 09:06:36 davem Exp $
+/* $Id: sys_sparc32.c,v 1.184 2002/02/09 19:49:31 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -49,6 +49,7 @@
 #include <linux/in.h>
 #include <linux/icmpv6.h>
 #include <linux/sysctl.h>
+#include <linux/binfmts.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -1459,138 +1460,63 @@
 	return ret;
 }
 
-static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
+static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
 {
-	unsigned long ino, blksize, blocks;
-	kdev_t dev, rdev;
-	umode_t mode;
-	nlink_t nlink;
-	uid_t uid;
-	gid_t gid;
-	off_t size;
-	time_t atime, mtime, ctime;
 	int err;
 
-	/* Stream the loads of inode data into the load buffer,
-	 * then we push it all into the store buffer below.  This
-	 * should give optimal cache performance.
-	 */
-	ino = inode->i_ino;
-	dev = inode->i_dev;
-	mode = inode->i_mode;
-	nlink = inode->i_nlink;
-	uid = inode->i_uid;
-	gid = inode->i_gid;
-	rdev = inode->i_rdev;
-	size = inode->i_size;
-	atime = inode->i_atime;
-	mtime = inode->i_mtime;
-	ctime = inode->i_ctime;
-	blksize = inode->i_blksize;
-	blocks = inode->i_blocks;
-
-	err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
-	err |= put_user(ino, &statbuf->st_ino);
-	err |= put_user(mode, &statbuf->st_mode);
-	err |= put_user(nlink, &statbuf->st_nlink);
-	err |= put_user(high2lowuid(uid), &statbuf->st_uid);
-	err |= put_user(high2lowgid(gid), &statbuf->st_gid);
-	err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
-	err |= put_user(size, &statbuf->st_size);
-	err |= put_user(atime, &statbuf->st_atime);
+	err  = put_user(stat->dev, &statbuf->st_dev);
+	err |= put_user(stat->ino, &statbuf->st_ino);
+	err |= put_user(stat->mode, &statbuf->st_mode);
+	err |= put_user(stat->nlink, &statbuf->st_nlink);
+	err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
+	err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
+	err |= put_user(stat->rdev, &statbuf->st_rdev);
+	err |= put_user(stat->size, &statbuf->st_size);
+	err |= put_user(stat->atime, &statbuf->st_atime);
 	err |= put_user(0, &statbuf->__unused1);
-	err |= put_user(mtime, &statbuf->st_mtime);
+	err |= put_user(stat->mtime, &statbuf->st_mtime);
 	err |= put_user(0, &statbuf->__unused2);
-	err |= put_user(ctime, &statbuf->st_ctime);
+	err |= put_user(stat->ctime, &statbuf->st_ctime);
 	err |= put_user(0, &statbuf->__unused3);
-	if (blksize) {
-		err |= put_user(blksize, &statbuf->st_blksize);
-		err |= put_user(blocks, &statbuf->st_blocks);
-	} else {
-		unsigned int tmp_blocks;
-
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-		tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		if (tmp_blocks > D_B) {
-			unsigned int indirect;
-
-			indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
-			tmp_blocks += indirect;
-			if (indirect > 1) {
-				indirect = (indirect - 1 + I_B - 1) / I_B;
-				tmp_blocks += indirect;
-				if (indirect > 1)
-					tmp_blocks++;
-			}
-		}
-		err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
-		err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
-#undef D_B
-#undef I_B
-	}
+	err |= put_user(stat->blksize, &statbuf->st_blksize);
+	err |= put_user(stat->blocks, &statbuf->st_blocks);
 	err |= put_user(0, &statbuf->__unused4[0]);
 	err |= put_user(0, &statbuf->__unused4[1]);
 
 	return err;
 }
 
-/* Perhaps this belongs in fs.h or similar. -DaveM */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-	struct inode * inode = dentry->d_inode;
-	if (inode->i_op && inode->i_op->revalidate)
-		return inode->i_op->revalidate(dentry);
-	return 0;
-}
-
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
+
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
-	error = user_path_walk(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
 	return error;
 }
 
 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
 
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
-		path_release(&nd);
-	}
 	return error;
 }
 
 asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
 {
-	struct file *f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
+	if (!error)
+		error = cp_new_stat32(&stat, statbuf);
 
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_new_stat32(dentry->d_inode, statbuf);
-		fput(f);
-	}
-	return err;
+	return error;
 }
 
 extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
@@ -2801,8 +2727,8 @@
         struct k_sigaction new_ka, old_ka;
         int ret;
 
-	if(sig < 0) {
-		current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
+	if (sig < 0) {
+		set_thread_flag(TIF_NEWSIGNALS);
 		sig = -sig;
 	}
 
@@ -2846,7 +2772,7 @@
 	/* All tasks which use RT signals (effectively) use
 	 * new style signals.
 	 */
-	current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
+	set_thread_flag(TIF_NEWSIGNALS);
 
         if (act) {
 		new_ka.ka_restorer = restorer;
@@ -3069,8 +2995,8 @@
 
 	if(!error) {
 		fprs_write(0);
-		current->thread.xfsr[0] = 0;
-		current->thread.fpsaved[0] = 0;
+		current_thread_info()->xfsr[0] = 0;
+		current_thread_info()->fpsaved[0] = 0;
 		regs->tstate &= ~TSTATE_PEF;
 	}
 out:
diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
--- a/arch/sparc64/kernel/sys_sunos32.c	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/kernel/sys_sunos32.c	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.62 2002/01/08 16:00:14 davem Exp $
+/* $Id: sys_sunos32.c,v 1.64 2002/02/09 19:49:31 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -455,8 +455,8 @@
 	siginfo_t info;
 	static int cnt;
 
-	regs = current->thread.kregs;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	regs = current_thread_info()->kregs;
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -612,7 +612,7 @@
 
 	inode = file->f_dentry->d_inode;
 
-	socket = &inode->u.socket_i;
+	socket = SOCKET_I(inode);
 	local.sin_family = AF_INET;
 	local.sin_addr.s_addr = INADDR_ANY;
 
@@ -1046,7 +1046,7 @@
 		if(!kmbuf)
 			break;
 		sp = (struct sparc_stackf32 *)
-			(current->thread.kregs->u_regs[UREG_FP] & 0xffffffffUL);
+			(current_thread_info()->kregs->u_regs[UREG_FP] & 0xffffffffUL);
 		if(get_user(arg5, &sp->xxargs[0])) {
 			rval = -EFAULT;
 			kfree(kmbuf);
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/systbls.S	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.79 2001/10/18 08:27:05 davem Exp $
+/* $Id: systbls.S,v 1.81 2002/02/08 03:57:14 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -52,11 +52,11 @@
 /*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
 	.word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
 /*160*/	.word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
-	.word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
-/*170*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
-	.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
-	.word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
+	.word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
+/*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
+	.word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
+/*180*/	.word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
+	.word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
 /*190*/	.word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
 /*200*/	.word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
@@ -111,11 +111,11 @@
 /*150*/	.word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
 	.word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/	.word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
-	.word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
-/*170*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
-	.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
-	.word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
+	.word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
+/*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
+	.word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
+/*180*/	.word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
+	.word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
 /*190*/	.word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
 /*200*/	.word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
diff -Nru a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
--- a/arch/sparc64/kernel/trampoline.S	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/trampoline.S	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: trampoline.S,v 1.25 2002/01/11 08:45:38 davem Exp $
+/* $Id: trampoline.S,v 1.26 2002/02/09 19:49:30 davem Exp $
  * trampoline.S: Jump start slave processors on sparc64.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -14,7 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/spitfire.h>
 #include <asm/processor.h>
-#include <asm/asm_offsets.h>
+#include <asm/thread_info.h>
 
 	.data
 	.align	8
@@ -262,7 +262,7 @@
 	wrpr		%o1, PSTATE_IG, %pstate
 
 	/* Get our UPA MID. */
-	lduw		[%o2 + AOFF_task_cpu], %g1
+	ldub		[%o2 + TI_CPU], %g1
 	sethi		%hi(cpu_data), %g5
 	or		%g5, %lo(cpu_data), %g5
 
diff -Nru a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
--- a/arch/sparc64/kernel/traps.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/traps.c	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.83 2002/01/11 08:45:38 davem Exp $
+/* $Id: traps.c,v 1.85 2002/02/09 19:49:31 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -51,7 +51,7 @@
 		sprintf(buffer, "Kernel bad sw trap %lx", lvl);
 		die_if_kernel (buffer, regs);
 	}
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -89,7 +89,7 @@
 		       sfsr, sfar);
 		die_if_kernel("Iax", regs);
 	}
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -527,6 +527,21 @@
 			       "i" (ASI_PHYS_USE_EC));
 }
 
+#ifdef CONFIG_SMP
+unsigned long cheetah_tune_scheduling(void)
+{
+	unsigned long tick1, tick2, raw;
+
+	__asm__ __volatile__("rd %%tick, %0" : "=r" (tick1));
+	cheetah_flush_ecache();
+	__asm__ __volatile__("rd %%tick, %0" : "=r" (tick2));
+
+	raw = (tick2 - tick1);
+
+	return (raw - (raw >> 2));
+}
+#endif
+
 /* Unfortunately, the diagnostic access to the I-cache tags we need to
  * use to clear the thing interferes with I-cache coherency transactions.
  *
@@ -1296,14 +1311,14 @@
 
 void do_fpe_common(struct pt_regs *regs)
 {
-	if(regs->tstate & TSTATE_PRIV) {
+	if (regs->tstate & TSTATE_PRIV) {
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
 	} else {
-		unsigned long fsr = current->thread.xfsr[0];
+		unsigned long fsr = current_thread_info()->xfsr[0];
 		siginfo_t info;
 
-		if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+		if (test_thread_flag(TIF_32BIT)) {
 			regs->tpc &= 0xffffffff;
 			regs->tnpc &= 0xffffffff;
 		}
@@ -1340,7 +1355,7 @@
 	struct fpustate *f = FPUSTATE;
 	int ret = 0;
 
-	switch ((current->thread.xfsr[0] & 0x1c000)) {
+	switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
 	case (2 << 14): /* unfinished_FPop */
 	case (3 << 14): /* unimplemented_FPop */
 		ret = do_mathemu(regs, f);
@@ -1355,9 +1370,9 @@
 {
 	siginfo_t info;
 
-	if(regs->tstate & TSTATE_PRIV)
+	if (regs->tstate & TSTATE_PRIV)
 		die_if_kernel("Penguin overflow trap from kernel mode", regs);
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -1373,7 +1388,7 @@
 {
 	siginfo_t info;
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -1389,11 +1404,11 @@
 {
 	int i;
 
-	if((((unsigned long) pc) & 3))
+	if ((((unsigned long) pc) & 3))
 		return;
 
 	printk("Instruction DUMP:");
-	for(i = -3; i < 6; i++)
+	for (i = -3; i < 6; i++)
 		printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
 	printk("\n");
 }
@@ -1403,14 +1418,14 @@
 	int i;
 	unsigned int buf[9];
 	
-	if((((unsigned long) pc) & 3))
+	if ((((unsigned long) pc) & 3))
 		return;
 		
-	if(copy_from_user(buf, pc - 3, sizeof(buf)))
+	if (copy_from_user(buf, pc - 3, sizeof(buf)))
 		return;
 
 	printk("Instruction DUMP:");
-	for(i = 0; i < 9; i++)
+	for (i = 0; i < 9; i++)
 		printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>');
 	printk("\n");
 }
@@ -1418,18 +1433,18 @@
 void show_trace_task(struct task_struct *tsk)
 {
 	unsigned long pc, fp;
-	unsigned long task_base = (unsigned long)tsk;
+	unsigned long thread_base = (unsigned long) tsk->thread_info;
 	struct reg_window *rw;
 	int count = 0;
 
 	if (!tsk)
 		return;
 
-	fp = tsk->thread.ksp + STACK_BIAS;
+	fp = tsk->thread_info->ksp + STACK_BIAS;
 	do {
 		/* Bogus frame pointer? */
-		if (fp < (task_base + sizeof(struct task_struct)) ||
-		    fp >= (task_base + THREAD_SIZE))
+		if (fp < (thread_base + sizeof(struct thread_info)) ||
+		    fp >= (thread_base + THREAD_SIZE))
 			break;
 		rw = (struct reg_window *)fp;
 		pc = rw->ins[7];
@@ -1456,7 +1471,7 @@
 	printk("%s(%d): %s\n", current->comm, current->pid, str);
 	__asm__ __volatile__("flushw");
 	__show_regs(regs);
-	if(regs->tstate & TSTATE_PRIV) {
+	if (regs->tstate & TSTATE_PRIV) {
 		struct reg_window *rw = (struct reg_window *)
 			(regs->u_regs[UREG_FP] + STACK_BIAS);
 
@@ -1464,12 +1479,12 @@
 		 * find some badly aligned kernel stack.
 		 */
 		lastrw = (struct reg_window *)current;
-		while(rw					&&
-		      count++ < 30				&&
-		      rw >= lastrw				&&
-		      (char *) rw < ((char *) current)
-		        + sizeof (union task_union) 		&&
-		      !(((unsigned long) rw) & 0x7)) {
+		while (rw					&&
+		       count++ < 30				&&
+		       rw >= lastrw				&&
+		       (char *) rw < ((char *) current)
+		       + sizeof (union thread_union) 		&&
+		       !(((unsigned long) rw) & 0x7)) {
 			printk("Caller[%016lx]\n", rw->ins[7]);
 			lastrw = rw;
 			rw = (struct reg_window *)
@@ -1477,7 +1492,7 @@
 		}
 		instruction_dump ((unsigned int *) regs->tpc);
 	} else {
-		if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+		if (test_thread_flag(TIF_32BIT)) {
 			regs->tpc &= 0xffffffff;
 			regs->tnpc &= 0xffffffff;
 		}
@@ -1487,7 +1502,7 @@
 	smp_report_regs();
 #endif
                                                 	
-	if(regs->tstate & TSTATE_PRIV)
+	if (regs->tstate & TSTATE_PRIV)
 		do_exit(SIGKILL);
 	do_exit(SIGSEGV);
 }
@@ -1502,9 +1517,9 @@
 	u32 insn;
 	siginfo_t info;
 
-	if(tstate & TSTATE_PRIV)
+	if (tstate & TSTATE_PRIV)
 		die_if_kernel("Kernel illegal instruction", regs);
-	if(current->thread.flags & SPARC_FLAG_32BIT)
+	if (test_thread_flag(TIF_32BIT))
 		pc = (u32)pc;
 	if (get_user(insn, (u32 *)pc) != -EFAULT) {
 		if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ {
@@ -1527,7 +1542,7 @@
 {
 	siginfo_t info;
 
-	if(regs->tstate & TSTATE_PRIV) {
+	if (regs->tstate & TSTATE_PRIV) {
 		extern void kernel_unaligned_trap(struct pt_regs *regs,
 						  unsigned int insn, 
 						  unsigned long sfar, unsigned long sfsr);
@@ -1546,7 +1561,7 @@
 {
 	siginfo_t info;
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -1654,15 +1669,42 @@
 	regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate);
 	regs->tpc   = regs->tnpc;
 	regs->tnpc += 4;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
 }
 
+extern void thread_info_offsets_are_bolixed_dave(void);
+
 /* Only invoked on boot processor. */
 void trap_init(void)
 {
+	/* Compile time sanity check. */
+	if (TI_TASK != offsetof(struct thread_info, task) ||
+	    TI_FLAGS != offsetof(struct thread_info, flags) ||
+	    TI_CPU != offsetof(struct thread_info, cpu) ||
+	    TI_FPSAVED != offsetof(struct thread_info, fpsaved) ||
+	    TI_KSP != offsetof(struct thread_info, ksp) ||
+	    TI_FAULT_ADDR != offsetof(struct thread_info, fault_address) ||
+	    TI_KREGS != offsetof(struct thread_info, kregs) ||
+	    TI_UTRAPS != offsetof(struct thread_info, utraps) ||
+	    TI_EXEC_DOMAIN != offsetof(struct thread_info, exec_domain) ||
+	    TI_REG_WINDOW != offsetof(struct thread_info, reg_window) ||
+	    TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) ||
+	    TI_GSR != offsetof(struct thread_info, gsr) ||
+	    TI_XFSR != offsetof(struct thread_info, xfsr) ||
+	    TI_USER_CNTD0 != offsetof(struct thread_info, user_cntd0) ||
+	    TI_USER_CNTD1 != offsetof(struct thread_info, user_cntd1) ||
+	    TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) ||
+	    TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) ||
+	    TI_PCR != offsetof(struct thread_info, pcr_reg) ||
+	    TI_CEE_STUFF != offsetof(struct thread_info, cee_stuff) ||
+	    TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
+	    TI_FPREGS != offsetof(struct thread_info, fpregs) ||
+	    (TI_FPREGS & (64 - 1)))
+		thread_info_offsets_are_bolixed_dave();
+
 	/* Attach to the address space of init_task.  On SMP we
 	 * do this in smp.c:smp_callin for other cpus.
 	 */
@@ -1670,6 +1712,6 @@
 	current->active_mm = &init_mm;
 
 #ifdef CONFIG_SMP
-	current->cpu = hard_smp_processor_id();
+	current_thread_info()->cpu = hard_smp_processor_id();
 #endif
 }
diff -Nru a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
--- a/arch/sparc64/kernel/ttable.S	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/kernel/ttable.S	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: ttable.S,v 1.37 2002/01/23 11:27:32 davem Exp $
+/* $Id: ttable.S,v 1.38 2002/02/09 19:49:30 davem Exp $
  * ttable.S: Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
  *
  * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu)
@@ -211,20 +211,20 @@
 tl1_paw:	TRAPTL1(do_paw_tl1)
 tl1_vaw:	TRAPTL1(do_vaw_tl1)
 
-		/* The grotty trick to save %g1 into current->thread.kernel_cntd0
+		/* The grotty trick to save %g1 into current->thread.cee_stuff
 		 * is because when we take this trap we could be interrupting trap
-		 * code already using the trap alternate global registers.  It is
-		 * better to corrupt a performance counter than corrupt trap register
-		 * state.  We cross our fingers and pray that this store/load does
+		 * code already using the trap alternate global registers.
+		 *
+		 * We cross our fingers and pray that this store/load does
 		 * not cause yet another CEE trap.
 		 */
 tl1_cee:	membar	#Sync
-		stx	%g1, [%g6 + AOFF_task_thread + AOFF_thread_kernel_cntd0]
+		stx	%g1, [%g6 + TI_CEE_STUFF]
 		ldxa	[%g0] ASI_AFSR, %g1
 		membar	#Sync
 		stxa	%g1, [%g0] ASI_AFSR
 		membar	#Sync
-		ldx	[%g6 + AOFF_task_thread + AOFF_thread_kernel_cntd0], %g1
+		ldx	[%g6 + TI_CEE_STUFF], %g1
 		retry
 
 tl1_iamiss:	BTRAPTL1(0x64) BTRAPTL1(0x65) BTRAPTL1(0x66) BTRAPTL1(0x67)
diff -Nru a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
--- a/arch/sparc64/kernel/unaligned.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/kernel/unaligned.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.23 2001/04/09 04:29:03 davem Exp $
+/* $Id: unaligned.c,v 1.24 2002/02/09 19:49:31 davem Exp $
  * unaligned.c: Unaligned load/store trap handling with special
  *              cases for the kernel to do them more quickly.
  *
@@ -42,7 +42,7 @@
 {
 	unsigned long tmp = (insn >> 21) & 1;
 
-	if(!tmp)
+	if (!tmp)
 		return load;
 	else {
 		switch ((insn>>19)&0xf) {
@@ -63,15 +63,15 @@
 	if (tmp == 11 || tmp == 14) /* ldx/stx */
 		return 8;
 	tmp &= 3;
-	if(!tmp)
+	if (!tmp)
 		return 4;
-	else if(tmp == 3)
+	else if (tmp == 3)
 		return 16;	/* ldd/std - Although it is actually 8 */
-	else if(tmp == 2)
+	else if (tmp == 2)
 		return 2;
 	else {
 		printk("Impossible unaligned trap. insn=%08x\n", insn);
-		die_if_kernel("Byte sized unaligned access?!?!", current->thread.kregs);
+		die_if_kernel("Byte sized unaligned access?!?!", current_thread_info()->kregs);
 	}
 }
 
@@ -95,8 +95,8 @@
 static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
 				       unsigned int rd, int from_kernel)
 {
-	if(rs2 >= 16 || rs1 >= 16 || rd >= 16) {
-		if(from_kernel != 0)
+	if (rs2 >= 16 || rs1 >= 16 || rd >= 16) {
+		if (from_kernel != 0)
 			__asm__ __volatile__("flushw");
 		else
 			flushw_user();
@@ -112,13 +112,13 @@
 {
 	unsigned long value;
 	
-	if(reg < 16)
+	if (reg < 16)
 		return (!reg ? 0 : regs->u_regs[reg]);
 	if (regs->tstate & TSTATE_PRIV) {
 		struct reg_window *win;
 		win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
 		value = win->locals[reg - 16];
-	} else if (current->thread.flags & SPARC_FLAG_32BIT) {
+	} else if (test_thread_flag(TIF_32BIT)) {
 		struct reg_window32 *win32;
 		win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
 		get_user(value, &win32->locals[reg - 16]);
@@ -132,13 +132,13 @@
 
 static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
 {
-	if(reg < 16)
+	if (reg < 16)
 		return &regs->u_regs[reg];
 	if (regs->tstate & TSTATE_PRIV) {
 		struct reg_window *win;
 		win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
 		return &win->locals[reg - 16];
-	} else if (current->thread.flags & SPARC_FLAG_32BIT) {
+	} else if (test_thread_flag(TIF_32BIT)) {
 		struct reg_window32 *win32;
 		win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
 		return (unsigned long *)&win32->locals[reg - 16];
@@ -156,7 +156,7 @@
 	unsigned int rs2 = insn & 0x1f;
 	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
 
-	if(insn & 0x2000) {
+	if (insn & 0x2000) {
 		maybe_flush_windows(rs1, 0, rd, from_kernel);
 		return (fetch_reg(rs1, regs) + sign_extend_imm13(insn));
 	} else {
@@ -335,7 +335,7 @@
 {
 	regs->tpc   = regs->tnpc;
 	regs->tnpc += 4;
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
 	}
@@ -360,7 +360,7 @@
 
 	if (!fixup) {
 		unsigned long address = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f));
-        	if(address < PAGE_SIZE) {
+        	if (address < PAGE_SIZE) {
                 	printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler");
         	} else
                 	printk(KERN_ALERT "Unable to handle kernel paging request in mna handler");
@@ -387,7 +387,7 @@
 	enum direction dir = decode_direction(insn);
 	int size = decode_access_size(insn);
 
-	if(!ok_for_kernel(insn) || dir == both) {
+	if (!ok_for_kernel(insn) || dir == both) {
 		printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n",
 		       regs->tpc);
 		unaligned_panic("Kernel does fpu/atomic unaligned load/store.", regs);
@@ -408,7 +408,7 @@
 		printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] retpc[%016lx]\n",
 		       regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]);
 #endif
-		switch(dir) {
+		switch (dir) {
 		case load:
 			do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
 					size, (unsigned long *) addr,
@@ -459,11 +459,11 @@
 		ret += popc_helper[value & 0xf];
 		value >>= 4;
 	}
-	if(rd < 16) {
+	if (rd < 16) {
 		if (rd)
 			regs->u_regs[rd] = ret;
 	} else {
-		if (current->thread.flags & SPARC_FLAG_32BIT) {
+		if (test_thread_flag(TIF_32BIT)) {
 			struct reg_window32 *win32;
 			win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
 			put_user(ret, &win32->locals[rd - 16]);
@@ -490,9 +490,9 @@
 	int flag = (freg < 32) ? FPRS_DL : FPRS_DU;
 
 	save_and_clear_fpu();
-	current->thread.xfsr[0] &= ~0x1c000;
+	current_thread_info()->xfsr[0] &= ~0x1c000;
 	if (freg & 3) {
-		current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+		current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */;
 		do_fpother(regs);
 		return 0;
 	}
@@ -500,7 +500,7 @@
 		/* STQ */
 		u64 first = 0, second = 0;
 		
-		if (current->thread.fpsaved[0] & flag) {
+		if (current_thread_info()->fpsaved[0] & flag) {
 			first = *(u64 *)&f->regs[freg];
 			second = *(u64 *)&f->regs[freg+2];
 		}
@@ -575,18 +575,18 @@
 				break;
 			}
 		}
-		if (!(current->thread.fpsaved[0] & FPRS_FEF)) {
-			current->thread.fpsaved[0] = FPRS_FEF;
-			current->thread.gsr[0] = 0;
+		if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) {
+			current_thread_info()->fpsaved[0] = FPRS_FEF;
+			current_thread_info()->gsr[0] = 0;
 		}
-		if (!(current->thread.fpsaved[0] & flag)) {
+		if (!(current_thread_info()->fpsaved[0] & flag)) {
 			if (freg < 32)
 				memset(f->regs, 0, 32*sizeof(u32));
 			else
 				memset(f->regs+32, 0, 32*sizeof(u32));
 		}
 		memcpy(f->regs + freg, data, size * 4);
-		current->thread.fpsaved[0] |= flag;
+		current_thread_info()->fpsaved[0] |= flag;
 	}
 	advance(regs);
 	return 1;
@@ -604,7 +604,7 @@
 		reg[0] = 0;
 		if ((insn & 0x780000) == 0x180000)
 			reg[1] = 0;
-	} else if (current->thread.flags & SPARC_FLAG_32BIT) {
+	} else if (test_thread_flag(TIF_32BIT)) {
 		put_user(0, (int *)reg);
 		if ((insn & 0x780000) == 0x180000)
 			put_user(0, ((int *)reg) + 1);
@@ -627,9 +627,9 @@
 	int flag;
 	struct fpustate *f = FPUSTATE;
 
-	if(tstate & TSTATE_PRIV)
+	if (tstate & TSTATE_PRIV)
 		die_if_kernel("lddfmna from kernel", regs);
-	if(current->thread.flags & SPARC_FLAG_32BIT)
+	if (test_thread_flag(TIF_32BIT))
 		pc = (u32)pc;
 	if (get_user(insn, (u32 *)pc) != -EFAULT) {
 		asi = sfsr >> 16;
@@ -649,18 +649,18 @@
 		if (asi & 0x8) /* Little */
 			value = __swab64p(&value);
 		flag = (freg < 32) ? FPRS_DL : FPRS_DU;
-		if (!(current->thread.fpsaved[0] & FPRS_FEF)) {
-			current->thread.fpsaved[0] = FPRS_FEF;
-			current->thread.gsr[0] = 0;
+		if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) {
+			current_thread_info()->fpsaved[0] = FPRS_FEF;
+			current_thread_info()->gsr[0] = 0;
 		}
-		if (!(current->thread.fpsaved[0] & flag)) {
+		if (!(current_thread_info()->fpsaved[0] & flag)) {
 			if (freg < 32)
 				memset(f->regs, 0, 32*sizeof(u32));
 			else
 				memset(f->regs+32, 0, 32*sizeof(u32));
 		}
 		*(u64 *)(f->regs + freg) = value;
-		current->thread.fpsaved[0] |= flag;
+		current_thread_info()->fpsaved[0] |= flag;
 	} else {
 daex:		data_access_exception(regs);
 		return;
@@ -679,9 +679,9 @@
 	int flag;
 	struct fpustate *f = FPUSTATE;
 
-	if(tstate & TSTATE_PRIV)
+	if (tstate & TSTATE_PRIV)
 		die_if_kernel("stdfmna from kernel", regs);
-	if(current->thread.flags & SPARC_FLAG_32BIT)
+	if (test_thread_flag(TIF_32BIT))
 		pc = (u32)pc;
 	if (get_user(insn, (u32 *)pc) != -EFAULT) {
 		freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
@@ -692,7 +692,7 @@
 		    (asi < ASI_P))
 			goto daex;
 		save_and_clear_fpu();
-		if (current->thread.fpsaved[0] & flag)
+		if (current_thread_info()->fpsaved[0] & flag)
 			value = *(u64 *)&f->regs[freg];
 		switch (asi) {
 		case ASI_P:
diff -Nru a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
--- a/arch/sparc64/kernel/winfixup.S	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/kernel/winfixup.S	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: winfixup.S,v 1.29 2000/03/26 09:13:48 davem Exp $
+/* $Id: winfixup.S,v 1.30 2002/02/09 19:49:30 davem Exp $
  *
  * winfixup.S: Handle cases where user stack pointer is found to be bogus.
  *
@@ -11,7 +11,7 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/spitfire.h>
-#include <asm/asm_offsets.h>
+#include <asm/thread_info.h>
 
 	.text
 	.align	32
@@ -69,8 +69,8 @@
 	mov		%g6, %o7			! Get current.
 
 	andn		%l1, PSTATE_MM, %l1		! We want to be in RMO
-	stb		%g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code]
-	stx		%g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address]
+	stb		%g4, [%g6 + TI_FAULT_CODE]
+	stx		%g5, [%g6 + TI_FAULT_ADDR]
 	wrpr		%g0, 0x0, %tl			! Out of trap levels.
 	wrpr		%l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
 	sethi		%uhi(PAGE_OFFSET), %g4		! Prepare page_offset global reg
@@ -94,56 +94,56 @@
 	 * do not touch %g7 or %g2 so we handle the two cases fine.
 	 */
 spill_fixup:
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_flags], %g1
-	andcc		%g1, SPARC_FLAG_32BIT, %g0
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1
+	ldx		[%g6 + TI_FLAGS], %g1
+	andcc		%g1, _TIF_32BIT, %g0
+	ldub		[%g6 + TI_WSAVED], %g1
 
 	sll		%g1, 3, %g3
 	add		%g6, %g3, %g3
-	stx		%sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
+	stx		%sp, [%g3 + TI_RWIN_SPTRS]
 	sll		%g1, 7, %g3
 	bne,pt		%xcc, 1f
 	 add		%g6, %g3, %g3
-	stx		%l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
-	stx		%l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
+	stx		%l0, [%g3 + TI_REG_WINDOW + 0x00]
+	stx		%l1, [%g3 + TI_REG_WINDOW + 0x08]
 
-	stx		%l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
-	stx		%l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
-	stx		%l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
-	stx		%l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
-	stx		%l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
-	stx		%l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
-	stx		%i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40]
-	stx		%i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48]
-
-	stx		%i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50]
-	stx		%i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58]
-	stx		%i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60]
-	stx		%i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68]
-	stx		%i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70]
+	stx		%l2, [%g3 + TI_REG_WINDOW + 0x10]
+	stx		%l3, [%g3 + TI_REG_WINDOW + 0x18]
+	stx		%l4, [%g3 + TI_REG_WINDOW + 0x20]
+	stx		%l5, [%g3 + TI_REG_WINDOW + 0x28]
+	stx		%l6, [%g3 + TI_REG_WINDOW + 0x30]
+	stx		%l7, [%g3 + TI_REG_WINDOW + 0x38]
+	stx		%i0, [%g3 + TI_REG_WINDOW + 0x40]
+	stx		%i1, [%g3 + TI_REG_WINDOW + 0x48]
+
+	stx		%i2, [%g3 + TI_REG_WINDOW + 0x50]
+	stx		%i3, [%g3 + TI_REG_WINDOW + 0x58]
+	stx		%i4, [%g3 + TI_REG_WINDOW + 0x60]
+	stx		%i5, [%g3 + TI_REG_WINDOW + 0x68]
+	stx		%i6, [%g3 + TI_REG_WINDOW + 0x70]
 	b,pt		%xcc, 2f
-	 stx		%i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78]
-1:	stw		%l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
+	 stx		%i7, [%g3 + TI_REG_WINDOW + 0x78]
+1:	stw		%l0, [%g3 + TI_REG_WINDOW + 0x00]
 
-	stw		%l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x04]
-	stw		%l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
-	stw		%l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x0c]
-	stw		%l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
-	stw		%l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x14]
-	stw		%l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
-	stw		%l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x1c]
-	stw		%i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
-
-	stw		%i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x24]
-	stw		%i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
-	stw		%i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x2c]
-	stw		%i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
-	stw		%i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x34]
-	stw		%i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
-	stw		%i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x3c]
+	stw		%l1, [%g3 + TI_REG_WINDOW + 0x04]
+	stw		%l2, [%g3 + TI_REG_WINDOW + 0x08]
+	stw		%l3, [%g3 + TI_REG_WINDOW + 0x0c]
+	stw		%l4, [%g3 + TI_REG_WINDOW + 0x10]
+	stw		%l5, [%g3 + TI_REG_WINDOW + 0x14]
+	stw		%l6, [%g3 + TI_REG_WINDOW + 0x18]
+	stw		%l7, [%g3 + TI_REG_WINDOW + 0x1c]
+	stw		%i0, [%g3 + TI_REG_WINDOW + 0x20]
+
+	stw		%i1, [%g3 + TI_REG_WINDOW + 0x24]
+	stw		%i2, [%g3 + TI_REG_WINDOW + 0x28]
+	stw		%i3, [%g3 + TI_REG_WINDOW + 0x2c]
+	stw		%i4, [%g3 + TI_REG_WINDOW + 0x30]
+	stw		%i5, [%g3 + TI_REG_WINDOW + 0x34]
+	stw		%i6, [%g3 + TI_REG_WINDOW + 0x38]
+	stw		%i7, [%g3 + TI_REG_WINDOW + 0x3c]
 2:	add		%g1, 1, %g1
 
-	stb		%g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
+	stb		%g1, [%g6 + TI_WSAVED]
 	rdpr		%tstate, %g1
 	andcc		%g1, TSTATE_PRIV, %g0
 	saved
@@ -153,8 +153,8 @@
 	retry
 
 window_scheisse_from_user_common:
-	stb		%g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code]
-	stx		%g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address]
+	stb		%g4, [%g6 + TI_FAULT_CODE]
+	stx		%g5, [%g6 + TI_FAULT_ADDR]
 	wrpr		%g1, %cwp
 	ba,pt		%xcc, etrap
 	 rd		%pc, %g7
@@ -204,47 +204,47 @@
 	b,pt		%xcc, rtrap
 	 nop						! yes, the nop is correct
 spill_fixup_mna:
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_flags], %g1
-	andcc		%g1, SPARC_FLAG_32BIT, %g0
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1
+	ldx		[%g6 + TI_FLAGS], %g1
+	andcc		%g1, _TIF_32BIT, %g0
+	ldub		[%g6 + TI_WSAVED], %g1
 	sll		%g1, 3, %g3
 	add		%g6, %g3, %g3
-	stx		%sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
+	stx		%sp, [%g3 + TI_RWIN_SPTRS]
 
 	sll		%g1, 7, %g3
 	bne,pt		%xcc, 1f
 	 add		%g6, %g3, %g3
-	stx		%l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
-	stx		%l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
-	stx		%l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
-	stx		%l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
-	stx		%l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
-
-	stx		%l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
-	stx		%l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
-	stx		%l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
-	stx		%i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40]
-	stx		%i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48]
-	stx		%i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50]
-	stx		%i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58]
-	stx		%i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60]
-
-	stx		%i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68]
-	stx		%i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70]
-	stx		%i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78]
+	stx		%l0, [%g3 + TI_REG_WINDOW + 0x00]
+	stx		%l1, [%g3 + TI_REG_WINDOW + 0x08]
+	stx		%l2, [%g3 + TI_REG_WINDOW + 0x10]
+	stx		%l3, [%g3 + TI_REG_WINDOW + 0x18]
+	stx		%l4, [%g3 + TI_REG_WINDOW + 0x20]
+
+	stx		%l5, [%g3 + TI_REG_WINDOW + 0x28]
+	stx		%l6, [%g3 + TI_REG_WINDOW + 0x30]
+	stx		%l7, [%g3 + TI_REG_WINDOW + 0x38]
+	stx		%i0, [%g3 + TI_REG_WINDOW + 0x40]
+	stx		%i1, [%g3 + TI_REG_WINDOW + 0x48]
+	stx		%i2, [%g3 + TI_REG_WINDOW + 0x50]
+	stx		%i3, [%g3 + TI_REG_WINDOW + 0x58]
+	stx		%i4, [%g3 + TI_REG_WINDOW + 0x60]
+
+	stx		%i5, [%g3 + TI_REG_WINDOW + 0x68]
+	stx		%i6, [%g3 + TI_REG_WINDOW + 0x70]
+	stx		%i7, [%g3 + TI_REG_WINDOW + 0x78]
 	b,pt		%xcc, 2f
 	 add		%g1, 1, %g1
-1:	std		%l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
-	std		%l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
-	std		%l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
-
-	std		%l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
-	std		%i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
-	std		%i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
-	std		%i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
-	std		%i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
+1:	std		%l0, [%g3 + TI_REG_WINDOW + 0x00]
+	std		%l2, [%g3 + TI_REG_WINDOW + 0x08]
+	std		%l4, [%g3 + TI_REG_WINDOW + 0x10]
+
+	std		%l6, [%g3 + TI_REG_WINDOW + 0x18]
+	std		%i0, [%g3 + TI_REG_WINDOW + 0x20]
+	std		%i2, [%g3 + TI_REG_WINDOW + 0x28]
+	std		%i4, [%g3 + TI_REG_WINDOW + 0x30]
+	std		%i6, [%g3 + TI_REG_WINDOW + 0x38]
 	add		%g1, 1, %g1
-2:	stb		%g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
+2:	stb		%g1, [%g6 + TI_WSAVED]
 	rdpr		%tstate, %g1
 
 	andcc		%g1, TSTATE_PRIV, %g0
@@ -311,47 +311,47 @@
 	b,pt		%xcc, rtrap
 	 nop						! yes, the nop is correct
 spill_fixup_dax:
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_flags], %g1
-	andcc		%g1, SPARC_FLAG_32BIT, %g0
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1
+	ldx		[%g6 + TI_FLAGS], %g1
+	andcc		%g1, _TIF_32BIT, %g0
+	ldub		[%g6 + TI_WSAVED], %g1
 	sll		%g1, 3, %g3
 	add		%g6, %g3, %g3
-	stx		%sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
+	stx		%sp, [%g3 + TI_RWIN_SPTRS]
 
 	sll		%g1, 7, %g3
 	bne,pt		%xcc, 1f
 	 add		%g6, %g3, %g3
-	stx		%l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
-	stx		%l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
-	stx		%l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
-	stx		%l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
-	stx		%l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
-
-	stx		%l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
-	stx		%l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
-	stx		%l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
-	stx		%i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40]
-	stx		%i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48]
-	stx		%i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50]
-	stx		%i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58]
-	stx		%i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60]
-
-	stx		%i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68]
-	stx		%i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70]
-	stx		%i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78]
+	stx		%l0, [%g3 + TI_REG_WINDOW + 0x00]
+	stx		%l1, [%g3 + TI_REG_WINDOW + 0x08]
+	stx		%l2, [%g3 + TI_REG_WINDOW + 0x10]
+	stx		%l3, [%g3 + TI_REG_WINDOW + 0x18]
+	stx		%l4, [%g3 + TI_REG_WINDOW + 0x20]
+
+	stx		%l5, [%g3 + TI_REG_WINDOW + 0x28]
+	stx		%l6, [%g3 + TI_REG_WINDOW + 0x30]
+	stx		%l7, [%g3 + TI_REG_WINDOW + 0x38]
+	stx		%i0, [%g3 + TI_REG_WINDOW + 0x40]
+	stx		%i1, [%g3 + TI_REG_WINDOW + 0x48]
+	stx		%i2, [%g3 + TI_REG_WINDOW + 0x50]
+	stx		%i3, [%g3 + TI_REG_WINDOW + 0x58]
+	stx		%i4, [%g3 + TI_REG_WINDOW + 0x60]
+
+	stx		%i5, [%g3 + TI_REG_WINDOW + 0x68]
+	stx		%i6, [%g3 + TI_REG_WINDOW + 0x70]
+	stx		%i7, [%g3 + TI_REG_WINDOW + 0x78]
 	b,pt		%xcc, 2f
 	 add		%g1, 1, %g1
-1:	std		%l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
-	std		%l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
-	std		%l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
-
-	std		%l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
-	std		%i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
-	std		%i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
-	std		%i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
-	std		%i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
+1:	std		%l0, [%g3 + TI_REG_WINDOW + 0x00]
+	std		%l2, [%g3 + TI_REG_WINDOW + 0x08]
+	std		%l4, [%g3 + TI_REG_WINDOW + 0x10]
+
+	std		%l6, [%g3 + TI_REG_WINDOW + 0x18]
+	std		%i0, [%g3 + TI_REG_WINDOW + 0x20]
+	std		%i2, [%g3 + TI_REG_WINDOW + 0x28]
+	std		%i4, [%g3 + TI_REG_WINDOW + 0x30]
+	std		%i6, [%g3 + TI_REG_WINDOW + 0x38]
 	add		%g1, 1, %g1
-2:	stb		%g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
+2:	stb		%g1, [%g6 + TI_WSAVED]
 	rdpr		%tstate, %g1
 
 	andcc		%g1, TSTATE_PRIV, %g0
diff -Nru a/arch/sparc64/lib/VIScopy.S b/arch/sparc64/lib/VIScopy.S
--- a/arch/sparc64/lib/VIScopy.S	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/lib/VIScopy.S	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: VIScopy.S,v 1.26 2001/09/27 04:36:24 kanoj Exp $
+/* $Id: VIScopy.S,v 1.27 2002/02/09 19:49:30 davem Exp $
  * VIScopy.S: High speed copy operations utilizing the UltraSparc
  *            Visual Instruction Set.
  *
@@ -26,24 +26,24 @@
 #ifdef __KERNEL__
 
 #include <asm/visasm.h>
-#include <asm/asm_offsets.h>
+#include <asm/thread_info.h>
 
-#define FPU_CLEAN_RETL								\
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1;	\
-	VISExit									\
-	clr		%o0;							\
-	retl;									\
+#define FPU_CLEAN_RETL					\
+	ldub		[%g6 + TI_CURRENT_DS], %o1;	\
+	VISExit						\
+	clr		%o0;				\
+	retl;						\
 	 wr		%o1, %g0, %asi;
-#define FPU_RETL								\
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1;	\
-	VISExit									\
-	clr		%o0;							\
-	retl;									\
+#define FPU_RETL					\
+	ldub		[%g6 + TI_CURRENT_DS], %o1;	\
+	VISExit						\
+	clr		%o0;				\
+	retl;						\
 	 wr		%o1, %g0, %asi;
-#define NORMAL_RETL								\
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1;	\
-	clr		%o0;							\
-	retl;									\
+#define NORMAL_RETL					\
+	ldub		[%g6 + TI_CURRENT_DS], %o1;	\
+	clr		%o0;				\
+	retl;						\
 	 wr		%o1, %g0, %asi;
 #define EX(x,y,a,b) 				\
 98: 	x,y;					\
@@ -1032,7 +1032,7 @@
 		/* If this is copy_from_user(), zero out the rest of the
 		 * kernel buffer.
 		 */
-		ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o4
+		ldub		[%g6 + TI_CURRENT_DS], %o4
 		andcc		asi_src, 0x1, %g0
 		be,pt		%icc, 1f
 		 VISExit
diff -Nru a/arch/sparc64/lib/VIScsum.S b/arch/sparc64/lib/VIScsum.S
--- a/arch/sparc64/lib/VIScsum.S	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/lib/VIScsum.S	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: VIScsum.S,v 1.6 2000/02/20 23:21:39 davem Exp $
+/* $Id: VIScsum.S,v 1.7 2002/02/09 19:49:30 davem Exp $
  * VIScsum.S: High bandwidth IP checksumming utilizing the UltraSparc
  *            Visual Instruction Set.
  *
@@ -28,7 +28,7 @@
 #include <asm/head.h>
 #include <asm/asi.h>
 #include <asm/visasm.h>
-#include <asm/asm_offsets.h>
+#include <asm/thread_info.h>
 #else
 #define ASI_BLK_P	0xf0
 #define FRPS_FEF	0x04
@@ -342,7 +342,7 @@
 	DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14)
 	END_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30)
 #ifdef __KERNEL__
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %g7
+	ldub		[%g6 + TI_CURRENT_DS], %g7
 #endif
 	and		%o1, 0x3f, %o1		/*  IEU0	Group		*/
 #ifdef __KERNEL__
diff -Nru a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S
--- a/arch/sparc64/lib/VISsave.S	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/lib/VISsave.S	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: VISsave.S,v 1.5 2001/03/08 22:08:51 davem Exp $
+/* $Id: VISsave.S,v 1.6 2002/02/09 19:49:30 davem Exp $
  * VISsave.S: Code for saving FPU register state for
  *            VIS routines. One should not call this directly,
  *            but use macros provided in <asm/visasm.h>.
@@ -10,6 +10,7 @@
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/visasm.h>
+#include <asm/thread_info.h>
 
 	.text
 	.globl		VISenter, VISenterhalf
@@ -17,47 +18,51 @@
 	/* On entry: %o5=current FPRS value, %g7 is callers address */
 	/* May clobber %o5, %g1, %g2, %g3, %g7, %icc, %xcc */
 
+	/* Nothing special need be done here to handle pre-emption, this
+	 * FPU save/restore mechanism is already preemption safe.
+	 */
+
 	.align		32
 VISenter:
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %g1
+	ldub		[%g6 + TI_FPDEPTH], %g1
 	brnz,a,pn	%g1, 1f
 	 cmp		%g1, 1
-	stb		%g0, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
-	stx		%fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
+	stb		%g0, [%g6 + TI_FPSAVED]
+	stx		%fsr, [%g6 + TI_XFSR]
 9:	jmpl		%g7 + %g0, %g0
 	 nop
 1:	bne,pn		%icc, 2f
 
 	 srl		%g1, 1, %g1
-vis1:	ldub		[%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3
-	stx		%fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
+vis1:	ldub		[%g6 + TI_FPSAVED], %g3
+	stx		%fsr, [%g6 + TI_XFSR]
 	or		%g3, %o5, %g3
-	stb		%g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
+	stb		%g3, [%g6 + TI_FPSAVED]
 	rd		%gsr, %g3
 	clr		%g1
 	ba,pt		%xcc, 3f
 
-	 stx		%g3, [%g6 + AOFF_task_thread + AOFF_thread_gsr]
+	 stx		%g3, [%g6 + TI_GSR]
 2:	add		%g6, %g1, %g3
 	cmp		%o5, FPRS_DU
 	be,pn		%icc, 6f
 	 sll		%g1, 3, %g1
-	stb		%o5, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved]
+	stb		%o5, [%g3 + TI_FPSAVED]
 	rd		%gsr, %g2
 	add		%g6, %g1, %g3
-	stx		%g2, [%g3 + AOFF_task_thread + AOFF_thread_gsr]
+	stx		%g2, [%g3 + TI_GSR]
 
 	add		%g6, %g1, %g2
-	stx		%fsr, [%g2 + AOFF_task_thread + AOFF_thread_xfsr]
+	stx		%fsr, [%g2 + TI_XFSR]
 	sll		%g1, 5, %g1
 3:	andcc		%o5, FPRS_DL|FPRS_DU, %g0
 	be,pn		%icc, 9b
-	 add		%g6, AOFF_task_fpregs, %g2
+	 add		%g6, TI_FPREGS, %g2
 	andcc		%o5, FPRS_DL, %g0
 	membar		#StoreStore | #LoadStore
 
 	be,pn		%icc, 4f
-	 add		%g6, AOFF_task_fpregs+0x40, %g3
+	 add		%g6, TI_FPREGS+0x40, %g3
 	stda		%f0, [%g2 + %g1] ASI_BLK_P
 	stda		%f16, [%g3 + %g1] ASI_BLK_P
 	andcc		%o5, FPRS_DU, %g0
@@ -70,13 +75,13 @@
 	jmpl		%g7 + %g0, %g0
 	 nop
 
-6:	ldub		[%g3 + AOFF_task_thread + AOFF_thread_fpsaved], %o5
+6:	ldub		[%g3 + TI_FPSAVED], %o5
 	or		%o5, FPRS_DU, %o5
-	add		%g6, AOFF_task_fpregs+0x80, %g2
-	stb		%o5, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved]
+	add		%g6, TI_FPREGS+0x80, %g2
+	stb		%o5, [%g3 + TI_FPSAVED]
 
 	sll		%g1, 5, %g1
-	add		%g6, AOFF_task_fpregs+0xc0, %g3
+	add		%g6, TI_FPREGS+0xc0, %g3
 	wr		%g0, FPRS_FEF, %fprs
 	membar		#StoreStore | #LoadStore
 	stda		%f32, [%g2 + %g1] ASI_BLK_P
@@ -88,11 +93,11 @@
 
 	.align		32
 VISenterhalf:
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %g1
+	ldub		[%g6 + TI_FPDEPTH], %g1
 	brnz,a,pn	%g1, 1f
 	 cmp		%g1, 1
-	stb		%g0, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
-	stx		%fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
+	stb		%g0, [%g6 + TI_FPSAVED]
+	stx		%fsr, [%g6 + TI_XFSR]
 	clr		%o5
 	jmpl		%g7 + %g0, %g0
 	 wr		%g0, FPRS_FEF, %fprs
@@ -104,20 +109,20 @@
 2:	addcc		%g6, %g1, %g3
 	sll		%g1, 3, %g1
 	andn		%o5, FPRS_DU, %g2
-	stb		%g2, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved]
+	stb		%g2, [%g3 + TI_FPSAVED]
 
 	rd		%gsr, %g2
 	add		%g6, %g1, %g3
-	stx		%g2, [%g3 + AOFF_task_thread + AOFF_thread_gsr]
+	stx		%g2, [%g3 + TI_GSR]
 	add		%g6, %g1, %g2
-	stx		%fsr, [%g2 + AOFF_task_thread + AOFF_thread_xfsr]
+	stx		%fsr, [%g2 + TI_XFSR]
 	sll		%g1, 5, %g1
 3:	andcc		%o5, FPRS_DL, %g0
 	be,pn		%icc, 4f
-	 add		%g6, AOFF_task_fpregs, %g2
+	 add		%g6, TI_FPREGS, %g2
 
 	membar		#StoreStore | #LoadStore
-	add		%g6, AOFF_task_fpregs+0x40, %g3
+	add		%g6, TI_FPREGS+0x40, %g3
 	stda		%f0, [%g2 + %g1] ASI_BLK_P
 	stda		%f16, [%g3 + %g1] ASI_BLK_P
 	membar		#Sync
diff -Nru a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S
--- a/arch/sparc64/lib/blockops.S	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/lib/blockops.S	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.41 2001/12/05 06:05:35 davem Exp $
+/* $Id: blockops.S,v 1.42 2002/02/09 19:49:30 davem Exp $
  * blockops.S: UltraSparc block zero optimized routines.
  *
  * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com)
@@ -7,9 +7,9 @@
 
 #include "VIS.h"
 #include <asm/visasm.h>
+#include <asm/thread_info.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/asm_offsets.h>
 
 #define TOUCH(reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7)	\
 	fmovd	%reg0, %f48; 	fmovd	%reg1, %f50;		\
@@ -61,7 +61,7 @@
 	 * so we do not risk a multiple TLB match condition later when
 	 * restoring those entries.
 	 */
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_use_blkcommit], %g3
+	ldx		[%g6 + TI_FLAGS], %g3
 
 	/* Spitfire Errata #32 workaround */
 	mov		0x8, %o4
@@ -100,7 +100,7 @@
 	stxa		%g2, [%o3] ASI_DTLB_DATA_ACCESS
 	membar		#Sync
 
-	cmp		%g3, 0
+	andcc		%g3, _TIF_BLKCOMMIT, %g0
 	bne,pn		%xcc, copy_page_using_blkcommit
 	 nop
 
diff -Nru a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S
--- a/arch/sparc64/lib/checksum.S	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/lib/checksum.S	Sun Feb 10 19:58:04 2002
@@ -18,7 +18,7 @@
 #include <asm/ptrace.h>
 #include <asm/asi.h>
 #include <asm/page.h>
-#include <asm/asm_offsets.h>
+#include <asm/thread_info.h>
 
 	/* The problem with the "add with carry" instructions on Ultra
 	 * are two fold.  Firstly, they cannot pair with jack shit,
@@ -498,7 +498,7 @@
 	.globl	cpc_handler
 cpc_handler:
 	ldx	[%sp + 0x7ff + 128], %g1
-	ldub	[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %g3
+	ldub	[%g6 + TI_CURRENT_DS], %g3
 	sub	%g0, EFAULT, %g2
 	brnz,a,pt %g1, 1f
 	 st	%g2, [%g1]
diff -Nru a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S
--- a/arch/sparc64/lib/dec_and_lock.S	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/lib/dec_and_lock.S	Sun Feb 10 19:58:06 2002
@@ -5,6 +5,7 @@
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
  */
 #include <linux/config.h>
+#include <asm/thread_info.h>
 
 #ifndef CONFIG_DEBUG_SPINLOCK
 	.text
@@ -40,6 +41,11 @@
 	membar	#StoreLoad | #StoreStore
 	retl
 	 mov	%g1, %o0
+#ifdef CONFIG_PREEMPT
+	ldsw	[%g6 + TI_PRE_COUNT], %g3
+	add	%g3, 1, %g3
+	stw	%g3, [%g6 + TI_PRE_COUNT]
+#endif
 to_zero:
 	ldstub	[%o1], %g3
 	brnz,pn	%g3, spin_on_lock
@@ -55,6 +61,11 @@
 	 nop
 	membar	#StoreStore | #LoadStore
 	stb	%g0, [%o1]
+#ifdef CONFIG_PREEMPT
+	ldsw	[%g6 + TI_PRE_COUNT], %g3
+	sub	%g3, 1, %g3
+	stw	%g3, [%g6 + TI_PRE_COUNT]
+#endif
 
 	b,pt	%xcc, nzero
 	 nop
diff -Nru a/arch/sparc64/math-emu/math.c b/arch/sparc64/math-emu/math.c
--- a/arch/sparc64/math-emu/math.c	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/math-emu/math.c	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: math.c,v 1.11 1999/12/20 05:02:25 davem Exp $
+/* $Id: math.c,v 1.12 2002/02/09 19:49:31 davem Exp $
  * arch/sparc64/math-emu/math.c
  *
  * Copyright (C) 1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -90,25 +90,25 @@
  */
 static inline int record_exception(struct pt_regs *regs, int eflag)
 {
-	u64 fsr = current->thread.xfsr[0];
+	u64 fsr = current_thread_info()->xfsr[0];
 	int would_trap;
 
 	/* Determine if this exception would have generated a trap. */
 	would_trap = (fsr & ((long)eflag << FSR_TEM_SHIFT)) != 0UL;
 
 	/* If trapping, we only want to signal one bit. */
-	if(would_trap != 0) {
+	if (would_trap != 0) {
 		eflag &= ((fsr & FSR_TEM_MASK) >> FSR_TEM_SHIFT);
-		if((eflag & (eflag - 1)) != 0) {
-			if(eflag & FP_EX_INVALID)
+		if ((eflag & (eflag - 1)) != 0) {
+			if (eflag & FP_EX_INVALID)
 				eflag = FP_EX_INVALID;
-			else if(eflag & FP_EX_OVERFLOW)
+			else if (eflag & FP_EX_OVERFLOW)
 				eflag = FP_EX_OVERFLOW;
-			else if(eflag & FP_EX_UNDERFLOW)
+			else if (eflag & FP_EX_UNDERFLOW)
 				eflag = FP_EX_UNDERFLOW;
-			else if(eflag & FP_EX_DIVZERO)
+			else if (eflag & FP_EX_DIVZERO)
 				eflag = FP_EX_DIVZERO;
-			else if(eflag & FP_EX_INEXACT)
+			else if (eflag & FP_EX_INEXACT)
 				eflag = FP_EX_INEXACT;
 		}
 	}
@@ -128,19 +128,19 @@
 	 *    CEXC just generated is OR'd into the
 	 *    existing value of AEXC.
 	 */
-	if(would_trap == 0)
+	if (would_trap == 0)
 		fsr |= ((long)eflag << FSR_AEXC_SHIFT);
 
 	/* If trapping, indicate fault trap type IEEE. */
-	if(would_trap != 0)
+	if (would_trap != 0)
 		fsr |= (1UL << 14);
 
-	current->thread.xfsr[0] = fsr;
+	current_thread_info()->xfsr[0] = fsr;
 
 	/* If we will not trap, advance the program counter over
 	 * the instruction being handled.
 	 */
-	if(would_trap == 0) {
+	if (would_trap == 0) {
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
 	}
@@ -174,10 +174,10 @@
 	int IR;
 	long XR, xfsr;
 
-	if(tstate & TSTATE_PRIV)
+	if (tstate & TSTATE_PRIV)
 		die_if_kernel("FPQuad from kernel", regs);
-	if(current->thread.flags & SPARC_FLAG_32BIT)
-		pc = (u32)pc;
+	if (test_thread_flag(TIF_32BIT))
+		pc &= 0xffffffff;
 	if (get_user(insn, (u32 *)pc) != -EFAULT) {
 		if ((insn & 0xc1f80000) == 0x81a00000) /* FPOP1 */ {
 			switch ((insn >> 5) & 0x1ff) {
@@ -231,9 +231,9 @@
 			case FMOVQ3:
 				/* fmovq %fccX, %fY, %fZ */
 				if (!((insn >> 11) & 3))
-					XR = current->thread.xfsr[0] >> 10;
+					XR = current_thread_info()->xfsr[0] >> 10;
 				else
-					XR = current->thread.xfsr[0] >> (30 + ((insn >> 10) & 0x6));
+					XR = current_thread_info()->xfsr[0] >> (30 + ((insn >> 10) & 0x6));
 				XR &= 3;
 				IR = 0;
 				switch ((insn >> 14) & 0x7) {
@@ -282,7 +282,7 @@
 					XR = 0;
 				else if (freg < 16)
 					XR = regs->u_regs[freg];
-				else if (current->thread.flags & SPARC_FLAG_32BIT) {
+				else if (test_thread_flag(TIF_32BIT)) {
 					struct reg_window32 *win32;
 					flushw_user ();
 					win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
@@ -305,7 +305,7 @@
 			}
 			if (IR == 0) {
 				/* The fmov test was false. Do a nop instead */
-				current->thread.xfsr[0] &= ~(FSR_CEXC_MASK);
+				current_thread_info()->xfsr[0] &= ~(FSR_CEXC_MASK);
 				regs->tpc = regs->tnpc;
 				regs->tnpc += 4;
 				return 1;
@@ -319,20 +319,20 @@
 	if (type) {
 		argp rs1 = NULL, rs2 = NULL, rd = NULL;
 		
-		freg = (current->thread.xfsr[0] >> 14) & 0xf;
+		freg = (current_thread_info()->xfsr[0] >> 14) & 0xf;
 		if (freg != (type >> 9))
 			goto err;
-		current->thread.xfsr[0] &= ~0x1c000;
+		current_thread_info()->xfsr[0] &= ~0x1c000;
 		freg = ((insn >> 14) & 0x1f);
 		switch (type & 0x3) {
 		case 3: if (freg & 2) {
-				current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+				current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */;
 				goto err;
 			}
 		case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
 		case 1: rs1 = (argp)&f->regs[freg];
 			flags = (freg < 32) ? FPRS_DL : FPRS_DU; 
-			if (!(current->thread.fpsaved[0] & flags))
+			if (!(current_thread_info()->fpsaved[0] & flags))
 				rs1 = (argp)&zero;
 			break;
 		}
@@ -344,13 +344,13 @@
 		freg = (insn & 0x1f);
 		switch ((type >> 3) & 0x3) {
 		case 3: if (freg & 2) {
-				current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+				current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */;
 				goto err;
 			}
 		case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
 		case 1: rs2 = (argp)&f->regs[freg];
 			flags = (freg < 32) ? FPRS_DL : FPRS_DU; 
-			if (!(current->thread.fpsaved[0] & flags))
+			if (!(current_thread_info()->fpsaved[0] & flags))
 				rs2 = (argp)&zero;
 			break;
 		}
@@ -362,23 +362,23 @@
 		freg = ((insn >> 25) & 0x1f);
 		switch ((type >> 6) & 0x3) {
 		case 3: if (freg & 2) {
-				current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+				current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */;
 				goto err;
 			}
 		case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
 		case 1: rd = (argp)&f->regs[freg];
 			flags = (freg < 32) ? FPRS_DL : FPRS_DU; 
-			if (!(current->thread.fpsaved[0] & FPRS_FEF)) {
-				current->thread.fpsaved[0] = FPRS_FEF;
-				current->thread.gsr[0] = 0;
+			if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) {
+				current_thread_info()->fpsaved[0] = FPRS_FEF;
+				current_thread_info()->gsr[0] = 0;
 			}
-			if (!(current->thread.fpsaved[0] & flags)) {
+			if (!(current_thread_info()->fpsaved[0] & flags)) {
 				if (freg < 32)
 					memset(f->regs, 0, 32*sizeof(u32));
 				else
 					memset(f->regs+32, 0, 32*sizeof(u32));
 			}
-			current->thread.fpsaved[0] |= flags;
+			current_thread_info()->fpsaved[0] |= flags;
 			break;
 		}
 		switch ((insn >> 5) & 0x1ff) {
@@ -439,7 +439,7 @@
 		}
 		if (!FP_INHIBIT_RESULTS) {
 			switch ((type >> 6) & 0x7) {
-			case 0: xfsr = current->thread.xfsr[0];
+			case 0: xfsr = current_thread_info()->xfsr[0];
 				if (XR == -1) XR = 2;
 				switch (freg & 3) {
 				/* fcc0, 1, 2, 3 */
@@ -448,7 +448,7 @@
 				case 2: xfsr &= ~0xc00000000UL; xfsr |= (XR << 34); break;
 				case 3: xfsr &= ~0x3000000000UL; xfsr |= (XR << 36); break;
 				}
-				current->thread.xfsr[0] = xfsr;
+				current_thread_info()->xfsr[0] = xfsr;
 				break;
 			case 1: rd->s = IR; break;
 			case 2: rd->d = XR; break;
@@ -458,11 +458,11 @@
 			}
 		}
 
-		if(_fex != 0)
+		if (_fex != 0)
 			return record_exception(regs, _fex);
 
 		/* Success and no exceptions detected. */
-		current->thread.xfsr[0] &= ~(FSR_CEXC_MASK);
+		current_thread_info()->xfsr[0] &= ~(FSR_CEXC_MASK);
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
 		return 1;
diff -Nru a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
--- a/arch/sparc64/mm/fault.c	Sun Feb 10 19:58:06 2002
+++ b/arch/sparc64/mm/fault.c	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.58 2001/09/01 00:11:16 kanoj Exp $
+/* $Id: fault.c,v 1.59 2002/02/09 19:49:31 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -287,8 +287,8 @@
 	unsigned long address;
 
 	si_code = SEGV_MAPERR;
-	fault_code = current->thread.fault_code;
-	address = current->thread.fault_address;
+	fault_code = get_thread_fault_code();
+	address = current_thread_info()->fault_address;
 
 	if ((fault_code & FAULT_CODE_ITLB) &&
 	    (fault_code & FAULT_CODE_DTLB))
@@ -301,7 +301,7 @@
 	if (in_interrupt() || !mm)
 		goto intr_or_no_mm;
 
-	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
+	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		address &= 0xffffffff;
 	}
@@ -358,7 +358,7 @@
 		if (tlb_type == spitfire &&
 		    (vma->vm_flags & VM_EXEC) != 0 &&
 		    vma->vm_file != NULL)
-			current->thread.use_blkcommit = 1;
+			set_thread_flag(TIF_BLKCOMMIT);
 	} else {
 		/* Allow reads even for write-only mappings */
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
@@ -426,7 +426,7 @@
 
 fault_done:
 	/* These values are no longer needed, clear them. */
-	current->thread.fault_code = 0;
-	current->thread.use_blkcommit = 0;
-	current->thread.fault_address = 0;
+	set_thread_fault_code(0);
+	clear_thread_flag(TIF_BLKCOMMIT);
+	current_thread_info()->fault_address = 0;
 }
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/mm/init.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.208 2001/12/21 04:56:15 davem Exp $
+/*  $Id: init.c,v 1.209 2002/02/09 19:49:31 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -111,8 +111,6 @@
         return freed;
 }
 
-extern void __update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-
 #ifdef CONFIG_DEBUG_DCFLUSH
 atomic_t dcpage_flushes = ATOMIC_INIT(0);
 #ifdef CONFIG_SMP
@@ -181,6 +179,8 @@
 			     : "g5", "g7");
 }
 
+extern void __update_mmu_cache(unsigned long mmu_context_hw, unsigned long address, pte_t pte, int code);
+
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
 	struct page *page = pte_page(pte);
@@ -201,7 +201,9 @@
 
 		clear_dcache_dirty_cpu(page, cpu);
 	}
-	__update_mmu_cache(vma, address, pte);
+	if (get_thread_fault_code())
+		__update_mmu_cache(vma->vm_mm->context & TAG_CONTEXT_BITS,
+				   address, pte, get_thread_fault_code());
 }
 
 void flush_dcache_page(struct page *page)
@@ -706,7 +708,7 @@
 	int i;
 
 	if (!enter)
-		set_fs(current->thread.current_ds);
+		set_fs((mm_segment_t) { get_thread_current_ds() });
 
 	if (!prom_ditlb_set)
 		return;
diff -Nru a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
--- a/arch/sparc64/mm/ultra.S	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/mm/ultra.S	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.71 2002/01/23 11:27:36 davem Exp $
+/* $Id: ultra.S,v 1.72 2002/02/09 19:49:31 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com)
@@ -391,8 +391,8 @@
 	rdpr		%pstate, %g7
 	wrpr		%g7, PSTATE_IE, %pstate
 	mov		TLB_TAG_ACCESS, %g1
-	stxa		%o0, [%g1] ASI_DMMU
-	stxa		%o1, [%g0] ASI_DTLB_DATA_IN
+	stxa		%o5, [%g1] ASI_DMMU
+	stxa		%o2, [%g0] ASI_DTLB_DATA_IN
 	flush		%g6
 	retl
 	 wrpr		%g7, %pstate
@@ -400,28 +400,20 @@
 	rdpr		%pstate, %g7
 	wrpr		%g7, PSTATE_IE, %pstate
 	mov		TLB_TAG_ACCESS, %g1
-	stxa		%o0, [%g1] ASI_IMMU
-	stxa		%o1, [%g0] ASI_ITLB_DATA_IN
+	stxa		%o5, [%g1] ASI_IMMU
+	stxa		%o2, [%g0] ASI_ITLB_DATA_IN
 	flush		%g6
 	retl
 	 wrpr		%g7, %pstate
 
 	.globl		__update_mmu_cache
-__update_mmu_cache:	/* %o0=vma, %o1=address, %o2=pte */
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_fault_code], %o3
+__update_mmu_cache:	/* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */
 	srlx		%o1, PAGE_SHIFT, %o1
-	ldx		[%o0 + 0x0], %o4		/* XXX vma->vm_mm */
-	brz,pn		%o3, 1f
-	 sllx		%o1, PAGE_SHIFT, %o0
-	ldx		[%o4 + AOFF_mm_context], %o5
 	andcc		%o3, FAULT_CODE_DTLB, %g0
-	mov		%o2, %o1
-	and		%o5, TAG_CONTEXT_BITS, %o5
+	sllx		%o1, PAGE_SHIFT, %o5
 	bne,pt		%xcc, __prefill_dtlb
-	 or		%o0, %o5, %o0
+	 or		%o5, %o0, %o5
 	ba,a,pt		%xcc, __prefill_itlb
-1:	retl
-	 nop
 
 #ifdef CONFIG_SMP
 	/* These are all called by the slaves of a cross call, at
@@ -501,8 +493,8 @@
 109:	 or		%g7, %lo(109b), %g7
 	call		__show_regs
 	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
-	b,pt		%xcc, rtrap
-	 clr		%l6
+	b,pt		%xcc, rtrap_irq
+	 nop
 
 	.align		32
 	.globl		xcall_flush_dcache_page_cheetah
@@ -562,8 +554,8 @@
 109:	 or		%g7, %lo(109b), %g7
 	call		smp_penguin_jailcell
 	 nop
-	b,pt		%xcc, rtrap
-	 clr		%l6
+	b,pt		%xcc, rtrap_irq
+	 nop
 
 	.globl		xcall_promstop
 xcall_promstop:
@@ -689,8 +681,8 @@
 109:	 or		%g7, %lo(109b), %g7
 	call		smp_call_function_client
 	 nop
-	b,pt		%xcc, rtrap
-	 clr		%l6
+	b,pt		%xcc, rtrap_irq
+	 nop
 
 	.globl		xcall_migrate_task
 xcall_migrate_task:
diff -Nru a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S
--- a/arch/sparc64/solaris/entry64.S	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/solaris/entry64.S	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: entry64.S,v 1.6 2000/01/12 02:59:26 davem Exp $
+/* $Id: entry64.S,v 1.7 2002/02/09 19:49:31 davem Exp $
  * entry64.S:  Solaris syscall emulation entry point.
  *
  * Copyright (C) 1996,1997,1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
@@ -68,9 +68,11 @@
 
 	/* Solaris system calls enter here... */
 	.align	32
-	.globl	solaris_sparc_syscall
+	.globl	solaris_sparc_syscall, entry64_personality_patch
 solaris_sparc_syscall:
-	ldub		[%g6 + AOFF_task_personality + ASIZ_task_personality - 1], %l0
+	ldx		[%g6 + TI_TASK], %l0
+entry64_personality_patch:
+	ldub		[%l0 + 0x0], %l0
 	cmp		%g1, 255
 	bg,pn		%icc, solaris_unimplemented
 	 srl		%g1, 0, %g1
@@ -83,7 +85,7 @@
 1:	 srl		%i0, 0, %o0
 	lduw		[%l7 + %l4], %l3
 	srl		%i1, 0, %o1
-	ldx		[%g6 + AOFF_task_flags], %l5
+	ldx		[%g6 + TI_FLAGS], %l5
 	cmp		%l3, NR_SYSCALLS
 	bleu,a,pn	%xcc, linux_syscall_for_solaris
 	 sethi		%hi(sys_call_table32), %l6
@@ -93,21 +95,21 @@
 10:	srl		%i2, 0, %o2
 	mov		%i5, %o5
 	andn		%l3, 3, %l7
-	andcc		%l5, 0x20, %g0				
+	andcc		%l5, _TIF_SYSCALL_TRACE, %g0				
 	bne,pn		%icc, solaris_syscall_trace		
 	 mov		%i0, %l5
 2:	call		%l7
 	 srl		%i3, 0, %o3
 ret_from_solaris:
 	stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
-	ldx		[%g6 + AOFF_task_flags], %l6
+	ldx		[%g6 + TI_FLAGS], %l6
 	sra		%o0, 0, %o0
 	mov		%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
 	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
 	cmp		%o0, -ENOIOCTLCMD
 	sllx		%g2, 32, %g2
 	bgeu,pn		%xcc, 1f
-	 andcc		%l6, 0x20, %l6	
+	 andcc		%l6, _TIF_SYSCALL_TRACE, %l6	
 
 	/* System call success, clear Carry condition code. */
 	andn		%g3, %g2, %g3
@@ -175,25 +177,30 @@
 
 	.globl		solaris_getpid
 solaris_getpid:
-	call		sys_getppid	/* This is tricky, so don't do it in assembly */
+	call		sys_getppid
 	 nop
-	stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+	call		sys_getpid
+	 stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
 	b,pt		%xcc, ret_from_solaris
-	 lduw		[%g6 + AOFF_task_pid], %o0
+	 nop
 
 	.globl	solaris_getuid
 solaris_getuid:
-	lduw		[%g6 + AOFF_task_euid], %o1
-	lduw		[%g6 + AOFF_task_uid], %o0
-	b,pt		%xcc, ret_from_solaris
+	call		sys_geteuid
+	 nop
+	call		sys_getuid
 	 stx		%o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+	b,pt		%xcc, ret_from_solaris
+	 nop
 
 	.globl	solaris_getgid
 solaris_getgid:
-	lduw		[%g6 + AOFF_task_egid], %o1
-	lduw		[%g6 + AOFF_task_gid], %o0
-	b,pt		%xcc, ret_from_solaris
+	call		sys_getegid
+	 nop
+	call		sys_getgid
 	 stx		%o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+	b,pt		%xcc, ret_from_solaris
+	 nop
 
 	.globl		solaris_unimplemented
 solaris_unimplemented:
diff -Nru a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
--- a/arch/sparc64/solaris/fs.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/solaris/fs.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: fs.c,v 1.26 2002/01/08 16:00:21 davem Exp $
+/* $Id: fs.c,v 1.27 2002/02/08 03:57:14 davem Exp $
  * fs.c: fs related syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -79,47 +79,49 @@
 
 #define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
 
-static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
+static inline int putstat(struct sol_stat *ubuf, struct kstat *kbuf)
 {
-	if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev)	||
-	    __put_user (kbuf->st_ino, &ubuf->st_ino)		||
-	    __put_user (kbuf->st_mode, &ubuf->st_mode)		||
-	    __put_user (kbuf->st_nlink, &ubuf->st_nlink)	||
-	    __put_user (kbuf->st_uid, &ubuf->st_uid)		||
-	    __put_user (kbuf->st_gid, &ubuf->st_gid)		||
-	    __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev)	||
-	    __put_user (kbuf->st_size, &ubuf->st_size)		||
-	    __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec)	||
+	if (kbuf->size > MAX_NON_LFS)
+		return -EOVERFLOW;
+	if (put_user (R4_DEV(kbuf->dev), &ubuf->st_dev)	||
+	    __put_user (kbuf->ino, &ubuf->st_ino)		||
+	    __put_user (kbuf->mode, &ubuf->st_mode)		||
+	    __put_user (kbuf->nlink, &ubuf->st_nlink)	||
+	    __put_user (kbuf->uid, &ubuf->st_uid)		||
+	    __put_user (kbuf->gid, &ubuf->st_gid)		||
+	    __put_user (R4_DEV(kbuf->rdev), &ubuf->st_rdev)	||
+	    __put_user (kbuf->size, &ubuf->st_size)		||
+	    __put_user (kbuf->atime, &ubuf->st_atime.tv_sec)	||
 	    __put_user (0, &ubuf->st_atime.tv_nsec)		||
-	    __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec)	||
+	    __put_user (kbuf->mtime, &ubuf->st_mtime.tv_sec)	||
 	    __put_user (0, &ubuf->st_mtime.tv_nsec)		||
-	    __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec)	||
+	    __put_user (kbuf->ctime, &ubuf->st_ctime.tv_sec)	||
 	    __put_user (0, &ubuf->st_ctime.tv_nsec)		||
-	    __put_user (kbuf->st_blksize, &ubuf->st_blksize)	||
-	    __put_user (kbuf->st_blocks, &ubuf->st_blocks)	||
+	    __put_user (kbuf->blksize, &ubuf->st_blksize)	||
+	    __put_user (kbuf->blocks, &ubuf->st_blocks)	||
 	    __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
 		return -EFAULT;
 	return 0;
 }
 
-static inline int putstat64(struct sol_stat64 *ubuf, struct stat *kbuf)
+static inline int putstat64(struct sol_stat64 *ubuf, struct kstat *kbuf)
 {
-	if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev)	||
-	    __put_user (kbuf->st_ino, &ubuf->st_ino)		||
-	    __put_user (kbuf->st_mode, &ubuf->st_mode)		||
-	    __put_user (kbuf->st_nlink, &ubuf->st_nlink)	||
-	    __put_user (kbuf->st_uid, &ubuf->st_uid)		||
-	    __put_user (kbuf->st_gid, &ubuf->st_gid)		||
-	    __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev)	||
-	    __put_user (kbuf->st_size, &ubuf->st_size)		||
-	    __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec)	||
+	if (put_user (R4_DEV(kbuf->dev), &ubuf->st_dev)	||
+	    __put_user (kbuf->ino, &ubuf->st_ino)		||
+	    __put_user (kbuf->mode, &ubuf->st_mode)		||
+	    __put_user (kbuf->nlink, &ubuf->st_nlink)	||
+	    __put_user (kbuf->uid, &ubuf->st_uid)		||
+	    __put_user (kbuf->gid, &ubuf->st_gid)		||
+	    __put_user (R4_DEV(kbuf->rdev), &ubuf->st_rdev)	||
+	    __put_user (kbuf->size, &ubuf->st_size)		||
+	    __put_user (kbuf->atime, &ubuf->st_atime.tv_sec)	||
 	    __put_user (0, &ubuf->st_atime.tv_nsec)		||
-	    __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec)	||
+	    __put_user (kbuf->mtime, &ubuf->st_mtime.tv_sec)	||
 	    __put_user (0, &ubuf->st_mtime.tv_nsec)		||
-	    __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec)	||
+	    __put_user (kbuf->ctime, &ubuf->st_ctime.tv_sec)	||
 	    __put_user (0, &ubuf->st_ctime.tv_nsec)		||
-	    __put_user (kbuf->st_blksize, &ubuf->st_blksize)	||
-	    __put_user (kbuf->st_blocks, &ubuf->st_blocks)	||
+	    __put_user (kbuf->blksize, &ubuf->st_blksize)	||
+	    __put_user (kbuf->blocks, &ubuf->st_blocks)	||
 	    __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
 		return -EFAULT;
 	return 0;
@@ -128,21 +130,18 @@
 asmlinkage int solaris_stat(u32 filename, u32 statbuf)
 {
 	int ret;
-	struct stat s;
+	struct kstat s;
 	char *filenam;
 	mm_segment_t old_fs = get_fs();
-	int (*sys_newstat)(char *,struct stat *) = 
-		(int (*)(char *,struct stat *))SYS(stat);
 	
 	filenam = getname ((char *)A(filename));
 	ret = PTR_ERR(filenam);
 	if (!IS_ERR(filenam)) {
 		set_fs (KERNEL_DS);
-		ret = sys_newstat(filenam, &s);
+		ret = vfs_stat(filenam, &s);
 		set_fs (old_fs);
 		putname (filenam);
-		if (putstat ((struct sol_stat *)A(statbuf), &s))
-			return -EFAULT;
+		return putstat((struct sol_stat *)A(statbuf), &s);
 	}
 	return ret;
 }
@@ -156,21 +155,18 @@
 asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
 {
 	int ret;
-	struct stat s;
+	struct kstat s;
 	char *filenam;
 	mm_segment_t old_fs = get_fs();
-	int (*sys_newstat)(char *,struct stat *) = 
-		(int (*)(char *,struct stat *))SYS(stat);
 	
 	filenam = getname ((char *)A(filename));
 	ret = PTR_ERR(filenam);
 	if (!IS_ERR(filenam)) {
 		set_fs (KERNEL_DS);
-		ret = sys_newstat(filenam, &s);
+		ret = vfs_stat(filenam, &s);
 		set_fs (old_fs);
 		putname (filenam);
-		if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
-			return -EFAULT;
+		return putstat64((struct sol_stat64 *)A(statbuf), &s);
 	}
 	return ret;
 }
@@ -178,21 +174,18 @@
 asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
 {
 	int ret;
-	struct stat s;
+	struct kstat s;
 	char *filenam;
 	mm_segment_t old_fs = get_fs();
-	int (*sys_newlstat)(char *,struct stat *) = 
-		(int (*)(char *,struct stat *))SYS(lstat);
 	
 	filenam = getname ((char *)A(filename));
 	ret = PTR_ERR(filenam);
 	if (!IS_ERR(filenam)) {
 		set_fs (KERNEL_DS);
-		ret = sys_newlstat(filenam, &s);
+		ret = vfs_lstat(filenam, &s);
 		set_fs (old_fs);
 		putname (filenam);
-		if (putstat ((struct sol_stat *)A(statbuf), &s))
-			return -EFAULT;
+		return putstat((struct sol_stat *)A(statbuf), &s);
 	}
 	return ret;
 }
@@ -205,21 +198,18 @@
 asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
 {
 	int ret;
-	struct stat s;
+	struct kstat s;
 	char *filenam;
 	mm_segment_t old_fs = get_fs();
-	int (*sys_newlstat)(char *,struct stat *) = 
-		(int (*)(char *,struct stat *))SYS(lstat);
 	
 	filenam = getname ((char *)A(filename));
 	ret = PTR_ERR(filenam);
 	if (!IS_ERR(filenam)) {
 		set_fs (KERNEL_DS);
-		ret = sys_newlstat(filenam, &s);
+		ret = vfs_lstat(filenam, &s);
 		set_fs (old_fs);
 		putname (filenam);
-		if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
-			return -EFAULT;
+		return putstat64((struct sol_stat64 *)A(statbuf), &s);
 	}
 	return ret;
 }
@@ -227,16 +217,10 @@
 asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
 {
 	int ret;
-	struct stat s;
-	mm_segment_t old_fs = get_fs();
-	int (*sys_newfstat)(unsigned,struct stat *) = 
-		(int (*)(unsigned,struct stat *))SYS(fstat);
-	
-	set_fs (KERNEL_DS);
-	ret = sys_newfstat(fd, &s);
-	set_fs (old_fs);
-	if (putstat ((struct sol_stat *)A(statbuf), &s))
-		return -EFAULT;
+	struct kstat s;
+	ret = vfs_fstat(fd, &s);
+	if (!ret)
+		return putstat((struct sol_stat *)A(statbuf), &s);
 	return ret;
 }
 
@@ -248,16 +232,11 @@
 asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
 {
 	int ret;
-	struct stat s;
-	mm_segment_t old_fs = get_fs();
-	int (*sys_newfstat)(unsigned,struct stat *) = 
-		(int (*)(unsigned,struct stat *))SYS(fstat);
+	struct kstat s;
 	
-	set_fs (KERNEL_DS);
-	ret = sys_newfstat(fd, &s);
-	set_fs (old_fs);
-	if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
-		return -EFAULT;
+	ret = vfs_fstat(fd, &s);
+	if (!ret)
+		return putstat64((struct sol_stat64 *)A(statbuf), &s);
 	return ret;
 }
 
diff -Nru a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
--- a/arch/sparc64/solaris/ioctl.c	Sun Feb 10 19:58:03 2002
+++ b/arch/sparc64/solaris/ioctl.c	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: ioctl.c,v 1.16 2000/11/18 02:10:59 davem Exp $
+/* $Id: ioctl.c,v 1.17 2002/02/08 03:57:14 davem Exp $
  * ioctl.c: Solaris ioctl emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -308,7 +308,7 @@
 	case 110: /* SI_GETUDATA */
 	{
 		int etsdusize, servtype;
-		switch (ino->u.socket_i.type) {
+		switch (SOCKET_I(ino)->type) {
 		case SOCK_STREAM:
 			etsdusize = 1;
 			servtype = 2;
@@ -326,16 +326,16 @@
 		    __put_user(0, &((struct solaris_si_udata *)A(arg))->so_state) ||
 		    __put_user(0, &((struct solaris_si_udata *)A(arg))->so_options) ||
 		    __put_user(16384, &((struct solaris_si_udata *)A(arg))->tsdusize) ||
-		    __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_family) ||
-		    __put_user(ino->u.socket_i.type, &((struct solaris_si_udata *)A(arg))->sockparams.sp_type) ||
-		    __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_protocol))
+		    __put_user(SOCKET_I(ino)->ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_family) ||
+		    __put_user(SOCKET_I(ino)->type, &((struct solaris_si_udata *)A(arg))->sockparams.sp_type) ||
+		    __put_user(SOCKET_I(ino)->ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_protocol))
 			return (EFAULT << 8) | TSYSERR;
 		return 0;
 	}
 	case 101: /* O_SI_GETUDATA */
 	{
 		int etsdusize, servtype;
-		switch (ino->u.socket_i.type) {
+		switch (SOCKET_I(ino)->type) {
 		case SOCK_STREAM:
 			etsdusize = 1;
 			servtype = 2;
diff -Nru a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
--- a/arch/sparc64/solaris/misc.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/solaris/misc.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.35 2002/01/08 16:00:21 davem Exp $
+/* $Id: misc.c,v 1.36 2002/02/09 19:49:31 davem Exp $
  * misc.c: Miscelaneous syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -739,6 +739,8 @@
 extern u32 solaris_syscall[];
 extern void cleanup_socksys(void);
 
+extern u32 entry64_personality_patch;
+
 int init_module(void)
 {
 	int ret;
@@ -750,6 +752,11 @@
 		return ret;
 	}
 	update_ttable(solaris_sparc_syscall);
+	entry64_personality_patch |=
+		(offsetof(struct task_struct, personality) +
+		 (sizeof(unsigned long) - 1));
+	__asm__ __volatile__("membar #StoreStore; flush %0"
+			     : : "r" (&entry64_personality_patch));
 	return 0;
 }
 
diff -Nru a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
--- a/arch/sparc64/solaris/socket.c	Sun Feb 10 19:58:04 2002
+++ b/arch/sparc64/solaris/socket.c	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: socket.c,v 1.5 2001/02/13 01:16:44 davem Exp $
+/* $Id: socket.c,v 1.6 2002/02/08 03:57:14 davem Exp $
  * socket.c: Socket syscall emulation for Solaris 2.6+
  *
  * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -248,12 +248,6 @@
 					   24 for IPv6,
 					   about 80 for AX.25 */
 
-/* XXX These as well... */
-extern __inline__ struct socket *socki_lookup(struct inode *inode)
-{
-	return &inode->u.socket_i;
-}
-
 extern __inline__ struct socket *sockfd_lookup(int fd, int *err)
 {
 	struct file *file;
@@ -265,13 +259,13 @@
 	}
 
 	inode = file->f_dentry->d_inode;
-	if (!inode->i_sock || !socki_lookup(inode)) {
+	if (!inode->i_sock) {
 		*err = -ENOTSOCK;
 		fput(file);
 		return NULL;
 	}
 
-	return socki_lookup(inode);
+	return SOCKET_I(inode);
 }
 
 extern __inline__ void sockfd_put(struct socket *sock)
diff -Nru a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
--- a/arch/sparc64/solaris/socksys.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/solaris/socksys.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.20 2002/01/08 16:00:21 davem Exp $
+/* $Id: socksys.c,v 1.21 2002/02/08 03:57:14 davem Exp $
  * socksys.c: /dev/inet/ stuff for Solaris emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -6,6 +6,13 @@
  * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
  */
 
+/*
+ *  Dave, _please_ give me specifications on this fscking mess so that I
+ * could at least get it into the state when it wouldn't screw the rest of
+ * the kernel over.  socksys.c and timod.c _stink_ and we are not talking
+ * H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV
+ */
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -86,6 +93,9 @@
 		return fd;
 	/*
 	 * N.B. The following operations are not legal!
+	 *
+	 * No shit.  WTF is it supposed to do, anyway?
+	 *
 	 * Try instead:
 	 * d_delete(filp->f_dentry), then d_instantiate with sock inode
 	 */
@@ -93,7 +103,7 @@
 	filp->f_dentry = dget(fcheck(fd)->f_dentry);
 	filp->f_dentry->d_inode->i_rdev = inode->i_rdev;
 	filp->f_dentry->d_inode->i_flock = inode->i_flock;
-	filp->f_dentry->d_inode->u.socket_i.file = filp;
+	SOCKET_I(filp->f_dentry->d_inode)->file = filp;
 	filp->f_op = &socksys_file_ops;
         sock = (struct sol_socket_struct*) 
         	mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
diff -Nru a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
--- a/arch/sparc64/solaris/timod.c	Sun Feb 10 19:58:05 2002
+++ b/arch/sparc64/solaris/timod.c	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: timod.c,v 1.18 2002/01/08 16:00:21 davem Exp $
+/* $Id: timod.c,v 1.19 2002/02/08 03:57:14 davem Exp $
  * timod.c: timod emulation.
  *
  * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
@@ -149,7 +149,7 @@
 	struct socket *sock;
 
 	SOLD("wakeing socket");
-	sock = &current->files->fd[fd]->f_dentry->d_inode->u.socket_i;
+	sock = SOCKET_I(current->files->fd[fd]->f_dentry->d_inode);
 	wake_up_interruptible(&sock->wait);
 	read_lock(&sock->sk->callback_lock);
 	if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
@@ -640,7 +640,7 @@
 	ino = filp->f_dentry->d_inode;
 	sock = (struct sol_socket_struct *)filp->private_data;
 	SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
-	if ( ctl_maxlen > 0 && !sock->pfirst && ino->u.socket_i.type == SOCK_STREAM
+	if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM
 		&& sock->state == TS_IDLE) {
 		SOLD("calling LISTEN");
 		args[0] = fd;
@@ -730,7 +730,7 @@
 	*flags_p = 0;
 	if (ctl_maxlen >= 0) {
 		SOLD("ACCEPT perhaps?");
-		if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) {
+		if (SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) {
 			struct T_conn_ind ind;
 			char *buf = getpage();
 			int len = BUF_SIZE;
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Sun Feb 10 19:58:05 2002
+++ b/drivers/Makefile	Sun Feb 10 19:58:05 2002
@@ -8,7 +8,7 @@
 
 mod-subdirs :=	dio mtd sbus video macintosh usb input telephony sgi ide \
 		message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
-		fc4 net/hamradio i2c acpi bluetooth
+		fc4 net/hamradio i2c acpi bluetooth input/serio input/gameport
 
 subdir-y :=	base parport char block net sound misc media cdrom hotplug
 subdir-m :=	$(subdir-y)
@@ -27,6 +27,8 @@
 subdir-$(CONFIG_ALL_PPC)	+= macintosh
 subdir-$(CONFIG_USB)		+= usb
 subdir-$(CONFIG_INPUT)		+= input
+subdir-$(CONFIG_SERIO)		+= input/serio
+subdir-$(CONFIG_GAMEPORT)	+= input/gameport
 subdir-$(CONFIG_PHONE)		+= telephony
 subdir-$(CONFIG_SGI)		+= sgi
 subdir-$(CONFIG_IDE)		+= ide
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/base/core.c	Sun Feb 10 19:58:04 2002
@@ -7,7 +7,9 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/err.h>
 
 #undef DEBUG
 
@@ -17,9 +19,9 @@
 # define DBG(x...)
 #endif
 
-static struct iobus device_root = {
-	bus_id: "root",
-	name:	"Logical System Root",
+static struct device device_root = {
+	bus_id:		"root",
+	name:		"System Root",
 };
 
 int (*platform_notify)(struct device * dev) = NULL;
@@ -28,9 +30,6 @@
 extern int device_make_dir(struct device * dev);
 extern void device_remove_dir(struct device * dev);
 
-extern int iobus_make_dir(struct iobus * iobus);
-extern void iobus_remove_dir(struct iobus * iobus);
-
 static spinlock_t device_lock;
 
 /**
@@ -47,19 +46,23 @@
 
 	if (!dev || !strlen(dev->bus_id))
 		return -EINVAL;
-	BUG_ON(!dev->parent);
 
 	spin_lock(&device_lock);
 	INIT_LIST_HEAD(&dev->node);
+	INIT_LIST_HEAD(&dev->children);
 	spin_lock_init(&dev->lock);
 	atomic_set(&dev->refcount,2);
 
-	get_iobus(dev->parent);
-	list_add_tail(&dev->node,&dev->parent->devices);
+	if (dev != &device_root) {
+		if (!dev->parent)
+			dev->parent = &device_root;
+		get_device(dev->parent);
+		list_add_tail(&dev->node,&dev->parent->children);
+	}
 	spin_unlock(&device_lock);
 
-	DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
-	    dev->bus_id, dev->name, parent->bus_id);
+	DBG("DEV: registering device: ID = '%s', name = %s\n",
+	    dev->bus_id, dev->name);
 
 	if ((error = device_make_dir(dev)))
 		goto register_done;
@@ -70,8 +73,8 @@
 
  register_done:
 	put_device(dev);
-	if (error)
-		put_iobus(dev->parent);
+	if (error && dev->parent)
+		put_device(dev->parent);
 	return error;
 }
 
@@ -100,9 +103,6 @@
 	/* remove the driverfs directory */
 	device_remove_dir(dev);
 
-	if (dev->subordinate)
-		iobus_remove_dir(dev->subordinate);
-
 	/* Notify the platform of the removal, in case they
 	 * need to do anything...
 	 */
@@ -116,73 +116,15 @@
 	if (dev->driver && dev->driver->remove)
 		dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
 
-	put_iobus(dev->parent);
-}
-
-int iobus_register(struct iobus *bus)
-{
-	int error;
-
-	if (!bus || !strlen(bus->bus_id))
-		return -EINVAL;
-	
-	spin_lock(&device_lock);
-	atomic_set(&bus->refcount,2);
-	spin_lock_init(&bus->lock);
-	INIT_LIST_HEAD(&bus->node);
-	INIT_LIST_HEAD(&bus->devices);
-	INIT_LIST_HEAD(&bus->children);
-
-	if (bus != &device_root) {
-		if (!bus->parent)
-			bus->parent = &device_root;
-		get_iobus(bus->parent);
-		list_add_tail(&bus->node,&bus->parent->children);
-	}
-	spin_unlock(&device_lock);
-
-	DBG("DEV: registering bus. ID = '%s' name = '%s' parent = %p\n",
-	    bus->bus_id,bus->name,bus->parent);
-
-	error = iobus_make_dir(bus);
-
-	put_iobus(bus);
-	if (error && bus->parent)
-		put_iobus(bus->parent);
-	return error;
-}
-
-/**
- * iobus_unregister - remove bus and children from device tree
- * @bus:	pointer to bus structure
- *
- * Remove device from parent's list of children and decrement
- * reference count on controlling device. That should take care of
- * the rest of the cleanup.
- */
-void put_iobus(struct iobus * iobus)
-{
-	if (!atomic_dec_and_lock(&iobus->refcount,&device_lock))
-		return;
-	list_del_init(&iobus->node);
-	spin_unlock(&device_lock);
-
-	if (!list_empty(&iobus->devices) ||
-	    !list_empty(&iobus->children))
-		BUG();
-
-	put_iobus(iobus->parent);
-	/* unregister itself */
-	put_device(iobus->self);
+	put_device(dev->parent);
 }
 
 static int __init device_init_root(void)
 {
-	/* initialize parent bus lists */
-	return iobus_register(&device_root);
+	return device_register(&device_root);
 }
 
-int __init device_driver_init(void)
+static int __init device_init(void)
 {
 	int error = 0;
 
@@ -197,18 +139,12 @@
 		return error;
 	}
 
-	error = device_init_root();
-	if (error) {
+	if ((error = device_init_root()))
 		printk(KERN_ERR "%s: device root init failed!\n", __FUNCTION__);
-		return error;
-	}
-
-	DBG("DEV: Done Initialising\n");
 	return error;
 }
 
+subsys_initcall(device_init);
+
 EXPORT_SYMBOL(device_register);
 EXPORT_SYMBOL(put_device);
-EXPORT_SYMBOL(iobus_register);
-EXPORT_SYMBOL(put_iobus);
-EXPORT_SYMBOL(device_driver_init);
diff -Nru a/drivers/base/fs.c b/drivers/base/fs.c
--- a/drivers/base/fs.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/base/fs.c	Sun Feb 10 19:58:06 2002
@@ -8,7 +8,9 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/stat.h>
 
 extern struct driver_file_entry * device_default_files[];
 
@@ -102,28 +104,6 @@
 		}
 	}
 	return 0;
-}
-
-void iobus_remove_dir(struct iobus * iobus)
-{
-	if (iobus)
-		driverfs_remove_dir(&iobus->dir);
-}
-
-int iobus_make_dir(struct iobus * iobus)
-{
-	struct driver_dir_entry * parent = NULL;
-	int error;
-
-	INIT_LIST_HEAD(&iobus->dir.files);
-	iobus->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
-	iobus->dir.name = iobus->bus_id;
-
-	if (iobus->parent)
-		parent = &iobus->parent->dir;
-
-	error = driverfs_create_dir(&iobus->dir,parent);
-	return error;
 }
 
 EXPORT_SYMBOL(device_create_file);
diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c
--- a/drivers/base/interface.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/base/interface.c	Sun Feb 10 19:58:04 2002
@@ -6,6 +6,8 @@
  */
 
 #include <linux/device.h>
+#include <linux/err.h>
+#include <linux/stat.h>
 
 /**
  * device_read_status - report some device information
@@ -19,15 +21,7 @@
  */
 static ssize_t device_read_status(struct device * dev, char * page, size_t count, loff_t off)
 {
-	char *str = page;
-
-	if (off)
-		return 0;
-
-	str += sprintf(str,"Name:       %s\n",dev->name);
-	str += sprintf(str,"Bus ID:     %s\n",dev->bus_id);
-
-	return (str - page);
+	return off ? 0 : sprintf(page,"%s\n",dev->bus_id);
 }
 
 /**
@@ -84,17 +78,21 @@
 	store:		device_write_status,
 };
 
-static ssize_t
-device_read_power(struct device * dev, char * page, size_t count, loff_t off)
+static ssize_t device_read_name(struct device * dev, char * buf, size_t count, loff_t off)
 {
-	char	* str = page;
-
-	if (off)
-		return 0;
+	return off ? 0 : sprintf(buf,"%s\n",dev->name);
+}
 
-	str += sprintf(str,"State:      %d\n",dev->current_state);
+static struct driver_file_entry device_name_entry = {
+	name:	"name",
+	mode:	S_IRUGO,
+	show:	device_read_name,
+};
 
-	return (str - page);
+static ssize_t
+device_read_power(struct device * dev, char * page, size_t count, loff_t off)
+{
+	return off ? 0 : sprintf(page,"%d\n",dev->current_state);
 }
 
 static ssize_t
@@ -169,6 +167,7 @@
 
 struct driver_file_entry * device_default_files[] = {
 	&device_status_entry,
+	&device_name_entry,
 	&device_power_entry,
 	NULL,
 };
diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h
--- a/drivers/block/DAC960.h	Sun Feb 10 19:58:06 2002
+++ b/drivers/block/DAC960.h	Sun Feb 10 19:58:06 2002
@@ -2573,39 +2573,7 @@
   spin_unlock_irqrestore(&Controller->RequestQueue->queue_lock, *ProcessorFlags);
 }
 
-
-/*
-  Virtual_to_Bus32 maps from Kernel Virtual Addresses to 32 Bit PCI Bus
-  Addresses.
-*/
-
-static inline DAC960_BusAddress32_T Virtual_to_Bus32(void *VirtualAddress)
-{
-  return (DAC960_BusAddress32_T) virt_to_bus(VirtualAddress);
-}
-
-
-/*
-  Bus32_to_Virtual maps from 32 Bit PCI Bus Addresses to Kernel Virtual
-  Addresses.
-*/
-
-static inline void *Bus32_to_Virtual(DAC960_BusAddress32_T BusAddress)
-{
-  return (void *) bus_to_virt(BusAddress);
-}
-
-
-/*
-  Virtual_to_Bus64 maps from Kernel Virtual Addresses to 64 Bit PCI Bus
-  Addresses.
-*/
-
-static inline DAC960_BusAddress64_T Virtual_to_Bus64(void *VirtualAddress)
-{
-  return (DAC960_BusAddress64_T) virt_to_bus(VirtualAddress);
-}
-
+#error I am a non-portable driver, please convert me to use the Documentation/DMA-mapping.txt interfaces
 
 /*
   Define the DAC960 BA Series Controller Interface Register Offsets.
diff -Nru a/drivers/block/blkpg.c b/drivers/block/blkpg.c
--- a/drivers/block/blkpg.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/block/blkpg.c	Sun Feb 10 19:58:04 2002
@@ -280,7 +280,8 @@
 
 			if (cmd == BLKGETSIZE)
 				return put_user((unsigned long)ullval, (unsigned long *)arg);
-			return put_user(ullval, (u64 *)arg);
+			else
+				return put_user((u64)ullval << 9 , (u64 *)arg);
 #if 0
 		case BLKRRPART: /* Re-read partition tables */
 			if (!capable(CAP_SYS_ADMIN)) 
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/block/nbd.c	Sun Feb 10 19:58:05 2002
@@ -155,14 +155,15 @@
 	unsigned long size = req->nr_sectors << 9;
 
 	DEBUG("NBD: sending control, ");
+	
+	rw = rq_data_dir(req);
+	
 	request.magic = htonl(NBD_REQUEST_MAGIC);
-	request.type = htonl(req->flags);
+	request.type = htonl((rw & WRITE) ? 1 : 0);
 	request.from = cpu_to_be64( (u64) req->sector << 9);
 	request.len = htonl(size);
 	memcpy(request.handle, &req, sizeof(req));
 
-	rw = rq_data_dir(req);
-
 	result = nbd_xmit(1, sock, (char *) &request, sizeof(request), rw & WRITE ? MSG_MORE : 0);
 	if (result <= 0)
 		FAIL("Sendmsg failed for control.");
@@ -417,10 +418,13 @@
 		file = fget(arg);
 		if (file) {
 			inode = file->f_dentry->d_inode;
-			/* N.B. Should verify that it's a socket */
-			lo->file = file;
-			lo->sock = &inode->u.socket_i;
-			error = 0;
+			if (inode->i_sock) {
+				lo->file = file;
+				lo->sock = SOCKET_I(inode);
+				error = 0;
+			} else {
+				fput(file);
+			}
 		}
 		return error;
 	case NBD_SET_BLKSIZE:
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/block/ps2esdi.c	Sun Feb 10 19:58:03 2002
@@ -475,7 +475,7 @@
 	   list + sanity checks.                     */
 	INIT_REQUEST;
 
-	if (virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
+	if (isa_virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
 		printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
 		end_request(FAIL);
 	}			/* check for above 16Mb dmas */
@@ -663,7 +663,7 @@
 
 	mca_disable_dma(dma_arb_level);
 
-	mca_set_dma_addr(dma_arb_level, virt_to_bus(buffer));
+	mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer));
 
 	mca_set_dma_count(dma_arb_level, length * 512 / 2);
 
diff -Nru a/drivers/block/smart1,2.h b/drivers/block/smart1,2.h
--- a/drivers/block/smart1,2.h	Sun Feb 10 19:58:04 2002
+++ b/drivers/block/smart1,2.h	Sun Feb 10 19:58:04 2002
@@ -252,6 +252,7 @@
 
 		outb(CHANNEL_CLEAR, h->ioaddr + SMART1_LOCAL_DOORBELL);
 
+#error Please convert me to Documentation/DMA-mapping.txt
 		if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status;
 	} else {
 		cmd = 0;
diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
--- a/drivers/bluetooth/hci_usb.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/bluetooth/hci_usb.c	Sun Feb 10 19:58:05 2002
@@ -120,11 +120,11 @@
 	DBG("%s", hdev->name);
 
 	husb->read_urb->dev = husb->udev;
-	if ((status = usb_submit_urb(husb->read_urb)))
+	if ((status = usb_submit_urb(husb->read_urb, GFP_KERNEL)))
 		DBG("read submit failed. %d", status);
 
 	husb->intr_urb->dev = husb->udev;
-	if ((status = usb_submit_urb(husb->intr_urb)))
+	if ((status = usb_submit_urb(husb->intr_urb, GFP_KERNEL)))
 		DBG("interrupt submit failed. %d", status);
 
 	hdev->flags |= HCI_RUNNING;
@@ -428,7 +428,7 @@
 
 resubmit:
 	husb->read_urb->dev = husb->udev;
-	if ((status = usb_submit_urb(husb->read_urb)))
+	if ((status = usb_submit_urb(husb->read_urb, GFP_KERNEL)))
 		DBG("%s read URB submit failed %d", husb->hdev.name, status);
 
 	DBG("%s read URB re-submited", husb->hdev.name);
@@ -453,7 +453,7 @@
 	FILL_CONTROL_URB(urb, husb->udev, pipe, (void*)dr, skb->data, skb->len,
 	                 hci_usb_ctrl, skb);
 
-	if ((status = usb_submit_urb(urb))) {
+	if ((status = usb_submit_urb(urb, GFP_KERNEL))) {
 		DBG("%s control URB submit failed %d", husb->hdev.name, status);
 		return status;
 	}
@@ -474,7 +474,7 @@
 	              hci_usb_bulk_write, skb);
 	urb->transfer_flags |= USB_QUEUE_BULK;
 
-	if ((status = usb_submit_urb(urb))) {
+	if ((status = usb_submit_urb(urb, GFP_KERNEL))) {
 		DBG("%s write URB submit failed %d", husb->hdev.name, status);
 		return status;
 	}
diff -Nru a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
--- a/drivers/bluetooth/hci_vhci.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/bluetooth/hci_vhci.c	Sun Feb 10 19:58:06 2002
@@ -221,11 +221,6 @@
 	return ret;
 }
 
-static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-
 static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	return -EINVAL;
@@ -296,7 +291,7 @@
 
 static struct file_operations hci_vhci_fops = {
 	owner:	THIS_MODULE,	
-	llseek:	hci_vhci_chr_lseek,
+	llseek:	no_llseek,
 	read:	hci_vhci_chr_read,
 	write:	hci_vhci_chr_write,
 	poll:	hci_vhci_chr_poll,
diff -Nru a/drivers/char/Config.in b/drivers/char/Config.in
--- a/drivers/char/Config.in	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/Config.in	Sun Feb 10 19:58:05 2002
@@ -127,8 +127,6 @@
 fi
 endmenu
 
-source drivers/char/joystick/Config.in
-
 tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
 if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
    bool '  Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF
@@ -210,7 +208,7 @@
 
 dep_tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP
 if [ "$CONFIG_AGP" != "n" ]; then
-   bool '  Intel 440LX/BX/GX and I815/I830M/I840/I850 support' CONFIG_AGP_INTEL
+   bool '  Intel 440LX/BX/GX and I815/I820/I830M/I840/I845/I850/I860 support' CONFIG_AGP_INTEL
    bool '  Intel I810/I815/I830M (on-board) support' CONFIG_AGP_I810
    bool '  VIA chipset support' CONFIG_AGP_VIA
    bool '  AMD Irongate, 761, and 762 support' CONFIG_AGP_AMD
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/Makefile	Sun Feb 10 19:58:05 2002
@@ -25,7 +25,7 @@
 			misc.o pty.o random.o selection.o serial.o \
 			sonypi.o tty_io.o tty_ioctl.o generic_serial.o
 
-mod-subdirs	:=	joystick ftape drm pcmcia
+mod-subdirs	:=	ftape drm pcmcia
 
 list-multi	:=	
 
@@ -166,15 +166,10 @@
 obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o
 
 subdir-$(CONFIG_RIO) += rio
-subdir-$(CONFIG_INPUT) += joystick
 
 obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o
 obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o
 obj-$(CONFIG_PRINTER) += lp.o
-
-ifeq ($(CONFIG_INPUT),y)
-obj-y += joystick/js.o
-endif
 
 obj-$(CONFIG_BUSMOUSE) += busmouse.o
 obj-$(CONFIG_DTLK) += dtlk.o
diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
--- a/drivers/char/agp/agp.h	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/agp/agp.h	Sun Feb 10 19:58:06 2002
@@ -179,6 +179,9 @@
 #ifndef PCI_DEVICE_ID_INTEL_820_0
 #define PCI_DEVICE_ID_INTEL_820_0       0x2500
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_820_UP_0
+#define PCI_DEVICE_ID_INTEL_820_UP_0    0x2501
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_840_0
 #define PCI_DEVICE_ID_INTEL_840_0		0x1a21
 #endif
@@ -189,7 +192,7 @@
 #define PCI_DEVICE_ID_INTEL_850_0     0x2530
 #endif
 #ifndef PCI_DEVICE_ID_INTEL_860_0
-#define PCI_DEVICE_ID_INTEL_860_0	0x2532
+#define PCI_DEVICE_ID_INTEL_860_0     0x2531
 #endif
 #ifndef PCI_DEVICE_ID_INTEL_810_DC100_0
 #define PCI_DEVICE_ID_INTEL_810_DC100_0 0x7122
@@ -276,6 +279,7 @@
 #define I830_RDRAM_ND(x)           (((x) & 0x20) >> 5)
 #define I830_RDRAM_DDT(x)          (((x) & 0x18) >> 3)
 
+/* This one is for I830MP w. an external graphic card */
 #define INTEL_I830_ERRSTS          0x92
 
 /* intel i820 registers */
diff -Nru a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
--- a/drivers/char/agp/agpgart_be.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/char/agp/agpgart_be.c	Sun Feb 10 19:58:04 2002
@@ -409,8 +409,18 @@
 	 *        AGP devices and collect their data.
 	 */
 
-	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
-					device)) != NULL) {
+
+	pci_for_each_dev(device)
+	{
+		/*
+		 *	Enable AGP devices. Most will be VGA display but
+		 *	some may be coprocessors on non VGA devices too
+		 */
+		 
+		if((((device->class >> 16) & 0xFF) != PCI_BASE_CLASS_DISPLAY) &&
+			(device->class != (PCI_CLASS_PROCESSOR_CO << 8)))
+			continue;
+
 		pci_read_config_dword(device, 0x04, &scratch);
 
 		if (!(scratch & 0x00100000))
@@ -1826,7 +1836,7 @@
        agp_bridge.needs_scratch_page = FALSE;
        agp_bridge.configure = intel_820_configure;
        agp_bridge.fetch_size = intel_8xx_fetch_size;
-       agp_bridge.cleanup = intel_cleanup;
+       agp_bridge.cleanup = intel_820_cleanup;
        agp_bridge.tlb_flush = intel_820_tlbflush;
        agp_bridge.mask_memory = intel_mask_memory;
        agp_bridge.agp_enable = agp_generic_agp_enable;
@@ -1839,6 +1849,9 @@
        agp_bridge.free_by_type = agp_generic_free_by_type;
        agp_bridge.agp_alloc_page = agp_generic_alloc_page;
        agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+       agp_bridge.suspend = agp_generic_suspend;
+       agp_bridge.resume = agp_generic_resume;
+       agp_bridge.cant_use_aperture = 0;
 
        return 0;
 
@@ -1869,6 +1882,9 @@
        agp_bridge.free_by_type = agp_generic_free_by_type;
        agp_bridge.agp_alloc_page = agp_generic_alloc_page;
        agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+       agp_bridge.suspend = agp_generic_suspend;
+       agp_bridge.resume = agp_generic_resume;
+       agp_bridge.cant_use_aperture = 0;
 
        return 0;
 
@@ -2375,7 +2391,7 @@
 
 	agp_bridge.gatt_table_real = page_dir.real;
 	agp_bridge.gatt_table = page_dir.remapped;
-	agp_bridge.gatt_bus_addr = virt_to_bus(page_dir.real);
+	agp_bridge.gatt_bus_addr = virt_to_phys(page_dir.real);
 
 	/* Get the address for the gart region.
 	 * This is a bus address even on the alpha, b/c its
@@ -2389,7 +2405,7 @@
 	/* Calculate the agp offset */
 	for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
 		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] =
-			virt_to_bus(amd_irongate_private.gatt_pages[i]->real);
+			virt_to_phys(amd_irongate_private.gatt_pages[i]->real);
 		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001;
 	}
 
@@ -3011,7 +3027,7 @@
 	for(i = 0; i < 1024; i++) {
 		serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge.scratch_page;
 		page_dir.remapped[i] =
-			virt_to_bus(serverworks_private.scratch_dir.real);
+			virt_to_phys(serverworks_private.scratch_dir.real);
 		page_dir.remapped[i] |= 0x00000001;
 	}
 
@@ -3024,7 +3040,7 @@
 
 	agp_bridge.gatt_table_real = page_dir.real;
 	agp_bridge.gatt_table = page_dir.remapped;
-	agp_bridge.gatt_bus_addr = virt_to_bus(page_dir.real);
+	agp_bridge.gatt_bus_addr = virt_to_phys(page_dir.real);
 
 	/* Get the address for the gart region.
 	 * This is a bus address even on the alpha, b/c its
@@ -3040,7 +3056,7 @@
 
 	for(i = 0; i < value->num_entries / 1024; i++) {
 		page_dir.remapped[i] =
-			virt_to_bus(serverworks_private.gatt_pages[i]->real);
+			virt_to_phys(serverworks_private.gatt_pages[i]->real);
 		page_dir.remapped[i] |= 0x00000001;
 	}
 
@@ -3307,8 +3323,18 @@
 	 *        AGP devices and collect their data.
 	 */
 
-	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
-					device)) != NULL) {
+
+	pci_for_each_dev(device)
+	{
+		/*
+		 *	Enable AGP devices. Most will be VGA display but
+		 *	some may be coprocessors on non VGA devices too
+		 */
+		 
+		if((((device->class >> 16) & 0xFF) != PCI_BASE_CLASS_DISPLAY) &&
+			(device->class != (PCI_CLASS_PROCESSOR_CO << 8)))
+			continue;
+
 		pci_read_config_dword(device, 0x04, &scratch);
 
 		if (!(scratch & 0x00100000))
@@ -3606,6 +3632,12 @@
 		"i815",
 		intel_generic_setup },
 	{ PCI_DEVICE_ID_INTEL_820_0,
+		PCI_VENDOR_ID_INTEL,
+		INTEL_I820,
+		"Intel",
+		"i820",
+		intel_820_setup },
+	{ PCI_DEVICE_ID_INTEL_820_UP_0,
 		PCI_VENDOR_ID_INTEL,
 		INTEL_I820,
 		"Intel",
diff -Nru a/drivers/char/agp/agpgart_fe.c b/drivers/char/agp/agpgart_fe.c
--- a/drivers/char/agp/agpgart_fe.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/char/agp/agpgart_fe.c	Sun Feb 10 19:58:04 2002
@@ -301,7 +301,7 @@
 	agp_memory *memory;
 
 	memory = agp_allocate_memory(pg_count, type);
-   	printk(KERN_DEBUG "memory : %p\n", memory);
+   	printk(KERN_DEBUG "agp_allocate_memory: %p\n", memory);
 	if (memory == NULL) {
 		return NULL;
 	}
diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c
--- a/drivers/char/esp.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/char/esp.c	Sun Feb 10 19:58:03 2002
@@ -392,7 +392,7 @@
         disable_dma(dma);
         clear_dma_ff(dma);
         set_dma_mode(dma, DMA_MODE_READ);
-        set_dma_addr(dma, virt_to_bus(dma_buffer));
+        set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
         set_dma_count(dma, dma_bytes);
         enable_dma(dma);
         release_dma_lock(flags);
@@ -569,7 +569,7 @@
         disable_dma(dma);
         clear_dma_ff(dma);
         set_dma_mode(dma, DMA_MODE_WRITE);
-        set_dma_addr(dma, virt_to_bus(dma_buffer));
+        set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
         set_dma_count(dma, dma_bytes);
         enable_dma(dma);
         release_dma_lock(flags);
@@ -599,7 +599,7 @@
         	disable_dma(dma);
         	clear_dma_ff(dma);
         	set_dma_mode(dma, DMA_MODE_WRITE);
-        	set_dma_addr(dma, virt_to_bus(dma_buffer));
+        	set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
         	set_dma_count(dma, dma_bytes);
         	enable_dma(dma);
         	release_dma_lock(flags);
diff -Nru a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
--- a/drivers/char/ftape/lowlevel/fdc-io.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/ftape/lowlevel/fdc-io.c	Sun Feb 10 19:58:05 2002
@@ -928,18 +928,6 @@
 	set_dma_mode(fdc.dma, mode);
 	set_dma_addr(fdc.dma, virt_to_bus((void*)addr));
 	set_dma_count(fdc.dma, count);
-#ifdef GCC_2_4_5_BUG
-	/*  This seemingly stupid construction confuses the gcc-2.4.5
-	 *  code generator enough to create correct code.
-	 */
-	if (1) {
-		int i;
-		
-		for (i = 0; i < 1; ++i) {
-			ftape_udelay(1);
-		}
-	}
-#endif
 	enable_dma(fdc.dma);
 }
 
diff -Nru a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
--- a/drivers/char/generic_serial.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/generic_serial.c	Sun Feb 10 19:58:06 2002
@@ -143,9 +143,14 @@
 		/* Can't copy more? break out! */
 		if (c <= 0) break;
 		if (from_user)
-			copy_from_user (port->xmit_buf + port->xmit_head, buf, c);
+			if (copy_from_user (port->xmit_buf + port->xmit_head, 
+					    buf, c)) {
+				up (& port->port_write_sem);
+				return -EFAULT;
+			}
+
 		else
-			memcpy         (port->xmit_buf + port->xmit_head, buf, c);
+			memcpy (port->xmit_buf + port->xmit_head, buf, c);
 
 		port -> xmit_cnt += c;
 		port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1);
@@ -604,7 +609,7 @@
 	 * until it's done, and then try again.
 	 */
 	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-	  interruptible_sleep_on(&port->close_wait);
+		interruptible_sleep_on(&port->close_wait);
 		if (port->flags & ASYNC_HUP_NOTIFY)
 			return -EAGAIN;
 		else
@@ -1003,7 +1008,8 @@
 {
 	struct serial_struct sio;
 
-	copy_from_user(&sio, sp, sizeof(struct serial_struct));
+	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
+		return(-EFAULT);
 
 	if (!capable(CAP_SYS_ADMIN)) {
 		if ((sio.baud_base != port->baud_base) ||
@@ -1033,7 +1039,7 @@
  *      Generate the serial struct info.
  */
 
-void gs_getserial(struct gs_port *port, struct serial_struct *sp)
+int gs_getserial(struct gs_port *port, struct serial_struct *sp)
 {
 	struct serial_struct    sio;
 
@@ -1055,7 +1061,10 @@
 	if (port->rd->getserial)
 		port->rd->getserial (port, &sio);
 
-	copy_to_user(sp, &sio, sizeof(struct serial_struct));
+	if (copy_to_user(sp, &sio, sizeof(struct serial_struct)))
+		return -EFAULT;
+	return 0;
+
 }
 
 
diff -Nru a/drivers/char/joystick/Config.help b/drivers/char/joystick/Config.help
--- a/drivers/char/joystick/Config.help	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,300 +0,0 @@
-CONFIG_INPUT_GAMEPORT
-  Gameport support is for the standard 15-pin PC gameport.  If you
-  have a joystick, gamepad, gameport card, a soundcard with a gameport
-  or anything else that uses the gameport, say Y or M here and also to
-  at least one of the hardware specific drivers.
-  Please read the file <file:Documentation/input/joystick.txt> which
-  contains more information and the location of the joystick package
-  that you'll need if you use the gameport with a joystick.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called gameport.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_NS558
-  Say Y here if you have an ISA or PnP gameport.
-  For more information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called ns558.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_LIGHTNING
-  Say Y here if you have a PDPI Lightning 4 gamecard. For more
-  information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called lightning.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_CS461X
-  Say Y here if you have a Cirrus CS461x aka "Crystal SoundFusion"
-  PCI audio accelerator.  A product page for the CS4614 is at
-  <http://www.cirrus.com/design/products/overview/index.cfm?ProductID=40>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called cs461x.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_PCIGAME
-  Say Y here if you have a Trident 4DWave DX/NX or Aureal Vortex 1/2
-  card. For more information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called pcigame.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_EMU10K1
-  Say Y here if you have a SoundBlaster Live! card and want to use
-  its gameport.  For more information on how to use the driver
-  please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called emu10k1-gp.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_ANALOG
-  Say Y here if you have a controller that connects to the PC
-  gameport.  This supports many different types, including joysticks
-  with throttle control, with rudders, or with extensions like
-  additional hats and buttons compatible with CH Flightstick Pro,
-  ThrustMaster FCS, 6 and 8 button gamepads, or Saitek Cyborg
-  joysticks.  For more information on how to use the driver please
-  read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called analog.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_A3D
-  Say Y here if you have an FPGaming or MadCatz controller using the
-  A3D protocol over the PC gameport.  For more information on how to
-  use the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called a3d.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_ADI
-  Say Y here if you have a Logitech controller using the ADI
-  protocol over the PC gameport. For more information on how to use
-  the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called adi.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_COBRA
-  Say Y here if you have a Creative Labs Blaster Cobra gamepad.
-  For more information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called cobra.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_GF2K
-  Say Y here if you have a Genius Flight2000 or MaxFighter digitally
-  communicating joystick or gamepad.  For more information on how to
-  use the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called gf2k.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_GRIP
-  Say Y here if you have a Gravis controller using the GrIP protocol
-  over the PC gameport.  For more information on how to use the driver
-  please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called grip.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_INTERACT
-  Say Y hereif you have an InterAct gameport or joystick
-  communicating digitally over the gameport.  For more information on
-  how to use the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called interact.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_TMDC
-  Say Y here if you have a ThrustMaster controller using the
-  DirectConnect (BSP) protocol over the PC gameport.  For more
-  information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called tmdc.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_SIDEWINDER
-  Say Y here if you have a Microsoft controller using the Digital
-  Overdrive protocol over PC gameport.  For more information on how to
-  use the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called sidewinder.o.  If you want to compile it
-  as a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_SERIO
-  Say Y here and to the Serial port input line discipline option if
-  you plan to use a joystick that communicates over the serial (COM)
-  port.  For more information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called sidewinder.o.  If you want to compile it
-  as a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_SERPORT
-  Say Y here if you plan to use a joystick that communicates over the
-  serial (COM) port.  For more information on how to use the driver
-  please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called serport.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_WARRIOR
-  Say Y here if you have a Logitech WingMan Warrior joystick connected
-  to your computer's serial port.  For more information on how to use
-  the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called warrior.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_MAGELLAN
-  Say Y here if you have a Magellan or Space Mouse 6DOF controller
-  connected to your computer's serial port.  For more information on
-  how to use the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called magellan.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_SPACEORB
-  Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
-  controller connected to your computer's serial port.  For more
-  information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called spaceorb.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_SPACEBALL
-  Say Y here if you have a SpaceTec SpaceBall 4000 FLX controller
-  connected to your computer's serial port.  For more information on
-  how to use the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called spaceball.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_STINGER
-  Say Y here if you have a Gravis Stinger connected to one of your
-  serial ports.  For more information on how to use the driver please
-  read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called stinger.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_IFORCE_232
-  Say Y here if you have an I-Force joystick or steering wheel
-  connected to your serial (COM) port.  For more information on how
-  to use the driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called iforce.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_IFORCE_USB
-  Say Y here if you have an I-Force joystick or steering wheel
-  connected to your USB port.  For more information on how to use the
-  driver please read <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called iforce.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_DB9
-  Say Y here if you have a Sega Master System gamepad, Sega Genesis
-  gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
-  Commodore, Amstrad CPC joystick connected to your parallel port.
-  For more information on how to use the driver please read
-  <file:Documentation/input/joystick.txt> and
-  <file:Documentation/input/joystick-parport.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called db9.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_GAMECON
-  Say Y here if you have a Nintendo Entertainment System gamepad,
-  Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,
-  Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
-  Commodore, Amstrad CPC joystick connected to your parallel port.
-  For more information on how to use the driver please read
-  <file:Documentation/input/joystick.txt> and
-  <file:Documentation/input/joystick-parport.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called gamecon.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_TURBOGRAFX
-  Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
-  and want to use it with Multisystem -- Atari, Amiga, Commodore,
-  Amstrad CPC joystick.  For more information on how to use the driver
-  please read <file:Documentation/input/joystick.txt> and
-  <file:Documentation/input/joystick-parport.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called turbografx.o.  If you want to compile it
-  as a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_INPUT_AMIJOY
-  Say Y here if you have an Amiga with a digital joystick connected
-  to it.  For more information on how to use the driver please read
-  <file:Documentation/input/joystick.txt>.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called joy-amiga.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
diff -Nru a/drivers/char/joystick/Config.in b/drivers/char/joystick/Config.in
--- a/drivers/char/joystick/Config.in	Sun Feb 10 19:58:06 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,53 +0,0 @@
-#
-# Joystick driver configuration
-#
-
-mainmenu_option next_comment
-comment 'Joysticks'
-
-if [ "$CONFIG_INPUT" != "n" ]; then
-   dep_tristate 'Game port support' CONFIG_INPUT_GAMEPORT $CONFIG_INPUT
-      dep_tristate '  Classic ISA/PnP gameports' CONFIG_INPUT_NS558 $CONFIG_INPUT_GAMEPORT
-      dep_tristate '  PDPI Lightning 4 gamecard' CONFIG_INPUT_LIGHTNING $CONFIG_INPUT_GAMEPORT
-      dep_tristate '  Aureal Vortex and Trident 4DWave gameports' CONFIG_INPUT_PCIGAME $CONFIG_INPUT_GAMEPORT
-      dep_tristate '  Crystal SoundFusion gameports' CONFIG_INPUT_CS461X  $CONFIG_INPUT_GAMEPORT
-      dep_tristate '  SoundBlaster Live! gameports' CONFIG_INPUT_EMU10K1 $CONFIG_INPUT_GAMEPORT
-   tristate 'Serial port device support' CONFIG_INPUT_SERIO
-      dep_tristate '  Serial port input line discipline' CONFIG_INPUT_SERPORT $CONFIG_INPUT_SERIO
-else
-   # Must explicitly set to n for drivers/sound/Config.in
-   define_tristate CONFIG_INPUT_GAMEPORT n
-   comment 'Input core support is needed for gameports'
-fi
-
-if [ "$CONFIG_INPUT" != "n" ]; then
-   comment 'Joysticks'
-
-   dep_tristate '  Classic PC analog joysticks and gamepads' CONFIG_INPUT_ANALOG $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  Assasin 3D and MadCatz Panther devices' CONFIG_INPUT_A3D $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  Logitech ADI digital joysticks and gamepads' CONFIG_INPUT_ADI $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  Creative Labs Blaster Cobra gamepad' CONFIG_INPUT_COBRA $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  Genius Flight2000 Digital joysticks and gamepads' CONFIG_INPUT_GF2K $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  Gravis GrIP joysticks and gamepads' CONFIG_INPUT_GRIP $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  InterAct digital joysticks and gamepads' CONFIG_INPUT_INTERACT $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  ThrustMaster DirectConnect joysticks and gamepads' CONFIG_INPUT_TMDC $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  Microsoft SideWinder digital joysticks and gamepads' CONFIG_INPUT_SIDEWINDER $CONFIG_INPUT $CONFIG_INPUT_GAMEPORT
-   dep_tristate '  I-Force USB joysticks and wheels' CONFIG_INPUT_IFORCE_USB $CONFIG_INPUT $CONFIG_USB
-   dep_tristate '  I-Force Serial joysticks and wheels' CONFIG_INPUT_IFORCE_232 $CONFIG_INPUT $CONFIG_INPUT_SERIO
-   dep_tristate '  Logitech WingMan Warrior joystick' CONFIG_INPUT_WARRIOR $CONFIG_INPUT $CONFIG_INPUT_SERIO
-   dep_tristate '  LogiCad3d Magellan/SpaceMouse 6dof controller' CONFIG_INPUT_MAGELLAN $CONFIG_INPUT $CONFIG_INPUT_SERIO
-   dep_tristate '  SpaceTec SpaceOrb/Avenger 6dof controller' CONFIG_INPUT_SPACEORB $CONFIG_INPUT $CONFIG_INPUT_SERIO
-   dep_tristate '  SpaceTec SpaceBall 4000 FLX 6dof controller' CONFIG_INPUT_SPACEBALL $CONFIG_INPUT $CONFIG_INPUT_SERIO
-   dep_tristate '  Gravis Stinger gamepad' CONFIG_INPUT_STINGER $CONFIG_INPUT $CONFIG_INPUT_SERIO
-   dep_tristate '  Multisystem, Sega Genesis, Saturn joysticks and gamepads' CONFIG_INPUT_DB9 $CONFIG_INPUT $CONFIG_PARPORT
-   dep_tristate '  Multisystem, NES, SNES, N64, PSX joysticks and gamepads' CONFIG_INPUT_GAMECON $CONFIG_INPUT $CONFIG_PARPORT
-   dep_tristate '  Multisystem joysticks via TurboGraFX device' CONFIG_INPUT_TURBOGRAFX $CONFIG_INPUT $CONFIG_PARPORT
-
-   if [ "$CONFIG_AMIGA" = "y" ]; then
-      dep_tristate '  Amiga joysticks' CONFIG_INPUT_AMIJOY $CONFIG_INPUT
-   fi
-else
-   comment 'Input core support is needed for joysticks'
-fi
-
-endmenu
diff -Nru a/drivers/char/joystick/Makefile b/drivers/char/joystick/Makefile
--- a/drivers/char/joystick/Makefile	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,70 +0,0 @@
-#
-# Makefile for the joystick drivers.
-#
-
-O_TARGET	:= js.o
-
-# Objects that export symbols.
-
-export-objs	:= serio.o gameport.o
-
-# I-Force may need both USB and RS-232
-
-ifeq ($(CONFIG_INPUT_IFORCE_232),m)
-	ifeq ($(CONFIG_INPUT_IFORCE_USB),y)
-		CONFIG_INPUT_IFORCE_USB := m
-	endif
-endif
-ifeq ($(CONFIG_INPUT_IFORCE_USB),m)
-	ifeq ($(CONFIG_INPUT_IFORCE_232),y)
-		CONFIG_INPUT_IFORCE_232 := m
-	endif
-endif
-
-# Object file lists.
-
-obj-y	:=
-obj-m	:=
-obj-n	:=
-obj-	:=
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_INPUT_GAMEPORT)	+= gameport.o
-obj-$(CONFIG_INPUT_SERIO)	+= serio.o
-
-obj-$(CONFIG_INPUT_SERPORT)	+= serport.o
-
-obj-$(CONFIG_INPUT_NS558)	+= ns558.o
-obj-$(CONFIG_INPUT_LIGHTNING)	+= lightning.o
-obj-$(CONFIG_INPUT_PCIGAME)	+= pcigame.o
-obj-$(CONFIG_INPUT_CS461X)	+= cs461x.o
-obj-$(CONFIG_INPUT_EMU10K1)	+= emu10k1-gp.o
-
-obj-$(CONFIG_INPUT_WARRIOR)	+= warrior.o
-obj-$(CONFIG_INPUT_MAGELLAN)	+= magellan.o
-obj-$(CONFIG_INPUT_SPACEORB)	+= spaceorb.o
-obj-$(CONFIG_INPUT_SPACEBALL)	+= spaceball.o
-obj-$(CONFIG_INPUT_STINGER)	+= stinger.o
-obj-$(CONFIG_INPUT_IFORCE_232)	+= iforce.o
-obj-$(CONFIG_INPUT_IFORCE_USB)	+= iforce.o
-
-obj-$(CONFIG_INPUT_ANALOG)	+= analog.o
-obj-$(CONFIG_INPUT_A3D)		+= a3d.o
-obj-$(CONFIG_INPUT_ADI)		+= adi.o
-obj-$(CONFIG_INPUT_COBRA)	+= cobra.o
-obj-$(CONFIG_INPUT_GF2K)	+= gf2k.o
-obj-$(CONFIG_INPUT_GRIP)	+= grip.o
-obj-$(CONFIG_INPUT_INTERACT)	+= interact.o
-obj-$(CONFIG_INPUT_TMDC)	+= tmdc.o
-obj-$(CONFIG_INPUT_SIDEWINDER)	+= sidewinder.o
-
-obj-$(CONFIG_INPUT_DB9)		+= db9.o
-obj-$(CONFIG_INPUT_GAMECON)	+= gamecon.o
-obj-$(CONFIG_INPUT_TURBOGRAFX)	+= turbografx.o
-
-obj-$(CONFIG_INPUT_AMIJOY)	+= amijoy.o
-
-# The global Rules.make.
-
-include $(TOPDIR)/Rules.make
diff -Nru a/drivers/char/joystick/a3d.c b/drivers/char/joystick/a3d.c
--- a/drivers/char/joystick/a3d.c	Sun Feb 10 19:58:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,388 +0,0 @@
-/*
- * $Id: a3d.c,v 1.14 2001/04/26 10:24:46 vojtech Exp $
- *
- *  Copyright (c) 1998-2001 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * FP-Gaming Assasin 3D joystick driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/input.h>
-
-#define A3D_MAX_START		400	/* 400 us */ 
-#define A3D_MAX_STROBE		60	/* 40 us */ 
-#define A3D_DELAY_READ		3	/* 3 ms */
-#define A3D_MAX_LENGTH		40	/* 40*3 bits */
-#define A3D_REFRESH_TIME	HZ/50	/* 20 ms */
-
-#define A3D_MODE_A3D		1	/* Assassin 3D */
-#define A3D_MODE_PAN		2	/* Panther */
-#define A3D_MODE_OEM		3	/* Panther OEM version */
-#define A3D_MODE_PXL		4	/* Panther XL */
-
-char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
-			"MadCatz Panther XL", "MadCatz Panther XL w/ rudder" };
-
-struct a3d {
-	struct gameport *gameport;
-	struct gameport adc;
-	struct input_dev dev;
-	struct timer_list timer;
-	int axes[4];
-	int buttons;
-	int mode;
-	int length;
-	int used;
-	int reads;
-	int bads;
-};
-
-/*
- * a3d_read_packet() reads an Assassin 3D packet.
- */
-
-static int a3d_read_packet(struct gameport *gameport, int length, char *data)
-{
-	unsigned long flags;
-	unsigned char u, v;
-	unsigned int t, s;
-	int i;
-
-	i = 0;
-	t = gameport_time(gameport, A3D_MAX_START);
-	s = gameport_time(gameport, A3D_MAX_STROBE);
-
-	__save_flags(flags);
-	__cli();
-	gameport_trigger(gameport);
-	v = gameport_read(gameport);
-
-	while (t > 0 && i < length) {
-		t--;
-		u = v; v = gameport_read(gameport);
-		if (~v & u & 0x10) {
-			data[i++] = v >> 5;
-			t = s;
-		}
-	}
-
-	__restore_flags(flags);
-
-	return i;
-}
-
-/*
- * a3d_csum() computes checksum of triplet packet
- */
-
-static int a3d_csum(char *data, int count)
-{
-	int i, csum = 0;
-	for (i = 0; i < count - 2; i++) csum += data[i];
-	return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
-}
-
-static void a3d_read(struct a3d *a3d, unsigned char *data)
-{
-	struct input_dev *dev = &a3d->dev;
-
-	switch (a3d->mode) {
-
-		case A3D_MODE_A3D:
-		case A3D_MODE_OEM:
-		case A3D_MODE_PAN:
-
-			input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7));
-			input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7));
-			
-			input_report_key(dev, BTN_RIGHT,  data[2] & 1);
-			input_report_key(dev, BTN_LEFT,   data[3] & 2);
-			input_report_key(dev, BTN_MIDDLE, data[3] & 4);
-
-			a3d->axes[0] = ((signed char)((data[11] << 6) | (data[12] << 3) | (data[13]))) + 128;
-			a3d->axes[1] = ((signed char)((data[14] << 6) | (data[15] << 3) | (data[16]))) + 128;
-			a3d->axes[2] = ((signed char)((data[17] << 6) | (data[18] << 3) | (data[19]))) + 128;
-			a3d->axes[3] = ((signed char)((data[20] << 6) | (data[21] << 3) | (data[22]))) + 128;
-
-			a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;
-
-			return;
-
-		case A3D_MODE_PXL:
-
-			input_report_rel(dev, REL_X, ((data[ 9] << 6) | (data[10] << 3) | data[11]) - ((data[ 9] & 4) << 7));
-			input_report_rel(dev, REL_Y, ((data[12] << 6) | (data[13] << 3) | data[14]) - ((data[12] & 4) << 7));
-
-			input_report_key(dev, BTN_RIGHT,  data[2] & 1);
-			input_report_key(dev, BTN_LEFT,   data[3] & 2);
-			input_report_key(dev, BTN_MIDDLE, data[3] & 4);
-			input_report_key(dev, BTN_SIDE,   data[7] & 2);
-			input_report_key(dev, BTN_EXTRA,  data[7] & 4);
-
-			input_report_abs(dev, ABS_X,        ((signed char)((data[15] << 6) | (data[16] << 3) | (data[17]))) + 128);
-			input_report_abs(dev, ABS_Y,        ((signed char)((data[18] << 6) | (data[19] << 3) | (data[20]))) + 128);
-			input_report_abs(dev, ABS_RUDDER,   ((signed char)((data[21] << 6) | (data[22] << 3) | (data[23]))) + 128);
-			input_report_abs(dev, ABS_THROTTLE, ((signed char)((data[24] << 6) | (data[25] << 3) | (data[26]))) + 128);
-
-			input_report_abs(dev, ABS_HAT0X, ( data[5]       & 1) - ((data[5] >> 2) & 1));
-			input_report_abs(dev, ABS_HAT0Y, ((data[5] >> 1) & 1) - ((data[6] >> 2) & 1));
-			input_report_abs(dev, ABS_HAT1X, ((data[4] >> 1) & 1) - ( data[3]       & 1));
-			input_report_abs(dev, ABS_HAT1Y, ((data[4] >> 2) & 1) - ( data[4]       & 1));
-
-			input_report_key(dev, BTN_TRIGGER, data[8] & 1);
-			input_report_key(dev, BTN_THUMB,   data[8] & 2);
-			input_report_key(dev, BTN_TOP,     data[8] & 4);
-			input_report_key(dev, BTN_PINKIE,  data[7] & 1);
-
-			return;
-	}
-}
-
-
-/*
- * a3d_timer() reads and analyzes A3D joystick data.
- */
-
-static void a3d_timer(unsigned long private)
-{
-	struct a3d *a3d = (void *) private;
-	unsigned char data[A3D_MAX_LENGTH];
-	a3d->reads++;
-	if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length
-		|| data[0] != a3d->mode || a3d_csum(data, a3d->length))
-	 	a3d->bads++; else a3d_read(a3d, data);
-	mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
-}
-
-/*
- * a3d_adc_cooked_read() copies the acis and button data to the
- * callers arrays. It could do the read itself, but the caller could
- * call this more than 50 times a second, which would use too much CPU.
- */
-
-int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
-{
-	struct a3d *a3d = gameport->private;
-	int i;
-	for (i = 0; i < 4; i++)
-		axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
-	*buttons = a3d->buttons; 
-	return 0;
-}
-
-/*
- * a3d_adc_open() is the gameport open routine. It refuses to serve
- * any but cooked data.
- */
-
-int a3d_adc_open(struct gameport *gameport, int mode)
-{
-	struct a3d *a3d = gameport->private;
-	if (mode != GAMEPORT_MODE_COOKED)
-		return -1;
-	if (!a3d->used++)
-		mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);	
-	return 0;
-}
-
-/*
- * a3d_adc_close() is a callback from the input close routine.
- */
-
-static void a3d_adc_close(struct gameport *gameport)
-{
-	struct a3d *a3d = gameport->private;
-	if (!--a3d->used)
-		del_timer(&a3d->timer);
-}
-
-/*
- * a3d_open() is a callback from the input open routine.
- */
-
-static int a3d_open(struct input_dev *dev)
-{
-	struct a3d *a3d = dev->private;
-	if (!a3d->used++)
-		mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);	
-	return 0;
-}
-
-/*
- * a3d_close() is a callback from the input close routine.
- */
-
-static void a3d_close(struct input_dev *dev)
-{
-	struct a3d *a3d = dev->private;
-	if (!--a3d->used)
-		del_timer(&a3d->timer);
-}
-
-/*
- * a3d_connect() probes for A3D joysticks.
- */
-
-static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct a3d *a3d;
-	unsigned char data[A3D_MAX_LENGTH];
-	int i;
-
-	if (!(a3d = kmalloc(sizeof(struct a3d), GFP_KERNEL)))
-		return;
-	memset(a3d, 0, sizeof(struct a3d));
-
-	gameport->private = a3d;
-
-	a3d->gameport = gameport;
-	init_timer(&a3d->timer);
-	a3d->timer.data = (long) a3d;
-	a3d->timer.function = a3d_timer;
-
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		goto fail1;
-
-	i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);
-
-	if (!i || a3d_csum(data, i))
-		goto fail2;
-
-	a3d->mode = data[0];
-
-	if (!a3d->mode || a3d->mode > 5) {
-		printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
-			"(gameport%d, id=%d), contact <vojtech@suse.cz>\n", gameport->number, a3d->mode);
-		goto fail2;
-	}
-
-
-	if (a3d->mode == A3D_MODE_PXL) {
-
-		int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
-
-		a3d->length = 33;
-
-		a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
-		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
-		a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
-				   | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
-
-		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
-						 | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-
-		a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE);
-
-		a3d_read(a3d, data);
-
-		for (i = 0; i < 4; i++) {
-			if (i < 2) {
-				a3d->dev.absmin[axes[i]] = 48;
-				a3d->dev.absmax[axes[i]] = a3d->dev.abs[axes[i]] * 2 - 48;
-				a3d->dev.absflat[axes[i]] = 8;
-			} else {
-				a3d->dev.absmin[axes[i]] = 2;
-				a3d->dev.absmax[axes[i]] = 253;
-			}
-			a3d->dev.absmin[ABS_HAT0X + i] = -1;
-			a3d->dev.absmax[ABS_HAT0X + i] = 1;
-		}
-
-	} else {
-		a3d->length = 29;
-
-		a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
-		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
-		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
-
-		a3d->adc.private = a3d;
-		a3d->adc.open = a3d_adc_open;
-		a3d->adc.close = a3d_adc_close;
-		a3d->adc.cooked_read = a3d_adc_cooked_read;
-		a3d->adc.fuzz = 1; 
-
-		a3d_read(a3d, data);
-
-		gameport_register_port(&a3d->adc);
-		printk(KERN_INFO "gameport%d: %s on gameport%d.0\n",
-			a3d->adc.number, a3d_names[a3d->mode], gameport->number);
-	}
-
-	a3d->dev.private = a3d;
-	a3d->dev.open = a3d_open;
-	a3d->dev.close = a3d_close;
-
-	a3d->dev.name = a3d_names[a3d->mode];
-	a3d->dev.idbus = BUS_GAMEPORT;
-	a3d->dev.idvendor = GAMEPORT_ID_VENDOR_MADCATZ;
-	a3d->dev.idproduct = a3d->mode;
-	a3d->dev.idversion = 0x0100;
-
-	input_register_device(&a3d->dev);
-	printk(KERN_INFO "input%d: %s on gameport%d.0\n",
-		a3d->dev.number, a3d_names[a3d->mode], gameport->number);
-
-	return;
-fail2:	gameport_close(gameport);
-fail1:  kfree(a3d);
-}
-
-static void a3d_disconnect(struct gameport *gameport)
-{
-
-	struct a3d *a3d = gameport->private;
-	input_unregister_device(&a3d->dev);
-	if (a3d->mode < A3D_MODE_PXL)
-		gameport_unregister_port(&a3d->adc);
-	gameport_close(gameport);
-	kfree(a3d);
-}
-
-static struct gameport_dev a3d_dev = {
-	connect:	a3d_connect,
-	disconnect:	a3d_disconnect,
-};
-
-int __init a3d_init(void)
-{
-	gameport_register_device(&a3d_dev);
-	return 0;
-}
-
-void __exit a3d_exit(void)
-{
-	gameport_unregister_device(&a3d_dev);
-}
-
-module_init(a3d_init);
-module_exit(a3d_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/adi.c b/drivers/char/joystick/adi.c
--- a/drivers/char/joystick/adi.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,557 +0,0 @@
-/*
- * $Id: adi.c,v 1.15 2001/01/09 13:32:39 vojtech Exp $
- *
- *  Copyright (c) 1998-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Logitech ADI joystick family driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/gameport.h>
-#include <linux/init.h>
-
-/*
- * Times, array sizes, flags, ids.
- */
-
-#define ADI_MAX_START		200	/* Trigger to packet timeout [200us] */
-#define ADI_MAX_STROBE		40	/* Single bit timeout [40us] */
-#define ADI_REFRESH_TIME	HZ/50	/* How often to poll the joystick [20 ms] */
-#define ADI_INIT_DELAY		10	/* Delay after init packet [10ms] */
-#define ADI_DATA_DELAY		4	/* Delay after data packet [4ms] */
-
-#define ADI_MAX_LENGTH		256
-#define ADI_MIN_LENGTH		8
-#define ADI_MIN_LEN_LENGTH	10
-#define ADI_MIN_ID_LENGTH	66
-#define ADI_MAX_NAME_LENGTH	48
-#define ADI_MAX_CNAME_LENGTH	16
-
-#define ADI_FLAG_HAT		0x04
-#define ADI_FLAG_10BIT		0x08
-
-#define ADI_ID_TPD		0x01
-#define ADI_ID_WGP		0x06
-#define ADI_ID_WGPE		0x08
-#define ADI_ID_MAX		0x0a
-
-/*
- * Names, buttons, axes ...
- */
-
-static char *adi_names[] = {	"WingMan Extreme Digital", "ThunderPad Digital", "SideCar", "CyberMan 2",
-				"WingMan Interceptor", "WingMan Formula", "WingMan GamePad", 
-				"WingMan Extreme Digital 3D", "WingMan GamePad Extreme", 
-				"WingMan GamePad USB", "Unknown Device %#x" };
-
-static char adi_wmgpe_abs[] =	{ ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y };
-static char adi_wmi_abs[] =	{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
-static char adi_wmed3d_abs[] =	{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RZ, ABS_HAT0X, ABS_HAT0Y };
-static char adi_cm2_abs[] =	{ ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-static char adi_wmf_abs[] =	{ ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
-
-static short adi_wmgpe_key[] =	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z,  BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT };
-static short adi_wmi_key[] = 	{ BTN_TRIGGER,  BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA };
-static short adi_wmed3d_key[] =	{ BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 };
-static short adi_cm2_key[] =	{ BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
-
-static char* adi_abs[] = { adi_wmi_abs, adi_wmgpe_abs, adi_wmf_abs, adi_cm2_abs, adi_wmi_abs, adi_wmf_abs,
-			   adi_wmgpe_abs, adi_wmed3d_abs, adi_wmgpe_abs, adi_wmgpe_abs, adi_wmi_abs };
-
-static short* adi_key[] = { adi_wmi_key, adi_wmgpe_key, adi_cm2_key, adi_cm2_key, adi_wmi_key, adi_cm2_key,
-			    adi_wmgpe_key, adi_wmed3d_key, adi_wmgpe_key, adi_wmgpe_key, adi_wmi_key };
-
-/*
- * Hat to axis conversion arrays.
- */
-
-static struct {
-	int x;
-	int y;
-} adi_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
-
-/*
- * Per-port information.
- */
-
-struct adi {
-	struct input_dev dev;
-	int length;
-	int ret;
-	int idx;
-	unsigned char id;
-	char buttons;
-	char axes10;
-	char axes8;
-	signed char pad;
-	char hats;
-	char *abs;
-	short *key;
-	char name[ADI_MAX_NAME_LENGTH];
-	char cname[ADI_MAX_CNAME_LENGTH];
-	unsigned char data[ADI_MAX_LENGTH];
-};
-
-struct adi_port {
-	struct gameport *gameport;
-	struct timer_list timer;
-	struct adi adi[2];
-	int bad;
-	int reads;
-	int used;
-};
-
-/*
- * adi_read_packet() reads a Logitech ADI packet.
- */
-
-static void adi_read_packet(struct adi_port *port)
-{
-	struct adi *adi = port->adi;
-	struct gameport *gameport = port->gameport;
-	unsigned char u, v, w, x, z;
-	int t[2], s[2], i;
-	unsigned long flags;
-
-	for (i = 0; i < 2; i++) {
-		adi[i].ret = -1;
-		t[i] = gameport_time(gameport, ADI_MAX_START);
-		s[i] = 0;
-	}
-
-	__save_flags(flags);
-	__cli();
-
-	gameport_trigger(gameport);
-	v = z = gameport_read(gameport);
-
-	do {
-		u = v;
-		w = u ^ (v = x = gameport_read(gameport));
-		for (i = 0; i < 2; i++, w >>= 2, x >>= 2) {
-			t[i]--;
-			if ((w & 0x30) && s[i]) {
-				if ((w & 0x30) < 0x30 && adi[i].ret < ADI_MAX_LENGTH && t[i] > 0) {
-					adi[i].data[++adi[i].ret] = w;
-					t[i] = gameport_time(gameport, ADI_MAX_STROBE);
-				} else t[i] = 0;
-			} else if (!(x & 0x30)) s[i] = 1;
-		}
-	} while (t[0] > 0 || t[1] > 0);
-
-	__restore_flags(flags);
-
-	return;
-}
-
-/*
- * adi_move_bits() detects a possible 2-stream mode, and moves
- * the bits accordingly. 
- */
-
-static void adi_move_bits(struct adi_port *port, int length)
-{
-	int i;
-	struct adi *adi = port->adi;
-
- 	adi[0].idx = adi[1].idx = 0;
-
-	if (adi[0].ret <= 0 || adi[1].ret <= 0) return;
-	if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return;
-
-	for (i = 1; i <= adi[1].ret; i++)
-		adi[0].data[((length - 1) >> 1) + i + 1] = adi[1].data[i];
-
-	adi[0].ret += adi[1].ret;
-	adi[1].ret = -1;
-}
-
-/*
- * adi_get_bits() gathers bits from the data packet.
- */
-
-static inline int adi_get_bits(struct adi *adi, int count)
-{
-	int bits = 0;
-	int i;
-	if ((adi->idx += count) > adi->ret) return 0;
-	for (i = 0; i < count; i++)
-		bits |= ((adi->data[adi->idx - i] >> 5) & 1) << i; 
-	return bits;
-}
-
-/*
- * adi_decode() decodes Logitech joystick data into input events.
- */
-
-static int adi_decode(struct adi *adi)
-{
-	struct input_dev *dev = &adi->dev;
-	char *abs = adi->abs;
-	short *key = adi->key;
-	int i, t;
-
-	if (adi->ret < adi->length || adi->id != (adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4)))
-		return -1;	
-
-	for (i = 0; i < adi->axes10; i++) 
-		input_report_abs(dev, *abs++, adi_get_bits(adi, 10));
-
-	for (i = 0; i < adi->axes8; i++) 
-		input_report_abs(dev, *abs++, adi_get_bits(adi, 8));
-
-	for (i = 0; i < adi->buttons && i < 63; i++) {
-		if (i == adi->pad) {
-			t = adi_get_bits(adi, 4);
-			input_report_abs(dev, *abs++, ((t >> 2) & 1) - ( t       & 1));
-			input_report_abs(dev, *abs++, ((t >> 1) & 1) - ((t >> 3) & 1));
-		}
-		input_report_key(dev, *key++, adi_get_bits(adi, 1));
-	}
-
-	for (i = 0; i < adi->hats; i++) {
-		if ((t = adi_get_bits(adi, 4)) > 8) t = 0;
-		input_report_abs(dev, *abs++, adi_hat_to_axis[t].x);
-		input_report_abs(dev, *abs++, adi_hat_to_axis[t].y);
-	}
-
-	for (i = 63; i < adi->buttons; i++)
-		input_report_key(dev, *key++, adi_get_bits(adi, 1));
-
-	return 0;
-}
-
-/*
- * adi_read() reads the data packet and decodes it.
- */
-
-static int adi_read(struct adi_port *port)
-{
-	int i;
-	int result = 0;
-
-	adi_read_packet(port);
-	adi_move_bits(port, port->adi[0].length);
-
-	for (i = 0; i < 2; i++)
-		if (port->adi[i].length)
-			 result |= adi_decode(port->adi + i);
-
-	return result;
-}
-
-/*
- * adi_timer() repeatedly polls the Logitech joysticks.
- */
-
-static void adi_timer(unsigned long data)
-{
-	struct adi_port *port = (void *) data;
-	port->bad -= adi_read(port);
-	port->reads++;
-	mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);
-}
-
-/*
- * adi_open() is a callback from the input open routine.
- */
-
-static int adi_open(struct input_dev *dev)
-{
-	struct adi_port *port = dev->private;
-	if (!port->used++)
-		mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);	
-	return 0;
-}
-
-/*
- * adi_close() is a callback from the input close routine.
- */
-
-static void adi_close(struct input_dev *dev)
-{
-	struct adi_port *port = dev->private;
-	if (!--port->used)
-		del_timer(&port->timer);
-}
-
-/*
- * adi_init_digital() sends a trigger & delay sequence
- * to reset and initialize a Logitech joystick into digital mode.
- */
-
-static void adi_init_digital(struct gameport *gameport)
-{
-	int seq[] = { 3, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
-	int i;
-
-	for (i = 0; seq[i]; i++) {
-		gameport_trigger(gameport);
-		if (seq[i] > 0) wait_ms(seq[i]);
-		if (seq[i] < 0) mdelay(-seq[i]);
-	}
-}
-
-static void adi_id_decode(struct adi *adi, struct adi_port *port)
-{
-	int i, t;
-
-	if (adi->ret < ADI_MIN_ID_LENGTH) /* Minimum ID packet length */
-		return;
-
-	if (adi->ret < (t = adi_get_bits(adi, 10))) {
-		printk(KERN_WARNING "adi: Short ID packet: reported: %d != read: %d\n", t, adi->ret); 
-		return;
-	}
-
-	adi->id = adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4);
-
-	if ((t = adi_get_bits(adi, 4)) & ADI_FLAG_HAT) adi->hats++;
-
-	adi->length = adi_get_bits(adi, 10);
-
-	if (adi->length >= ADI_MAX_LENGTH || adi->length < ADI_MIN_LENGTH) {
-		printk(KERN_WARNING "adi: Bad data packet length (%d).\n", adi->length);
-		adi->length = 0;
-		return;
-	}
-
-	adi->axes8 = adi_get_bits(adi, 4);
-	adi->buttons = adi_get_bits(adi, 6);
-
-	if (adi_get_bits(adi, 6) != 8 && adi->hats) {
-		printk(KERN_WARNING "adi: Other than 8-dir POVs not supported yet.\n");
-		adi->length = 0;
-		return;
-	}
-
-	adi->buttons += adi_get_bits(adi, 6);
-	adi->hats += adi_get_bits(adi, 4);
-
-	i = adi_get_bits(adi, 4);
-
-	if (t & ADI_FLAG_10BIT) {
-		adi->axes10 = adi->axes8 - i;
-		adi->axes8 = i;
-	}
-
-	t = adi_get_bits(adi, 4);
-
-	for (i = 0; i < t; i++)
-		adi->cname[i] = adi_get_bits(adi, 8);
-	adi->cname[i] = 0;
-
-	t = 8 + adi->buttons + adi->axes10 * 10 + adi->axes8 * 8 + adi->hats * 4;
-	if (adi->length != t && adi->length != t + (t & 1)) {
-		printk(KERN_WARNING "adi: Expected length %d != data length %d\n", t, adi->length);
-		adi->length = 0;
-		return;
-	}
-
-	switch (adi->id) {
-		case ADI_ID_TPD:
-			adi->pad = 4;
-			adi->buttons -= 4;
-			break;
-		case ADI_ID_WGP:
-			adi->pad = 0;
-			adi->buttons -= 4;
-			break;
-		default:
-			adi->pad = -1;
-			break;
-	}
-}
-
-static void adi_init_input(struct adi *adi, struct adi_port *port)
-{
-	int i, t;
-	char buf[ADI_MAX_NAME_LENGTH];
-
-	if (!adi->length) return;
-
-	t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
-
-	sprintf(buf, adi_names[t], adi->id);
-	sprintf(adi->name, "Logitech %s", buf);
-
-	adi->abs = adi_abs[t];
-	adi->key = adi_key[t];
-
-	adi->dev.open = adi_open;
-	adi->dev.close = adi_close;
-
-	adi->dev.name = adi->name;
-	adi->dev.idbus = BUS_GAMEPORT;
-	adi->dev.idvendor = GAMEPORT_ID_VENDOR_LOGITECH;
-	adi->dev.idproduct = adi->id;
-	adi->dev.idversion = 0x0100;
-
-	adi->dev.private = port;
-	adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++)
-		set_bit(adi->abs[i], &adi->dev.absbit);
-
-	for (i = 0; i < adi->buttons; i++)
-		set_bit(adi->key[i], &adi->dev.keybit);
-}
-
-static void adi_init_center(struct adi *adi)
-{
-	int i, t, x;
-
-	if (!adi->length) return;
-
-	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++) {
-
-		t = adi->abs[i];
-		x = adi->dev.abs[t];
-
-		if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) {
-			if (i < adi->axes10) x = 512; else x = 128;
-		}
-
-		if (i < adi->axes10) {
-			adi->dev.absmax[t] = x * 2 - 64;
-			adi->dev.absmin[t] = 64;
-			adi->dev.absfuzz[t] = 2;
-			adi->dev.absflat[t] = 16;
-			continue;
-		}
-
-		if (i < adi->axes10 + adi->axes8) {
-			adi->dev.absmax[t] = x * 2 - 48;
-			adi->dev.absmin[t] = 48;
-			adi->dev.absfuzz[t] = 1;
-			adi->dev.absflat[t] = 16;
-			continue;
-		}
-
-		adi->dev.absmax[t] = 1;
-		adi->dev.absmin[t] = -1;
-	}
-}
-
-/*
- * adi_connect() probes for Logitech ADI joysticks.
- */
-
-static void adi_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct adi_port *port;
-	int i;
-
-	if (!(port = kmalloc(sizeof(struct adi_port), GFP_KERNEL)))
-		return;
-	memset(port, 0, sizeof(struct adi_port));
-
-	gameport->private = port;
-
-	port->gameport = gameport;
-	init_timer(&port->timer);
-	port->timer.data = (long) port;
-	port->timer.function = adi_timer;
-
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
-		kfree(port);
-		return;
-	}
-
-	adi_init_digital(gameport);
-	adi_read_packet(port);
-	
-	if (port->adi[0].ret >= ADI_MIN_LEN_LENGTH)
-		adi_move_bits(port, adi_get_bits(port->adi, 10));
-
-	for (i = 0; i < 2; i++) {
-		adi_id_decode(port->adi + i, port);
-		adi_init_input(port->adi + i, port);
-	}
-
-	if (!port->adi[0].length && !port->adi[1].length) {
-		gameport_close(gameport);
-		kfree(port);
-		return;
-	}
-
-	wait_ms(ADI_INIT_DELAY);
-	if (adi_read(port)) {
-		wait_ms(ADI_DATA_DELAY);
-		adi_read(port);
-	}
-
-	for (i = 0; i < 2; i++)
-		if (port->adi[i].length > 0) {
-			adi_init_center(port->adi + i);
-			input_register_device(&port->adi[i].dev);
-			printk(KERN_INFO "input%d: %s [%s] on gameport%d.%d\n",
-				port->adi[i].dev.number, port->adi[i].name, port->adi[i].cname, gameport->number, i);
-		}
-}
-
-static void adi_disconnect(struct gameport *gameport)
-{
-	int i;
-
-	struct adi_port *port = gameport->private;
-	for (i = 0; i < 2; i++)
-		if (port->adi[i].length > 0)
-			input_unregister_device(&port->adi[i].dev);
-	gameport_close(gameport);
-	kfree(port);
-}
-
-/*
- * The gameport device structure.
- */
-
-static struct gameport_dev adi_dev = {
-	connect:	adi_connect,
-	disconnect:	adi_disconnect,
-};
-
-int __init adi_init(void)
-{
-	gameport_register_device(&adi_dev);
-	return 0;
-}
-
-void __exit adi_exit(void)
-{
-	gameport_unregister_device(&adi_dev);
-}
-
-module_init(adi_init);
-module_exit(adi_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/amijoy.c b/drivers/char/joystick/amijoy.c
--- a/drivers/char/joystick/amijoy.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,161 +0,0 @@
-/*
- * $Id: amijoy.c,v 1.5 2000/07/21 22:52:24 vojtech Exp $
- *
- *  Copyright (c) 1998-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Driver for Amiga joysticks for Linux/m68k
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-
-#include <asm/system.h>
-#include <asm/amigahw.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_PARM(amijoy, "1-2i");
-MODULE_LICENSE("GPL");
-
-static int amijoy[2] = { 0, 1 };
-static int amijoy_used[2] = { 0, 0 };
-static struct input_dev amijoy_dev[2];
-
-static char *amijoy_name = "Amiga joystick";
-
-static void amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
-{
-	int i, data = 0, button = 0;
-
-	for (i = 0; i < 2; i++)
-		if (amijoy[i]) {
-
-			switch (i) {
-				case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
-				case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
-			}
-
-			input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
-
-			input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1);
-			data = ~(data ^ (data << 1));
-			input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1);
-		}
-}
-
-static int amijoy_open(struct input_dev *dev)
-{
-	int *used = dev->private;
-
-	if ((*used)++)
-		return 0;
-	
-	if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", NULL)) {
-		(*used)--;
-		printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", amijoy_irq);
-		return -EBUSY;
-	}
-		
-	return 0;
-}
-
-static void amijoy_close(struct input_dev *dev)
-{
-	int *used = dev->private;
-
-	if (!--(*used))
-		free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
-}
-
-static int __init amijoy_setup(char *str)
-{
-	int i;
-	int ints[4]
-        str = get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) amijoy[i] = ints[i+1];
-	return 1;
-}
-__setup("amijoy=", amijoy_setup);
-
-static int __init amijoy_init(void)
-{
-	int i, j;
-
-	init_timer(amijoy_timer);
-	port->timer.function = amijoy_timer;
-
-	for (i = 0; i < 2; i++)
-		if (amijoy[i]) {
-			if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
-						"amijoy [Denise]")) {
-				if (i == 1 && amijoy[0]) {
-					input_unregister_device(amijoy_dev);
-					release_mem_region(CUSTOM_PHYSADDR+10, 2);
-				}
-				return -EBUSY;
-			}
-
-			amijoy_dev[i].open = amijoy_open;
-			amijoy_dev[i].close = amijoy_close;
-			amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-			amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-			amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-			for (j = 0; j < 2; j++) {
-				amijoy_dev[i].absmin[ABS_X + j] = -1;
-				amijoy_dev[i].absmax[ABS_X + j] = 1;
-			}
-
-			amijoy->dev[i].name = amijoy_name;
-			amijoy->dev[i].idbus = BUS_AMIGA;
-			amijoy->dev[i].idvendor = 0x0001;
-			amijoy->dev[i].idproduct = 0x0003;
-			amijoy->dev[i].version = 0x0100;
-
-			amijoy_dev[i].private = amijoy_used + i;
-
-			input_register_device(amijoy_dev + i);
-			printk(KERN_INFO "input%d: %s at joy%ddat\n", amijoy_dev[i].number, amijoy_name, i);
-		}
-	return 0;
-}
-
-static void _exit amijoy_exit(void)
-{
-	int i;
-
-	for (i = 0; i < 2; i++)
-		if (amijoy[i]) {
-			input_unregister_device(amijoy_dev + i);
-			release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
-		}
-}
-
-module_init(amijoy_init);
-module_exit(amijoy_exit);
diff -Nru a/drivers/char/joystick/analog.c b/drivers/char/joystick/analog.c
--- a/drivers/char/joystick/analog.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,761 +0,0 @@
-/*
- * $Id: analog.c,v 1.52 2000/06/07 13:07:06 vojtech Exp $
- *
- *  Copyright (c) 1996-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Analog joystick and gamepad driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/gameport.h>
-#include <asm/timex.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Analog joystick and gamepad driver for Linux");
-MODULE_LICENSE("GPL");
-
-/*
- * Option parsing.
- */
-
-#define ANALOG_PORTS		16
-
-static char *js[ANALOG_PORTS];
-static int analog_options[ANALOG_PORTS];
-MODULE_PARM(js, "1-" __MODULE_STRING(ANALOG_PORTS) "s");
-MODULE_PARM_DESC(js, "Analog joystick options");
-
-/*
- * Times, feature definitions.
- */
-
-#define ANALOG_RUDDER		0x00004
-#define ANALOG_THROTTLE		0x00008
-#define ANALOG_AXES_STD		0x0000f
-#define ANALOG_BTNS_STD		0x000f0
-
-#define ANALOG_BTNS_CHF		0x00100
-#define ANALOG_HAT1_CHF		0x00200
-#define ANALOG_HAT2_CHF		0x00400
-#define ANALOG_HAT_FCS		0x00800
-#define ANALOG_HATS_ALL		0x00e00
-#define ANALOG_BTN_TL		0x01000
-#define ANALOG_BTN_TR		0x02000
-#define ANALOG_BTN_TL2		0x04000
-#define ANALOG_BTN_TR2		0x08000
-#define ANALOG_BTNS_TLR		0x03000
-#define ANALOG_BTNS_TLR2	0x0c000
-#define ANALOG_BTNS_GAMEPAD	0x0f000
-
-#define ANALOG_HBTN_CHF		0x10000
-#define ANALOG_ANY_CHF		0x10700
-#define ANALOG_SAITEK		0x20000
-#define ANALOG_EXTENSIONS	0x7ff00
-#define ANALOG_GAMEPAD		0x80000
-
-#define ANALOG_MAX_TIME		3	/* 3 ms */
-#define ANALOG_LOOP_TIME	2000	/* 2 * loop */
-#define ANALOG_REFRESH_TIME	HZ/100	/* 10 ms */
-#define ANALOG_SAITEK_DELAY	200	/* 200 us */
-#define ANALOG_SAITEK_TIME	2000	/* 2000 us */
-#define ANALOG_AXIS_TIME	2	/* 2 * refresh */
-#define ANALOG_INIT_RETRIES	8	/* 8 times */
-#define ANALOG_FUZZ_BITS	2	/* 2 bit more */
-#define ANALOG_FUZZ_MAGIC	36	/* 36 u*ms/loop */
-
-#define ANALOG_MAX_NAME_LENGTH  128
-
-static short analog_axes[] = { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE };
-static short analog_hats[] = { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
-static short analog_pads[] = { BTN_Y, BTN_Z, BTN_TL, BTN_TR };
-static short analog_exts[] = { ANALOG_HAT1_CHF, ANALOG_HAT2_CHF, ANALOG_HAT_FCS };
-static short analog_pad_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_TL2, BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_BASE };
-static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2,
-				  BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_BASE6 };
-
-static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
-
-struct analog {
-	struct input_dev dev;
-	int mask;
-	short *buttons;
-	char name[ANALOG_MAX_NAME_LENGTH];
-};
-
-struct analog_port {
-	struct gameport *gameport;
-	struct timer_list timer;
-	struct analog analog[2];
-	unsigned char mask;
-	char saitek;
-	char cooked;
-	int bads;
-	int reads;
-	int speed;
-	int loop;
-	int fuzz;
-	int axes[4];
-	int buttons;
-	int initial[4];
-	int used;
-	int axtime;
-};
-
-/*
- * Time macros.
- */
-
-#ifdef __i386__
-#define TSC_PRESENT	(test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability))
-#define GET_TIME(x)	do { if (TSC_PRESENT) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } } while (0)
-#define DELTA(x,y)	(TSC_PRESENT?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
-#define TIME_NAME	(TSC_PRESENT?"TSC":"PIT")
-#elif __x86_64__
-#define GET_TIME(x)	rdtscl(x)
-#define DELTA(x,y)	((y)-(x))
-#define TIME_NAME	"TSC"
-#elif __alpha__
-#define GET_TIME(x)	((x) = get_cycles())
-#define DELTA(x,y)	((y)-(x))
-#define TIME_NAME	"PCC"
-#else
-#define FAKE_TIME
-static unsigned long analog_faketime = 0;
-#define GET_TIME(x)     do { x = analog_faketime++; } while(0)
-#define DELTA(x,y)	((y)-(x))
-#define TIME_NAME	"Unreliable"
-#warning Precise timer not defined for this architecture.
-#endif
-
-/*
- * analog_decode() decodes analog joystick data and reports input events.
- */
-
-static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
-{
-	struct input_dev *dev = &analog->dev;
-	int i, j;
-
-	if (analog->mask & ANALOG_HAT_FCS)
-		for (i = 0; i < 4; i++)
-			if (axes[3] < ((initial[3] * ((i << 1) + 1)) >> 3)) {
-				buttons |= 1 << (i + 14);
-				break;
-			}
-
-	for (i = j = 0; i < 6; i++)
-		if (analog->mask & (0x10 << i))
-			input_report_key(dev, analog->buttons[j++], (buttons >> i) & 1);
-
-	if (analog->mask & ANALOG_HBTN_CHF)
-		for (i = 0; i < 4; i++)
-			input_report_key(dev, analog->buttons[j++], (buttons >> (i + 10)) & 1);
-
-	if (analog->mask & ANALOG_BTN_TL)
-		input_report_key(dev, analog_pads[0], axes[2] < (initial[2] >> 1));
-	if (analog->mask & ANALOG_BTN_TR)
-		input_report_key(dev, analog_pads[1], axes[3] < (initial[3] >> 1));
-	if (analog->mask & ANALOG_BTN_TL2)
-		input_report_key(dev, analog_pads[2], axes[2] > (initial[2] + (initial[2] >> 1)));
-	if (analog->mask & ANALOG_BTN_TR2)
-		input_report_key(dev, analog_pads[3], axes[3] > (initial[3] + (initial[3] >> 1)));
-
-	for (i = j = 0; i < 4; i++)
-		if (analog->mask & (1 << i))
-			input_report_abs(dev, analog_axes[j++], axes[i]);
-
-	for (i = j = 0; i < 3; i++)
-		if (analog->mask & analog_exts[i]) {
-			input_report_abs(dev, analog_hats[j++],
-				((buttons >> ((i << 2) + 7)) & 1) - ((buttons >> ((i << 2) + 9)) & 1));
-			input_report_abs(dev, analog_hats[j++],
-				((buttons >> ((i << 2) + 8)) & 1) - ((buttons >> ((i << 2) + 6)) & 1));
-		}
-}
-
-/*
- * analog_cooked_read() reads analog joystick data.
- */
-
-static int analog_cooked_read(struct analog_port *port)
-{
-	struct gameport *gameport = port->gameport;
-	unsigned int time[4], start, loop, now, loopout, timeout;
-	unsigned char data[4], this, last;
-	unsigned long flags;
-	int i, j;
-
-	loopout = (ANALOG_LOOP_TIME * port->loop) / 1000;
-	timeout = ANALOG_MAX_TIME * port->speed;
-	
-	__save_flags(flags);
-	__cli();
-	gameport_trigger(gameport);
-	GET_TIME(now);
-	__restore_flags(flags);
-
-	start = now;
-	this = port->mask;
-	i = 0;
-
-	do {
-		loop = now;
-		last = this;
-
-		__cli();
-		this = gameport_read(gameport) & port->mask;
-		GET_TIME(now);
-		__restore_flags(flags);
-
-		if ((last ^ this) && (DELTA(loop, now) < loopout)) {
-			data[i] = last ^ this;
-			time[i] = now;
-			i++;
-		}
-
-	} while (this && (i < 4) && (DELTA(start, now) < timeout));
-
-	this <<= 4;
-
-	for (--i; i >= 0; i--) {
-		this |= data[i];
-		for (j = 0; j < 4; j++)
-			if (data[i] & (1 << j))
-				port->axes[j] = (DELTA(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop;
-	}
-
-	return -(this != port->mask);
-}
-
-static int analog_button_read(struct analog_port *port, char saitek, char chf)
-{
-	unsigned char u;
-	int t = 1, i = 0;
-	int strobe = gameport_time(port->gameport, ANALOG_SAITEK_TIME);
-
-	u = gameport_read(port->gameport);
-
-	if (!chf) { 
-		port->buttons = (~u >> 4) & 0xf;
-		return 0;
-	}
-
-	port->buttons = 0;
-
-	while ((~u & 0xf0) && (i < 16) && t) {
-		port->buttons |= 1 << analog_chf[(~u >> 4) & 0xf];
-		if (!saitek) return 0;
-		udelay(ANALOG_SAITEK_DELAY);
-		t = strobe;
-		gameport_trigger(port->gameport);
-		while (((u = gameport_read(port->gameport)) & port->mask) && t) t--;
-		i++;
-	}
-
-	return -(!t || (i == 16));
-}
-
-/*
- * analog_timer() repeatedly polls the Analog joysticks.
- */
-
-static void analog_timer(unsigned long data)
-{
-	struct analog_port *port = (void *) data;
-	int i;
-
-	char saitek = !!(port->analog[0].mask & ANALOG_SAITEK);
-	char chf = !!(port->analog[0].mask & ANALOG_ANY_CHF);
-
-	if (port->cooked) {
-		port->bads -= gameport_cooked_read(port->gameport, port->axes, &port->buttons);
-		if (chf)
-			port->buttons = port->buttons ? (1 << analog_chf[port->buttons]) : 0;
-		port->reads++;
-	} else {
-		if (!port->axtime--) {
-			port->bads -= analog_cooked_read(port);
-			port->bads -= analog_button_read(port, saitek, chf);
-			port->reads++;
-			port->axtime = ANALOG_AXIS_TIME - 1;
-		} else {
-			if (!saitek)
-				analog_button_read(port, saitek, chf);
-		}
-	}
-
-	for (i = 0; i < 2; i++) 
-		if (port->analog[i].mask)
-			analog_decode(port->analog + i, port->axes, port->initial, port->buttons);
-
-	mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);
-}
-
-/*
- * analog_open() is a callback from the input open routine.
- */
-
-static int analog_open(struct input_dev *dev)
-{
-	struct analog_port *port = dev->private;
-	if (!port->used++)
-		mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);	
-	return 0;
-}
-
-/*
- * analog_close() is a callback from the input close routine.
- */
-
-static void analog_close(struct input_dev *dev)
-{
-	struct analog_port *port = dev->private;
-	if (!--port->used)
-		del_timer(&port->timer);
-}
-
-/*
- * analog_calibrate_timer() calibrates the timer and computes loop
- * and timeout values for a joystick port.
- */
-
-static void analog_calibrate_timer(struct analog_port *port)
-{
-	struct gameport *gameport = port->gameport;
-	unsigned int i, t, tx, t1, t2, t3;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	GET_TIME(t1);
-#ifdef FAKE_TIME
-	analog_faketime += 830;
-#endif
-	udelay(1000);
-	GET_TIME(t2);
-	GET_TIME(t3);
-	restore_flags(flags);
-
-	port->speed = DELTA(t1, t2) - DELTA(t2, t3);
-
-	tx = ~0;
-
-	for (i = 0; i < 50; i++) {
-		save_flags(flags);
-		cli();
-		GET_TIME(t1);
-		for (t = 0; t < 50; t++) { gameport_read(gameport); GET_TIME(t2); }
-		GET_TIME(t3);
-		restore_flags(flags);
-		udelay(i);
-		t = DELTA(t1, t2) - DELTA(t2, t3);
-		if (t < tx) tx = t;
-	}
-
-        port->loop = tx / 50;
-}
-
-/*
- * analog_name() constructs a name for an analog joystick.
- */
-
-static void analog_name(struct analog *analog)
-{
-	sprintf(analog->name, "Analog %d-axis %d-button", 
-		hweight8(analog->mask & ANALOG_AXES_STD),
-		hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
-		hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
-
-	if (analog->mask & ANALOG_HATS_ALL)
-		sprintf(analog->name, "%s %d-hat",
-			analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));
-
-	if (analog->mask & ANALOG_HAT_FCS)
-			strcat(analog->name, " FCS");
-	if (analog->mask & ANALOG_ANY_CHF)
-			strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF");
-
-	strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick");
-}
-
-/*
- * analog_init_device()
- */
-
-static void analog_init_device(struct analog_port *port, struct analog *analog, int index)
-{
-	int i, j, t, v, w, x, y, z;
-
-	analog_name(analog);
-
-	analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
-
-	analog->dev.name = analog->name;
-	analog->dev.idbus = BUS_GAMEPORT;
-	analog->dev.idvendor = GAMEPORT_ID_VENDOR_ANALOG;
-	analog->dev.idproduct = analog->mask >> 4;
-	analog->dev.idversion = 0x0100;
-
-	analog->dev.open = analog_open;
-	analog->dev.close = analog_close;
-	analog->dev.private = port;
-	analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	
-	for (i = j = 0; i < 4; i++)
-		if (analog->mask & (1 << i)) {
-			
-			t = analog_axes[j];
-			x = port->axes[i];
-			y = (port->axes[0] + port->axes[1]) >> 1;
-			z = y - port->axes[i];
-			z = z > 0 ? z : -z;
-			v = (x >> 3);
-			w = (x >> 3);
-
-			set_bit(t, analog->dev.absbit);
-
-			if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
-				x = y;
-
-			if (analog->mask & ANALOG_SAITEK) {
-				if (i == 2) x = port->axes[i];
-				v = x - (x >> 2);
-				w = (x >> 4);
-			}
-
-			analog->dev.absmax[t] = (x << 1) - v;
-			analog->dev.absmin[t] = v;
-			analog->dev.absfuzz[t] = port->fuzz;
-			analog->dev.absflat[t] = w;
-
-			j++;
-		}
-
-	for (i = j = 0; i < 3; i++) 
-		if (analog->mask & analog_exts[i]) 
-			for (x = 0; x < 2; x++) {
-				t = analog_hats[j++];
-				set_bit(t, analog->dev.absbit);
-				analog->dev.absmax[t] = 1;
-				analog->dev.absmin[t] = -1;
-			}
-
-	for (i = j = 0; i < 4; i++)
-		if (analog->mask & (0x10 << i))
-			set_bit(analog->buttons[j++], analog->dev.keybit);
-
-	if (analog->mask & ANALOG_BTNS_CHF)
-		for (i = 0; i < 2; i++)
-			set_bit(analog->buttons[j++], analog->dev.keybit);
-
-	if (analog->mask & ANALOG_HBTN_CHF)
-		for (i = 0; i < 4; i++)
-			set_bit(analog->buttons[j++], analog->dev.keybit);
-
-	for (i = 0; i < 4; i++)
-		if (analog->mask & (ANALOG_BTN_TL << i))
-			set_bit(analog_pads[i], analog->dev.keybit);
-
-	analog_decode(analog, port->axes, port->initial, port->buttons);
-
-	input_register_device(&analog->dev);
-
-	printk(KERN_INFO "input%d: %s at gameport%d.%d",
-		analog->dev.number, analog->name, port->gameport->number, index);
-
-	if (port->cooked)
-		printk(" [ADC port]\n");
-	else
-		printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
-		port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
-		port->speed > 10000 ? "M" : "k",
-		port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
-				    : (port->loop * 1000000) / port->speed);
-}
-
-/*
- * analog_init_devices() sets up device-specific values and registers the input devices.
- */
-
-static int analog_init_masks(struct analog_port *port)
-{
-	int i;
-	struct analog *analog = port->analog;
-	int max[4];
-
-	if (!port->mask)
-		return -1;
-
-	if ((port->mask & 3) != 3 && port->mask != 0xc) {
-		printk(KERN_WARNING "analog.c: Unknown joystick device found  "
-			"(data=%#x, gameport%d), probably not analog joystick.\n",
-			port->mask, port->gameport->number);
-		return -1;
-	}
-
-	i = port->gameport->number < ANALOG_PORTS ? analog_options[port->gameport->number] : 0xff;
-
-	analog[0].mask = i & 0xfffff;
-
-	analog[0].mask &= ~(ANALOG_AXES_STD | ANALOG_HAT_FCS | ANALOG_BTNS_GAMEPAD)
-			| port->mask | ((port->mask << 8) & ANALOG_HAT_FCS)
-			| ((port->mask << 10) & ANALOG_BTNS_TLR) | ((port->mask << 12) & ANALOG_BTNS_TLR2);
-
-	analog[0].mask &= ~(ANALOG_HAT2_CHF)
-			| ((analog[0].mask & ANALOG_HBTN_CHF) ? 0 : ANALOG_HAT2_CHF);
-
-	analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_BTN_TR | ANALOG_BTN_TR2)
-			| ((~analog[0].mask & ANALOG_HAT_FCS) >> 8)
-			| ((~analog[0].mask & ANALOG_HAT_FCS) << 2)
-			| ((~analog[0].mask & ANALOG_HAT_FCS) << 4);
-
-	analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_RUDDER)
-			| (((~analog[0].mask & ANALOG_BTNS_TLR ) >> 10)
-			&  ((~analog[0].mask & ANALOG_BTNS_TLR2) >> 12));
-
-	analog[1].mask = ((i >> 20) & 0xff) | ((i >> 12) & 0xf0000);
-
-	analog[1].mask &= (analog[0].mask & ANALOG_EXTENSIONS) ? ANALOG_GAMEPAD
-			: (((ANALOG_BTNS_STD | port->mask) & ~analog[0].mask) | ANALOG_GAMEPAD);
-
-	if (port->cooked) {
-
-		for (i = 0; i < 4; i++) max[i] = port->axes[i] << 1;
-
-		if ((analog[0].mask & 0x7) == 0x7) max[2] = (max[0] + max[1]) >> 1;
-		if ((analog[0].mask & 0xb) == 0xb) max[3] = (max[0] + max[1]) >> 1;
-		if ((analog[0].mask & ANALOG_BTN_TL) && !(analog[0].mask & ANALOG_BTN_TL2)) max[2] >>= 1;
-		if ((analog[0].mask & ANALOG_BTN_TR) && !(analog[0].mask & ANALOG_BTN_TR2)) max[3] >>= 1;
-		if ((analog[0].mask & ANALOG_HAT_FCS)) max[3] >>= 1;
-
-		gameport_calibrate(port->gameport, port->axes, max);
-	}
-		
-	for (i = 0; i < 4; i++) 
-		port->initial[i] = port->axes[i];
-
-	return -!(analog[0].mask || analog[1].mask);	
-}
-
-static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, struct analog_port *port)
-{
-	int i, t, u, v;
-
-	gameport->private = port;
-	port->gameport = gameport;
-	init_timer(&port->timer);
-	port->timer.data = (long) port;
-	port->timer.function = analog_timer;
-
-	if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
-
-		analog_calibrate_timer(port);
-
-		gameport_trigger(gameport);
-		t = gameport_read(gameport);
-		wait_ms(ANALOG_MAX_TIME);
-		port->mask = (gameport_read(gameport) ^ t) & t & 0xf;
-		port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;
-	
-		for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
-			if (!analog_cooked_read(port)) break;
-			wait_ms(ANALOG_MAX_TIME);
-		}
-
-		u = v = 0;
-
-		wait_ms(ANALOG_MAX_TIME);
-		t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
-		gameport_trigger(gameport);
-		while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++; 
-		udelay(ANALOG_SAITEK_DELAY);
-		t = gameport_time(gameport, ANALOG_SAITEK_TIME);
-		gameport_trigger(gameport);
-		while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++; 
-
-		if (v < (u >> 1) && port->gameport->number < ANALOG_PORTS) {
-			analog_options[port->gameport->number] |=
-				ANALOG_SAITEK | ANALOG_BTNS_CHF | ANALOG_HBTN_CHF | ANALOG_HAT1_CHF;
-			return 0;
-		}
-
-		gameport_close(gameport);
-	}
-
-	if (!gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
-
-		for (i = 0; i < ANALOG_INIT_RETRIES; i++)
-			if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
-				break;
-		for (i = 0; i < 4; i++)
-			if (port->axes[i] != -1) port->mask |= 1 << i;
-
-		port->fuzz = gameport->fuzz;
-		port->cooked = 1;
-		return 0;
-	}
-
-	if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		return 0;
-
-	return -1;
-}
-
-static void analog_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct analog_port *port;
-	int i;
-
-	if (!(port = kmalloc(sizeof(struct analog_port), GFP_KERNEL)))
-		return;
-	memset(port, 0, sizeof(struct analog_port));
-
-	if (analog_init_port(gameport, dev, port)) {
-		kfree(port);
-		return;
-	}
-
-	if (analog_init_masks(port)) {
-		gameport_close(gameport);
-		kfree(port);
-		return;
-	}
-
-	for (i = 0; i < 2; i++)
-		if (port->analog[i].mask)
-			analog_init_device(port, port->analog + i, i);
-}
-
-static void analog_disconnect(struct gameport *gameport)
-{
-	int i;
-
-	struct analog_port *port = gameport->private;
-	for (i = 0; i < 2; i++)
-		if (port->analog[i].mask)
-			input_unregister_device(&port->analog[i].dev);
-	gameport_close(gameport);
-	printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on gameport%d failed\n",
-		port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
-		port->gameport->number);
-	kfree(port);
-}
-
-struct analog_types {
-	char *name;
-	int value;
-};
-
-struct analog_types analog_types[] = {
-	{ "none",	0x00000000 },
-	{ "auto",	0x000000ff },
-	{ "2btn",	0x0000003f },
-	{ "y-joy",	0x0cc00033 },
-	{ "y-pad",	0x8cc80033 },
-	{ "fcs",	0x000008f7 },
-	{ "chf",	0x000002ff },
-	{ "fullchf",	0x000007ff },
-	{ "gamepad",	0x000830f3 },
-	{ "gamepad8",	0x0008f0f3 },
-	{ NULL, 0 }
-};
-
-static void analog_parse_options(void)
-{
-	int i, j;
-	char *end;
-
-	for (i = 0; i < ANALOG_PORTS && js[i]; i++) {
-
-		for (j = 0; analog_types[j].name; j++)
-			if (!strcmp(analog_types[j].name, js[i])) {
-				analog_options[i] = analog_types[j].value;
-				break;
-			} 
-		if (analog_types[j].name) continue;
-
-		analog_options[i] = simple_strtoul(js[i], &end, 0);
-		if (end != js[i]) continue;
-
-		analog_options[i] = 0xff;
-		if (!strlen(js[i])) continue;
-
-		printk(KERN_WARNING "analog.c: Bad config for port %d - \"%s\"\n", i, js[i]);
-	}
-
-	for (; i < ANALOG_PORTS; i++)
-		analog_options[i] = 0xff;
-}
-
-/*
- * The gameport device structure.
- */
-
-static struct gameport_dev analog_dev = {
-	connect:	analog_connect,
-	disconnect:	analog_disconnect,
-};
-
-#ifndef MODULE
-static int __init analog_setup(char *str)
-{
-	char *s = str;
-	int i = 0;
-
-	if (!str || !*str) return 0;
-
-	while ((str = s) && (i < ANALOG_PORTS)) {
-		if ((s = strchr(str,','))) *s++ = 0;
-		js[i++] = str;
-	}
-
-	return 1;
-}
-__setup("js=", analog_setup);
-#endif
-
-int __init analog_init(void)
-{
-	analog_parse_options();
-	gameport_register_device(&analog_dev);
-	return 0;
-}
-
-void __exit analog_exit(void)
-{
-	gameport_unregister_device(&analog_dev);
-}
-
-module_init(analog_init);
-module_exit(analog_exit);
diff -Nru a/drivers/char/joystick/cobra.c b/drivers/char/joystick/cobra.c
--- a/drivers/char/joystick/cobra.c	Sun Feb 10 19:58:06 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,252 +0,0 @@
-/*
- * $Id: cobra.c,v 1.10 2000/06/08 10:23:45 vojtech Exp $
- *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Creative Labd Blaster GamePad Cobra driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/input.h>
-
-#define COBRA_MAX_STROBE	45	/* 45 us max wait for first strobe */
-#define COBRA_REFRESH_TIME	HZ/50	/* 20 ms between reads */
-#define COBRA_LENGTH		36
-
-static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
-
-static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };
-
-struct cobra {
-	struct gameport *gameport;
-	struct timer_list timer;
-	struct input_dev dev[2];
-	int used;
-	int reads;
-	int bads;
-	unsigned char exists;
-};
-
-static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *data)
-{
-	unsigned long flags;
-	unsigned char u, v, w;
-	__u64 buf[2];
-	int r[2], t[2];
-	int i, j, ret;
-
-	int strobe = gameport_time(gameport, COBRA_MAX_STROBE);
-
-	for (i = 0; i < 2; i++) {
-		r[i] = buf[i] = 0;
-		t[i] = COBRA_MAX_STROBE;
-	}
-	
-	__save_flags(flags);
-	__cli();
-
-	u = gameport_read(gameport);
-
-	do {
-		t[0]--; t[1]--;
-		v = gameport_read(gameport);
-		for (i = 0, w = u ^ v; i < 2 && w; i++, w >>= 2)
-			if (w & 0x30) {
-				if ((w & 0x30) < 0x30 && r[i] < COBRA_LENGTH && t[i] > 0) {
-					buf[i] |= (__u64)((w >> 5) & 1) << r[i]++;
-					t[i] = strobe;
-					u = v;
-				} else t[i] = 0;
-			}
-	} while (t[0] > 0 || t[1] > 0);
-
-	__restore_flags(flags);
-
-	ret = 0;
-
-	for (i = 0; i < 2; i++) {
-
-		if (r[i] != COBRA_LENGTH) continue;
-
-		for (j = 0; j < COBRA_LENGTH && (buf[i] & 0x04104107f) ^ 0x041041040; j++)
-			buf[i] = (buf[i] >> 1) | ((__u64)(buf[i] & 1) << (COBRA_LENGTH - 1));
-
-		if (j < COBRA_LENGTH) ret |= (1 << i);
-
-		data[i] = ((buf[i] >>  7) & 0x000001f) | ((buf[i] >>  8) & 0x00003e0)
-			| ((buf[i] >>  9) & 0x0007c00) | ((buf[i] >> 10) & 0x00f8000)
-			| ((buf[i] >> 11) & 0x1f00000);
-
-	}
-
-	return ret;
-}
-
-static void cobra_timer(unsigned long private)
-{
-	struct cobra *cobra = (void *) private;
-	struct input_dev *dev;
-	unsigned int data[2];
-	int i, j, r;
-
-	cobra->reads++;
-
-	if ((r = cobra_read_packet(cobra->gameport, data)) != cobra->exists)
-		cobra->bads++;
-
-	for (i = 0; i < 2; i++)
-		if (cobra->exists & r & (1 << i)) {
-
-			dev = cobra->dev + i;
-
-			input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
-			input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
-
-			for (j = 0; cobra_btn[j]; j++)
-				input_report_key(dev, cobra_btn[j], data[i] & (0x20 << j));
-
-		}
-
-	mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);	
-}
-
-static int cobra_open(struct input_dev *dev)
-{
-	struct cobra *cobra = dev->private;
-	if (!cobra->used++)
-		mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);	
-	return 0;
-}
-
-static void cobra_close(struct input_dev *dev)
-{
-	struct cobra *cobra = dev->private;
-	if (!--cobra->used)
-		del_timer(&cobra->timer);
-}
-
-static void cobra_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct cobra *cobra;
-	unsigned int data[2];
-	int i, j;
-
-	if (!(cobra = kmalloc(sizeof(struct cobra), GFP_KERNEL)))
-		return;
-	memset(cobra, 0, sizeof(struct cobra));
-
-	gameport->private = cobra;
-
-	cobra->gameport = gameport;
-	init_timer(&cobra->timer);
-	cobra->timer.data = (long) cobra;
-	cobra->timer.function = cobra_timer;
-
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		goto fail1;
-
-	cobra->exists = cobra_read_packet(gameport, data);
-
-	for (i = 0; i < 2; i++) 
-		if ((cobra->exists >> i) & data[i] & 1) {
-			printk(KERN_WARNING "cobra.c: Device on gameport%d.%d has the Ext bit set. ID is: %d"
-				" Contact vojtech@suse.cz\n", gameport->number, i, (data[i] >> 2) & 7);
-			cobra->exists &= ~(1 << i);
-		}
-
-	if (!cobra->exists)
-		goto fail2;
-
-	for (i = 0; i < 2; i++)
-		if ((cobra->exists >> i) & 1) {
-
-			cobra->dev[i].private = cobra;
-			cobra->dev[i].open = cobra_open;
-			cobra->dev[i].close = cobra_close;
-
-			cobra->dev[i].name = cobra_name;
-			cobra->dev[i].idbus = BUS_GAMEPORT;
-			cobra->dev[i].idvendor = GAMEPORT_ID_VENDOR_CREATIVE;
-			cobra->dev[i].idproduct = 0x0008;
-			cobra->dev[i].idversion = 0x0100;
-		
-			cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-			cobra->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
-			for (j = 0; cobra_btn[j]; j++)
-				set_bit(cobra_btn[j], cobra->dev[i].keybit);
-
-			cobra->dev[i].absmin[ABS_X] = -1; cobra->dev[i].absmax[ABS_X] = 1;
-			cobra->dev[i].absmin[ABS_Y] = -1; cobra->dev[i].absmax[ABS_Y] = 1;
-
-			input_register_device(cobra->dev + i);
-			printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
-				cobra->dev[i].number, cobra_name, gameport->number, i);
-		}
-
-
-	return;
-fail2:	gameport_close(gameport);
-fail1:	kfree(cobra);
-}
-
-static void cobra_disconnect(struct gameport *gameport)
-{
-	int i;
-
-	struct cobra *cobra = gameport->private;
-	for (i = 0; i < 2; i++)
-		if ((cobra->exists >> i) & 1)
-			input_unregister_device(cobra->dev + i);
-	gameport_close(gameport);
-	kfree(cobra);
-}
-
-static struct gameport_dev cobra_dev = {
-	connect:	cobra_connect,
-	disconnect:	cobra_disconnect,
-};
-
-int __init cobra_init(void)
-{
-	gameport_register_device(&cobra_dev);
-	return 0;
-}
-
-void __exit cobra_exit(void)
-{
-	gameport_unregister_device(&cobra_dev);
-}
-
-module_init(cobra_init);
-module_exit(cobra_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/cs461x.c b/drivers/char/joystick/cs461x.c
--- a/drivers/char/joystick/cs461x.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,331 +0,0 @@
-/*
-	The all defines and part of code (such as cs461x_*) are 
-	contributed from ALSA 0.5.8 sources. 
-	See http://www.alsa-project.org/ for sources
-	
-	Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610
-*/
-
-#include <asm/io.h>
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-
-MODULE_AUTHOR("Victor Krapivin <vik@belcaf.minsk.by>");
-MODULE_LICENSE("GPL");
-
-/*
-	These options are experimental
-
-#define CS461X_FULL_MAP
-*/
-
-#define COOKED_MODE
-
-
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS            0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4610
-#define PCI_DEVICE_ID_CIRRUS_4610       0x6001
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4612
-#define PCI_DEVICE_ID_CIRRUS_4612       0x6003
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4615
-#define PCI_DEVICE_ID_CIRRUS_4615       0x6004
-#endif
-
-/* Registers */
-
-#define BA0_JSPT                                0x00000480
-#define BA0_JSCTL                               0x00000484
-#define BA0_JSC1                                0x00000488
-#define BA0_JSC2                                0x0000048C
-#define BA0_JSIO                                0x000004A0
-
-/* Bits for JSPT */
-
-#define JSPT_CAX                                0x00000001
-#define JSPT_CAY                                0x00000002
-#define JSPT_CBX                                0x00000004
-#define JSPT_CBY                                0x00000008
-#define JSPT_BA1                                0x00000010
-#define JSPT_BA2                                0x00000020
-#define JSPT_BB1                                0x00000040
-#define JSPT_BB2                                0x00000080
-
-/* Bits for JSCTL */
-
-#define JSCTL_SP_MASK                           0x00000003
-#define JSCTL_SP_SLOW                           0x00000000
-#define JSCTL_SP_MEDIUM_SLOW                    0x00000001
-#define JSCTL_SP_MEDIUM_FAST                    0x00000002
-#define JSCTL_SP_FAST                           0x00000003
-#define JSCTL_ARE                               0x00000004
-
-/* Data register pairs masks */
-
-#define JSC1_Y1V_MASK                           0x0000FFFF
-#define JSC1_X1V_MASK                           0xFFFF0000
-#define JSC1_Y1V_SHIFT                          0
-#define JSC1_X1V_SHIFT                          16
-#define JSC2_Y2V_MASK                           0x0000FFFF
-#define JSC2_X2V_MASK                           0xFFFF0000
-#define JSC2_Y2V_SHIFT                          0
-#define JSC2_X2V_SHIFT                          16
-
-/* JS GPIO */
-
-#define JSIO_DAX                                0x00000001
-#define JSIO_DAY                                0x00000002
-#define JSIO_DBX                                0x00000004
-#define JSIO_DBY                                0x00000008
-#define JSIO_AXOE                               0x00000010
-#define JSIO_AYOE                               0x00000020
-#define JSIO_BXOE                               0x00000040
-#define JSIO_BYOE                               0x00000080
-
-/* 
-   The card initialization code is obfuscated; the module cs461x 
-   need to be loaded after ALSA modules initialized and something
-   played on the CS 4610 chip (see sources for details of CS4610
-   initialization code from ALSA)
-*/
-
-/* Card specific definitions */
-
-#define CS461X_BA0_SIZE         0x2000
-#define CS461X_BA1_DATA0_SIZE   0x3000
-#define CS461X_BA1_DATA1_SIZE   0x3800
-#define CS461X_BA1_PRG_SIZE     0x7000
-#define CS461X_BA1_REG_SIZE     0x0100
-
-#define BA1_SP_DMEM0                            0x00000000
-#define BA1_SP_DMEM1                            0x00010000
-#define BA1_SP_PMEM                             0x00020000
-#define BA1_SP_REG                              0x00030000
-
-#define BA1_DWORD_SIZE          (13 * 1024 + 512)
-#define BA1_MEMORY_COUNT        3
-
-/* 
-   Only one CS461x card is still suppoted; the code requires
-   redesign to avoid this limitatuion.
-*/
-
-static unsigned long ba0_addr;
-static unsigned int *ba0;
-
-#ifdef CS461X_FULL_MAP
-static unsigned long ba1_addr;
-static union ba1_t {
-        struct {
-                unsigned int *data0;
-                unsigned int *data1;
-                unsigned int *pmem;
-                unsigned int *reg;
-        } name;
-        unsigned int *idx[4];
-} ba1;
-
-static void cs461x_poke(unsigned long reg, unsigned int val)
-{
-        ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff] = val;
-}
-
-static unsigned int cs461x_peek(unsigned long reg)
-{
-        return ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff];
-}
-
-#endif
-
-static void cs461x_pokeBA0(unsigned long reg, unsigned int val)
-{
-        ba0[reg >> 2] = val;
-}
-
-static unsigned int cs461x_peekBA0(unsigned long reg)
-{
-        return ba0[reg >> 2];
-}
-
-static int cs461x_free(struct pci_dev *pdev)
-{
-	struct gameport *port = pci_get_drvdata(pdev);
-	if(port){
-	    gameport_unregister_port(port);
-	    kfree(port);
-	}    
-	if (ba0) iounmap(ba0);
-#ifdef CS461X_FULL_MAP
-	if (ba1.name.data0) iounmap(ba1.name.data0);
-	if (ba1.name.data1) iounmap(ba1.name.data1);
-	if (ba1.name.pmem)  iounmap(ba1.name.pmem);
-	if (ba1.name.reg)   iounmap(ba1.name.reg);
-#endif
-	return 0;
-}
-
-static void cs461x_gameport_trigger(struct gameport *gameport)
-{
-	cs461x_pokeBA0(BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
-}
-
-static unsigned char cs461x_gameport_read(struct gameport *gameport)
-{
-	return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io);
-}
-
-static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
-{
-	unsigned js1, js2, jst;
-	
-	js1 = cs461x_peekBA0(BA0_JSC1);
-	js2 = cs461x_peekBA0(BA0_JSC2);
-	jst = cs461x_peekBA0(BA0_JSPT);
-	
-	*buttons = (~jst >> 4) & 0x0F; 
-	
-	axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
-	axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
-	axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
-	axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
-
-	for(jst=0;jst<4;++jst)
-		if(axes[jst]==0xFFFF) axes[jst] = -1;
-	return 0;
-}
-
-static int cs461x_gameport_open(struct gameport *gameport, int mode)
-{
-	switch (mode) {
-#ifdef COOKED_MODE
-	case GAMEPORT_MODE_COOKED:
-		return 0;
-#endif
-	case GAMEPORT_MODE_RAW:
-		return 0;
-	default:
-		return -1;
-	}
-	return 0;
-}
-
-static struct pci_device_id cs461x_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */
-	{ PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */
-	{ PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl);
-
-static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int rc;
-	struct gameport* port;
-	
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n",
-			pdev->bus->number, pdev->devfn, rc);
-		return rc;
-	}
-
-	ba0_addr = pci_resource_start(pdev, 0);
-#ifdef CS461X_FULL_MAP
-	ba1_addr = pci_resource_start(pdev, 1);
-#endif
-	if (ba0_addr == 0 || ba0_addr == ~0 
-#ifdef CS461X_FULL_MAP
-            || ba1_addr == 0 || ba1_addr == ~0
-#endif
-	    ) {
-                printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr);
-#ifdef CS461X_FULL_MAP
-                printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr);
-#endif
-		cs461x_free(pdev);
-                return -ENOMEM;
-        }
-
-	ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE);
-#ifdef CS461X_FULL_MAP
-	ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
-	ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
-	ba1.name.pmem  = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
-	ba1.name.reg   = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
-
-	if (ba0 == NULL || ba1.name.data0 == NULL ||
-            ba1.name.data1 == NULL || ba1.name.pmem == NULL ||
-            ba1.name.reg == NULL) {
-		cs461x_free(pdev);
-                return -ENOMEM;
-        }
-#else
-	if (ba0 == NULL){
-		cs461x_free(pdev);
-		return -ENOMEM;
-	}
-#endif
-	printk(KERN_INFO "CS461x PCI: %lx[%d]\n",
-	    ba0_addr, CS461X_BA0_SIZE);
-        
-	if (!(port = kmalloc(sizeof(struct gameport), GFP_KERNEL))) {
-		printk(KERN_ERR "Memory allocation failed.\n");
-		cs461x_free(pdev);
-		return -ENOMEM;
-	}
-	memset(port, 0, sizeof(struct gameport));
-
-	pci_set_drvdata(pdev, port);
-	
-	port->open = cs461x_gameport_open;
-	port->read = cs461x_gameport_read;
-	port->trigger = cs461x_gameport_trigger;
-#ifdef COOKED_MODE
-	port->cooked_read = cs461x_gameport_cooked_read;
-#endif
-
-	cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
-	cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
-
-	gameport_register_port(port);
-
-	printk(KERN_INFO "gameport%d: CS461x Gameport speed %d kHz\n",
-		port->number, port->speed);
-
-	return 0;
-}
-
-static void __devexit cs461x_pci_remove(struct pci_dev *pdev)
-{
-	cs461x_free(pdev);
-}
-	
-static struct pci_driver cs461x_pci_driver = {
-        name:           "PCI Gameport",
-        id_table:       cs461x_pci_tbl,
-        probe:          cs461x_pci_probe,
-        remove:         cs461x_pci_remove,
-};
-
-int __init js_cs461x_init(void)
-{
-        return pci_module_init(&cs461x_pci_driver);
-}
-
-void __exit js_cs461x_exit(void)
-{
-        pci_unregister_driver(&cs461x_pci_driver);
-}
-
-module_init(js_cs461x_init);
-module_exit(js_cs461x_exit);
-
diff -Nru a/drivers/char/joystick/db9.c b/drivers/char/joystick/db9.c
--- a/drivers/char/joystick/db9.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,424 +0,0 @@
-/*
- * $Id: db9.c,v 1.6 2000/06/25 10:57:50 vojtech Exp $
- *
- *  Copyright (c) 1999 Vojtech Pavlik
- *
- *  Based on the work of:
- *	Andree Borrmann		Mats Sjövall
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/parport.h>
-#include <linux/input.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_LICENSE("GPL");
-MODULE_PARM(db9, "2i");
-MODULE_PARM(db9_2, "2i");
-MODULE_PARM(db9_3, "2i");
-
-#define DB9_MULTI_STICK		0x01
-#define DB9_MULTI2_STICK	0x02
-#define DB9_GENESIS_PAD		0x03
-#define DB9_GENESIS5_PAD	0x05
-#define DB9_GENESIS6_PAD	0x06
-#define DB9_SATURN_PAD		0x07
-#define DB9_MULTI_0802		0x08
-#define DB9_MULTI_0802_2	0x09
-#define DB9_CD32_PAD		0x0A
-#define DB9_MAX_PAD		0x0B
-
-#define DB9_UP			0x01
-#define DB9_DOWN		0x02
-#define DB9_LEFT		0x04
-#define DB9_RIGHT		0x08
-#define DB9_FIRE1		0x10
-#define DB9_FIRE2		0x20
-#define DB9_FIRE3		0x40
-#define DB9_FIRE4		0x80
-
-#define DB9_NORMAL		0x0a
-#define DB9_NOSELECT		0x08
-
-#define DB9_SATURN0		0x00
-#define DB9_SATURN1		0x02
-#define DB9_SATURN2		0x04
-#define DB9_SATURN3		0x06
-
-#define DB9_GENESIS6_DELAY	14
-#define DB9_REFRESH_TIME	HZ/100
-
-static int db9[] __initdata = { -1, 0 };
-static int db9_2[] __initdata = { -1, 0 };
-static int db9_3[] __initdata = { -1, 0 };
-
-struct db9 {
-	struct input_dev dev[2];
-	struct timer_list timer;
-	struct pardevice *pd;	
-	int mode;
-	int used;
-};
-
-static struct db9 *db9_base[3];
-
-static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
-static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
-static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
-
-static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 8, 1, 1, 7 };
-static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
-					db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn };
-static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
-				      NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
-				     "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad" };
-
-static void db9_timer(unsigned long private)
-{
-	struct db9 *db9 = (void *) private;
-	struct parport *port = db9->pd->port;
-	struct input_dev *dev = db9->dev;
-	int data, i;
-
-	switch(db9->mode) {
-		case DB9_MULTI_0802_2:
-
-			data = parport_read_data(port) >> 3;
-
-			input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
-
-		case DB9_MULTI_0802:
-
-			data = parport_read_status(port) >> 3;
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
-			break;
-
-		case DB9_MULTI_STICK:
-
-			data = parport_read_data(port);
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
-			break;
-
-		case DB9_MULTI2_STICK:
-
-			data = parport_read_data(port);
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
-			input_report_key(dev, BTN_THUMB,   ~data & DB9_FIRE2);
-			break;
-
-		case DB9_GENESIS_PAD:
-
-			parport_write_control(port, DB9_NOSELECT);
-			data = parport_read_data(port);
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
-			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
-
-			parport_write_control(port, DB9_NORMAL);
-			data=parport_read_data(port);
-
-			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
-			input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
-			break;
-
-		case DB9_GENESIS5_PAD:
-
-			parport_write_control(port, DB9_NOSELECT);
-			data=parport_read_data(port);
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
-			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
-
-			parport_write_control(port, DB9_NORMAL);
-			data=parport_read_data(port);
-
-			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
-			input_report_key(dev, BTN_X,     ~data & DB9_FIRE2);
-			input_report_key(dev, BTN_Y,     ~data & DB9_LEFT);
-			input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
-			break;
-
-		case DB9_GENESIS6_PAD:
-
-			parport_write_control(port, DB9_NOSELECT); /* 1 */
-			udelay(DB9_GENESIS6_DELAY);
-			data=parport_read_data(port);
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
-			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
-
-			parport_write_control(port, DB9_NORMAL);
-			udelay(DB9_GENESIS6_DELAY);
-			data=parport_read_data(port);
-
-			input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
-			input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
-
-			parport_write_control(port, DB9_NOSELECT); /* 2 */
-			udelay(DB9_GENESIS6_DELAY);
-			parport_write_control(port, DB9_NORMAL);
-			udelay(DB9_GENESIS6_DELAY);
-			parport_write_control(port, DB9_NOSELECT); /* 3 */
-			udelay(DB9_GENESIS6_DELAY);
-			data=parport_read_data(port);
-
-			input_report_key(dev, BTN_Y,     ~data & DB9_LEFT);
-			input_report_key(dev, BTN_Z,     ~data & DB9_DOWN);
-			input_report_key(dev, BTN_MODE,  ~data & DB9_UP);
-			input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
-
-			parport_write_control(port, DB9_NORMAL);
-			udelay(DB9_GENESIS6_DELAY);
-			parport_write_control(port, DB9_NOSELECT); /* 4 */
-			udelay(DB9_GENESIS6_DELAY);
-			parport_write_control(port, DB9_NORMAL);
-			break;
-
-		case DB9_SATURN_PAD:
-
-			parport_write_control(port, DB9_SATURN0);
-			data = parport_read_data(port);
-
-			input_report_key(dev, BTN_Y,  ~data & DB9_LEFT);
-			input_report_key(dev, BTN_Z,  ~data & DB9_DOWN);
-			input_report_key(dev, BTN_TL, ~data & DB9_UP);
-			input_report_key(dev, BTN_TR, ~data & DB9_RIGHT);
-
-			parport_write_control(port, DB9_SATURN2);
-			data = parport_read_data(port);
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			
-			parport_write_control(port, DB9_NORMAL);
-			data = parport_read_data(port);
-
-			input_report_key(dev, BTN_A, ~data & DB9_LEFT);
-			input_report_key(dev, BTN_B, ~data & DB9_UP);
-			input_report_key(dev, BTN_C, ~data & DB9_DOWN);
-			input_report_key(dev, BTN_X, ~data & DB9_RIGHT);
-			break;
-
-		case DB9_CD32_PAD:
-
-			data=parport_read_data(port);
-
-			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-
-			parport_write_control(port, 0x0a); 
-
-			for (i = 0; i < 7; i++) { 
-				data = parport_read_data(port);
-				parport_write_control(port, 0x02); 
-				parport_write_control(port, 0x0a); 
-				input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
-				}
-
-			parport_write_control(port, 0x00); 
-			break;
-		}
-
-	mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
-}
-
-static int db9_open(struct input_dev *dev)
-{
-	struct db9 *db9 = dev->private;
-	struct parport *port = db9->pd->port;
-
-	if (!db9->used++) {
-		parport_claim(db9->pd);
-		parport_write_data(port, 0xff);
-		parport_data_reverse(port);
-		parport_write_control(port, DB9_NORMAL);
-		mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
-	}
-
-	return 0;
-}
-
-static void db9_close(struct input_dev *dev)
-{
-	struct db9 *db9 = dev->private;
-	struct parport *port = db9->pd->port;
-
-	if (!--db9->used) {
-		del_timer(&db9->timer);
-		parport_write_control(port, 0x00);
-		parport_data_forward(port);
-		parport_release(db9->pd);
-	}
-}
-
-static struct db9 __init *db9_probe(int *config)
-{
-	struct db9 *db9;
-	struct parport *pp;
-	int i, j;
-
-	if (config[0] < 0)
-		return NULL;
-	if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
-		printk(KERN_ERR "db9.c: bad config\n");
-		return NULL;
-	}
-
-	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
-		config[0]--;
-
-	if (!pp) {
-		printk(KERN_ERR "db9.c: no such parport\n");
-		return NULL;
-	}
-
-	if (!(pp->modes & PARPORT_MODE_TRISTATE) && config[1] != DB9_MULTI_0802) {
-		printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
-		return NULL;
-	}
-	
-	if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL)))
-		return NULL;
-	memset(db9, 0, sizeof(struct db9));
-
-	db9->mode = config[1];
-	init_timer(&db9->timer);
-	db9->timer.data = (long) db9;
-	db9->timer.function = db9_timer;
-
-	db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-
-	if (!db9->pd) {
-		printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
-		kfree(db9);
-		return NULL;
-	}
-
-	for (i = 0; i < 1 + (db9->mode == DB9_MULTI_0802_2); i++) {
-
-		db9->dev[i].private = db9;
-		db9->dev[i].open = db9_open;
-		db9->dev[i].close = db9_close;
-
-		db9->dev[i].name = db9_name[db9->mode];
-		db9->dev[i].idbus = BUS_PARPORT;
-		db9->dev[i].idvendor = 0x0002;
-		db9->dev[i].idproduct = config[1];
-		db9->dev[i].idversion = 0x0100;
-
-		db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-		db9->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
-		for (j = 0; j < db9_buttons[db9->mode]; j++)
-			set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit); 
-
-		db9->dev[i].absmin[ABS_X] = -1; db9->dev[i].absmax[ABS_X] = 1;
-		db9->dev[i].absmin[ABS_Y] = -1; db9->dev[i].absmax[ABS_Y] = 1;
-
-		input_register_device(db9->dev + i);
-		printk(KERN_INFO "input%d: %s on %s\n",
-			db9->dev[i].number, db9_name[db9->mode], db9->pd->port->name);
-	}
-
-	return db9;
-}
-
-#ifndef MODULE
-int __init db9_setup(char *str)
-{
-	int i, ints[3];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) db9[i] = ints[i + 1];
-	return 1;
-}
-int __init db9_setup_2(char *str)
-{
-	int i, ints[3];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) db9_2[i] = ints[i + 1];
-	return 1;
-}
-int __init db9_setup_3(char *str)
-{
-	int i, ints[3];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) db9_3[i] = ints[i + 1];
-	return 1;
-}
-__setup("db9=", db9_setup);
-__setup("db9_2=", db9_setup_2);
-__setup("db9_3=", db9_setup_3);
-#endif
-
-int __init db9_init(void)
-{
-	db9_base[0] = db9_probe(db9);
-	db9_base[1] = db9_probe(db9_2);
-	db9_base[2] = db9_probe(db9_3);
-
-	if (db9_base[0] || db9_base[1] || db9_base[2])
-		return 0;
-
-	return -ENODEV;
-}
-
-void __exit db9_exit(void)
-{
-	int i, j;
-
-	for (i = 0; i < 3; i++) 
-		if (db9_base[i]) {
-			for (j = 0; j < 1 + (db9_base[i]->mode == DB9_MULTI_0802_2); j++)
-				input_unregister_device(db9_base[i]->dev + j);
-		parport_unregister_device(db9_base[i]->pd);
-	}
-}
-
-module_init(db9_init);
-module_exit(db9_exit);
diff -Nru a/drivers/char/joystick/emu10k1-gp.c b/drivers/char/joystick/emu10k1-gp.c
--- a/drivers/char/joystick/emu10k1-gp.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,125 +0,0 @@
-/*
- * $Id: emu10k1-gp.c,v 1.2 2001/04/24 07:48:56 vojtech Exp $
- *
- *  Copyright (c) 2001 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * EMU10k1 - SB Live! - gameport driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <asm/io.h>
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_LICENSE("GPL");
-
-struct emu {
-	struct pci_dev *dev;
-	struct emu *next;
-	struct gameport gameport;
-	int size;
-};
-	
-static struct pci_device_id emu_tbl[] __devinitdata = {
-	{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live! gameport */
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, emu_tbl);
-
-static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int ioport, iolen;
-	int rc;
-	struct emu *port;
-        
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		printk(KERN_ERR "emu10k1-gp: Cannot enable emu10k1 gameport (bus %d, devfn %d) error=%d\n",
-			pdev->bus->number, pdev->devfn, rc);
-		return rc;
-	}
-
-	ioport = pci_resource_start(pdev, 0);
-	iolen = pci_resource_len(pdev, 0);
-
-	if (!request_region(ioport, iolen, "emu10k1-gp"))
-		return -EBUSY;
-
-	if (!(port = kmalloc(sizeof(struct emu), GFP_KERNEL))) {
-		printk(KERN_ERR "emu10k1-gp: Memory allocation failed.\n");
-		release_region(ioport, iolen);
-		return -ENOMEM;
-	}
-	memset(port, 0, sizeof(struct emu));
-
-	port->gameport.io = ioport;
-	port->size = iolen;
-	port->dev = pdev;
-	pci_set_drvdata(pdev, port);
-
-	gameport_register_port(&port->gameport);
-
-	printk(KERN_INFO "gameport%d: Emu10k1 Gameport at %#x size %d speed %d kHz\n",
-		port->gameport.number, port->gameport.io, iolen, port->gameport.speed);
-
-	return 0;
-}
-
-static void __devexit emu_remove(struct pci_dev *pdev)
-{
-	struct emu *port = pci_get_drvdata(pdev);
-	gameport_unregister_port(&port->gameport);
-	release_region(port->gameport.io, port->size);
-	kfree(port);
-}
-
-static struct pci_driver emu_driver = {
-        name:           "Emu10k1 Gameport",
-        id_table:       emu_tbl,
-        probe:          emu_probe,
-        remove:         emu_remove,
-};
-
-int __init emu_init(void)
-{
-	return pci_module_init(&emu_driver);
-}
-
-void __exit emu_exit(void)
-{
-	pci_unregister_driver(&emu_driver);
-}
-
-module_init(emu_init);
-module_exit(emu_exit);
diff -Nru a/drivers/char/joystick/gamecon.c b/drivers/char/joystick/gamecon.c
--- a/drivers/char/joystick/gamecon.c	Sun Feb 10 19:58:06 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,670 +0,0 @@
-/*
- * $Id: gamecon.c,v 1.14 2001/04/29 22:42:14 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *
- *  Based on the work of:
- *  	Andree Borrmann		John Dahlstrom
- *  	David Kuder		Nathan Hand
- *
- *  Sponsored by SuSE
- */
-
-/*
- * NES, SNES, N64, Multi1, Multi2, PSX gamepad driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/parport.h>
-#include <linux/input.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_LICENSE("GPL");
-MODULE_PARM(gc, "2-6i");
-MODULE_PARM(gc_2,"2-6i");
-MODULE_PARM(gc_3,"2-6i");
-
-#define GC_SNES		1
-#define GC_NES		2
-#define GC_NES4		3
-#define GC_MULTI	4
-#define GC_MULTI2	5
-#define GC_N64		6	
-#define GC_PSX		7
-
-#define GC_MAX		7
-
-#define GC_REFRESH_TIME	HZ/100
- 
-struct gc {
-	struct pardevice *pd;
-	struct input_dev dev[5];
-	struct timer_list timer;
-	unsigned char pads[GC_MAX + 1];
-	int used;
-};
-
-static struct gc *gc_base[3];
-
-static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
-
-static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
-
-static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
-				"Multisystem 2-button joystick", "N64 controller", "PSX controller" };
-/*
- * N64 support.
- */
-
-static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 };
-static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START };
-
-#define GC_N64_LENGTH		32		/* N64 bit length, not including stop bit */
-#define GC_N64_REQUEST_LENGTH	37		/* transmit request sequence is 9 bits long */
-#define GC_N64_DELAY		133		/* delay between transmit request, and response ready (us) */
-#define GC_N64_REQUEST		0x1dd1111111ULL /* the request data command (encoded for 000000011) */
-#define GC_N64_DWS		3		/* delay between write segments (required for sound playback because of ISA DMA) */
-						/* GC_N64_DWS > 24 is known to fail */ 
-#define GC_N64_POWER_W		0xe2		/* power during write (transmit request) */
-#define GC_N64_POWER_R		0xfd		/* power during read */
-#define GC_N64_OUT		0x1d		/* output bits to the 4 pads */
-						/* Reading the main axes of any N64 pad is known to fail if the corresponding bit */
-						/* in GC_N64_OUT is pulled low on the output port (by any routine) for more */
-						/* than 123 us */
-#define GC_N64_CLOCK		0x02		/* clock bits for read */
-
-/* 
- * gc_n64_read_packet() reads an N64 packet. 
- * Each pad uses one bit per byte. So all pads connected to this port are read in parallel.
- */
-
-static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
-{
-	int i;
-	unsigned long flags;
-
-/*
- * Request the pad to transmit data
- */
-
-	__save_flags(flags);
-	__cli();
-	for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) {
-		parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0));
-		udelay(GC_N64_DWS);
-	}
-	__restore_flags(flags);
-
-/*
- * Wait for the pad response to be loaded into the 33-bit register of the adapter
- */
-
-	udelay(GC_N64_DELAY);
-
-/*
- * Grab data (ignoring the last bit, which is a stop bit)
- */
-
-	for (i = 0; i < GC_N64_LENGTH; i++) {
-		parport_write_data(gc->pd->port, GC_N64_POWER_R);
-		data[i] = parport_read_status(gc->pd->port);
-		parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK);
-	 }
-
-/*
- * We must wait 200 ms here for the controller to reinitialize before the next read request.
- * No worries as long as gc_read is polled less frequently than this.
- */
-
-}
-
-/*
- * NES/SNES support.
- */
-
-#define GC_NES_DELAY	6	/* Delay between bits - 6us */
-#define GC_NES_LENGTH	8	/* The NES pads use 8 bits of data */
-#define GC_SNES_LENGTH	12	/* The SNES true length is 16, but the last 4 bits are unused */
-
-#define GC_NES_POWER	0xfc
-#define GC_NES_CLOCK	0x01
-#define GC_NES_LATCH	0x02
-
-static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 };
-static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 };
-static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR };
-
-/*
- * gc_nes_read_packet() reads a NES/SNES packet.
- * Each pad uses one bit per byte. So all pads connected to
- * this port are read in parallel.
- */
-
-static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
-{
-	int i;
-
-	parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK | GC_NES_LATCH);
-	udelay(GC_NES_DELAY * 2);
-	parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
-
-	for (i = 0; i < length; i++) {
-		udelay(GC_NES_DELAY);
-		parport_write_data(gc->pd->port, GC_NES_POWER);
-		data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
-		udelay(GC_NES_DELAY);
-		parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
-	}
-}
-
-/*
- * Multisystem joystick support
- */
-
-#define GC_MULTI_LENGTH		5	/* Multi system joystick packet length is 5 */
-#define GC_MULTI2_LENGTH	6	/* One more bit for one more button */
-
-/*
- * gc_multi_read_packet() reads a Multisystem joystick packet.
- */
-
-static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
-{
-	int i;
-
-	for (i = 0; i < length; i++) {
-		parport_write_data(gc->pd->port, ~(1 << i));
-		data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
-	}
-}
-
-/*
- * PSX support
- *
- * See documentation at:
- *	http://www.dim.com/~mackys/psxmemcard/ps-eng2.txt
- *	http://www.gamesx.com/controldata/psxcont/psxcont.htm
- *	ftp://milano.usal.es/pablo/
- *	
- */
-
-#define GC_PSX_DELAY	60		/* 60 usec */
-#define GC_PSX_LENGTH	8		/* talk to the controller in bytes */
-
-#define GC_PSX_MOUSE	1		/* Mouse */
-#define GC_PSX_NEGCON	2		/* NegCon */
-#define GC_PSX_NORMAL	4		/* Digital / Analog or Rumble in Digital mode  */
-#define GC_PSX_ANALOG	5		/* Analog in Analog mode / Rumble in Green mode */
-#define GC_PSX_RUMBLE	7		/* Rumble in Red mode */
-
-#define GC_PSX_CLOCK	0x04		/* Pin 4 */
-#define GC_PSX_COMMAND	0x01		/* Pin 1 */
-#define GC_PSX_POWER	0xf8		/* Pins 5-9 */
-#define GC_PSX_SELECT	0x02		/* Pin 3 */
-
-#define GC_PSX_ID(x)	((x) >> 4)	/* High nibble is device type */
-#define GC_PSX_LEN(x)	((x) & 0xf)	/* Low nibble is length in words */
-
-static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
-static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
-				BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
-
-/*
- * gc_psx_command() writes 8bit command and reads 8bit data from
- * the psx pad.
- */
-
-static int gc_psx_command(struct gc *gc, int b)
-{
-	int i, cmd, data = 0;
-
-	for (i = 0; i < 8; i++, b >>= 1) {
-		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
-		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
-		udelay(GC_PSX_DELAY);
-		data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
-		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
-		udelay(GC_PSX_DELAY);
-	}
-	return data;
-}
-
-/*
- * gc_psx_read_packet() reads a whole psx packet and returns
- * device identifier code.
- */
-
-static int gc_psx_read_packet(struct gc *gc, unsigned char *data)
-{
-	int i, id;
-	unsigned long flags;
-
-	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
-	udelay(GC_PSX_DELAY * 2);
-	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);			/* Deselect, begin command */
-	udelay(GC_PSX_DELAY * 2);
-
-	__save_flags(flags);
-	__cli();
-
-	gc_psx_command(gc, 0x01);							/* Access pad */
-	id = gc_psx_command(gc, 0x42);							/* Get device id */
-	if (gc_psx_command(gc, 0) == 0x5a) {						/* Okay? */
-		for (i = 0; i < GC_PSX_LEN(id) * 2; i++)
-			data[i] = gc_psx_command(gc, 0);
-	} else id = 0;
-
-	__restore_flags(flags);
-
-	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
-
-	return GC_PSX_ID(id);
-}
-
-/*
- * gc_timer() reads and analyzes console pads data.
- */
-
-#define GC_MAX_LENGTH GC_N64_LENGTH
-
-static void gc_timer(unsigned long private)
-{
-	struct gc *gc = (void *) private;
-	struct input_dev *dev = gc->dev;
-	unsigned char data[GC_MAX_LENGTH];
-	int i, j, s;
-
-/*
- * N64 pads - must be read first, any read confuses them for 200 us
- */
-
-	if (gc->pads[GC_N64]) {
-
-		gc_n64_read_packet(gc, data);
-
-		for (i = 0; i < 5; i++) {
-
-			s = gc_status_bit[i];
-
-			if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
-	
-				signed char axes[2];
-				axes[0] = axes[1] = 0;
-
-				for (j = 0; j < 8; j++) {
-					if (data[23 - j] & s) axes[0] |= 1 << j; 
-					if (data[31 - j] & s) axes[1] |= 1 << j; 
-				}
-
-				input_report_abs(dev + i, ABS_X,  axes[0]);
-				input_report_abs(dev + i, ABS_Y, -axes[1]);
-
-				input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
-				input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
-
-				for (j = 0; j < 10; j++)
-					input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
-			}
-		}
-	}
-
-/*
- * NES and SNES pads
- */
-
-	if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {
-
-		gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
-
-		for (i = 0; i < 5; i++) {
-
-			s = gc_status_bit[i];
-
-			if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
-				input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
-				input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
-			}
-
-			if (s & gc->pads[GC_NES])
-				for (j = 0; j < 4; j++)
-					input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
-
-			if (s & gc->pads[GC_SNES])
-				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
-		}
-	}
-
-/*
- * Multi and Multi2 joysticks
- */
-
-	if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {
-
-		gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
-
-		for (i = 0; i < 5; i++) {
-
-			s = gc_status_bit[i];
-
-			if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
-				input_report_abs(dev + i, ABS_X,  !(s & data[2]) - !(s & data[3]));
-				input_report_abs(dev + i, ABS_Y,  !(s & data[0]) - !(s & data[1]));
-				input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
-			}
-
-			if (s & gc->pads[GC_MULTI2])
-				input_report_key(dev + i, BTN_THUMB, s & data[5]);
-		}
-	}
-
-/*
- * PSX controllers
- */
-
-	if (gc->pads[GC_PSX]) {
-
-		for (i = 0; i < 5; i++)
-	       		if (gc->pads[GC_PSX] & gc_status_bit[i])
-				break;
-
- 		switch (gc_psx_read_packet(gc, data)) {
-
-			case GC_PSX_RUMBLE:
-
-				input_report_key(dev + i, BTN_THUMB,  ~data[0] & 0x04);
-				input_report_key(dev + i, BTN_THUMB2, ~data[0] & 0x02);
-
-			case GC_PSX_NEGCON:
-			case GC_PSX_ANALOG:
-
-				for (j = 0; j < 4; j++)
-					input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]);
-
-				input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80));
-				input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10));
-
-				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
-
-				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
-
-				break;
-
-			case GC_PSX_NORMAL:
-
-				input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128);
-				input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128);
-
-				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
-
-				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
-
-				break;
-		}
-	}
-
-	mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
-}
-
-static int gc_open(struct input_dev *dev)
-{
-	struct gc *gc = dev->private;
-	if (!gc->used++) {
-		parport_claim(gc->pd);
-		parport_write_control(gc->pd->port, 0x04);
-		mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
-	}
-	return 0;
-}
-
-static void gc_close(struct input_dev *dev)
-{
-	struct gc *gc = dev->private;
-	if (!--gc->used) {
-		del_timer(&gc->timer);
-		parport_write_control(gc->pd->port, 0x00);
-		parport_release(gc->pd);
-	}
-}
-
-static struct gc __init *gc_probe(int *config)
-{
-	struct gc *gc;
-	struct parport *pp;
-	int i, j, psx;
-	unsigned char data[32];
-
-	if (config[0] < 0)
-		return NULL;
-
-	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
-		config[0]--;
-
-	if (!pp) {
-		printk(KERN_ERR "gamecon.c: no such parport\n");
-		return NULL;
-	}
-
-	if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL)))
-		return NULL;
-	memset(gc, 0, sizeof(struct gc));
-
-	gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-
-	if (!gc->pd) {
-		printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
-		kfree(gc);
-		return NULL;
-	}
-
-	parport_claim(gc->pd);
-
-	init_timer(&gc->timer);
-	gc->timer.data = (long) gc;
-	gc->timer.function = gc_timer;
-
-	for (i = 0; i < 5; i++) {
-
-		if (!config[i + 1])
-			continue;
-
-		if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
-			printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
-			continue;
-		}
-
-                gc->dev[i].private = gc;
-                gc->dev[i].open = gc_open;
-                gc->dev[i].close = gc_close;
-
-                gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-		for (j = 0; j < 2; j++) {
-			set_bit(ABS_X + j, gc->dev[i].absbit);
-			gc->dev[i].absmin[ABS_X + j] = -1;
-			gc->dev[i].absmax[ABS_X + j] =  1;
-		}
-
-		gc->pads[0] |= gc_status_bit[i];
-		gc->pads[config[i + 1]] |= gc_status_bit[i];
-
-		switch(config[i + 1]) {
-
-			case GC_N64:
-				for (j = 0; j < 10; j++)
-					set_bit(gc_n64_btn[j], gc->dev[i].keybit);
-
-				for (j = 0; j < 2; j++) {
-					set_bit(ABS_X + j, gc->dev[i].absbit);
-					gc->dev[i].absmin[ABS_X + j] = -127;
-					gc->dev[i].absmax[ABS_X + j] =  126;
-					gc->dev[i].absflat[ABS_X + j] = 2;
-					set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
-					gc->dev[i].absmin[ABS_HAT0X + j] = -1;
-					gc->dev[i].absmax[ABS_HAT0X + j] =  1;
-				}
-
-				break;
-
-			case GC_SNES:
-				for (j = 4; j < 8; j++)
-					set_bit(gc_snes_btn[j], gc->dev[i].keybit);
-			case GC_NES:
-				for (j = 0; j < 4; j++)
-					set_bit(gc_snes_btn[j], gc->dev[i].keybit);
-				break;
-
-			case GC_MULTI2:
-				set_bit(BTN_THUMB, gc->dev[i].keybit);
-			case GC_MULTI:
-				set_bit(BTN_TRIGGER, gc->dev[i].keybit);
-				break;
-
-			case GC_PSX:
-				
-				psx = gc_psx_read_packet(gc, data);
-
-				switch(psx) {
-					case GC_PSX_NEGCON:
-					case GC_PSX_NORMAL:
-					case GC_PSX_ANALOG:
-					case GC_PSX_RUMBLE:
-
-						for (j = 0; j < 6; j++) {
-							psx = gc_psx_abs[j];
-							set_bit(psx, gc->dev[i].absbit);
-							if (j < 4) {
-								gc->dev[i].absmin[psx] = 4;
-								gc->dev[i].absmax[psx] = 252;
-								gc->dev[i].absflat[psx] = 2;
-							} else {
-								gc->dev[i].absmin[psx] = -1;
-								gc->dev[i].absmax[psx] = 1;
-							}
-						}
-
-						for (j = 0; j < 12; j++)
-							set_bit(gc_psx_btn[j], gc->dev[i].keybit);
-
-						break;
-
-					case 0:
-						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						printk(KERN_ERR "gamecon.c: No PSX controller found.\n");
-						break;
-
-					default:
-						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
-							" please report to <vojtech@suse.cz>.\n", psx);
-				}
-				break;
-		}
-
-                gc->dev[i].name = gc_names[config[i + 1]];
-                gc->dev[i].idbus = BUS_PARPORT;
-                gc->dev[i].idvendor = 0x0001;
-                gc->dev[i].idproduct = config[i + 1];
-                gc->dev[i].idversion = 0x0100;
-	}
-
-	parport_release(gc->pd);
-
-	if (!gc->pads[0]) {
-		parport_unregister_device(gc->pd);
-		kfree(gc);
-		return NULL;
-	}
-
-	for (i = 0; i < 5; i++) 
-		if (gc->pads[0] & gc_status_bit[i]) {
-			input_register_device(gc->dev + i);
-			printk(KERN_INFO "input%d: %s on %s\n", gc->dev[i].number, gc->dev[i].name, gc->pd->port->name);
-		}
-
-	return gc;
-}
-
-#ifndef MODULE
-int __init gc_setup(char *str)
-{
-	int i, ints[7];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 6; i++) gc[i] = ints[i + 1];
-	return 1;
-}
-int __init gc_setup_2(char *str)
-{
-	int i, ints[7];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 6; i++) gc_2[i] = ints[i + 1];
-	return 1;
-}
-int __init gc_setup_3(char *str)
-{
-	int i, ints[7];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 6; i++) gc_3[i] = ints[i + 1];
-	return 1;
-}
-__setup("gc=", gc_setup);
-__setup("gc_2=", gc_setup_2);
-__setup("gc_3=", gc_setup_3);
-#endif
-
-int __init gc_init(void)
-{
-	gc_base[0] = gc_probe(gc);
-	gc_base[1] = gc_probe(gc_2);
-	gc_base[2] = gc_probe(gc_3);
-
-	if (gc_base[0] || gc_base[1] || gc_base[2])
-		return 0;
-
-	return -ENODEV;
-}
-
-void __exit gc_exit(void)
-{
-	int i, j;
-
-	for (i = 0; i < 3; i++)
-		if (gc_base[i]) {
-			for (j = 0; j < 5; j++)
-				if (gc_base[i]->pads[0] & gc_status_bit[j])
-					input_unregister_device(gc_base[i]->dev + j); 
-			parport_unregister_device(gc_base[i]->pd);
-		}
-}
-
-module_init(gc_init);
-module_exit(gc_exit);
diff -Nru a/drivers/char/joystick/gameport.c b/drivers/char/joystick/gameport.c
--- a/drivers/char/joystick/gameport.c	Sun Feb 10 19:58:06 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,199 +0,0 @@
-/*
- * $Id: gameport.c,v 1.5 2000/05/29 10:54:53 vojtech Exp $
- *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Generic gameport layer
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <asm/io.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/slab.h>
-#include <linux/isapnp.h>
-#include <linux/stddef.h>
-#include <linux/delay.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(gameport_register_port);
-EXPORT_SYMBOL(gameport_unregister_port);
-EXPORT_SYMBOL(gameport_register_device);
-EXPORT_SYMBOL(gameport_unregister_device);
-EXPORT_SYMBOL(gameport_open);
-EXPORT_SYMBOL(gameport_close);
-EXPORT_SYMBOL(gameport_rescan);
-EXPORT_SYMBOL(gameport_cooked_read);
-
-static struct gameport *gameport_list;
-static struct gameport_dev *gameport_dev;
-static int gameport_number;
-
-/*
- * gameport_measure_speed() measures the gameport i/o speed.
- */
-
-static int gameport_measure_speed(struct gameport *gameport)
-{
-#if defined(__i386__) || defined(__x86_64__)
-
-#define GET_TIME(x)     do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
-#define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193180L/HZ:0))
-
-	unsigned int i, t, t1, t2, t3, tx;
-	unsigned long flags;
-
-	if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
-		return 0;
-
-	tx = 1 << 30;
-
-	for(i = 0; i < 50; i++) {
-		save_flags(flags);	/* Yes, all CPUs */
-		cli();
-		GET_TIME(t1);
-		for(t = 0; t < 50; t++) gameport_read(gameport);
-		GET_TIME(t2);
-		GET_TIME(t3);
-		restore_flags(flags);
-		udelay(i * 10);
-		if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
-	}
-
-	return 59659 / (tx < 1 ? 1 : tx);
-
-#else
-
-	unsigned int j, t = 0;
-
-	j = jiffies; while (j == jiffies);
-	j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
-
-	return t * HZ / 1000;
-
-#endif
-
-	gameport_close(gameport);
-}
-
-static void gameport_find_dev(struct gameport *gameport)
-{
-        struct gameport_dev *dev = gameport_dev;
-
-        while (dev && !gameport->dev) {
-		if (dev->connect)
-                	dev->connect(gameport, dev);
-                dev = dev->next;
-        }
-}
-
-void gameport_rescan(struct gameport *gameport)
-{
-	gameport_close(gameport);
-	gameport_find_dev(gameport);
-}
-
-void gameport_register_port(struct gameport *gameport)
-{
-	gameport->number = gameport_number++;
-	gameport->next = gameport_list;	
-	gameport_list = gameport;
-
-	gameport->speed = gameport_measure_speed(gameport);
-
-	gameport_find_dev(gameport);
-}
-
-void gameport_unregister_port(struct gameport *gameport)
-{
-        struct gameport **gameportptr = &gameport_list;
-
-        while (*gameportptr && (*gameportptr != gameport)) gameportptr = &((*gameportptr)->next);
-        *gameportptr = (*gameportptr)->next;
-
-	if (gameport->dev && gameport->dev->disconnect)
-		gameport->dev->disconnect(gameport);
-
-	gameport_number--;
-}
-
-void gameport_register_device(struct gameport_dev *dev)
-{
-	struct gameport *gameport = gameport_list;
-
-	dev->next = gameport_dev;	
-	gameport_dev = dev;
-
-	while (gameport) {
-		if (!gameport->dev && dev->connect)
-			dev->connect(gameport, dev);
-		gameport = gameport->next;
-	}
-}
-
-void gameport_unregister_device(struct gameport_dev *dev)
-{
-        struct gameport_dev **devptr = &gameport_dev;
-	struct gameport *gameport = gameport_list;
-
-        while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next);
-        *devptr = (*devptr)->next;
-
-	while (gameport) {
-		if (gameport->dev == dev && dev->disconnect)
-			dev->disconnect(gameport);
-		gameport_find_dev(gameport);
-		gameport = gameport->next;
-	}
-}
-
-int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
-{
-	if (gameport->open) {
-		if (gameport->open(gameport, mode))
-			return -1;
-	} else {
-		if (mode != GAMEPORT_MODE_RAW)
-			return -1;
-	}
-
-	if (gameport->dev)
-		return -1;
-
-	gameport->dev = dev;
-	
-	return 0;
-}
-
-void gameport_close(struct gameport *gameport)
-{
-	gameport->dev = NULL;
-	if (gameport->close) gameport->close(gameport);
-}
diff -Nru a/drivers/char/joystick/gf2k.c b/drivers/char/joystick/gf2k.c
--- a/drivers/char/joystick/gf2k.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,361 +0,0 @@
-/*
- * $Id: gf2k.c,v 1.12 2000/06/04 14:53:44 vojtech Exp $
- *
- *  Copyright (c) 1998-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Genius Flight 2000 joystick driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/gameport.h>
-
-#define GF2K_START		400	/* The time we wait for the first bit [400 us] */
-#define GF2K_STROBE		40	/* The time we wait for the first bit [40 us] */
-#define GF2K_TIMEOUT		4	/* Wait for everything to settle [4 ms] */
-#define GF2K_LENGTH		80	/* Max number of triplets in a packet */
-#define GF2K_REFRESH		HZ/50	/* Time between joystick polls [20 ms] */
-
-/*
- * Genius joystick ids ...
- */
-
-#define GF2K_ID_G09		1
-#define GF2K_ID_F30D		2
-#define GF2K_ID_F30		3
-#define GF2K_ID_F31D		4
-#define GF2K_ID_F305		5
-#define GF2K_ID_F23P		6
-#define GF2K_ID_F31		7
-#define GF2K_ID_MAX		7
-
-static char gf2k_length[] = { 40, 40, 40, 40, 40, 40, 40, 40 };
-static char gf2k_hat_to_axis[][2] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
-
-static char *gf2k_names[] = {"", "Genius G-09D", "Genius F-30D", "Genius F-30", "Genius MaxFighter F-31D",
-				"Genius F-30-5", "Genius Flight2000 F-23", "Genius F-31"};
-static unsigned char gf2k_hats[] = { 0, 2, 0, 0, 2, 0, 2, 0 };
-static unsigned char gf2k_axes[] = { 0, 2, 0, 0, 4, 0, 4, 0 };
-static unsigned char gf2k_joys[] = { 0, 0, 0, 0,10, 0, 8, 0 };
-static unsigned char gf2k_pads[] = { 0, 6, 0, 0, 0, 0, 0, 0 };
-static unsigned char gf2k_lens[] = { 0,18, 0, 0,18, 0,18, 0 };
-
-static unsigned char gf2k_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_GAS, ABS_BRAKE };
-static short gf2k_btn_joy[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 };
-static short gf2k_btn_pad[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_START, BTN_SELECT };
-
-
-static short gf2k_seq_reset[] = { 240, 340, 0 };
-static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
-
-struct gf2k {
-	struct gameport *gameport;
-	struct timer_list timer;
-	struct input_dev dev;
-	int reads;
-	int bads;
-	int used;
-	unsigned char id;
-	unsigned char length;
-};
-
-/*
- * gf2k_read_packet() reads a Genius Flight2000 packet.
- */
-
-static int gf2k_read_packet(struct gameport *gameport, int length, char *data)
-{
-	unsigned char u, v;
-	int i;
-	unsigned int t, p;
-	unsigned long flags;
-
-	t = gameport_time(gameport, GF2K_START);
-	p = gameport_time(gameport, GF2K_STROBE);
-
-	i = 0;
-
-	__save_flags(flags);
-	__cli();
-
-	gameport_trigger(gameport);
-	v = gameport_read(gameport);;
-
-	while (t > 0 && i < length) {
-		t--; u = v;
-		v = gameport_read(gameport);
-		if (v & ~u & 0x10) {
-			data[i++] = v >> 5;
-			t = p;
-		}
-	}
-
-	__restore_flags(flags);
-
-	return i;
-}
-
-/*
- * gf2k_trigger_seq() initializes a Genius Flight2000 joystick
- * into digital mode.
- */
-
-static void gf2k_trigger_seq(struct gameport *gameport, short *seq)
-{
-
-	unsigned long flags;
-	int i, t;
-
-        __save_flags(flags);
-        __cli();
-
-	i = 0;
-        do {
-		gameport_trigger(gameport);
-		t = gameport_time(gameport, GF2K_TIMEOUT * 1000);
-		while ((gameport_read(gameport) & 1) && t) t--;
-                udelay(seq[i]);
-        } while (seq[++i]);
-
-	gameport_trigger(gameport);
-
-	__restore_flags(flags);
-}
-
-/*
- * js_sw_get_bits() composes bits from the triplet buffer into a __u64.
- * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
- * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
- * is number of bits per triplet.
- */
-
-#define GB(p,n,s)	gf2k_get_bits(data, p, n, s)
-
-static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
-{
-	__u64 data = 0;
-	int i;
-
-	for (i = 0; i < num / 3 + 2; i++)
-		data |= buf[pos / 3 + i] << (i * 3);
-	data >>= pos % 3;
-	data &= (1 << num) - 1;
-	data <<= shift;
-
-	return data;
-}
-
-static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
-{
-	struct input_dev *dev = &gf2k->dev;
-	int i, t;
-
-	for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
-		input_report_abs(dev, gf2k_abs[i], GB(i<<3,8,0) | GB(i+46,1,8) | GB(i+50,1,9));
-
-	for (i = 0; i < 2 && i < gf2k_axes[gf2k->id] - 4; i++)
-		input_report_abs(dev, gf2k_abs[i], GB(i*9+60,8,0) | GB(i+54,1,9));
-
-	t = GB(40,4,0);
-
-	for (i = 0; i < gf2k_hats[gf2k->id]; i++)
-		input_report_abs(dev, ABS_HAT0X + i, gf2k_hat_to_axis[t][i]);
-
-	t = GB(44,2,0) | GB(32,8,2) | GB(78,2,10);
-
-	for (i = 0; i < gf2k_joys[gf2k->id]; i++)
-		input_report_key(dev, gf2k_btn_joy[i], (t >> i) & 1);
-
-	for (i = 0; i < gf2k_pads[gf2k->id]; i++)
-		input_report_key(dev, gf2k_btn_pad[i], (t >> i) & 1);
-}
-
-/*
- * gf2k_timer() reads and analyzes Genius joystick data.
- */
-
-static void gf2k_timer(unsigned long private)
-{
-	struct gf2k *gf2k = (void *) private;
-	unsigned char data[GF2K_LENGTH];
-
-	gf2k->reads++;
-
-	if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id]) {
-		gf2k->bads++;
-	} else gf2k_read(gf2k, data);
-
-	mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);
-}
-
-static int gf2k_open(struct input_dev *dev)
-{
-	struct gf2k *gf2k = dev->private;
-	if (!gf2k->used++)
-		mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);	
-	return 0;
-}
-
-static void gf2k_close(struct input_dev *dev)
-{
-	struct gf2k *gf2k = dev->private;
-	if (!--gf2k->used)
-		del_timer(&gf2k->timer);
-}
-
-/*
- * gf2k_connect() probes for Genius id joysticks.
- */
-
-static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct gf2k *gf2k;
-	unsigned char data[GF2K_LENGTH];
-	int i;
-
-	if (!(gf2k = kmalloc(sizeof(struct gf2k), GFP_KERNEL)))
-		return;
-	memset(gf2k, 0, sizeof(struct gf2k));
-
-	gameport->private = gf2k;
-
-	gf2k->gameport = gameport;
-	init_timer(&gf2k->timer);
-	gf2k->timer.data = (long) gf2k;
-	gf2k->timer.function = gf2k_timer;
-
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		goto fail1;
-
-	gf2k_trigger_seq(gameport, gf2k_seq_reset);
-
-	wait_ms(GF2K_TIMEOUT);
-
-	gf2k_trigger_seq(gameport, gf2k_seq_digital);
-
-	wait_ms(GF2K_TIMEOUT);
-
-	if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12)
-		goto fail2;
-
-	if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5)))
-		goto fail2;
-
-#ifdef RESET_WORKS
-	if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
-	    (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5))))
-		goto fail2;
-#else
-	gf2k->id = 6;
-#endif
-
-	if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
-		printk(KERN_WARNING "gf2k.c: Not yet supported joystick on gameport%d. [id: %d type:%s]\n",
-			gameport->number, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
-		goto fail2;
-	}
-
-	gf2k->length = gf2k_lens[gf2k->id];
-
-	gf2k->dev.private = gf2k;
-	gf2k->dev.open = gf2k_open;
-	gf2k->dev.close = gf2k_close;
-	gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-	gf2k->dev.name = gf2k_names[gf2k->id];
-	gf2k->dev.idbus = BUS_GAMEPORT;
-	gf2k->dev.idvendor = GAMEPORT_ID_VENDOR_GENIUS;
-	gf2k->dev.idproduct = gf2k->id;
-	gf2k->dev.idversion = 0x0100;
-
-	for (i = 0; i < gf2k_axes[gf2k->id]; i++)
-		set_bit(gf2k_abs[i], gf2k->dev.absbit);
-
-	for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
-		set_bit(ABS_HAT0X + i, gf2k->dev.absbit);
-		gf2k->dev.absmin[ABS_HAT0X + i] = -1;
-		gf2k->dev.absmax[ABS_HAT0X + i] = 1;
-	}
-
-	for (i = 0; i < gf2k_joys[gf2k->id]; i++)
-		set_bit(gf2k_btn_joy[i], gf2k->dev.keybit);
-
-	for (i = 0; i < gf2k_pads[gf2k->id]; i++)
-		set_bit(gf2k_btn_pad[i], gf2k->dev.keybit);
-
-	gf2k_read_packet(gameport, gf2k->length, data);
-	gf2k_read(gf2k, data);
-
-	for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
-		gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
-	      		  gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; 
-		gf2k->dev.absmin[gf2k_abs[i]] = 32;
-		gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
-		gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
-	}
-
-	input_register_device(&gf2k->dev);
-	printk(KERN_INFO "input%d: %s on gameport%d.0\n",
-		gf2k->dev.number, gf2k_names[gf2k->id], gameport->number);
-
-	return;
-fail2:	gameport_close(gameport);
-fail1:	kfree(gf2k);
-}
-
-static void gf2k_disconnect(struct gameport *gameport)
-{
-	struct gf2k *gf2k = gameport->private;
-	input_unregister_device(&gf2k->dev);
-	gameport_close(gameport);
-	kfree(gf2k);
-}
-
-static struct gameport_dev gf2k_dev = {
-	connect:	gf2k_connect,
-	disconnect:	gf2k_disconnect,
-};
-
-int __init gf2k_init(void)
-{
-	gameport_register_device(&gf2k_dev);
-	return 0;
-}
-
-void __exit gf2k_exit(void)
-{
-	gameport_unregister_device(&gf2k_dev);
-}
-
-module_init(gf2k_init);
-module_exit(gf2k_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/grip.c b/drivers/char/joystick/grip.c
--- a/drivers/char/joystick/grip.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,425 +0,0 @@
-/*
- * $Id: grip.c,v 1.14 2000/06/06 21:13:36 vojtech Exp $
- *
- *  Copyright (c) 1998-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Gravis/Kensington GrIP protocol joystick and gamepad driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/gameport.h>
-#include <linux/input.h>
-
-#define GRIP_MODE_GPP		1
-#define GRIP_MODE_BD		2
-#define GRIP_MODE_XT		3
-#define GRIP_MODE_DC		4
-
-#define GRIP_LENGTH_GPP		24
-#define GRIP_STROBE_GPP		200	/* 200 us */
-#define GRIP_LENGTH_XT		4
-#define GRIP_STROBE_XT		64	/* 64 us */
-#define GRIP_MAX_CHUNKS_XT	10	
-#define GRIP_MAX_BITS_XT	30	
-
-#define GRIP_REFRESH_TIME	HZ/50	/* 20 ms */
-
-struct grip {
-	struct gameport *gameport;
-	struct timer_list timer;
-	struct input_dev dev[2];
-	unsigned char mode[2];
-	int used;
-	int reads;
-	int bads;
-};
-
-static int grip_btn_gpp[] = { BTN_START, BTN_SELECT, BTN_TR2, BTN_Y, 0, BTN_TL2, BTN_A, BTN_B, BTN_X, 0, BTN_TL, BTN_TR, -1 };
-static int grip_btn_bd[] = { BTN_THUMB, BTN_THUMB2, BTN_TRIGGER, BTN_TOP, BTN_BASE, -1 };
-static int grip_btn_xt[] = { BTN_TRIGGER, BTN_THUMB, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_SELECT, BTN_START, BTN_MODE, -1 };
-static int grip_btn_dc[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, -1 };
-
-static int grip_abs_gpp[] = { ABS_X, ABS_Y, -1 };
-static int grip_abs_bd[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
-static int grip_abs_xt[] = { ABS_X, ABS_Y, ABS_BRAKE, ABS_GAS, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, -1 };
-static int grip_abs_dc[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
-
-static char *grip_name[] = { NULL, "Gravis GamePad Pro", "Gravis Blackhawk Digital",
-				"Gravis Xterminator Digital", "Gravis Xterminator DualControl" };
-static int *grip_abs[] = { 0, grip_abs_gpp, grip_abs_bd, grip_abs_xt, grip_abs_dc };
-static int *grip_btn[] = { 0, grip_btn_gpp, grip_btn_bd, grip_btn_xt, grip_btn_dc };
-static char grip_anx[] = { 0, 0, 3, 5, 5 };
-static char grip_cen[] = { 0, 0, 2, 2, 4 };
-
-/*
- * grip_gpp_read_packet() reads a Gravis GamePad Pro packet.
- */
-
-static int grip_gpp_read_packet(struct gameport *gameport, int shift, unsigned int *data)
-{
-	unsigned long flags;
-	unsigned char u, v;
-	unsigned int t;
-	int i;
-
-	int strobe = gameport_time(gameport, GRIP_STROBE_GPP);
-
-	data[0] = 0;
-	t = strobe;
-	i = 0;
-
-	__save_flags(flags);
-	__cli();
-
-	v = gameport_read(gameport) >> shift;
-
-	do {
-		t--;
-		u = v; v = (gameport_read(gameport) >> shift) & 3;
-		if (~v & u & 1) {
-			data[0] |= (v >> 1) << i++;
-			t = strobe;
-		}
-	} while (i < GRIP_LENGTH_GPP && t > 0);
-
-	__restore_flags(flags);
-
-	if (i < GRIP_LENGTH_GPP) return -1;
-
-	for (i = 0; i < GRIP_LENGTH_GPP && (data[0] & 0xfe4210) ^ 0x7c0000; i++)
-		data[0] = data[0] >> 1 | (data[0] & 1) << (GRIP_LENGTH_GPP - 1);
-
-	return -(i == GRIP_LENGTH_GPP);
-}
-
-/*
- * grip_xt_read_packet() reads a Gravis Xterminator packet.
- */
-
-static int grip_xt_read_packet(struct gameport *gameport, int shift, unsigned int *data)
-{
-	unsigned int i, j, buf, crc;
-	unsigned char u, v, w;
-	unsigned long flags;
-	unsigned int t;
-	char status;
-
-	int strobe = gameport_time(gameport, GRIP_STROBE_XT);
-
-	data[0] = data[1] = data[2] = data[3] = 0;
-	status = buf = i = j = 0;
-	t = strobe;
-
-	__save_flags(flags);
-	__cli();
-
-	v = w = (gameport_read(gameport) >> shift) & 3;
-
-	do {
-		t--;
-		u = (gameport_read(gameport) >> shift) & 3;
-
-		if (u ^ v) {
-
-			if ((u ^ v) & 1) {
-				buf = (buf << 1) | (u >> 1);
-				t = strobe;
-				i++;
-			} else 
-
-			if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) {
-				if (i == 20) {
-					crc = buf ^ (buf >> 7) ^ (buf >> 14);
-					if (!((crc ^ (0x25cb9e70 >> ((crc >> 2) & 0x1c))) & 0xf)) {
-						data[buf >> 18] = buf >> 4;
-						status |= 1 << (buf >> 18);
-					}
-					j++;
-				}
-				t = strobe;
-				buf = 0;
-				i = 0;
-			}
-			w = v;
-			v = u;
-		}
-
-	} while (status != 0xf && i < GRIP_MAX_BITS_XT && j < GRIP_MAX_CHUNKS_XT && t > 0);
-
-	__restore_flags(flags);
-
-	return -(status != 0xf);
-}
-
-/*
- * grip_timer() repeatedly polls the joysticks and generates events.
- */
-
-static void grip_timer(unsigned long private)
-{
-	struct grip *grip = (void*) private;
-	unsigned int data[GRIP_LENGTH_XT];
-	struct input_dev *dev;
-	int i, j;
-
-	for (i = 0; i < 2; i++) {
-
-		dev = grip->dev + i;
-		grip->reads++;
-
-		switch (grip->mode[i]) {
-
-			case GRIP_MODE_GPP:
-
-				if (grip_gpp_read_packet(grip->gameport, (i << 1) + 4, data)) {
-					grip->bads++;
-					break;
-				}
-
-				input_report_abs(dev, ABS_X, ((*data >> 15) & 1) - ((*data >> 16) & 1));
-				input_report_abs(dev, ABS_Y, ((*data >> 13) & 1) - ((*data >> 12) & 1));
-
-				for (j = 0; j < 12; j++)
-					if (grip_btn_gpp[j])
-						input_report_key(dev, grip_btn_gpp[j], (*data >> j) & 1);
-
-				break;
-
-			case GRIP_MODE_BD:
-
-				if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
-					grip->bads++;
-					break;
-				}
-
-				input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
-				input_report_abs(dev, ABS_Y,  63 - ((data[0] >> 8) & 0x3f));
-				input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
-
-				input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
-				input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
-
-				for (j = 0; j < 5; j++)
-					input_report_key(dev, grip_btn_bd[j], (data[3] >> (j + 4)) & 1);
-
-				break;
-
-			case GRIP_MODE_XT:
-
-				if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
-					grip->bads++;
-					break;
-				}
-
-				input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
-				input_report_abs(dev, ABS_Y,  63 - ((data[0] >> 8) & 0x3f));
-				input_report_abs(dev, ABS_BRAKE,    (data[1] >> 2) & 0x3f);
-				input_report_abs(dev, ABS_GAS,	    (data[1] >> 8) & 0x3f);
-				input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
-
-				input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
-				input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
-				input_report_abs(dev, ABS_HAT1X, ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1));
-				input_report_abs(dev, ABS_HAT1Y, ((data[2] >> 6) & 1) - ((data[2] >> 7) & 1));
-
-				for (j = 0; j < 11; j++)
-					input_report_key(dev, grip_btn_xt[j], (data[3] >> (j + 3)) & 1);
-				break;
-
-			case GRIP_MODE_DC:
-
-				if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
-					grip->bads++;
-					break;
-				}
-
-				input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
-				input_report_abs(dev, ABS_Y,        (data[0] >> 8) & 0x3f);
-				input_report_abs(dev, ABS_RX,       (data[1] >> 2) & 0x3f);
-				input_report_abs(dev, ABS_RY,	    (data[1] >> 8) & 0x3f);
-				input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
-
-				input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
-				input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
-
-				for (j = 0; j < 9; j++)
-					input_report_key(dev, grip_btn_dc[j], (data[3] >> (j + 3)) & 1);
-				break;
-
-
-		}
-	}
-
-	mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
-}
-
-static int grip_open(struct input_dev *dev)
-{
-	struct grip *grip = dev->private;
-	if (!grip->used++)
-		mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
-	return 0;
-}
-
-static void grip_close(struct input_dev *dev)
-{
-	struct grip *grip = dev->private;
-	if (!--grip->used)
-		del_timer(&grip->timer);
-}
-
-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct grip *grip;
-	unsigned int data[GRIP_LENGTH_XT];
-	int i, j, t;
-
-	if (!(grip = kmalloc(sizeof(struct grip), GFP_KERNEL)))
-		return;
-	memset(grip, 0, sizeof(struct grip));
-
-	gameport->private = grip;
-
-	grip->gameport = gameport;
-	init_timer(&grip->timer);
-	grip->timer.data = (long) grip;
-	grip->timer.function = grip_timer;
-
-	 if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		goto fail1;
-
-	for (i = 0; i < 2; i++) {
-		if (!grip_gpp_read_packet(gameport, (i << 1) + 4, data)) {
-			grip->mode[i] = GRIP_MODE_GPP;
-			continue;
-		}
-		if (!grip_xt_read_packet(gameport, (i << 1) + 4, data)) {
-			if (!(data[3] & 7)) {
-				grip->mode[i] = GRIP_MODE_BD;
-				continue;
-			}
-			if (!(data[2] & 0xf0)) {
-				grip->mode[i] = GRIP_MODE_XT;
-				continue;
-			}
-			grip->mode[i] = GRIP_MODE_DC;
-			continue;
-		}
-	}
-
-	if (!grip->mode[0] && !grip->mode[1])
-		goto fail2;
-
-	for (i = 0; i < 2; i++)
-		if (grip->mode[i]) {
-
-			grip->dev[i].private = grip;
-
-			grip->dev[i].open = grip_open;
-			grip->dev[i].close = grip_close;
-
-			grip->dev[i].name = grip_name[grip->mode[i]];
-			grip->dev[i].idbus = BUS_GAMEPORT;
-			grip->dev[i].idvendor = GAMEPORT_ID_VENDOR_GRAVIS;
-			grip->dev[i].idproduct = grip->mode[i];
-			grip->dev[i].idversion = 0x0100;
-
-			grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-			for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
-
-				set_bit(t, grip->dev[i].absbit);
-
-				if (j < grip_cen[grip->mode[i]]) {
-					grip->dev[i].absmin[t] = 14;
-					grip->dev[i].absmax[t] = 52;
-					grip->dev[i].absfuzz[t] = 1;
-					grip->dev[i].absflat[t] = 2;
-					continue;
-				}
-
-				if (j < grip_anx[grip->mode[i]]) {
-					grip->dev[i].absmin[t] = 3;
-					grip->dev[i].absmax[t] = 57;
-					grip->dev[i].absfuzz[t] = 1;
-					continue;
-				}
-
-				grip->dev[i].absmin[t] = -1;
-				grip->dev[i].absmax[t] = 1;
-			}
-
-			for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
-				if (t > 0)
-					set_bit(t, grip->dev[i].keybit);
-
-			input_register_device(grip->dev + i);
-
-			printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
-				grip->dev[i].number, grip_name[grip->mode[i]], gameport->number, i);
-		}
-
-	return;
-fail2:	gameport_close(gameport);
-fail1:	kfree(grip);
-}
-
-static void grip_disconnect(struct gameport *gameport)
-{
-	int i;
-
-	struct grip *grip = gameport->private;
-	for (i = 0; i < 2; i++)
-		if (grip->mode[i])
-			input_unregister_device(grip->dev + i);
-	gameport_close(gameport);
-	kfree(grip);
-}
-
-static struct gameport_dev grip_dev = {
-	connect:	grip_connect,
-	disconnect:	grip_disconnect,
-};
-
-int __init grip_init(void)
-{
-	gameport_register_device(&grip_dev);
-	return 0;
-}
-
-void __exit grip_exit(void)
-{
-	gameport_unregister_device(&grip_dev);
-}
-
-module_init(grip_init);
-module_exit(grip_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/iforce.c b/drivers/char/joystick/iforce.c
--- a/drivers/char/joystick/iforce.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1224 +0,0 @@
-/*
- * $Id: iforce.c,v 1.56 2001/05/27 14:41:26 jdeneux Exp $
- *
- *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
- *  Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
- *
- *  USB/RS232 I-Force joysticks and wheels.
- *
- *  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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/usb.h>
-#include <linux/serio.h>
-#include <linux/config.h>
-
-/* FF: This module provides arbitrary resource management routines.
- * I use it to manage the device's memory.
- * Despite the name of this module, I am *not* going to access the ioports.
- */
-#include <linux/ioport.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>, Johann Deneux <deneux@ifrance.com>");
-MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
-MODULE_LICENSE("GPL");
-
-#define IFORCE_MAX_LENGTH	16
-
-#if defined(CONFIG_INPUT_IFORCE_232) || defined(CONFIG_INPUT_IFORCE_232_MODULE)
-#define IFORCE_232	1
-#endif
-#if defined(CONFIG_INPUT_IFORCE_USB) || defined(CONFIG_INPUT_IFORCE_USB_MODULE)
-#define IFORCE_USB	2
-#endif
-
-#define FF_EFFECTS_MAX	32
-
-/* Each force feedback effect is made of one core effect, which can be
- * associated to at most to effect modifiers
- */
-#define FF_MOD1_IS_USED		0
-#define FF_MOD2_IS_USED		1
-#define FF_CORE_IS_USED		2
-#define FF_CORE_IS_PLAYED	3
-#define FF_MODCORE_MAX		3
-
-struct iforce_core_effect {
-	/* Information about where modifiers are stored in the device's memory */
-	struct resource mod1_chunk;
-	struct resource mod2_chunk;
-	unsigned long flags[NBITS(FF_MODCORE_MAX)];
-};
-
-#define FF_CMD_EFFECT		0x010e
-#define FF_CMD_SHAPE		0x0208
-#define FF_CMD_MAGNITUDE	0x0303
-#define FF_CMD_PERIOD		0x0407
-#define FF_CMD_INTERACT		0x050a
-
-#define FF_CMD_AUTOCENTER	0x4002
-#define FF_CMD_PLAY		0x4103
-#define FF_CMD_ENABLE		0x4201
-#define FF_CMD_GAIN		0x4301
-
-#define FF_CMD_QUERY		0xff01
-
-static signed short btn_joystick[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
-	BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, BTN_DEAD, -1 };
-static signed short btn_wheel[] =    { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
-	BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
-static signed short abs_joystick[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
-static signed short abs_wheel[] =    { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, -1 };
-static signed short ff_iforce[] =    { FF_PERIODIC, FF_CONSTANT, FF_SPRING, FF_FRICTION,
-	FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP, FF_SAW_DOWN, FF_GAIN, FF_AUTOCENTER, -1 };
-
-static struct iforce_device {
-	u16 idvendor;
-	u16 idproduct;
-	char *name;
-	signed short *btn;
-	signed short *abs;
-	signed short *ff;
-} iforce_device[] = {
-	{ 0x046d, 0xc281, "Logitech WingMan Force",			btn_joystick, abs_joystick, ff_iforce },
-	{ 0x046d, 0xc291, "Logitech WingMan Formula Force",		btn_wheel, abs_wheel, ff_iforce },
-	{ 0x05ef, 0x020a, "AVB Top Shot Pegasus",			btn_joystick, abs_joystick, ff_iforce },
-	{ 0x05ef, 0x8884, "AVB Mag Turbo Force",			btn_wheel, abs_wheel, ff_iforce },
-	{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback",	btn_wheel, abs_wheel, ff_iforce },
-	{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]",		btn_joystick, abs_joystick, ff_iforce }
-};
-
-struct iforce {
-	struct input_dev dev;		/* Input device interface */
-	struct iforce_device *type;
-	char name[64];
-	int open;
-	int bus;
-
-	unsigned char data[IFORCE_MAX_LENGTH];
-	unsigned char edata[IFORCE_MAX_LENGTH];
-	u16 ecmd;
-	u16 expect_packet;
-
-#ifdef IFORCE_232
-	struct serio *serio;		/* RS232 transfer */
-	int idx, pkt, len, id;
-	unsigned char csum;
-#endif
-#ifdef IFORCE_USB
-	struct usb_device *usbdev;	/* USB transfer */
-	struct urb *irq, *out, *ctrl;
-	struct usb_ctrlrequest dr;
-#endif
-					/* Force Feedback */
-	wait_queue_head_t wait;
-	struct resource device_memory;
-	struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
-};
-
-static struct {
-	__s32 x;
-	__s32 y;
-} iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
-
-/* Get hi and low bytes of a 16-bits int */
-#define HI(a)	((unsigned char)((a) >> 8))
-#define LO(a)	((unsigned char)((a) & 0xff))
-
-/* Encode a time value */
-#define TIME_SCALE(a)	((a) == 0xffff ? 0xffff : (a) * 1000 / 256)
-
-static void dump_packet(char *msg, u16 cmd, unsigned char *data)
-{
-	int i;
-
-	printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
-	for (i = 0; i < LO(cmd); i++)
-		printk("%02x ", data[i]);
-	printk(")\n");
-}
-
-/*
- * Send a packet of bytes to the device
- */
-static void send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
-{
-	switch (iforce->bus) {
-
-#ifdef IFORCE_232
-		case IFORCE_232: {
-
-			int i;
-			unsigned char csum = 0x2b ^ HI(cmd) ^ LO(cmd);
-
-			serio_write(iforce->serio, 0x2b);
-			serio_write(iforce->serio, HI(cmd));
-			serio_write(iforce->serio, LO(cmd));
-
-			for (i = 0; i < LO(cmd); i++) {
-				serio_write(iforce->serio, data[i]);
-				csum = csum ^ data[i];
-			}
-
-			serio_write(iforce->serio, csum);
-			return;
-		}
-#endif
-#ifdef IFORCE_USB
-		case IFORCE_USB: {
-
-			DECLARE_WAITQUEUE(wait, current);
-			int timeout = HZ; /* 1 second */
-
-			memcpy(iforce->out->transfer_buffer + 1, data, LO(cmd));
-			((char*)iforce->out->transfer_buffer)[0] = HI(cmd);
-			iforce->out->transfer_buffer_length = LO(cmd) + 2;
-			iforce->out->dev = iforce->usbdev;
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			add_wait_queue(&iforce->wait, &wait);
-
-			if (usb_submit_urb(iforce->out)) {
-				set_current_state(TASK_RUNNING);
-				remove_wait_queue(&iforce->wait, &wait);
-				return;
-			}
-
-			while (timeout && iforce->out->status == -EINPROGRESS)
-				timeout = schedule_timeout(timeout);
-
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&iforce->wait, &wait);
-
-			if (!timeout)
-				usb_unlink_urb(iforce->out);
-
-			return;
-		}
-#endif
-	}
-}
-
-static void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
-{
-	struct input_dev *dev = &iforce->dev;
-	int i;
-
-#ifdef IFORCE_232
-	if (HI(iforce->expect_packet) == HI(cmd)) {
-		iforce->expect_packet = 0;
-		iforce->ecmd = cmd;
-		memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
-		if (waitqueue_active(&iforce->wait))
-			wake_up(&iforce->wait);
-	}
-#endif
-
-	if (!iforce->type)
-		return;
-
-	switch (HI(cmd)) {
-
-		case 0x01:	/* joystick position data */
-		case 0x03:	/* wheel position data */
-
-			if (HI(cmd) == 1) {
-				input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
-				input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
-				input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
-			} else {
-				input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0]));
-				input_report_abs(dev, ABS_GAS,   255 - data[2]);
-				input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
-			}
-
-			input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
-			input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
-
-			for (i = 0; iforce->type->btn[i] >= 0; i++)
-				input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7)));
-
-			break;
-
-		case 0x02:	/* status report */
-
-			input_report_key(dev, BTN_DEAD, data[0] & 0x02);
-			break;
-	}
-}
-
-static int get_id_packet(struct iforce *iforce, char *packet)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int timeout = HZ; /* 1 second */
-
-	switch (iforce->bus) {
-
-#ifdef IFORCE_USB
-		case IFORCE_USB:
-
-			iforce->dr.bRequest = packet[0];
-			iforce->ctrl->dev = iforce->usbdev;
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			add_wait_queue(&iforce->wait, &wait);
-
-			if (usb_submit_urb(iforce->ctrl)) {
-				set_current_state(TASK_RUNNING);
-				remove_wait_queue(&iforce->wait, &wait);
-				return -1;
-			}
-
-			while (timeout && iforce->ctrl->status == -EINPROGRESS)
-				timeout = schedule_timeout(timeout);
-
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&iforce->wait, &wait);
-
-			if (!timeout) {
-				usb_unlink_urb(iforce->ctrl);
-				return -1;
-			}
-
-			break;
-#endif
-#ifdef IFORCE_232
-		case IFORCE_232:
-
-			iforce->expect_packet = FF_CMD_QUERY;
-			send_packet(iforce, FF_CMD_QUERY, packet);
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			add_wait_queue(&iforce->wait, &wait);
-
-			while (timeout && iforce->expect_packet)
-				timeout = schedule_timeout(timeout);
-
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&iforce->wait, &wait);
-
-			if (!timeout) {
-				iforce->expect_packet = 0;
-				return -1;
-			}
-
-			break;
-#endif
-	}
-
-	return -(iforce->edata[0] != packet[0]);
-}
-
-static int iforce_open(struct input_dev *dev)
-{
-	struct iforce *iforce = dev->private;
-
-	switch (iforce->bus) {
-#ifdef IFORCE_USB
-		case IFORCE_USB:
-			if (iforce->open++)
-				break;
-			iforce->irq->dev = iforce->usbdev;
-			if (usb_submit_urb(iforce->irq))
-					return -EIO;
-			break;
-#endif
-	}
-	return 0;
-}
-
-static void iforce_close(struct input_dev *dev)
-{
-	struct iforce *iforce = dev->private;
-
-	switch (iforce->bus) {
-#ifdef IFORCE_USB
-		case IFORCE_USB:
-			if (!--iforce->open)
-				usb_unlink_urb(iforce->irq);
-			break;
-#endif
-	}
-}
-
-/*
- * Start or stop playing an effect
- */
-
-static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	struct iforce* iforce = (struct iforce*)(dev->private);
-	unsigned char data[3];
-
-	printk(KERN_DEBUG "iforce.c: input_event(type = %d, code = %d, value = %d)\n", type, code, value);
-
-	if (type != EV_FF)
-		return -1;
-
-	switch (code) {
-
-		case FF_GAIN:
-
-			data[0] = value >> 9;
-			send_packet(iforce, FF_CMD_GAIN, data);
-
-			return 0;
-
-		case FF_AUTOCENTER:
-
-			data[0] = 0x03;
-			data[1] = value >> 9;
-			send_packet(iforce, FF_CMD_AUTOCENTER, data);
-
-			data[0] = 0x04;
-			data[1] = 0x01;
-			send_packet(iforce, FF_CMD_AUTOCENTER, data);
-
-			return 0;
-
-		default: /* Play an effect */
-
-			if (code >= iforce->dev.ff_effects_max)
-				return -1;
-
-			data[0] = LO(code);
-			data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
-			data[2] = LO(value);
-			send_packet(iforce, FF_CMD_PLAY, data);
-
-			return 0;
-	}
-
-	return -1;
-}
-
-/*
- * Set the magnitude of a constant force effect
- * Return error code
- *
- * Note: caller must ensure exclusive access to device
- */
-
-static int make_magnitude_modifier(struct iforce* iforce,
-	struct resource* mod_chunk, __s16 level)
-{
-	unsigned char data[3];
-
-	if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
-		iforce->device_memory.start, iforce->device_memory.end, 2L,
-		NULL, NULL)) {
-		return -ENOMEM;
-	}
-
-	data[0] = LO(mod_chunk->start);
-	data[1] = HI(mod_chunk->start);
-	data[2] = HI(level);
-
-	send_packet(iforce, FF_CMD_MAGNITUDE, data);
-
-	return 0;
-}
-
-/*
- * Upload the component of an effect dealing with the period, phase and magnitude
- */
-
-static int make_period_modifier(struct iforce* iforce, struct resource* mod_chunk,
-	__s16 magnitude, __s16 offset, u16 period, u16 phase)
-{
-	unsigned char data[7];
-
-	period = TIME_SCALE(period);
-
-	if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
-		iforce->device_memory.start, iforce->device_memory.end, 2L,
-		NULL, NULL)) {
-		return -ENOMEM;
-	}
-
-	data[0] = LO(mod_chunk->start);
-	data[1] = HI(mod_chunk->start);
-
-	data[2] = HI(magnitude);
-	data[3] = HI(offset);
-	data[4] = HI(phase);
-
-	data[5] = LO(period);
-	data[6] = HI(period);
-
-	send_packet(iforce, FF_CMD_PERIOD, data);
-
-	return 0;
-}
-
-/*
- * Uploads the part of an effect setting the shape of the force
- */
-
-static int make_shape_modifier(struct iforce* iforce, struct resource* mod_chunk,
-	u16 attack_duration, __s16 initial_level,
-	u16 fade_duration, __s16 final_level)
-{
-	unsigned char data[8];
-
-	attack_duration = TIME_SCALE(attack_duration);
-	fade_duration = TIME_SCALE(fade_duration);
-
-	if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
-		iforce->device_memory.start, iforce->device_memory.end, 2L,
-		NULL, NULL)) {
-		return -ENOMEM;
-	}
-
-	data[0] = LO(mod_chunk->start);
-	data[1] = HI(mod_chunk->start);
-
-	data[2] = LO(attack_duration);
-	data[3] = HI(attack_duration);
-	data[4] = HI(initial_level);
-
-	data[5] = LO(fade_duration);
-	data[6] = HI(fade_duration);
-	data[7] = HI(final_level);
-
-	send_packet(iforce, FF_CMD_SHAPE, data);
-
-	return 0;
-}
-
-/*
- * Component of spring, friction, inertia... effects
- */
-
-static int make_interactive_modifier(struct iforce* iforce,
-	struct resource* mod_chunk,
-	__s16 rsat, __s16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center)
-{
-	unsigned char data[10];
-
-	if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
-		iforce->device_memory.start, iforce->device_memory.end, 2L,
-		NULL, NULL)) {
-		return -ENOMEM;
-	}
-
-	data[0] = LO(mod_chunk->start);
-	data[1] = HI(mod_chunk->start);
-
-	data[2] = HI(rk);
-	data[3] = HI(lk);
-
-	data[4] = LO(center);
-	data[5] = HI(center);
-
-	data[6] = LO(db);
-	data[7] = HI(db);
-
-	data[8] = HI(rsat);
-	data[9] = HI(lsat);
-
-	send_packet(iforce, FF_CMD_INTERACT, data);
-
-	return 0;
-}
-
-static unsigned char find_button(struct iforce *iforce, signed short button)
-{
-	int i;
-	for (i = 1; iforce->type->btn[i] >= 0; i++)
-		if (iforce->type->btn[i] == button)
-			return i + 1;
-	return 0;
-}
-
-/*
- * Send the part common to all effects to the device
- */
-
-static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2,
-	u8 effect_type, u8 axes, u16 duration, u16 delay, u16 button,
-	u16 interval, u16 direction)
-{
-	unsigned char data[14];
-
-	duration = TIME_SCALE(duration);
-	delay    = TIME_SCALE(delay);
-	interval = TIME_SCALE(interval);
-
-	data[0]  = LO(id);
-	data[1]  = effect_type;
-	data[2]  = LO(axes) | find_button(iforce, button);
-
-	data[3]  = LO(duration);
-	data[4]  = HI(duration);
-
-	data[5]  = HI(direction);
-
-	data[6]  = LO(interval);
-	data[7]  = HI(interval);
-
-	data[8]  = LO(mod_id1);
-	data[9]  = HI(mod_id1);
-	data[10] = LO(mod_id2);
-	data[11] = HI(mod_id2);
-
-	data[12] = LO(delay);
-	data[13] = HI(delay);
-
-	send_packet(iforce, FF_CMD_EFFECT, data);
-
-	return 0;
-}
-
-/*
- * Upload a periodic effect to the device
- */
-
-static int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect)
-{
-	u8 wave_code;
-	int core_id = effect->id;
-	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
-	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
-	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
-	int err = 0;
-
-	err = make_period_modifier(iforce, mod1_chunk,
-		effect->u.periodic.magnitude, effect->u.periodic.offset,
-		effect->u.periodic.period, effect->u.periodic.phase);
-	if (err) return err;
-	set_bit(FF_MOD1_IS_USED, core_effect->flags);
-
-	err = make_shape_modifier(iforce, mod2_chunk,
-		effect->u.periodic.shape.attack_length,
-		effect->u.periodic.shape.attack_level,
-		effect->u.periodic.shape.fade_length,
-		effect->u.periodic.shape.fade_level);
-	if (err) return err;
-	set_bit(FF_MOD2_IS_USED, core_effect->flags);
-
-	switch (effect->u.periodic.waveform) {
-		case FF_SQUARE:		wave_code = 0x20; break;
-		case FF_TRIANGLE:	wave_code = 0x21; break;
-		case FF_SINE:		wave_code = 0x22; break;
-		case FF_SAW_UP:		wave_code = 0x23; break;
-		case FF_SAW_DOWN:	wave_code = 0x24; break;
-		default:		wave_code = 0x20; break;
-	}
-
-	err = make_core(iforce, effect->id,
-		mod1_chunk->start,
-		mod2_chunk->start,
-		wave_code,
-		0x20,
-		effect->replay.length,
-		effect->replay.delay,
-		effect->trigger.button,
-		effect->trigger.interval,
-		effect->u.periodic.direction);
-
-	return err;
-}
-
-/*
- * Upload a constant force effect
- */
-static int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect)
-{
-	int core_id = effect->id;
-	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
-	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
-	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
-	int err = 0;
-
-	printk(KERN_DEBUG "iforce.c: make constant effect\n");
-
-	err = make_magnitude_modifier(iforce, mod1_chunk, effect->u.constant.level);
-	if (err) return err;
-	set_bit(FF_MOD1_IS_USED, core_effect->flags);
-
-	err = make_shape_modifier(iforce, mod2_chunk,
-		effect->u.constant.shape.attack_length,
-		effect->u.constant.shape.attack_level,
-		effect->u.constant.shape.fade_length,
-		effect->u.constant.shape.fade_level);
-	if (err) return err;
-	set_bit(FF_MOD2_IS_USED, core_effect->flags);
-
-	err = make_core(iforce, effect->id,
-		mod1_chunk->start,
-		mod2_chunk->start,
-		0x00,
-		0x20,
-		effect->replay.length,
-		effect->replay.delay,
-		effect->trigger.button,
-		effect->trigger.interval,
-		effect->u.constant.direction);
-
-	return err;
-}
-
-/*
- * Upload an interactive effect. Those are for example friction, inertia, springs...
- */
-static int iforce_upload_interactive(struct iforce* iforce, struct ff_effect* effect)
-{
-	int core_id = effect->id;
-	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
-	struct resource* mod_chunk = &(core_effect->mod1_chunk);
-	u8 type, axes;
-	u16 mod1, mod2, direction;
-	int err = 0;
-
-	printk(KERN_DEBUG "iforce.c: make interactive effect\n");
-
-	switch (effect->type) {
-		case FF_SPRING:		type = 0x40; break;
-		case FF_FRICTION:	type = 0x41; break;
-		default: return -1;
-	}
-
-	err = make_interactive_modifier(iforce, mod_chunk,
-		effect->u.interactive.right_saturation,
-		effect->u.interactive.left_saturation,
-		effect->u.interactive.right_coeff,
-		effect->u.interactive.left_coeff,
-		effect->u.interactive.deadband,
-		effect->u.interactive.center);
-	if (err) return err;
-	set_bit(FF_MOD1_IS_USED, core_effect->flags);
-
-	switch ((test_bit(ABS_X, &effect->u.interactive.axis) ||
-		test_bit(ABS_WHEEL, &effect->u.interactive.axis)) |
-		(!!test_bit(ABS_Y, &effect->u.interactive.axis) << 1)) {
-
-		case 0: /* Only one axis, choose orientation */
-			mod1 = mod_chunk->start;
-			mod2 = 0xffff;
-			direction = effect->u.interactive.direction;
-			axes = 0x20;
-			break;
-
-		case 1:	/* Only X axis */
-			mod1 = mod_chunk->start;
-			mod2 = 0xffff;
-			direction = 0x5a00;
-			axes = 0x40;
-			break;
-
-		case 2: /* Only Y axis */
-			mod1 = 0xffff;
-			mod2 = mod_chunk->start;
-			direction = 0xb400;
-			axes = 0x80;
-			break;
-
-		case 3:	/* Both X and Y axes */
-			/* TODO: same setting for both axes is not mandatory */
-			mod1 = mod_chunk->start;
-			mod2 = mod_chunk->start;
-			direction = 0x6000;
-			axes = 0xc0;
-			break;
-
-		default:
-			return -1;
-	}
-
-	err = make_core(iforce, effect->id,
-		mod1, mod2,
-		type, axes,
-		effect->replay.length, effect->replay.delay,
-		effect->trigger.button, effect->trigger.interval,
-		direction);
-
-	return err;
-}
-
-/*
- * Function called when an ioctl is performed on the event dev entry.
- * It uploads an effect to the device
- */
-static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
-{
-	struct iforce* iforce = (struct iforce*)(dev->private);
-	int id;
-
-	printk(KERN_DEBUG "iforce.c: upload effect\n");
-
-/*
- * Get a free id
- */
-
-	for (id=0; id < FF_EFFECTS_MAX; ++id)
-		if (!test_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
-
-	if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
-		return -ENOMEM;
-
-	effect->id = id;
-	set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags);
-
-/*
- * Upload the effect
- */
-
-	switch (effect->type) {
-
-		case FF_PERIODIC:
-			return iforce_upload_periodic(iforce, effect);
-
-		case FF_CONSTANT:
-			return iforce_upload_constant(iforce, effect);
-
-		case FF_SPRING:
-		case FF_FRICTION:
-			return iforce_upload_interactive(iforce, effect);
-
-		default:
-			return -1;
-	}
-}
-
-/*
- * Erases an effect: it frees the effect id and mark as unused the memory
- * allocated for the parameters
- */
-static int iforce_erase_effect(struct input_dev *dev, int effect_id)
-{
-	struct iforce* iforce = (struct iforce*)(dev->private);
-	int err = 0;
-	struct iforce_core_effect* core_effect;
-
-	printk(KERN_DEBUG "iforce.c: erase effect %d\n", effect_id);
-
-	if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
-		return -EINVAL;
-
-	core_effect = iforce->core_effects + effect_id;
-
-	if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
-		err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
-
-	if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
-		err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
-
-	/*TODO: remember to change that if more FF_MOD* bits are added */
-	core_effect->flags[0] = 0;
-
-	return err;
-}
-static int iforce_init_device(struct iforce *iforce)
-{
-	unsigned char c[] = "CEOV";
-	int i;
-
-	init_waitqueue_head(&iforce->wait);
-	iforce->dev.ff_effects_max = 10;
-
-/*
- * Input device fields.
- */
-
-	iforce->dev.idbus = BUS_USB;
-	iforce->dev.private = iforce;
-	iforce->dev.name = iforce->name;
-	iforce->dev.open = iforce_open;
-	iforce->dev.close = iforce_close;
-	iforce->dev.event = iforce_input_event;
-	iforce->dev.upload_effect = iforce_upload_effect;
-	iforce->dev.erase_effect = iforce_erase_effect;
-
-/*
- * On-device memory allocation.
- */
-
-	iforce->device_memory.name = "I-Force device effect memory";
-	iforce->device_memory.start = 0;
-	iforce->device_memory.end = 200;
-	iforce->device_memory.flags = IORESOURCE_MEM;
-	iforce->device_memory.parent = NULL;
-	iforce->device_memory.child = NULL;
-	iforce->device_memory.sibling = NULL;
-
-/*
- * Wait until device ready - until it sends its first response.
- */
-
-	for (i = 0; i < 20; i++)
-		if (!get_id_packet(iforce, "O"))
-			break;
-
-	if (i == 20) { /* 5 seconds */
-		printk(KERN_ERR "iforce.c: Timeout waiting for response from device.\n");
-		iforce_close(&iforce->dev);
-		return -1;
-	}
-
-/*
- * Get device info.
- */
-
-	if (!get_id_packet(iforce, "M"))
-		iforce->dev.idvendor = (iforce->edata[2] << 8) | iforce->edata[1];
-	if (!get_id_packet(iforce, "P"))
-		iforce->dev.idproduct = (iforce->edata[2] << 8) | iforce->edata[1];
-	if (!get_id_packet(iforce, "B"))
-		iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
-	if (!get_id_packet(iforce, "N"))
-		iforce->dev.ff_effects_max = iforce->edata[1];
-
-/*
- * Display additional info.
- */
-
-	for (i = 0; c[i]; i++)
-		if (!get_id_packet(iforce, c + i))
-			dump_packet("info", iforce->ecmd, iforce->edata);
-
-/*
- * Disable spring, enable force feedback.
- * FIXME: We should use iforce_set_autocenter() et al here.
- */
-
-	send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");
-	send_packet(iforce, FF_CMD_ENABLE, "\004");
-
-/*
- * Find appropriate device entry
- */
-
-	for (i = 0; iforce_device[i].idvendor; i++)
-		if (iforce_device[i].idvendor == iforce->dev.idvendor &&
-		    iforce_device[i].idproduct == iforce->dev.idproduct)
-			break;
-
-	iforce->type = iforce_device + i;
-
-	sprintf(iforce->name, iforce->type->name,
-		iforce->dev.idproduct, iforce->dev.idvendor);
-
-/*
- * Set input device bitfields and ranges.
- */
-
-	iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF);
-
-	for (i = 0; iforce->type->btn[i] >= 0; i++) {
-		signed short t = iforce->type->btn[i];
-		set_bit(t, iforce->dev.keybit);
-		if (t != BTN_DEAD)
-			set_bit(FF_BTN(t), iforce->dev.ffbit);
-	}
-
-	for (i = 0; iforce->type->abs[i] >= 0; i++) {
-
-		signed short t = iforce->type->abs[i];
-		set_bit(t, iforce->dev.absbit);
-
-		switch (t) {
-
-			case ABS_X:
-			case ABS_Y:
-			case ABS_WHEEL:
-
-				iforce->dev.absmax[t] =  1920;
-				iforce->dev.absmin[t] = -1920;
-				iforce->dev.absflat[t] = 128;
-				iforce->dev.absfuzz[t] = 16;
-
-				set_bit(FF_ABS(t), iforce->dev.ffbit);
-				break;
-
-			case ABS_THROTTLE:
-			case ABS_GAS:
-			case ABS_BRAKE:
-
-				iforce->dev.absmax[t] = 255;
-				iforce->dev.absmin[t] = 0;
-				break;
-
-			case ABS_HAT0X:
-			case ABS_HAT0Y:
-				iforce->dev.absmax[t] =  1;
-				iforce->dev.absmin[t] = -1;
-				break;
-		}
-	}
-
-	for (i = 0; iforce->type->ff[i] >= 0; i++)
-		set_bit(iforce->type->ff[i], iforce->dev.ffbit);
-
-/*
- * Register input device.
- */
-
-	input_register_device(&iforce->dev);
-
-	return 0;
-}
-
-#ifdef IFORCE_USB
-
-static void iforce_usb_irq(struct urb *urb)
-{
-	struct iforce *iforce = urb->context;
-	if (urb->status) return;
-	iforce_process_packet(iforce,
-		(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1);
-}
-
-static void iforce_usb_out(struct urb *urb)
-{
-	struct iforce *iforce = urb->context;
-	if (urb->status) return;
-	if (waitqueue_active(&iforce->wait))
-		wake_up(&iforce->wait);
-}
-
-static void iforce_usb_ctrl(struct urb *urb)
-{
-	struct iforce *iforce = urb->context;
-	if (urb->status) return;
-	iforce->ecmd = 0xff00 | urb->actual_length;
-	if (waitqueue_active(&iforce->wait))
-		wake_up(&iforce->wait);
-}
-
-static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum,
-				const struct usb_device_id *id)
-{
-	struct usb_endpoint_descriptor *epirq, *epout;
-	struct iforce *iforce;
-
-	epirq = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
-	epout = dev->config[0].interface[ifnum].altsetting[0].endpoint + 1;
-
-	if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) return NULL;
-	memset(iforce, 0, sizeof(struct iforce));
-
-	iforce->irq = usb_alloc_urb(0);
-	if (!iforce->irq) {
-		kfree(iforce);
-		return NULL;
-	}
-	iforce->out = usb_alloc_urb(0);
-	if (!iforce->out) {
-		usb_free_urb(iforce->irq);
-		kfree(iforce);
-		return NULL;
-	}
-	iforce->ctrl = usb_alloc_urb(0);
-	if (!iforce->ctrl) {
-		usb_free_urb(iforce->out);
-		usb_free_urb(iforce->irq);
-		kfree(iforce);
-		return NULL;
-	}
-
-	iforce->bus = IFORCE_USB;
-	iforce->usbdev = dev;
-
-	iforce->dr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
-	iforce->dr.wIndex = 0;
-	iforce->dr.wLength = 16;
-
-	FILL_INT_URB(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
-			iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
-
-	FILL_BULK_URB(iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
-			iforce + 1, 32, iforce_usb_out, iforce);
-
-	FILL_CONTROL_URB(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
-			(void*) &iforce->dr, iforce->edata, 16, iforce_usb_ctrl, iforce);
-
-	if (iforce_init_device(iforce)) {
-		usb_free_urb(iforce->ctrl);
-		usb_free_urb(iforce->out);
-		usb_free_urb(iforce->irq);
-		kfree(iforce);
-		return NULL;
-	}
-
-	printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on usb%d:%d.%d\n",
-		iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,
-		iforce->device_memory.end, dev->bus->busnum, dev->devnum, ifnum);
-
-	return iforce;
-}
-
-static void iforce_usb_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct iforce *iforce = ptr;
-	usb_unlink_urb(iforce->irq);
-	input_unregister_device(&iforce->dev);
-	usb_free_urb(iforce->ctrl);
-	usb_free_urb(iforce->out);
-	usb_free_urb(iforce->irq);
-	kfree(iforce);
-}
-
-static struct usb_device_id iforce_usb_ids [] = {
-	{ USB_DEVICE(0x046d, 0xc281) },		/* Logitech WingMan Force */
-	{ USB_DEVICE(0x046d, 0xc291) },		/* Logitech WingMan Formula Force */
-	{ USB_DEVICE(0x05ef, 0x020a) },		/* AVB Top Shot Pegasus */
-	{ USB_DEVICE(0x05ef, 0x8884) },		/* AVB Mag Turbo Force */
-	{ USB_DEVICE(0x06f8, 0x0001) },		/* Guillemot Race Leader Force Feedback */
-	{ }					/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
-
-static struct usb_driver iforce_usb_driver = {
-	name:		"iforce",
-	probe:		iforce_usb_probe,
-	disconnect:	iforce_usb_disconnect,
-	id_table:	iforce_usb_ids,
-};
-
-#endif
-
-#ifdef IFORCE_232
-
-static void iforce_serio_irq(struct serio *serio, unsigned char data, unsigned int flags)
-{
-	struct iforce* iforce = serio->private;
-
-	if (!iforce->pkt) {
-		if (data != 0x2b) {
-			return;
-		}
-		iforce->pkt = 1;
-		return;
-	}
-
-	if (!iforce->id) {
-		if (data > 3 && data != 0xff) {
-			iforce->pkt = 0;
-			return;
-		}
-		iforce->id = data;
-		return;
-	}
-
-	if (!iforce->len) {
-		if (data > IFORCE_MAX_LENGTH) {
-			iforce->pkt = 0;
-			iforce->id = 0;
-			return;
-		}
-		iforce->len = data;
-		return;
-	}
-
-	if (iforce->idx < iforce->len) {
-		iforce->csum += iforce->data[iforce->idx++] = data;
-		return;
-	}
-
-	if (iforce->idx == iforce->len) {
-		iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data);
-		iforce->pkt = 0;
-		iforce->id  = 0;
-		iforce->len = 0;
-		iforce->idx = 0;
-		iforce->csum = 0;
-	}
-}
-
-static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
-{
-	struct iforce *iforce;
-	if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
-		return;
-
-	if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return;
-	memset(iforce, 0, sizeof(struct iforce));
-
-	iforce->bus = IFORCE_232;
-	iforce->serio = serio;
-	serio->private = iforce;
-
-	if (serio_open(serio, dev)) {
-		kfree(iforce);
-		return;
-	}
-
-	if (iforce_init_device(iforce)) {
-		serio_close(serio);
-		kfree(iforce);
-		return;
-	}
-
-	printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on serio%d\n",
-		iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,
-		iforce->device_memory.end, serio->number);
-}
-
-static void iforce_serio_disconnect(struct serio *serio)
-{
-	struct iforce* iforce = serio->private;
-
-	input_unregister_device(&iforce->dev);
-	serio_close(serio);
-	kfree(iforce);
-}
-
-static struct serio_dev iforce_serio_dev = {
-	interrupt:	iforce_serio_irq,
-	connect:	iforce_serio_connect,
-	disconnect:	iforce_serio_disconnect,
-};
-
-#endif
-
-static int __init iforce_init(void)
-{
-#ifdef IFORCE_USB
-	usb_register(&iforce_usb_driver);
-#endif
-#ifdef IFORCE_232
-	serio_register_device(&iforce_serio_dev);
-#endif
-	return 0;
-}
-
-static void __exit iforce_exit(void)
-{
-#ifdef IFORCE_USB
-	usb_deregister(&iforce_usb_driver);
-#endif
-#ifdef IFORCE_232
-	serio_unregister_device(&iforce_serio_dev);
-#endif
-}
-
-module_init(iforce_init);
-module_exit(iforce_exit);
diff -Nru a/drivers/char/joystick/interact.c b/drivers/char/joystick/interact.c
--- a/drivers/char/joystick/interact.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,308 +0,0 @@
-/*
- * $Id: interact.c,v 1.8 2000/05/29 11:19:51 vojtech Exp $
- *
- *  Copyright (c) 2000 Vojtech Pavlik
- *
- *  Based on the work of:
- *	Toby Deshane
- *
- *  Sponsored by SuSE
- */
-
-/*
- * InterAct digital gamepad/joystick driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/input.h>
-
-#define INTERACT_MAX_START	400	/* 400 us */
-#define INTERACT_MAX_STROBE	40	/* 40 us */
-#define INTERACT_MAX_LENGTH	32	/* 32 bits */
-#define INTERACT_REFRESH_TIME	HZ/50	/* 20 ms */
-
-#define INTERACT_TYPE_HHFX	0	/* HammerHead/FX */
-#define INTERACT_TYPE_PP8D	1	/* ProPad 8 */
-
-struct interact {
-	struct gameport *gameport;
-	struct input_dev dev;
-	struct timer_list timer;
-	int used;
-	int bads;
-	int reads;
-	unsigned char type;
-	unsigned char length;
-};
-
-static short interact_abs_hhfx[] = 
-	{ ABS_RX, ABS_RY, ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y, -1 };
-static short interact_abs_pp8d[] =
-	{ ABS_X, ABS_Y, -1 };
-
-static short interact_btn_hhfx[] =
-	{ BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL, BTN_TL2, BTN_TR2, BTN_MODE, BTN_SELECT, -1 };
-static short interact_btn_pp8d[] =
-	{ BTN_C, BTN_TL, BTN_TR, BTN_A, BTN_B, BTN_Y, BTN_Z, BTN_X, -1 };
-
-struct interact_type {
-	int id;
-	short *abs;
-	short *btn;
-	char *name;
-	unsigned char length;
-	unsigned char b8;
-};
-
-static struct interact_type interact_type[] = {
-	{ 0x6202, interact_abs_hhfx, interact_btn_hhfx, "InterAct HammerHead/FX",    32, 4 },
-	{ 0x53f8, interact_abs_pp8d, interact_btn_pp8d, "InterAct ProPad 8 Digital", 16, 0 },
-	{ 0 }};
-
-/*
- * interact_read_packet() reads and InterAct joystick data.
- */
-
-static int interact_read_packet(struct gameport *gameport, int length, u32 *data)
-{
-	unsigned long flags;
-	unsigned char u, v;
-	unsigned int t, s;
-	int i;
-
-	i = 0;
-	data[0] = data[1] = data[2] = 0;
-	t = gameport_time(gameport, INTERACT_MAX_START);
-	s = gameport_time(gameport, INTERACT_MAX_STROBE);
-
-	__save_flags(flags);
-	__cli();
-	gameport_trigger(gameport);
-	v = gameport_read(gameport);
-
-	while (t > 0 && i < length) {
-		t--;
-		u = v; v = gameport_read(gameport);
-		if (v & ~u & 0x40) {
-			data[0] = (data[0] << 1) | ((v >> 4) & 1);
-			data[1] = (data[1] << 1) | ((v >> 5) & 1);
-			data[2] = (data[2] << 1) | ((v >> 7) & 1);
-			i++;
-			t = s;
-		}
-	}
-
-	__restore_flags(flags);
-
-	return i;
-}
-
-/*
- * interact_timer() reads and analyzes InterAct joystick data.
- */
-
-static void interact_timer(unsigned long private)
-{
-	struct interact *interact = (struct interact *) private;
-	struct input_dev *dev = &interact->dev;
-	u32 data[3];
-	int i;
-
-	interact->reads++;
-
-	if (interact_read_packet(interact->gameport, interact->length, data) < interact->length) {
-		interact->bads++;
-	} else
-
-	for (i = 0; i < 3; i++)
-		data[i] <<= INTERACT_MAX_LENGTH - interact->length;
-
-	switch (interact->type) {
-
-		case INTERACT_TYPE_HHFX:
-
-			for (i = 0; i < 4; i++)
-				input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);
-
-			for (i = 0; i < 2; i++)
-				input_report_abs(dev, ABS_HAT0Y - i,
-					((data[1] >> ((i << 1) + 17)) & 1)  - ((data[1] >> ((i << 1) + 16)) & 1));
-
-			for (i = 0; i < 8; i++)
-				input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);
-
-			for (i = 0; i < 4; i++)
-				input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);
-
-			break;
-
-		case INTERACT_TYPE_PP8D:
-
-			for (i = 0; i < 2; i++)
-				input_report_abs(dev, interact_abs_pp8d[i], 
-					((data[0] >> ((i << 1) + 20)) & 1)  - ((data[0] >> ((i << 1) + 21)) & 1));
-
-			for (i = 0; i < 8; i++)
-				input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);
-
-			break;
-	}
-
-	mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
-
-}
-
-/*
- * interact_open() is a callback from the input open routine.
- */
-
-static int interact_open(struct input_dev *dev)
-{
-	struct interact *interact = dev->private;
-	if (!interact->used++)
-		mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);	
-	return 0;
-}
-
-/*
- * interact_close() is a callback from the input close routine.
- */
-
-static void interact_close(struct input_dev *dev)
-{
-	struct interact *interact = dev->private;
-	if (!--interact->used)
-		del_timer(&interact->timer);
-}
-
-/*
- * interact_connect() probes for InterAct joysticks.
- */
-
-static void interact_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct interact *interact;
-	__u32 data[3];
-	int i, t;
-
-	if (!(interact = kmalloc(sizeof(struct interact), GFP_KERNEL)))
-		return;
-	memset(interact, 0, sizeof(struct interact));
-
-	gameport->private = interact;
-
-	interact->gameport = gameport;
-	init_timer(&interact->timer);
-	interact->timer.data = (long) interact;
-	interact->timer.function = interact_timer;
-
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		goto fail1;
-
-	i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);
-
-	if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
-		goto fail2;
-	}
-
-	for (i = 0; interact_type[i].length; i++)
-		if (interact_type[i].id == (data[2] >> 16))
-			break;
-
-	if (!interact_type[i].length) {
-		printk(KERN_WARNING "interact.c: Unknown joystick on gameport%d. [len %d d0 %08x d1 %08x i2 %08x]\n",
-			gameport->number, i, data[0], data[1], data[2]);
-		goto fail2;	
-	}
-
-	interact->type = i;
-	interact->length = interact_type[i].length;
-
-	interact->dev.private = interact;
-	interact->dev.open = interact_open;
-	interact->dev.close = interact_close;
-
-	interact->dev.name = interact_type[i].name;
-	interact->dev.idbus = BUS_GAMEPORT;
-	interact->dev.idvendor = GAMEPORT_ID_VENDOR_INTERACT;
-	interact->dev.idproduct = interact_type[i].id;
-	interact->dev.idversion = 0x0100;
-
-	interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-	for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
-		set_bit(t, interact->dev.absbit);
-		if (i < interact_type[interact->type].b8) {
-			interact->dev.absmin[t] = 0;
-			interact->dev.absmax[t] = 255;
-		} else {
-			interact->dev.absmin[t] = -1;
-			interact->dev.absmax[t] = 1;
-		}
-	}
-
-	for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
-		set_bit(t, interact->dev.keybit);
-
-	input_register_device(&interact->dev);
-	printk(KERN_INFO "input%d: %s on gameport%d.0\n",
-		interact->dev.number, interact_type[interact->type].name, gameport->number);
-
-	return;
-fail2:	gameport_close(gameport);
-fail1:  kfree(interact);
-}
-
-static void interact_disconnect(struct gameport *gameport)
-{
-	struct interact *interact = gameport->private;
-	input_unregister_device(&interact->dev);
-	gameport_close(gameport);
-	kfree(interact);
-}
-
-static struct gameport_dev interact_dev = {
-	connect:	interact_connect,
-	disconnect:	interact_disconnect,
-};
-
-int __init interact_init(void)
-{
-	gameport_register_device(&interact_dev);
-	return 0;
-}
-
-void __exit interact_exit(void)
-{
-	gameport_unregister_device(&interact_dev);
-}
-
-module_init(interact_init);
-module_exit(interact_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/lightning.c b/drivers/char/joystick/lightning.c
--- a/drivers/char/joystick/lightning.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,298 +0,0 @@
-/*
- * $Id: lightning.c,v 1.13 2001/04/26 10:24:46 vojtech Exp $
- *
- *  Copyright (c) 1998-2001 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * PDPI Lightning 4 gamecard driver for Linux.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/slab.h>
-
-#define L4_PORT			0x201
-#define L4_SELECT_ANALOG	0xa4
-#define L4_SELECT_DIGITAL	0xa5
-#define L4_SELECT_SECONDARY	0xa6
-#define L4_CMD_ID		0x80
-#define L4_CMD_GETCAL		0x92
-#define L4_CMD_SETCAL		0x93
-#define L4_ID			0x04
-#define L4_BUSY			0x01
-#define L4_TIMEOUT		80	/* 80 us */
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_LICENSE("GPL");
-
-struct l4 {
-	struct gameport gameport;
-	unsigned char port;
-} *l4_port[8];
-
-/*
- * l4_wait_ready() waits for the L4 to become ready.
- */
-
-static int l4_wait_ready(void)
-{
-	unsigned int t;
-	t = L4_TIMEOUT;
-	while ((inb(L4_PORT) & L4_BUSY) && t > 0) t--;
-	return -(t<=0);
-}
-
-/*
- * l4_cooked_read() reads data from the Lightning 4.
- */
-
-static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
-{
-	struct l4 *l4 = gameport->private;
-	unsigned char status;
-	int i, result = -1;
-
-	outb(L4_SELECT_ANALOG, L4_PORT);
-	outb(L4_SELECT_DIGITAL + (l4->port >> 2), L4_PORT);
-
-	if (inb(L4_PORT) & L4_BUSY) goto fail;
-	outb(l4->port & 3, L4_PORT);
-
-	if (l4_wait_ready()) goto fail;
-	status = inb(L4_PORT);
-
-	for (i = 0; i < 4; i++)
-		if (status & (1 << i)) {
-			if (l4_wait_ready()) goto fail;
-			axes[i] = inb(L4_PORT);
-			if (axes[i] > 252) axes[i] = -1;
-		}
-
-	if (status & 0x10) {
-		if (l4_wait_ready()) goto fail;
-		*buttons = inb(L4_PORT) & 0x0f;
-	}
-
-	result = 0;
-
-fail:	outb(L4_SELECT_ANALOG, L4_PORT);	
-	return result;
-}
-
-static int l4_open(struct gameport *gameport, int mode)
-{
-	struct l4 *l4 = gameport->private;
-        if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
-		return -1;
-	outb(L4_SELECT_ANALOG, L4_PORT);
-	return 0;
-}
-
-/*
- * l4_getcal() reads the L4 with calibration values.
- */
-
-static int l4_getcal(int port, int *cal)
-{
-	int i, result = -1;
-	
-	outb(L4_SELECT_ANALOG, L4_PORT);
-	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
-
-	if (inb(L4_PORT) & L4_BUSY) goto fail;
-	outb(L4_CMD_GETCAL, L4_PORT);
-
-	if (l4_wait_ready()) goto fail;
-	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
-
-	if (l4_wait_ready()) goto fail;
-        outb(port & 3, L4_PORT);
-
-	for (i = 0; i < 4; i++) {
-		if (l4_wait_ready()) goto fail;
-		cal[i] = inb(L4_PORT);
-	}
-
-	result = 0;
-
-fail:	outb(L4_SELECT_ANALOG, L4_PORT);
-	return result;
-}
-
-/*
- * l4_setcal() programs the L4 with calibration values.
- */
-
-static int l4_setcal(int port, int *cal)
-{
-	int i, result = -1;
-
-	outb(L4_SELECT_ANALOG, L4_PORT);
-	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
-
-	if (inb(L4_PORT) & L4_BUSY) goto fail;
-	outb(L4_CMD_SETCAL, L4_PORT);
-
-	if (l4_wait_ready()) goto fail;
-	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
-
-	if (l4_wait_ready()) goto fail;
-        outb(port & 3, L4_PORT);
-
-	for (i = 0; i < 4; i++) {
-		if (l4_wait_ready()) goto fail;
-		outb(cal[i], L4_PORT);
-	}
-
-	result = 0;
-
-fail:	outb(L4_SELECT_ANALOG, L4_PORT);
-	return result;
-}
-
-/*
- * l4_calibrate() calibrates the L4 for the attached device, so
- * that the device's resistance fits into the L4's 8-bit range.
- */
-
-static int l4_calibrate(struct gameport *gameport, int *axes, int *max)
-{
-	int i, t;
-	int cal[4];
-	struct l4 *l4 = gameport->private;
-
-	if (l4_getcal(l4->port, cal))
-		return -1;
-
-	for (i = 0; i < 4; i++) {
-		t = (max[i] * cal[i]) / 200;
-		t = (t < 1) ? 1 : ((t > 255) ? 255 : t);
-		axes[i] = (axes[i] < 0) ? -1 : (axes[i] * cal[i]) / t;
-		axes[i] = (axes[i] > 252) ? 252 : axes[i];
-		cal[i] = t;
-	}
-
-	if (l4_setcal(l4->port, cal))
-		return -1;
-
-	return 0;
-}
-	
-int __init l4_init(void)
-{
-	int cal[4] = {255,255,255,255};
-	int i, j, rev, cards = 0;
-	struct gameport *gameport;
-	struct l4 *l4;
-
-	if (!request_region(L4_PORT, 1, "lightning"))
-		return -1;
-
-	for (i = 0; i < 2; i++) {
-
-		outb(L4_SELECT_ANALOG, L4_PORT);
-		outb(L4_SELECT_DIGITAL + i, L4_PORT);
-
-		if (inb(L4_PORT) & L4_BUSY) continue;
-		outb(L4_CMD_ID, L4_PORT);
-
-		if (l4_wait_ready()) continue;
-		if (inb(L4_PORT) != L4_SELECT_DIGITAL + i) continue;
-
-		if (l4_wait_ready()) continue;
-		if (inb(L4_PORT) != L4_ID) continue;
-
-		if (l4_wait_ready()) continue;
-		rev = inb(L4_PORT);
-
-		if (!rev) continue;
-
-		if (!(l4_port[i * 4] = kmalloc(sizeof(struct l4) * 4, GFP_KERNEL))) {
-			printk(KERN_ERR "lightning: Out of memory allocating ports.\n");
-			continue;
-		}
-		memset(l4_port[i * 4], 0, sizeof(struct l4) * 4);
-
-		for (j = 0; j < 4; j++) {
-
-			l4 = l4_port[i * 4 + j] = l4_port[i * 4] + j;
-			l4->port = i * 4 + j;
-
-			gameport = &l4->gameport;
-			gameport->private = l4;
-			gameport->open = l4_open;
-			gameport->cooked_read = l4_cooked_read;
-			gameport->calibrate = l4_calibrate;
-
-			if (!i && !j)
-				gameport->io = L4_PORT;
-
-			if (rev > 0x28)		/* on 2.9+ the setcal command works correctly */
-				l4_setcal(l4->port, cal);
-			
-			gameport_register_port(gameport);
-		}
-
-		printk(KERN_INFO "gameport%d,%d,%d,%d: PDPI Lightning 4 %s card v%d.%d at %#x\n",
-			l4_port[i * 4 + 0]->gameport.number, l4_port[i * 4 + 1]->gameport.number, 
-			l4_port[i * 4 + 2]->gameport.number, l4_port[i * 4 + 3]->gameport.number, 
-			i ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
-
-		cards++;
-	}
-
-	outb(L4_SELECT_ANALOG, L4_PORT);
-
-	if (!cards) {
-		release_region(L4_PORT, 1);
-		return -1;
-	}
-
-	return 0;
-}
-
-void __init l4_exit(void)
-{
-	int i;
-	int cal[4] = {59, 59, 59, 59};
-
-	for (i = 0; i < 8; i++)
-		if (l4_port[i]) {
-			l4_setcal(l4_port[i]->port, cal);
-			gameport_unregister_port(&l4_port[i]->gameport);
-		}
-	outb(L4_SELECT_ANALOG, L4_PORT);
-	release_region(L4_PORT, 1);
-}
-
-module_init(l4_init);
-module_exit(l4_exit);
diff -Nru a/drivers/char/joystick/magellan.c b/drivers/char/joystick/magellan.c
--- a/drivers/char/joystick/magellan.c	Sun Feb 10 19:58:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,212 +0,0 @@
-/*
- * $Id: magellan.c,v 1.8 2000/05/31 13:17:12 vojtech Exp $
- *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Magellan and Space Mouse 6dof controller driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- *  Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/serio.h>
-#include <linux/init.h>
-
-/*
- * Definitions & global arrays.
- */
-
-#define	MAGELLAN_MAX_LENGTH	32
-
-static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8};
-static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ};
-static char *magellan_name = "LogiCad3D Magellan";
-
-/*
- * Per-Magellan data.
- */
-
-struct magellan {
-	struct input_dev dev;
-	int idx;
-	unsigned char data[MAGELLAN_MAX_LENGTH];
-};
-
-/*
- * magellan_crunch_nibbles() verifies that the bytes sent from the Magellan
- * have correct upper nibbles for the lower ones, if not, the packet will
- * be thrown away. It also strips these upper halves to simplify further
- * processing.
- */
-
-static int magellan_crunch_nibbles(unsigned char *data, int count)
-{
-	static unsigned char nibbles[16] = "0AB3D56GH9:K<MN?";
-
-	do {
-		if (data[count] == nibbles[data[count] & 0xf])
-			data[count] = data[count] & 0xf;
-		else
-			return -1;
-	} while (--count);
-
-	return 0;
-}
-
-static void magellan_process_packet(struct magellan* magellan)
-{
-	struct input_dev *dev = &magellan->dev;
-	unsigned char *data = magellan->data;
-	int i, t;
-
-	if (!magellan->idx) return;
-
-	switch (magellan->data[0]) {
-
-		case 'd':				/* Axis data */
-			if (magellan->idx != 25) return;
-			if (magellan_crunch_nibbles(data, 24)) return;
-			for (i = 0; i < 6; i++)
-				input_report_abs(dev, magellan_axes[i],
-					(data[(i << 2) + 1] << 12 | data[(i << 2) + 2] << 8 |
-					 data[(i << 2) + 3] <<  4 | data[(i << 2) + 4]) - 32768);
-			break;
-
-		case 'k':				/* Button data */
-			if (magellan->idx != 4) return;
-			if (magellan_crunch_nibbles(data, 3)) return;
-			t = (data[1] << 1) | (data[2] << 5) | data[3];
-			for (i = 0; i < 9; i++) input_report_key(dev, magellan_buttons[i], (t >> i) & 1);
-			break;
-	}
-}
-
-static void magellan_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
-{
-	struct magellan* magellan = serio->private;
-
-	if (data == '\r') {
-		magellan_process_packet(magellan);
-		magellan->idx = 0;
-	} else {
-		if (magellan->idx < MAGELLAN_MAX_LENGTH)
-			magellan->data[magellan->idx++] = data;
-	} 
-}
-
-/*
- * magellan_disconnect() is the opposite of magellan_connect()
- */
-
-static void magellan_disconnect(struct serio *serio)
-{
-	struct magellan* magellan = serio->private;
-	input_unregister_device(&magellan->dev);
-	serio_close(serio);
-	kfree(magellan);
-}
-
-/*
- * magellan_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Magellan, and if found, registers
- * it as an input device.
- */
-
-static void magellan_connect(struct serio *serio, struct serio_dev *dev)
-{
-	struct magellan *magellan;
-	int i, t;
-
-	if (serio->type != (SERIO_RS232 | SERIO_MAGELLAN))
-		return;
-
-	if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
-		return;
-
-	memset(magellan, 0, sizeof(struct magellan));
-
-	magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
-
-	for (i = 0; i < 9; i++)
-		set_bit(magellan_buttons[i], &magellan->dev.keybit);
-
-	for (i = 0; i < 6; i++) {
-		t = magellan_axes[i];
-		set_bit(t, magellan->dev.absbit);
-		magellan->dev.absmin[t] = -360;
-		magellan->dev.absmax[t] =  360;
-	}
-
-	magellan->dev.private = magellan;
-	magellan->dev.name = magellan_name;
-	magellan->dev.idbus = BUS_RS232;
-	magellan->dev.idvendor = SERIO_MAGELLAN;
-	magellan->dev.idproduct = 0x0001;
-	magellan->dev.idversion = 0x0100;
-	
-	serio->private = magellan;
-
-	if (serio_open(serio, dev)) {
-		kfree(magellan);
-		return;
-	}
-
-	input_register_device(&magellan->dev);
-
-	printk(KERN_INFO "input%d: %s on serio%d\n", magellan->dev.number, magellan_name, serio->number);
-}
-
-/*
- * The serio device structure.
- */
-
-static struct serio_dev magellan_dev = {
-	interrupt:	magellan_interrupt,
-	connect:	magellan_connect,
-	disconnect:	magellan_disconnect,
-};
-
-/*
- * The functions for inserting/removing us as a module.
- */
-
-int __init magellan_init(void)
-{
-	serio_register_device(&magellan_dev);
-	return 0;
-}
-
-void __exit magellan_exit(void)
-{
-	serio_unregister_device(&magellan_dev);
-}
-
-module_init(magellan_init);
-module_exit(magellan_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/ns558.c b/drivers/char/joystick/ns558.c
--- a/drivers/char/joystick/ns558.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,285 +0,0 @@
-/*
- * $Id: ns558.c,v 1.29 2001/04/24 07:48:56 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *  Copyright (c) 1999 Brian Gerst
- *
- *  Sponsored by SuSE
- */
-
-/*
- * NS558 based standard IBM game port driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <asm/io.h>
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/slab.h>
-#include <linux/isapnp.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_LICENSE("GPL");
-
-#define NS558_ISA	1
-#define NS558_PNP	2
-
-static int ns558_isa_portlist[] = { 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209,
-				    0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 };
-
-struct ns558 {
-	int type;
-	int size;
-	struct pci_dev *dev;
-	struct ns558 *next;
-	struct gameport gameport;
-};
-	
-static struct ns558 *ns558;
-
-/*
- * ns558_isa_probe() tries to find an isa gameport at the
- * specified address, and also checks for mirrors.
- * A joystick must be attached for this to work.
- */
-
-static struct ns558* ns558_isa_probe(int io, struct ns558 *next)
-{
-	int i, j, b;
-	unsigned char c, u, v;
-	struct ns558 *port;
-
-/*
- * No one should be using this address.
- */
-
-	if (check_region(io, 1))
-		return next;
-
-/*
- * We must not be able to write arbitrary values to the port.
- * The lower two axis bits must be 1 after a write.
- */
-
-	c = inb(io);
-	outb(~c & ~3, io);
-	if (~(u = v = inb(io)) & 3) {
-		outb(c, io);
-		return next;
-	}
-/*
- * After a trigger, there must be at least some bits changing.
- */
-
-	for (i = 0; i < 1000; i++) v &= inb(io);
-
-	if (u == v) {
-		outb(c, io);
-		return next;
-	}
-	wait_ms(3);
-/*
- * After some time (4ms) the axes shouldn't change anymore.
- */
-
-	u = inb(io);
-	for (i = 0; i < 1000; i++)
-		if ((u ^ inb(io)) & 0xf) {
-			outb(c, io);
-			return next;
-		}
-/* 
- * And now find the number of mirrors of the port.
- */
-
-	for (i = 1; i < 5; i++) {
-
-		if (check_region(io & (-1 << i), (1 << i)))	/* Don't disturb anyone */
-			break;
-
-		outb(0xff, io & (-1 << i));
-		for (j = b = 0; j < 1000; j++)
-			if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++;
-		wait_ms(3);
-
-		if (b > 300)					/* We allow 30% difference */
-			break;
-	}
-
-	i--;
-
-	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
-		printk(KERN_ERR "ns558: Memory allocation failed.\n");
-		return next;
-	}
-       	memset(port, 0, sizeof(struct ns558));
-	
-	port->next = next;
-	port->type = NS558_ISA;
-	port->size = (1 << i);
-	port->gameport.io = io & (-1 << i);
-
-	request_region(port->gameport.io, (1 << i), "ns558-isa");
-
-	gameport_register_port(&port->gameport);
-
-	printk(KERN_INFO "gameport%d: NS558 ISA at %#x", port->gameport.number, port->gameport.io);
-	if (port->size > 1) printk(" size %d", port->size);
-	printk(" speed %d kHz\n", port->gameport.speed);
-
-	return port;
-}
-
-#ifdef __ISAPNP__
-
-static struct isapnp_device_id pnp_devids[] = {
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x0001), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x2001), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7001), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7002), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0b35), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P','N','P'), ISAPNP_DEVICE(0xb02f), 0 },
-	{ 0, },
-};
-
-MODULE_DEVICE_TABLE(isapnp, pnp_devids);
-
-static struct ns558* ns558_pnp_probe(struct pci_dev *dev, struct ns558 *next)
-{
-	int ioport, iolen;
-	struct ns558 *port;
-
-	if (dev->prepare && dev->prepare(dev) < 0)
-		return next;
-
-	if (!(dev->resource[0].flags & IORESOURCE_IO)) {
-		printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n");
-		return next;
-	}
-
-	if (dev->activate && dev->activate(dev) < 0) {
-		printk(KERN_ERR "ns558: PnP resource allocation failed\n");
-		return next;
-	}
-	
-	ioport = pci_resource_start(dev, 0);
-	iolen = pci_resource_len(dev, 0);
-
-	if (!request_region(ioport, iolen, "ns558-pnp"))
-		goto deactivate;
-
-	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
-		printk(KERN_ERR "ns558: Memory allocation failed.\n");
-		goto deactivate;
-	}
-	memset(port, 0, sizeof(struct ns558));
-
-	port->next = next;
-	port->type = NS558_PNP;
-	port->gameport.io = ioport;
-	port->size = iolen;
-	port->dev = dev;
-
-	gameport_register_port(&port->gameport);
-
-	printk(KERN_INFO "gameport%d: NS558 PnP at %#x", port->gameport.number, port->gameport.io);
-	if (iolen > 1) printk(" size %d", iolen);
-	printk(" speed %d kHz\n", port->gameport.speed);
-
-	return port;
-
-deactivate:
-	if (dev->deactivate)
-		dev->deactivate(dev);
-	return next;
-}
-#endif
-
-int __init ns558_init(void)
-{
-	int i = 0;
-#ifdef __ISAPNP__
-	struct isapnp_device_id *devid;
-	struct pci_dev *dev = NULL;
-#endif
-
-/*
- * Probe for ISA ports.
- */
-
-	while (ns558_isa_portlist[i]) 
-		ns558 = ns558_isa_probe(ns558_isa_portlist[i++], ns558);
-
-/*
- * Probe for PnP ports.
- */
-
-#ifdef __ISAPNP__
-	for (devid = pnp_devids; devid->vendor; devid++) {
-		while ((dev = isapnp_find_dev(NULL, devid->vendor, devid->function, dev))) {
-			ns558 = ns558_pnp_probe(dev, ns558);
-		}
-	}
-#endif
-
-	return ns558 ? 0 : -ENODEV;
-}
-
-void __exit ns558_exit(void)
-{
-	struct ns558 *next, *port = ns558;
-
-	while (port) {
-		gameport_unregister_port(&port->gameport);
-		switch (port->type) {
-
-#ifdef __ISAPNP__
-			case NS558_PNP:
-				if (port->dev->deactivate)
-					port->dev->deactivate(port->dev);
-				/* fall through */
-#endif
-
-			case NS558_ISA:
-				release_region(port->gameport.io, port->size);
-				break;
-		
-			default:
-				break;
-		}
-		
-		next = port->next;
-		kfree(port);
-		port = next;
-	}
-}
-
-module_init(ns558_init);
-module_exit(ns558_exit);
diff -Nru a/drivers/char/joystick/pcigame.c b/drivers/char/joystick/pcigame.c
--- a/drivers/char/joystick/pcigame.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,199 +0,0 @@
-/*
- * $Id: pcigame.c,v 1.10 2001/04/26 10:24:46 vojtech Exp $
- *
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- *
- *  Based on the work of:
- *	Raymond Ingles
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Trident 4DWave and Aureal Vortex gameport driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/gameport.h>
-
-#define PCI_VENDOR_ID_AUREAL	0x12eb
-
-#define PCIGAME_DATA_WAIT	20	/* 20 ms */
-
-#define PCIGAME_4DWAVE		0
-#define PCIGAME_VORTEX		1
-#define PCIGAME_VORTEX2		2
-
-struct pcigame_data {
-	int gcr;	/* Gameport control register */
-	int legacy;	/* Legacy port location */
-	int axes;	/* Axes start */
-	int axsize;	/* Axis field size */
-	int axmax;	/* Axis field max value */
-	int adcmode;	/* Value to enable ADC mode in GCR */
-};
-
-static struct pcigame_data pcigame_data[] __devinitdata =
-{{ 0x00030, 0x00031, 0x00034, 2, 0xffff, 0x80 },
- { 0x1100c, 0x11008, 0x11010, 4, 0x1fff, 0x40 },
- { 0x2880c, 0x28808, 0x28810, 4, 0x1fff, 0x40 },
- { 0 }};
-
-struct pcigame {
-	struct gameport gameport;
-	struct pci_dev *dev;
-        unsigned char *base;
-	struct pcigame_data *data;
-};
-
-static unsigned char pcigame_read(struct gameport *gameport)
-{
-	struct pcigame *pcigame = gameport->private;
-	return readb(pcigame->base + pcigame->data->legacy);
-}
-
-static void pcigame_trigger(struct gameport *gameport)
-{
-	struct pcigame *pcigame = gameport->private;
-	writeb(0xff, pcigame->base + pcigame->data->legacy);
-}
-
-static int pcigame_cooked_read(struct gameport *gameport, int *axes, int *buttons)
-{
-        struct pcigame *pcigame = gameport->private;
-	int i;
-
-	*buttons = (~readb(pcigame->base + pcigame->data->legacy) >> 4) & 0xf;
-
-	for (i = 0; i < 4; i++) {
-		axes[i] = readw(pcigame->base + pcigame->data->axes + i * pcigame->data->axsize);
-		if (axes[i] == pcigame->data->axmax) axes[i] = -1;
-	}
-        
-        return 0;
-}
-
-static int pcigame_open(struct gameport *gameport, int mode)
-{
-	struct pcigame *pcigame = gameport->private;
-
-	switch (mode) {
-		case GAMEPORT_MODE_COOKED:
-			writeb(pcigame->data->adcmode, pcigame->base + pcigame->data->gcr);
-			wait_ms(PCIGAME_DATA_WAIT);
-			return 0;
-		case GAMEPORT_MODE_RAW:
-			writeb(0, pcigame->base + pcigame->data->gcr);
-			return 0;
-		default:
-			return -1;
-	}
-
-	return 0;
-}
-
-static int __devinit pcigame_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct pcigame *pcigame;
-	int i;
-
-	if (!(pcigame = kmalloc(sizeof(struct pcigame), GFP_KERNEL)))
-		return -1;
-        memset(pcigame, 0, sizeof(struct pcigame));
-
-
-	pcigame->data = pcigame_data + id->driver_data;
-
-	pcigame->dev = dev;
-	pci_set_drvdata(dev, pcigame);
-
-	pcigame->gameport.private = pcigame;
-	pcigame->gameport.fuzz = 64;
-	
-	pcigame->gameport.read = pcigame_read;
-	pcigame->gameport.trigger = pcigame_trigger;
-	pcigame->gameport.cooked_read = pcigame_cooked_read;
-	pcigame->gameport.open = pcigame_open;
-
-	for (i = 0; i < 6; i++)
-		if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
-			break;
-
-	pci_enable_device(dev);
-
-	pcigame->base = ioremap(pci_resource_start(pcigame->dev, i),
-				pci_resource_len(pcigame->dev, i));
-
-	gameport_register_port(&pcigame->gameport);
-	
-	printk(KERN_INFO "gameport%d: %s at pci%02x:%02x.%x speed %d kHz\n",
-		pcigame->gameport.number, dev->name, dev->bus->number,
-			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), pcigame->gameport.speed);
-
-	return 0;
-}
-
-static void __devexit pcigame_remove(struct pci_dev *dev)
-{
-	struct pcigame *pcigame = pci_get_drvdata(dev);
-	gameport_unregister_port(&pcigame->gameport);
-	iounmap(pcigame->base);
-	kfree(pcigame);
-}
-
-static struct pci_device_id pcigame_id_table[] __devinitdata =
-{{ PCI_VENDOR_ID_TRIDENT, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_4DWAVE  },
- { PCI_VENDOR_ID_TRIDENT, 0x2001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_4DWAVE  },
- { PCI_VENDOR_ID_AUREAL,  0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_VORTEX  },
- { PCI_VENDOR_ID_AUREAL,  0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_VORTEX2 },
- { 0 }};
-
-static struct pci_driver pcigame_driver = {
-	name:		"pcigame",
-	id_table:	pcigame_id_table,
-	probe:		pcigame_probe,
-	remove:		pcigame_remove,
-};
-
-int __init pcigame_init(void)
-{
-	return pci_module_init(&pcigame_driver);
-}
-
-void __exit pcigame_exit(void)
-{
-	pci_unregister_driver(&pcigame_driver);
-}
-
-module_init(pcigame_init);
-module_exit(pcigame_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/serio.c b/drivers/char/joystick/serio.c
--- a/drivers/char/joystick/serio.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,133 +0,0 @@
-/*
- * $Id: serio.c,v 1.5 2000/06/04 17:44:59 vojtech Exp $
- *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- *  The Serio abstraction module
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/stddef.h>
-#include <linux/module.h>
-#include <linux/serio.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(serio_register_port);
-EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_register_device);
-EXPORT_SYMBOL(serio_unregister_device);
-EXPORT_SYMBOL(serio_open);
-EXPORT_SYMBOL(serio_close);
-EXPORT_SYMBOL(serio_rescan);
-
-static struct serio *serio_list;
-static struct serio_dev *serio_dev;
-static int serio_number;
-
-static void serio_find_dev(struct serio *serio)
-{
-        struct serio_dev *dev = serio_dev;
-
-        while (dev && !serio->dev) {
-		if (dev->connect)
-                	dev->connect(serio, dev);
-                dev = dev->next;
-        }
-}
-
-void serio_rescan(struct serio *serio)
-{
-	if (serio->dev && serio->dev->disconnect)
-		serio->dev->disconnect(serio);
-	serio_find_dev(serio);
-}
-
-void serio_register_port(struct serio *serio)
-{
-	serio->number = serio_number++;
-	serio->next = serio_list;	
-	serio_list = serio;
-	serio_find_dev(serio);
-}
-
-void serio_unregister_port(struct serio *serio)
-{
-        struct serio **serioptr = &serio_list;
-
-        while (*serioptr && (*serioptr != serio)) serioptr = &((*serioptr)->next);
-        *serioptr = (*serioptr)->next;
-
-	if (serio->dev && serio->dev->disconnect)
-		serio->dev->disconnect(serio);
-
-	serio_number--;
-}
-
-void serio_register_device(struct serio_dev *dev)
-{
-	struct serio *serio = serio_list;
-
-	dev->next = serio_dev;	
-	serio_dev = dev;
-
-	while (serio) {
-		if (!serio->dev && dev->connect)
-			dev->connect(serio, dev);
-		serio = serio->next;
-	}
-}
-
-void serio_unregister_device(struct serio_dev *dev)
-{
-        struct serio_dev **devptr = &serio_dev;
-	struct serio *serio = serio_list;
-
-        while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next);
-        *devptr = (*devptr)->next;
-
-	while (serio) {
-		if (serio->dev == dev && dev->disconnect)
-			dev->disconnect(serio);
-		serio_find_dev(serio);
-		serio = serio->next;
-	}
-}
-
-int serio_open(struct serio *serio, struct serio_dev *dev)
-{
-	if (serio->open(serio))
-		return -1;
-	serio->dev = dev;
-	return 0;
-}
-
-void serio_close(struct serio *serio)
-{
-	serio->close(serio);
-	serio->dev = NULL;
-}
diff -Nru a/drivers/char/joystick/serport.c b/drivers/char/joystick/serport.c
--- a/drivers/char/joystick/serport.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,226 +0,0 @@
-/*
- * $Id: serport.c,v 1.7 2001/05/25 19:00:27 jdeneux Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * This is a module that converts a tty line into a much simpler
- * 'serial io port' abstraction that the input device drivers use.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- *  Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <asm/uaccess.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serio.h>
-#include <linux/tty.h>
-
-struct serport {
-	struct tty_struct *tty;
-	wait_queue_head_t wait;
-	struct serio serio;
-};
-
-/*
- * Callback functions from the serio code.
- */
-
-static int serport_serio_write(struct serio *serio, unsigned char data)
-{
-	struct serport *serport = serio->driver;
-	return -(serport->tty->driver.write(serport->tty, 0, &data, 1) != 1);
-}
-
-static int serport_serio_open(struct serio *serio)
-{
-        return 0;
-}
-
-static void serport_serio_close(struct serio *serio)
-{
-	struct serport *serport = serio->driver;
-	wake_up_interruptible(&serport->wait);
-}
-
-/*
- * serport_ldisc_open() is the routine that is called upon setting our line
- * discipline on a tty. It looks for the Mag, and if found, registers
- * it as a joystick device.
- */
-
-static int serport_ldisc_open(struct tty_struct *tty)
-{
-	struct serport *serport;
-
-	MOD_INC_USE_COUNT;
-
-	if (!(serport = kmalloc(sizeof(struct serport), GFP_KERNEL))) {
-		MOD_DEC_USE_COUNT;
-		return -ENOMEM;
-	}
-
-	memset(serport, 0, sizeof(struct serport));
-
-	serport->tty = tty;
-	tty->disc_data = serport;
-
-	serport->serio.type = SERIO_RS232;
-	serport->serio.write = serport_serio_write;
-	serport->serio.open = serport_serio_open;
-	serport->serio.close = serport_serio_close;
-	serport->serio.driver = serport;
-
-	init_waitqueue_head(&serport->wait);
-
-	return 0;
-}
-
-/*
- * serport_ldisc_close() is the opposite of serport_ldisc_open()
- */
-
-static void serport_ldisc_close(struct tty_struct *tty)
-{
-	struct serport *serport = (struct serport*) tty->disc_data;
-	kfree(serport);
-	MOD_DEC_USE_COUNT;
-}
-
-/*
- * serport_ldisc_receive() is called by the low level tty driver when characters
- * are ready for us. We forward the characters, one by one to the 'interrupt'
- * routine.
- */
-
-static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
-{
-	struct serport *serport = (struct serport*) tty->disc_data;
-	int i;
-	for (i = 0; i < count; i++)
-		if (serport->serio.dev)
-			serport->serio.dev->interrupt(&serport->serio, cp[i], 0);
-}
-
-/*
- * serport_ldisc_room() reports how much room we do have for receiving data.
- * Although we in fact have infinite room, we need to specify some value
- * here, and 256 seems to be reasonable.
- */
-
-static int serport_ldisc_room(struct tty_struct *tty)
-{
-	return 256;
-}
-
-/*
- * serport_ldisc_read() just waits indefinitely if everything goes well. 
- * However, when the serio driver closes the serio port, it finishes,
- * returning 0 characters.
- */
-
-static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char * buf, size_t nr)
-{
-	struct serport *serport = (struct serport*) tty->disc_data;
-	DECLARE_WAITQUEUE(wait, current);
-	char name[32];
-
-#ifdef CONFIG_DEVFS_FS
-	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);
-#endif
-
-	serio_register_port(&serport->serio);
-
-	printk(KERN_INFO "serio%d: Serial port %s\n", serport->serio.number, name);
-
-	add_wait_queue(&serport->wait, &wait);
-	current->state = TASK_INTERRUPTIBLE;
-
-	while(serport->serio.type && !signal_pending(current)) schedule();
-
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&serport->wait, &wait);
-
-	serio_unregister_port(&serport->serio);
-
-	return 0;
-}
-
-/*
- * serport_ldisc_ioctl() allows to set the port protocol, and device ID
- */
-
-static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	struct serport *serport = (struct serport*) tty->disc_data;
-	
-	switch (cmd) {
-		case SPIOCSTYPE:
-			return get_user(serport->serio.type, (unsigned long *) arg);
-	}
-
-	return -EINVAL;
-}
-
-/*
- * The line discipline structure.
- */
-
-static struct tty_ldisc serport_ldisc = {
-	name:		"input",
-	open:		serport_ldisc_open,
-	close:		serport_ldisc_close,
-	read:		serport_ldisc_read,
-	ioctl:		serport_ldisc_ioctl,
-	receive_buf:	serport_ldisc_receive,
-	receive_room:	serport_ldisc_room,
-};
-
-/*
- * The functions for insering/removing us as a module.
- */
-
-int __init serport_init(void)
-{
-        if (tty_register_ldisc(N_MOUSE, &serport_ldisc)) {
-                printk(KERN_ERR "serport.c: Error registering line discipline.\n");
-		return -ENODEV;
-	}
-
-	return  0;
-}
-
-void __exit serport_exit(void)
-{
-	tty_register_ldisc(N_MOUSE, NULL);
-}
-
-module_init(serport_init);
-module_exit(serport_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/sidewinder.c b/drivers/char/joystick/sidewinder.c
--- a/drivers/char/joystick/sidewinder.c	Sun Feb 10 19:58:06 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,761 +0,0 @@
-/*
- * $Id: sidewinder.c,v 1.20 2001/05/19 08:14:54 vojtech Exp $
- *
- *  Copyright (c) 1998-2001 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Microsoft SideWinder joystick family driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/gameport.h>
-
-/*
- * These are really magic values. Changing them can make a problem go away,
- * as well as break everything.
- */
-
-#undef SW_DEBUG
-
-#define SW_START	400	/* The time we wait for the first bit [400 us] */
-#define SW_STROBE	45	/* Max time per bit [45 us] */
-#define SW_TIMEOUT	4000	/* Wait for everything to settle [4 ms] */
-#define SW_KICK		45	/* Wait after A0 fall till kick [45 us] */
-#define SW_END		8	/* Number of bits before end of packet to kick */
-#define SW_FAIL		16	/* Number of packet read errors to fail and reinitialize */
-#define SW_BAD		2	/* Number of packet read errors to switch off 3d Pro optimization */
-#define SW_OK		64	/* Number of packet read successes to switch optimization back on */
-#define SW_LENGTH	512	/* Max number of bits in a packet */
-#define SW_REFRESH	HZ/50	/* Time to wait between updates of joystick data [20 ms] */
-
-#ifdef SW_DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-
-/*
- * SideWinder joystick types ...
- */
-
-#define SW_ID_3DP	0
-#define SW_ID_GP	1
-#define SW_ID_PP	2
-#define SW_ID_FFP	3
-#define SW_ID_FSP	4
-#define SW_ID_FFW	5
-
-/*
- * Names, buttons, axes ...
- */
-
-static char *sw_name[] = {	"3D Pro", "GamePad", "Precision Pro", "Force Feedback Pro", "FreeStyle Pro",
-				"Force Feedback Wheel" };
-
-static char sw_abs[][7] = {
-	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
-	{ ABS_X, ABS_Y },
-	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
-	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
-	{ ABS_X, ABS_Y,         ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
-	{ ABS_RX, ABS_RUDDER,   ABS_THROTTLE }};
-
-static char sw_bit[][7] = {
-	{ 10, 10,  9, 10,  1,  1 },
-	{  1,  1                 },
-	{ 10, 10,  6,  7,  1,  1 },
-	{ 10, 10,  6,  7,  1,  1 },
-	{ 10, 10,  6,  1,  1     },
-	{ 10,  7,  7,  1,  1     }};
-
-static short sw_btn[][12] = {
-	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_MODE },
-	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE },
-	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
-	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
-	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT },
-	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }};
-
-static struct {
-	int x;
-	int y;
-} sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
-
-struct sw {
-	struct gameport *gameport;
-	struct timer_list timer;
-	struct input_dev dev[4];
-	char name[64];
-	int length;
-	int type;
-	int bits;
-	int number;
-	int fail;
-	int ok;
-	int reads;
-	int bads;
-	int used;
-};
-
-/*
- * sw_read_packet() is a function which reads either a data packet, or an
- * identification packet from a SideWinder joystick. The protocol is very,
- * very, very braindamaged. Microsoft patented it in US patent #5628686.
- */
-
-static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int length, int id)
-{
-	unsigned long flags;
-	int timeout, bitout, sched, i, kick, start, strobe;
-	unsigned char pending, u, v;
-
-	i = -id;						/* Don't care about data, only want ID */
-	timeout = id ? gameport_time(gameport, SW_TIMEOUT) : 0;	/* Set up global timeout for ID packet */
-	kick = id ? gameport_time(gameport, SW_KICK) : 0;	/* Set up kick timeout for ID packet */
-	start = gameport_time(gameport, SW_START);
-	strobe = gameport_time(gameport, SW_STROBE);
-	bitout = start;
-	pending = 0;
-	sched = 0;
-
-        __save_flags(flags);					/* Quiet, please */
-        __cli();
-
-	gameport_trigger(gameport);				/* Trigger */
-	v = gameport_read(gameport);
-
-	do {
-		bitout--;
-		u = v;
-		v = gameport_read(gameport);
-	} while (!(~v & u & 0x10) && (bitout > 0));		/* Wait for first falling edge on clock */
-
-	if (bitout > 0) bitout = strobe;			/* Extend time if not timed out */
-
-	while ((timeout > 0 || bitout > 0) && (i < length)) {
-
-		timeout--;
-		bitout--;					/* Decrement timers */
-		sched--;
-
-		u = v;
-		v = gameport_read(gameport);
-
-		if ((~u & v & 0x10) && (bitout > 0)) {		/* Rising edge on clock - data bit */
-			if (i >= 0)				/* Want this data */
-				buf[i] = v >> 5;		/* Store it */
-			i++;					/* Advance index */
-			bitout = strobe;			/* Extend timeout for next bit */
-		} 
-
-		if (kick && (~v & u & 0x01)) {			/* Falling edge on axis 0 */
-			sched = kick;				/* Schedule second trigger */
-			kick = 0;				/* Don't schedule next time on falling edge */
-			pending = 1;				/* Mark schedule */
-		} 
-
-		if (pending && sched < 0 && (i > -SW_END)) {	/* Second trigger time */
-			gameport_trigger(gameport);		/* Trigger */
-			bitout = start;				/* Long bit timeout */
-			pending = 0;				/* Unmark schedule */
-			timeout = 0;				/* Switch from global to bit timeouts */ 
-		}
-	}
-
-	__restore_flags(flags);					/* Done - relax */
-
-#ifdef SW_DEBUG
-	{
-		int j;
-		printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);
-		for (j = 0; j < i; j++) printk("%d", buf[j]);
-		printk("]\n");
-	}
-#endif
-
-	return i;
-}
-
-/*
- * sw_get_bits() and GB() compose bits from the triplet buffer into a __u64.
- * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
- * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
- * is number of bits per triplet.
- */
-
-#define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits)
-
-static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits)
-{
-	__u64 data = 0;
-	int tri = pos % bits;						/* Start position */
-	int i   = pos / bits;
-	int bit = 0;
-
-	while (num--) {
-		data |= (__u64)((buf[i] >> tri++) & 1) << bit++;	/* Transfer bit */
-		if (tri == bits) {
-			i++;						/* Next triplet */
-			tri = 0;
-		}
-	}
-
-	return data;
-}
-
-/*
- * sw_init_digital() initializes a SideWinder 3D Pro joystick
- * into digital mode.
- */
-
-static void sw_init_digital(struct gameport *gameport)
-{
-	int seq[] = { 140, 140+725, 140+300, 0 };
-	unsigned long flags;
-	int i, t;
-
-        __save_flags(flags);
-        __cli();
-
-	i = 0;
-        do {
-                gameport_trigger(gameport);			/* Trigger */
-		t = gameport_time(gameport, SW_TIMEOUT);
-		while ((gameport_read(gameport) & 1) && t) t--;	/* Wait for axis to fall back to 0 */
-                udelay(seq[i]);					/* Delay magic time */
-        } while (seq[++i]);
-
-	gameport_trigger(gameport);				/* Last trigger */
-
-	__restore_flags(flags);
-}
-
-/*
- * sw_parity() computes parity of __u64
- */
-
-static int sw_parity(__u64 t)
-{
-	int x = t ^ (t >> 32);
-	x ^= x >> 16;
-	x ^= x >> 8;
-	x ^= x >> 4;
-	x ^= x >> 2;
-	x ^= x >> 1;
-	return x & 1;
-}
-
-/*
- * sw_ccheck() checks synchronization bits and computes checksum of nibbles.
- */
-
-static int sw_check(__u64 t)
-{
-	unsigned char sum = 0;
-
-	if ((t & 0x8080808080808080ULL) ^ 0x80)			/* Sync */
-		return -1;
-
-	while (t) {						/* Sum */
-		sum += t & 0xf;
-		t >>= 4;
-	}
-
-	return sum & 0xf;
-}
-
-/*
- * sw_parse() analyzes SideWinder joystick data, and writes the results into
- * the axes and buttons arrays.
- */
-
-static int sw_parse(unsigned char *buf, struct sw *sw)
-{
-	int hat, i, j;
-	struct input_dev *dev = sw->dev;
-
-	switch (sw->type) {
-
-		case SW_ID_3DP:
-
-			if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8) return -1;
-
-			input_report_abs(dev, ABS_X,        (GB( 3,3) << 7) | GB(16,7));
-			input_report_abs(dev, ABS_Y,        (GB( 0,3) << 7) | GB(24,7));
-			input_report_abs(dev, ABS_RZ,       (GB(35,2) << 7) | GB(40,7));
-			input_report_abs(dev, ABS_THROTTLE, (GB(32,3) << 7) | GB(48,7));
-
-			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
-			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
-
-			for (j = 0; j < 7; j++)
-				input_report_key(dev, sw_btn[SW_ID_3DP][j], !GB(j+8,1));
-
-			input_report_key(dev, BTN_BASE4, !GB(38,1));
-			input_report_key(dev, BTN_BASE5, !GB(37,1));
-
-			return 0;
-
-		case SW_ID_GP:
-
-			for (i = 0; i < sw->number; i ++) {
-
-				if (sw_parity(GB(i*15,15))) return -1;
-
-				input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
-				input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
-
-				for (j = 0; j < 10; j++)
-					input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
-			}
-
-			return 0;
-
-		case SW_ID_PP:
-		case SW_ID_FFP:
-
-			if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8) return -1;
-
-			input_report_abs(dev, ABS_X,        GB( 9,10));
-			input_report_abs(dev, ABS_Y,        GB(19,10));
-			input_report_abs(dev, ABS_RZ,       GB(36, 6));
-			input_report_abs(dev, ABS_THROTTLE, GB(29, 7));
-
-			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
-			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
-
-			for (j = 0; j < 9; j++)
-				input_report_key(dev, sw_btn[SW_ID_PP][j], !GB(j,1));
-
-			return 0;
-
-		case SW_ID_FSP:
-
-			if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8) return -1;
-
-			input_report_abs(dev, ABS_X,        GB( 0,10));
-			input_report_abs(dev, ABS_Y,        GB(16,10));
-			input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
-
-			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
-			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
-
-			for (j = 0; j < 6; j++)
-				input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1));
-
-			input_report_key(dev, BTN_TR,     GB(26,1));
-			input_report_key(dev, BTN_START,  GB(27,1));
-			input_report_key(dev, BTN_MODE,   GB(38,1));
-			input_report_key(dev, BTN_SELECT, GB(39,1));
-
-			return 0;
-
-		case SW_ID_FFW:
-
-			if (!sw_parity(GB(0,33))) return -1;
-
-			input_report_abs(dev, ABS_RX,       GB( 0,10));
-			input_report_abs(dev, ABS_RUDDER,   GB(10, 6));
-			input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
-
-			for (j = 0; j < 8; j++)
-				input_report_key(dev, sw_btn[SW_ID_FFW][j], !GB(j+22,1));
-
-			return 0;
-	}
-
-	return -1;
-}
-
-/*
- * sw_read() reads SideWinder joystick data, and reinitializes
- * the joystick in case of persistent problems. This is the function that is
- * called from the generic code to poll the joystick.
- */
-
-static int sw_read(struct sw *sw)
-{
-	unsigned char buf[SW_LENGTH];
-	int i;
-
-	i = sw_read_packet(sw->gameport, buf, sw->length, 0);
-
-	if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) {		/* Broken packet, try to fix */
-
-		if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) {		/* Last init failed, 1 bit mode */
-			printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on gameport%d"
-				" - going to reinitialize.\n", sw->gameport->number);
-			sw->fail = SW_FAIL;					/* Reinitialize */
-			i = 128;						/* Bogus value */
-		}
-
-		if (i < 66 && GB(0,64) == GB(i*3-66,64))			/* 1 == 3 */
-			i = 66;							/* Everything is fine */
-
-		if (i < 66 && GB(0,64) == GB(66,64))				/* 1 == 2 */
-			i = 66;							/* Everything is fine */
-
-		if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) {		/* 2 == 3 */
-			memmove(buf, buf + i - 22, 22);				/* Move data */
-			i = 66;							/* Carry on */
-		}
-	}
-
-	if (i == sw->length && !sw_parse(buf, sw)) {				/* Parse data */
-
-		sw->fail = 0;
-		sw->ok++;
-
-		if (sw->type == SW_ID_3DP && sw->length == 66			/* Many packets OK */
-			&& sw->ok > SW_OK) {
-
-			printk(KERN_INFO "sidewinder.c: No more trouble on gameport%d"
-				" - enabling optimization again.\n", sw->gameport->number);
-			sw->length = 22;
-		}
-
-		return 0;
-	}
-
-	sw->ok = 0;
-	sw->fail++;
-
-	if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) {	/* Consecutive bad packets */
-
-		printk(KERN_INFO "sidewinder.c: Many bit errors on gameport%d"
-			" - disabling optimization.\n", sw->gameport->number);
-		sw->length = 66;
-	}
-
-	if (sw->fail < SW_FAIL) return -1;					/* Not enough, don't reinitialize yet */
-
-	printk(KERN_WARNING "sidewinder.c: Too many bit errors on gameport%d"
-		" - reinitializing joystick.\n", sw->gameport->number);
-
-	if (!i && sw->type == SW_ID_3DP) {					/* 3D Pro can be in analog mode */
-		udelay(3 * SW_TIMEOUT);
-		sw_init_digital(sw->gameport);
-	}
-
-	udelay(SW_TIMEOUT);
-	i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0);			/* Read normal data packet */
-	udelay(SW_TIMEOUT);
-	sw_read_packet(sw->gameport, buf, SW_LENGTH, i);			/* Read ID packet, this initializes the stick */
-
-	sw->fail = SW_FAIL;
-	
-	return -1;
-}
-
-static void sw_timer(unsigned long private)
-{
-	struct sw *sw = (void *) private;
-	
-	sw->reads++;
-	if (sw_read(sw)) sw->bads++;
-	mod_timer(&sw->timer, jiffies + SW_REFRESH);
-}
-
-static int sw_open(struct input_dev *dev)
-{
-	struct sw *sw = dev->private;
-	if (!sw->used++)
-		mod_timer(&sw->timer, jiffies + SW_REFRESH);
-	return 0;
-}
-
-static void sw_close(struct input_dev *dev)
-{
-	struct sw *sw = dev->private;
-	if (!--sw->used)
-		del_timer(&sw->timer);
-}
-
-/*
- * sw_print_packet() prints the contents of a SideWinder packet.
- */
-
-static void sw_print_packet(char *name, int length, unsigned char *buf, char bits)
-{
-	int i;
-
-	printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length);
-	for (i = (((length + 3) >> 2) - 1); i >= 0; i--)
-		printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits));
-	printk("]\n");
-}
-
-/*
- * sw_3dp_id() translates the 3DP id into a human legible string.
- * Unfortunately I don't know how to do this for the other SW types.
- */
-
-static void sw_3dp_id(unsigned char *buf, char *comment)
-{
-	int i;
-	char pnp[8], rev[9];
-
-	for (i = 0; i < 7; i++)						/* ASCII PnP ID */
-		pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);
-
-	for (i = 0; i < 8; i++)						/* ASCII firmware revision */
-		rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);
-
-	pnp[7] = rev[8] = 0;
-
-	sprintf(comment, " [PnP %d.%02d id %s rev %s]",
-		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |		/* Two 6-bit values */
-			sw_get_bits(buf, 16, 6, 1)) / 100,
-		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
-			sw_get_bits(buf, 16, 6, 1)) % 100,
-		 pnp, rev);
-}
-
-/*
- * sw_guess_mode() checks the upper two button bits for toggling -
- * indication of that the joystick is in 3-bit mode. This is documented
- * behavior for 3DP ID packet, and for example the FSP does this in
- * normal packets instead. Fun ...
- */
-
-static int sw_guess_mode(unsigned char *buf, int len)
-{
-	int i;
-	unsigned char xor = 0;
-	for (i = 1; i < len; i++) xor |= (buf[i - 1] ^ buf[i]) & 6;
-	return !!xor * 2 + 1;
-}
-
-/*
- * sw_connect() probes for SideWinder type joysticks.
- */
-
-static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct sw *sw;
-	int i, j, k, l;
-	unsigned char buf[SW_LENGTH];
-	unsigned char idbuf[SW_LENGTH];
-	unsigned char m = 1;
-	char comment[40];
-
-	comment[0] = 0;
-
-	if (!(sw = kmalloc(sizeof(struct sw), GFP_KERNEL))) return;
-	memset(sw, 0, sizeof(struct sw));
-
-	gameport->private = sw;
-
-	sw->gameport = gameport;
-	init_timer(&sw->timer);
-	sw->timer.data = (long) sw;
-	sw->timer.function = sw_timer;
-
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		goto fail1;
-
-	dbg("Init 0: Opened gameport %d, io %#x, speed %d",
-		gameport->number, gameport->io, gameport->speed);
-
-	i = sw_read_packet(gameport, buf, SW_LENGTH, 0);		/* Read normal packet */
-	m |= sw_guess_mode(buf, i);					/* Data packet (1-bit) can carry mode info [FSP] */
-	udelay(SW_TIMEOUT);
-	dbg("Init 1: Mode %d. Length %d.", m , i);
-
-	if (!i) {							/* No data. 3d Pro analog mode? */
-		sw_init_digital(gameport);				/* Switch to digital */
-		udelay(SW_TIMEOUT);
-		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
-		udelay(SW_TIMEOUT);
-		dbg("Init 1b: Length %d.", i);
-		if (!i) goto fail2;					/* No data -> FAIL */
-	}
-
-	j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);		/* Read ID. This initializes the stick */
-	m |= sw_guess_mode(idbuf, j);					/* ID packet should carry mode info [3DP] */
-	dbg("Init 2: Mode %d. ID Length %d.", m , j);
-
-	if (!j) {							/* Read ID failed. Happens in 1-bit mode on PP */
-		udelay(SW_TIMEOUT);
-		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
-		dbg("Init 2b: Mode %d. Length %d.", m, i);
-		if (!i) goto fail2;
-		udelay(SW_TIMEOUT);
-		j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);	/* Retry reading ID */
-		dbg("Init 2c: ID Length %d.", j);
-	}
-
-	sw->type = -1;
-	k = SW_FAIL;							/* Try SW_FAIL times */
-	l = 0;
-
-	do {
-		k--;
-		udelay(SW_TIMEOUT);
-		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Read data packet */
-		dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
-
-		if (i > l) {						/* Longer? As we can only lose bits, it makes */
-									/* no sense to try detection for a packet shorter */
-			l = i;						/* than the previous one */
-
-			sw->number = 1;
-			sw->gameport = gameport;
-			sw->length = i;
-			sw->bits = m;
-
-			dbg("Init 3a: Case %d.\n", i * m);
-
-			switch (i * m) {
-				case 60:
-					sw->number++;
-				case 45:				/* Ambiguous packet length */
-					if (j <= 40) {			/* ID length less or eq 40 -> FSP */	
-				case 43:
-						sw->type = SW_ID_FSP;
-						break;
-					}
-					sw->number++;
-				case 30:
-					sw->number++;
-				case 15:
-					sw->type = SW_ID_GP;
-					break;
-				case 33:
-				case 31:
-					sw->type = SW_ID_FFW;
-					break;
-				case 48:				/* Ambiguous */
-					if (j == 14) {			/* ID length 14*3 -> FFP */
-						sw->type = SW_ID_FFP;
-						sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");
-					} else
-					sw->type = SW_ID_PP;
-					break;
-				case 198:
-					sw->length = 22;
-				case 64:
-					sw->type = SW_ID_3DP;
-					if (j == 160) sw_3dp_id(idbuf, comment);
-					break;
-			}
-		}
-
-	} while (k && (sw->type == -1));
-
-	if (sw->type == -1) {
-		printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
-			"on gameport%d, contact <vojtech@suse.cz>\n", gameport->number);
-		sw_print_packet("ID", j * 3, idbuf, 3);
-		sw_print_packet("Data", i * m, buf, m);
-		goto fail2;
-	}
-
-#ifdef SW_DEBUG
-	sw_print_packet("ID", j * 3, idbuf, 3);
-	sw_print_packet("Data", i * m, buf, m);
-#endif
-
-	k = i;
-	l = j;
-
-	for (i = 0; i < sw->number; i++) {
-		int bits, code;
-
-		sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
-
-		sw->dev[i].private = sw;
-
-		sw->dev[i].open = sw_open;
-		sw->dev[i].close = sw_close;
-
-		sw->dev[i].name = sw->name;
-		sw->dev[i].idbus = BUS_GAMEPORT;
-		sw->dev[i].idvendor = GAMEPORT_ID_VENDOR_MICROSOFT;
-		sw->dev[i].idproduct = sw->type;
-		sw->dev[i].idversion = 0x0100;
-
-		sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-		for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
-			code = sw_abs[sw->type][j];
-			set_bit(code, sw->dev[i].absbit);
-			sw->dev[i].absmax[code] = (1 << bits) - 1;
-			sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0;
-			sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
-			if (code != ABS_THROTTLE)
-				sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
-		}
-
-		for (j = 0; (code = sw_btn[sw->type][j]); j++)
-			set_bit(code, sw->dev[i].keybit);
-
-		input_register_device(sw->dev + i);
-		printk(KERN_INFO "input%d: %s%s on gameport%d.%d [%d-bit id %d data %d]\n",
-			sw->dev[i].number, sw->name, comment, gameport->number, i, m, l, k);
-	}
-
-	return;
-fail2:	gameport_close(gameport);
-fail1:	kfree(sw);
-}
-
-static void sw_disconnect(struct gameport *gameport)
-{
-	int i;
-
-	struct sw *sw = gameport->private;
-	for (i = 0; i < sw->number; i++)
-		input_unregister_device(sw->dev + i);
-	gameport_close(gameport);
-	kfree(sw);
-}
-
-static struct gameport_dev sw_dev = {
-	connect:	sw_connect,
-	disconnect:	sw_disconnect,
-};
-
-int __init sw_init(void)
-{
-	gameport_register_device(&sw_dev);
-	return 0;
-}
-
-void __exit sw_exit(void)
-{
-	gameport_unregister_device(&sw_dev);
-}
-
-module_init(sw_init);
-module_exit(sw_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/spaceball.c b/drivers/char/joystick/spaceball.c
--- a/drivers/char/joystick/spaceball.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,238 +0,0 @@
-/*
- * $Id: spaceball.c,v 1.8 2000/11/23 11:42:39 vojtech Exp $
- *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Based on the work of:
- *  	David Thompson
- *  	Joseph Krahn
- *
- *  Sponsored by SuSE
- */
-
-/*
- * SpaceTec SpaceBall 4000 FLX driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- *  Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/serio.h>
-
-/*
- * Constants.
- */
-
-#define JS_SBALL_MAX_LENGTH	128
-static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
-static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX"; 
-
-/*
- * Per-Ball data.
- */
-
-struct spaceball {
-	struct input_dev dev;
-	struct serio *serio;
-	int idx;
-	int escape;
-	unsigned char data[JS_SBALL_MAX_LENGTH];
-};
-
-/*
- * spaceball_process_packet() decodes packets the driver receives from the
- * SpaceBall.
- */
-
-static void spaceball_process_packet(struct spaceball* spaceball)
-{
-	struct input_dev *dev = &spaceball->dev;
-	unsigned char *data = spaceball->data;
-	int i;
-
-	if (spaceball->idx < 2) return;
-
-	printk("%c %d\n", spaceball->data[0], spaceball->idx);
-
-	switch (spaceball->data[0]) {
-
-		case '@':					/* Reset packet */
-			spaceball->data[spaceball->idx - 1] = 0;
-			for (i = 1; i < spaceball->idx && spaceball->data[i] == ' '; i++);
-			printk(KERN_INFO "input%d: %s [%s] on serio%d\n",
-				spaceball->dev.number, spaceball_name, spaceball->data + i, spaceball->serio->number);
-			break;
-
-		case 'D':					/* Ball data */
-			if (spaceball->idx != 15) return;
-			for (i = 0; i < 6; i++) {
-				input_report_abs(dev, spaceball_axes[i], 
-					(__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
-			}
-			break;
-
-		case '.':				/* Button data, part2 */
-			if (spaceball->idx != 3) return;
-			input_report_key(dev, BTN_0,  data[2] & 1);
-			input_report_key(dev, BTN_1, data[2] & 2);
-			break;
-
-		case '?':				/* Error packet */
-			spaceball->data[spaceball->idx - 1] = 0;
-			printk(KERN_ERR "spaceball: Device error. [%s]\n", spaceball->data + 1);
-			break;
-	}
-}
-
-/*
- * Spaceball 4000 FLX packets all start with a one letter packet-type decriptor,
- * and end in 0x0d. It uses '^' as an escape for CR, XOFF and XON characters which
- * can occur in the axis values.
- */
-
-static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
-{
-	struct spaceball *spaceball = serio->private;
-
-	switch (data) {
-		case 0xd:
-			spaceball_process_packet(spaceball);
-			spaceball->idx = 0;
-			spaceball->escape = 0;
-			return;
-		case '^':
-			if (!spaceball->escape) {
-				spaceball->escape = 1;
-				return;
-			}
-			spaceball->escape = 0;
-		case 'M':
-		case 'Q':
-		case 'S':
-			if (spaceball->escape) {
-				spaceball->escape = 0;
-				data &= 0x1f;
-			}
-		default:
-			if (spaceball->escape) {
-				spaceball->escape = 0;
-				printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data);
-			}
-			if (spaceball->idx < JS_SBALL_MAX_LENGTH)
-				spaceball->data[spaceball->idx++] = data;
-			return;
-	}
-}
-
-/*
- * spaceball_disconnect() is the opposite of spaceball_connect()
- */
-
-static void spaceball_disconnect(struct serio *serio)
-{
-	struct spaceball* spaceball = serio->private;
-	input_unregister_device(&spaceball->dev);
-	serio_close(serio);
-	kfree(spaceball);
-}
-
-/*
- * spaceball_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Magellan, and if found, registers
- * it as an input device.
- */
-
-static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
-{
-	struct spaceball *spaceball;
-	int i, t;
-
-	if (serio->type != (SERIO_RS232 | SERIO_SPACEBALL))
-		return;
-
-	if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
-		return;
-	memset(spaceball, 0, sizeof(struct spaceball));
-
-	spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
-	spaceball->dev.keybit[LONG(BTN_0)] = BIT(BTN_0) | BIT(BTN_1);
-
-	for (i = 0; i < 6; i++) {
-		t = spaceball_axes[i];
-		set_bit(t, spaceball->dev.absbit);
-		spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
-		spaceball->dev.absmax[t] = i < 3 ?  8000 :  1600;
-		spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
-		spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
-	}
-
-	spaceball->serio = serio;
-	spaceball->dev.private = spaceball;
-
-	spaceball->dev.name = spaceball_name;
-	spaceball->dev.idbus = BUS_RS232;
-	spaceball->dev.idvendor = SERIO_SPACEBALL;
-	spaceball->dev.idproduct = 0x0001;
-	spaceball->dev.idversion = 0x0100;
-	
-	serio->private = spaceball;
-
-	if (serio_open(serio, dev)) {
-		kfree(spaceball);
-		return;
-	}
-
-	input_register_device(&spaceball->dev);
-}
-
-/*
- * The serio device structure.
- */
-
-static struct serio_dev spaceball_dev = {
-	interrupt:	spaceball_interrupt,
-	connect:	spaceball_connect,
-	disconnect:	spaceball_disconnect,
-};
-
-/*
- * The functions for inserting/removing us as a module.
- */
-
-int __init spaceball_init(void)
-{
-	serio_register_device(&spaceball_dev);
-	return 0;
-}
-
-void __exit spaceball_exit(void)
-{
-	serio_unregister_device(&spaceball_dev);
-}
-
-module_init(spaceball_init);
-module_exit(spaceball_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/spaceorb.c b/drivers/char/joystick/spaceorb.c
--- a/drivers/char/joystick/spaceorb.c	Sun Feb 10 19:58:06 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,227 +0,0 @@
-/*
- * $Id: spaceorb.c,v 1.7 2000/05/29 11:19:51 vojtech Exp $
- *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- * 
- *  Based on the work of:
- *  	David Thompson
- *
- *  Sponsored by SuSE
- */
-
-/*
- * SpaceTec SpaceOrb 360 and Avenger 6dof controller driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- *  Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/serio.h>
-
-/*
- * Constants.
- */
-
-#define SPACEORB_MAX_LENGTH	64
-
-static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A, BTN_MODE};
-static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ};
-static char *spaceorb_name = "SpaceTec SpaceOrb 360";
-
-/*
- * Per-Orb data.
- */
-
-struct spaceorb {
-	struct input_dev dev;
-	struct serio *serio;
-	int idx;
-	unsigned char data[SPACEORB_MAX_LENGTH];
-};
-
-static unsigned char spaceorb_xor[] = "SpaceWare";
-
-static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive queue overflow", "Transmit queue timeout",
-		"Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" }; 
-
-/*
- * spaceorb_process_packet() decodes packets the driver receives from the
- * SpaceOrb.
- */
-
-static void spaceorb_process_packet(struct spaceorb *spaceorb)
-{
-	struct input_dev *dev = &spaceorb->dev;
-	unsigned char *data = spaceorb->data;
-	unsigned char c = 0;
-	int axes[6];
-	int i;
-
-	if (spaceorb->idx < 2) return;
-	for (i = 0; i < spaceorb->idx; i++) c ^= data[i];
-	if (c) return;
-
-	switch (data[0]) {
-
-		case 'R':				/* Reset packet */
-			spaceorb->data[spaceorb->idx - 1] = 0;
-			for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
-			printk(KERN_INFO "input%d: %s [%s] on serio%d\n",
-				 spaceorb->dev.number, spaceorb_name, spaceorb->data + i, spaceorb->serio->number);
-			break;
-
-		case 'D':				/* Ball + button data */
-			if (spaceorb->idx != 12) return;
-			for (i = 0; i < 9; i++) spaceorb->data[i+2] ^= spaceorb_xor[i]; 
-			axes[0] = ( data[2]	 << 3) | (data[ 3] >> 4);
-			axes[1] = ((data[3] & 0x0f) << 6) | (data[ 4] >> 1);
-			axes[2] = ((data[4] & 0x01) << 9) | (data[ 5] << 2) | (data[4] >> 5);
-			axes[3] = ((data[6] & 0x1f) << 5) | (data[ 7] >> 2);
-			axes[4] = ((data[7] & 0x03) << 8) | (data[ 8] << 1) | (data[7] >> 6);
-			axes[5] = ((data[9] & 0x3f) << 4) | (data[10] >> 3);
-			for (i = 0; i < 6; i++)
-				input_report_abs(dev, spaceorb_axes[i], axes[i] - ((axes[i] & 0x200) ? 1024 : 0));
-			for (i = 0; i < 8; i++)
-				input_report_key(dev, spaceorb_buttons[i], (data[1] >> i) & 1);
-			break;
-
-		case 'K':				/* Button data */
-			if (spaceorb->idx != 5) return;
-			for (i = 0; i < 7; i++)
-				input_report_key(dev, spaceorb_buttons[i], (data[2] >> i) & 1);
-
-			break;
-
-		case 'E':				/* Error packet */
-			if (spaceorb->idx != 4) return;
-			printk(KERN_ERR "joy-spaceorb: Device error. [ ");
-			for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
-			printk("]\n");
-			break;
-	}
-}
-
-static void spaceorb_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
-{
-	struct spaceorb* spaceorb = serio->private;
-
-	if (~data & 0x80) {
-		if (spaceorb->idx) spaceorb_process_packet(spaceorb);
-		spaceorb->idx = 0;
-	}
-	if (spaceorb->idx < SPACEORB_MAX_LENGTH)
-		spaceorb->data[spaceorb->idx++] = data & 0x7f;
-}
-
-/*
- * spaceorb_disconnect() is the opposite of spaceorb_connect()
- */
-
-static void spaceorb_disconnect(struct serio *serio)
-{
-	struct spaceorb* spaceorb = serio->private;
-	input_unregister_device(&spaceorb->dev);
-	serio_close(serio);
-	kfree(spaceorb);
-}
-
-/*
- * spaceorb_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the SpaceOrb/Avenger, and if found, registers
- * it as an input device.
- */
-
-static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
-{
-	struct spaceorb *spaceorb;
-	int i, t;
-
-	if (serio->type != (SERIO_RS232 | SERIO_SPACEORB))
-		return;
-
-	if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
-		return;
-	memset(spaceorb, 0, sizeof(struct spaceorb));
-
-	spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
-
-	for (i = 0; i < 7; i++)
-		set_bit(spaceorb_buttons[i], &spaceorb->dev.keybit);
-
-	for (i = 0; i < 6; i++) {
-		t = spaceorb_axes[i];
-		set_bit(t, spaceorb->dev.absbit);
-		spaceorb->dev.absmin[t] = -508;
-		spaceorb->dev.absmax[t] =  508;
-	}
-
-	spaceorb->serio = serio;
-	spaceorb->dev.private = spaceorb;
-
-	spaceorb->dev.name = spaceorb_name;
-	spaceorb->dev.idbus = BUS_RS232;
-	spaceorb->dev.idvendor = SERIO_SPACEORB;
-	spaceorb->dev.idproduct = 0x0001;
-	spaceorb->dev.idversion = 0x0100;
-	
-	serio->private = spaceorb;
-
-	if (serio_open(serio, dev)) {
-		kfree(spaceorb);
-		return;
-	}
-
-	input_register_device(&spaceorb->dev);
-}
-
-/*
- * The serio device structure.
- */
-
-static struct serio_dev spaceorb_dev = {
-	interrupt:	spaceorb_interrupt,
-	connect:	spaceorb_connect,
-	disconnect:	spaceorb_disconnect,
-};
-
-/*
- * The functions for inserting/removing us as a module.
- */
-
-int __init spaceorb_init(void)
-{
-	serio_register_device(&spaceorb_dev);
-	return 0;
-}
-
-void __exit spaceorb_exit(void)
-{
-	serio_unregister_device(&spaceorb_dev);
-}
-
-module_init(spaceorb_init);
-module_exit(spaceorb_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/stinger.c b/drivers/char/joystick/stinger.c
--- a/drivers/char/joystick/stinger.c	Sun Feb 10 19:58:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,202 +0,0 @@
-/*
- * $Id: stinger.c,v 1.4 2001/05/23 09:25:02 vojtech Exp $
- *
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- *  Copyright (c) 2000 Mark Fletcher
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Gravis Stinger gamepad driver for Linux
- */
-
-/*
- * This program is free warftware; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *  Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/serio.h>
-#include <linux/init.h>
-
-/*
- * Constants.
- */
-
-#define STINGER_MAX_LENGTH 8
-
-static char *stinger_name = "Gravis Stinger";
-
-/*
- * Per-Stinger data.
- */
-
-struct stinger {
-	struct input_dev dev;
-	int idx;
-	unsigned char data[STINGER_MAX_LENGTH];
-};
-
-/*
- * stinger_process_packet() decodes packets the driver receives from the
- * Stinger. It updates the data accordingly.
- */
-
-static void stinger_process_packet(struct stinger *stinger)
-{
-	struct input_dev *dev = &stinger->dev;
-	unsigned char *data = stinger->data;
-
-	if (!stinger->idx) return;
-
-	input_report_key(dev, BTN_A,	  ((data[0] & 0x20) >> 5));
-	input_report_key(dev, BTN_B,	  ((data[0] & 0x10) >> 4));
-	input_report_key(dev, BTN_C,	  ((data[0] & 0x08) >> 3));
-	input_report_key(dev, BTN_X,	  ((data[0] & 0x04) >> 2));
-	input_report_key(dev, BTN_Y,	  ((data[3] & 0x20) >> 5));
-	input_report_key(dev, BTN_Z,	  ((data[3] & 0x10) >> 4));
-	input_report_key(dev, BTN_TL,     ((data[3] & 0x08) >> 3));
-	input_report_key(dev, BTN_TR,     ((data[3] & 0x04) >> 2));
-	input_report_key(dev, BTN_SELECT, ((data[3] & 0x02) >> 1));
-	input_report_key(dev, BTN_START,   (data[3] & 0x01));
-
-	input_report_abs(dev, ABS_X, (data[1] & 0x3F) - ((data[0] & 0x01) << 6));
-	input_report_abs(dev, ABS_Y, ((data[0] & 0x02) << 5) - (data[2] & 0x3F));
-
-	return;
-}
-
-/*
- * stinger_interrupt() is called by the low level driver when characters
- * are ready for us. We then buffer them for further processing, or call the
- * packet processing routine.
- */
-
-static void stinger_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
-{
-	struct stinger* stinger = serio->private;
-
-	/* All Stinger packets are 4 bytes */
-
-	if (stinger->idx < STINGER_MAX_LENGTH)
-		stinger->data[stinger->idx++] = data;
-
-	if (stinger->idx == 4) {
-		stinger_process_packet(stinger);
-		stinger->idx = 0;
-	}
-
-	return;
-}
-
-/*
- * stinger_disconnect() is the opposite of stinger_connect()
- */
-
-static void stinger_disconnect(struct serio *serio)
-{
-	struct stinger* stinger = serio->private;
-	input_unregister_device(&stinger->dev);
-	serio_close(serio);
-	kfree(stinger);
-}
-
-/*
- * stinger_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Stinger, and if found, registers
- * it as an input device.
- */
-
-static void stinger_connect(struct serio *serio, struct serio_dev *dev)
-{
-	struct stinger *stinger;
-	int i;
-
-	if (serio->type != (SERIO_RS232 | SERIO_STINGER))
-		return;
-
-	if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
-		return;
-
-	memset(stinger, 0, sizeof(struct stinger));
-
-	stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
-	stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
-					   BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
-					   BIT(BTN_START) | BIT(BTN_SELECT);
-	stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
-	stinger->dev.name = stinger_name;
-	stinger->dev.idbus = BUS_RS232;
-	stinger->dev.idvendor = SERIO_STINGER;
-	stinger->dev.idproduct = 0x0001;
-	stinger->dev.idversion = 0x0100;
-
-	for (i = 0; i < 2; i++) {
-		stinger->dev.absmax[ABS_X+i] =  64;	
-		stinger->dev.absmin[ABS_X+i] = -64;	
-		stinger->dev.absflat[ABS_X+i] = 4;
-	}
-
-	stinger->dev.private = stinger;
-	
-	serio->private = stinger;
-
-	if (serio_open(serio, dev)) {
-		kfree(stinger);
-		return;
-	}
-
-	input_register_device(&stinger->dev);
-
-	printk(KERN_INFO "input%d: %s on serio%d\n", stinger->dev.number, stinger_name, serio->number);
-}
-
-/*
- * The serio device structure.
- */
-
-static struct serio_dev stinger_dev = {
-	interrupt:	stinger_interrupt,
-	connect:	stinger_connect,
-	disconnect:	stinger_disconnect,
-};
-
-/*
- * The functions for inserting/removing us as a module.
- */
-
-int __init stinger_init(void)
-{
-	serio_register_device(&stinger_dev);
-	return 0;
-}
-
-void __exit stinger_exit(void)
-{
-	serio_unregister_device(&stinger_dev);
-}
-
-module_init(stinger_init);
-module_exit(stinger_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/tmdc.c b/drivers/char/joystick/tmdc.c
--- a/drivers/char/joystick/tmdc.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,378 +0,0 @@
-/*
- * $Id: tmdc.c,v 1.23 2000/11/29 19:52:24 vojtech Exp $
- *
- *  Copyright (c) 1998-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- *
- *   Based on the work of:
- *	Trystan Larey-Williams 
- *
- */
-
-/*
- * ThrustMaster DirectConnect (BSP) joystick family driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/gameport.h>
-#include <linux/input.h>
-
-#define TMDC_MAX_START		400	/* 400 us */
-#define TMDC_MAX_STROBE		45	/* 45 us */
-#define TMDC_MAX_LENGTH		13
-#define TMDC_REFRESH_TIME	HZ/50	/* 20 ms */
-
-#define TMDC_MODE_M3DI		1
-#define TMDC_MODE_3DRP		3
-#define TMDC_MODE_AT		4
-#define TMDC_MODE_FM		8
-#define TMDC_MODE_FGP		163
-
-#define TMDC_BYTE_ID		10
-#define TMDC_BYTE_REV		11
-#define TMDC_BYTE_DEF		12
-
-#define TMDC_ABS		7	
-#define TMDC_ABS_HAT		4
-#define TMDC_BTN		16
-
-static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
-static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
-
-static signed char tmdc_abs[TMDC_ABS] =
-	{ ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
-static signed char tmdc_abs_hat[TMDC_ABS_HAT] =
-	{ ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
-static signed char tmdc_abs_at[TMDC_ABS] =
-	{ ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
-static signed char tmdc_abs_fm[TMDC_ABS] =
-	{ ABS_RX, ABS_RY, ABS_X, ABS_Y };
-
-static short tmdc_btn_pad[TMDC_BTN] =
-	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
-static short tmdc_btn_joy[TMDC_BTN] =
-	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
- 	  BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
-static short tmdc_btn_fm[TMDC_BTN] =
-        { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
-static short tmdc_btn_at[TMDC_BTN] =
-        { BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
-          BTN_BASE3, BTN_BASE2, BTN_BASE };
-
-static struct {
-        int x;
-        int y;
-} tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
-
-struct tmdc {
-	struct gameport *gameport;
-	struct timer_list timer;
-	struct input_dev dev[2];
-	char name[2][64];
-	int mode[2];
-	signed char *abs[2];
-	short *btn[2];
-	unsigned char absc[2];
-	unsigned char btnc[2][4];
-	unsigned char btno[2][4];
-	int used;
-	int reads;
-	int bads;	
-	unsigned char exists;
-};
-
-/*
- * tmdc_read_packet() reads a ThrustMaster packet.
- */
-
-static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMDC_MAX_LENGTH])
-{
-	unsigned char u, v, w, x;
-	unsigned long flags;
-	int i[2], j[2], t[2], p, k;
-
-	p = gameport_time(gameport, TMDC_MAX_STROBE);
-
-	for (k = 0; k < 2; k++) {
-		t[k] = gameport_time(gameport, TMDC_MAX_START);
-		i[k] = j[k] = 0;
-	}
-
-	__save_flags(flags);
-	__cli();
-	gameport_trigger(gameport);
-	
-	w = gameport_read(gameport) >> 4;
-
-	do {
-		x = w;
-		w = gameport_read(gameport) >> 4;
-
-		for (k = 0, v = w, u = x; k < 2; k++, v >>= 2, u >>= 2) {
-			if (~v & u & 2) {
-				if (t[k] <= 0 || i[k] >= TMDC_MAX_LENGTH) continue;
-				t[k] = p;
-				if (j[k] == 0) {				 /* Start bit */
-					if (~v & 1) t[k] = 0;
-					data[k][i[k]] = 0; j[k]++; continue;
-				}
-				if (j[k] == 9) {				/* Stop bit */
-					if (v & 1) t[k] = 0;
-					j[k] = 0; i[k]++; continue;
-				}
-				data[k][i[k]] |= (~v & 1) << (j[k]++ - 1);	/* Data bit */
-			}
-			t[k]--; 
-		}
-	} while (t[0] > 0 || t[1] > 0);
-
-	__restore_flags(flags);
-
-	return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
-}
-
-/*
- * tmdc_read() reads and analyzes ThrustMaster joystick data.
- */
-
-static void tmdc_timer(unsigned long private)
-{
-	unsigned char data[2][TMDC_MAX_LENGTH];
-	struct tmdc *tmdc = (void *) private;
-	struct input_dev *dev;
-	unsigned char r, bad = 0;
-	int i, j, k, l;
-
-	tmdc->reads++;
-
-	if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
-		bad = 1;
-
-	for (j = 0; j < 2; j++) 
-		if (r & (1 << j) & tmdc->exists) {
-
-			if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
-				bad = 1;
-				continue;
-			}
-
-			dev = tmdc->dev + j;
-
-			for (i = 0; i < tmdc->absc[j]; i++) {
-				if (tmdc->abs[j][i] < 0) continue;
-				input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
-			}
-
-			switch (tmdc->mode[j]) {
-
-				case TMDC_MODE_M3DI:
-
-					i = tmdc_byte_d[0];
-					input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
-					input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i]       & 1));
-					break;
-
-				case TMDC_MODE_AT:
-
-					i = tmdc_byte_a[3];
-					input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
-					input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
-					break;
-
-			}
-
-			for (k = l = 0; k < 4; k++) {
-				for (i = 0; i < tmdc->btnc[j][k]; i++)
-					input_report_key(dev, tmdc->btn[j][i + l],
-						((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
-				l += tmdc->btnc[j][k];
-			}
-	}
-
-	tmdc->bads += bad;
-
-	mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
-}
-
-static int tmdc_open(struct input_dev *dev)
-{
-	struct tmdc *tmdc = dev->private;
-	if (!tmdc->used++)
-		mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);	
-	return 0;
-}
-
-static void tmdc_close(struct input_dev *dev)
-{
-	struct tmdc *tmdc = dev->private;
-	if (!--tmdc->used)
-		del_timer(&tmdc->timer);
-}
-
-/*
- * tmdc_probe() probes for ThrustMaster type joysticks.
- */
-
-static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
-{
-	struct models {
-		unsigned char id;
-		char *name;
-		char abs;
-		char hats;
-		char btnc[4];
-		char btno[4];
-		signed char *axes;
-		short *buttons;
-	} models[] = {	{   1, "ThrustMaster Millenium 3D Inceptor",	  6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
-			{   3, "ThrustMaster Rage 3D Gamepad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
-			{   4, "ThrustMaster Attack Throttle",		  5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
-			{   8, "ThrustMaster FragMaster",		  4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
-			{ 163, "Thrustmaster Fusion GamePad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
-			{   0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
-
-	unsigned char data[2][TMDC_MAX_LENGTH];
-	struct tmdc *tmdc;
-	int i, j, k, l, m;
-
-	if (!(tmdc = kmalloc(sizeof(struct tmdc), GFP_KERNEL)))
-		return;
-	memset(tmdc, 0, sizeof(struct tmdc));
-
-	gameport->private = tmdc;
-
-	tmdc->gameport = gameport;
-	init_timer(&tmdc->timer);
-	tmdc->timer.data = (long) tmdc;
-	tmdc->timer.function = tmdc_timer;
-
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		goto fail1;
-
-	if (!(tmdc->exists = tmdc_read_packet(gameport, data)))
-		goto fail2;
-
-	for (j = 0; j < 2; j++)
-		if (tmdc->exists & (1 << j)) {
-
-			tmdc->mode[j] = data[j][TMDC_BYTE_ID];
-
-			for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
-
-			tmdc->abs[j] = models[m].axes;
-			tmdc->btn[j] = models[m].buttons;
-
-			if (!models[m].id) {
-				models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
-				for (k = 0; k < 4; k++)
-					models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
-			}
-
-			tmdc->absc[j] = models[m].abs;
-			for (k = 0; k < 4; k++) {
-				tmdc->btnc[j][k] = models[m].btnc[k];
-				tmdc->btno[j][k] = models[m].btno[k];
-			}
-
-			sprintf(tmdc->name[j], models[m].name, models[m].abs,
-				(data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
-
-			tmdc->dev[j].private = tmdc;
-			tmdc->dev[j].open = tmdc_open;
-			tmdc->dev[j].close = tmdc_close;
-
-			tmdc->dev[j].name = tmdc->name[j];
-			tmdc->dev[j].idbus = BUS_GAMEPORT;
-			tmdc->dev[j].idvendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
-			tmdc->dev[j].idproduct = models[m].id;
-			tmdc->dev[j].idversion = 0x0100;
-
-			tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-			for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
-				if (tmdc->abs[i] < 0) continue;
-				set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
-				tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
-				tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
-				tmdc->dev[j].absfuzz[tmdc->abs[j][i]] = 2;
-				tmdc->dev[j].absflat[tmdc->abs[j][i]] = 4;
-			}
-
-			for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++) {
-				set_bit(tmdc_abs_hat[i], tmdc->dev[j].absbit);
-				tmdc->dev[j].absmin[tmdc_abs_hat[i]] = -1;
-				tmdc->dev[j].absmax[tmdc_abs_hat[i]] = 1;
-			}
-
-			for (k = l = 0; k < 4; k++) {
-				for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
-					set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
-				l += models[m].btnc[k];
-			}
-
-			input_register_device(tmdc->dev + j);
-			printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
-				tmdc->dev[j].number, tmdc->name[j], gameport->number, j);
-		}
-
-	return;
-fail2:	gameport_close(gameport);
-fail1:	kfree(tmdc);
-}
-
-static void tmdc_disconnect(struct gameport *gameport)
-{
-	struct tmdc *tmdc = gameport->private;
-	int i;
-	for (i = 0; i < 2; i++)
-		if (tmdc->exists & (1 << i)) 
-			input_unregister_device(tmdc->dev + i);
-	gameport_close(gameport);
-	kfree(tmdc);
-}
-
-static struct gameport_dev tmdc_dev = {
-	connect:	tmdc_connect,
-	disconnect:	tmdc_disconnect,
-};
-
-int __init tmdc_init(void)
-{
-	gameport_register_device(&tmdc_dev);
-	return 0;
-}
-
-void __exit tmdc_exit(void)
-{
-	gameport_unregister_device(&tmdc_dev);
-}
-
-module_init(tmdc_init);
-module_exit(tmdc_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/joystick/turbografx.c b/drivers/char/joystick/turbografx.c
--- a/drivers/char/joystick/turbografx.c	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,259 +0,0 @@
-/*
- * $Id: turbografx.c,v 1.8 2000/05/29 20:39:38 vojtech Exp $
- *
- *  Copyright (c) 1998-2000 Vojtech Pavlik
- *
- *  Based on the work of:
- *	Steffen Schwenke
- *
- *  Sponsored by SuSE
- */
-
-/*
- * TurboGraFX parallel port interface driver for Linux.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/parport.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_LICENSE("GPL");
-MODULE_PARM(tgfx, "2-8i");
-MODULE_PARM(tgfx_2, "2-8i");
-MODULE_PARM(tgfx_3, "2-8i");
-
-#define TGFX_REFRESH_TIME	HZ/100	/* 10 ms */
-
-#define TGFX_TRIGGER		0x08
-#define TGFX_UP			0x10
-#define TGFX_DOWN		0x20	
-#define TGFX_LEFT		0x40
-#define TGFX_RIGHT		0x80
-
-#define TGFX_THUMB		0x02
-#define TGFX_THUMB2		0x04
-#define TGFX_TOP		0x01
-#define TGFX_TOP2		0x08
-
-static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-
-static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
-static char *tgfx_name = "TurboGraFX Multisystem joystick";
-
-struct tgfx {
-	struct pardevice *pd;
-	struct timer_list timer;
-	struct input_dev dev[7];
-	int sticks;
-	int used;
-} *tgfx_base[3];
-
-/*
- * tgfx_timer() reads and analyzes TurboGraFX joystick data.
- */
-
-static void tgfx_timer(unsigned long private)
-{
-	struct tgfx *tgfx = (void *) private;
-	struct input_dev *dev;
-	int data1, data2, i;
-
-	for (i = 0; i < 7; i++)
-		if (tgfx->sticks & (1 << i)) {
-
- 			dev = tgfx->dev + i;
-
-			parport_write_data(tgfx->pd->port, ~(1 << i));
-			data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
-			data2 = parport_read_control(tgfx->pd->port) ^ 0x04;	/* CAVEAT parport */
-
-			input_report_abs(dev, ABS_X, !!(data1 & TGFX_RIGHT) - !!(data1 & TGFX_LEFT));
-			input_report_abs(dev, ABS_Y, !!(data1 & TGFX_DOWN ) - !!(data1 & TGFX_UP  ));
-
-			input_report_key(dev, BTN_TRIGGER, (data1 & TGFX_TRIGGER));
-			input_report_key(dev, BTN_THUMB,   (data2 & TGFX_THUMB  ));
-			input_report_key(dev, BTN_THUMB2,  (data2 & TGFX_THUMB2 ));
-			input_report_key(dev, BTN_TOP,     (data2 & TGFX_TOP    ));
-			input_report_key(dev, BTN_TOP2,    (data2 & TGFX_TOP2   ));
-		}
-
-	mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
-}
-
-static int tgfx_open(struct input_dev *dev)
-{
-        struct tgfx *tgfx = dev->private;
-        if (!tgfx->used++) {
-		parport_claim(tgfx->pd);
-		parport_write_control(tgfx->pd->port, 0x04);
-                mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); 
-	}
-        return 0;
-}
-
-static void tgfx_close(struct input_dev *dev)
-{
-        struct tgfx *tgfx = dev->private;
-        if (!--tgfx->used) {
-                del_timer(&tgfx->timer);
-		parport_write_control(tgfx->pd->port, 0x00);
-        	parport_release(tgfx->pd);
-	}
-}
-
-/*
- * tgfx_probe() probes for tg gamepads.
- */
-
-static struct tgfx __init *tgfx_probe(int *config)
-{
-	struct tgfx *tgfx;
-	struct parport *pp;
-	int i, j;
-
-	if (config[0] < 0)
-		return NULL;
-
-	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
-		config[0]--;
-
-	if (!pp) {
-		printk(KERN_ERR "turbografx.c: no such parport\n");
-		return NULL;
-	}
-
-	if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL)))
-		return NULL;
-	memset(tgfx, 0, sizeof(struct tgfx));
-
-	tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-
-	if (!tgfx->pd) {
-		printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
-		kfree(tgfx);
-		return NULL;
-	}
-
-	init_timer(&tgfx->timer);
-	tgfx->timer.data = (long) tgfx;
-	tgfx->timer.function = tgfx_timer;
-
-	tgfx->sticks = 0;
-
-	for (i = 0; i < 7; i++)
-		if (config[i+1] > 0 && config[i+1] < 6) {
-
-			tgfx->sticks |= (1 << i);
-
-			tgfx->dev[i].private = tgfx;
-			tgfx->dev[i].open = tgfx_open;
-			tgfx->dev[i].close = tgfx_close;
-
-			tgfx->dev[i].name = tgfx_name;
-			tgfx->dev[i].idbus = BUS_PARPORT;
-			tgfx->dev[i].idvendor = 0x0003;
-			tgfx->dev[i].idproduct = config[i+1];
-			tgfx->dev[i].idversion = 0x0100;
-
-			tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-			tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
-			for (j = 0; j < config[i+1]; j++)
-				set_bit(tgfx_buttons[j], tgfx->dev[i].keybit); 
-
-			tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
-			tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
-
-			input_register_device(tgfx->dev + i);
-			printk(KERN_INFO "input%d: %d-button Multisystem joystick on %s\n",
-				tgfx->dev[i].number, config[i+1], tgfx->pd->port->name);
-		}
-
-        if (!tgfx->sticks) {
-		parport_unregister_device(tgfx->pd);
-		kfree(tgfx);
-		return NULL;
-        }
-		
-	return tgfx;
-}
-
-#ifndef MODULE
-int __init tgfx_setup(char *str)
-{
-	int i, ints[9];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 8; i++) tgfx[i] = ints[i + 1];
-	return 1;
-}
-int __init tgfx_setup_2(char *str)
-{
-	int i, ints[9];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 8; i++) tgfx_2[i] = ints[i + 1];
-	return 1;
-}
-int __init tgfx_setup_3(char *str)
-{
-	int i, ints[9];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 8; i++) tgfx_3[i] = ints[i + 1];
-	return 1;
-}
-__setup("tgfx=", tgfx_setup);
-__setup("tgfx_2=", tgfx_setup_2);
-__setup("tgfx_3=", tgfx_setup_3);
-#endif
-
-int __init tgfx_init(void)
-{
-	tgfx_base[0] = tgfx_probe(tgfx);
-	tgfx_base[1] = tgfx_probe(tgfx_2);
-	tgfx_base[2] = tgfx_probe(tgfx_3);
-
-	if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
-		return 0;
-
-	return -ENODEV;
-}
-
-void __exit tgfx_exit(void)
-{
-	int i, j;
-
-	for (i = 0; i < 3; i++) 
-		if (tgfx_base[i]) {
-			for (j = 0; j < 7; j++)
-				if (tgfx_base[i]->sticks & (1 << j))
-					input_unregister_device(tgfx_base[i]->dev + j);
-		parport_unregister_device(tgfx_base[i]->pd);
-	}
-}
-
-module_init(tgfx_init);
-module_exit(tgfx_exit);
diff -Nru a/drivers/char/joystick/warrior.c b/drivers/char/joystick/warrior.c
--- a/drivers/char/joystick/warrior.c	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,214 +0,0 @@
-/*
- * $Id: warrior.c,v 1.8 2000/05/31 13:17:12 vojtech Exp $
- *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
- */
-
-/*
- * Logitech WingMan Warrior joystick driver for Linux
- */
-
-/*
- * This program is free warftware; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- *  Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/serio.h>
-#include <linux/init.h>
-
-/*
- * Constants.
- */
-
-#define WARRIOR_MAX_LENGTH	16
-static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 }; 
-static char *warrior_name = "Logitech WingMan Warrior";
-
-/*
- * Per-Warrior data.
- */
-
-struct warrior {
-	struct input_dev dev;
-	int idx, len;
-	unsigned char data[WARRIOR_MAX_LENGTH];
-};
-
-/*
- * warrior_process_packet() decodes packets the driver receives from the
- * Warrior. It updates the data accordingly.
- */
-
-static void warrior_process_packet(struct warrior *warrior)
-{
-	struct input_dev *dev = &warrior->dev;
-	unsigned char *data = warrior->data;
-
-	if (!warrior->idx) return;
-
-	switch ((data[0] >> 4) & 7) {
-		case 1:					/* Button data */
-			input_report_key(dev, BTN_TRIGGER,  data[3]       & 1);
-			input_report_key(dev, BTN_THUMB,   (data[3] >> 1) & 1);
-			input_report_key(dev, BTN_TOP,     (data[3] >> 2) & 1);
-			input_report_key(dev, BTN_TOP2,    (data[3] >> 3) & 1);
-			return;
-		case 3:					/* XY-axis info->data */
-			input_report_abs(dev, ABS_X, ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5)));
-			input_report_abs(dev, ABS_Y, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
-			return;
-		case 5:					/* Throttle, spinner, hat info->data */
-			input_report_abs(dev, ABS_THROTTLE, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
-			input_report_abs(dev, ABS_HAT0X, (data[3] & 2 ? 1 : 0) - (data[3] & 1 ? 1 : 0));
-			input_report_abs(dev, ABS_HAT0Y, (data[3] & 8 ? 1 : 0) - (data[3] & 4 ? 1 : 0));
-			input_report_rel(dev, REL_DIAL,  (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5));
-			return;
-	}
-}
-
-/*
- * warrior_interrupt() is called by the low level driver when characters
- * are ready for us. We then buffer them for further processing, or call the
- * packet processing routine.
- */
-
-static void warrior_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
-{
-	struct warrior* warrior = serio->private;
-
-	if (data & 0x80) {
-		if (warrior->idx) warrior_process_packet(warrior);
-		warrior->idx = 0;
-		warrior->len = warrior_lengths[(data >> 4) & 7];
-	}
-
-	if (warrior->idx < warrior->len)
-		warrior->data[warrior->idx++] = data;
-
-	if (warrior->idx == warrior->len) {
-		if (warrior->idx) warrior_process_packet(warrior);	
-		warrior->idx = 0;
-		warrior->len = 0;
-	}
-}
-
-/*
- * warrior_disconnect() is the opposite of warrior_connect()
- */
-
-static void warrior_disconnect(struct serio *serio)
-{
-	struct warrior* warrior = serio->private;
-	input_unregister_device(&warrior->dev);
-	serio_close(serio);
-	kfree(warrior);
-}
-
-/*
- * warrior_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Warrior, and if found, registers
- * it as an input device.
- */
-
-static void warrior_connect(struct serio *serio, struct serio_dev *dev)
-{
-	struct warrior *warrior;
-	int i;
-
-	if (serio->type != (SERIO_RS232 | SERIO_WARRIOR))
-		return;
-
-	if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
-		return;
-
-	memset(warrior, 0, sizeof(struct warrior));
-
-	warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);	
-	warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
-	warrior->dev.relbit[0] = BIT(REL_DIAL);
-	warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
-
-	warrior->dev.name = warrior_name;
-	warrior->dev.idbus = BUS_RS232;
-	warrior->dev.idvendor = SERIO_WARRIOR;
-	warrior->dev.idproduct = 0x0001;
-	warrior->dev.idversion = 0x0100;
-
-	for (i = 0; i < 2; i++) {
-		warrior->dev.absmax[ABS_X+i] = -64;	
-		warrior->dev.absmin[ABS_X+i] =  64;	
-		warrior->dev.absflat[ABS_X+i] = 8;	
-	}
-
-	warrior->dev.absmax[ABS_THROTTLE] = -112;	
-	warrior->dev.absmin[ABS_THROTTLE] =  112;	
-
-	for (i = 0; i < 2; i++) {
-		warrior->dev.absmax[ABS_HAT0X+i] = -1;	
-		warrior->dev.absmin[ABS_HAT0X+i] =  1;	
-	}
-
-	warrior->dev.private = warrior;
-	
-	serio->private = warrior;
-
-	if (serio_open(serio, dev)) {
-		kfree(warrior);
-		return;
-	}
-
-	input_register_device(&warrior->dev);
-
-	printk(KERN_INFO "input%d: Logitech WingMan Warrior on serio%d\n", warrior->dev.number, serio->number);
-}
-
-/*
- * The serio device structure.
- */
-
-static struct serio_dev warrior_dev = {
-	interrupt:	warrior_interrupt,
-	connect:	warrior_connect,
-	disconnect:	warrior_disconnect,
-};
-
-/*
- * The functions for inserting/removing us as a module.
- */
-
-int __init warrior_init(void)
-{
-	serio_register_device(&warrior_dev);
-	return 0;
-}
-
-void __exit warrior_exit(void)
-{
-	serio_unregister_device(&warrior_dev);
-}
-
-module_init(warrior_init);
-module_exit(warrior_exit);
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c
--- a/drivers/char/lp.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/char/lp.c	Sun Feb 10 19:58:03 2002
@@ -648,7 +648,7 @@
 	do {
 		/* Write the data, converting LF->CRLF as we go. */
 		ssize_t canwrite = count;
-		char *lf = strchr (s, '\n');
+		char *lf = memchr (s, '\n', count);
 		if (lf)
 			canwrite = lf - s;
 
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/mem.c	Sun Feb 10 19:58:06 2002
@@ -21,6 +21,7 @@
 #include <linux/raw.h>
 #include <linux/tty.h>
 #include <linux/capability.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -466,16 +467,23 @@
  */
 static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
 {
+	int ret;
+
+	lock_kernel();
 	switch (orig) {
 		case 0:
 			file->f_pos = offset;
-			return file->f_pos;
+			ret = file->f_pos;
+			break;
 		case 1:
 			file->f_pos += offset;
-			return file->f_pos;
+			ret = file->f_pos;
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
 	}
+	unlock_kernel();
+	return ret;
 }
 
 static int open_port(struct inode * inode, struct file * filp)
diff -Nru a/drivers/char/nvram.c b/drivers/char/nvram.c
--- a/drivers/char/nvram.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/nvram.c	Sun Feb 10 19:58:05 2002
@@ -216,6 +216,7 @@
 
 static long long nvram_llseek(struct file *file,loff_t offset, int origin )
 {
+	lock_kernel();
 	switch( origin ) {
 	  case 0:
 		/* nothing to do */
@@ -227,6 +228,7 @@
 		offset += NVRAM_BYTES;
 		break;
 	}
+	unlock_kernel();
 	return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL );
 }
 
diff -Nru a/drivers/char/nwflash.c b/drivers/char/nwflash.c
--- a/drivers/char/nwflash.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/nwflash.c	Sun Feb 10 19:58:06 2002
@@ -26,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 
 #include <asm/hardware/dec21285.h>
 #include <asm/io.h>
@@ -301,30 +302,45 @@
  */
 static long long flash_llseek(struct file *file, long long offset, int orig)
 {
+	long long ret;
+
+	lock_kernel();
 	if (flashdebug)
 		printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
 		       (unsigned int) offset, orig);
 
 	switch (orig) {
 	case 0:
-		if (offset < 0)
-			return -EINVAL;
+		if (offset < 0) {
+			ret = -EINVAL;
+			break;
+		}
 
-		if ((unsigned int) offset > gbFlashSize)
-			return -EINVAL;
+		if ((unsigned int) offset > gbFlashSize) {
+			ret = -EINVAL;
+			break;
+		}
 
 		file->f_pos = (unsigned int) offset;
-		return file->f_pos;
+		ret = file->f_pos;
+		break;
 	case 1:
-		if ((file->f_pos + offset) > gbFlashSize)
-			return -EINVAL;
-		if ((file->f_pos + offset) < 0)
-			return -EINVAL;
+		if ((file->f_pos + offset) > gbFlashSize) {
+			ret = -EINVAL;
+			break;
+		}
+		if ((file->f_pos + offset) < 0) {
+			ret = -EINVAL;
+			break;
+		}
 		file->f_pos += offset;
-		return file->f_pos;
+		ret = file->f_pos;
+		break;
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+	unlock_kernel();
+	return ret;
 }
 
 
diff -Nru a/drivers/char/ppdev.c b/drivers/char/ppdev.c
--- a/drivers/char/ppdev.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/ppdev.c	Sun Feb 10 19:58:06 2002
@@ -320,6 +320,7 @@
 	case PPCLAIM:
 	    {
 		struct ieee1284_info *info;
+		int ret;
 
 		if (pp->flags & PP_CLAIMED) {
 			printk (KERN_DEBUG CHRDEV
@@ -335,7 +336,10 @@
 			}
 		}
 
-		parport_claim_or_block (pp->pdev);
+		ret = parport_claim_or_block (pp->pdev);
+		if (ret < 0)
+			return ret;
+
 		pp->flags |= PP_CLAIMED;
 
 		/* For interrupt-reporting to work, we need to be
@@ -429,8 +433,12 @@
 	    {
 		unsigned int modes;
 
-		modes = pp->pdev->port->modes;
-		if (copy_to_user ((unsigned int *)arg, &modes, sizeof (port->modes))) {
+		port = parport_find_number (minor);
+		if (!port)
+			return -ENODEV;
+
+		modes = port->modes;
+		if (copy_to_user ((unsigned int *)arg, &modes, sizeof (modes))) {
 			return -EFAULT;
 		}
 		return 0;
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/char/random.c	Sun Feb 10 19:58:04 2002
@@ -251,6 +251,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
+#include <linux/fs.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
--- a/drivers/char/rio/rio_linux.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/char/rio/rio_linux.c	Sun Feb 10 19:58:04 2002
@@ -742,7 +742,7 @@
   case TIOCGSERIAL:
     if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
                           sizeof(struct serial_struct))) == 0)
-      gs_getserial(&PortP->gs, (struct serial_struct *) arg);
+      rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);
     break;
   case TCSBRK:
     if ( PortP->State & RIO_DELETED ) {
diff -Nru a/drivers/char/serial.c b/drivers/char/serial.c
--- a/drivers/char/serial.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/serial.c	Sun Feb 10 19:58:05 2002
@@ -3095,36 +3095,52 @@
 
 	sstate = rs_table + line;
 	sstate->count++;
-	if (sstate->info) {
-		*ret_info = sstate->info;
-		return 0;
-	}
+	info = sstate->info;
+
+	/*
+	 * If the async_struct is already allocated, do the fastpath.
+	 */
+	if (info)
+		goto out;
+
 	info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
 	if (!info) {
 		sstate->count--;
 		return -ENOMEM;
 	}
+
 	memset(info, 0, sizeof(struct async_struct));
 	init_waitqueue_head(&info->open_wait);
 	init_waitqueue_head(&info->close_wait);
 	init_waitqueue_head(&info->delta_msr_wait);
 	info->magic = SERIAL_MAGIC;
 	info->port = sstate->port;
+	info->hub6 = sstate->hub6;
 	info->flags = sstate->flags;
-	info->io_type = sstate->io_type;
-	info->iomem_base = sstate->iomem_base;
-	info->iomem_reg_shift = sstate->iomem_reg_shift;
 	info->xmit_fifo_size = sstate->xmit_fifo_size;
+	info->state = sstate;
 	info->line = line;
+	info->iomem_base = sstate->iomem_base;
+	info->iomem_reg_shift = sstate->iomem_reg_shift;
+	info->io_type = sstate->io_type;
 	info->tqueue.routine = do_softint;
 	info->tqueue.data = info;
-	info->state = sstate;
+
 	if (sstate->info) {
 		kfree(info);
-		*ret_info = sstate->info;
-		return 0;
+		info = sstate->info;
+	} else {
+		sstate->info = info;
+	}
+
+out:
+	/*
+	 * If this is the first open, copy over some timeouts.
+	 */
+	if (sstate->count == 1) {
+		info->closing_wait = sstate->closing_wait;
 	}
-	*ret_info = sstate->info = info;
+	*ret_info = info;
 	return 0;
 }
 
diff -Nru a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c
--- a/drivers/char/serial_tx3912.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/serial_tx3912.c	Sun Feb 10 19:58:06 2002
@@ -673,7 +673,7 @@
 	case TIOCGSERIAL:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
 		                      sizeof(struct serial_struct))) == 0)
-			gs_getserial(&port->gs, (struct serial_struct *) arg);
+			rc = gs_getserial(&port->gs, (struct serial_struct *) arg);
 		break;
 	case TIOCSSERIAL:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg,
diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c
--- a/drivers/char/sh-sci.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/sh-sci.c	Sun Feb 10 19:58:06 2002
@@ -919,7 +919,7 @@
 	case TIOCGSERIAL:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
 		                      sizeof(struct serial_struct))) == 0)
-			gs_getserial(&port->gs, (struct serial_struct *) arg);
+			rc = gs_getserial(&port->gs, (struct serial_struct *) arg);
 		break;
 	case TIOCSSERIAL:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg,
diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c
--- a/drivers/char/sx.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/sx.c	Sun Feb 10 19:58:05 2002
@@ -1160,7 +1160,8 @@
 				/* DCD went UP */
 				if( (~(port->gs.flags & ASYNC_NORMAL_ACTIVE) || 
 						 ~(port->gs.flags & ASYNC_CALLOUT_ACTIVE)) &&
-						(sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED)) {
+						(sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) &&
+						!(port->gs.tty->termios->c_cflag & CLOCAL) ) {
 					/* Are we blocking in open?*/
 					sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD active, unblocking open\n");
 					wake_up_interruptible(&port->gs.open_wait);
@@ -1170,7 +1171,8 @@
 			} else {
 				/* DCD went down! */
 				if (!((port->gs.flags & ASYNC_CALLOUT_ACTIVE) &&
-				      (port->gs.flags & ASYNC_CALLOUT_NOHUP))) {
+				      (port->gs.flags & ASYNC_CALLOUT_NOHUP)) &&
+				    !(port->gs.tty->termios->c_cflag & CLOCAL) ) {
 					sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. hanging up....\n");
 					tty_hangup (port->gs.tty);
 				} else {
@@ -1815,7 +1817,7 @@
 	case TIOCGSERIAL:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
 		                      sizeof(struct serial_struct))) == 0)
-			gs_getserial(&port->gs, (struct serial_struct *) arg);
+			rc = gs_getserial(&port->gs, (struct serial_struct *) arg);
 		break;
 	case TIOCSSERIAL:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg,
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/synclink.c	Sun Feb 10 19:58:05 2002
@@ -60,6 +60,8 @@
 #  define BREAKPOINT() { }
 #endif
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #define MAX_ISA_DEVICES 10
 #define MAX_PCI_DEVICES 10
 #define MAX_TOTAL_DEVICES 20
diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
--- a/drivers/char/tpqic02.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/char/tpqic02.c	Sun Feb 10 19:58:06 2002
@@ -1408,7 +1408,7 @@
 	clear_dma_ff(QIC02_TAPE_DMA);
 	set_dma_mode(QIC02_TAPE_DMA, dma_mode);
 	set_dma_addr(QIC02_TAPE_DMA,
-		     virt_to_bus(buffaddr) + dma_bytes_done);
+		     isa_virt_to_bus(buffaddr) + dma_bytes_done);
 	set_dma_count(QIC02_TAPE_DMA, TAPE_BLKSIZE);
 
 	/* start tape DMA controller */
diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
--- a/drivers/char/vc_screen.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/char/vc_screen.c	Sun Feb 10 19:58:05 2002
@@ -36,6 +36,7 @@
 #include <linux/selection.h>
 #include <linux/kbd_kern.h>
 #include <linux/console.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
@@ -67,10 +68,13 @@
 
 static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
 {
-	int size = vcs_size(file->f_dentry->d_inode);
+	int size;
 
+	lock_kernel();
+	size = vcs_size(file->f_dentry->d_inode);
 	switch (orig) {
 		default:
+			unlock_kernel();
 			return -EINVAL;
 		case 2:
 			offset += size;
@@ -80,9 +84,12 @@
 		case 0:
 			break;
 	}
-	if (offset < 0 || offset > size)
+	if (offset < 0 || offset > size) {
+		unlock_kernel();
 		return -EINVAL;
+	}
 	file->f_pos = offset;
+	unlock_kernel();
 	return file->f_pos;
 }
 
diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
--- a/drivers/hotplug/pci_hotplug_core.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/hotplug/pci_hotplug_core.c	Sun Feb 10 19:58:05 2002
@@ -362,7 +362,7 @@
 	put_inode:	force_delete,
 };
 
-static struct super_block *pcihpfs_read_super (struct super_block *sb, void *data, int silent)
+static int pcihpfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
 	struct dentry *root;
@@ -375,20 +375,31 @@
 
 	if (!inode) {
 		dbg("%s: could not get inode!\n",__FUNCTION__);
-		return NULL;
+		return -ENOMEM;
 	}
 
 	root = d_alloc_root(inode);
 	if (!root) {
 		dbg("%s: could not get root dentry!\n",__FUNCTION__);
 		iput(inode);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root = root;
-	return sb;
+	return 0;
+}
+
+static struct super_block *pcihpfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, pcihpfs_fill_super);
 }
 
-static DECLARE_FSTYPE(pcihpfs_fs_type, "pcihpfs", pcihpfs_read_super, FS_SINGLE | FS_LITTER);
+static struct file_system_type pcihpfs_type = {
+	owner:		THIS_MODULE,
+	name:		"pcihpfs",
+	get_sb:		pcihpfs_get_sb,
+	fs_flags:	FS_LITTER,
+};
 
 static int get_mount (void)
 {
@@ -403,7 +414,7 @@
 	}
 
 	spin_unlock (&mount_lock);
-	mnt = kern_mount (&pcihpfs_fs_type);
+	mnt = kern_mount (&pcihpfs_type);
 	if (IS_ERR(mnt)) {
 		err ("could not mount the fs...erroring out!\n");
 		return -ENODEV;
@@ -1103,7 +1114,7 @@
 	spin_lock_init(&list_lock);
 
 	dbg("registering filesystem.\n");
-	result = register_filesystem(&pcihpfs_fs_type);
+	result = register_filesystem(&pcihpfs_type);
 	if (result) {
 		err("register_filesystem failed with %d\n", result);
 		goto exit;
@@ -1117,7 +1128,7 @@
 
 static void __exit pci_hotplug_exit (void)
 {
-	unregister_filesystem(&pcihpfs_fs_type);
+	unregister_filesystem(&pcihpfs_type);
 }
 
 module_init(pci_hotplug_init);
diff -Nru a/drivers/ide/Config.help b/drivers/ide/Config.help
--- a/drivers/ide/Config.help	Sun Feb 10 19:58:06 2002
+++ b/drivers/ide/Config.help	Sun Feb 10 19:58:06 2002
@@ -796,3 +796,61 @@
   Enable vendor-specific code for TiVo IDE disks.  Unless you are the
   IDE maintainer, you probably do not want to mess with this.
 
+CONFIG_IDEDISK_STROKE
+  Should you have a system w/ an AWARD Bios and your drives are larger
+  than 32GB and it will not boot, one is required to perform a few OEM
+  operations first.  The option is called "STROKE" because it allows
+  one to "soft clip" the drive to work around a barrier limit.  For
+  Maxtor drives it is called "jumpon.exe".  Please search Maxtor's
+  web-site for "JUMPON.EXE".  IBM has a similar tool at:
+  <http://www.storage.ibm.com/hdd/support/download.htm>.
+
+  If you are unsure, say N here.
+
+CONFIG_IDE_TASK_IOCTL
+  This is a direct raw access to the media.  It is a complex but
+  elegant solution to test and validate the domain of the hardware and
+  perform below the driver data recovery if needed.  This is the most
+  basic form of media-forensics.
+
+  If you are unsure, say N here.
+
+CONFIG_BLK_DEV_IDEDMA_FORCED
+  This is an old piece of lost code from Linux 2.0 Kernels.
+
+  Generally say N here.
+
+CONFIG_IDEDMA_ONLYDISK
+  This is used if you know your ATAPI Devices are going to fail DMA
+  Transfers.
+
+  Generally say N here.
+
+CONFIG_BLK_DEV_IT8172
+  Say Y here to support the on-board IDE controller on the Integrated
+  Technology Express, Inc. ITE8172 SBC.  Vendor page at
+  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
+  board at <http://www.mvista.com/allies/semiconductor/ite.html>.
+
+CONFIG_IT8172_TUNING
+  Say Y here to support tuning the ITE8172's IDE interface.  This makes
+  it possible to set DMA channel or PIO opration and the transfer rate.
+
+CONFIG_IT8172_REVC
+  Say Y here to support the older, Revision C version of the Integrated
+  Technology Express, Inc. ITE8172 SBC.  Vendor page at
+  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
+  board at <http://www.mvista.com/allies/semiconductor/ite.html>.
+
+CONFIG_IT8172_SCR0
+  Say Y here to support smart-card reader 0 (SCR0) on the Integrated
+  Technology Express, Inc. ITE8172 SBC.  Vendor page at
+  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
+  board at <http://www.mvista.com/allies/semiconductor/ite.html>.
+
+CONFIG_IT8172_SCR1
+  Say Y here to support smart-card reader 1 (SCR1) on the Integrated
+  Technology Express, Inc. ITE8172 SBC.  Vendor page at
+  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
+  board at <http://www.mvista.com/allies/semiconductor/ite.html>.
+
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/ide/ide-disk.c	Sun Feb 10 19:58:03 2002
@@ -192,11 +192,6 @@
 	sectors = rq->nr_sectors;
 	if (sectors == 256)
 		sectors = 0;
-	if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
-		sectors = drive->mult_count;
-		if (sectors > rq->current_nr_sectors)
-			sectors = rq->current_nr_sectors;
-	}
 
 	taskfile.sector_count	= sectors;
 	taskfile.sector_number	= sect;
@@ -241,11 +236,6 @@
 	sectors = rq->nr_sectors;
 	if (sectors == 256)
 		sectors = 0;
-	if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
-		sectors = drive->mult_count;
-		if (sectors > rq->current_nr_sectors)
-			sectors = rq->current_nr_sectors;
-	}
 
 	memset(&taskfile, 0, sizeof(task_struct_t));
 	memset(&hobfile, 0, sizeof(hob_struct_t));
@@ -300,13 +290,8 @@
 	memset(&hobfile, 0, sizeof(hob_struct_t));
 
 	sectors = rq->nr_sectors;
-	if (sectors == 256)
+	if (sectors == 65536)
 		sectors = 0;
-	if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
-		sectors = drive->mult_count;
-		if (sectors > rq->current_nr_sectors)
-			sectors = rq->current_nr_sectors;
-	}
 
 	taskfile.sector_count	= sectors;
 	hobfile.sector_count	= sectors >> 8;
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/ide/ide-dma.c	Sun Feb 10 19:58:04 2002
@@ -266,14 +266,16 @@
 #if 1	
 	if (sector_count > 128) {
 		memset(&sg[nents], 0, sizeof(*sg));
-		sg[nents].address = virt_addr;
+		sg[nents].page = virt_to_page(virt_addr);
+		sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
 		sg[nents].length = 128  * SECTOR_SIZE;
 		nents++;
 		virt_addr = virt_addr + (128 * SECTOR_SIZE);
 		sector_count -= 128;
 	}
 	memset(&sg[nents], 0, sizeof(*sg));
-	sg[nents].address = virt_addr;
+	sg[nents].page = virt_to_page(virt_addr);
+	sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
 	sg[nents].length =  sector_count  * SECTOR_SIZE;
 	nents++;
  #endif
diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
--- a/drivers/ide/ide-proc.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/ide/ide-proc.c	Sun Feb 10 19:58:04 2002
@@ -597,7 +597,7 @@
 	if (!driver)
 		len = sprintf(page, "(none)\n");
         else
-		len = sprintf(page,"%llu\n", (__u64) ((ide_driver_t *)drive->driver)->capacity(drive));
+		len = sprintf(page,"%llu\n", (unsigned long long) ((ide_driver_t *)drive->driver)->capacity(drive));
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/ide/ide-taskfile.c	Sun Feb 10 19:58:06 2002
@@ -255,6 +255,7 @@
 	return 1;		/* drive ready: *might* be interrupting */
 }
 
+ide_startstop_t bio_mulout_intr (ide_drive_t *drive);
 ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 {
 	task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
@@ -263,7 +264,7 @@
 	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
 
 	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (task->handler != task_mulout_intr) {
+	if (task->handler != task_mulout_intr && task->handler != bio_mulout_intr) {
 		if (IDE_CONTROL_REG)
 			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);	/* clear nIEN */
 		SELECT_MASK(HWIF(drive), drive, 0);
@@ -313,7 +314,7 @@
 	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
 
 	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (*handler != task_mulout_intr) {
+	if (*handler != task_mulout_intr && handler != bio_mulout_intr) {
 		if (IDE_CONTROL_REG)
 			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);  /* clear nIEN */
 		SELECT_MASK(HWIF(drive), drive, 0);
@@ -936,15 +937,12 @@
 	char *pBuf		= NULL;
 	unsigned long flags;
 
-	if (!rq->current_nr_sectors) { 
-		printk("task_out_intr: should not trigger\n");
-		ide_end_request(1, HWGROUP(drive));
-		return ide_stopped;
-	}
-
-	if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) {
+	if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat))
 		return ide_error(drive, "task_out_intr", stat);
-	}
+
+	if (!rq->current_nr_sectors)
+		if (!ide_end_request(1, HWGROUP(drive)))
+			return ide_stopped;
 
 	if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
 		rq = HWGROUP(drive)->rq;
@@ -958,16 +956,8 @@
 		rq->current_nr_sectors--;
 	}
 
-	if (rq->current_nr_sectors <= 0) {
-		if (ide_end_request(1, HWGROUP(drive))) {
-			ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
-			return ide_started;
-		}
-	} else {
-		ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
-		return ide_started;
-	}
-	return ide_stopped;
+	ide_set_handler(drive, task_out_intr, WAIT_CMD, NULL);
+	return ide_started;
 }
 
 /*
@@ -1061,14 +1051,132 @@
 	return ide_started;
 }
 
+ide_startstop_t pre_bio_out_intr (ide_drive_t *drive, struct request *rq)
+{
+	ide_task_t *args = rq->special;
+	ide_startstop_t startstop;
+
+	/*
+	 * assign private copy for multi-write
+	 */
+	memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
+
+	if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
+		return startstop;
+
+	/*
+	 * (ks/hs): Stuff the first sector(s)
+	 * by implicitly calling the handler
+	 */
+	if (!(drive_is_ready(drive))) {
+		int i;
+		/*
+		 * (ks/hs): FIXME: Replace hard-coded
+		 *               100, error handling?
+		 */
+		for (i=0; i<100; i++) {
+			if (drive_is_ready(drive))
+				break;
+		}
+	}
+
+	return args->handler(drive);
+}
+
+
+ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
+{
+#ifdef ALTSTAT_SCREW_UP
+	byte stat	= altstat_multi_busy(drive, GET_ALTSTAT(), "write");
+#else
+	byte stat		= GET_STAT();
+#endif /* ALTSTAT_SCREW_UP */
+
+	byte io_32bit		= drive->io_32bit;
+	struct request *rq	= &HWGROUP(drive)->wrq;
+	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
+	int mcount		= drive->mult_count;
+	ide_startstop_t startstop;
+
+	/*
+	 * (ks/hs): Handle last IRQ on multi-sector transfer,
+	 * occurs after all data was sent in this chunk
+	 */
+	if (!rq->nr_sectors) {
+		if (stat & (ERR_STAT|DRQ_STAT)) {
+			startstop = ide_error(drive, "bio_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
+		}
+
+		__ide_end_request(HWGROUP(drive), 1, rq->hard_nr_sectors);
+		HWGROUP(drive)->wrq.bio = NULL;
+		return ide_stopped;
+	}
+
+	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
+		if (stat & (ERR_STAT | DRQ_STAT)) {
+			startstop = ide_error(drive, "bio_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
+		}
+
+		/* no data yet, so wait for another interrupt */
+		if (hwgroup->handler == NULL)
+			ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
+
+		return ide_started;
+	}
+
+	do {
+  		char *buffer;
+  		int nsect = rq->current_nr_sectors;
+		unsigned long flags;
+
+		if (nsect > mcount)
+			nsect = mcount;
+		mcount -= nsect;
+
+		buffer = ide_map_buffer(rq, &flags);
+		rq->sector += nsect;
+		rq->nr_sectors -= nsect;
+		rq->current_nr_sectors -= nsect;
+
+		/* Do we move to the next bio after this? */
+		if (!rq->current_nr_sectors) {
+			/* remember to fix this up /jens */
+			struct bio *bio = rq->bio->bi_next;
+
+			/* end early early we ran out of requests */
+			if (!bio) {
+				mcount = 0;
+			} else {
+				rq->bio = bio;
+				rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
+			}
+		}
+
+		/*
+		 * Ok, we're all setup for the interrupt
+		 * re-entering us on the last transfer.
+		 */
+		taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
+		ide_unmap_buffer(buffer, &flags);
+	} while (mcount);
+
+	drive->io_32bit = io_32bit;
+	rq->errors = 0;
+	if (hwgroup->handler == NULL)
+		ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
+
+	return ide_started;
+}
+
 /* Called by internal to feature out type of command being called */
 ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
 {
 	switch(taskfile->command) {
 				/* IDE_DRIVE_TASK_RAW_WRITE */
-		case CFA_WRITE_MULTI_WO_ERASE:
-		case WIN_MULTWRITE:
-		case WIN_MULTWRITE_EXT:
 				/* IDE_DRIVE_TASK_OUT */
 		case WIN_WRITE:
 		case WIN_WRITE_EXT:
@@ -1077,7 +1185,10 @@
 		case CFA_WRITE_SECT_WO_ERASE:
 		case WIN_DOWNLOAD_MICROCODE:
 			return &pre_task_out_intr;
-				/* IDE_DRIVE_TASK_OUT */
+		case CFA_WRITE_MULTI_WO_ERASE:
+		case WIN_MULTWRITE:
+		case WIN_MULTWRITE_EXT:
+			return &pre_bio_out_intr;
 		case WIN_SMART:
 			if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
 				return &pre_task_out_intr;
@@ -1120,7 +1231,7 @@
 		case CFA_WRITE_MULTI_WO_ERASE:
 		case WIN_MULTWRITE:
 		case WIN_MULTWRITE_EXT:
-			return &task_mulout_intr;
+			return &bio_mulout_intr;
 		case WIN_SMART:
 			switch(taskfile->feature) {
 				case SMART_READ_VALUES:
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/ide/ide.c	Sun Feb 10 19:58:06 2002
@@ -813,7 +813,7 @@
 					high = read_24(drive);
 
 					sectors = ((__u64)high << 24) | low;
-					printk(", LBAsect=%lld, high=%d, low=%d", sectors, high, low);
+					printk(", LBAsect=%lld, high=%d, low=%d", (long long) sectors, high, low);
 				} else {
 					byte cur = IN_BYTE(IDE_SELECT_REG);
 					if (cur & 0x40) {	/* using LBA? */
diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
--- a/drivers/ieee1394/pcilynx.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/ieee1394/pcilynx.c	Sun Feb 10 19:58:05 2002
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
+#include <linux/smp_lock.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -732,8 +733,9 @@
 
 loff_t mem_llseek(struct file *file, loff_t offs, int orig)
 {
-        loff_t newoffs;
+        loff_t newoffs = -1;
 
+        lock_kernel();
         switch (orig) {
         case 0:
                 newoffs = offs;
@@ -743,12 +745,12 @@
                 break;
         case 2:
                 newoffs = PCILYNX_MAX_MEMORY + 1 + offs;
-                break;
-        default:
-                return -EINVAL;
         }
 
-        if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) return -EINVAL;
+        if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) {
+                lock_kernel();
+                return -EINVAL;
+        }
 
         file->f_pos = newoffs;
         return newoffs;
diff -Nru a/drivers/input/Config.help b/drivers/input/Config.help
--- a/drivers/input/Config.help	Sun Feb 10 19:58:05 2002
+++ b/drivers/input/Config.help	Sun Feb 10 19:58:05 2002
@@ -1,27 +1,35 @@
 CONFIG_INPUT
-  Say Y here if you want to enable any of the following options for
-  USB Human Interface Device (HID) support.
+  Say Y here if you have any input device (mouse, keyboard, tablet,
+  joystick, steering wheel ...) connected to your system and want
+  it to be available to applications. This includes standard PS/2
+  keyboard and mouse.
 
-  Say Y here if you want to enable any of the USB HID options in the
-  USB support section which require Input core support.
+  Say N here if you have a headless (no monitor, no keyboard) system.
 
-  Otherwise, say N.
+  More information is available: <file:Documentation/input/input.txt>
+
+  If unsure, say Y.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called input.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
 
 CONFIG_INPUT_KEYBDEV
-  Say Y here if you want your USB HID keyboard (or an ADB keyboard
-  handled by the input layer) to be able to serve as a system
-  keyboard.
+  Say Y here if you want your keyboard to be able to serve as a system
+  keyboard. This is needed in most cases. The only exceptions are
+  headless and embedded systems.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
-  The module will be called keybdev.o.  If you want to compile it as a
+  The module will be called keybdev.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
 CONFIG_INPUT_MOUSEDEV
-  Say Y here if you want your USB HID mouse (or ADB mouse handled by
-  the input layer) to be accessible as char devices 13:32+ -
-  /dev/input/mouseX and 13:63 - /dev/input/mice as an emulated ImPS/2
-  mouse.  That way, all user space programs will be able to use your
+  Say Y here if you want your mouse to be accessible as char devices
+  13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
+  emulated IntelliMouse Explorer PS/2 mouse. That way, all user space
+  programs (includung SVGAlib, GPM and X) will be able to use your
   mouse.
 
   If unsure, say Y.
@@ -44,16 +52,23 @@
   you're not using a digitizer, this value is ignored.
 
 CONFIG_INPUT_JOYDEV
-  Say Y here if you want your USB HID joystick or gamepad to be
+  Say Y here if you want your joystick or gamepad to be
   accessible as char device 13:0+ - /dev/input/jsX device.
 
+  If unsure, say Y.
+
+  More information is available: <file:Documentation/input/joystick.txt>
+
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called joydev.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
 CONFIG_INPUT_EVDEV
-  Say Y here if you want your USB or ADB HID device events be
-  accessible under char device 13:64+ - /dev/input/eventX in a generic
-  way.  This is the future ...
+  Say Y here if you want your input device events be accessible
+  under char device 13:64+ - /dev/input/eventX in a generic way.
 
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called evdev.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/input/Config.in b/drivers/input/Config.in
--- a/drivers/input/Config.in	Sun Feb 10 19:58:06 2002
+++ b/drivers/input/Config.in	Sun Feb 10 19:58:06 2002
@@ -1,18 +1,25 @@
 #
-# Input core configuration
+# Input device configuration
 #
 
 mainmenu_option next_comment
-comment 'Input core support'
+comment 'Input device support'
 
 tristate 'Input core support' CONFIG_INPUT
-dep_tristate '  Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT
-dep_tristate '  Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT
+dep_tristate '  Keyboard interface' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT
+dep_tristate '  Mouse interface' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT
 if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
    int '   Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
    int '   Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768
 fi
-dep_tristate '  Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT
-dep_tristate '  Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT
+dep_tristate '  Joystick interface' CONFIG_INPUT_JOYDEV $CONFIG_INPUT
+dep_tristate '  Event interface' CONFIG_INPUT_EVDEV $CONFIG_INPUT
+
+source drivers/input/gameport/Config.in
+source drivers/input/serio/Config.in
+
+if [ "$CONFIG_INPUT" != "n" ]; then
+   source drivers/input/joystick/Config.in
+fi
 
 endmenu
diff -Nru a/drivers/input/Makefile b/drivers/input/Makefile
--- a/drivers/input/Makefile	Sun Feb 10 19:58:05 2002
+++ b/drivers/input/Makefile	Sun Feb 10 19:58:05 2002
@@ -8,15 +8,9 @@
 
 # Objects that export symbols.
 
+mod-subdirs	:= joystick
 export-objs	:= input.o
 
-# Object file lists.
-
-obj-y	:=
-obj-m	:=
-obj-n	:=
-obj-	:=
-
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_INPUT)		+= input.o
@@ -24,6 +18,12 @@
 obj-$(CONFIG_INPUT_MOUSEDEV)	+= mousedev.o
 obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o
 obj-$(CONFIG_INPUT_EVDEV)	+= evdev.o
+
+subdir-$(CONFIG_INPUT_JOYSTICK)	+= joystick
+
+ifeq ($(CONFIG_INPUT_JOYSTICK),y)
+	obj-y += joystick/joydrv.o
+endif
 
 # The global Rules.make.
 
diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c
--- a/drivers/input/evdev.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/input/evdev.c	Sun Feb 10 19:58:04 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: evdev.c,v 1.42 2002/01/02 11:59:56 vojtech Exp $
  *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Event char devices, giving access to raw input device events.
- *
- *  Sponsored by SuSE
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #define EVDEV_MINOR_BASE	64
@@ -42,7 +40,9 @@
 struct evdev {
 	int exist;
 	int open;
+	int open_for_write;
 	int minor;
+	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	devfs_handle_t devfs;
@@ -89,6 +89,11 @@
 	return retval < 0 ? retval : 0;
 }
 
+static int evdev_flush(struct file * file)
+{
+	return input_flush_device(&((struct evdev_list*)file->private_data)->evdev->handle, file);
+}
+
 static int evdev_release(struct inode * inode, struct file * file)
 {
 	struct evdev_list *list = file->private_data;
@@ -120,10 +125,16 @@
 {
 	struct evdev_list *list;
 	int i = minor(inode->i_rdev) - EVDEV_MINOR_BASE;
+	int accept_err;
 
 	if (i >= EVDEV_MINORS || !evdev_table[i])
 		return -ENODEV;
 
+	/* Ask the driver if he wishes to accept the open() */
+	if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) {
+		return accept_err;
+	}
+
 	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
 		return -ENOMEM;
 	memset(list, 0, sizeof(struct evdev_list));
@@ -167,7 +178,7 @@
 	if (list->head == list->tail) {
 
 		add_wait_queue(&list->evdev->wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		while (list->head == list->tail) {
 
@@ -187,7 +198,7 @@
 			schedule();
 		}
 
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&list->evdev->wait, &wait);
 	}
 
@@ -219,7 +230,7 @@
 	struct evdev_list *list = file->private_data;
 	struct evdev *evdev = list->evdev;
 	struct input_dev *dev = evdev->handle.dev;
-	int retval;
+	int retval, t, u;
 
 	switch (cmd) {
 
@@ -232,6 +243,40 @@
 			if ((retval = put_user(dev->idproduct, ((short *) arg) + 2))) return retval;
 			if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval;
 			return 0;
+		
+		case EVIOCGREP:
+			if ((retval = put_user(dev->rep[0], ((int *) arg) + 0))) return retval;
+			if ((retval = put_user(dev->rep[1], ((int *) arg) + 1))) return retval;
+			return 0;
+
+		case EVIOCSREP:
+			if ((retval = get_user(dev->rep[0], ((int *) arg) + 0))) return retval;
+			if ((retval = get_user(dev->rep[1], ((int *) arg) + 1))) return retval;
+			return 0;
+
+		case EVIOCGKEYCODE:
+			if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
+			if (t < 0 || t > dev->keycodemax) return -EINVAL;
+			switch (dev->keycodesize) {
+				case 1: u = *(u8*)(dev->keycode + t); break;
+				case 2: u = *(u16*)(dev->keycode + t * 2); break;
+				case 4: u = *(u32*)(dev->keycode + t * 4); break;
+				default: return -EINVAL;
+			}
+			if ((retval = put_user(u, ((int *) arg) + 1))) return retval;
+			return 0;
+
+		case EVIOCSKEYCODE:
+			if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
+			if (t < 0 || t > dev->keycodemax) return -EINVAL;
+			if ((retval = get_user(u, ((int *) arg) + 1))) return retval;
+			switch (dev->keycodesize) {
+				case 1: *(u8*)(dev->keycode + t) = u; break;
+				case 2: *(u16*)(dev->keycode + t * 2) = u; break;
+				case 4: *(u32*)(dev->keycode + t * 4) = u; break;
+				default: return -EINVAL;
+			}
+			return 0;
 
 		case EVIOCSFF:
 			if (dev->upload_effect) {
@@ -280,22 +325,55 @@
 					default: return -EINVAL;
 				}
 				len = NBITS(len) * sizeof(long);
-				if (len > _IOC_SIZE(cmd)) {
-					printk(KERN_WARNING "evdev.c: Truncating bitfield length from %d to %d\n",
-						len, _IOC_SIZE(cmd));
-					len = _IOC_SIZE(cmd);
-				}
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
 				return copy_to_user((char *) arg, bits, len) ? -EFAULT : len;
 			}
 
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
+				int len;
+				len = NBITS(KEY_MAX) * sizeof(long);
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->key, len) ? -EFAULT : len;
+			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
+				int len;
+				len = NBITS(LED_MAX) * sizeof(long);
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->led, len) ? -EFAULT : len;
+			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
+				int len;
+				len = NBITS(SND_MAX) * sizeof(long);
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->snd, len) ? -EFAULT : len;
+			}
+
 			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
 				int len;
-				if (!dev->name) return 0;
+				if (!dev->name) return -ENOENT;
 				len = strlen(dev->name) + 1;
 				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
 				return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len;
 			}
 
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
+				int len;
+				if (!dev->phys) return -ENOENT;
+				len = strlen(dev->phys) + 1;
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->phys, len) ? -EFAULT : len;
+			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
+				int len;
+				if (!dev->uniq) return -ENOENT;
+				len = strlen(dev->uniq) + 1;
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->uniq, len) ? -EFAULT : len;
+			}
+
 			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
 				int t = _IOC_NR(cmd) & ABS_MAX;
@@ -321,9 +399,10 @@
 	release:	evdev_release,
 	ioctl:		evdev_ioctl,
 	fasync:		evdev_fasync,
+	flush:		evdev_flush
 };
 
-static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct evdev *evdev;
 	int minor;
@@ -342,16 +421,17 @@
 
 	evdev->minor = minor;
 	evdev_table[minor] = evdev;
+	
+	sprintf(evdev->name, "event%d", minor);
 
 	evdev->handle.dev = dev;
+	evdev->handle.name = evdev->name;
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
 
-	evdev->exist = 1;
-
 	evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
 
-//	printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
+	evdev->exist = 1;
 
 	return &evdev->handle;
 }
@@ -372,12 +452,21 @@
 	}
 }
 
+static struct input_device_id evdev_ids[] = {
+	{ driver_info: 1 },	/* Matches all devices */
+	{ },			/* Terminating zero entry */
+};
+
+MODULE_DEVICE_TABLE(input, evdev_ids);
+
 static struct input_handler evdev_handler = {
 	event:		evdev_event,
 	connect:	evdev_connect,
 	disconnect:	evdev_disconnect,
 	fops:		&evdev_fops,
 	minor:		EVDEV_MINOR_BASE,
+	name:		"evdev",
+	id_table:	evdev_ids,
 };
 
 static int __init evdev_init(void)
@@ -394,7 +483,6 @@
 module_init(evdev_init);
 module_exit(evdev_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Event character device driver");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input driver event char devices");
 MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/input/gameport/Config.help b/drivers/input/gameport/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/Config.help	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,62 @@
+CONFIG_GAMEPORT
+  Gameport support is for the standard 15-pin PC gameport. If you
+  have a joystick, gamepad, gameport card, a soundcard with a gameport
+  or anything else that uses the gameport, say Y or M here and also to
+  at least one of the hardware specific drivers.
+
+  For Ensoniq AudioPCI (ES1370), AudioPCI 97 (ES1371), ESS Solo1,
+  S3 SonicVibes, Trident 4DWave, SiS7018, and ALi 5451 gameport
+  support is provided by the sound drivers, so you won't need any
+  from the below listed modules. You still need to say Y here.
+
+  If unsure, say Y.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called gameport.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_GAMEPORT_NS558
+  Say Y here if you have an ISA or PnP gameport.
+
+  If unsure, say Y.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ns558.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_GAMEPORT_L4
+  Say Y here if you have a PDPI Lightning 4 gamecard.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called lightning.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_GAMEPORT_EMU10K1
+  Say Y here if you have a SoundBlaster Live! or SoundBlaster
+  Audigy card and want to use its gameport.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called emu10k1-gp.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_GAMEPORT_PCIGAME
+  Say Y here if you have an Aureal Vortex 1 or 2 or a Trident
+  4DWave NX or DX card and want to use its gameport.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called pcigame.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_GAMEPORT_CS461X
+  Say Y here if you have a Cirrus CS461x aka "Crystal SoundFusion"
+  PCI audio accelerator and want to use its gameport.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called cs461x.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/input/gameport/Config.in b/drivers/input/gameport/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/Config.in	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,19 @@
+#
+# Gameport configuration
+#
+
+tristate 'Gameport support' CONFIG_GAMEPORT
+
+if [ "$CONFIG_GAMEPORT" = "m" ]; then
+	define_tristate CONFIG_SOUND_GAMEPORT m
+fi
+if [ "$CONFIG_GAMEPORT" != "m" ]; then
+	define_tristate CONFIG_SOUND_GAMEPORT y
+fi
+
+dep_tristate '  Classic ISA and PnP gameport support' CONFIG_GAMEPORT_NS558 $CONFIG_GAMEPORT
+dep_tristate '  PDPI Lightning 4 gamecard support' CONFIG_GAMEPORT_L4 $CONFIG_GAMEPORT
+dep_tristate '  SB Live and Audigy gameport support' CONFIG_INPUT_EMU10K1 $CONFIG_GAMEPORT
+dep_tristate '  Aureal Vortex, Vortex 2 and Trident 4DWave NX/DX gameport support' CONFIG_GAMEPORT_PCIGAME $CONFIG_GAMEPORT
+dep_tristate '  ForteMedia FM801 gameport support' CONFIG_GAMEPORT_FM801 $CONFIG_GAMEPORT
+dep_tristate '  Crystal SoundFusion gameport support' CONFIG_GAMEPORT_CS461x $CONFIG_GAMEPORT
diff -Nru a/drivers/input/gameport/Makefile b/drivers/input/gameport/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/Makefile	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,24 @@
+#
+# Makefile for the gameport drivers.
+#
+
+# The target object and module list name.
+
+O_TARGET	:= gamedrv.o
+
+# Objects that export symbols.
+
+export-objs	:= gameport.o
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_GAMEPORT)		+= gameport.o
+obj-$(CONFIG_GAMEPORT_CS461X)	+= cs461x.o
+obj-$(CONFIG_GAMEPORT_EMU10K1)	+= emu10k1-gp.o
+obj-$(CONFIG_GAMEPORT_L4)	+= lightning.o
+obj-$(CONFIG_GAMEPORT_NS558)	+= ns558.o
+obj-$(CONFIG_GAMEPORT_PCIGAME)	+= pcigame.o
+
+# The global Rules.make.
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/cs461x.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,331 @@
+/*
+	The all defines and part of code (such as cs461x_*) are 
+	contributed from ALSA 0.5.8 sources. 
+	See http://www.alsa-project.org/ for sources
+	
+	Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610
+*/
+
+#include <asm/io.h>
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+
+MODULE_AUTHOR("Victor Krapivin <vik@belcaf.minsk.by>");
+MODULE_LICENSE("GPL");
+
+/*
+	These options are experimental
+
+#define CS461X_FULL_MAP
+*/
+
+#define COOKED_MODE
+
+
+#ifndef PCI_VENDOR_ID_CIRRUS
+#define PCI_VENDOR_ID_CIRRUS            0x1013
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_4610
+#define PCI_DEVICE_ID_CIRRUS_4610       0x6001
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_4612
+#define PCI_DEVICE_ID_CIRRUS_4612       0x6003
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_4615
+#define PCI_DEVICE_ID_CIRRUS_4615       0x6004
+#endif
+
+/* Registers */
+
+#define BA0_JSPT                                0x00000480
+#define BA0_JSCTL                               0x00000484
+#define BA0_JSC1                                0x00000488
+#define BA0_JSC2                                0x0000048C
+#define BA0_JSIO                                0x000004A0
+
+/* Bits for JSPT */
+
+#define JSPT_CAX                                0x00000001
+#define JSPT_CAY                                0x00000002
+#define JSPT_CBX                                0x00000004
+#define JSPT_CBY                                0x00000008
+#define JSPT_BA1                                0x00000010
+#define JSPT_BA2                                0x00000020
+#define JSPT_BB1                                0x00000040
+#define JSPT_BB2                                0x00000080
+
+/* Bits for JSCTL */
+
+#define JSCTL_SP_MASK                           0x00000003
+#define JSCTL_SP_SLOW                           0x00000000
+#define JSCTL_SP_MEDIUM_SLOW                    0x00000001
+#define JSCTL_SP_MEDIUM_FAST                    0x00000002
+#define JSCTL_SP_FAST                           0x00000003
+#define JSCTL_ARE                               0x00000004
+
+/* Data register pairs masks */
+
+#define JSC1_Y1V_MASK                           0x0000FFFF
+#define JSC1_X1V_MASK                           0xFFFF0000
+#define JSC1_Y1V_SHIFT                          0
+#define JSC1_X1V_SHIFT                          16
+#define JSC2_Y2V_MASK                           0x0000FFFF
+#define JSC2_X2V_MASK                           0xFFFF0000
+#define JSC2_Y2V_SHIFT                          0
+#define JSC2_X2V_SHIFT                          16
+
+/* JS GPIO */
+
+#define JSIO_DAX                                0x00000001
+#define JSIO_DAY                                0x00000002
+#define JSIO_DBX                                0x00000004
+#define JSIO_DBY                                0x00000008
+#define JSIO_AXOE                               0x00000010
+#define JSIO_AYOE                               0x00000020
+#define JSIO_BXOE                               0x00000040
+#define JSIO_BYOE                               0x00000080
+
+/* 
+   The card initialization code is obfuscated; the module cs461x 
+   need to be loaded after ALSA modules initialized and something
+   played on the CS 4610 chip (see sources for details of CS4610
+   initialization code from ALSA)
+*/
+
+/* Card specific definitions */
+
+#define CS461X_BA0_SIZE         0x2000
+#define CS461X_BA1_DATA0_SIZE   0x3000
+#define CS461X_BA1_DATA1_SIZE   0x3800
+#define CS461X_BA1_PRG_SIZE     0x7000
+#define CS461X_BA1_REG_SIZE     0x0100
+
+#define BA1_SP_DMEM0                            0x00000000
+#define BA1_SP_DMEM1                            0x00010000
+#define BA1_SP_PMEM                             0x00020000
+#define BA1_SP_REG                              0x00030000
+
+#define BA1_DWORD_SIZE          (13 * 1024 + 512)
+#define BA1_MEMORY_COUNT        3
+
+/* 
+   Only one CS461x card is still suppoted; the code requires
+   redesign to avoid this limitatuion.
+*/
+
+static unsigned long ba0_addr;
+static unsigned int *ba0;
+
+#ifdef CS461X_FULL_MAP
+static unsigned long ba1_addr;
+static union ba1_t {
+        struct {
+                unsigned int *data0;
+                unsigned int *data1;
+                unsigned int *pmem;
+                unsigned int *reg;
+        } name;
+        unsigned int *idx[4];
+} ba1;
+
+static void cs461x_poke(unsigned long reg, unsigned int val)
+{
+        ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff] = val;
+}
+
+static unsigned int cs461x_peek(unsigned long reg)
+{
+        return ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff];
+}
+
+#endif
+
+static void cs461x_pokeBA0(unsigned long reg, unsigned int val)
+{
+        ba0[reg >> 2] = val;
+}
+
+static unsigned int cs461x_peekBA0(unsigned long reg)
+{
+        return ba0[reg >> 2];
+}
+
+static int cs461x_free(struct pci_dev *pdev)
+{
+	struct gameport *port = pci_get_drvdata(pdev);
+	if(port){
+	    gameport_unregister_port(port);
+	    kfree(port);
+	}    
+	if (ba0) iounmap(ba0);
+#ifdef CS461X_FULL_MAP
+	if (ba1.name.data0) iounmap(ba1.name.data0);
+	if (ba1.name.data1) iounmap(ba1.name.data1);
+	if (ba1.name.pmem)  iounmap(ba1.name.pmem);
+	if (ba1.name.reg)   iounmap(ba1.name.reg);
+#endif
+	return 0;
+}
+
+static void cs461x_gameport_trigger(struct gameport *gameport)
+{
+	cs461x_pokeBA0(BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
+}
+
+static unsigned char cs461x_gameport_read(struct gameport *gameport)
+{
+	return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io);
+}
+
+static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+	unsigned js1, js2, jst;
+	
+	js1 = cs461x_peekBA0(BA0_JSC1);
+	js2 = cs461x_peekBA0(BA0_JSC2);
+	jst = cs461x_peekBA0(BA0_JSPT);
+	
+	*buttons = (~jst >> 4) & 0x0F; 
+	
+	axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
+	axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
+	axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
+	axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
+
+	for(jst=0;jst<4;++jst)
+		if(axes[jst]==0xFFFF) axes[jst] = -1;
+	return 0;
+}
+
+static int cs461x_gameport_open(struct gameport *gameport, int mode)
+{
+	switch (mode) {
+#ifdef COOKED_MODE
+	case GAMEPORT_MODE_COOKED:
+		return 0;
+#endif
+	case GAMEPORT_MODE_RAW:
+		return 0;
+	default:
+		return -1;
+	}
+	return 0;
+}
+
+static struct pci_device_id cs461x_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */
+	{ PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */
+	{ PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl);
+
+static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+	struct gameport* port;
+	
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n",
+			pdev->bus->number, pdev->devfn, rc);
+		return rc;
+	}
+
+	ba0_addr = pci_resource_start(pdev, 0);
+#ifdef CS461X_FULL_MAP
+	ba1_addr = pci_resource_start(pdev, 1);
+#endif
+	if (ba0_addr == 0 || ba0_addr == ~0 
+#ifdef CS461X_FULL_MAP
+            || ba1_addr == 0 || ba1_addr == ~0
+#endif
+	    ) {
+                printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr);
+#ifdef CS461X_FULL_MAP
+                printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr);
+#endif
+		cs461x_free(pdev);
+                return -ENOMEM;
+        }
+
+	ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE);
+#ifdef CS461X_FULL_MAP
+	ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
+	ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
+	ba1.name.pmem  = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
+	ba1.name.reg   = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
+
+	if (ba0 == NULL || ba1.name.data0 == NULL ||
+            ba1.name.data1 == NULL || ba1.name.pmem == NULL ||
+            ba1.name.reg == NULL) {
+		cs461x_free(pdev);
+                return -ENOMEM;
+        }
+#else
+	if (ba0 == NULL){
+		cs461x_free(pdev);
+		return -ENOMEM;
+	}
+#endif
+	printk(KERN_INFO "CS461x PCI: %lx[%d]\n",
+	    ba0_addr, CS461X_BA0_SIZE);
+        
+	if (!(port = kmalloc(sizeof(struct gameport), GFP_KERNEL))) {
+		printk(KERN_ERR "Memory allocation failed.\n");
+		cs461x_free(pdev);
+		return -ENOMEM;
+	}
+	memset(port, 0, sizeof(struct gameport));
+
+	pci_set_drvdata(pdev, port);
+	
+	port->open = cs461x_gameport_open;
+	port->read = cs461x_gameport_read;
+	port->trigger = cs461x_gameport_trigger;
+#ifdef COOKED_MODE
+	port->cooked_read = cs461x_gameport_cooked_read;
+#endif
+
+	cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
+	cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
+
+	gameport_register_port(port);
+
+	printk(KERN_INFO "gameport%d: CS461x Gameport speed %d kHz\n",
+		port->number, port->speed);
+
+	return 0;
+}
+
+static void __devexit cs461x_pci_remove(struct pci_dev *pdev)
+{
+	cs461x_free(pdev);
+}
+	
+static struct pci_driver cs461x_pci_driver = {
+        name:           "PCI Gameport",
+        id_table:       cs461x_pci_tbl,
+        probe:          cs461x_pci_probe,
+        remove:         cs461x_pci_remove,
+};
+
+int __init js_cs461x_init(void)
+{
+        return pci_module_init(&cs461x_pci_driver);
+}
+
+void __exit js_cs461x_exit(void)
+{
+        pci_unregister_driver(&cs461x_pci_driver);
+}
+
+module_init(js_cs461x_init);
+module_exit(js_cs461x_exit);
+
diff -Nru a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/emu10k1-gp.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,125 @@
+/*
+ * $Id: emu10k1-gp.c,v 1.2 2001/04/24 07:48:56 vojtech Exp $
+ *
+ *  Copyright (c) 2001 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * EMU10k1 - SB Live! - gameport driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/io.h>
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_LICENSE("GPL");
+
+struct emu {
+	struct pci_dev *dev;
+	struct emu *next;
+	struct gameport gameport;
+	int size;
+};
+	
+static struct pci_device_id emu_tbl[] __devinitdata = {
+	{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live! gameport */
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, emu_tbl);
+
+static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int ioport, iolen;
+	int rc;
+	struct emu *port;
+        
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		printk(KERN_ERR "emu10k1-gp: Cannot enable emu10k1 gameport (bus %d, devfn %d) error=%d\n",
+			pdev->bus->number, pdev->devfn, rc);
+		return rc;
+	}
+
+	ioport = pci_resource_start(pdev, 0);
+	iolen = pci_resource_len(pdev, 0);
+
+	if (!request_region(ioport, iolen, "emu10k1-gp"))
+		return -EBUSY;
+
+	if (!(port = kmalloc(sizeof(struct emu), GFP_KERNEL))) {
+		printk(KERN_ERR "emu10k1-gp: Memory allocation failed.\n");
+		release_region(ioport, iolen);
+		return -ENOMEM;
+	}
+	memset(port, 0, sizeof(struct emu));
+
+	port->gameport.io = ioport;
+	port->size = iolen;
+	port->dev = pdev;
+	pci_set_drvdata(pdev, port);
+
+	gameport_register_port(&port->gameport);
+
+	printk(KERN_INFO "gameport%d: Emu10k1 Gameport at %#x size %d speed %d kHz\n",
+		port->gameport.number, port->gameport.io, iolen, port->gameport.speed);
+
+	return 0;
+}
+
+static void __devexit emu_remove(struct pci_dev *pdev)
+{
+	struct emu *port = pci_get_drvdata(pdev);
+	gameport_unregister_port(&port->gameport);
+	release_region(port->gameport.io, port->size);
+	kfree(port);
+}
+
+static struct pci_driver emu_driver = {
+        name:           "Emu10k1 Gameport",
+        id_table:       emu_tbl,
+        probe:          emu_probe,
+        remove:         emu_remove,
+};
+
+int __init emu_init(void)
+{
+	return pci_module_init(&emu_driver);
+}
+
+void __exit emu_exit(void)
+{
+	pci_unregister_driver(&emu_driver);
+}
+
+module_init(emu_init);
+module_exit(emu_exit);
diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/gameport.c	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,199 @@
+/*
+ * $Id: gameport.c,v 1.5 2000/05/29 10:54:53 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Generic gameport layer
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/io.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/slab.h>
+#include <linux/isapnp.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(gameport_register_port);
+EXPORT_SYMBOL(gameport_unregister_port);
+EXPORT_SYMBOL(gameport_register_device);
+EXPORT_SYMBOL(gameport_unregister_device);
+EXPORT_SYMBOL(gameport_open);
+EXPORT_SYMBOL(gameport_close);
+EXPORT_SYMBOL(gameport_rescan);
+EXPORT_SYMBOL(gameport_cooked_read);
+
+static struct gameport *gameport_list;
+static struct gameport_dev *gameport_dev;
+static int gameport_number;
+
+/*
+ * gameport_measure_speed() measures the gameport i/o speed.
+ */
+
+static int gameport_measure_speed(struct gameport *gameport)
+{
+#if defined(__i386__) || defined(__x86_64__)
+
+#define GET_TIME(x)     do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
+#define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193180L/HZ:0))
+
+	unsigned int i, t, t1, t2, t3, tx;
+	unsigned long flags;
+
+	if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
+		return 0;
+
+	tx = 1 << 30;
+
+	for(i = 0; i < 50; i++) {
+		save_flags(flags);	/* Yes, all CPUs */
+		cli();
+		GET_TIME(t1);
+		for(t = 0; t < 50; t++) gameport_read(gameport);
+		GET_TIME(t2);
+		GET_TIME(t3);
+		restore_flags(flags);
+		udelay(i * 10);
+		if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
+	}
+
+	return 59659 / (tx < 1 ? 1 : tx);
+
+#else
+
+	unsigned int j, t = 0;
+
+	j = jiffies; while (j == jiffies);
+	j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
+
+	return t * HZ / 1000;
+
+#endif
+
+	gameport_close(gameport);
+}
+
+static void gameport_find_dev(struct gameport *gameport)
+{
+        struct gameport_dev *dev = gameport_dev;
+
+        while (dev && !gameport->dev) {
+		if (dev->connect)
+                	dev->connect(gameport, dev);
+                dev = dev->next;
+        }
+}
+
+void gameport_rescan(struct gameport *gameport)
+{
+	gameport_close(gameport);
+	gameport_find_dev(gameport);
+}
+
+void gameport_register_port(struct gameport *gameport)
+{
+	gameport->number = gameport_number++;
+	gameport->next = gameport_list;	
+	gameport_list = gameport;
+
+	gameport->speed = gameport_measure_speed(gameport);
+
+	gameport_find_dev(gameport);
+}
+
+void gameport_unregister_port(struct gameport *gameport)
+{
+        struct gameport **gameportptr = &gameport_list;
+
+        while (*gameportptr && (*gameportptr != gameport)) gameportptr = &((*gameportptr)->next);
+        *gameportptr = (*gameportptr)->next;
+
+	if (gameport->dev && gameport->dev->disconnect)
+		gameport->dev->disconnect(gameport);
+
+	gameport_number--;
+}
+
+void gameport_register_device(struct gameport_dev *dev)
+{
+	struct gameport *gameport = gameport_list;
+
+	dev->next = gameport_dev;	
+	gameport_dev = dev;
+
+	while (gameport) {
+		if (!gameport->dev && dev->connect)
+			dev->connect(gameport, dev);
+		gameport = gameport->next;
+	}
+}
+
+void gameport_unregister_device(struct gameport_dev *dev)
+{
+        struct gameport_dev **devptr = &gameport_dev;
+	struct gameport *gameport = gameport_list;
+
+        while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next);
+        *devptr = (*devptr)->next;
+
+	while (gameport) {
+		if (gameport->dev == dev && dev->disconnect)
+			dev->disconnect(gameport);
+		gameport_find_dev(gameport);
+		gameport = gameport->next;
+	}
+}
+
+int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
+{
+	if (gameport->open) {
+		if (gameport->open(gameport, mode))
+			return -1;
+	} else {
+		if (mode != GAMEPORT_MODE_RAW)
+			return -1;
+	}
+
+	if (gameport->dev)
+		return -1;
+
+	gameport->dev = dev;
+	
+	return 0;
+}
+
+void gameport_close(struct gameport *gameport)
+{
+	gameport->dev = NULL;
+	if (gameport->close) gameport->close(gameport);
+}
diff -Nru a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/lightning.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,298 @@
+/*
+ * $Id: lightning.c,v 1.13 2001/04/26 10:24:46 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2001 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * PDPI Lightning 4 gamecard driver for Linux.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/slab.h>
+
+#define L4_PORT			0x201
+#define L4_SELECT_ANALOG	0xa4
+#define L4_SELECT_DIGITAL	0xa5
+#define L4_SELECT_SECONDARY	0xa6
+#define L4_CMD_ID		0x80
+#define L4_CMD_GETCAL		0x92
+#define L4_CMD_SETCAL		0x93
+#define L4_ID			0x04
+#define L4_BUSY			0x01
+#define L4_TIMEOUT		80	/* 80 us */
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_LICENSE("GPL");
+
+struct l4 {
+	struct gameport gameport;
+	unsigned char port;
+} *l4_port[8];
+
+/*
+ * l4_wait_ready() waits for the L4 to become ready.
+ */
+
+static int l4_wait_ready(void)
+{
+	unsigned int t;
+	t = L4_TIMEOUT;
+	while ((inb(L4_PORT) & L4_BUSY) && t > 0) t--;
+	return -(t<=0);
+}
+
+/*
+ * l4_cooked_read() reads data from the Lightning 4.
+ */
+
+static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+	struct l4 *l4 = gameport->private;
+	unsigned char status;
+	int i, result = -1;
+
+	outb(L4_SELECT_ANALOG, L4_PORT);
+	outb(L4_SELECT_DIGITAL + (l4->port >> 2), L4_PORT);
+
+	if (inb(L4_PORT) & L4_BUSY) goto fail;
+	outb(l4->port & 3, L4_PORT);
+
+	if (l4_wait_ready()) goto fail;
+	status = inb(L4_PORT);
+
+	for (i = 0; i < 4; i++)
+		if (status & (1 << i)) {
+			if (l4_wait_ready()) goto fail;
+			axes[i] = inb(L4_PORT);
+			if (axes[i] > 252) axes[i] = -1;
+		}
+
+	if (status & 0x10) {
+		if (l4_wait_ready()) goto fail;
+		*buttons = inb(L4_PORT) & 0x0f;
+	}
+
+	result = 0;
+
+fail:	outb(L4_SELECT_ANALOG, L4_PORT);	
+	return result;
+}
+
+static int l4_open(struct gameport *gameport, int mode)
+{
+	struct l4 *l4 = gameport->private;
+        if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
+		return -1;
+	outb(L4_SELECT_ANALOG, L4_PORT);
+	return 0;
+}
+
+/*
+ * l4_getcal() reads the L4 with calibration values.
+ */
+
+static int l4_getcal(int port, int *cal)
+{
+	int i, result = -1;
+	
+	outb(L4_SELECT_ANALOG, L4_PORT);
+	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+
+	if (inb(L4_PORT) & L4_BUSY) goto fail;
+	outb(L4_CMD_GETCAL, L4_PORT);
+
+	if (l4_wait_ready()) goto fail;
+	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+
+	if (l4_wait_ready()) goto fail;
+        outb(port & 3, L4_PORT);
+
+	for (i = 0; i < 4; i++) {
+		if (l4_wait_ready()) goto fail;
+		cal[i] = inb(L4_PORT);
+	}
+
+	result = 0;
+
+fail:	outb(L4_SELECT_ANALOG, L4_PORT);
+	return result;
+}
+
+/*
+ * l4_setcal() programs the L4 with calibration values.
+ */
+
+static int l4_setcal(int port, int *cal)
+{
+	int i, result = -1;
+
+	outb(L4_SELECT_ANALOG, L4_PORT);
+	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+
+	if (inb(L4_PORT) & L4_BUSY) goto fail;
+	outb(L4_CMD_SETCAL, L4_PORT);
+
+	if (l4_wait_ready()) goto fail;
+	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+
+	if (l4_wait_ready()) goto fail;
+        outb(port & 3, L4_PORT);
+
+	for (i = 0; i < 4; i++) {
+		if (l4_wait_ready()) goto fail;
+		outb(cal[i], L4_PORT);
+	}
+
+	result = 0;
+
+fail:	outb(L4_SELECT_ANALOG, L4_PORT);
+	return result;
+}
+
+/*
+ * l4_calibrate() calibrates the L4 for the attached device, so
+ * that the device's resistance fits into the L4's 8-bit range.
+ */
+
+static int l4_calibrate(struct gameport *gameport, int *axes, int *max)
+{
+	int i, t;
+	int cal[4];
+	struct l4 *l4 = gameport->private;
+
+	if (l4_getcal(l4->port, cal))
+		return -1;
+
+	for (i = 0; i < 4; i++) {
+		t = (max[i] * cal[i]) / 200;
+		t = (t < 1) ? 1 : ((t > 255) ? 255 : t);
+		axes[i] = (axes[i] < 0) ? -1 : (axes[i] * cal[i]) / t;
+		axes[i] = (axes[i] > 252) ? 252 : axes[i];
+		cal[i] = t;
+	}
+
+	if (l4_setcal(l4->port, cal))
+		return -1;
+
+	return 0;
+}
+	
+int __init l4_init(void)
+{
+	int cal[4] = {255,255,255,255};
+	int i, j, rev, cards = 0;
+	struct gameport *gameport;
+	struct l4 *l4;
+
+	if (!request_region(L4_PORT, 1, "lightning"))
+		return -1;
+
+	for (i = 0; i < 2; i++) {
+
+		outb(L4_SELECT_ANALOG, L4_PORT);
+		outb(L4_SELECT_DIGITAL + i, L4_PORT);
+
+		if (inb(L4_PORT) & L4_BUSY) continue;
+		outb(L4_CMD_ID, L4_PORT);
+
+		if (l4_wait_ready()) continue;
+		if (inb(L4_PORT) != L4_SELECT_DIGITAL + i) continue;
+
+		if (l4_wait_ready()) continue;
+		if (inb(L4_PORT) != L4_ID) continue;
+
+		if (l4_wait_ready()) continue;
+		rev = inb(L4_PORT);
+
+		if (!rev) continue;
+
+		if (!(l4_port[i * 4] = kmalloc(sizeof(struct l4) * 4, GFP_KERNEL))) {
+			printk(KERN_ERR "lightning: Out of memory allocating ports.\n");
+			continue;
+		}
+		memset(l4_port[i * 4], 0, sizeof(struct l4) * 4);
+
+		for (j = 0; j < 4; j++) {
+
+			l4 = l4_port[i * 4 + j] = l4_port[i * 4] + j;
+			l4->port = i * 4 + j;
+
+			gameport = &l4->gameport;
+			gameport->private = l4;
+			gameport->open = l4_open;
+			gameport->cooked_read = l4_cooked_read;
+			gameport->calibrate = l4_calibrate;
+
+			if (!i && !j)
+				gameport->io = L4_PORT;
+
+			if (rev > 0x28)		/* on 2.9+ the setcal command works correctly */
+				l4_setcal(l4->port, cal);
+			
+			gameport_register_port(gameport);
+		}
+
+		printk(KERN_INFO "gameport%d,%d,%d,%d: PDPI Lightning 4 %s card v%d.%d at %#x\n",
+			l4_port[i * 4 + 0]->gameport.number, l4_port[i * 4 + 1]->gameport.number, 
+			l4_port[i * 4 + 2]->gameport.number, l4_port[i * 4 + 3]->gameport.number, 
+			i ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
+
+		cards++;
+	}
+
+	outb(L4_SELECT_ANALOG, L4_PORT);
+
+	if (!cards) {
+		release_region(L4_PORT, 1);
+		return -1;
+	}
+
+	return 0;
+}
+
+void __init l4_exit(void)
+{
+	int i;
+	int cal[4] = {59, 59, 59, 59};
+
+	for (i = 0; i < 8; i++)
+		if (l4_port[i]) {
+			l4_setcal(l4_port[i]->port, cal);
+			gameport_unregister_port(&l4_port[i]->gameport);
+		}
+	outb(L4_SELECT_ANALOG, L4_PORT);
+	release_region(L4_PORT, 1);
+}
+
+module_init(l4_init);
+module_exit(l4_exit);
diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/ns558.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,285 @@
+/*
+ * $Id: ns558.c,v 1.29 2001/04/24 07:48:56 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *  Copyright (c) 1999 Brian Gerst
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * NS558 based standard IBM game port driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/io.h>
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/slab.h>
+#include <linux/isapnp.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_LICENSE("GPL");
+
+#define NS558_ISA	1
+#define NS558_PNP	2
+
+static int ns558_isa_portlist[] = { 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209,
+				    0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 };
+
+struct ns558 {
+	int type;
+	int size;
+	struct pci_dev *dev;
+	struct ns558 *next;
+	struct gameport gameport;
+};
+	
+static struct ns558 *ns558;
+
+/*
+ * ns558_isa_probe() tries to find an isa gameport at the
+ * specified address, and also checks for mirrors.
+ * A joystick must be attached for this to work.
+ */
+
+static struct ns558* ns558_isa_probe(int io, struct ns558 *next)
+{
+	int i, j, b;
+	unsigned char c, u, v;
+	struct ns558 *port;
+
+/*
+ * No one should be using this address.
+ */
+
+	if (check_region(io, 1))
+		return next;
+
+/*
+ * We must not be able to write arbitrary values to the port.
+ * The lower two axis bits must be 1 after a write.
+ */
+
+	c = inb(io);
+	outb(~c & ~3, io);
+	if (~(u = v = inb(io)) & 3) {
+		outb(c, io);
+		return next;
+	}
+/*
+ * After a trigger, there must be at least some bits changing.
+ */
+
+	for (i = 0; i < 1000; i++) v &= inb(io);
+
+	if (u == v) {
+		outb(c, io);
+		return next;
+	}
+	wait_ms(3);
+/*
+ * After some time (4ms) the axes shouldn't change anymore.
+ */
+
+	u = inb(io);
+	for (i = 0; i < 1000; i++)
+		if ((u ^ inb(io)) & 0xf) {
+			outb(c, io);
+			return next;
+		}
+/* 
+ * And now find the number of mirrors of the port.
+ */
+
+	for (i = 1; i < 5; i++) {
+
+		if (check_region(io & (-1 << i), (1 << i)))	/* Don't disturb anyone */
+			break;
+
+		outb(0xff, io & (-1 << i));
+		for (j = b = 0; j < 1000; j++)
+			if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++;
+		wait_ms(3);
+
+		if (b > 300)					/* We allow 30% difference */
+			break;
+	}
+
+	i--;
+
+	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
+		printk(KERN_ERR "ns558: Memory allocation failed.\n");
+		return next;
+	}
+       	memset(port, 0, sizeof(struct ns558));
+	
+	port->next = next;
+	port->type = NS558_ISA;
+	port->size = (1 << i);
+	port->gameport.io = io & (-1 << i);
+
+	request_region(port->gameport.io, (1 << i), "ns558-isa");
+
+	gameport_register_port(&port->gameport);
+
+	printk(KERN_INFO "gameport%d: NS558 ISA at %#x", port->gameport.number, port->gameport.io);
+	if (port->size > 1) printk(" size %d", port->size);
+	printk(" speed %d kHz\n", port->gameport.speed);
+
+	return port;
+}
+
+#ifdef __ISAPNP__
+
+static struct isapnp_device_id pnp_devids[] = {
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x0001), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x2001), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7001), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7002), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0b35), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P','N','P'), ISAPNP_DEVICE(0xb02f), 0 },
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(isapnp, pnp_devids);
+
+static struct ns558* ns558_pnp_probe(struct pci_dev *dev, struct ns558 *next)
+{
+	int ioport, iolen;
+	struct ns558 *port;
+
+	if (dev->prepare && dev->prepare(dev) < 0)
+		return next;
+
+	if (!(dev->resource[0].flags & IORESOURCE_IO)) {
+		printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n");
+		return next;
+	}
+
+	if (dev->activate && dev->activate(dev) < 0) {
+		printk(KERN_ERR "ns558: PnP resource allocation failed\n");
+		return next;
+	}
+	
+	ioport = pci_resource_start(dev, 0);
+	iolen = pci_resource_len(dev, 0);
+
+	if (!request_region(ioport, iolen, "ns558-pnp"))
+		goto deactivate;
+
+	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
+		printk(KERN_ERR "ns558: Memory allocation failed.\n");
+		goto deactivate;
+	}
+	memset(port, 0, sizeof(struct ns558));
+
+	port->next = next;
+	port->type = NS558_PNP;
+	port->gameport.io = ioport;
+	port->size = iolen;
+	port->dev = dev;
+
+	gameport_register_port(&port->gameport);
+
+	printk(KERN_INFO "gameport%d: NS558 PnP at %#x", port->gameport.number, port->gameport.io);
+	if (iolen > 1) printk(" size %d", iolen);
+	printk(" speed %d kHz\n", port->gameport.speed);
+
+	return port;
+
+deactivate:
+	if (dev->deactivate)
+		dev->deactivate(dev);
+	return next;
+}
+#endif
+
+int __init ns558_init(void)
+{
+	int i = 0;
+#ifdef __ISAPNP__
+	struct isapnp_device_id *devid;
+	struct pci_dev *dev = NULL;
+#endif
+
+/*
+ * Probe for ISA ports.
+ */
+
+	while (ns558_isa_portlist[i]) 
+		ns558 = ns558_isa_probe(ns558_isa_portlist[i++], ns558);
+
+/*
+ * Probe for PnP ports.
+ */
+
+#ifdef __ISAPNP__
+	for (devid = pnp_devids; devid->vendor; devid++) {
+		while ((dev = isapnp_find_dev(NULL, devid->vendor, devid->function, dev))) {
+			ns558 = ns558_pnp_probe(dev, ns558);
+		}
+	}
+#endif
+
+	return ns558 ? 0 : -ENODEV;
+}
+
+void __exit ns558_exit(void)
+{
+	struct ns558 *next, *port = ns558;
+
+	while (port) {
+		gameport_unregister_port(&port->gameport);
+		switch (port->type) {
+
+#ifdef __ISAPNP__
+			case NS558_PNP:
+				if (port->dev->deactivate)
+					port->dev->deactivate(port->dev);
+				/* fall through */
+#endif
+
+			case NS558_ISA:
+				release_region(port->gameport.io, port->size);
+				break;
+		
+			default:
+				break;
+		}
+		
+		next = port->next;
+		kfree(port);
+		port = next;
+	}
+}
+
+module_init(ns558_init);
+module_exit(ns558_exit);
diff -Nru a/drivers/input/gameport/pcigame.c b/drivers/input/gameport/pcigame.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/gameport/pcigame.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,199 @@
+/*
+ * $Id: pcigame.c,v 1.10 2001/04/26 10:24:46 vojtech Exp $
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *	Raymond Ingles
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Trident 4DWave and Aureal Vortex gameport driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gameport.h>
+
+#define PCI_VENDOR_ID_AUREAL	0x12eb
+
+#define PCIGAME_DATA_WAIT	20	/* 20 ms */
+
+#define PCIGAME_4DWAVE		0
+#define PCIGAME_VORTEX		1
+#define PCIGAME_VORTEX2		2
+
+struct pcigame_data {
+	int gcr;	/* Gameport control register */
+	int legacy;	/* Legacy port location */
+	int axes;	/* Axes start */
+	int axsize;	/* Axis field size */
+	int axmax;	/* Axis field max value */
+	int adcmode;	/* Value to enable ADC mode in GCR */
+};
+
+static struct pcigame_data pcigame_data[] __devinitdata =
+{{ 0x00030, 0x00031, 0x00034, 2, 0xffff, 0x80 },
+ { 0x1100c, 0x11008, 0x11010, 4, 0x1fff, 0x40 },
+ { 0x2880c, 0x28808, 0x28810, 4, 0x1fff, 0x40 },
+ { 0 }};
+
+struct pcigame {
+	struct gameport gameport;
+	struct pci_dev *dev;
+        unsigned char *base;
+	struct pcigame_data *data;
+};
+
+static unsigned char pcigame_read(struct gameport *gameport)
+{
+	struct pcigame *pcigame = gameport->private;
+	return readb(pcigame->base + pcigame->data->legacy);
+}
+
+static void pcigame_trigger(struct gameport *gameport)
+{
+	struct pcigame *pcigame = gameport->private;
+	writeb(0xff, pcigame->base + pcigame->data->legacy);
+}
+
+static int pcigame_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+        struct pcigame *pcigame = gameport->private;
+	int i;
+
+	*buttons = (~readb(pcigame->base + pcigame->data->legacy) >> 4) & 0xf;
+
+	for (i = 0; i < 4; i++) {
+		axes[i] = readw(pcigame->base + pcigame->data->axes + i * pcigame->data->axsize);
+		if (axes[i] == pcigame->data->axmax) axes[i] = -1;
+	}
+        
+        return 0;
+}
+
+static int pcigame_open(struct gameport *gameport, int mode)
+{
+	struct pcigame *pcigame = gameport->private;
+
+	switch (mode) {
+		case GAMEPORT_MODE_COOKED:
+			writeb(pcigame->data->adcmode, pcigame->base + pcigame->data->gcr);
+			wait_ms(PCIGAME_DATA_WAIT);
+			return 0;
+		case GAMEPORT_MODE_RAW:
+			writeb(0, pcigame->base + pcigame->data->gcr);
+			return 0;
+		default:
+			return -1;
+	}
+
+	return 0;
+}
+
+static int __devinit pcigame_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct pcigame *pcigame;
+	int i;
+
+	if (!(pcigame = kmalloc(sizeof(struct pcigame), GFP_KERNEL)))
+		return -1;
+        memset(pcigame, 0, sizeof(struct pcigame));
+
+
+	pcigame->data = pcigame_data + id->driver_data;
+
+	pcigame->dev = dev;
+	pci_set_drvdata(dev, pcigame);
+
+	pcigame->gameport.private = pcigame;
+	pcigame->gameport.fuzz = 64;
+	
+	pcigame->gameport.read = pcigame_read;
+	pcigame->gameport.trigger = pcigame_trigger;
+	pcigame->gameport.cooked_read = pcigame_cooked_read;
+	pcigame->gameport.open = pcigame_open;
+
+	for (i = 0; i < 6; i++)
+		if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
+			break;
+
+	pci_enable_device(dev);
+
+	pcigame->base = ioremap(pci_resource_start(pcigame->dev, i),
+				pci_resource_len(pcigame->dev, i));
+
+	gameport_register_port(&pcigame->gameport);
+	
+	printk(KERN_INFO "gameport%d: %s at pci%02x:%02x.%x speed %d kHz\n",
+		pcigame->gameport.number, dev->name, dev->bus->number,
+			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), pcigame->gameport.speed);
+
+	return 0;
+}
+
+static void __devexit pcigame_remove(struct pci_dev *dev)
+{
+	struct pcigame *pcigame = pci_get_drvdata(dev);
+	gameport_unregister_port(&pcigame->gameport);
+	iounmap(pcigame->base);
+	kfree(pcigame);
+}
+
+static struct pci_device_id pcigame_id_table[] __devinitdata =
+{{ PCI_VENDOR_ID_TRIDENT, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_4DWAVE  },
+ { PCI_VENDOR_ID_TRIDENT, 0x2001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_4DWAVE  },
+ { PCI_VENDOR_ID_AUREAL,  0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_VORTEX  },
+ { PCI_VENDOR_ID_AUREAL,  0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_VORTEX2 },
+ { 0 }};
+
+static struct pci_driver pcigame_driver = {
+	name:		"pcigame",
+	id_table:	pcigame_id_table,
+	probe:		pcigame_probe,
+	remove:		pcigame_remove,
+};
+
+int __init pcigame_init(void)
+{
+	return pci_module_init(&pcigame_driver);
+}
+
+void __exit pcigame_exit(void)
+{
+	pci_unregister_driver(&pcigame_driver);
+}
+
+module_init(pcigame_init);
+module_exit(pcigame_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/input.c b/drivers/input/input.c
--- a/drivers/input/input.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/input/input.c	Sun Feb 10 19:58:03 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: input.c,v 1.20 2001/05/17 15:50:27 vojtech Exp $
+ * $Id: input.c,v 1.48 2001/12/26 21:08:33 jsimmons Exp $
  *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  The input layer module itself
- *
- *  Sponsored by SuSE
+ *  The input core
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <linux/init.h>
@@ -34,12 +32,16 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/random.h>
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input layer module");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
-
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
@@ -48,6 +50,8 @@
 EXPORT_SYMBOL(input_unregister_minor);
 EXPORT_SYMBOL(input_open_device);
 EXPORT_SYMBOL(input_close_device);
+EXPORT_SYMBOL(input_accept_process);
+EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
 
 #define INPUT_MAJOR	13
@@ -60,17 +64,31 @@
 static int input_number;
 static long input_devices[NBITS(INPUT_DEVICES)];
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_bus_input_dir;
+DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static int input_devices_state;
+#endif
+
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	struct input_handle *handle = dev->handle;
 
 /*
+ * Wake up the device if it is sleeping.
+ */
+	if (dev->pm_dev)
+		pm_access(dev->pm_dev);
+
+/*
  * Filter non-events, and bad input values out.
  */
 
 	if (type > EV_MAX || !test_bit(type, dev->evbit))
 		return;
 
+	add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
+
 	switch (type) {
 
 		case EV_KEY:
@@ -130,6 +148,8 @@
 
 			if (code > MSC_MAX || !test_bit(code, dev->mscbit))
 				return;
+
+			if (dev->event) dev->event(dev, type, code, value);	
 	
 			break;
 
@@ -185,16 +205,36 @@
 	mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
 }
 
+int input_accept_process(struct input_handle *handle, struct file *file)
+{
+	if (handle->dev->accept)
+		return handle->dev->accept(handle->dev, file);
+
+	return 0;
+}
+
 int input_open_device(struct input_handle *handle)
 {
+	if (handle->dev->pm_dev)
+		pm_access(handle->dev->pm_dev);
 	handle->open++;
 	if (handle->dev->open)
 		return handle->dev->open(handle->dev);
 	return 0;
 }
 
+int input_flush_device(struct input_handle* handle, struct file* file)
+{
+	if (handle->dev->flush)
+		return handle->dev->flush(handle->dev, file);
+
+	return 0;
+}
+
 void input_close_device(struct input_handle *handle)
 {
+	if (handle->dev->pm_dev)
+		pm_dev_idle(handle->dev->pm_dev);
 	if (handle->dev->close)
 		handle->dev->close(handle->dev);
 	handle->open--;
@@ -208,25 +248,197 @@
 	handle->handler->handle = handle;
 }
 
+/**
+ *     input_find_and_remove - Find and remove node
+ *
+ *     @type:          data type
+ *     @initval:       initial value
+ *     @targ:          node to find
+ *     @next:          next node in the list
+ *
+ *     Searches the linked list for the target node @targ. If the node
+ *     is found, it is removed from the list.
+ *
+ *     If the node is not found, the end of the list will be hit,
+ *     indicating that it wasn't in the list to begin with.
+ *
+ *     Returns nothing.
+ */
+#define input_find_and_remove(type, initval, targ, next)		\
+	do {								\
+		type **ptr;						\
+		for (ptr = &initval; *ptr; ptr = &((*ptr)->next))	\
+			if (*ptr == targ) break;			\
+		if (*ptr) *ptr = (*ptr)->next;				\
+	} while (0)
+
 static void input_unlink_handle(struct input_handle *handle)
 {
-	struct input_handle **handleptr;
+	input_find_and_remove(struct input_handle, handle->dev->handle, handle, dnext);
+        input_find_and_remove(struct input_handle, handle->handler->handle, handle, hnext);
+}
+
+#define MATCH_BIT(bit, max) \
+		for (i = 0; i < NBITS(max); i++) \
+			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
+				break; \
+		if (i != NBITS(max)) \
+			continue;
+
+static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
+{
+	int i;
+
+	for (; id->flags || id->driver_info; id++) {
+
+		if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+			if (id->idbus != dev->idbus)
+				continue;
 
-	handleptr = &handle->dev->handle;
-	while (*handleptr && (*handleptr != handle))
-		handleptr = &((*handleptr)->dnext);
-	*handleptr = (*handleptr)->dnext;
-
-	handleptr = &handle->handler->handle;
-	while (*handleptr && (*handleptr != handle))
-		handleptr = &((*handleptr)->hnext);
-	*handleptr = (*handleptr)->hnext;
+		if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
+			if (id->idvendor != dev->idvendor)
+				continue;
+	
+		if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
+			if (id->idproduct != dev->idproduct)
+				continue;
+		
+		if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+			if (id->idversion != dev->idversion)
+				continue;
+
+		MATCH_BIT(evbit,  EV_MAX);
+		MATCH_BIT(keybit, KEY_MAX);
+		MATCH_BIT(relbit, REL_MAX);
+		MATCH_BIT(absbit, ABS_MAX);
+		MATCH_BIT(mscbit, MSC_MAX);
+		MATCH_BIT(ledbit, LED_MAX);
+		MATCH_BIT(sndbit, SND_MAX);
+		MATCH_BIT(ffbit,  FF_MAX);
+
+		return id;
+	}
+
+	return NULL;
 }
 
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Input hotplugging invokes what /proc/sys/kernel/hotplug says
+ * (normally /sbin/hotplug) when input devices get added or removed.
+ *
+ * This invokes a user mode policy agent, typically helping to load driver
+ * or other modules, configure the device, and more.  Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ */
+
+#define SPRINTF_BIT_A(bit, name, max) \
+	do { \
+		envp[i++] = scratch; \
+		scratch += sprintf(scratch, name); \
+		for (j = NBITS(max) - 1; j >= 0; j--) \
+			if (dev->bit[j]) break; \
+		for (; j >= 0; j--) \
+			scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
+		scratch++; \
+	} while (0)
+
+#define SPRINTF_BIT_A2(bit, name, max, ev) \
+	do { \
+		if (test_bit(ev, dev->evbit)) \
+			SPRINTF_BIT_A(bit, name, max); \
+	} while (0)
+
+static void input_call_hotplug(char *verb, struct input_dev *dev)
+{
+	char *argv[3], **envp, *buf, *scratch;
+	int i = 0, j, value;
+
+	if (!hotplug_path[0]) {
+		printk(KERN_ERR "input.c: calling hotplug a hotplug agent defined\n");
+		return;
+	}
+	if (in_interrupt()) {
+		printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
+		return; 
+	}
+	if (!current->fs->root) {
+		printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
+		return; 
+	}
+	if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
+		printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+		return;
+	}
+	if (!(buf = kmalloc(1024, GFP_KERNEL))) {
+		kfree (envp);
+		printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+		return;
+	}
+
+	argv[0] = hotplug_path;
+	argv[1] = "input";
+	argv[2] = 0;
+
+	envp[i++] = "HOME=/";
+	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+	scratch = buf;
+
+	envp[i++] = scratch;
+	scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+
+	envp[i++] = scratch;
+	scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
+		dev->idbus, dev->idvendor, dev->idproduct, dev->idversion) + 1; 
+	
+	if (dev->name) {
+		envp[i++] = scratch;
+		scratch += sprintf(scratch, "NAME=%s", dev->name) + 1; 
+	}
+
+	if (dev->phys) {
+		envp[i++] = scratch;
+		scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1; 
+	}	
+
+	SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
+	SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
+	SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
+	SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
+	SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+	SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
+	SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
+	SPRINTF_BIT_A2(ffbit,  "FF=",  FF_MAX, EV_FF);
+
+	envp[i++] = 0;
+
+	printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
+		argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
+
+	value = call_usermodehelper(argv [0], argv, envp);
+
+	kfree(buf);
+	kfree(envp);
+
+	if (value != 0)
+		printk(KERN_WARNING "input.c: hotplug returned %d\n", value);
+}
+
+#endif
+
 void input_register_device(struct input_dev *dev)
 {
 	struct input_handler *handler = input_handler;
 	struct input_handle *handle;
+	struct input_device_id *id;
 
 /*
  * Initialize repeat timer to default values.
@@ -259,18 +471,45 @@
  */
 
 	while (handler) {
-		if ((handle = handler->connect(handler, dev)))
-			input_link_handle(handle);
+		if ((id = input_match_device(handler->id_table, dev)))
+			if ((handle = handler->connect(handler, dev, id)))
+				input_link_handle(handle);
 		handler = handler->next;
 	}
+
+/*
+ * Notify the hotplug agent.
+ */
+
+#ifdef CONFIG_HOTPLUG
+	input_call_hotplug("add", dev);
+#endif
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
+
 }
 
 void input_unregister_device(struct input_dev *dev)
 {
 	struct input_handle *handle = dev->handle;
-	struct input_dev **devptr = &input_dev;
 	struct input_handle *dnext;
 
+	if (!dev) return;
+
+/*
+ * Turn off power management for the device.
+ */
+	if (dev->pm_dev)
+		pm_unregister(dev->pm_dev);
+
+
 /*
  * Kill any pending repeat timers.
  */
@@ -289,23 +528,36 @@
 	}
 
 /*
- * Remove the device.
+ * Notify the hotplug agent.
  */
 
-	while (*devptr && (*devptr != dev))
-		devptr = &((*devptr)->next);
-	*devptr = (*devptr)->next;
+#ifdef CONFIG_HOTPLUG
+	input_call_hotplug("remove", dev);
+#endif
+
+/*
+ * Remove the device.
+ */
+	input_find_and_remove(struct input_dev, input_dev, dev, next);
 
 	input_number--;
+/*
+ * Notify /proc.
+ */
 
-	if (dev->number < INPUT_DEVICES)
-		clear_bit(dev->number, input_devices);
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
 }
 
 void input_register_handler(struct input_handler *handler)
 {
 	struct input_dev *dev = input_dev;
 	struct input_handle *handle;
+	struct input_device_id *id;
+
+	if (!handler) return;
 
 /*
  * Add minors if needed.
@@ -326,15 +578,24 @@
  */
 
 	while (dev) {
-		if ((handle = handler->connect(handler, dev)))
-			input_link_handle(handle);
+		if ((id = input_match_device(handler->id_table, dev)))
+			if ((handle = handler->connect(handler, dev, id)))
+				input_link_handle(handle);
 		dev = dev->next;
 	}
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
 }
 
 void input_unregister_handler(struct input_handler *handler)
 {
-	struct input_handler **handlerptr = &input_handler;
 	struct input_handle *handle = handler->handle;
 	struct input_handle *hnext;
 
@@ -352,18 +613,23 @@
 /*
  * Remove it.
  */
-
-	while (*handlerptr && (*handlerptr != handler))
-		handlerptr = &((*handlerptr)->next);
-
-	*handlerptr = (*handlerptr)->next;
+	input_find_and_remove(struct input_handler, input_handler, handler,
+				next);
 
 /*
  * Remove minors.
  */
-
 	if (handler->fops != NULL)
 		input_table[handler->minor >> 5] = NULL;
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
 }
 
 static int input_open_file(struct inode *inode, struct file *file)
@@ -415,18 +681,164 @@
 	devfs_unregister(handle);
 }
 
+/*
+ * ProcFS interface for the input drivers.
+ */
+
+#ifdef CONFIG_PROC_FS
+
+#define SPRINTF_BIT_B(bit, name, max) \
+	do { \
+		len += sprintf(buf + len, "B: %s", name); \
+		for (i = NBITS(max) - 1; i >= 0; i--) \
+			if (dev->bit[i]) break; \
+		for (; i >= 0; i--) \
+			len += sprintf(buf + len, "%lx ", dev->bit[i]); \
+		len += sprintf(buf + len, "\n"); \
+	} while (0)
+
+#define SPRINTF_BIT_B2(bit, name, max, ev) \
+	do { \
+		if (test_bit(ev, dev->evbit)) \
+			SPRINTF_BIT_B(bit, name, max); \
+	} while (0)
+
+
+static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+{
+	int state = input_devices_state;
+	poll_wait(file, &input_devices_poll_wait, wait);
+	if (state != input_devices_state)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+	struct input_dev *dev = input_dev;
+	struct input_handle *handle;
+
+	off_t at = 0;
+	int i, len, cnt = 0;
+
+	while (dev) {
+
+		len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+			dev->idbus, dev->idvendor, dev->idproduct, dev->idversion);
+
+		len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+		len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+		len += sprintf(buf + len, "D: Drivers=");
+
+		handle = dev->handle;
+
+		while (handle) {
+			len += sprintf(buf + len, "%s ", handle->name);
+			handle = handle->dnext;
+		}
+
+		len += sprintf(buf + len, "\n");
+
+		SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
+		SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
+		SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
+		SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
+		SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+		SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
+		SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
+		SPRINTF_BIT_B2(ffbit,  "FF=",  FF_MAX, EV_FF);
+
+		len += sprintf(buf + len, "\n");
+
+		at += len;
+
+		if (at >= pos) {
+			if (!*start) {
+				*start = buf + (pos - (at - len));
+				cnt = at - pos;
+			} else  cnt += len;
+			buf += len;
+			if (cnt >= count)
+				break;
+		}
+
+		dev = dev->next;
+	}
+
+	if (!dev) *eof = 1;
+
+	return (count > cnt) ? cnt : count;
+}
+
+static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+	struct input_handler *handler = input_handler;
+
+	off_t at = 0;
+	int len = 0, cnt = 0;
+	int i = 0;
+
+	while (handler) {
+
+		if (handler->fops)
+			len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
+				i++, handler->name, handler->minor);
+		else
+			len = sprintf(buf, "N: Number=%d Name=%s\n",
+				i++, handler->name);
+
+		at += len;
+
+		if (at >= pos) {
+			if (!*start) {
+				*start = buf + (pos - (at - len));
+				cnt = at - pos;
+			} else  cnt += len;
+			buf += len;
+			if (cnt >= count)
+				break;
+		}
+
+		handler = handler->next;
+	}
+
+	if (!handler) *eof = 1;
+
+	return (count > cnt) ? cnt : count;
+}
+
+#endif
+
 static int __init input_init(void)
 {
+	struct proc_dir_entry *entry;
+
+#ifdef CONFIG_PROC_FS
+	proc_bus_input_dir = proc_mkdir("input", proc_bus);
+	proc_bus_input_dir->owner = THIS_MODULE;
+	entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+	entry->owner = THIS_MODULE;
+	entry->proc_fops->poll = input_devices_poll;
+	entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+	entry->owner = THIS_MODULE;
+#endif
 	if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
 		printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
 		return -EBUSY;
 	}
+
 	input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);
+
 	return 0;
 }
 
 static void __exit input_exit(void)
 {
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("devices", proc_bus_input_dir);
+	remove_proc_entry("handlers", proc_bus_input_dir);
+	remove_proc_entry("input", proc_bus);
+#endif
 	devfs_unregister(input_devfs_handle);
         if (devfs_unregister_chrdev(INPUT_MAJOR, "input"))
                 printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR);
diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/input/joydev.c	Sun Feb 10 19:58:06 2002
@@ -1,12 +1,10 @@
 /*
- * $Id: joydev.c,v 1.19 2001/01/10 19:49:40 vojtech Exp $
+ * $Id: joydev.c,v 1.38 2001/12/27 10:37:41 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik 
+ *  Copyright (c) 1999-2001 Vojtech Pavlik 
  *  Copyright (c) 1999 Colin Van Dyke 
  *
  *  Joystick device driver for the input driver suite.
- *
- *  Sponsored by SuSE and Intel
  */
 
 /*
@@ -25,8 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <asm/io.h>
@@ -45,14 +43,22 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Joystick device interfaces");
+MODULE_SUPPORTED_DEVICE("input/js");
+MODULE_LICENSE("GPL");
+
 #define JOYDEV_MINOR_BASE	0
 #define JOYDEV_MINORS		32
 #define JOYDEV_BUFFER_SIZE	64
 
+#define MSECS(t)	(1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
+
 struct joydev {
 	int exist;
 	int open;
 	int minor;
+	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	devfs_handle_t devfs;
@@ -81,11 +87,6 @@
 
 static struct joydev *joydev_table[JOYDEV_MINORS];
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Joystick device driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("input/js");
-
 static int joydev_correct(int value, struct js_corr *corr)
 {
 	switch (corr->type) {
@@ -133,7 +134,7 @@
 			return;
 	}  
 
-	event.time = jiffies * (1000 / HZ);
+	event.time = MSECS(jiffies);
 
 	while (list) {
 
@@ -163,7 +164,7 @@
 {
 	struct joydev_list *list = file->private_data;
 	struct joydev_list **listptr;
-	
+
 	listptr = &list->joydev->list;
 	joydev_fasync(-1, file, 0);
 
@@ -249,7 +250,7 @@
 	if (list->head == list->tail && list->startup == joydev->nabs + joydev->nkey) {
 
 		add_wait_queue(&list->joydev->wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		while (list->head == list->tail) {
 
@@ -265,7 +266,7 @@
 			schedule();
 		}
 
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&list->joydev->wait, &wait);
 	}
 
@@ -276,7 +277,7 @@
 
 		struct js_event event;
 
-		event.time = jiffies * (1000/HZ);
+		event.time = MSECS(jiffies);
 
 		if (list->startup < joydev->nkey) {
 			event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
@@ -360,9 +361,9 @@
 			return copy_to_user((struct js_corr *) arg, joydev->corr,
 						sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
 		case JSIOCSAXMAP:
-			if (copy_from_user((__u8 *) arg, joydev->abspam, sizeof(__u8) * ABS_MAX))
+			if (copy_from_user(joydev->abspam, (__u8 *) arg, sizeof(__u8) * ABS_MAX))
 				return -EFAULT;
-			for (i = 0; i < ABS_MAX; i++) {
+			for (i = 0; i < joydev->nabs; i++) {
 				if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
 				joydev->absmap[joydev->abspam[i]] = i;
 			}
@@ -371,11 +372,11 @@
 			return copy_to_user((__u8 *) arg, joydev->abspam,
 						sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
 		case JSIOCSBTNMAP:
-			if (copy_from_user((__u16 *) arg, joydev->absmap, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+			if (copy_from_user(joydev->keypam, (__u16 *) arg, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
 				return -EFAULT;
-			for (i = 0; i < KEY_MAX - BTN_MISC; i++); {
+			for (i = 0; i < joydev->nkey; i++); {
 				if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
-				joydev->keymap[joydev->abspam[i - BTN_MISC]] = i;
+				joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
 			}
 			return 0;
 		case JSIOCGBTNMAP:
@@ -405,15 +406,13 @@
 	fasync:		joydev_fasync,
 };
 
-static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct joydev *joydev;
-	int i, j, minor;
+	int i, j, t, minor;
 
-	if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
-	     (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) &&
-	     (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
-		|| test_bit(BTN_1, dev->keybit)))) return NULL; 
+        if (test_bit(BTN_TOUCH, dev->keybit))
+		return NULL;
 
 	for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
 	if (minor == JOYDEV_MINORS) {
@@ -430,12 +429,13 @@
 	joydev->minor = minor;
 	joydev_table[minor] = joydev;
 
+	sprintf(joydev->name, "js%d", minor);
+
 	joydev->handle.dev = dev;
+	joydev->handle.name = joydev->name;
 	joydev->handle.handler = handler;
 	joydev->handle.private = joydev;
 
-	joydev->exist = 1;
-
 	for (i = 0; i < ABS_MAX; i++)
 		if (test_bit(i, dev->absbit)) {
 			joydev->absmap[i] = joydev->nabs;
@@ -467,15 +467,17 @@
 		joydev->corr[i].prec = dev->absfuzz[j];
 		joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
 		joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
-		joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
-		joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
+		if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
+			continue;
+		joydev->corr[i].coef[2] = (1 << 29) / t;
+		joydev->corr[i].coef[3] = (1 << 29) / t;
 
 		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 	}
 
 	joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
 
-//	printk(KERN_INFO "js%d: Joystick device for input%d\n", minor, dev->number);
+	joydev->exist = 1;
 
 	return &joydev->handle;
 }
@@ -495,12 +497,35 @@
 	}
 }
 
+static struct input_device_id joydev_ids[] = {
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		absbit: { BIT(ABS_X) },
+	},
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		absbit: { BIT(ABS_WHEEL) },
+	},
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		absbit: { BIT(ABS_THROTTLE) },
+	},
+	{ }, 	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, joydev_ids);
+
 static struct input_handler joydev_handler = {
 	event:		joydev_event,
 	connect:	joydev_connect,
 	disconnect:	joydev_disconnect,
 	fops:		&joydev_fops,
 	minor:		JOYDEV_MINOR_BASE,
+	name:		"joydev",
+	id_table:	joydev_ids,
 };
 
 static int __init joydev_init(void)
diff -Nru a/drivers/input/joystick/Config.help b/drivers/input/joystick/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/Config.help	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,205 @@
+CONFIG_JOYSTICK
+  If you have a joystick, 6dof controller, gamepad, steering wheel,
+  weapon control system or something like that you can say Y here
+  and the list of supported devices will be displayed. This option
+  doesn't affect the kernel.
+
+  Please read the file <file:Documentation/input/joystick.txt> which
+  contains more information.
+
+CONFIG_JOYSTICK_ANALOG
+  Say Y here if you have a joystick that connects to the PC
+  gameport. In addition to the usual PC analog joystick, this driver
+  supports many extensions, including joysticks with throttle control,
+  with rudders, additional hats and buttons compatible with CH
+  Flightstick Pro, ThrustMaster FCS, 6 and 8 button gamepads, or
+  Saitek Cyborg joysticks. 
+
+  Please read the file <file:Documentation/input/joystick.txt> which
+  contains more information.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called analog.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_A3D
+  Say Y here if you have an FPGaming or MadCatz controller using the
+  A3D protocol over the PC gameport. 
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called a3d.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_ADI
+  Say Y here if you have a Logitech controller using the ADI
+  protocol over the PC gameport. 
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called adi.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_COBRA
+  Say Y here if you have a Creative Labs Blaster Cobra gamepad.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called cobra.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_GF2K
+  Say Y here if you have a Genius Flight2000 or MaxFighter digitally
+  communicating joystick or gamepad.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called gf2k.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_GRIP
+  Say Y here if you have a Gravis controller using the GrIP protocol
+  over the PC gameport. 
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called grip.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_INTERACT
+  Say Y here if you have an InterAct gameport or joystick
+  communicating digitally over the gameport.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called interact.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_SIDEWINDER
+  Say Y here if you have a Microsoft controller using the Digital
+  Overdrive protocol over PC gameport.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called sidewinder.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_TMDC
+  Say Y here if you have a ThrustMaster controller using the
+  DirectConnect (BSP) protocol over the PC gameport. 
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called tmdc.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_IFORCE_USB
+  Say Y here if you have an I-Force joystick or steering wheel
+  connected to your USB port. 
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called iforce.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_IFORCE_232
+  Say Y here if you have an I-Force joystick or steering wheel
+  connected to your serial (COM) port.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called iforce.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_WARRIOR
+  Say Y here if you have a Logitech WingMan Warrior joystick connected
+  to your computer's serial port. 
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called warrior.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_MAGELLAN
+  Say Y here if you have a Magellan or Space Mouse 6DOF controller
+  connected to your computer's serial port.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called magellan.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_SPACEORB
+  Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
+  controller connected to your computer's serial port.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called spaceorb.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_SPACEBALL
+  Say Y here if you have a SpaceTec SpaceBall 2003/3003/4000 FLX
+  controller connected to your computer's serial port. For the
+  SpaceBall 4000 USB model, use the USB HID driver.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called spaceball.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_STINGER
+  Say Y here if you have a Gravis Stinger connected to one of your
+  serial ports.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called stinger.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_DB9
+  Say Y here if you have a Sega Master System gamepad, Sega Genesis
+  gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
+  Commodore, Amstrad CPC joystick connected to your parallel port.
+  For more information on how to use the driver please read
+  <file:Documentation/input/joystick-parport.txt>.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called db9.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_GAMECON
+  Say Y here if you have a Nintendo Entertainment System gamepad,
+  Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,
+  Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
+  Commodore, Amstrad CPC joystick connected to your parallel port.
+  For more information on how to use the driver please read
+  <file:Documentation/input/joystick-parport.txt>.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called gamecon.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_TURBOGRAFX
+  Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
+  and want to use it with Multisystem -- Atari, Amiga, Commodore,
+  Amstrad CPC joystick. For more information on how to use the driver
+  please read <file:Documentation/input/joystick-parport.txt>.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called turbografx.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_JOYSTICK_AMIJOY
+  Say Y here if you have an Amiga with a digital joystick connected
+  to it.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called joy-amiga.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
diff -Nru a/drivers/input/joystick/Config.in b/drivers/input/joystick/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/Config.in	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,31 @@
+#
+# Joystick driver configuration
+#
+
+bool 'Joysticks' CONFIG_INPUT_JOYSTICK
+
+dep_tristate '  Classic PC analog joysticks and gamepads' CONFIG_JOYSTICK_ANALOG $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  Assasin 3D and MadCatz Panther devices' CONFIG_JOYSTICK_A3D $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  Logitech ADI digital joysticks and gamepads' CONFIG_JOYSTICK_ADI $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  Creative Labs Blaster Cobra gamepad' CONFIG_JOYSTICK_COBRA $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  Genius Flight2000 Digital joysticks and gamepads' CONFIG_JOYSTICK_GF2K $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  Gravis GrIP joysticks and gamepads' CONFIG_JOYSTICK_GRIP $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  InterAct digital joysticks and gamepads' CONFIG_JOYSTICK_INTERACT $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  Microsoft SideWinder digital joysticks and gamepads' CONFIG_JOYSTICK_SIDEWINDER $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+dep_tristate '  ThrustMaster DirectConnect joysticks and gamepads' CONFIG_JOYSTICK_TMDC $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_GAMEPORT
+
+dep_tristate '  I-Force USB joysticks and wheels' CONFIG_JOYSTICK_IFORCE_USB $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_USB
+dep_tristate '  I-Force Serial joysticks and wheels' CONFIG_JOYSTICK_IFORCE_232 $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_SERIO
+dep_tristate '  Logitech WingMan Warrior joystick' CONFIG_JOYSTICK_WARRIOR $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_SERIO
+dep_tristate '  LogiCad3d Magellan/SpaceMouse 6dof controllers' CONFIG_JOYSTICK_MAGELLAN $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_SERIO
+dep_tristate '  SpaceTec SpaceOrb/Avenger 6dof controllers' CONFIG_JOYSTICK_SPACEORB $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_SERIO
+dep_tristate '  SpaceTec SpaceBall 6dof controllers' CONFIG_JOYSTICK_SPACEBALL $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_SERIO
+dep_tristate '  Gravis Stinger gamepad' CONFIG_JOYSTICK_STINGER $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_SERIO
+
+dep_tristate '  Multisystem, Sega Genesis, Saturn joysticks and gamepads' CONFIG_JOYSTICK_DB9 $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_PARPORT
+dep_tristate '  Multisystem, NES, SNES, N64, PSX joysticks and gamepads' CONFIG_JOYSTICK_GAMECON $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_PARPORT
+dep_tristate '  Multisystem joysticks via TurboGraFX device' CONFIG_JOYSTICK_TURBOGRAFX $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK $CONFIG_PARPORT
+
+if [ "$CONFIG_AMIGA" = "y" ]; then
+   dep_tristate '  Amiga joysticks' CONFIG_JOYSTICK_AMIJOY $CONFIG_INPUT $CONFIG_INPUT_JOYSTICK
+fi
diff -Nru a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/Makefile	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,51 @@
+#
+# Makefile for the input core drivers.
+#
+
+# The target object and module list name.
+
+O_TARGET	:= joydrv.o
+
+# I-Force may need both USB and RS-232
+
+CONFIG_JOYSTICK_IFORCE := n
+
+ifeq ($(CONFIG_JOYSTICK_IFORCE_232),y)
+	ifeq ($(CONFIG_JOYSTICK_IFORCE_USB),y)
+		CONFIG_JOYSTICK_IFORCE := y
+	endif
+endif
+
+ifeq ($(CONFIG_JOYSTICK_IFORCE_232),m)
+	CONFIG_JOYSTICK_IFORCE := m
+endif
+
+ifeq ($(CONFIG_JOYSTICK_IFORCE_USB),m)
+	CONFIG_JOYSTICK_IFORCE := m
+endif
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_JOYSTICK_A3D)		+= a3d.o
+obj-$(CONFIG_JOYSTICK_ADI)		+= adi.o
+obj-$(CONFIG_JOYSTICK_AMIGA)		+= amijoy.o
+obj-$(CONFIG_JOYSTICK_ANALOG)		+= analog.o
+obj-$(CONFIG_JOYSTICK_COBRA)		+= cobra.o
+obj-$(CONFIG_JOYSTICK_DB9)		+= db9.o
+obj-$(CONFIG_JOYSTICK_GAMECON)		+= gamecon.o
+obj-$(CONFIG_JOYSTICK_GF2K)		+= gf2k.o
+obj-$(CONFIG_JOYSTICK_GRIP)		+= grip.o
+obj-$(CONFIG_JOYSTICK_IFORCE)		+= iforce.o
+obj-$(CONFIG_JOYSTICK_INTERACT)		+= interact.o
+obj-$(CONFIG_JOYSTICK_MAGELLAN)		+= magellan.o
+obj-$(CONFIG_JOYSTICK_SIDEWINDER)	+= sidewinder.o
+obj-$(CONFIG_JOYSTICK_SPACEBALL)	+= spaceball.o
+obj-$(CONFIG_JOYSTICK_SPACEORB)		+= spaceorb.o
+obj-$(CONFIG_JOYSTICK_STINGER)		+= stinger.o
+obj-$(CONFIG_JOYSTICK_TMDC)		+= tmdc.o
+obj-$(CONFIG_JOYSTICK_TURBOGRAFX)	+= turbografx.o
+obj-$(CONFIG_JOYSTICK_WARRIOR)		+= warrior.o
+
+# The global Rules.make.
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/a3d.c	Sun Feb 10 19:58:03 2002
@@ -0,0 +1,388 @@
+/*
+ * $Id: a3d.c,v 1.14 2001/04/26 10:24:46 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2001 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * FP-Gaming Assasin 3D joystick driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/input.h>
+
+#define A3D_MAX_START		400	/* 400 us */ 
+#define A3D_MAX_STROBE		60	/* 40 us */ 
+#define A3D_DELAY_READ		3	/* 3 ms */
+#define A3D_MAX_LENGTH		40	/* 40*3 bits */
+#define A3D_REFRESH_TIME	HZ/50	/* 20 ms */
+
+#define A3D_MODE_A3D		1	/* Assassin 3D */
+#define A3D_MODE_PAN		2	/* Panther */
+#define A3D_MODE_OEM		3	/* Panther OEM version */
+#define A3D_MODE_PXL		4	/* Panther XL */
+
+char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
+			"MadCatz Panther XL", "MadCatz Panther XL w/ rudder" };
+
+struct a3d {
+	struct gameport *gameport;
+	struct gameport adc;
+	struct input_dev dev;
+	struct timer_list timer;
+	int axes[4];
+	int buttons;
+	int mode;
+	int length;
+	int used;
+	int reads;
+	int bads;
+};
+
+/*
+ * a3d_read_packet() reads an Assassin 3D packet.
+ */
+
+static int a3d_read_packet(struct gameport *gameport, int length, char *data)
+{
+	unsigned long flags;
+	unsigned char u, v;
+	unsigned int t, s;
+	int i;
+
+	i = 0;
+	t = gameport_time(gameport, A3D_MAX_START);
+	s = gameport_time(gameport, A3D_MAX_STROBE);
+
+	__save_flags(flags);
+	__cli();
+	gameport_trigger(gameport);
+	v = gameport_read(gameport);
+
+	while (t > 0 && i < length) {
+		t--;
+		u = v; v = gameport_read(gameport);
+		if (~v & u & 0x10) {
+			data[i++] = v >> 5;
+			t = s;
+		}
+	}
+
+	__restore_flags(flags);
+
+	return i;
+}
+
+/*
+ * a3d_csum() computes checksum of triplet packet
+ */
+
+static int a3d_csum(char *data, int count)
+{
+	int i, csum = 0;
+	for (i = 0; i < count - 2; i++) csum += data[i];
+	return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
+}
+
+static void a3d_read(struct a3d *a3d, unsigned char *data)
+{
+	struct input_dev *dev = &a3d->dev;
+
+	switch (a3d->mode) {
+
+		case A3D_MODE_A3D:
+		case A3D_MODE_OEM:
+		case A3D_MODE_PAN:
+
+			input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7));
+			input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7));
+			
+			input_report_key(dev, BTN_RIGHT,  data[2] & 1);
+			input_report_key(dev, BTN_LEFT,   data[3] & 2);
+			input_report_key(dev, BTN_MIDDLE, data[3] & 4);
+
+			a3d->axes[0] = ((signed char)((data[11] << 6) | (data[12] << 3) | (data[13]))) + 128;
+			a3d->axes[1] = ((signed char)((data[14] << 6) | (data[15] << 3) | (data[16]))) + 128;
+			a3d->axes[2] = ((signed char)((data[17] << 6) | (data[18] << 3) | (data[19]))) + 128;
+			a3d->axes[3] = ((signed char)((data[20] << 6) | (data[21] << 3) | (data[22]))) + 128;
+
+			a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;
+
+			return;
+
+		case A3D_MODE_PXL:
+
+			input_report_rel(dev, REL_X, ((data[ 9] << 6) | (data[10] << 3) | data[11]) - ((data[ 9] & 4) << 7));
+			input_report_rel(dev, REL_Y, ((data[12] << 6) | (data[13] << 3) | data[14]) - ((data[12] & 4) << 7));
+
+			input_report_key(dev, BTN_RIGHT,  data[2] & 1);
+			input_report_key(dev, BTN_LEFT,   data[3] & 2);
+			input_report_key(dev, BTN_MIDDLE, data[3] & 4);
+			input_report_key(dev, BTN_SIDE,   data[7] & 2);
+			input_report_key(dev, BTN_EXTRA,  data[7] & 4);
+
+			input_report_abs(dev, ABS_X,        ((signed char)((data[15] << 6) | (data[16] << 3) | (data[17]))) + 128);
+			input_report_abs(dev, ABS_Y,        ((signed char)((data[18] << 6) | (data[19] << 3) | (data[20]))) + 128);
+			input_report_abs(dev, ABS_RUDDER,   ((signed char)((data[21] << 6) | (data[22] << 3) | (data[23]))) + 128);
+			input_report_abs(dev, ABS_THROTTLE, ((signed char)((data[24] << 6) | (data[25] << 3) | (data[26]))) + 128);
+
+			input_report_abs(dev, ABS_HAT0X, ( data[5]       & 1) - ((data[5] >> 2) & 1));
+			input_report_abs(dev, ABS_HAT0Y, ((data[5] >> 1) & 1) - ((data[6] >> 2) & 1));
+			input_report_abs(dev, ABS_HAT1X, ((data[4] >> 1) & 1) - ( data[3]       & 1));
+			input_report_abs(dev, ABS_HAT1Y, ((data[4] >> 2) & 1) - ( data[4]       & 1));
+
+			input_report_key(dev, BTN_TRIGGER, data[8] & 1);
+			input_report_key(dev, BTN_THUMB,   data[8] & 2);
+			input_report_key(dev, BTN_TOP,     data[8] & 4);
+			input_report_key(dev, BTN_PINKIE,  data[7] & 1);
+
+			return;
+	}
+}
+
+
+/*
+ * a3d_timer() reads and analyzes A3D joystick data.
+ */
+
+static void a3d_timer(unsigned long private)
+{
+	struct a3d *a3d = (void *) private;
+	unsigned char data[A3D_MAX_LENGTH];
+	a3d->reads++;
+	if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length
+		|| data[0] != a3d->mode || a3d_csum(data, a3d->length))
+	 	a3d->bads++; else a3d_read(a3d, data);
+	mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
+}
+
+/*
+ * a3d_adc_cooked_read() copies the acis and button data to the
+ * callers arrays. It could do the read itself, but the caller could
+ * call this more than 50 times a second, which would use too much CPU.
+ */
+
+int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+	struct a3d *a3d = gameport->private;
+	int i;
+	for (i = 0; i < 4; i++)
+		axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
+	*buttons = a3d->buttons; 
+	return 0;
+}
+
+/*
+ * a3d_adc_open() is the gameport open routine. It refuses to serve
+ * any but cooked data.
+ */
+
+int a3d_adc_open(struct gameport *gameport, int mode)
+{
+	struct a3d *a3d = gameport->private;
+	if (mode != GAMEPORT_MODE_COOKED)
+		return -1;
+	if (!a3d->used++)
+		mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);	
+	return 0;
+}
+
+/*
+ * a3d_adc_close() is a callback from the input close routine.
+ */
+
+static void a3d_adc_close(struct gameport *gameport)
+{
+	struct a3d *a3d = gameport->private;
+	if (!--a3d->used)
+		del_timer(&a3d->timer);
+}
+
+/*
+ * a3d_open() is a callback from the input open routine.
+ */
+
+static int a3d_open(struct input_dev *dev)
+{
+	struct a3d *a3d = dev->private;
+	if (!a3d->used++)
+		mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);	
+	return 0;
+}
+
+/*
+ * a3d_close() is a callback from the input close routine.
+ */
+
+static void a3d_close(struct input_dev *dev)
+{
+	struct a3d *a3d = dev->private;
+	if (!--a3d->used)
+		del_timer(&a3d->timer);
+}
+
+/*
+ * a3d_connect() probes for A3D joysticks.
+ */
+
+static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct a3d *a3d;
+	unsigned char data[A3D_MAX_LENGTH];
+	int i;
+
+	if (!(a3d = kmalloc(sizeof(struct a3d), GFP_KERNEL)))
+		return;
+	memset(a3d, 0, sizeof(struct a3d));
+
+	gameport->private = a3d;
+
+	a3d->gameport = gameport;
+	init_timer(&a3d->timer);
+	a3d->timer.data = (long) a3d;
+	a3d->timer.function = a3d_timer;
+
+	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		goto fail1;
+
+	i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);
+
+	if (!i || a3d_csum(data, i))
+		goto fail2;
+
+	a3d->mode = data[0];
+
+	if (!a3d->mode || a3d->mode > 5) {
+		printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
+			"(gameport%d, id=%d), contact <vojtech@suse.cz>\n", gameport->number, a3d->mode);
+		goto fail2;
+	}
+
+
+	if (a3d->mode == A3D_MODE_PXL) {
+
+		int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
+
+		a3d->length = 33;
+
+		a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
+		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
+		a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
+				   | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
+
+		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
+						 | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+
+		a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE);
+
+		a3d_read(a3d, data);
+
+		for (i = 0; i < 4; i++) {
+			if (i < 2) {
+				a3d->dev.absmin[axes[i]] = 48;
+				a3d->dev.absmax[axes[i]] = a3d->dev.abs[axes[i]] * 2 - 48;
+				a3d->dev.absflat[axes[i]] = 8;
+			} else {
+				a3d->dev.absmin[axes[i]] = 2;
+				a3d->dev.absmax[axes[i]] = 253;
+			}
+			a3d->dev.absmin[ABS_HAT0X + i] = -1;
+			a3d->dev.absmax[ABS_HAT0X + i] = 1;
+		}
+
+	} else {
+		a3d->length = 29;
+
+		a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
+		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
+		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
+
+		a3d->adc.private = a3d;
+		a3d->adc.open = a3d_adc_open;
+		a3d->adc.close = a3d_adc_close;
+		a3d->adc.cooked_read = a3d_adc_cooked_read;
+		a3d->adc.fuzz = 1; 
+
+		a3d_read(a3d, data);
+
+		gameport_register_port(&a3d->adc);
+		printk(KERN_INFO "gameport%d: %s on gameport%d.0\n",
+			a3d->adc.number, a3d_names[a3d->mode], gameport->number);
+	}
+
+	a3d->dev.private = a3d;
+	a3d->dev.open = a3d_open;
+	a3d->dev.close = a3d_close;
+
+	a3d->dev.name = a3d_names[a3d->mode];
+	a3d->dev.idbus = BUS_GAMEPORT;
+	a3d->dev.idvendor = GAMEPORT_ID_VENDOR_MADCATZ;
+	a3d->dev.idproduct = a3d->mode;
+	a3d->dev.idversion = 0x0100;
+
+	input_register_device(&a3d->dev);
+	printk(KERN_INFO "input%d: %s on gameport%d.0\n",
+		a3d->dev.number, a3d_names[a3d->mode], gameport->number);
+
+	return;
+fail2:	gameport_close(gameport);
+fail1:  kfree(a3d);
+}
+
+static void a3d_disconnect(struct gameport *gameport)
+{
+
+	struct a3d *a3d = gameport->private;
+	input_unregister_device(&a3d->dev);
+	if (a3d->mode < A3D_MODE_PXL)
+		gameport_unregister_port(&a3d->adc);
+	gameport_close(gameport);
+	kfree(a3d);
+}
+
+static struct gameport_dev a3d_dev = {
+	connect:	a3d_connect,
+	disconnect:	a3d_disconnect,
+};
+
+int __init a3d_init(void)
+{
+	gameport_register_device(&a3d_dev);
+	return 0;
+}
+
+void __exit a3d_exit(void)
+{
+	gameport_unregister_device(&a3d_dev);
+}
+
+module_init(a3d_init);
+module_exit(a3d_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/adi.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,557 @@
+/*
+ * $Id: adi.c,v 1.15 2001/01/09 13:32:39 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Logitech ADI joystick family driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/gameport.h>
+#include <linux/init.h>
+
+/*
+ * Times, array sizes, flags, ids.
+ */
+
+#define ADI_MAX_START		200	/* Trigger to packet timeout [200us] */
+#define ADI_MAX_STROBE		40	/* Single bit timeout [40us] */
+#define ADI_REFRESH_TIME	HZ/50	/* How often to poll the joystick [20 ms] */
+#define ADI_INIT_DELAY		10	/* Delay after init packet [10ms] */
+#define ADI_DATA_DELAY		4	/* Delay after data packet [4ms] */
+
+#define ADI_MAX_LENGTH		256
+#define ADI_MIN_LENGTH		8
+#define ADI_MIN_LEN_LENGTH	10
+#define ADI_MIN_ID_LENGTH	66
+#define ADI_MAX_NAME_LENGTH	48
+#define ADI_MAX_CNAME_LENGTH	16
+
+#define ADI_FLAG_HAT		0x04
+#define ADI_FLAG_10BIT		0x08
+
+#define ADI_ID_TPD		0x01
+#define ADI_ID_WGP		0x06
+#define ADI_ID_WGPE		0x08
+#define ADI_ID_MAX		0x0a
+
+/*
+ * Names, buttons, axes ...
+ */
+
+static char *adi_names[] = {	"WingMan Extreme Digital", "ThunderPad Digital", "SideCar", "CyberMan 2",
+				"WingMan Interceptor", "WingMan Formula", "WingMan GamePad", 
+				"WingMan Extreme Digital 3D", "WingMan GamePad Extreme", 
+				"WingMan GamePad USB", "Unknown Device %#x" };
+
+static char adi_wmgpe_abs[] =	{ ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y };
+static char adi_wmi_abs[] =	{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
+static char adi_wmed3d_abs[] =	{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RZ, ABS_HAT0X, ABS_HAT0Y };
+static char adi_cm2_abs[] =	{ ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
+static char adi_wmf_abs[] =	{ ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
+
+static short adi_wmgpe_key[] =	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z,  BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT };
+static short adi_wmi_key[] = 	{ BTN_TRIGGER,  BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA };
+static short adi_wmed3d_key[] =	{ BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 };
+static short adi_cm2_key[] =	{ BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
+
+static char* adi_abs[] = { adi_wmi_abs, adi_wmgpe_abs, adi_wmf_abs, adi_cm2_abs, adi_wmi_abs, adi_wmf_abs,
+			   adi_wmgpe_abs, adi_wmed3d_abs, adi_wmgpe_abs, adi_wmgpe_abs, adi_wmi_abs };
+
+static short* adi_key[] = { adi_wmi_key, adi_wmgpe_key, adi_cm2_key, adi_cm2_key, adi_wmi_key, adi_cm2_key,
+			    adi_wmgpe_key, adi_wmed3d_key, adi_wmgpe_key, adi_wmgpe_key, adi_wmi_key };
+
+/*
+ * Hat to axis conversion arrays.
+ */
+
+static struct {
+	int x;
+	int y;
+} adi_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+/*
+ * Per-port information.
+ */
+
+struct adi {
+	struct input_dev dev;
+	int length;
+	int ret;
+	int idx;
+	unsigned char id;
+	char buttons;
+	char axes10;
+	char axes8;
+	signed char pad;
+	char hats;
+	char *abs;
+	short *key;
+	char name[ADI_MAX_NAME_LENGTH];
+	char cname[ADI_MAX_CNAME_LENGTH];
+	unsigned char data[ADI_MAX_LENGTH];
+};
+
+struct adi_port {
+	struct gameport *gameport;
+	struct timer_list timer;
+	struct adi adi[2];
+	int bad;
+	int reads;
+	int used;
+};
+
+/*
+ * adi_read_packet() reads a Logitech ADI packet.
+ */
+
+static void adi_read_packet(struct adi_port *port)
+{
+	struct adi *adi = port->adi;
+	struct gameport *gameport = port->gameport;
+	unsigned char u, v, w, x, z;
+	int t[2], s[2], i;
+	unsigned long flags;
+
+	for (i = 0; i < 2; i++) {
+		adi[i].ret = -1;
+		t[i] = gameport_time(gameport, ADI_MAX_START);
+		s[i] = 0;
+	}
+
+	__save_flags(flags);
+	__cli();
+
+	gameport_trigger(gameport);
+	v = z = gameport_read(gameport);
+
+	do {
+		u = v;
+		w = u ^ (v = x = gameport_read(gameport));
+		for (i = 0; i < 2; i++, w >>= 2, x >>= 2) {
+			t[i]--;
+			if ((w & 0x30) && s[i]) {
+				if ((w & 0x30) < 0x30 && adi[i].ret < ADI_MAX_LENGTH && t[i] > 0) {
+					adi[i].data[++adi[i].ret] = w;
+					t[i] = gameport_time(gameport, ADI_MAX_STROBE);
+				} else t[i] = 0;
+			} else if (!(x & 0x30)) s[i] = 1;
+		}
+	} while (t[0] > 0 || t[1] > 0);
+
+	__restore_flags(flags);
+
+	return;
+}
+
+/*
+ * adi_move_bits() detects a possible 2-stream mode, and moves
+ * the bits accordingly. 
+ */
+
+static void adi_move_bits(struct adi_port *port, int length)
+{
+	int i;
+	struct adi *adi = port->adi;
+
+ 	adi[0].idx = adi[1].idx = 0;
+
+	if (adi[0].ret <= 0 || adi[1].ret <= 0) return;
+	if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return;
+
+	for (i = 1; i <= adi[1].ret; i++)
+		adi[0].data[((length - 1) >> 1) + i + 1] = adi[1].data[i];
+
+	adi[0].ret += adi[1].ret;
+	adi[1].ret = -1;
+}
+
+/*
+ * adi_get_bits() gathers bits from the data packet.
+ */
+
+static inline int adi_get_bits(struct adi *adi, int count)
+{
+	int bits = 0;
+	int i;
+	if ((adi->idx += count) > adi->ret) return 0;
+	for (i = 0; i < count; i++)
+		bits |= ((adi->data[adi->idx - i] >> 5) & 1) << i; 
+	return bits;
+}
+
+/*
+ * adi_decode() decodes Logitech joystick data into input events.
+ */
+
+static int adi_decode(struct adi *adi)
+{
+	struct input_dev *dev = &adi->dev;
+	char *abs = adi->abs;
+	short *key = adi->key;
+	int i, t;
+
+	if (adi->ret < adi->length || adi->id != (adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4)))
+		return -1;	
+
+	for (i = 0; i < adi->axes10; i++) 
+		input_report_abs(dev, *abs++, adi_get_bits(adi, 10));
+
+	for (i = 0; i < adi->axes8; i++) 
+		input_report_abs(dev, *abs++, adi_get_bits(adi, 8));
+
+	for (i = 0; i < adi->buttons && i < 63; i++) {
+		if (i == adi->pad) {
+			t = adi_get_bits(adi, 4);
+			input_report_abs(dev, *abs++, ((t >> 2) & 1) - ( t       & 1));
+			input_report_abs(dev, *abs++, ((t >> 1) & 1) - ((t >> 3) & 1));
+		}
+		input_report_key(dev, *key++, adi_get_bits(adi, 1));
+	}
+
+	for (i = 0; i < adi->hats; i++) {
+		if ((t = adi_get_bits(adi, 4)) > 8) t = 0;
+		input_report_abs(dev, *abs++, adi_hat_to_axis[t].x);
+		input_report_abs(dev, *abs++, adi_hat_to_axis[t].y);
+	}
+
+	for (i = 63; i < adi->buttons; i++)
+		input_report_key(dev, *key++, adi_get_bits(adi, 1));
+
+	return 0;
+}
+
+/*
+ * adi_read() reads the data packet and decodes it.
+ */
+
+static int adi_read(struct adi_port *port)
+{
+	int i;
+	int result = 0;
+
+	adi_read_packet(port);
+	adi_move_bits(port, port->adi[0].length);
+
+	for (i = 0; i < 2; i++)
+		if (port->adi[i].length)
+			 result |= adi_decode(port->adi + i);
+
+	return result;
+}
+
+/*
+ * adi_timer() repeatedly polls the Logitech joysticks.
+ */
+
+static void adi_timer(unsigned long data)
+{
+	struct adi_port *port = (void *) data;
+	port->bad -= adi_read(port);
+	port->reads++;
+	mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);
+}
+
+/*
+ * adi_open() is a callback from the input open routine.
+ */
+
+static int adi_open(struct input_dev *dev)
+{
+	struct adi_port *port = dev->private;
+	if (!port->used++)
+		mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);	
+	return 0;
+}
+
+/*
+ * adi_close() is a callback from the input close routine.
+ */
+
+static void adi_close(struct input_dev *dev)
+{
+	struct adi_port *port = dev->private;
+	if (!--port->used)
+		del_timer(&port->timer);
+}
+
+/*
+ * adi_init_digital() sends a trigger & delay sequence
+ * to reset and initialize a Logitech joystick into digital mode.
+ */
+
+static void adi_init_digital(struct gameport *gameport)
+{
+	int seq[] = { 3, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
+	int i;
+
+	for (i = 0; seq[i]; i++) {
+		gameport_trigger(gameport);
+		if (seq[i] > 0) wait_ms(seq[i]);
+		if (seq[i] < 0) mdelay(-seq[i]);
+	}
+}
+
+static void adi_id_decode(struct adi *adi, struct adi_port *port)
+{
+	int i, t;
+
+	if (adi->ret < ADI_MIN_ID_LENGTH) /* Minimum ID packet length */
+		return;
+
+	if (adi->ret < (t = adi_get_bits(adi, 10))) {
+		printk(KERN_WARNING "adi: Short ID packet: reported: %d != read: %d\n", t, adi->ret); 
+		return;
+	}
+
+	adi->id = adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4);
+
+	if ((t = adi_get_bits(adi, 4)) & ADI_FLAG_HAT) adi->hats++;
+
+	adi->length = adi_get_bits(adi, 10);
+
+	if (adi->length >= ADI_MAX_LENGTH || adi->length < ADI_MIN_LENGTH) {
+		printk(KERN_WARNING "adi: Bad data packet length (%d).\n", adi->length);
+		adi->length = 0;
+		return;
+	}
+
+	adi->axes8 = adi_get_bits(adi, 4);
+	adi->buttons = adi_get_bits(adi, 6);
+
+	if (adi_get_bits(adi, 6) != 8 && adi->hats) {
+		printk(KERN_WARNING "adi: Other than 8-dir POVs not supported yet.\n");
+		adi->length = 0;
+		return;
+	}
+
+	adi->buttons += adi_get_bits(adi, 6);
+	adi->hats += adi_get_bits(adi, 4);
+
+	i = adi_get_bits(adi, 4);
+
+	if (t & ADI_FLAG_10BIT) {
+		adi->axes10 = adi->axes8 - i;
+		adi->axes8 = i;
+	}
+
+	t = adi_get_bits(adi, 4);
+
+	for (i = 0; i < t; i++)
+		adi->cname[i] = adi_get_bits(adi, 8);
+	adi->cname[i] = 0;
+
+	t = 8 + adi->buttons + adi->axes10 * 10 + adi->axes8 * 8 + adi->hats * 4;
+	if (adi->length != t && adi->length != t + (t & 1)) {
+		printk(KERN_WARNING "adi: Expected length %d != data length %d\n", t, adi->length);
+		adi->length = 0;
+		return;
+	}
+
+	switch (adi->id) {
+		case ADI_ID_TPD:
+			adi->pad = 4;
+			adi->buttons -= 4;
+			break;
+		case ADI_ID_WGP:
+			adi->pad = 0;
+			adi->buttons -= 4;
+			break;
+		default:
+			adi->pad = -1;
+			break;
+	}
+}
+
+static void adi_init_input(struct adi *adi, struct adi_port *port)
+{
+	int i, t;
+	char buf[ADI_MAX_NAME_LENGTH];
+
+	if (!adi->length) return;
+
+	t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
+
+	sprintf(buf, adi_names[t], adi->id);
+	sprintf(adi->name, "Logitech %s", buf);
+
+	adi->abs = adi_abs[t];
+	adi->key = adi_key[t];
+
+	adi->dev.open = adi_open;
+	adi->dev.close = adi_close;
+
+	adi->dev.name = adi->name;
+	adi->dev.idbus = BUS_GAMEPORT;
+	adi->dev.idvendor = GAMEPORT_ID_VENDOR_LOGITECH;
+	adi->dev.idproduct = adi->id;
+	adi->dev.idversion = 0x0100;
+
+	adi->dev.private = port;
+	adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++)
+		set_bit(adi->abs[i], &adi->dev.absbit);
+
+	for (i = 0; i < adi->buttons; i++)
+		set_bit(adi->key[i], &adi->dev.keybit);
+}
+
+static void adi_init_center(struct adi *adi)
+{
+	int i, t, x;
+
+	if (!adi->length) return;
+
+	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++) {
+
+		t = adi->abs[i];
+		x = adi->dev.abs[t];
+
+		if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) {
+			if (i < adi->axes10) x = 512; else x = 128;
+		}
+
+		if (i < adi->axes10) {
+			adi->dev.absmax[t] = x * 2 - 64;
+			adi->dev.absmin[t] = 64;
+			adi->dev.absfuzz[t] = 2;
+			adi->dev.absflat[t] = 16;
+			continue;
+		}
+
+		if (i < adi->axes10 + adi->axes8) {
+			adi->dev.absmax[t] = x * 2 - 48;
+			adi->dev.absmin[t] = 48;
+			adi->dev.absfuzz[t] = 1;
+			adi->dev.absflat[t] = 16;
+			continue;
+		}
+
+		adi->dev.absmax[t] = 1;
+		adi->dev.absmin[t] = -1;
+	}
+}
+
+/*
+ * adi_connect() probes for Logitech ADI joysticks.
+ */
+
+static void adi_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct adi_port *port;
+	int i;
+
+	if (!(port = kmalloc(sizeof(struct adi_port), GFP_KERNEL)))
+		return;
+	memset(port, 0, sizeof(struct adi_port));
+
+	gameport->private = port;
+
+	port->gameport = gameport;
+	init_timer(&port->timer);
+	port->timer.data = (long) port;
+	port->timer.function = adi_timer;
+
+	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+		kfree(port);
+		return;
+	}
+
+	adi_init_digital(gameport);
+	adi_read_packet(port);
+	
+	if (port->adi[0].ret >= ADI_MIN_LEN_LENGTH)
+		adi_move_bits(port, adi_get_bits(port->adi, 10));
+
+	for (i = 0; i < 2; i++) {
+		adi_id_decode(port->adi + i, port);
+		adi_init_input(port->adi + i, port);
+	}
+
+	if (!port->adi[0].length && !port->adi[1].length) {
+		gameport_close(gameport);
+		kfree(port);
+		return;
+	}
+
+	wait_ms(ADI_INIT_DELAY);
+	if (adi_read(port)) {
+		wait_ms(ADI_DATA_DELAY);
+		adi_read(port);
+	}
+
+	for (i = 0; i < 2; i++)
+		if (port->adi[i].length > 0) {
+			adi_init_center(port->adi + i);
+			input_register_device(&port->adi[i].dev);
+			printk(KERN_INFO "input%d: %s [%s] on gameport%d.%d\n",
+				port->adi[i].dev.number, port->adi[i].name, port->adi[i].cname, gameport->number, i);
+		}
+}
+
+static void adi_disconnect(struct gameport *gameport)
+{
+	int i;
+
+	struct adi_port *port = gameport->private;
+	for (i = 0; i < 2; i++)
+		if (port->adi[i].length > 0)
+			input_unregister_device(&port->adi[i].dev);
+	gameport_close(gameport);
+	kfree(port);
+}
+
+/*
+ * The gameport device structure.
+ */
+
+static struct gameport_dev adi_dev = {
+	connect:	adi_connect,
+	disconnect:	adi_disconnect,
+};
+
+int __init adi_init(void)
+{
+	gameport_register_device(&adi_dev);
+	return 0;
+}
+
+void __exit adi_exit(void)
+{
+	gameport_unregister_device(&adi_dev);
+}
+
+module_init(adi_init);
+module_exit(adi_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/amijoy.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,161 @@
+/*
+ * $Id: amijoy.c,v 1.5 2000/07/21 22:52:24 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Driver for Amiga joysticks for Linux/m68k
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+
+#include <asm/system.h>
+#include <asm/amigahw.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_PARM(amijoy, "1-2i");
+MODULE_LICENSE("GPL");
+
+static int amijoy[2] = { 0, 1 };
+static int amijoy_used[2] = { 0, 0 };
+static struct input_dev amijoy_dev[2];
+
+static char *amijoy_name = "Amiga joystick";
+
+static void amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
+{
+	int i, data = 0, button = 0;
+
+	for (i = 0; i < 2; i++)
+		if (amijoy[i]) {
+
+			switch (i) {
+				case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
+				case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
+			}
+
+			input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
+
+			input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1);
+			data = ~(data ^ (data << 1));
+			input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1);
+		}
+}
+
+static int amijoy_open(struct input_dev *dev)
+{
+	int *used = dev->private;
+
+	if ((*used)++)
+		return 0;
+	
+	if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", NULL)) {
+		(*used)--;
+		printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", amijoy_irq);
+		return -EBUSY;
+	}
+		
+	return 0;
+}
+
+static void amijoy_close(struct input_dev *dev)
+{
+	int *used = dev->private;
+
+	if (!--(*used))
+		free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
+}
+
+static int __init amijoy_setup(char *str)
+{
+	int i;
+	int ints[4]
+        str = get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 2; i++) amijoy[i] = ints[i+1];
+	return 1;
+}
+__setup("amijoy=", amijoy_setup);
+
+static int __init amijoy_init(void)
+{
+	int i, j;
+
+	init_timer(amijoy_timer);
+	port->timer.function = amijoy_timer;
+
+	for (i = 0; i < 2; i++)
+		if (amijoy[i]) {
+			if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
+						"amijoy [Denise]")) {
+				if (i == 1 && amijoy[0]) {
+					input_unregister_device(amijoy_dev);
+					release_mem_region(CUSTOM_PHYSADDR+10, 2);
+				}
+				return -EBUSY;
+			}
+
+			amijoy_dev[i].open = amijoy_open;
+			amijoy_dev[i].close = amijoy_close;
+			amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+			amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+			amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+			for (j = 0; j < 2; j++) {
+				amijoy_dev[i].absmin[ABS_X + j] = -1;
+				amijoy_dev[i].absmax[ABS_X + j] = 1;
+			}
+
+			amijoy->dev[i].name = amijoy_name;
+			amijoy->dev[i].idbus = BUS_AMIGA;
+			amijoy->dev[i].idvendor = 0x0001;
+			amijoy->dev[i].idproduct = 0x0003;
+			amijoy->dev[i].version = 0x0100;
+
+			amijoy_dev[i].private = amijoy_used + i;
+
+			input_register_device(amijoy_dev + i);
+			printk(KERN_INFO "input%d: %s at joy%ddat\n", amijoy_dev[i].number, amijoy_name, i);
+		}
+	return 0;
+}
+
+static void _exit amijoy_exit(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++)
+		if (amijoy[i]) {
+			input_unregister_device(amijoy_dev + i);
+			release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
+		}
+}
+
+module_init(amijoy_init);
+module_exit(amijoy_exit);
diff -Nru a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/analog.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,761 @@
+/*
+ * $Id: analog.c,v 1.52 2000/06/07 13:07:06 vojtech Exp $
+ *
+ *  Copyright (c) 1996-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Analog joystick and gamepad driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/gameport.h>
+#include <asm/timex.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Analog joystick and gamepad driver for Linux");
+MODULE_LICENSE("GPL");
+
+/*
+ * Option parsing.
+ */
+
+#define ANALOG_PORTS		16
+
+static char *js[ANALOG_PORTS];
+static int analog_options[ANALOG_PORTS];
+MODULE_PARM(js, "1-" __MODULE_STRING(ANALOG_PORTS) "s");
+MODULE_PARM_DESC(js, "Analog joystick options");
+
+/*
+ * Times, feature definitions.
+ */
+
+#define ANALOG_RUDDER		0x00004
+#define ANALOG_THROTTLE		0x00008
+#define ANALOG_AXES_STD		0x0000f
+#define ANALOG_BTNS_STD		0x000f0
+
+#define ANALOG_BTNS_CHF		0x00100
+#define ANALOG_HAT1_CHF		0x00200
+#define ANALOG_HAT2_CHF		0x00400
+#define ANALOG_HAT_FCS		0x00800
+#define ANALOG_HATS_ALL		0x00e00
+#define ANALOG_BTN_TL		0x01000
+#define ANALOG_BTN_TR		0x02000
+#define ANALOG_BTN_TL2		0x04000
+#define ANALOG_BTN_TR2		0x08000
+#define ANALOG_BTNS_TLR		0x03000
+#define ANALOG_BTNS_TLR2	0x0c000
+#define ANALOG_BTNS_GAMEPAD	0x0f000
+
+#define ANALOG_HBTN_CHF		0x10000
+#define ANALOG_ANY_CHF		0x10700
+#define ANALOG_SAITEK		0x20000
+#define ANALOG_EXTENSIONS	0x7ff00
+#define ANALOG_GAMEPAD		0x80000
+
+#define ANALOG_MAX_TIME		3	/* 3 ms */
+#define ANALOG_LOOP_TIME	2000	/* 2 * loop */
+#define ANALOG_REFRESH_TIME	HZ/100	/* 10 ms */
+#define ANALOG_SAITEK_DELAY	200	/* 200 us */
+#define ANALOG_SAITEK_TIME	2000	/* 2000 us */
+#define ANALOG_AXIS_TIME	2	/* 2 * refresh */
+#define ANALOG_INIT_RETRIES	8	/* 8 times */
+#define ANALOG_FUZZ_BITS	2	/* 2 bit more */
+#define ANALOG_FUZZ_MAGIC	36	/* 36 u*ms/loop */
+
+#define ANALOG_MAX_NAME_LENGTH  128
+
+static short analog_axes[] = { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE };
+static short analog_hats[] = { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
+static short analog_pads[] = { BTN_Y, BTN_Z, BTN_TL, BTN_TR };
+static short analog_exts[] = { ANALOG_HAT1_CHF, ANALOG_HAT2_CHF, ANALOG_HAT_FCS };
+static short analog_pad_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_TL2, BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_BASE };
+static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2,
+				  BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_BASE6 };
+
+static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
+
+struct analog {
+	struct input_dev dev;
+	int mask;
+	short *buttons;
+	char name[ANALOG_MAX_NAME_LENGTH];
+};
+
+struct analog_port {
+	struct gameport *gameport;
+	struct timer_list timer;
+	struct analog analog[2];
+	unsigned char mask;
+	char saitek;
+	char cooked;
+	int bads;
+	int reads;
+	int speed;
+	int loop;
+	int fuzz;
+	int axes[4];
+	int buttons;
+	int initial[4];
+	int used;
+	int axtime;
+};
+
+/*
+ * Time macros.
+ */
+
+#ifdef __i386__
+#define TSC_PRESENT	(test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability))
+#define GET_TIME(x)	do { if (TSC_PRESENT) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } } while (0)
+#define DELTA(x,y)	(TSC_PRESENT?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
+#define TIME_NAME	(TSC_PRESENT?"TSC":"PIT")
+#elif __x86_64__
+#define GET_TIME(x)	rdtscl(x)
+#define DELTA(x,y)	((y)-(x))
+#define TIME_NAME	"TSC"
+#elif __alpha__
+#define GET_TIME(x)	((x) = get_cycles())
+#define DELTA(x,y)	((y)-(x))
+#define TIME_NAME	"PCC"
+#else
+#define FAKE_TIME
+static unsigned long analog_faketime = 0;
+#define GET_TIME(x)     do { x = analog_faketime++; } while(0)
+#define DELTA(x,y)	((y)-(x))
+#define TIME_NAME	"Unreliable"
+#warning Precise timer not defined for this architecture.
+#endif
+
+/*
+ * analog_decode() decodes analog joystick data and reports input events.
+ */
+
+static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
+{
+	struct input_dev *dev = &analog->dev;
+	int i, j;
+
+	if (analog->mask & ANALOG_HAT_FCS)
+		for (i = 0; i < 4; i++)
+			if (axes[3] < ((initial[3] * ((i << 1) + 1)) >> 3)) {
+				buttons |= 1 << (i + 14);
+				break;
+			}
+
+	for (i = j = 0; i < 6; i++)
+		if (analog->mask & (0x10 << i))
+			input_report_key(dev, analog->buttons[j++], (buttons >> i) & 1);
+
+	if (analog->mask & ANALOG_HBTN_CHF)
+		for (i = 0; i < 4; i++)
+			input_report_key(dev, analog->buttons[j++], (buttons >> (i + 10)) & 1);
+
+	if (analog->mask & ANALOG_BTN_TL)
+		input_report_key(dev, analog_pads[0], axes[2] < (initial[2] >> 1));
+	if (analog->mask & ANALOG_BTN_TR)
+		input_report_key(dev, analog_pads[1], axes[3] < (initial[3] >> 1));
+	if (analog->mask & ANALOG_BTN_TL2)
+		input_report_key(dev, analog_pads[2], axes[2] > (initial[2] + (initial[2] >> 1)));
+	if (analog->mask & ANALOG_BTN_TR2)
+		input_report_key(dev, analog_pads[3], axes[3] > (initial[3] + (initial[3] >> 1)));
+
+	for (i = j = 0; i < 4; i++)
+		if (analog->mask & (1 << i))
+			input_report_abs(dev, analog_axes[j++], axes[i]);
+
+	for (i = j = 0; i < 3; i++)
+		if (analog->mask & analog_exts[i]) {
+			input_report_abs(dev, analog_hats[j++],
+				((buttons >> ((i << 2) + 7)) & 1) - ((buttons >> ((i << 2) + 9)) & 1));
+			input_report_abs(dev, analog_hats[j++],
+				((buttons >> ((i << 2) + 8)) & 1) - ((buttons >> ((i << 2) + 6)) & 1));
+		}
+}
+
+/*
+ * analog_cooked_read() reads analog joystick data.
+ */
+
+static int analog_cooked_read(struct analog_port *port)
+{
+	struct gameport *gameport = port->gameport;
+	unsigned int time[4], start, loop, now, loopout, timeout;
+	unsigned char data[4], this, last;
+	unsigned long flags;
+	int i, j;
+
+	loopout = (ANALOG_LOOP_TIME * port->loop) / 1000;
+	timeout = ANALOG_MAX_TIME * port->speed;
+	
+	__save_flags(flags);
+	__cli();
+	gameport_trigger(gameport);
+	GET_TIME(now);
+	__restore_flags(flags);
+
+	start = now;
+	this = port->mask;
+	i = 0;
+
+	do {
+		loop = now;
+		last = this;
+
+		__cli();
+		this = gameport_read(gameport) & port->mask;
+		GET_TIME(now);
+		__restore_flags(flags);
+
+		if ((last ^ this) && (DELTA(loop, now) < loopout)) {
+			data[i] = last ^ this;
+			time[i] = now;
+			i++;
+		}
+
+	} while (this && (i < 4) && (DELTA(start, now) < timeout));
+
+	this <<= 4;
+
+	for (--i; i >= 0; i--) {
+		this |= data[i];
+		for (j = 0; j < 4; j++)
+			if (data[i] & (1 << j))
+				port->axes[j] = (DELTA(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop;
+	}
+
+	return -(this != port->mask);
+}
+
+static int analog_button_read(struct analog_port *port, char saitek, char chf)
+{
+	unsigned char u;
+	int t = 1, i = 0;
+	int strobe = gameport_time(port->gameport, ANALOG_SAITEK_TIME);
+
+	u = gameport_read(port->gameport);
+
+	if (!chf) { 
+		port->buttons = (~u >> 4) & 0xf;
+		return 0;
+	}
+
+	port->buttons = 0;
+
+	while ((~u & 0xf0) && (i < 16) && t) {
+		port->buttons |= 1 << analog_chf[(~u >> 4) & 0xf];
+		if (!saitek) return 0;
+		udelay(ANALOG_SAITEK_DELAY);
+		t = strobe;
+		gameport_trigger(port->gameport);
+		while (((u = gameport_read(port->gameport)) & port->mask) && t) t--;
+		i++;
+	}
+
+	return -(!t || (i == 16));
+}
+
+/*
+ * analog_timer() repeatedly polls the Analog joysticks.
+ */
+
+static void analog_timer(unsigned long data)
+{
+	struct analog_port *port = (void *) data;
+	int i;
+
+	char saitek = !!(port->analog[0].mask & ANALOG_SAITEK);
+	char chf = !!(port->analog[0].mask & ANALOG_ANY_CHF);
+
+	if (port->cooked) {
+		port->bads -= gameport_cooked_read(port->gameport, port->axes, &port->buttons);
+		if (chf)
+			port->buttons = port->buttons ? (1 << analog_chf[port->buttons]) : 0;
+		port->reads++;
+	} else {
+		if (!port->axtime--) {
+			port->bads -= analog_cooked_read(port);
+			port->bads -= analog_button_read(port, saitek, chf);
+			port->reads++;
+			port->axtime = ANALOG_AXIS_TIME - 1;
+		} else {
+			if (!saitek)
+				analog_button_read(port, saitek, chf);
+		}
+	}
+
+	for (i = 0; i < 2; i++) 
+		if (port->analog[i].mask)
+			analog_decode(port->analog + i, port->axes, port->initial, port->buttons);
+
+	mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);
+}
+
+/*
+ * analog_open() is a callback from the input open routine.
+ */
+
+static int analog_open(struct input_dev *dev)
+{
+	struct analog_port *port = dev->private;
+	if (!port->used++)
+		mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);	
+	return 0;
+}
+
+/*
+ * analog_close() is a callback from the input close routine.
+ */
+
+static void analog_close(struct input_dev *dev)
+{
+	struct analog_port *port = dev->private;
+	if (!--port->used)
+		del_timer(&port->timer);
+}
+
+/*
+ * analog_calibrate_timer() calibrates the timer and computes loop
+ * and timeout values for a joystick port.
+ */
+
+static void analog_calibrate_timer(struct analog_port *port)
+{
+	struct gameport *gameport = port->gameport;
+	unsigned int i, t, tx, t1, t2, t3;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	GET_TIME(t1);
+#ifdef FAKE_TIME
+	analog_faketime += 830;
+#endif
+	udelay(1000);
+	GET_TIME(t2);
+	GET_TIME(t3);
+	restore_flags(flags);
+
+	port->speed = DELTA(t1, t2) - DELTA(t2, t3);
+
+	tx = ~0;
+
+	for (i = 0; i < 50; i++) {
+		save_flags(flags);
+		cli();
+		GET_TIME(t1);
+		for (t = 0; t < 50; t++) { gameport_read(gameport); GET_TIME(t2); }
+		GET_TIME(t3);
+		restore_flags(flags);
+		udelay(i);
+		t = DELTA(t1, t2) - DELTA(t2, t3);
+		if (t < tx) tx = t;
+	}
+
+        port->loop = tx / 50;
+}
+
+/*
+ * analog_name() constructs a name for an analog joystick.
+ */
+
+static void analog_name(struct analog *analog)
+{
+	sprintf(analog->name, "Analog %d-axis %d-button", 
+		hweight8(analog->mask & ANALOG_AXES_STD),
+		hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
+		hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
+
+	if (analog->mask & ANALOG_HATS_ALL)
+		sprintf(analog->name, "%s %d-hat",
+			analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));
+
+	if (analog->mask & ANALOG_HAT_FCS)
+			strcat(analog->name, " FCS");
+	if (analog->mask & ANALOG_ANY_CHF)
+			strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF");
+
+	strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick");
+}
+
+/*
+ * analog_init_device()
+ */
+
+static void analog_init_device(struct analog_port *port, struct analog *analog, int index)
+{
+	int i, j, t, v, w, x, y, z;
+
+	analog_name(analog);
+
+	analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
+
+	analog->dev.name = analog->name;
+	analog->dev.idbus = BUS_GAMEPORT;
+	analog->dev.idvendor = GAMEPORT_ID_VENDOR_ANALOG;
+	analog->dev.idproduct = analog->mask >> 4;
+	analog->dev.idversion = 0x0100;
+
+	analog->dev.open = analog_open;
+	analog->dev.close = analog_close;
+	analog->dev.private = port;
+	analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	
+	for (i = j = 0; i < 4; i++)
+		if (analog->mask & (1 << i)) {
+			
+			t = analog_axes[j];
+			x = port->axes[i];
+			y = (port->axes[0] + port->axes[1]) >> 1;
+			z = y - port->axes[i];
+			z = z > 0 ? z : -z;
+			v = (x >> 3);
+			w = (x >> 3);
+
+			set_bit(t, analog->dev.absbit);
+
+			if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
+				x = y;
+
+			if (analog->mask & ANALOG_SAITEK) {
+				if (i == 2) x = port->axes[i];
+				v = x - (x >> 2);
+				w = (x >> 4);
+			}
+
+			analog->dev.absmax[t] = (x << 1) - v;
+			analog->dev.absmin[t] = v;
+			analog->dev.absfuzz[t] = port->fuzz;
+			analog->dev.absflat[t] = w;
+
+			j++;
+		}
+
+	for (i = j = 0; i < 3; i++) 
+		if (analog->mask & analog_exts[i]) 
+			for (x = 0; x < 2; x++) {
+				t = analog_hats[j++];
+				set_bit(t, analog->dev.absbit);
+				analog->dev.absmax[t] = 1;
+				analog->dev.absmin[t] = -1;
+			}
+
+	for (i = j = 0; i < 4; i++)
+		if (analog->mask & (0x10 << i))
+			set_bit(analog->buttons[j++], analog->dev.keybit);
+
+	if (analog->mask & ANALOG_BTNS_CHF)
+		for (i = 0; i < 2; i++)
+			set_bit(analog->buttons[j++], analog->dev.keybit);
+
+	if (analog->mask & ANALOG_HBTN_CHF)
+		for (i = 0; i < 4; i++)
+			set_bit(analog->buttons[j++], analog->dev.keybit);
+
+	for (i = 0; i < 4; i++)
+		if (analog->mask & (ANALOG_BTN_TL << i))
+			set_bit(analog_pads[i], analog->dev.keybit);
+
+	analog_decode(analog, port->axes, port->initial, port->buttons);
+
+	input_register_device(&analog->dev);
+
+	printk(KERN_INFO "input%d: %s at gameport%d.%d",
+		analog->dev.number, analog->name, port->gameport->number, index);
+
+	if (port->cooked)
+		printk(" [ADC port]\n");
+	else
+		printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
+		port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
+		port->speed > 10000 ? "M" : "k",
+		port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
+				    : (port->loop * 1000000) / port->speed);
+}
+
+/*
+ * analog_init_devices() sets up device-specific values and registers the input devices.
+ */
+
+static int analog_init_masks(struct analog_port *port)
+{
+	int i;
+	struct analog *analog = port->analog;
+	int max[4];
+
+	if (!port->mask)
+		return -1;
+
+	if ((port->mask & 3) != 3 && port->mask != 0xc) {
+		printk(KERN_WARNING "analog.c: Unknown joystick device found  "
+			"(data=%#x, gameport%d), probably not analog joystick.\n",
+			port->mask, port->gameport->number);
+		return -1;
+	}
+
+	i = port->gameport->number < ANALOG_PORTS ? analog_options[port->gameport->number] : 0xff;
+
+	analog[0].mask = i & 0xfffff;
+
+	analog[0].mask &= ~(ANALOG_AXES_STD | ANALOG_HAT_FCS | ANALOG_BTNS_GAMEPAD)
+			| port->mask | ((port->mask << 8) & ANALOG_HAT_FCS)
+			| ((port->mask << 10) & ANALOG_BTNS_TLR) | ((port->mask << 12) & ANALOG_BTNS_TLR2);
+
+	analog[0].mask &= ~(ANALOG_HAT2_CHF)
+			| ((analog[0].mask & ANALOG_HBTN_CHF) ? 0 : ANALOG_HAT2_CHF);
+
+	analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_BTN_TR | ANALOG_BTN_TR2)
+			| ((~analog[0].mask & ANALOG_HAT_FCS) >> 8)
+			| ((~analog[0].mask & ANALOG_HAT_FCS) << 2)
+			| ((~analog[0].mask & ANALOG_HAT_FCS) << 4);
+
+	analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_RUDDER)
+			| (((~analog[0].mask & ANALOG_BTNS_TLR ) >> 10)
+			&  ((~analog[0].mask & ANALOG_BTNS_TLR2) >> 12));
+
+	analog[1].mask = ((i >> 20) & 0xff) | ((i >> 12) & 0xf0000);
+
+	analog[1].mask &= (analog[0].mask & ANALOG_EXTENSIONS) ? ANALOG_GAMEPAD
+			: (((ANALOG_BTNS_STD | port->mask) & ~analog[0].mask) | ANALOG_GAMEPAD);
+
+	if (port->cooked) {
+
+		for (i = 0; i < 4; i++) max[i] = port->axes[i] << 1;
+
+		if ((analog[0].mask & 0x7) == 0x7) max[2] = (max[0] + max[1]) >> 1;
+		if ((analog[0].mask & 0xb) == 0xb) max[3] = (max[0] + max[1]) >> 1;
+		if ((analog[0].mask & ANALOG_BTN_TL) && !(analog[0].mask & ANALOG_BTN_TL2)) max[2] >>= 1;
+		if ((analog[0].mask & ANALOG_BTN_TR) && !(analog[0].mask & ANALOG_BTN_TR2)) max[3] >>= 1;
+		if ((analog[0].mask & ANALOG_HAT_FCS)) max[3] >>= 1;
+
+		gameport_calibrate(port->gameport, port->axes, max);
+	}
+		
+	for (i = 0; i < 4; i++) 
+		port->initial[i] = port->axes[i];
+
+	return -!(analog[0].mask || analog[1].mask);	
+}
+
+static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, struct analog_port *port)
+{
+	int i, t, u, v;
+
+	gameport->private = port;
+	port->gameport = gameport;
+	init_timer(&port->timer);
+	port->timer.data = (long) port;
+	port->timer.function = analog_timer;
+
+	if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+
+		analog_calibrate_timer(port);
+
+		gameport_trigger(gameport);
+		t = gameport_read(gameport);
+		wait_ms(ANALOG_MAX_TIME);
+		port->mask = (gameport_read(gameport) ^ t) & t & 0xf;
+		port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;
+	
+		for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
+			if (!analog_cooked_read(port)) break;
+			wait_ms(ANALOG_MAX_TIME);
+		}
+
+		u = v = 0;
+
+		wait_ms(ANALOG_MAX_TIME);
+		t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
+		gameport_trigger(gameport);
+		while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++; 
+		udelay(ANALOG_SAITEK_DELAY);
+		t = gameport_time(gameport, ANALOG_SAITEK_TIME);
+		gameport_trigger(gameport);
+		while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++; 
+
+		if (v < (u >> 1) && port->gameport->number < ANALOG_PORTS) {
+			analog_options[port->gameport->number] |=
+				ANALOG_SAITEK | ANALOG_BTNS_CHF | ANALOG_HBTN_CHF | ANALOG_HAT1_CHF;
+			return 0;
+		}
+
+		gameport_close(gameport);
+	}
+
+	if (!gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
+
+		for (i = 0; i < ANALOG_INIT_RETRIES; i++)
+			if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
+				break;
+		for (i = 0; i < 4; i++)
+			if (port->axes[i] != -1) port->mask |= 1 << i;
+
+		port->fuzz = gameport->fuzz;
+		port->cooked = 1;
+		return 0;
+	}
+
+	if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		return 0;
+
+	return -1;
+}
+
+static void analog_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct analog_port *port;
+	int i;
+
+	if (!(port = kmalloc(sizeof(struct analog_port), GFP_KERNEL)))
+		return;
+	memset(port, 0, sizeof(struct analog_port));
+
+	if (analog_init_port(gameport, dev, port)) {
+		kfree(port);
+		return;
+	}
+
+	if (analog_init_masks(port)) {
+		gameport_close(gameport);
+		kfree(port);
+		return;
+	}
+
+	for (i = 0; i < 2; i++)
+		if (port->analog[i].mask)
+			analog_init_device(port, port->analog + i, i);
+}
+
+static void analog_disconnect(struct gameport *gameport)
+{
+	int i;
+
+	struct analog_port *port = gameport->private;
+	for (i = 0; i < 2; i++)
+		if (port->analog[i].mask)
+			input_unregister_device(&port->analog[i].dev);
+	gameport_close(gameport);
+	printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on gameport%d failed\n",
+		port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
+		port->gameport->number);
+	kfree(port);
+}
+
+struct analog_types {
+	char *name;
+	int value;
+};
+
+struct analog_types analog_types[] = {
+	{ "none",	0x00000000 },
+	{ "auto",	0x000000ff },
+	{ "2btn",	0x0000003f },
+	{ "y-joy",	0x0cc00033 },
+	{ "y-pad",	0x8cc80033 },
+	{ "fcs",	0x000008f7 },
+	{ "chf",	0x000002ff },
+	{ "fullchf",	0x000007ff },
+	{ "gamepad",	0x000830f3 },
+	{ "gamepad8",	0x0008f0f3 },
+	{ NULL, 0 }
+};
+
+static void analog_parse_options(void)
+{
+	int i, j;
+	char *end;
+
+	for (i = 0; i < ANALOG_PORTS && js[i]; i++) {
+
+		for (j = 0; analog_types[j].name; j++)
+			if (!strcmp(analog_types[j].name, js[i])) {
+				analog_options[i] = analog_types[j].value;
+				break;
+			} 
+		if (analog_types[j].name) continue;
+
+		analog_options[i] = simple_strtoul(js[i], &end, 0);
+		if (end != js[i]) continue;
+
+		analog_options[i] = 0xff;
+		if (!strlen(js[i])) continue;
+
+		printk(KERN_WARNING "analog.c: Bad config for port %d - \"%s\"\n", i, js[i]);
+	}
+
+	for (; i < ANALOG_PORTS; i++)
+		analog_options[i] = 0xff;
+}
+
+/*
+ * The gameport device structure.
+ */
+
+static struct gameport_dev analog_dev = {
+	connect:	analog_connect,
+	disconnect:	analog_disconnect,
+};
+
+#ifndef MODULE
+static int __init analog_setup(char *str)
+{
+	char *s = str;
+	int i = 0;
+
+	if (!str || !*str) return 0;
+
+	while ((str = s) && (i < ANALOG_PORTS)) {
+		if ((s = strchr(str,','))) *s++ = 0;
+		js[i++] = str;
+	}
+
+	return 1;
+}
+__setup("js=", analog_setup);
+#endif
+
+int __init analog_init(void)
+{
+	analog_parse_options();
+	gameport_register_device(&analog_dev);
+	return 0;
+}
+
+void __exit analog_exit(void)
+{
+	gameport_unregister_device(&analog_dev);
+}
+
+module_init(analog_init);
+module_exit(analog_exit);
diff -Nru a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/cobra.c	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,252 @@
+/*
+ * $Id: cobra.c,v 1.10 2000/06/08 10:23:45 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Creative Labd Blaster GamePad Cobra driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/input.h>
+
+#define COBRA_MAX_STROBE	45	/* 45 us max wait for first strobe */
+#define COBRA_REFRESH_TIME	HZ/50	/* 20 ms between reads */
+#define COBRA_LENGTH		36
+
+static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
+
+static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };
+
+struct cobra {
+	struct gameport *gameport;
+	struct timer_list timer;
+	struct input_dev dev[2];
+	int used;
+	int reads;
+	int bads;
+	unsigned char exists;
+};
+
+static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *data)
+{
+	unsigned long flags;
+	unsigned char u, v, w;
+	__u64 buf[2];
+	int r[2], t[2];
+	int i, j, ret;
+
+	int strobe = gameport_time(gameport, COBRA_MAX_STROBE);
+
+	for (i = 0; i < 2; i++) {
+		r[i] = buf[i] = 0;
+		t[i] = COBRA_MAX_STROBE;
+	}
+	
+	__save_flags(flags);
+	__cli();
+
+	u = gameport_read(gameport);
+
+	do {
+		t[0]--; t[1]--;
+		v = gameport_read(gameport);
+		for (i = 0, w = u ^ v; i < 2 && w; i++, w >>= 2)
+			if (w & 0x30) {
+				if ((w & 0x30) < 0x30 && r[i] < COBRA_LENGTH && t[i] > 0) {
+					buf[i] |= (__u64)((w >> 5) & 1) << r[i]++;
+					t[i] = strobe;
+					u = v;
+				} else t[i] = 0;
+			}
+	} while (t[0] > 0 || t[1] > 0);
+
+	__restore_flags(flags);
+
+	ret = 0;
+
+	for (i = 0; i < 2; i++) {
+
+		if (r[i] != COBRA_LENGTH) continue;
+
+		for (j = 0; j < COBRA_LENGTH && (buf[i] & 0x04104107f) ^ 0x041041040; j++)
+			buf[i] = (buf[i] >> 1) | ((__u64)(buf[i] & 1) << (COBRA_LENGTH - 1));
+
+		if (j < COBRA_LENGTH) ret |= (1 << i);
+
+		data[i] = ((buf[i] >>  7) & 0x000001f) | ((buf[i] >>  8) & 0x00003e0)
+			| ((buf[i] >>  9) & 0x0007c00) | ((buf[i] >> 10) & 0x00f8000)
+			| ((buf[i] >> 11) & 0x1f00000);
+
+	}
+
+	return ret;
+}
+
+static void cobra_timer(unsigned long private)
+{
+	struct cobra *cobra = (void *) private;
+	struct input_dev *dev;
+	unsigned int data[2];
+	int i, j, r;
+
+	cobra->reads++;
+
+	if ((r = cobra_read_packet(cobra->gameport, data)) != cobra->exists)
+		cobra->bads++;
+
+	for (i = 0; i < 2; i++)
+		if (cobra->exists & r & (1 << i)) {
+
+			dev = cobra->dev + i;
+
+			input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
+			input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
+
+			for (j = 0; cobra_btn[j]; j++)
+				input_report_key(dev, cobra_btn[j], data[i] & (0x20 << j));
+
+		}
+
+	mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);	
+}
+
+static int cobra_open(struct input_dev *dev)
+{
+	struct cobra *cobra = dev->private;
+	if (!cobra->used++)
+		mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);	
+	return 0;
+}
+
+static void cobra_close(struct input_dev *dev)
+{
+	struct cobra *cobra = dev->private;
+	if (!--cobra->used)
+		del_timer(&cobra->timer);
+}
+
+static void cobra_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct cobra *cobra;
+	unsigned int data[2];
+	int i, j;
+
+	if (!(cobra = kmalloc(sizeof(struct cobra), GFP_KERNEL)))
+		return;
+	memset(cobra, 0, sizeof(struct cobra));
+
+	gameport->private = cobra;
+
+	cobra->gameport = gameport;
+	init_timer(&cobra->timer);
+	cobra->timer.data = (long) cobra;
+	cobra->timer.function = cobra_timer;
+
+	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		goto fail1;
+
+	cobra->exists = cobra_read_packet(gameport, data);
+
+	for (i = 0; i < 2; i++) 
+		if ((cobra->exists >> i) & data[i] & 1) {
+			printk(KERN_WARNING "cobra.c: Device on gameport%d.%d has the Ext bit set. ID is: %d"
+				" Contact vojtech@suse.cz\n", gameport->number, i, (data[i] >> 2) & 7);
+			cobra->exists &= ~(1 << i);
+		}
+
+	if (!cobra->exists)
+		goto fail2;
+
+	for (i = 0; i < 2; i++)
+		if ((cobra->exists >> i) & 1) {
+
+			cobra->dev[i].private = cobra;
+			cobra->dev[i].open = cobra_open;
+			cobra->dev[i].close = cobra_close;
+
+			cobra->dev[i].name = cobra_name;
+			cobra->dev[i].idbus = BUS_GAMEPORT;
+			cobra->dev[i].idvendor = GAMEPORT_ID_VENDOR_CREATIVE;
+			cobra->dev[i].idproduct = 0x0008;
+			cobra->dev[i].idversion = 0x0100;
+		
+			cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+			cobra->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+
+			for (j = 0; cobra_btn[j]; j++)
+				set_bit(cobra_btn[j], cobra->dev[i].keybit);
+
+			cobra->dev[i].absmin[ABS_X] = -1; cobra->dev[i].absmax[ABS_X] = 1;
+			cobra->dev[i].absmin[ABS_Y] = -1; cobra->dev[i].absmax[ABS_Y] = 1;
+
+			input_register_device(cobra->dev + i);
+			printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
+				cobra->dev[i].number, cobra_name, gameport->number, i);
+		}
+
+
+	return;
+fail2:	gameport_close(gameport);
+fail1:	kfree(cobra);
+}
+
+static void cobra_disconnect(struct gameport *gameport)
+{
+	int i;
+
+	struct cobra *cobra = gameport->private;
+	for (i = 0; i < 2; i++)
+		if ((cobra->exists >> i) & 1)
+			input_unregister_device(cobra->dev + i);
+	gameport_close(gameport);
+	kfree(cobra);
+}
+
+static struct gameport_dev cobra_dev = {
+	connect:	cobra_connect,
+	disconnect:	cobra_disconnect,
+};
+
+int __init cobra_init(void)
+{
+	gameport_register_device(&cobra_dev);
+	return 0;
+}
+
+void __exit cobra_exit(void)
+{
+	gameport_unregister_device(&cobra_dev);
+}
+
+module_init(cobra_init);
+module_exit(cobra_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/db9.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,424 @@
+/*
+ * $Id: db9.c,v 1.6 2000/06/25 10:57:50 vojtech Exp $
+ *
+ *  Copyright (c) 1999 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *	Andree Borrmann		Mats Sjövall
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/parport.h>
+#include <linux/input.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_LICENSE("GPL");
+MODULE_PARM(db9, "2i");
+MODULE_PARM(db9_2, "2i");
+MODULE_PARM(db9_3, "2i");
+
+#define DB9_MULTI_STICK		0x01
+#define DB9_MULTI2_STICK	0x02
+#define DB9_GENESIS_PAD		0x03
+#define DB9_GENESIS5_PAD	0x05
+#define DB9_GENESIS6_PAD	0x06
+#define DB9_SATURN_PAD		0x07
+#define DB9_MULTI_0802		0x08
+#define DB9_MULTI_0802_2	0x09
+#define DB9_CD32_PAD		0x0A
+#define DB9_MAX_PAD		0x0B
+
+#define DB9_UP			0x01
+#define DB9_DOWN		0x02
+#define DB9_LEFT		0x04
+#define DB9_RIGHT		0x08
+#define DB9_FIRE1		0x10
+#define DB9_FIRE2		0x20
+#define DB9_FIRE3		0x40
+#define DB9_FIRE4		0x80
+
+#define DB9_NORMAL		0x0a
+#define DB9_NOSELECT		0x08
+
+#define DB9_SATURN0		0x00
+#define DB9_SATURN1		0x02
+#define DB9_SATURN2		0x04
+#define DB9_SATURN3		0x06
+
+#define DB9_GENESIS6_DELAY	14
+#define DB9_REFRESH_TIME	HZ/100
+
+static int db9[] __initdata = { -1, 0 };
+static int db9_2[] __initdata = { -1, 0 };
+static int db9_3[] __initdata = { -1, 0 };
+
+struct db9 {
+	struct input_dev dev[2];
+	struct timer_list timer;
+	struct pardevice *pd;	
+	int mode;
+	int used;
+};
+
+static struct db9 *db9_base[3];
+
+static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
+static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
+static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
+
+static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 8, 1, 1, 7 };
+static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
+					db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn };
+static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
+				      NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
+				     "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad" };
+
+static void db9_timer(unsigned long private)
+{
+	struct db9 *db9 = (void *) private;
+	struct parport *port = db9->pd->port;
+	struct input_dev *dev = db9->dev;
+	int data, i;
+
+	switch(db9->mode) {
+		case DB9_MULTI_0802_2:
+
+			data = parport_read_data(port) >> 3;
+
+			input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
+
+		case DB9_MULTI_0802:
+
+			data = parport_read_status(port) >> 3;
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
+			break;
+
+		case DB9_MULTI_STICK:
+
+			data = parport_read_data(port);
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
+			break;
+
+		case DB9_MULTI2_STICK:
+
+			data = parport_read_data(port);
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
+			input_report_key(dev, BTN_THUMB,   ~data & DB9_FIRE2);
+			break;
+
+		case DB9_GENESIS_PAD:
+
+			parport_write_control(port, DB9_NOSELECT);
+			data = parport_read_data(port);
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
+			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
+
+			parport_write_control(port, DB9_NORMAL);
+			data=parport_read_data(port);
+
+			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
+			input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
+			break;
+
+		case DB9_GENESIS5_PAD:
+
+			parport_write_control(port, DB9_NOSELECT);
+			data=parport_read_data(port);
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
+			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
+
+			parport_write_control(port, DB9_NORMAL);
+			data=parport_read_data(port);
+
+			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
+			input_report_key(dev, BTN_X,     ~data & DB9_FIRE2);
+			input_report_key(dev, BTN_Y,     ~data & DB9_LEFT);
+			input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
+			break;
+
+		case DB9_GENESIS6_PAD:
+
+			parport_write_control(port, DB9_NOSELECT); /* 1 */
+			udelay(DB9_GENESIS6_DELAY);
+			data=parport_read_data(port);
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
+			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
+
+			parport_write_control(port, DB9_NORMAL);
+			udelay(DB9_GENESIS6_DELAY);
+			data=parport_read_data(port);
+
+			input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
+			input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
+
+			parport_write_control(port, DB9_NOSELECT); /* 2 */
+			udelay(DB9_GENESIS6_DELAY);
+			parport_write_control(port, DB9_NORMAL);
+			udelay(DB9_GENESIS6_DELAY);
+			parport_write_control(port, DB9_NOSELECT); /* 3 */
+			udelay(DB9_GENESIS6_DELAY);
+			data=parport_read_data(port);
+
+			input_report_key(dev, BTN_Y,     ~data & DB9_LEFT);
+			input_report_key(dev, BTN_Z,     ~data & DB9_DOWN);
+			input_report_key(dev, BTN_MODE,  ~data & DB9_UP);
+			input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
+
+			parport_write_control(port, DB9_NORMAL);
+			udelay(DB9_GENESIS6_DELAY);
+			parport_write_control(port, DB9_NOSELECT); /* 4 */
+			udelay(DB9_GENESIS6_DELAY);
+			parport_write_control(port, DB9_NORMAL);
+			break;
+
+		case DB9_SATURN_PAD:
+
+			parport_write_control(port, DB9_SATURN0);
+			data = parport_read_data(port);
+
+			input_report_key(dev, BTN_Y,  ~data & DB9_LEFT);
+			input_report_key(dev, BTN_Z,  ~data & DB9_DOWN);
+			input_report_key(dev, BTN_TL, ~data & DB9_UP);
+			input_report_key(dev, BTN_TR, ~data & DB9_RIGHT);
+
+			parport_write_control(port, DB9_SATURN2);
+			data = parport_read_data(port);
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			
+			parport_write_control(port, DB9_NORMAL);
+			data = parport_read_data(port);
+
+			input_report_key(dev, BTN_A, ~data & DB9_LEFT);
+			input_report_key(dev, BTN_B, ~data & DB9_UP);
+			input_report_key(dev, BTN_C, ~data & DB9_DOWN);
+			input_report_key(dev, BTN_X, ~data & DB9_RIGHT);
+			break;
+
+		case DB9_CD32_PAD:
+
+			data=parport_read_data(port);
+
+			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+
+			parport_write_control(port, 0x0a); 
+
+			for (i = 0; i < 7; i++) { 
+				data = parport_read_data(port);
+				parport_write_control(port, 0x02); 
+				parport_write_control(port, 0x0a); 
+				input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
+				}
+
+			parport_write_control(port, 0x00); 
+			break;
+		}
+
+	mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
+}
+
+static int db9_open(struct input_dev *dev)
+{
+	struct db9 *db9 = dev->private;
+	struct parport *port = db9->pd->port;
+
+	if (!db9->used++) {
+		parport_claim(db9->pd);
+		parport_write_data(port, 0xff);
+		parport_data_reverse(port);
+		parport_write_control(port, DB9_NORMAL);
+		mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
+	}
+
+	return 0;
+}
+
+static void db9_close(struct input_dev *dev)
+{
+	struct db9 *db9 = dev->private;
+	struct parport *port = db9->pd->port;
+
+	if (!--db9->used) {
+		del_timer(&db9->timer);
+		parport_write_control(port, 0x00);
+		parport_data_forward(port);
+		parport_release(db9->pd);
+	}
+}
+
+static struct db9 __init *db9_probe(int *config)
+{
+	struct db9 *db9;
+	struct parport *pp;
+	int i, j;
+
+	if (config[0] < 0)
+		return NULL;
+	if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
+		printk(KERN_ERR "db9.c: bad config\n");
+		return NULL;
+	}
+
+	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
+		config[0]--;
+
+	if (!pp) {
+		printk(KERN_ERR "db9.c: no such parport\n");
+		return NULL;
+	}
+
+	if (!(pp->modes & PARPORT_MODE_TRISTATE) && config[1] != DB9_MULTI_0802) {
+		printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
+		return NULL;
+	}
+	
+	if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL)))
+		return NULL;
+	memset(db9, 0, sizeof(struct db9));
+
+	db9->mode = config[1];
+	init_timer(&db9->timer);
+	db9->timer.data = (long) db9;
+	db9->timer.function = db9_timer;
+
+	db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+
+	if (!db9->pd) {
+		printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
+		kfree(db9);
+		return NULL;
+	}
+
+	for (i = 0; i < 1 + (db9->mode == DB9_MULTI_0802_2); i++) {
+
+		db9->dev[i].private = db9;
+		db9->dev[i].open = db9_open;
+		db9->dev[i].close = db9_close;
+
+		db9->dev[i].name = db9_name[db9->mode];
+		db9->dev[i].idbus = BUS_PARPORT;
+		db9->dev[i].idvendor = 0x0002;
+		db9->dev[i].idproduct = config[1];
+		db9->dev[i].idversion = 0x0100;
+
+		db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		db9->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+
+		for (j = 0; j < db9_buttons[db9->mode]; j++)
+			set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit); 
+
+		db9->dev[i].absmin[ABS_X] = -1; db9->dev[i].absmax[ABS_X] = 1;
+		db9->dev[i].absmin[ABS_Y] = -1; db9->dev[i].absmax[ABS_Y] = 1;
+
+		input_register_device(db9->dev + i);
+		printk(KERN_INFO "input%d: %s on %s\n",
+			db9->dev[i].number, db9_name[db9->mode], db9->pd->port->name);
+	}
+
+	return db9;
+}
+
+#ifndef MODULE
+int __init db9_setup(char *str)
+{
+	int i, ints[3];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 2; i++) db9[i] = ints[i + 1];
+	return 1;
+}
+int __init db9_setup_2(char *str)
+{
+	int i, ints[3];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 2; i++) db9_2[i] = ints[i + 1];
+	return 1;
+}
+int __init db9_setup_3(char *str)
+{
+	int i, ints[3];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 2; i++) db9_3[i] = ints[i + 1];
+	return 1;
+}
+__setup("db9=", db9_setup);
+__setup("db9_2=", db9_setup_2);
+__setup("db9_3=", db9_setup_3);
+#endif
+
+int __init db9_init(void)
+{
+	db9_base[0] = db9_probe(db9);
+	db9_base[1] = db9_probe(db9_2);
+	db9_base[2] = db9_probe(db9_3);
+
+	if (db9_base[0] || db9_base[1] || db9_base[2])
+		return 0;
+
+	return -ENODEV;
+}
+
+void __exit db9_exit(void)
+{
+	int i, j;
+
+	for (i = 0; i < 3; i++) 
+		if (db9_base[i]) {
+			for (j = 0; j < 1 + (db9_base[i]->mode == DB9_MULTI_0802_2); j++)
+				input_unregister_device(db9_base[i]->dev + j);
+		parport_unregister_device(db9_base[i]->pd);
+	}
+}
+
+module_init(db9_init);
+module_exit(db9_exit);
diff -Nru a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/gamecon.c	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,670 @@
+/*
+ * $Id: gamecon.c,v 1.14 2001/04/29 22:42:14 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *  	Andree Borrmann		John Dahlstrom
+ *  	David Kuder		Nathan Hand
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * NES, SNES, N64, Multi1, Multi2, PSX gamepad driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/parport.h>
+#include <linux/input.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_LICENSE("GPL");
+MODULE_PARM(gc, "2-6i");
+MODULE_PARM(gc_2,"2-6i");
+MODULE_PARM(gc_3,"2-6i");
+
+#define GC_SNES		1
+#define GC_NES		2
+#define GC_NES4		3
+#define GC_MULTI	4
+#define GC_MULTI2	5
+#define GC_N64		6	
+#define GC_PSX		7
+
+#define GC_MAX		7
+
+#define GC_REFRESH_TIME	HZ/100
+ 
+struct gc {
+	struct pardevice *pd;
+	struct input_dev dev[5];
+	struct timer_list timer;
+	unsigned char pads[GC_MAX + 1];
+	int used;
+};
+
+static struct gc *gc_base[3];
+
+static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
+static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
+static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
+
+static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
+
+static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
+				"Multisystem 2-button joystick", "N64 controller", "PSX controller" };
+/*
+ * N64 support.
+ */
+
+static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 };
+static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START };
+
+#define GC_N64_LENGTH		32		/* N64 bit length, not including stop bit */
+#define GC_N64_REQUEST_LENGTH	37		/* transmit request sequence is 9 bits long */
+#define GC_N64_DELAY		133		/* delay between transmit request, and response ready (us) */
+#define GC_N64_REQUEST		0x1dd1111111ULL /* the request data command (encoded for 000000011) */
+#define GC_N64_DWS		3		/* delay between write segments (required for sound playback because of ISA DMA) */
+						/* GC_N64_DWS > 24 is known to fail */ 
+#define GC_N64_POWER_W		0xe2		/* power during write (transmit request) */
+#define GC_N64_POWER_R		0xfd		/* power during read */
+#define GC_N64_OUT		0x1d		/* output bits to the 4 pads */
+						/* Reading the main axes of any N64 pad is known to fail if the corresponding bit */
+						/* in GC_N64_OUT is pulled low on the output port (by any routine) for more */
+						/* than 123 us */
+#define GC_N64_CLOCK		0x02		/* clock bits for read */
+
+/* 
+ * gc_n64_read_packet() reads an N64 packet. 
+ * Each pad uses one bit per byte. So all pads connected to this port are read in parallel.
+ */
+
+static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
+{
+	int i;
+	unsigned long flags;
+
+/*
+ * Request the pad to transmit data
+ */
+
+	__save_flags(flags);
+	__cli();
+	for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) {
+		parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0));
+		udelay(GC_N64_DWS);
+	}
+	__restore_flags(flags);
+
+/*
+ * Wait for the pad response to be loaded into the 33-bit register of the adapter
+ */
+
+	udelay(GC_N64_DELAY);
+
+/*
+ * Grab data (ignoring the last bit, which is a stop bit)
+ */
+
+	for (i = 0; i < GC_N64_LENGTH; i++) {
+		parport_write_data(gc->pd->port, GC_N64_POWER_R);
+		data[i] = parport_read_status(gc->pd->port);
+		parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK);
+	 }
+
+/*
+ * We must wait 200 ms here for the controller to reinitialize before the next read request.
+ * No worries as long as gc_read is polled less frequently than this.
+ */
+
+}
+
+/*
+ * NES/SNES support.
+ */
+
+#define GC_NES_DELAY	6	/* Delay between bits - 6us */
+#define GC_NES_LENGTH	8	/* The NES pads use 8 bits of data */
+#define GC_SNES_LENGTH	12	/* The SNES true length is 16, but the last 4 bits are unused */
+
+#define GC_NES_POWER	0xfc
+#define GC_NES_CLOCK	0x01
+#define GC_NES_LATCH	0x02
+
+static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 };
+static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 };
+static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR };
+
+/*
+ * gc_nes_read_packet() reads a NES/SNES packet.
+ * Each pad uses one bit per byte. So all pads connected to
+ * this port are read in parallel.
+ */
+
+static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
+{
+	int i;
+
+	parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK | GC_NES_LATCH);
+	udelay(GC_NES_DELAY * 2);
+	parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
+
+	for (i = 0; i < length; i++) {
+		udelay(GC_NES_DELAY);
+		parport_write_data(gc->pd->port, GC_NES_POWER);
+		data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
+		udelay(GC_NES_DELAY);
+		parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
+	}
+}
+
+/*
+ * Multisystem joystick support
+ */
+
+#define GC_MULTI_LENGTH		5	/* Multi system joystick packet length is 5 */
+#define GC_MULTI2_LENGTH	6	/* One more bit for one more button */
+
+/*
+ * gc_multi_read_packet() reads a Multisystem joystick packet.
+ */
+
+static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
+{
+	int i;
+
+	for (i = 0; i < length; i++) {
+		parport_write_data(gc->pd->port, ~(1 << i));
+		data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
+	}
+}
+
+/*
+ * PSX support
+ *
+ * See documentation at:
+ *	http://www.dim.com/~mackys/psxmemcard/ps-eng2.txt
+ *	http://www.gamesx.com/controldata/psxcont/psxcont.htm
+ *	ftp://milano.usal.es/pablo/
+ *	
+ */
+
+#define GC_PSX_DELAY	60		/* 60 usec */
+#define GC_PSX_LENGTH	8		/* talk to the controller in bytes */
+
+#define GC_PSX_MOUSE	1		/* Mouse */
+#define GC_PSX_NEGCON	2		/* NegCon */
+#define GC_PSX_NORMAL	4		/* Digital / Analog or Rumble in Digital mode  */
+#define GC_PSX_ANALOG	5		/* Analog in Analog mode / Rumble in Green mode */
+#define GC_PSX_RUMBLE	7		/* Rumble in Red mode */
+
+#define GC_PSX_CLOCK	0x04		/* Pin 4 */
+#define GC_PSX_COMMAND	0x01		/* Pin 1 */
+#define GC_PSX_POWER	0xf8		/* Pins 5-9 */
+#define GC_PSX_SELECT	0x02		/* Pin 3 */
+
+#define GC_PSX_ID(x)	((x) >> 4)	/* High nibble is device type */
+#define GC_PSX_LEN(x)	((x) & 0xf)	/* Low nibble is length in words */
+
+static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
+static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
+				BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
+
+/*
+ * gc_psx_command() writes 8bit command and reads 8bit data from
+ * the psx pad.
+ */
+
+static int gc_psx_command(struct gc *gc, int b)
+{
+	int i, cmd, data = 0;
+
+	for (i = 0; i < 8; i++, b >>= 1) {
+		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
+		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
+		udelay(GC_PSX_DELAY);
+		data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
+		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
+		udelay(GC_PSX_DELAY);
+	}
+	return data;
+}
+
+/*
+ * gc_psx_read_packet() reads a whole psx packet and returns
+ * device identifier code.
+ */
+
+static int gc_psx_read_packet(struct gc *gc, unsigned char *data)
+{
+	int i, id;
+	unsigned long flags;
+
+	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
+	udelay(GC_PSX_DELAY * 2);
+	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);			/* Deselect, begin command */
+	udelay(GC_PSX_DELAY * 2);
+
+	__save_flags(flags);
+	__cli();
+
+	gc_psx_command(gc, 0x01);							/* Access pad */
+	id = gc_psx_command(gc, 0x42);							/* Get device id */
+	if (gc_psx_command(gc, 0) == 0x5a) {						/* Okay? */
+		for (i = 0; i < GC_PSX_LEN(id) * 2; i++)
+			data[i] = gc_psx_command(gc, 0);
+	} else id = 0;
+
+	__restore_flags(flags);
+
+	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
+
+	return GC_PSX_ID(id);
+}
+
+/*
+ * gc_timer() reads and analyzes console pads data.
+ */
+
+#define GC_MAX_LENGTH GC_N64_LENGTH
+
+static void gc_timer(unsigned long private)
+{
+	struct gc *gc = (void *) private;
+	struct input_dev *dev = gc->dev;
+	unsigned char data[GC_MAX_LENGTH];
+	int i, j, s;
+
+/*
+ * N64 pads - must be read first, any read confuses them for 200 us
+ */
+
+	if (gc->pads[GC_N64]) {
+
+		gc_n64_read_packet(gc, data);
+
+		for (i = 0; i < 5; i++) {
+
+			s = gc_status_bit[i];
+
+			if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
+	
+				signed char axes[2];
+				axes[0] = axes[1] = 0;
+
+				for (j = 0; j < 8; j++) {
+					if (data[23 - j] & s) axes[0] |= 1 << j; 
+					if (data[31 - j] & s) axes[1] |= 1 << j; 
+				}
+
+				input_report_abs(dev + i, ABS_X,  axes[0]);
+				input_report_abs(dev + i, ABS_Y, -axes[1]);
+
+				input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
+				input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
+
+				for (j = 0; j < 10; j++)
+					input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
+			}
+		}
+	}
+
+/*
+ * NES and SNES pads
+ */
+
+	if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {
+
+		gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
+
+		for (i = 0; i < 5; i++) {
+
+			s = gc_status_bit[i];
+
+			if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
+				input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
+				input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
+			}
+
+			if (s & gc->pads[GC_NES])
+				for (j = 0; j < 4; j++)
+					input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
+
+			if (s & gc->pads[GC_SNES])
+				for (j = 0; j < 8; j++)
+					input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+		}
+	}
+
+/*
+ * Multi and Multi2 joysticks
+ */
+
+	if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {
+
+		gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
+
+		for (i = 0; i < 5; i++) {
+
+			s = gc_status_bit[i];
+
+			if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
+				input_report_abs(dev + i, ABS_X,  !(s & data[2]) - !(s & data[3]));
+				input_report_abs(dev + i, ABS_Y,  !(s & data[0]) - !(s & data[1]));
+				input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
+			}
+
+			if (s & gc->pads[GC_MULTI2])
+				input_report_key(dev + i, BTN_THUMB, s & data[5]);
+		}
+	}
+
+/*
+ * PSX controllers
+ */
+
+	if (gc->pads[GC_PSX]) {
+
+		for (i = 0; i < 5; i++)
+	       		if (gc->pads[GC_PSX] & gc_status_bit[i])
+				break;
+
+ 		switch (gc_psx_read_packet(gc, data)) {
+
+			case GC_PSX_RUMBLE:
+
+				input_report_key(dev + i, BTN_THUMB,  ~data[0] & 0x04);
+				input_report_key(dev + i, BTN_THUMB2, ~data[0] & 0x02);
+
+			case GC_PSX_NEGCON:
+			case GC_PSX_ANALOG:
+
+				for (j = 0; j < 4; j++)
+					input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]);
+
+				input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80));
+				input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10));
+
+				for (j = 0; j < 8; j++)
+					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+
+				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
+				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+
+				break;
+
+			case GC_PSX_NORMAL:
+
+				input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128);
+				input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128);
+
+				for (j = 0; j < 8; j++)
+					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+
+				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
+				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+
+				break;
+		}
+	}
+
+	mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
+}
+
+static int gc_open(struct input_dev *dev)
+{
+	struct gc *gc = dev->private;
+	if (!gc->used++) {
+		parport_claim(gc->pd);
+		parport_write_control(gc->pd->port, 0x04);
+		mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
+	}
+	return 0;
+}
+
+static void gc_close(struct input_dev *dev)
+{
+	struct gc *gc = dev->private;
+	if (!--gc->used) {
+		del_timer(&gc->timer);
+		parport_write_control(gc->pd->port, 0x00);
+		parport_release(gc->pd);
+	}
+}
+
+static struct gc __init *gc_probe(int *config)
+{
+	struct gc *gc;
+	struct parport *pp;
+	int i, j, psx;
+	unsigned char data[32];
+
+	if (config[0] < 0)
+		return NULL;
+
+	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
+		config[0]--;
+
+	if (!pp) {
+		printk(KERN_ERR "gamecon.c: no such parport\n");
+		return NULL;
+	}
+
+	if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL)))
+		return NULL;
+	memset(gc, 0, sizeof(struct gc));
+
+	gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+
+	if (!gc->pd) {
+		printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
+		kfree(gc);
+		return NULL;
+	}
+
+	parport_claim(gc->pd);
+
+	init_timer(&gc->timer);
+	gc->timer.data = (long) gc;
+	gc->timer.function = gc_timer;
+
+	for (i = 0; i < 5; i++) {
+
+		if (!config[i + 1])
+			continue;
+
+		if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
+			printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
+			continue;
+		}
+
+                gc->dev[i].private = gc;
+                gc->dev[i].open = gc_open;
+                gc->dev[i].close = gc_close;
+
+                gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+		for (j = 0; j < 2; j++) {
+			set_bit(ABS_X + j, gc->dev[i].absbit);
+			gc->dev[i].absmin[ABS_X + j] = -1;
+			gc->dev[i].absmax[ABS_X + j] =  1;
+		}
+
+		gc->pads[0] |= gc_status_bit[i];
+		gc->pads[config[i + 1]] |= gc_status_bit[i];
+
+		switch(config[i + 1]) {
+
+			case GC_N64:
+				for (j = 0; j < 10; j++)
+					set_bit(gc_n64_btn[j], gc->dev[i].keybit);
+
+				for (j = 0; j < 2; j++) {
+					set_bit(ABS_X + j, gc->dev[i].absbit);
+					gc->dev[i].absmin[ABS_X + j] = -127;
+					gc->dev[i].absmax[ABS_X + j] =  126;
+					gc->dev[i].absflat[ABS_X + j] = 2;
+					set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
+					gc->dev[i].absmin[ABS_HAT0X + j] = -1;
+					gc->dev[i].absmax[ABS_HAT0X + j] =  1;
+				}
+
+				break;
+
+			case GC_SNES:
+				for (j = 4; j < 8; j++)
+					set_bit(gc_snes_btn[j], gc->dev[i].keybit);
+			case GC_NES:
+				for (j = 0; j < 4; j++)
+					set_bit(gc_snes_btn[j], gc->dev[i].keybit);
+				break;
+
+			case GC_MULTI2:
+				set_bit(BTN_THUMB, gc->dev[i].keybit);
+			case GC_MULTI:
+				set_bit(BTN_TRIGGER, gc->dev[i].keybit);
+				break;
+
+			case GC_PSX:
+				
+				psx = gc_psx_read_packet(gc, data);
+
+				switch(psx) {
+					case GC_PSX_NEGCON:
+					case GC_PSX_NORMAL:
+					case GC_PSX_ANALOG:
+					case GC_PSX_RUMBLE:
+
+						for (j = 0; j < 6; j++) {
+							psx = gc_psx_abs[j];
+							set_bit(psx, gc->dev[i].absbit);
+							if (j < 4) {
+								gc->dev[i].absmin[psx] = 4;
+								gc->dev[i].absmax[psx] = 252;
+								gc->dev[i].absflat[psx] = 2;
+							} else {
+								gc->dev[i].absmin[psx] = -1;
+								gc->dev[i].absmax[psx] = 1;
+							}
+						}
+
+						for (j = 0; j < 12; j++)
+							set_bit(gc_psx_btn[j], gc->dev[i].keybit);
+
+						break;
+
+					case 0:
+						gc->pads[GC_PSX] &= ~gc_status_bit[i];
+						printk(KERN_ERR "gamecon.c: No PSX controller found.\n");
+						break;
+
+					default:
+						gc->pads[GC_PSX] &= ~gc_status_bit[i];
+						printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
+							" please report to <vojtech@suse.cz>.\n", psx);
+				}
+				break;
+		}
+
+                gc->dev[i].name = gc_names[config[i + 1]];
+                gc->dev[i].idbus = BUS_PARPORT;
+                gc->dev[i].idvendor = 0x0001;
+                gc->dev[i].idproduct = config[i + 1];
+                gc->dev[i].idversion = 0x0100;
+	}
+
+	parport_release(gc->pd);
+
+	if (!gc->pads[0]) {
+		parport_unregister_device(gc->pd);
+		kfree(gc);
+		return NULL;
+	}
+
+	for (i = 0; i < 5; i++) 
+		if (gc->pads[0] & gc_status_bit[i]) {
+			input_register_device(gc->dev + i);
+			printk(KERN_INFO "input%d: %s on %s\n", gc->dev[i].number, gc->dev[i].name, gc->pd->port->name);
+		}
+
+	return gc;
+}
+
+#ifndef MODULE
+int __init gc_setup(char *str)
+{
+	int i, ints[7];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 6; i++) gc[i] = ints[i + 1];
+	return 1;
+}
+int __init gc_setup_2(char *str)
+{
+	int i, ints[7];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 6; i++) gc_2[i] = ints[i + 1];
+	return 1;
+}
+int __init gc_setup_3(char *str)
+{
+	int i, ints[7];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 6; i++) gc_3[i] = ints[i + 1];
+	return 1;
+}
+__setup("gc=", gc_setup);
+__setup("gc_2=", gc_setup_2);
+__setup("gc_3=", gc_setup_3);
+#endif
+
+int __init gc_init(void)
+{
+	gc_base[0] = gc_probe(gc);
+	gc_base[1] = gc_probe(gc_2);
+	gc_base[2] = gc_probe(gc_3);
+
+	if (gc_base[0] || gc_base[1] || gc_base[2])
+		return 0;
+
+	return -ENODEV;
+}
+
+void __exit gc_exit(void)
+{
+	int i, j;
+
+	for (i = 0; i < 3; i++)
+		if (gc_base[i]) {
+			for (j = 0; j < 5; j++)
+				if (gc_base[i]->pads[0] & gc_status_bit[j])
+					input_unregister_device(gc_base[i]->dev + j); 
+			parport_unregister_device(gc_base[i]->pd);
+		}
+}
+
+module_init(gc_init);
+module_exit(gc_exit);
diff -Nru a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/gf2k.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,361 @@
+/*
+ * $Id: gf2k.c,v 1.12 2000/06/04 14:53:44 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Genius Flight 2000 joystick driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/gameport.h>
+
+#define GF2K_START		400	/* The time we wait for the first bit [400 us] */
+#define GF2K_STROBE		40	/* The time we wait for the first bit [40 us] */
+#define GF2K_TIMEOUT		4	/* Wait for everything to settle [4 ms] */
+#define GF2K_LENGTH		80	/* Max number of triplets in a packet */
+#define GF2K_REFRESH		HZ/50	/* Time between joystick polls [20 ms] */
+
+/*
+ * Genius joystick ids ...
+ */
+
+#define GF2K_ID_G09		1
+#define GF2K_ID_F30D		2
+#define GF2K_ID_F30		3
+#define GF2K_ID_F31D		4
+#define GF2K_ID_F305		5
+#define GF2K_ID_F23P		6
+#define GF2K_ID_F31		7
+#define GF2K_ID_MAX		7
+
+static char gf2k_length[] = { 40, 40, 40, 40, 40, 40, 40, 40 };
+static char gf2k_hat_to_axis[][2] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+static char *gf2k_names[] = {"", "Genius G-09D", "Genius F-30D", "Genius F-30", "Genius MaxFighter F-31D",
+				"Genius F-30-5", "Genius Flight2000 F-23", "Genius F-31"};
+static unsigned char gf2k_hats[] = { 0, 2, 0, 0, 2, 0, 2, 0 };
+static unsigned char gf2k_axes[] = { 0, 2, 0, 0, 4, 0, 4, 0 };
+static unsigned char gf2k_joys[] = { 0, 0, 0, 0,10, 0, 8, 0 };
+static unsigned char gf2k_pads[] = { 0, 6, 0, 0, 0, 0, 0, 0 };
+static unsigned char gf2k_lens[] = { 0,18, 0, 0,18, 0,18, 0 };
+
+static unsigned char gf2k_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_GAS, ABS_BRAKE };
+static short gf2k_btn_joy[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 };
+static short gf2k_btn_pad[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_START, BTN_SELECT };
+
+
+static short gf2k_seq_reset[] = { 240, 340, 0 };
+static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
+
+struct gf2k {
+	struct gameport *gameport;
+	struct timer_list timer;
+	struct input_dev dev;
+	int reads;
+	int bads;
+	int used;
+	unsigned char id;
+	unsigned char length;
+};
+
+/*
+ * gf2k_read_packet() reads a Genius Flight2000 packet.
+ */
+
+static int gf2k_read_packet(struct gameport *gameport, int length, char *data)
+{
+	unsigned char u, v;
+	int i;
+	unsigned int t, p;
+	unsigned long flags;
+
+	t = gameport_time(gameport, GF2K_START);
+	p = gameport_time(gameport, GF2K_STROBE);
+
+	i = 0;
+
+	__save_flags(flags);
+	__cli();
+
+	gameport_trigger(gameport);
+	v = gameport_read(gameport);;
+
+	while (t > 0 && i < length) {
+		t--; u = v;
+		v = gameport_read(gameport);
+		if (v & ~u & 0x10) {
+			data[i++] = v >> 5;
+			t = p;
+		}
+	}
+
+	__restore_flags(flags);
+
+	return i;
+}
+
+/*
+ * gf2k_trigger_seq() initializes a Genius Flight2000 joystick
+ * into digital mode.
+ */
+
+static void gf2k_trigger_seq(struct gameport *gameport, short *seq)
+{
+
+	unsigned long flags;
+	int i, t;
+
+        __save_flags(flags);
+        __cli();
+
+	i = 0;
+        do {
+		gameport_trigger(gameport);
+		t = gameport_time(gameport, GF2K_TIMEOUT * 1000);
+		while ((gameport_read(gameport) & 1) && t) t--;
+                udelay(seq[i]);
+        } while (seq[++i]);
+
+	gameport_trigger(gameport);
+
+	__restore_flags(flags);
+}
+
+/*
+ * js_sw_get_bits() composes bits from the triplet buffer into a __u64.
+ * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
+ * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
+ * is number of bits per triplet.
+ */
+
+#define GB(p,n,s)	gf2k_get_bits(data, p, n, s)
+
+static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
+{
+	__u64 data = 0;
+	int i;
+
+	for (i = 0; i < num / 3 + 2; i++)
+		data |= buf[pos / 3 + i] << (i * 3);
+	data >>= pos % 3;
+	data &= (1 << num) - 1;
+	data <<= shift;
+
+	return data;
+}
+
+static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
+{
+	struct input_dev *dev = &gf2k->dev;
+	int i, t;
+
+	for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
+		input_report_abs(dev, gf2k_abs[i], GB(i<<3,8,0) | GB(i+46,1,8) | GB(i+50,1,9));
+
+	for (i = 0; i < 2 && i < gf2k_axes[gf2k->id] - 4; i++)
+		input_report_abs(dev, gf2k_abs[i], GB(i*9+60,8,0) | GB(i+54,1,9));
+
+	t = GB(40,4,0);
+
+	for (i = 0; i < gf2k_hats[gf2k->id]; i++)
+		input_report_abs(dev, ABS_HAT0X + i, gf2k_hat_to_axis[t][i]);
+
+	t = GB(44,2,0) | GB(32,8,2) | GB(78,2,10);
+
+	for (i = 0; i < gf2k_joys[gf2k->id]; i++)
+		input_report_key(dev, gf2k_btn_joy[i], (t >> i) & 1);
+
+	for (i = 0; i < gf2k_pads[gf2k->id]; i++)
+		input_report_key(dev, gf2k_btn_pad[i], (t >> i) & 1);
+}
+
+/*
+ * gf2k_timer() reads and analyzes Genius joystick data.
+ */
+
+static void gf2k_timer(unsigned long private)
+{
+	struct gf2k *gf2k = (void *) private;
+	unsigned char data[GF2K_LENGTH];
+
+	gf2k->reads++;
+
+	if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id]) {
+		gf2k->bads++;
+	} else gf2k_read(gf2k, data);
+
+	mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);
+}
+
+static int gf2k_open(struct input_dev *dev)
+{
+	struct gf2k *gf2k = dev->private;
+	if (!gf2k->used++)
+		mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);	
+	return 0;
+}
+
+static void gf2k_close(struct input_dev *dev)
+{
+	struct gf2k *gf2k = dev->private;
+	if (!--gf2k->used)
+		del_timer(&gf2k->timer);
+}
+
+/*
+ * gf2k_connect() probes for Genius id joysticks.
+ */
+
+static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct gf2k *gf2k;
+	unsigned char data[GF2K_LENGTH];
+	int i;
+
+	if (!(gf2k = kmalloc(sizeof(struct gf2k), GFP_KERNEL)))
+		return;
+	memset(gf2k, 0, sizeof(struct gf2k));
+
+	gameport->private = gf2k;
+
+	gf2k->gameport = gameport;
+	init_timer(&gf2k->timer);
+	gf2k->timer.data = (long) gf2k;
+	gf2k->timer.function = gf2k_timer;
+
+	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		goto fail1;
+
+	gf2k_trigger_seq(gameport, gf2k_seq_reset);
+
+	wait_ms(GF2K_TIMEOUT);
+
+	gf2k_trigger_seq(gameport, gf2k_seq_digital);
+
+	wait_ms(GF2K_TIMEOUT);
+
+	if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12)
+		goto fail2;
+
+	if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5)))
+		goto fail2;
+
+#ifdef RESET_WORKS
+	if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
+	    (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5))))
+		goto fail2;
+#else
+	gf2k->id = 6;
+#endif
+
+	if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
+		printk(KERN_WARNING "gf2k.c: Not yet supported joystick on gameport%d. [id: %d type:%s]\n",
+			gameport->number, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
+		goto fail2;
+	}
+
+	gf2k->length = gf2k_lens[gf2k->id];
+
+	gf2k->dev.private = gf2k;
+	gf2k->dev.open = gf2k_open;
+	gf2k->dev.close = gf2k_close;
+	gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	gf2k->dev.name = gf2k_names[gf2k->id];
+	gf2k->dev.idbus = BUS_GAMEPORT;
+	gf2k->dev.idvendor = GAMEPORT_ID_VENDOR_GENIUS;
+	gf2k->dev.idproduct = gf2k->id;
+	gf2k->dev.idversion = 0x0100;
+
+	for (i = 0; i < gf2k_axes[gf2k->id]; i++)
+		set_bit(gf2k_abs[i], gf2k->dev.absbit);
+
+	for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
+		set_bit(ABS_HAT0X + i, gf2k->dev.absbit);
+		gf2k->dev.absmin[ABS_HAT0X + i] = -1;
+		gf2k->dev.absmax[ABS_HAT0X + i] = 1;
+	}
+
+	for (i = 0; i < gf2k_joys[gf2k->id]; i++)
+		set_bit(gf2k_btn_joy[i], gf2k->dev.keybit);
+
+	for (i = 0; i < gf2k_pads[gf2k->id]; i++)
+		set_bit(gf2k_btn_pad[i], gf2k->dev.keybit);
+
+	gf2k_read_packet(gameport, gf2k->length, data);
+	gf2k_read(gf2k, data);
+
+	for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
+		gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
+	      		  gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; 
+		gf2k->dev.absmin[gf2k_abs[i]] = 32;
+		gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
+		gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
+	}
+
+	input_register_device(&gf2k->dev);
+	printk(KERN_INFO "input%d: %s on gameport%d.0\n",
+		gf2k->dev.number, gf2k_names[gf2k->id], gameport->number);
+
+	return;
+fail2:	gameport_close(gameport);
+fail1:	kfree(gf2k);
+}
+
+static void gf2k_disconnect(struct gameport *gameport)
+{
+	struct gf2k *gf2k = gameport->private;
+	input_unregister_device(&gf2k->dev);
+	gameport_close(gameport);
+	kfree(gf2k);
+}
+
+static struct gameport_dev gf2k_dev = {
+	connect:	gf2k_connect,
+	disconnect:	gf2k_disconnect,
+};
+
+int __init gf2k_init(void)
+{
+	gameport_register_device(&gf2k_dev);
+	return 0;
+}
+
+void __exit gf2k_exit(void)
+{
+	gameport_unregister_device(&gf2k_dev);
+}
+
+module_init(gf2k_init);
+module_exit(gf2k_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/grip.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,425 @@
+/*
+ * $Id: grip.c,v 1.14 2000/06/06 21:13:36 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Gravis/Kensington GrIP protocol joystick and gamepad driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gameport.h>
+#include <linux/input.h>
+
+#define GRIP_MODE_GPP		1
+#define GRIP_MODE_BD		2
+#define GRIP_MODE_XT		3
+#define GRIP_MODE_DC		4
+
+#define GRIP_LENGTH_GPP		24
+#define GRIP_STROBE_GPP		200	/* 200 us */
+#define GRIP_LENGTH_XT		4
+#define GRIP_STROBE_XT		64	/* 64 us */
+#define GRIP_MAX_CHUNKS_XT	10	
+#define GRIP_MAX_BITS_XT	30	
+
+#define GRIP_REFRESH_TIME	HZ/50	/* 20 ms */
+
+struct grip {
+	struct gameport *gameport;
+	struct timer_list timer;
+	struct input_dev dev[2];
+	unsigned char mode[2];
+	int used;
+	int reads;
+	int bads;
+};
+
+static int grip_btn_gpp[] = { BTN_START, BTN_SELECT, BTN_TR2, BTN_Y, 0, BTN_TL2, BTN_A, BTN_B, BTN_X, 0, BTN_TL, BTN_TR, -1 };
+static int grip_btn_bd[] = { BTN_THUMB, BTN_THUMB2, BTN_TRIGGER, BTN_TOP, BTN_BASE, -1 };
+static int grip_btn_xt[] = { BTN_TRIGGER, BTN_THUMB, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_SELECT, BTN_START, BTN_MODE, -1 };
+static int grip_btn_dc[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, -1 };
+
+static int grip_abs_gpp[] = { ABS_X, ABS_Y, -1 };
+static int grip_abs_bd[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
+static int grip_abs_xt[] = { ABS_X, ABS_Y, ABS_BRAKE, ABS_GAS, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, -1 };
+static int grip_abs_dc[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
+
+static char *grip_name[] = { NULL, "Gravis GamePad Pro", "Gravis Blackhawk Digital",
+				"Gravis Xterminator Digital", "Gravis Xterminator DualControl" };
+static int *grip_abs[] = { 0, grip_abs_gpp, grip_abs_bd, grip_abs_xt, grip_abs_dc };
+static int *grip_btn[] = { 0, grip_btn_gpp, grip_btn_bd, grip_btn_xt, grip_btn_dc };
+static char grip_anx[] = { 0, 0, 3, 5, 5 };
+static char grip_cen[] = { 0, 0, 2, 2, 4 };
+
+/*
+ * grip_gpp_read_packet() reads a Gravis GamePad Pro packet.
+ */
+
+static int grip_gpp_read_packet(struct gameport *gameport, int shift, unsigned int *data)
+{
+	unsigned long flags;
+	unsigned char u, v;
+	unsigned int t;
+	int i;
+
+	int strobe = gameport_time(gameport, GRIP_STROBE_GPP);
+
+	data[0] = 0;
+	t = strobe;
+	i = 0;
+
+	__save_flags(flags);
+	__cli();
+
+	v = gameport_read(gameport) >> shift;
+
+	do {
+		t--;
+		u = v; v = (gameport_read(gameport) >> shift) & 3;
+		if (~v & u & 1) {
+			data[0] |= (v >> 1) << i++;
+			t = strobe;
+		}
+	} while (i < GRIP_LENGTH_GPP && t > 0);
+
+	__restore_flags(flags);
+
+	if (i < GRIP_LENGTH_GPP) return -1;
+
+	for (i = 0; i < GRIP_LENGTH_GPP && (data[0] & 0xfe4210) ^ 0x7c0000; i++)
+		data[0] = data[0] >> 1 | (data[0] & 1) << (GRIP_LENGTH_GPP - 1);
+
+	return -(i == GRIP_LENGTH_GPP);
+}
+
+/*
+ * grip_xt_read_packet() reads a Gravis Xterminator packet.
+ */
+
+static int grip_xt_read_packet(struct gameport *gameport, int shift, unsigned int *data)
+{
+	unsigned int i, j, buf, crc;
+	unsigned char u, v, w;
+	unsigned long flags;
+	unsigned int t;
+	char status;
+
+	int strobe = gameport_time(gameport, GRIP_STROBE_XT);
+
+	data[0] = data[1] = data[2] = data[3] = 0;
+	status = buf = i = j = 0;
+	t = strobe;
+
+	__save_flags(flags);
+	__cli();
+
+	v = w = (gameport_read(gameport) >> shift) & 3;
+
+	do {
+		t--;
+		u = (gameport_read(gameport) >> shift) & 3;
+
+		if (u ^ v) {
+
+			if ((u ^ v) & 1) {
+				buf = (buf << 1) | (u >> 1);
+				t = strobe;
+				i++;
+			} else 
+
+			if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) {
+				if (i == 20) {
+					crc = buf ^ (buf >> 7) ^ (buf >> 14);
+					if (!((crc ^ (0x25cb9e70 >> ((crc >> 2) & 0x1c))) & 0xf)) {
+						data[buf >> 18] = buf >> 4;
+						status |= 1 << (buf >> 18);
+					}
+					j++;
+				}
+				t = strobe;
+				buf = 0;
+				i = 0;
+			}
+			w = v;
+			v = u;
+		}
+
+	} while (status != 0xf && i < GRIP_MAX_BITS_XT && j < GRIP_MAX_CHUNKS_XT && t > 0);
+
+	__restore_flags(flags);
+
+	return -(status != 0xf);
+}
+
+/*
+ * grip_timer() repeatedly polls the joysticks and generates events.
+ */
+
+static void grip_timer(unsigned long private)
+{
+	struct grip *grip = (void*) private;
+	unsigned int data[GRIP_LENGTH_XT];
+	struct input_dev *dev;
+	int i, j;
+
+	for (i = 0; i < 2; i++) {
+
+		dev = grip->dev + i;
+		grip->reads++;
+
+		switch (grip->mode[i]) {
+
+			case GRIP_MODE_GPP:
+
+				if (grip_gpp_read_packet(grip->gameport, (i << 1) + 4, data)) {
+					grip->bads++;
+					break;
+				}
+
+				input_report_abs(dev, ABS_X, ((*data >> 15) & 1) - ((*data >> 16) & 1));
+				input_report_abs(dev, ABS_Y, ((*data >> 13) & 1) - ((*data >> 12) & 1));
+
+				for (j = 0; j < 12; j++)
+					if (grip_btn_gpp[j])
+						input_report_key(dev, grip_btn_gpp[j], (*data >> j) & 1);
+
+				break;
+
+			case GRIP_MODE_BD:
+
+				if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
+					grip->bads++;
+					break;
+				}
+
+				input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
+				input_report_abs(dev, ABS_Y,  63 - ((data[0] >> 8) & 0x3f));
+				input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
+
+				input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
+				input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
+
+				for (j = 0; j < 5; j++)
+					input_report_key(dev, grip_btn_bd[j], (data[3] >> (j + 4)) & 1);
+
+				break;
+
+			case GRIP_MODE_XT:
+
+				if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
+					grip->bads++;
+					break;
+				}
+
+				input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
+				input_report_abs(dev, ABS_Y,  63 - ((data[0] >> 8) & 0x3f));
+				input_report_abs(dev, ABS_BRAKE,    (data[1] >> 2) & 0x3f);
+				input_report_abs(dev, ABS_GAS,	    (data[1] >> 8) & 0x3f);
+				input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
+
+				input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
+				input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
+				input_report_abs(dev, ABS_HAT1X, ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1));
+				input_report_abs(dev, ABS_HAT1Y, ((data[2] >> 6) & 1) - ((data[2] >> 7) & 1));
+
+				for (j = 0; j < 11; j++)
+					input_report_key(dev, grip_btn_xt[j], (data[3] >> (j + 3)) & 1);
+				break;
+
+			case GRIP_MODE_DC:
+
+				if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
+					grip->bads++;
+					break;
+				}
+
+				input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
+				input_report_abs(dev, ABS_Y,        (data[0] >> 8) & 0x3f);
+				input_report_abs(dev, ABS_RX,       (data[1] >> 2) & 0x3f);
+				input_report_abs(dev, ABS_RY,	    (data[1] >> 8) & 0x3f);
+				input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
+
+				input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
+				input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
+
+				for (j = 0; j < 9; j++)
+					input_report_key(dev, grip_btn_dc[j], (data[3] >> (j + 3)) & 1);
+				break;
+
+
+		}
+	}
+
+	mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
+}
+
+static int grip_open(struct input_dev *dev)
+{
+	struct grip *grip = dev->private;
+	if (!grip->used++)
+		mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
+	return 0;
+}
+
+static void grip_close(struct input_dev *dev)
+{
+	struct grip *grip = dev->private;
+	if (!--grip->used)
+		del_timer(&grip->timer);
+}
+
+static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct grip *grip;
+	unsigned int data[GRIP_LENGTH_XT];
+	int i, j, t;
+
+	if (!(grip = kmalloc(sizeof(struct grip), GFP_KERNEL)))
+		return;
+	memset(grip, 0, sizeof(struct grip));
+
+	gameport->private = grip;
+
+	grip->gameport = gameport;
+	init_timer(&grip->timer);
+	grip->timer.data = (long) grip;
+	grip->timer.function = grip_timer;
+
+	 if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		goto fail1;
+
+	for (i = 0; i < 2; i++) {
+		if (!grip_gpp_read_packet(gameport, (i << 1) + 4, data)) {
+			grip->mode[i] = GRIP_MODE_GPP;
+			continue;
+		}
+		if (!grip_xt_read_packet(gameport, (i << 1) + 4, data)) {
+			if (!(data[3] & 7)) {
+				grip->mode[i] = GRIP_MODE_BD;
+				continue;
+			}
+			if (!(data[2] & 0xf0)) {
+				grip->mode[i] = GRIP_MODE_XT;
+				continue;
+			}
+			grip->mode[i] = GRIP_MODE_DC;
+			continue;
+		}
+	}
+
+	if (!grip->mode[0] && !grip->mode[1])
+		goto fail2;
+
+	for (i = 0; i < 2; i++)
+		if (grip->mode[i]) {
+
+			grip->dev[i].private = grip;
+
+			grip->dev[i].open = grip_open;
+			grip->dev[i].close = grip_close;
+
+			grip->dev[i].name = grip_name[grip->mode[i]];
+			grip->dev[i].idbus = BUS_GAMEPORT;
+			grip->dev[i].idvendor = GAMEPORT_ID_VENDOR_GRAVIS;
+			grip->dev[i].idproduct = grip->mode[i];
+			grip->dev[i].idversion = 0x0100;
+
+			grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+			for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
+
+				set_bit(t, grip->dev[i].absbit);
+
+				if (j < grip_cen[grip->mode[i]]) {
+					grip->dev[i].absmin[t] = 14;
+					grip->dev[i].absmax[t] = 52;
+					grip->dev[i].absfuzz[t] = 1;
+					grip->dev[i].absflat[t] = 2;
+					continue;
+				}
+
+				if (j < grip_anx[grip->mode[i]]) {
+					grip->dev[i].absmin[t] = 3;
+					grip->dev[i].absmax[t] = 57;
+					grip->dev[i].absfuzz[t] = 1;
+					continue;
+				}
+
+				grip->dev[i].absmin[t] = -1;
+				grip->dev[i].absmax[t] = 1;
+			}
+
+			for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
+				if (t > 0)
+					set_bit(t, grip->dev[i].keybit);
+
+			input_register_device(grip->dev + i);
+
+			printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
+				grip->dev[i].number, grip_name[grip->mode[i]], gameport->number, i);
+		}
+
+	return;
+fail2:	gameport_close(gameport);
+fail1:	kfree(grip);
+}
+
+static void grip_disconnect(struct gameport *gameport)
+{
+	int i;
+
+	struct grip *grip = gameport->private;
+	for (i = 0; i < 2; i++)
+		if (grip->mode[i])
+			input_unregister_device(grip->dev + i);
+	gameport_close(gameport);
+	kfree(grip);
+}
+
+static struct gameport_dev grip_dev = {
+	connect:	grip_connect,
+	disconnect:	grip_disconnect,
+};
+
+int __init grip_init(void)
+{
+	gameport_register_device(&grip_dev);
+	return 0;
+}
+
+void __exit grip_exit(void)
+{
+	gameport_unregister_device(&grip_dev);
+}
+
+module_init(grip_init);
+module_exit(grip_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/iforce.c b/drivers/input/joystick/iforce.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/iforce.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,1224 @@
+/*
+ * $Id: iforce.c,v 1.56 2001/05/27 14:41:26 jdeneux Exp $
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
+ *
+ *  USB/RS232 I-Force joysticks and wheels.
+ *
+ *  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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/serio.h>
+#include <linux/config.h>
+
+/* FF: This module provides arbitrary resource management routines.
+ * I use it to manage the device's memory.
+ * Despite the name of this module, I am *not* going to access the ioports.
+ */
+#include <linux/ioport.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>, Johann Deneux <deneux@ifrance.com>");
+MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
+MODULE_LICENSE("GPL");
+
+#define IFORCE_MAX_LENGTH	16
+
+#if defined(CONFIG_JOYSTICK_IFORCE_232) || defined(CONFIG_JOYSTICK_IFORCE_232_MODULE)
+#define IFORCE_232	1
+#endif
+#if defined(CONFIG_JOYSTICK_IFORCE_USB) || defined(CONFIG_JOYSTICK_IFORCE_USB_MODULE)
+#define IFORCE_USB	2
+#endif
+
+#define FF_EFFECTS_MAX	32
+
+/* Each force feedback effect is made of one core effect, which can be
+ * associated to at most to effect modifiers
+ */
+#define FF_MOD1_IS_USED		0
+#define FF_MOD2_IS_USED		1
+#define FF_CORE_IS_USED		2
+#define FF_CORE_IS_PLAYED	3
+#define FF_MODCORE_MAX		3
+
+struct iforce_core_effect {
+	/* Information about where modifiers are stored in the device's memory */
+	struct resource mod1_chunk;
+	struct resource mod2_chunk;
+	unsigned long flags[NBITS(FF_MODCORE_MAX)];
+};
+
+#define FF_CMD_EFFECT		0x010e
+#define FF_CMD_SHAPE		0x0208
+#define FF_CMD_MAGNITUDE	0x0303
+#define FF_CMD_PERIOD		0x0407
+#define FF_CMD_INTERACT		0x050a
+
+#define FF_CMD_AUTOCENTER	0x4002
+#define FF_CMD_PLAY		0x4103
+#define FF_CMD_ENABLE		0x4201
+#define FF_CMD_GAIN		0x4301
+
+#define FF_CMD_QUERY		0xff01
+
+static signed short btn_joystick[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
+	BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, BTN_DEAD, -1 };
+static signed short btn_wheel[] =    { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
+	BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
+static signed short abs_joystick[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
+static signed short abs_wheel[] =    { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, -1 };
+static signed short ff_iforce[] =    { FF_PERIODIC, FF_CONSTANT, FF_SPRING, FF_FRICTION,
+	FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP, FF_SAW_DOWN, FF_GAIN, FF_AUTOCENTER, -1 };
+
+static struct iforce_device {
+	u16 idvendor;
+	u16 idproduct;
+	char *name;
+	signed short *btn;
+	signed short *abs;
+	signed short *ff;
+} iforce_device[] = {
+	{ 0x046d, 0xc281, "Logitech WingMan Force",			btn_joystick, abs_joystick, ff_iforce },
+	{ 0x046d, 0xc291, "Logitech WingMan Formula Force",		btn_wheel, abs_wheel, ff_iforce },
+	{ 0x05ef, 0x020a, "AVB Top Shot Pegasus",			btn_joystick, abs_joystick, ff_iforce },
+	{ 0x05ef, 0x8884, "AVB Mag Turbo Force",			btn_wheel, abs_wheel, ff_iforce },
+	{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback",	btn_wheel, abs_wheel, ff_iforce },
+	{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]",		btn_joystick, abs_joystick, ff_iforce }
+};
+
+struct iforce {
+	struct input_dev dev;		/* Input device interface */
+	struct iforce_device *type;
+	char name[64];
+	int open;
+	int bus;
+
+	unsigned char data[IFORCE_MAX_LENGTH];
+	unsigned char edata[IFORCE_MAX_LENGTH];
+	u16 ecmd;
+	u16 expect_packet;
+
+#ifdef IFORCE_232
+	struct serio *serio;		/* RS232 transfer */
+	int idx, pkt, len, id;
+	unsigned char csum;
+#endif
+#ifdef IFORCE_USB
+	struct usb_device *usbdev;	/* USB transfer */
+	struct urb *irq, *out, *ctrl;
+	struct usb_ctrlrequest dr;
+#endif
+					/* Force Feedback */
+	wait_queue_head_t wait;
+	struct resource device_memory;
+	struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
+};
+
+static struct {
+	__s32 x;
+	__s32 y;
+} iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+/* Get hi and low bytes of a 16-bits int */
+#define HI(a)	((unsigned char)((a) >> 8))
+#define LO(a)	((unsigned char)((a) & 0xff))
+
+/* Encode a time value */
+#define TIME_SCALE(a)	((a) == 0xffff ? 0xffff : (a) * 1000 / 256)
+
+static void dump_packet(char *msg, u16 cmd, unsigned char *data)
+{
+	int i;
+
+	printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
+	for (i = 0; i < LO(cmd); i++)
+		printk("%02x ", data[i]);
+	printk(")\n");
+}
+
+/*
+ * Send a packet of bytes to the device
+ */
+static void send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
+{
+	switch (iforce->bus) {
+
+#ifdef IFORCE_232
+		case IFORCE_232: {
+
+			int i;
+			unsigned char csum = 0x2b ^ HI(cmd) ^ LO(cmd);
+
+			serio_write(iforce->serio, 0x2b);
+			serio_write(iforce->serio, HI(cmd));
+			serio_write(iforce->serio, LO(cmd));
+
+			for (i = 0; i < LO(cmd); i++) {
+				serio_write(iforce->serio, data[i]);
+				csum = csum ^ data[i];
+			}
+
+			serio_write(iforce->serio, csum);
+			return;
+		}
+#endif
+#ifdef IFORCE_USB
+		case IFORCE_USB: {
+
+			DECLARE_WAITQUEUE(wait, current);
+			int timeout = HZ; /* 1 second */
+
+			memcpy(iforce->out->transfer_buffer + 1, data, LO(cmd));
+			((char*)iforce->out->transfer_buffer)[0] = HI(cmd);
+			iforce->out->transfer_buffer_length = LO(cmd) + 2;
+			iforce->out->dev = iforce->usbdev;
+
+			set_current_state(TASK_INTERRUPTIBLE);
+			add_wait_queue(&iforce->wait, &wait);
+
+			if (usb_submit_urb(iforce->out, GFP_ATOMIC)) {
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&iforce->wait, &wait);
+				return;
+			}
+
+			while (timeout && iforce->out->status == -EINPROGRESS)
+				timeout = schedule_timeout(timeout);
+
+			set_current_state(TASK_RUNNING);
+			remove_wait_queue(&iforce->wait, &wait);
+
+			if (!timeout)
+				usb_unlink_urb(iforce->out);
+
+			return;
+		}
+#endif
+	}
+}
+
+static void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
+{
+	struct input_dev *dev = &iforce->dev;
+	int i;
+
+#ifdef IFORCE_232
+	if (HI(iforce->expect_packet) == HI(cmd)) {
+		iforce->expect_packet = 0;
+		iforce->ecmd = cmd;
+		memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
+		if (waitqueue_active(&iforce->wait))
+			wake_up(&iforce->wait);
+	}
+#endif
+
+	if (!iforce->type)
+		return;
+
+	switch (HI(cmd)) {
+
+		case 0x01:	/* joystick position data */
+		case 0x03:	/* wheel position data */
+
+			if (HI(cmd) == 1) {
+				input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
+				input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
+				input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
+			} else {
+				input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0]));
+				input_report_abs(dev, ABS_GAS,   255 - data[2]);
+				input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
+			}
+
+			input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
+			input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
+
+			for (i = 0; iforce->type->btn[i] >= 0; i++)
+				input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7)));
+
+			break;
+
+		case 0x02:	/* status report */
+
+			input_report_key(dev, BTN_DEAD, data[0] & 0x02);
+			break;
+	}
+}
+
+static int get_id_packet(struct iforce *iforce, char *packet)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int timeout = HZ; /* 1 second */
+
+	switch (iforce->bus) {
+
+#ifdef IFORCE_USB
+		case IFORCE_USB:
+
+			iforce->dr.bRequest = packet[0];
+			iforce->ctrl->dev = iforce->usbdev;
+
+			set_current_state(TASK_INTERRUPTIBLE);
+			add_wait_queue(&iforce->wait, &wait);
+
+			if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&iforce->wait, &wait);
+				return -1;
+			}
+
+			while (timeout && iforce->ctrl->status == -EINPROGRESS)
+				timeout = schedule_timeout(timeout);
+
+			set_current_state(TASK_RUNNING);
+			remove_wait_queue(&iforce->wait, &wait);
+
+			if (!timeout) {
+				usb_unlink_urb(iforce->ctrl);
+				return -1;
+			}
+
+			break;
+#endif
+#ifdef IFORCE_232
+		case IFORCE_232:
+
+			iforce->expect_packet = FF_CMD_QUERY;
+			send_packet(iforce, FF_CMD_QUERY, packet);
+
+			set_current_state(TASK_INTERRUPTIBLE);
+			add_wait_queue(&iforce->wait, &wait);
+
+			while (timeout && iforce->expect_packet)
+				timeout = schedule_timeout(timeout);
+
+			set_current_state(TASK_RUNNING);
+			remove_wait_queue(&iforce->wait, &wait);
+
+			if (!timeout) {
+				iforce->expect_packet = 0;
+				return -1;
+			}
+
+			break;
+#endif
+	}
+
+	return -(iforce->edata[0] != packet[0]);
+}
+
+static int iforce_open(struct input_dev *dev)
+{
+	struct iforce *iforce = dev->private;
+
+	switch (iforce->bus) {
+#ifdef IFORCE_USB
+		case IFORCE_USB:
+			if (iforce->open++)
+				break;
+			iforce->irq->dev = iforce->usbdev;
+			if (usb_submit_urb(iforce->irq, GFP_KERNEL))
+					return -EIO;
+			break;
+#endif
+	}
+	return 0;
+}
+
+static void iforce_close(struct input_dev *dev)
+{
+	struct iforce *iforce = dev->private;
+
+	switch (iforce->bus) {
+#ifdef IFORCE_USB
+		case IFORCE_USB:
+			if (!--iforce->open)
+				usb_unlink_urb(iforce->irq);
+			break;
+#endif
+	}
+}
+
+/*
+ * Start or stop playing an effect
+ */
+
+static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+	struct iforce* iforce = (struct iforce*)(dev->private);
+	unsigned char data[3];
+
+	printk(KERN_DEBUG "iforce.c: input_event(type = %d, code = %d, value = %d)\n", type, code, value);
+
+	if (type != EV_FF)
+		return -1;
+
+	switch (code) {
+
+		case FF_GAIN:
+
+			data[0] = value >> 9;
+			send_packet(iforce, FF_CMD_GAIN, data);
+
+			return 0;
+
+		case FF_AUTOCENTER:
+
+			data[0] = 0x03;
+			data[1] = value >> 9;
+			send_packet(iforce, FF_CMD_AUTOCENTER, data);
+
+			data[0] = 0x04;
+			data[1] = 0x01;
+			send_packet(iforce, FF_CMD_AUTOCENTER, data);
+
+			return 0;
+
+		default: /* Play an effect */
+
+			if (code >= iforce->dev.ff_effects_max)
+				return -1;
+
+			data[0] = LO(code);
+			data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
+			data[2] = LO(value);
+			send_packet(iforce, FF_CMD_PLAY, data);
+
+			return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * Set the magnitude of a constant force effect
+ * Return error code
+ *
+ * Note: caller must ensure exclusive access to device
+ */
+
+static int make_magnitude_modifier(struct iforce* iforce,
+	struct resource* mod_chunk, __s16 level)
+{
+	unsigned char data[3];
+
+	if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
+		iforce->device_memory.start, iforce->device_memory.end, 2L,
+		NULL, NULL)) {
+		return -ENOMEM;
+	}
+
+	data[0] = LO(mod_chunk->start);
+	data[1] = HI(mod_chunk->start);
+	data[2] = HI(level);
+
+	send_packet(iforce, FF_CMD_MAGNITUDE, data);
+
+	return 0;
+}
+
+/*
+ * Upload the component of an effect dealing with the period, phase and magnitude
+ */
+
+static int make_period_modifier(struct iforce* iforce, struct resource* mod_chunk,
+	__s16 magnitude, __s16 offset, u16 period, u16 phase)
+{
+	unsigned char data[7];
+
+	period = TIME_SCALE(period);
+
+	if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
+		iforce->device_memory.start, iforce->device_memory.end, 2L,
+		NULL, NULL)) {
+		return -ENOMEM;
+	}
+
+	data[0] = LO(mod_chunk->start);
+	data[1] = HI(mod_chunk->start);
+
+	data[2] = HI(magnitude);
+	data[3] = HI(offset);
+	data[4] = HI(phase);
+
+	data[5] = LO(period);
+	data[6] = HI(period);
+
+	send_packet(iforce, FF_CMD_PERIOD, data);
+
+	return 0;
+}
+
+/*
+ * Uploads the part of an effect setting the shape of the force
+ */
+
+static int make_shape_modifier(struct iforce* iforce, struct resource* mod_chunk,
+	u16 attack_duration, __s16 initial_level,
+	u16 fade_duration, __s16 final_level)
+{
+	unsigned char data[8];
+
+	attack_duration = TIME_SCALE(attack_duration);
+	fade_duration = TIME_SCALE(fade_duration);
+
+	if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
+		iforce->device_memory.start, iforce->device_memory.end, 2L,
+		NULL, NULL)) {
+		return -ENOMEM;
+	}
+
+	data[0] = LO(mod_chunk->start);
+	data[1] = HI(mod_chunk->start);
+
+	data[2] = LO(attack_duration);
+	data[3] = HI(attack_duration);
+	data[4] = HI(initial_level);
+
+	data[5] = LO(fade_duration);
+	data[6] = HI(fade_duration);
+	data[7] = HI(final_level);
+
+	send_packet(iforce, FF_CMD_SHAPE, data);
+
+	return 0;
+}
+
+/*
+ * Component of spring, friction, inertia... effects
+ */
+
+static int make_interactive_modifier(struct iforce* iforce,
+	struct resource* mod_chunk,
+	__s16 rsat, __s16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center)
+{
+	unsigned char data[10];
+
+	if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
+		iforce->device_memory.start, iforce->device_memory.end, 2L,
+		NULL, NULL)) {
+		return -ENOMEM;
+	}
+
+	data[0] = LO(mod_chunk->start);
+	data[1] = HI(mod_chunk->start);
+
+	data[2] = HI(rk);
+	data[3] = HI(lk);
+
+	data[4] = LO(center);
+	data[5] = HI(center);
+
+	data[6] = LO(db);
+	data[7] = HI(db);
+
+	data[8] = HI(rsat);
+	data[9] = HI(lsat);
+
+	send_packet(iforce, FF_CMD_INTERACT, data);
+
+	return 0;
+}
+
+static unsigned char find_button(struct iforce *iforce, signed short button)
+{
+	int i;
+	for (i = 1; iforce->type->btn[i] >= 0; i++)
+		if (iforce->type->btn[i] == button)
+			return i + 1;
+	return 0;
+}
+
+/*
+ * Send the part common to all effects to the device
+ */
+
+static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2,
+	u8 effect_type, u8 axes, u16 duration, u16 delay, u16 button,
+	u16 interval, u16 direction)
+{
+	unsigned char data[14];
+
+	duration = TIME_SCALE(duration);
+	delay    = TIME_SCALE(delay);
+	interval = TIME_SCALE(interval);
+
+	data[0]  = LO(id);
+	data[1]  = effect_type;
+	data[2]  = LO(axes) | find_button(iforce, button);
+
+	data[3]  = LO(duration);
+	data[4]  = HI(duration);
+
+	data[5]  = HI(direction);
+
+	data[6]  = LO(interval);
+	data[7]  = HI(interval);
+
+	data[8]  = LO(mod_id1);
+	data[9]  = HI(mod_id1);
+	data[10] = LO(mod_id2);
+	data[11] = HI(mod_id2);
+
+	data[12] = LO(delay);
+	data[13] = HI(delay);
+
+	send_packet(iforce, FF_CMD_EFFECT, data);
+
+	return 0;
+}
+
+/*
+ * Upload a periodic effect to the device
+ */
+
+static int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect)
+{
+	u8 wave_code;
+	int core_id = effect->id;
+	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
+	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
+	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
+	int err = 0;
+
+	err = make_period_modifier(iforce, mod1_chunk,
+		effect->u.periodic.magnitude, effect->u.periodic.offset,
+		effect->u.periodic.period, effect->u.periodic.phase);
+	if (err) return err;
+	set_bit(FF_MOD1_IS_USED, core_effect->flags);
+
+	err = make_shape_modifier(iforce, mod2_chunk,
+		effect->u.periodic.shape.attack_length,
+		effect->u.periodic.shape.attack_level,
+		effect->u.periodic.shape.fade_length,
+		effect->u.periodic.shape.fade_level);
+	if (err) return err;
+	set_bit(FF_MOD2_IS_USED, core_effect->flags);
+
+	switch (effect->u.periodic.waveform) {
+		case FF_SQUARE:		wave_code = 0x20; break;
+		case FF_TRIANGLE:	wave_code = 0x21; break;
+		case FF_SINE:		wave_code = 0x22; break;
+		case FF_SAW_UP:		wave_code = 0x23; break;
+		case FF_SAW_DOWN:	wave_code = 0x24; break;
+		default:		wave_code = 0x20; break;
+	}
+
+	err = make_core(iforce, effect->id,
+		mod1_chunk->start,
+		mod2_chunk->start,
+		wave_code,
+		0x20,
+		effect->replay.length,
+		effect->replay.delay,
+		effect->trigger.button,
+		effect->trigger.interval,
+		effect->direction);
+
+	return err;
+}
+
+/*
+ * Upload a constant force effect
+ */
+static int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect)
+{
+	int core_id = effect->id;
+	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
+	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
+	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
+	int err = 0;
+
+	printk(KERN_DEBUG "iforce.c: make constant effect\n");
+
+	err = make_magnitude_modifier(iforce, mod1_chunk, effect->u.constant.level);
+	if (err) return err;
+	set_bit(FF_MOD1_IS_USED, core_effect->flags);
+
+	err = make_shape_modifier(iforce, mod2_chunk,
+		effect->u.constant.shape.attack_length,
+		effect->u.constant.shape.attack_level,
+		effect->u.constant.shape.fade_length,
+		effect->u.constant.shape.fade_level);
+	if (err) return err;
+	set_bit(FF_MOD2_IS_USED, core_effect->flags);
+
+	err = make_core(iforce, effect->id,
+		mod1_chunk->start,
+		mod2_chunk->start,
+		0x00,
+		0x20,
+		effect->replay.length,
+		effect->replay.delay,
+		effect->trigger.button,
+		effect->trigger.interval,
+		effect->direction);
+
+	return err;
+}
+
+/*
+ * Upload an interactive effect. Those are for example friction, inertia, springs...
+ */
+static int iforce_upload_interactive(struct iforce* iforce, struct ff_effect* effect)
+{
+	int core_id = effect->id;
+	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
+	struct resource* mod_chunk = &(core_effect->mod1_chunk);
+	u8 type, axes;
+	u16 mod1, mod2, direction;
+	int err = 0;
+
+	printk(KERN_DEBUG "iforce.c: make interactive effect\n");
+
+	switch (effect->type) {
+		case FF_SPRING:		type = 0x40; break;
+		case FF_FRICTION:	type = 0x41; break;
+		default: return -1;
+	}
+
+	err = make_interactive_modifier(iforce, mod_chunk,
+		effect->u.interactive.right_saturation,
+		effect->u.interactive.left_saturation,
+		effect->u.interactive.right_coeff,
+		effect->u.interactive.left_coeff,
+		effect->u.interactive.deadband,
+		effect->u.interactive.center);
+	if (err) return err;
+	set_bit(FF_MOD1_IS_USED, core_effect->flags);
+
+	switch ((test_bit(ABS_X, &effect->u.interactive.axis) ||
+		test_bit(ABS_WHEEL, &effect->u.interactive.axis)) |
+		(!!test_bit(ABS_Y, &effect->u.interactive.axis) << 1)) {
+
+		case 0: /* Only one axis, choose orientation */
+			mod1 = mod_chunk->start;
+			mod2 = 0xffff;
+			direction = effect->direction;
+			axes = 0x20;
+			break;
+
+		case 1:	/* Only X axis */
+			mod1 = mod_chunk->start;
+			mod2 = 0xffff;
+			direction = 0x5a00;
+			axes = 0x40;
+			break;
+
+		case 2: /* Only Y axis */
+			mod1 = 0xffff;
+			mod2 = mod_chunk->start;
+			direction = 0xb400;
+			axes = 0x80;
+			break;
+
+		case 3:	/* Both X and Y axes */
+			/* TODO: same setting for both axes is not mandatory */
+			mod1 = mod_chunk->start;
+			mod2 = mod_chunk->start;
+			direction = 0x6000;
+			axes = 0xc0;
+			break;
+
+		default:
+			return -1;
+	}
+
+	err = make_core(iforce, effect->id,
+		mod1, mod2,
+		type, axes,
+		effect->replay.length, effect->replay.delay,
+		effect->trigger.button, effect->trigger.interval,
+		direction);
+
+	return err;
+}
+
+/*
+ * Function called when an ioctl is performed on the event dev entry.
+ * It uploads an effect to the device
+ */
+static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
+{
+	struct iforce* iforce = (struct iforce*)(dev->private);
+	int id;
+
+	printk(KERN_DEBUG "iforce.c: upload effect\n");
+
+/*
+ * Get a free id
+ */
+
+	for (id=0; id < FF_EFFECTS_MAX; ++id)
+		if (!test_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
+
+	if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
+		return -ENOMEM;
+
+	effect->id = id;
+	set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags);
+
+/*
+ * Upload the effect
+ */
+
+	switch (effect->type) {
+
+		case FF_PERIODIC:
+			return iforce_upload_periodic(iforce, effect);
+
+		case FF_CONSTANT:
+			return iforce_upload_constant(iforce, effect);
+
+		case FF_SPRING:
+		case FF_FRICTION:
+			return iforce_upload_interactive(iforce, effect);
+
+		default:
+			return -1;
+	}
+}
+
+/*
+ * Erases an effect: it frees the effect id and mark as unused the memory
+ * allocated for the parameters
+ */
+static int iforce_erase_effect(struct input_dev *dev, int effect_id)
+{
+	struct iforce* iforce = (struct iforce*)(dev->private);
+	int err = 0;
+	struct iforce_core_effect* core_effect;
+
+	printk(KERN_DEBUG "iforce.c: erase effect %d\n", effect_id);
+
+	if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
+		return -EINVAL;
+
+	core_effect = iforce->core_effects + effect_id;
+
+	if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
+		err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
+
+	if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
+		err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
+
+	/*TODO: remember to change that if more FF_MOD* bits are added */
+	core_effect->flags[0] = 0;
+
+	return err;
+}
+static int iforce_init_device(struct iforce *iforce)
+{
+	unsigned char c[] = "CEOV";
+	int i;
+
+	init_waitqueue_head(&iforce->wait);
+	iforce->dev.ff_effects_max = 10;
+
+/*
+ * Input device fields.
+ */
+
+	iforce->dev.idbus = BUS_USB;
+	iforce->dev.private = iforce;
+	iforce->dev.name = iforce->name;
+	iforce->dev.open = iforce_open;
+	iforce->dev.close = iforce_close;
+	iforce->dev.event = iforce_input_event;
+	iforce->dev.upload_effect = iforce_upload_effect;
+	iforce->dev.erase_effect = iforce_erase_effect;
+
+/*
+ * On-device memory allocation.
+ */
+
+	iforce->device_memory.name = "I-Force device effect memory";
+	iforce->device_memory.start = 0;
+	iforce->device_memory.end = 200;
+	iforce->device_memory.flags = IORESOURCE_MEM;
+	iforce->device_memory.parent = NULL;
+	iforce->device_memory.child = NULL;
+	iforce->device_memory.sibling = NULL;
+
+/*
+ * Wait until device ready - until it sends its first response.
+ */
+
+	for (i = 0; i < 20; i++)
+		if (!get_id_packet(iforce, "O"))
+			break;
+
+	if (i == 20) { /* 5 seconds */
+		printk(KERN_ERR "iforce.c: Timeout waiting for response from device.\n");
+		iforce_close(&iforce->dev);
+		return -1;
+	}
+
+/*
+ * Get device info.
+ */
+
+	if (!get_id_packet(iforce, "M"))
+		iforce->dev.idvendor = (iforce->edata[2] << 8) | iforce->edata[1];
+	if (!get_id_packet(iforce, "P"))
+		iforce->dev.idproduct = (iforce->edata[2] << 8) | iforce->edata[1];
+	if (!get_id_packet(iforce, "B"))
+		iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
+	if (!get_id_packet(iforce, "N"))
+		iforce->dev.ff_effects_max = iforce->edata[1];
+
+/*
+ * Display additional info.
+ */
+
+	for (i = 0; c[i]; i++)
+		if (!get_id_packet(iforce, c + i))
+			dump_packet("info", iforce->ecmd, iforce->edata);
+
+/*
+ * Disable spring, enable force feedback.
+ * FIXME: We should use iforce_set_autocenter() et al here.
+ */
+
+	send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");
+	send_packet(iforce, FF_CMD_ENABLE, "\004");
+
+/*
+ * Find appropriate device entry
+ */
+
+	for (i = 0; iforce_device[i].idvendor; i++)
+		if (iforce_device[i].idvendor == iforce->dev.idvendor &&
+		    iforce_device[i].idproduct == iforce->dev.idproduct)
+			break;
+
+	iforce->type = iforce_device + i;
+
+	sprintf(iforce->name, iforce->type->name,
+		iforce->dev.idproduct, iforce->dev.idvendor);
+
+/*
+ * Set input device bitfields and ranges.
+ */
+
+	iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF);
+
+	for (i = 0; iforce->type->btn[i] >= 0; i++) {
+		signed short t = iforce->type->btn[i];
+		set_bit(t, iforce->dev.keybit);
+		if (t != BTN_DEAD)
+			set_bit(FF_BTN(t), iforce->dev.ffbit);
+	}
+
+	for (i = 0; iforce->type->abs[i] >= 0; i++) {
+
+		signed short t = iforce->type->abs[i];
+		set_bit(t, iforce->dev.absbit);
+
+		switch (t) {
+
+			case ABS_X:
+			case ABS_Y:
+			case ABS_WHEEL:
+
+				iforce->dev.absmax[t] =  1920;
+				iforce->dev.absmin[t] = -1920;
+				iforce->dev.absflat[t] = 128;
+				iforce->dev.absfuzz[t] = 16;
+
+				set_bit(FF_ABS(t), iforce->dev.ffbit);
+				break;
+
+			case ABS_THROTTLE:
+			case ABS_GAS:
+			case ABS_BRAKE:
+
+				iforce->dev.absmax[t] = 255;
+				iforce->dev.absmin[t] = 0;
+				break;
+
+			case ABS_HAT0X:
+			case ABS_HAT0Y:
+				iforce->dev.absmax[t] =  1;
+				iforce->dev.absmin[t] = -1;
+				break;
+		}
+	}
+
+	for (i = 0; iforce->type->ff[i] >= 0; i++)
+		set_bit(iforce->type->ff[i], iforce->dev.ffbit);
+
+/*
+ * Register input device.
+ */
+
+	input_register_device(&iforce->dev);
+
+	return 0;
+}
+
+#ifdef IFORCE_USB
+
+static void iforce_usb_irq(struct urb *urb)
+{
+	struct iforce *iforce = urb->context;
+	if (urb->status) return;
+	iforce_process_packet(iforce,
+		(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1);
+}
+
+static void iforce_usb_out(struct urb *urb)
+{
+	struct iforce *iforce = urb->context;
+	if (urb->status) return;
+	if (waitqueue_active(&iforce->wait))
+		wake_up(&iforce->wait);
+}
+
+static void iforce_usb_ctrl(struct urb *urb)
+{
+	struct iforce *iforce = urb->context;
+	if (urb->status) return;
+	iforce->ecmd = 0xff00 | urb->actual_length;
+	if (waitqueue_active(&iforce->wait))
+		wake_up(&iforce->wait);
+}
+
+static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum,
+				const struct usb_device_id *id)
+{
+	struct usb_endpoint_descriptor *epirq, *epout;
+	struct iforce *iforce;
+
+	epirq = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+	epout = dev->config[0].interface[ifnum].altsetting[0].endpoint + 1;
+
+	if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) return NULL;
+	memset(iforce, 0, sizeof(struct iforce));
+
+	iforce->irq = usb_alloc_urb(0);
+	if (!iforce->irq) {
+		kfree(iforce);
+		return NULL;
+	}
+	iforce->out = usb_alloc_urb(0);
+	if (!iforce->out) {
+		usb_free_urb(iforce->irq);
+		kfree(iforce);
+		return NULL;
+	}
+	iforce->ctrl = usb_alloc_urb(0);
+	if (!iforce->ctrl) {
+		usb_free_urb(iforce->out);
+		usb_free_urb(iforce->irq);
+		kfree(iforce);
+		return NULL;
+	}
+
+	iforce->bus = IFORCE_USB;
+	iforce->usbdev = dev;
+
+	iforce->dr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
+	iforce->dr.wIndex = 0;
+	iforce->dr.wLength = 16;
+
+	FILL_INT_URB(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
+			iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
+
+	FILL_BULK_URB(iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
+			iforce + 1, 32, iforce_usb_out, iforce);
+
+	FILL_CONTROL_URB(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
+			(void*) &iforce->dr, iforce->edata, 16, iforce_usb_ctrl, iforce);
+
+	if (iforce_init_device(iforce)) {
+		usb_free_urb(iforce->ctrl);
+		usb_free_urb(iforce->out);
+		usb_free_urb(iforce->irq);
+		kfree(iforce);
+		return NULL;
+	}
+
+	printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on usb%d:%d.%d\n",
+		iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,
+		iforce->device_memory.end, dev->bus->busnum, dev->devnum, ifnum);
+
+	return iforce;
+}
+
+static void iforce_usb_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct iforce *iforce = ptr;
+	usb_unlink_urb(iforce->irq);
+	input_unregister_device(&iforce->dev);
+	usb_free_urb(iforce->ctrl);
+	usb_free_urb(iforce->out);
+	usb_free_urb(iforce->irq);
+	kfree(iforce);
+}
+
+static struct usb_device_id iforce_usb_ids [] = {
+	{ USB_DEVICE(0x046d, 0xc281) },		/* Logitech WingMan Force */
+	{ USB_DEVICE(0x046d, 0xc291) },		/* Logitech WingMan Formula Force */
+	{ USB_DEVICE(0x05ef, 0x020a) },		/* AVB Top Shot Pegasus */
+	{ USB_DEVICE(0x05ef, 0x8884) },		/* AVB Mag Turbo Force */
+	{ USB_DEVICE(0x06f8, 0x0001) },		/* Guillemot Race Leader Force Feedback */
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
+
+static struct usb_driver iforce_usb_driver = {
+	name:		"iforce",
+	probe:		iforce_usb_probe,
+	disconnect:	iforce_usb_disconnect,
+	id_table:	iforce_usb_ids,
+};
+
+#endif
+
+#ifdef IFORCE_232
+
+static void iforce_serio_irq(struct serio *serio, unsigned char data, unsigned int flags)
+{
+	struct iforce* iforce = serio->private;
+
+	if (!iforce->pkt) {
+		if (data != 0x2b) {
+			return;
+		}
+		iforce->pkt = 1;
+		return;
+	}
+
+	if (!iforce->id) {
+		if (data > 3 && data != 0xff) {
+			iforce->pkt = 0;
+			return;
+		}
+		iforce->id = data;
+		return;
+	}
+
+	if (!iforce->len) {
+		if (data > IFORCE_MAX_LENGTH) {
+			iforce->pkt = 0;
+			iforce->id = 0;
+			return;
+		}
+		iforce->len = data;
+		return;
+	}
+
+	if (iforce->idx < iforce->len) {
+		iforce->csum += iforce->data[iforce->idx++] = data;
+		return;
+	}
+
+	if (iforce->idx == iforce->len) {
+		iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data);
+		iforce->pkt = 0;
+		iforce->id  = 0;
+		iforce->len = 0;
+		iforce->idx = 0;
+		iforce->csum = 0;
+	}
+}
+
+static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
+{
+	struct iforce *iforce;
+	if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
+		return;
+
+	if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return;
+	memset(iforce, 0, sizeof(struct iforce));
+
+	iforce->bus = IFORCE_232;
+	iforce->serio = serio;
+	serio->private = iforce;
+
+	if (serio_open(serio, dev)) {
+		kfree(iforce);
+		return;
+	}
+
+	if (iforce_init_device(iforce)) {
+		serio_close(serio);
+		kfree(iforce);
+		return;
+	}
+
+	printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on serio%d\n",
+		iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,
+		iforce->device_memory.end, serio->number);
+}
+
+static void iforce_serio_disconnect(struct serio *serio)
+{
+	struct iforce* iforce = serio->private;
+
+	input_unregister_device(&iforce->dev);
+	serio_close(serio);
+	kfree(iforce);
+}
+
+static struct serio_dev iforce_serio_dev = {
+	interrupt:	iforce_serio_irq,
+	connect:	iforce_serio_connect,
+	disconnect:	iforce_serio_disconnect,
+};
+
+#endif
+
+static int __init iforce_init(void)
+{
+#ifdef IFORCE_USB
+	usb_register(&iforce_usb_driver);
+#endif
+#ifdef IFORCE_232
+	serio_register_device(&iforce_serio_dev);
+#endif
+	return 0;
+}
+
+static void __exit iforce_exit(void)
+{
+#ifdef IFORCE_USB
+	usb_deregister(&iforce_usb_driver);
+#endif
+#ifdef IFORCE_232
+	serio_unregister_device(&iforce_serio_dev);
+#endif
+}
+
+module_init(iforce_init);
+module_exit(iforce_exit);
diff -Nru a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/interact.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,308 @@
+/*
+ * $Id: interact.c,v 1.8 2000/05/29 11:19:51 vojtech Exp $
+ *
+ *  Copyright (c) 2000 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *	Toby Deshane
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * InterAct digital gamepad/joystick driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/input.h>
+
+#define INTERACT_MAX_START	400	/* 400 us */
+#define INTERACT_MAX_STROBE	40	/* 40 us */
+#define INTERACT_MAX_LENGTH	32	/* 32 bits */
+#define INTERACT_REFRESH_TIME	HZ/50	/* 20 ms */
+
+#define INTERACT_TYPE_HHFX	0	/* HammerHead/FX */
+#define INTERACT_TYPE_PP8D	1	/* ProPad 8 */
+
+struct interact {
+	struct gameport *gameport;
+	struct input_dev dev;
+	struct timer_list timer;
+	int used;
+	int bads;
+	int reads;
+	unsigned char type;
+	unsigned char length;
+};
+
+static short interact_abs_hhfx[] = 
+	{ ABS_RX, ABS_RY, ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y, -1 };
+static short interact_abs_pp8d[] =
+	{ ABS_X, ABS_Y, -1 };
+
+static short interact_btn_hhfx[] =
+	{ BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL, BTN_TL2, BTN_TR2, BTN_MODE, BTN_SELECT, -1 };
+static short interact_btn_pp8d[] =
+	{ BTN_C, BTN_TL, BTN_TR, BTN_A, BTN_B, BTN_Y, BTN_Z, BTN_X, -1 };
+
+struct interact_type {
+	int id;
+	short *abs;
+	short *btn;
+	char *name;
+	unsigned char length;
+	unsigned char b8;
+};
+
+static struct interact_type interact_type[] = {
+	{ 0x6202, interact_abs_hhfx, interact_btn_hhfx, "InterAct HammerHead/FX",    32, 4 },
+	{ 0x53f8, interact_abs_pp8d, interact_btn_pp8d, "InterAct ProPad 8 Digital", 16, 0 },
+	{ 0 }};
+
+/*
+ * interact_read_packet() reads and InterAct joystick data.
+ */
+
+static int interact_read_packet(struct gameport *gameport, int length, u32 *data)
+{
+	unsigned long flags;
+	unsigned char u, v;
+	unsigned int t, s;
+	int i;
+
+	i = 0;
+	data[0] = data[1] = data[2] = 0;
+	t = gameport_time(gameport, INTERACT_MAX_START);
+	s = gameport_time(gameport, INTERACT_MAX_STROBE);
+
+	__save_flags(flags);
+	__cli();
+	gameport_trigger(gameport);
+	v = gameport_read(gameport);
+
+	while (t > 0 && i < length) {
+		t--;
+		u = v; v = gameport_read(gameport);
+		if (v & ~u & 0x40) {
+			data[0] = (data[0] << 1) | ((v >> 4) & 1);
+			data[1] = (data[1] << 1) | ((v >> 5) & 1);
+			data[2] = (data[2] << 1) | ((v >> 7) & 1);
+			i++;
+			t = s;
+		}
+	}
+
+	__restore_flags(flags);
+
+	return i;
+}
+
+/*
+ * interact_timer() reads and analyzes InterAct joystick data.
+ */
+
+static void interact_timer(unsigned long private)
+{
+	struct interact *interact = (struct interact *) private;
+	struct input_dev *dev = &interact->dev;
+	u32 data[3];
+	int i;
+
+	interact->reads++;
+
+	if (interact_read_packet(interact->gameport, interact->length, data) < interact->length) {
+		interact->bads++;
+	} else
+
+	for (i = 0; i < 3; i++)
+		data[i] <<= INTERACT_MAX_LENGTH - interact->length;
+
+	switch (interact->type) {
+
+		case INTERACT_TYPE_HHFX:
+
+			for (i = 0; i < 4; i++)
+				input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);
+
+			for (i = 0; i < 2; i++)
+				input_report_abs(dev, ABS_HAT0Y - i,
+					((data[1] >> ((i << 1) + 17)) & 1)  - ((data[1] >> ((i << 1) + 16)) & 1));
+
+			for (i = 0; i < 8; i++)
+				input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);
+
+			for (i = 0; i < 4; i++)
+				input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);
+
+			break;
+
+		case INTERACT_TYPE_PP8D:
+
+			for (i = 0; i < 2; i++)
+				input_report_abs(dev, interact_abs_pp8d[i], 
+					((data[0] >> ((i << 1) + 20)) & 1)  - ((data[0] >> ((i << 1) + 21)) & 1));
+
+			for (i = 0; i < 8; i++)
+				input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);
+
+			break;
+	}
+
+	mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
+
+}
+
+/*
+ * interact_open() is a callback from the input open routine.
+ */
+
+static int interact_open(struct input_dev *dev)
+{
+	struct interact *interact = dev->private;
+	if (!interact->used++)
+		mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);	
+	return 0;
+}
+
+/*
+ * interact_close() is a callback from the input close routine.
+ */
+
+static void interact_close(struct input_dev *dev)
+{
+	struct interact *interact = dev->private;
+	if (!--interact->used)
+		del_timer(&interact->timer);
+}
+
+/*
+ * interact_connect() probes for InterAct joysticks.
+ */
+
+static void interact_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct interact *interact;
+	__u32 data[3];
+	int i, t;
+
+	if (!(interact = kmalloc(sizeof(struct interact), GFP_KERNEL)))
+		return;
+	memset(interact, 0, sizeof(struct interact));
+
+	gameport->private = interact;
+
+	interact->gameport = gameport;
+	init_timer(&interact->timer);
+	interact->timer.data = (long) interact;
+	interact->timer.function = interact_timer;
+
+	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		goto fail1;
+
+	i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);
+
+	if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
+		goto fail2;
+	}
+
+	for (i = 0; interact_type[i].length; i++)
+		if (interact_type[i].id == (data[2] >> 16))
+			break;
+
+	if (!interact_type[i].length) {
+		printk(KERN_WARNING "interact.c: Unknown joystick on gameport%d. [len %d d0 %08x d1 %08x i2 %08x]\n",
+			gameport->number, i, data[0], data[1], data[2]);
+		goto fail2;	
+	}
+
+	interact->type = i;
+	interact->length = interact_type[i].length;
+
+	interact->dev.private = interact;
+	interact->dev.open = interact_open;
+	interact->dev.close = interact_close;
+
+	interact->dev.name = interact_type[i].name;
+	interact->dev.idbus = BUS_GAMEPORT;
+	interact->dev.idvendor = GAMEPORT_ID_VENDOR_INTERACT;
+	interact->dev.idproduct = interact_type[i].id;
+	interact->dev.idversion = 0x0100;
+
+	interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
+		set_bit(t, interact->dev.absbit);
+		if (i < interact_type[interact->type].b8) {
+			interact->dev.absmin[t] = 0;
+			interact->dev.absmax[t] = 255;
+		} else {
+			interact->dev.absmin[t] = -1;
+			interact->dev.absmax[t] = 1;
+		}
+	}
+
+	for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
+		set_bit(t, interact->dev.keybit);
+
+	input_register_device(&interact->dev);
+	printk(KERN_INFO "input%d: %s on gameport%d.0\n",
+		interact->dev.number, interact_type[interact->type].name, gameport->number);
+
+	return;
+fail2:	gameport_close(gameport);
+fail1:  kfree(interact);
+}
+
+static void interact_disconnect(struct gameport *gameport)
+{
+	struct interact *interact = gameport->private;
+	input_unregister_device(&interact->dev);
+	gameport_close(gameport);
+	kfree(interact);
+}
+
+static struct gameport_dev interact_dev = {
+	connect:	interact_connect,
+	disconnect:	interact_disconnect,
+};
+
+int __init interact_init(void)
+{
+	gameport_register_device(&interact_dev);
+	return 0;
+}
+
+void __exit interact_exit(void)
+{
+	gameport_unregister_device(&interact_dev);
+}
+
+module_init(interact_init);
+module_exit(interact_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/magellan.c	Sun Feb 10 19:58:03 2002
@@ -0,0 +1,212 @@
+/*
+ * $Id: magellan.c,v 1.8 2000/05/31 13:17:12 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Magellan and Space Mouse 6dof controller driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ *  Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define	MAGELLAN_MAX_LENGTH	32
+
+static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8};
+static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ};
+static char *magellan_name = "LogiCad3D Magellan";
+
+/*
+ * Per-Magellan data.
+ */
+
+struct magellan {
+	struct input_dev dev;
+	int idx;
+	unsigned char data[MAGELLAN_MAX_LENGTH];
+};
+
+/*
+ * magellan_crunch_nibbles() verifies that the bytes sent from the Magellan
+ * have correct upper nibbles for the lower ones, if not, the packet will
+ * be thrown away. It also strips these upper halves to simplify further
+ * processing.
+ */
+
+static int magellan_crunch_nibbles(unsigned char *data, int count)
+{
+	static unsigned char nibbles[16] = "0AB3D56GH9:K<MN?";
+
+	do {
+		if (data[count] == nibbles[data[count] & 0xf])
+			data[count] = data[count] & 0xf;
+		else
+			return -1;
+	} while (--count);
+
+	return 0;
+}
+
+static void magellan_process_packet(struct magellan* magellan)
+{
+	struct input_dev *dev = &magellan->dev;
+	unsigned char *data = magellan->data;
+	int i, t;
+
+	if (!magellan->idx) return;
+
+	switch (magellan->data[0]) {
+
+		case 'd':				/* Axis data */
+			if (magellan->idx != 25) return;
+			if (magellan_crunch_nibbles(data, 24)) return;
+			for (i = 0; i < 6; i++)
+				input_report_abs(dev, magellan_axes[i],
+					(data[(i << 2) + 1] << 12 | data[(i << 2) + 2] << 8 |
+					 data[(i << 2) + 3] <<  4 | data[(i << 2) + 4]) - 32768);
+			break;
+
+		case 'k':				/* Button data */
+			if (magellan->idx != 4) return;
+			if (magellan_crunch_nibbles(data, 3)) return;
+			t = (data[1] << 1) | (data[2] << 5) | data[3];
+			for (i = 0; i < 9; i++) input_report_key(dev, magellan_buttons[i], (t >> i) & 1);
+			break;
+	}
+}
+
+static void magellan_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+	struct magellan* magellan = serio->private;
+
+	if (data == '\r') {
+		magellan_process_packet(magellan);
+		magellan->idx = 0;
+	} else {
+		if (magellan->idx < MAGELLAN_MAX_LENGTH)
+			magellan->data[magellan->idx++] = data;
+	} 
+}
+
+/*
+ * magellan_disconnect() is the opposite of magellan_connect()
+ */
+
+static void magellan_disconnect(struct serio *serio)
+{
+	struct magellan* magellan = serio->private;
+	input_unregister_device(&magellan->dev);
+	serio_close(serio);
+	kfree(magellan);
+}
+
+/*
+ * magellan_connect() is the routine that is called when someone adds a
+ * new serio device. It looks for the Magellan, and if found, registers
+ * it as an input device.
+ */
+
+static void magellan_connect(struct serio *serio, struct serio_dev *dev)
+{
+	struct magellan *magellan;
+	int i, t;
+
+	if (serio->type != (SERIO_RS232 | SERIO_MAGELLAN))
+		return;
+
+	if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
+		return;
+
+	memset(magellan, 0, sizeof(struct magellan));
+
+	magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
+
+	for (i = 0; i < 9; i++)
+		set_bit(magellan_buttons[i], &magellan->dev.keybit);
+
+	for (i = 0; i < 6; i++) {
+		t = magellan_axes[i];
+		set_bit(t, magellan->dev.absbit);
+		magellan->dev.absmin[t] = -360;
+		magellan->dev.absmax[t] =  360;
+	}
+
+	magellan->dev.private = magellan;
+	magellan->dev.name = magellan_name;
+	magellan->dev.idbus = BUS_RS232;
+	magellan->dev.idvendor = SERIO_MAGELLAN;
+	magellan->dev.idproduct = 0x0001;
+	magellan->dev.idversion = 0x0100;
+	
+	serio->private = magellan;
+
+	if (serio_open(serio, dev)) {
+		kfree(magellan);
+		return;
+	}
+
+	input_register_device(&magellan->dev);
+
+	printk(KERN_INFO "input%d: %s on serio%d\n", magellan->dev.number, magellan_name, serio->number);
+}
+
+/*
+ * The serio device structure.
+ */
+
+static struct serio_dev magellan_dev = {
+	interrupt:	magellan_interrupt,
+	connect:	magellan_connect,
+	disconnect:	magellan_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+int __init magellan_init(void)
+{
+	serio_register_device(&magellan_dev);
+	return 0;
+}
+
+void __exit magellan_exit(void)
+{
+	serio_unregister_device(&magellan_dev);
+}
+
+module_init(magellan_init);
+module_exit(magellan_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/sidewinder.c	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,761 @@
+/*
+ * $Id: sidewinder.c,v 1.20 2001/05/19 08:14:54 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2001 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Microsoft SideWinder joystick family driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/gameport.h>
+
+/*
+ * These are really magic values. Changing them can make a problem go away,
+ * as well as break everything.
+ */
+
+#undef SW_DEBUG
+
+#define SW_START	400	/* The time we wait for the first bit [400 us] */
+#define SW_STROBE	45	/* Max time per bit [45 us] */
+#define SW_TIMEOUT	4000	/* Wait for everything to settle [4 ms] */
+#define SW_KICK		45	/* Wait after A0 fall till kick [45 us] */
+#define SW_END		8	/* Number of bits before end of packet to kick */
+#define SW_FAIL		16	/* Number of packet read errors to fail and reinitialize */
+#define SW_BAD		2	/* Number of packet read errors to switch off 3d Pro optimization */
+#define SW_OK		64	/* Number of packet read successes to switch optimization back on */
+#define SW_LENGTH	512	/* Max number of bits in a packet */
+#define SW_REFRESH	HZ/50	/* Time to wait between updates of joystick data [20 ms] */
+
+#ifdef SW_DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+
+/*
+ * SideWinder joystick types ...
+ */
+
+#define SW_ID_3DP	0
+#define SW_ID_GP	1
+#define SW_ID_PP	2
+#define SW_ID_FFP	3
+#define SW_ID_FSP	4
+#define SW_ID_FFW	5
+
+/*
+ * Names, buttons, axes ...
+ */
+
+static char *sw_name[] = {	"3D Pro", "GamePad", "Precision Pro", "Force Feedback Pro", "FreeStyle Pro",
+				"Force Feedback Wheel" };
+
+static char sw_abs[][7] = {
+	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
+	{ ABS_X, ABS_Y },
+	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
+	{ ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
+	{ ABS_X, ABS_Y,         ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
+	{ ABS_RX, ABS_RUDDER,   ABS_THROTTLE }};
+
+static char sw_bit[][7] = {
+	{ 10, 10,  9, 10,  1,  1 },
+	{  1,  1                 },
+	{ 10, 10,  6,  7,  1,  1 },
+	{ 10, 10,  6,  7,  1,  1 },
+	{ 10, 10,  6,  1,  1     },
+	{ 10,  7,  7,  1,  1     }};
+
+static short sw_btn[][12] = {
+	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_MODE },
+	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE },
+	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
+	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
+	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT },
+	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }};
+
+static struct {
+	int x;
+	int y;
+} sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+struct sw {
+	struct gameport *gameport;
+	struct timer_list timer;
+	struct input_dev dev[4];
+	char name[64];
+	int length;
+	int type;
+	int bits;
+	int number;
+	int fail;
+	int ok;
+	int reads;
+	int bads;
+	int used;
+};
+
+/*
+ * sw_read_packet() is a function which reads either a data packet, or an
+ * identification packet from a SideWinder joystick. The protocol is very,
+ * very, very braindamaged. Microsoft patented it in US patent #5628686.
+ */
+
+static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int length, int id)
+{
+	unsigned long flags;
+	int timeout, bitout, sched, i, kick, start, strobe;
+	unsigned char pending, u, v;
+
+	i = -id;						/* Don't care about data, only want ID */
+	timeout = id ? gameport_time(gameport, SW_TIMEOUT) : 0;	/* Set up global timeout for ID packet */
+	kick = id ? gameport_time(gameport, SW_KICK) : 0;	/* Set up kick timeout for ID packet */
+	start = gameport_time(gameport, SW_START);
+	strobe = gameport_time(gameport, SW_STROBE);
+	bitout = start;
+	pending = 0;
+	sched = 0;
+
+        __save_flags(flags);					/* Quiet, please */
+        __cli();
+
+	gameport_trigger(gameport);				/* Trigger */
+	v = gameport_read(gameport);
+
+	do {
+		bitout--;
+		u = v;
+		v = gameport_read(gameport);
+	} while (!(~v & u & 0x10) && (bitout > 0));		/* Wait for first falling edge on clock */
+
+	if (bitout > 0) bitout = strobe;			/* Extend time if not timed out */
+
+	while ((timeout > 0 || bitout > 0) && (i < length)) {
+
+		timeout--;
+		bitout--;					/* Decrement timers */
+		sched--;
+
+		u = v;
+		v = gameport_read(gameport);
+
+		if ((~u & v & 0x10) && (bitout > 0)) {		/* Rising edge on clock - data bit */
+			if (i >= 0)				/* Want this data */
+				buf[i] = v >> 5;		/* Store it */
+			i++;					/* Advance index */
+			bitout = strobe;			/* Extend timeout for next bit */
+		} 
+
+		if (kick && (~v & u & 0x01)) {			/* Falling edge on axis 0 */
+			sched = kick;				/* Schedule second trigger */
+			kick = 0;				/* Don't schedule next time on falling edge */
+			pending = 1;				/* Mark schedule */
+		} 
+
+		if (pending && sched < 0 && (i > -SW_END)) {	/* Second trigger time */
+			gameport_trigger(gameport);		/* Trigger */
+			bitout = start;				/* Long bit timeout */
+			pending = 0;				/* Unmark schedule */
+			timeout = 0;				/* Switch from global to bit timeouts */ 
+		}
+	}
+
+	__restore_flags(flags);					/* Done - relax */
+
+#ifdef SW_DEBUG
+	{
+		int j;
+		printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);
+		for (j = 0; j < i; j++) printk("%d", buf[j]);
+		printk("]\n");
+	}
+#endif
+
+	return i;
+}
+
+/*
+ * sw_get_bits() and GB() compose bits from the triplet buffer into a __u64.
+ * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
+ * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
+ * is number of bits per triplet.
+ */
+
+#define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits)
+
+static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits)
+{
+	__u64 data = 0;
+	int tri = pos % bits;						/* Start position */
+	int i   = pos / bits;
+	int bit = 0;
+
+	while (num--) {
+		data |= (__u64)((buf[i] >> tri++) & 1) << bit++;	/* Transfer bit */
+		if (tri == bits) {
+			i++;						/* Next triplet */
+			tri = 0;
+		}
+	}
+
+	return data;
+}
+
+/*
+ * sw_init_digital() initializes a SideWinder 3D Pro joystick
+ * into digital mode.
+ */
+
+static void sw_init_digital(struct gameport *gameport)
+{
+	int seq[] = { 140, 140+725, 140+300, 0 };
+	unsigned long flags;
+	int i, t;
+
+        __save_flags(flags);
+        __cli();
+
+	i = 0;
+        do {
+                gameport_trigger(gameport);			/* Trigger */
+		t = gameport_time(gameport, SW_TIMEOUT);
+		while ((gameport_read(gameport) & 1) && t) t--;	/* Wait for axis to fall back to 0 */
+                udelay(seq[i]);					/* Delay magic time */
+        } while (seq[++i]);
+
+	gameport_trigger(gameport);				/* Last trigger */
+
+	__restore_flags(flags);
+}
+
+/*
+ * sw_parity() computes parity of __u64
+ */
+
+static int sw_parity(__u64 t)
+{
+	int x = t ^ (t >> 32);
+	x ^= x >> 16;
+	x ^= x >> 8;
+	x ^= x >> 4;
+	x ^= x >> 2;
+	x ^= x >> 1;
+	return x & 1;
+}
+
+/*
+ * sw_ccheck() checks synchronization bits and computes checksum of nibbles.
+ */
+
+static int sw_check(__u64 t)
+{
+	unsigned char sum = 0;
+
+	if ((t & 0x8080808080808080ULL) ^ 0x80)			/* Sync */
+		return -1;
+
+	while (t) {						/* Sum */
+		sum += t & 0xf;
+		t >>= 4;
+	}
+
+	return sum & 0xf;
+}
+
+/*
+ * sw_parse() analyzes SideWinder joystick data, and writes the results into
+ * the axes and buttons arrays.
+ */
+
+static int sw_parse(unsigned char *buf, struct sw *sw)
+{
+	int hat, i, j;
+	struct input_dev *dev = sw->dev;
+
+	switch (sw->type) {
+
+		case SW_ID_3DP:
+
+			if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8) return -1;
+
+			input_report_abs(dev, ABS_X,        (GB( 3,3) << 7) | GB(16,7));
+			input_report_abs(dev, ABS_Y,        (GB( 0,3) << 7) | GB(24,7));
+			input_report_abs(dev, ABS_RZ,       (GB(35,2) << 7) | GB(40,7));
+			input_report_abs(dev, ABS_THROTTLE, (GB(32,3) << 7) | GB(48,7));
+
+			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
+			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
+
+			for (j = 0; j < 7; j++)
+				input_report_key(dev, sw_btn[SW_ID_3DP][j], !GB(j+8,1));
+
+			input_report_key(dev, BTN_BASE4, !GB(38,1));
+			input_report_key(dev, BTN_BASE5, !GB(37,1));
+
+			return 0;
+
+		case SW_ID_GP:
+
+			for (i = 0; i < sw->number; i ++) {
+
+				if (sw_parity(GB(i*15,15))) return -1;
+
+				input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
+				input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
+
+				for (j = 0; j < 10; j++)
+					input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
+			}
+
+			return 0;
+
+		case SW_ID_PP:
+		case SW_ID_FFP:
+
+			if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8) return -1;
+
+			input_report_abs(dev, ABS_X,        GB( 9,10));
+			input_report_abs(dev, ABS_Y,        GB(19,10));
+			input_report_abs(dev, ABS_RZ,       GB(36, 6));
+			input_report_abs(dev, ABS_THROTTLE, GB(29, 7));
+
+			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
+			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
+
+			for (j = 0; j < 9; j++)
+				input_report_key(dev, sw_btn[SW_ID_PP][j], !GB(j,1));
+
+			return 0;
+
+		case SW_ID_FSP:
+
+			if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8) return -1;
+
+			input_report_abs(dev, ABS_X,        GB( 0,10));
+			input_report_abs(dev, ABS_Y,        GB(16,10));
+			input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
+
+			input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
+			input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
+
+			for (j = 0; j < 6; j++)
+				input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1));
+
+			input_report_key(dev, BTN_TR,     GB(26,1));
+			input_report_key(dev, BTN_START,  GB(27,1));
+			input_report_key(dev, BTN_MODE,   GB(38,1));
+			input_report_key(dev, BTN_SELECT, GB(39,1));
+
+			return 0;
+
+		case SW_ID_FFW:
+
+			if (!sw_parity(GB(0,33))) return -1;
+
+			input_report_abs(dev, ABS_RX,       GB( 0,10));
+			input_report_abs(dev, ABS_RUDDER,   GB(10, 6));
+			input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
+
+			for (j = 0; j < 8; j++)
+				input_report_key(dev, sw_btn[SW_ID_FFW][j], !GB(j+22,1));
+
+			return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * sw_read() reads SideWinder joystick data, and reinitializes
+ * the joystick in case of persistent problems. This is the function that is
+ * called from the generic code to poll the joystick.
+ */
+
+static int sw_read(struct sw *sw)
+{
+	unsigned char buf[SW_LENGTH];
+	int i;
+
+	i = sw_read_packet(sw->gameport, buf, sw->length, 0);
+
+	if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) {		/* Broken packet, try to fix */
+
+		if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) {		/* Last init failed, 1 bit mode */
+			printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on gameport%d"
+				" - going to reinitialize.\n", sw->gameport->number);
+			sw->fail = SW_FAIL;					/* Reinitialize */
+			i = 128;						/* Bogus value */
+		}
+
+		if (i < 66 && GB(0,64) == GB(i*3-66,64))			/* 1 == 3 */
+			i = 66;							/* Everything is fine */
+
+		if (i < 66 && GB(0,64) == GB(66,64))				/* 1 == 2 */
+			i = 66;							/* Everything is fine */
+
+		if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) {		/* 2 == 3 */
+			memmove(buf, buf + i - 22, 22);				/* Move data */
+			i = 66;							/* Carry on */
+		}
+	}
+
+	if (i == sw->length && !sw_parse(buf, sw)) {				/* Parse data */
+
+		sw->fail = 0;
+		sw->ok++;
+
+		if (sw->type == SW_ID_3DP && sw->length == 66			/* Many packets OK */
+			&& sw->ok > SW_OK) {
+
+			printk(KERN_INFO "sidewinder.c: No more trouble on gameport%d"
+				" - enabling optimization again.\n", sw->gameport->number);
+			sw->length = 22;
+		}
+
+		return 0;
+	}
+
+	sw->ok = 0;
+	sw->fail++;
+
+	if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) {	/* Consecutive bad packets */
+
+		printk(KERN_INFO "sidewinder.c: Many bit errors on gameport%d"
+			" - disabling optimization.\n", sw->gameport->number);
+		sw->length = 66;
+	}
+
+	if (sw->fail < SW_FAIL) return -1;					/* Not enough, don't reinitialize yet */
+
+	printk(KERN_WARNING "sidewinder.c: Too many bit errors on gameport%d"
+		" - reinitializing joystick.\n", sw->gameport->number);
+
+	if (!i && sw->type == SW_ID_3DP) {					/* 3D Pro can be in analog mode */
+		udelay(3 * SW_TIMEOUT);
+		sw_init_digital(sw->gameport);
+	}
+
+	udelay(SW_TIMEOUT);
+	i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0);			/* Read normal data packet */
+	udelay(SW_TIMEOUT);
+	sw_read_packet(sw->gameport, buf, SW_LENGTH, i);			/* Read ID packet, this initializes the stick */
+
+	sw->fail = SW_FAIL;
+	
+	return -1;
+}
+
+static void sw_timer(unsigned long private)
+{
+	struct sw *sw = (void *) private;
+	
+	sw->reads++;
+	if (sw_read(sw)) sw->bads++;
+	mod_timer(&sw->timer, jiffies + SW_REFRESH);
+}
+
+static int sw_open(struct input_dev *dev)
+{
+	struct sw *sw = dev->private;
+	if (!sw->used++)
+		mod_timer(&sw->timer, jiffies + SW_REFRESH);
+	return 0;
+}
+
+static void sw_close(struct input_dev *dev)
+{
+	struct sw *sw = dev->private;
+	if (!--sw->used)
+		del_timer(&sw->timer);
+}
+
+/*
+ * sw_print_packet() prints the contents of a SideWinder packet.
+ */
+
+static void sw_print_packet(char *name, int length, unsigned char *buf, char bits)
+{
+	int i;
+
+	printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length);
+	for (i = (((length + 3) >> 2) - 1); i >= 0; i--)
+		printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits));
+	printk("]\n");
+}
+
+/*
+ * sw_3dp_id() translates the 3DP id into a human legible string.
+ * Unfortunately I don't know how to do this for the other SW types.
+ */
+
+static void sw_3dp_id(unsigned char *buf, char *comment)
+{
+	int i;
+	char pnp[8], rev[9];
+
+	for (i = 0; i < 7; i++)						/* ASCII PnP ID */
+		pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);
+
+	for (i = 0; i < 8; i++)						/* ASCII firmware revision */
+		rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);
+
+	pnp[7] = rev[8] = 0;
+
+	sprintf(comment, " [PnP %d.%02d id %s rev %s]",
+		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |		/* Two 6-bit values */
+			sw_get_bits(buf, 16, 6, 1)) / 100,
+		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
+			sw_get_bits(buf, 16, 6, 1)) % 100,
+		 pnp, rev);
+}
+
+/*
+ * sw_guess_mode() checks the upper two button bits for toggling -
+ * indication of that the joystick is in 3-bit mode. This is documented
+ * behavior for 3DP ID packet, and for example the FSP does this in
+ * normal packets instead. Fun ...
+ */
+
+static int sw_guess_mode(unsigned char *buf, int len)
+{
+	int i;
+	unsigned char xor = 0;
+	for (i = 1; i < len; i++) xor |= (buf[i - 1] ^ buf[i]) & 6;
+	return !!xor * 2 + 1;
+}
+
+/*
+ * sw_connect() probes for SideWinder type joysticks.
+ */
+
+static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct sw *sw;
+	int i, j, k, l;
+	unsigned char buf[SW_LENGTH];
+	unsigned char idbuf[SW_LENGTH];
+	unsigned char m = 1;
+	char comment[40];
+
+	comment[0] = 0;
+
+	if (!(sw = kmalloc(sizeof(struct sw), GFP_KERNEL))) return;
+	memset(sw, 0, sizeof(struct sw));
+
+	gameport->private = sw;
+
+	sw->gameport = gameport;
+	init_timer(&sw->timer);
+	sw->timer.data = (long) sw;
+	sw->timer.function = sw_timer;
+
+	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		goto fail1;
+
+	dbg("Init 0: Opened gameport %d, io %#x, speed %d",
+		gameport->number, gameport->io, gameport->speed);
+
+	i = sw_read_packet(gameport, buf, SW_LENGTH, 0);		/* Read normal packet */
+	m |= sw_guess_mode(buf, i);					/* Data packet (1-bit) can carry mode info [FSP] */
+	udelay(SW_TIMEOUT);
+	dbg("Init 1: Mode %d. Length %d.", m , i);
+
+	if (!i) {							/* No data. 3d Pro analog mode? */
+		sw_init_digital(gameport);				/* Switch to digital */
+		udelay(SW_TIMEOUT);
+		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
+		udelay(SW_TIMEOUT);
+		dbg("Init 1b: Length %d.", i);
+		if (!i) goto fail2;					/* No data -> FAIL */
+	}
+
+	j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);		/* Read ID. This initializes the stick */
+	m |= sw_guess_mode(idbuf, j);					/* ID packet should carry mode info [3DP] */
+	dbg("Init 2: Mode %d. ID Length %d.", m , j);
+
+	if (!j) {							/* Read ID failed. Happens in 1-bit mode on PP */
+		udelay(SW_TIMEOUT);
+		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
+		dbg("Init 2b: Mode %d. Length %d.", m, i);
+		if (!i) goto fail2;
+		udelay(SW_TIMEOUT);
+		j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);	/* Retry reading ID */
+		dbg("Init 2c: ID Length %d.", j);
+	}
+
+	sw->type = -1;
+	k = SW_FAIL;							/* Try SW_FAIL times */
+	l = 0;
+
+	do {
+		k--;
+		udelay(SW_TIMEOUT);
+		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Read data packet */
+		dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
+
+		if (i > l) {						/* Longer? As we can only lose bits, it makes */
+									/* no sense to try detection for a packet shorter */
+			l = i;						/* than the previous one */
+
+			sw->number = 1;
+			sw->gameport = gameport;
+			sw->length = i;
+			sw->bits = m;
+
+			dbg("Init 3a: Case %d.\n", i * m);
+
+			switch (i * m) {
+				case 60:
+					sw->number++;
+				case 45:				/* Ambiguous packet length */
+					if (j <= 40) {			/* ID length less or eq 40 -> FSP */	
+				case 43:
+						sw->type = SW_ID_FSP;
+						break;
+					}
+					sw->number++;
+				case 30:
+					sw->number++;
+				case 15:
+					sw->type = SW_ID_GP;
+					break;
+				case 33:
+				case 31:
+					sw->type = SW_ID_FFW;
+					break;
+				case 48:				/* Ambiguous */
+					if (j == 14) {			/* ID length 14*3 -> FFP */
+						sw->type = SW_ID_FFP;
+						sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");
+					} else
+					sw->type = SW_ID_PP;
+					break;
+				case 198:
+					sw->length = 22;
+				case 64:
+					sw->type = SW_ID_3DP;
+					if (j == 160) sw_3dp_id(idbuf, comment);
+					break;
+			}
+		}
+
+	} while (k && (sw->type == -1));
+
+	if (sw->type == -1) {
+		printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
+			"on gameport%d, contact <vojtech@suse.cz>\n", gameport->number);
+		sw_print_packet("ID", j * 3, idbuf, 3);
+		sw_print_packet("Data", i * m, buf, m);
+		goto fail2;
+	}
+
+#ifdef SW_DEBUG
+	sw_print_packet("ID", j * 3, idbuf, 3);
+	sw_print_packet("Data", i * m, buf, m);
+#endif
+
+	k = i;
+	l = j;
+
+	for (i = 0; i < sw->number; i++) {
+		int bits, code;
+
+		sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
+
+		sw->dev[i].private = sw;
+
+		sw->dev[i].open = sw_open;
+		sw->dev[i].close = sw_close;
+
+		sw->dev[i].name = sw->name;
+		sw->dev[i].idbus = BUS_GAMEPORT;
+		sw->dev[i].idvendor = GAMEPORT_ID_VENDOR_MICROSOFT;
+		sw->dev[i].idproduct = sw->type;
+		sw->dev[i].idversion = 0x0100;
+
+		sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+		for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
+			code = sw_abs[sw->type][j];
+			set_bit(code, sw->dev[i].absbit);
+			sw->dev[i].absmax[code] = (1 << bits) - 1;
+			sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0;
+			sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
+			if (code != ABS_THROTTLE)
+				sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
+		}
+
+		for (j = 0; (code = sw_btn[sw->type][j]); j++)
+			set_bit(code, sw->dev[i].keybit);
+
+		input_register_device(sw->dev + i);
+		printk(KERN_INFO "input%d: %s%s on gameport%d.%d [%d-bit id %d data %d]\n",
+			sw->dev[i].number, sw->name, comment, gameport->number, i, m, l, k);
+	}
+
+	return;
+fail2:	gameport_close(gameport);
+fail1:	kfree(sw);
+}
+
+static void sw_disconnect(struct gameport *gameport)
+{
+	int i;
+
+	struct sw *sw = gameport->private;
+	for (i = 0; i < sw->number; i++)
+		input_unregister_device(sw->dev + i);
+	gameport_close(gameport);
+	kfree(sw);
+}
+
+static struct gameport_dev sw_dev = {
+	connect:	sw_connect,
+	disconnect:	sw_disconnect,
+};
+
+int __init sw_init(void)
+{
+	gameport_register_device(&sw_dev);
+	return 0;
+}
+
+void __exit sw_exit(void)
+{
+	gameport_unregister_device(&sw_dev);
+}
+
+module_init(sw_init);
+module_exit(sw_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/spaceball.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,238 @@
+/*
+ * $Id: spaceball.c,v 1.8 2000/11/23 11:42:39 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *  	David Thompson
+ *  	Joseph Krahn
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * SpaceTec SpaceBall 4000 FLX driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ *  Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+
+/*
+ * Constants.
+ */
+
+#define JS_SBALL_MAX_LENGTH	128
+static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
+static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX"; 
+
+/*
+ * Per-Ball data.
+ */
+
+struct spaceball {
+	struct input_dev dev;
+	struct serio *serio;
+	int idx;
+	int escape;
+	unsigned char data[JS_SBALL_MAX_LENGTH];
+};
+
+/*
+ * spaceball_process_packet() decodes packets the driver receives from the
+ * SpaceBall.
+ */
+
+static void spaceball_process_packet(struct spaceball* spaceball)
+{
+	struct input_dev *dev = &spaceball->dev;
+	unsigned char *data = spaceball->data;
+	int i;
+
+	if (spaceball->idx < 2) return;
+
+	printk("%c %d\n", spaceball->data[0], spaceball->idx);
+
+	switch (spaceball->data[0]) {
+
+		case '@':					/* Reset packet */
+			spaceball->data[spaceball->idx - 1] = 0;
+			for (i = 1; i < spaceball->idx && spaceball->data[i] == ' '; i++);
+			printk(KERN_INFO "input%d: %s [%s] on serio%d\n",
+				spaceball->dev.number, spaceball_name, spaceball->data + i, spaceball->serio->number);
+			break;
+
+		case 'D':					/* Ball data */
+			if (spaceball->idx != 15) return;
+			for (i = 0; i < 6; i++) {
+				input_report_abs(dev, spaceball_axes[i], 
+					(__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
+			}
+			break;
+
+		case '.':				/* Button data, part2 */
+			if (spaceball->idx != 3) return;
+			input_report_key(dev, BTN_0,  data[2] & 1);
+			input_report_key(dev, BTN_1, data[2] & 2);
+			break;
+
+		case '?':				/* Error packet */
+			spaceball->data[spaceball->idx - 1] = 0;
+			printk(KERN_ERR "spaceball: Device error. [%s]\n", spaceball->data + 1);
+			break;
+	}
+}
+
+/*
+ * Spaceball 4000 FLX packets all start with a one letter packet-type decriptor,
+ * and end in 0x0d. It uses '^' as an escape for CR, XOFF and XON characters which
+ * can occur in the axis values.
+ */
+
+static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+	struct spaceball *spaceball = serio->private;
+
+	switch (data) {
+		case 0xd:
+			spaceball_process_packet(spaceball);
+			spaceball->idx = 0;
+			spaceball->escape = 0;
+			return;
+		case '^':
+			if (!spaceball->escape) {
+				spaceball->escape = 1;
+				return;
+			}
+			spaceball->escape = 0;
+		case 'M':
+		case 'Q':
+		case 'S':
+			if (spaceball->escape) {
+				spaceball->escape = 0;
+				data &= 0x1f;
+			}
+		default:
+			if (spaceball->escape) {
+				spaceball->escape = 0;
+				printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data);
+			}
+			if (spaceball->idx < JS_SBALL_MAX_LENGTH)
+				spaceball->data[spaceball->idx++] = data;
+			return;
+	}
+}
+
+/*
+ * spaceball_disconnect() is the opposite of spaceball_connect()
+ */
+
+static void spaceball_disconnect(struct serio *serio)
+{
+	struct spaceball* spaceball = serio->private;
+	input_unregister_device(&spaceball->dev);
+	serio_close(serio);
+	kfree(spaceball);
+}
+
+/*
+ * spaceball_connect() is the routine that is called when someone adds a
+ * new serio device. It looks for the Magellan, and if found, registers
+ * it as an input device.
+ */
+
+static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
+{
+	struct spaceball *spaceball;
+	int i, t;
+
+	if (serio->type != (SERIO_RS232 | SERIO_SPACEBALL))
+		return;
+
+	if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
+		return;
+	memset(spaceball, 0, sizeof(struct spaceball));
+
+	spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
+	spaceball->dev.keybit[LONG(BTN_0)] = BIT(BTN_0) | BIT(BTN_1);
+
+	for (i = 0; i < 6; i++) {
+		t = spaceball_axes[i];
+		set_bit(t, spaceball->dev.absbit);
+		spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
+		spaceball->dev.absmax[t] = i < 3 ?  8000 :  1600;
+		spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
+		spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
+	}
+
+	spaceball->serio = serio;
+	spaceball->dev.private = spaceball;
+
+	spaceball->dev.name = spaceball_name;
+	spaceball->dev.idbus = BUS_RS232;
+	spaceball->dev.idvendor = SERIO_SPACEBALL;
+	spaceball->dev.idproduct = 0x0001;
+	spaceball->dev.idversion = 0x0100;
+	
+	serio->private = spaceball;
+
+	if (serio_open(serio, dev)) {
+		kfree(spaceball);
+		return;
+	}
+
+	input_register_device(&spaceball->dev);
+}
+
+/*
+ * The serio device structure.
+ */
+
+static struct serio_dev spaceball_dev = {
+	interrupt:	spaceball_interrupt,
+	connect:	spaceball_connect,
+	disconnect:	spaceball_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+int __init spaceball_init(void)
+{
+	serio_register_device(&spaceball_dev);
+	return 0;
+}
+
+void __exit spaceball_exit(void)
+{
+	serio_unregister_device(&spaceball_dev);
+}
+
+module_init(spaceball_init);
+module_exit(spaceball_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/spaceorb.c	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,227 @@
+/*
+ * $Id: spaceorb.c,v 1.7 2000/05/29 11:19:51 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ * 
+ *  Based on the work of:
+ *  	David Thompson
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * SpaceTec SpaceOrb 360 and Avenger 6dof controller driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ *  Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+
+/*
+ * Constants.
+ */
+
+#define SPACEORB_MAX_LENGTH	64
+
+static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A, BTN_MODE};
+static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ};
+static char *spaceorb_name = "SpaceTec SpaceOrb 360";
+
+/*
+ * Per-Orb data.
+ */
+
+struct spaceorb {
+	struct input_dev dev;
+	struct serio *serio;
+	int idx;
+	unsigned char data[SPACEORB_MAX_LENGTH];
+};
+
+static unsigned char spaceorb_xor[] = "SpaceWare";
+
+static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive queue overflow", "Transmit queue timeout",
+		"Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" }; 
+
+/*
+ * spaceorb_process_packet() decodes packets the driver receives from the
+ * SpaceOrb.
+ */
+
+static void spaceorb_process_packet(struct spaceorb *spaceorb)
+{
+	struct input_dev *dev = &spaceorb->dev;
+	unsigned char *data = spaceorb->data;
+	unsigned char c = 0;
+	int axes[6];
+	int i;
+
+	if (spaceorb->idx < 2) return;
+	for (i = 0; i < spaceorb->idx; i++) c ^= data[i];
+	if (c) return;
+
+	switch (data[0]) {
+
+		case 'R':				/* Reset packet */
+			spaceorb->data[spaceorb->idx - 1] = 0;
+			for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
+			printk(KERN_INFO "input%d: %s [%s] on serio%d\n",
+				 spaceorb->dev.number, spaceorb_name, spaceorb->data + i, spaceorb->serio->number);
+			break;
+
+		case 'D':				/* Ball + button data */
+			if (spaceorb->idx != 12) return;
+			for (i = 0; i < 9; i++) spaceorb->data[i+2] ^= spaceorb_xor[i]; 
+			axes[0] = ( data[2]	 << 3) | (data[ 3] >> 4);
+			axes[1] = ((data[3] & 0x0f) << 6) | (data[ 4] >> 1);
+			axes[2] = ((data[4] & 0x01) << 9) | (data[ 5] << 2) | (data[4] >> 5);
+			axes[3] = ((data[6] & 0x1f) << 5) | (data[ 7] >> 2);
+			axes[4] = ((data[7] & 0x03) << 8) | (data[ 8] << 1) | (data[7] >> 6);
+			axes[5] = ((data[9] & 0x3f) << 4) | (data[10] >> 3);
+			for (i = 0; i < 6; i++)
+				input_report_abs(dev, spaceorb_axes[i], axes[i] - ((axes[i] & 0x200) ? 1024 : 0));
+			for (i = 0; i < 8; i++)
+				input_report_key(dev, spaceorb_buttons[i], (data[1] >> i) & 1);
+			break;
+
+		case 'K':				/* Button data */
+			if (spaceorb->idx != 5) return;
+			for (i = 0; i < 7; i++)
+				input_report_key(dev, spaceorb_buttons[i], (data[2] >> i) & 1);
+
+			break;
+
+		case 'E':				/* Error packet */
+			if (spaceorb->idx != 4) return;
+			printk(KERN_ERR "joy-spaceorb: Device error. [ ");
+			for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
+			printk("]\n");
+			break;
+	}
+}
+
+static void spaceorb_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+	struct spaceorb* spaceorb = serio->private;
+
+	if (~data & 0x80) {
+		if (spaceorb->idx) spaceorb_process_packet(spaceorb);
+		spaceorb->idx = 0;
+	}
+	if (spaceorb->idx < SPACEORB_MAX_LENGTH)
+		spaceorb->data[spaceorb->idx++] = data & 0x7f;
+}
+
+/*
+ * spaceorb_disconnect() is the opposite of spaceorb_connect()
+ */
+
+static void spaceorb_disconnect(struct serio *serio)
+{
+	struct spaceorb* spaceorb = serio->private;
+	input_unregister_device(&spaceorb->dev);
+	serio_close(serio);
+	kfree(spaceorb);
+}
+
+/*
+ * spaceorb_connect() is the routine that is called when someone adds a
+ * new serio device. It looks for the SpaceOrb/Avenger, and if found, registers
+ * it as an input device.
+ */
+
+static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
+{
+	struct spaceorb *spaceorb;
+	int i, t;
+
+	if (serio->type != (SERIO_RS232 | SERIO_SPACEORB))
+		return;
+
+	if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
+		return;
+	memset(spaceorb, 0, sizeof(struct spaceorb));
+
+	spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
+
+	for (i = 0; i < 7; i++)
+		set_bit(spaceorb_buttons[i], &spaceorb->dev.keybit);
+
+	for (i = 0; i < 6; i++) {
+		t = spaceorb_axes[i];
+		set_bit(t, spaceorb->dev.absbit);
+		spaceorb->dev.absmin[t] = -508;
+		spaceorb->dev.absmax[t] =  508;
+	}
+
+	spaceorb->serio = serio;
+	spaceorb->dev.private = spaceorb;
+
+	spaceorb->dev.name = spaceorb_name;
+	spaceorb->dev.idbus = BUS_RS232;
+	spaceorb->dev.idvendor = SERIO_SPACEORB;
+	spaceorb->dev.idproduct = 0x0001;
+	spaceorb->dev.idversion = 0x0100;
+	
+	serio->private = spaceorb;
+
+	if (serio_open(serio, dev)) {
+		kfree(spaceorb);
+		return;
+	}
+
+	input_register_device(&spaceorb->dev);
+}
+
+/*
+ * The serio device structure.
+ */
+
+static struct serio_dev spaceorb_dev = {
+	interrupt:	spaceorb_interrupt,
+	connect:	spaceorb_connect,
+	disconnect:	spaceorb_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+int __init spaceorb_init(void)
+{
+	serio_register_device(&spaceorb_dev);
+	return 0;
+}
+
+void __exit spaceorb_exit(void)
+{
+	serio_unregister_device(&spaceorb_dev);
+}
+
+module_init(spaceorb_init);
+module_exit(spaceorb_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/stinger.c	Sun Feb 10 19:58:03 2002
@@ -0,0 +1,202 @@
+/*
+ * $Id: stinger.c,v 1.4 2001/05/23 09:25:02 vojtech Exp $
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *  Copyright (c) 2000 Mark Fletcher
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Gravis Stinger gamepad driver for Linux
+ */
+
+/*
+ * This program is free warftware; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *  Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+/*
+ * Constants.
+ */
+
+#define STINGER_MAX_LENGTH 8
+
+static char *stinger_name = "Gravis Stinger";
+
+/*
+ * Per-Stinger data.
+ */
+
+struct stinger {
+	struct input_dev dev;
+	int idx;
+	unsigned char data[STINGER_MAX_LENGTH];
+};
+
+/*
+ * stinger_process_packet() decodes packets the driver receives from the
+ * Stinger. It updates the data accordingly.
+ */
+
+static void stinger_process_packet(struct stinger *stinger)
+{
+	struct input_dev *dev = &stinger->dev;
+	unsigned char *data = stinger->data;
+
+	if (!stinger->idx) return;
+
+	input_report_key(dev, BTN_A,	  ((data[0] & 0x20) >> 5));
+	input_report_key(dev, BTN_B,	  ((data[0] & 0x10) >> 4));
+	input_report_key(dev, BTN_C,	  ((data[0] & 0x08) >> 3));
+	input_report_key(dev, BTN_X,	  ((data[0] & 0x04) >> 2));
+	input_report_key(dev, BTN_Y,	  ((data[3] & 0x20) >> 5));
+	input_report_key(dev, BTN_Z,	  ((data[3] & 0x10) >> 4));
+	input_report_key(dev, BTN_TL,     ((data[3] & 0x08) >> 3));
+	input_report_key(dev, BTN_TR,     ((data[3] & 0x04) >> 2));
+	input_report_key(dev, BTN_SELECT, ((data[3] & 0x02) >> 1));
+	input_report_key(dev, BTN_START,   (data[3] & 0x01));
+
+	input_report_abs(dev, ABS_X, (data[1] & 0x3F) - ((data[0] & 0x01) << 6));
+	input_report_abs(dev, ABS_Y, ((data[0] & 0x02) << 5) - (data[2] & 0x3F));
+
+	return;
+}
+
+/*
+ * stinger_interrupt() is called by the low level driver when characters
+ * are ready for us. We then buffer them for further processing, or call the
+ * packet processing routine.
+ */
+
+static void stinger_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+	struct stinger* stinger = serio->private;
+
+	/* All Stinger packets are 4 bytes */
+
+	if (stinger->idx < STINGER_MAX_LENGTH)
+		stinger->data[stinger->idx++] = data;
+
+	if (stinger->idx == 4) {
+		stinger_process_packet(stinger);
+		stinger->idx = 0;
+	}
+
+	return;
+}
+
+/*
+ * stinger_disconnect() is the opposite of stinger_connect()
+ */
+
+static void stinger_disconnect(struct serio *serio)
+{
+	struct stinger* stinger = serio->private;
+	input_unregister_device(&stinger->dev);
+	serio_close(serio);
+	kfree(stinger);
+}
+
+/*
+ * stinger_connect() is the routine that is called when someone adds a
+ * new serio device. It looks for the Stinger, and if found, registers
+ * it as an input device.
+ */
+
+static void stinger_connect(struct serio *serio, struct serio_dev *dev)
+{
+	struct stinger *stinger;
+	int i;
+
+	if (serio->type != (SERIO_RS232 | SERIO_STINGER))
+		return;
+
+	if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
+		return;
+
+	memset(stinger, 0, sizeof(struct stinger));
+
+	stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
+	stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
+					   BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
+					   BIT(BTN_START) | BIT(BTN_SELECT);
+	stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+
+	stinger->dev.name = stinger_name;
+	stinger->dev.idbus = BUS_RS232;
+	stinger->dev.idvendor = SERIO_STINGER;
+	stinger->dev.idproduct = 0x0001;
+	stinger->dev.idversion = 0x0100;
+
+	for (i = 0; i < 2; i++) {
+		stinger->dev.absmax[ABS_X+i] =  64;	
+		stinger->dev.absmin[ABS_X+i] = -64;	
+		stinger->dev.absflat[ABS_X+i] = 4;
+	}
+
+	stinger->dev.private = stinger;
+	
+	serio->private = stinger;
+
+	if (serio_open(serio, dev)) {
+		kfree(stinger);
+		return;
+	}
+
+	input_register_device(&stinger->dev);
+
+	printk(KERN_INFO "input%d: %s on serio%d\n", stinger->dev.number, stinger_name, serio->number);
+}
+
+/*
+ * The serio device structure.
+ */
+
+static struct serio_dev stinger_dev = {
+	interrupt:	stinger_interrupt,
+	connect:	stinger_connect,
+	disconnect:	stinger_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+int __init stinger_init(void)
+{
+	serio_register_device(&stinger_dev);
+	return 0;
+}
+
+void __exit stinger_exit(void)
+{
+	serio_unregister_device(&stinger_dev);
+}
+
+module_init(stinger_init);
+module_exit(stinger_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/tmdc.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,378 @@
+/*
+ * $Id: tmdc.c,v 1.23 2000/11/29 19:52:24 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ *
+ *   Based on the work of:
+ *	Trystan Larey-Williams 
+ *
+ */
+
+/*
+ * ThrustMaster DirectConnect (BSP) joystick family driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gameport.h>
+#include <linux/input.h>
+
+#define TMDC_MAX_START		400	/* 400 us */
+#define TMDC_MAX_STROBE		45	/* 45 us */
+#define TMDC_MAX_LENGTH		13
+#define TMDC_REFRESH_TIME	HZ/50	/* 20 ms */
+
+#define TMDC_MODE_M3DI		1
+#define TMDC_MODE_3DRP		3
+#define TMDC_MODE_AT		4
+#define TMDC_MODE_FM		8
+#define TMDC_MODE_FGP		163
+
+#define TMDC_BYTE_ID		10
+#define TMDC_BYTE_REV		11
+#define TMDC_BYTE_DEF		12
+
+#define TMDC_ABS		7	
+#define TMDC_ABS_HAT		4
+#define TMDC_BTN		16
+
+static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
+static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
+
+static signed char tmdc_abs[TMDC_ABS] =
+	{ ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
+static signed char tmdc_abs_hat[TMDC_ABS_HAT] =
+	{ ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
+static signed char tmdc_abs_at[TMDC_ABS] =
+	{ ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
+static signed char tmdc_abs_fm[TMDC_ABS] =
+	{ ABS_RX, ABS_RY, ABS_X, ABS_Y };
+
+static short tmdc_btn_pad[TMDC_BTN] =
+	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
+static short tmdc_btn_joy[TMDC_BTN] =
+	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
+ 	  BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
+static short tmdc_btn_fm[TMDC_BTN] =
+        { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
+static short tmdc_btn_at[TMDC_BTN] =
+        { BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
+          BTN_BASE3, BTN_BASE2, BTN_BASE };
+
+static struct {
+        int x;
+        int y;
+} tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
+
+struct tmdc {
+	struct gameport *gameport;
+	struct timer_list timer;
+	struct input_dev dev[2];
+	char name[2][64];
+	int mode[2];
+	signed char *abs[2];
+	short *btn[2];
+	unsigned char absc[2];
+	unsigned char btnc[2][4];
+	unsigned char btno[2][4];
+	int used;
+	int reads;
+	int bads;	
+	unsigned char exists;
+};
+
+/*
+ * tmdc_read_packet() reads a ThrustMaster packet.
+ */
+
+static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMDC_MAX_LENGTH])
+{
+	unsigned char u, v, w, x;
+	unsigned long flags;
+	int i[2], j[2], t[2], p, k;
+
+	p = gameport_time(gameport, TMDC_MAX_STROBE);
+
+	for (k = 0; k < 2; k++) {
+		t[k] = gameport_time(gameport, TMDC_MAX_START);
+		i[k] = j[k] = 0;
+	}
+
+	__save_flags(flags);
+	__cli();
+	gameport_trigger(gameport);
+	
+	w = gameport_read(gameport) >> 4;
+
+	do {
+		x = w;
+		w = gameport_read(gameport) >> 4;
+
+		for (k = 0, v = w, u = x; k < 2; k++, v >>= 2, u >>= 2) {
+			if (~v & u & 2) {
+				if (t[k] <= 0 || i[k] >= TMDC_MAX_LENGTH) continue;
+				t[k] = p;
+				if (j[k] == 0) {				 /* Start bit */
+					if (~v & 1) t[k] = 0;
+					data[k][i[k]] = 0; j[k]++; continue;
+				}
+				if (j[k] == 9) {				/* Stop bit */
+					if (v & 1) t[k] = 0;
+					j[k] = 0; i[k]++; continue;
+				}
+				data[k][i[k]] |= (~v & 1) << (j[k]++ - 1);	/* Data bit */
+			}
+			t[k]--; 
+		}
+	} while (t[0] > 0 || t[1] > 0);
+
+	__restore_flags(flags);
+
+	return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
+}
+
+/*
+ * tmdc_read() reads and analyzes ThrustMaster joystick data.
+ */
+
+static void tmdc_timer(unsigned long private)
+{
+	unsigned char data[2][TMDC_MAX_LENGTH];
+	struct tmdc *tmdc = (void *) private;
+	struct input_dev *dev;
+	unsigned char r, bad = 0;
+	int i, j, k, l;
+
+	tmdc->reads++;
+
+	if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
+		bad = 1;
+
+	for (j = 0; j < 2; j++) 
+		if (r & (1 << j) & tmdc->exists) {
+
+			if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
+				bad = 1;
+				continue;
+			}
+
+			dev = tmdc->dev + j;
+
+			for (i = 0; i < tmdc->absc[j]; i++) {
+				if (tmdc->abs[j][i] < 0) continue;
+				input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
+			}
+
+			switch (tmdc->mode[j]) {
+
+				case TMDC_MODE_M3DI:
+
+					i = tmdc_byte_d[0];
+					input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
+					input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i]       & 1));
+					break;
+
+				case TMDC_MODE_AT:
+
+					i = tmdc_byte_a[3];
+					input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
+					input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
+					break;
+
+			}
+
+			for (k = l = 0; k < 4; k++) {
+				for (i = 0; i < tmdc->btnc[j][k]; i++)
+					input_report_key(dev, tmdc->btn[j][i + l],
+						((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
+				l += tmdc->btnc[j][k];
+			}
+	}
+
+	tmdc->bads += bad;
+
+	mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
+}
+
+static int tmdc_open(struct input_dev *dev)
+{
+	struct tmdc *tmdc = dev->private;
+	if (!tmdc->used++)
+		mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);	
+	return 0;
+}
+
+static void tmdc_close(struct input_dev *dev)
+{
+	struct tmdc *tmdc = dev->private;
+	if (!--tmdc->used)
+		del_timer(&tmdc->timer);
+}
+
+/*
+ * tmdc_probe() probes for ThrustMaster type joysticks.
+ */
+
+static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
+{
+	struct models {
+		unsigned char id;
+		char *name;
+		char abs;
+		char hats;
+		char btnc[4];
+		char btno[4];
+		signed char *axes;
+		short *buttons;
+	} models[] = {	{   1, "ThrustMaster Millenium 3D Inceptor",	  6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
+			{   3, "ThrustMaster Rage 3D Gamepad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+			{   4, "ThrustMaster Attack Throttle",		  5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
+			{   8, "ThrustMaster FragMaster",		  4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
+			{ 163, "Thrustmaster Fusion GamePad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+			{   0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
+
+	unsigned char data[2][TMDC_MAX_LENGTH];
+	struct tmdc *tmdc;
+	int i, j, k, l, m;
+
+	if (!(tmdc = kmalloc(sizeof(struct tmdc), GFP_KERNEL)))
+		return;
+	memset(tmdc, 0, sizeof(struct tmdc));
+
+	gameport->private = tmdc;
+
+	tmdc->gameport = gameport;
+	init_timer(&tmdc->timer);
+	tmdc->timer.data = (long) tmdc;
+	tmdc->timer.function = tmdc_timer;
+
+	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+		goto fail1;
+
+	if (!(tmdc->exists = tmdc_read_packet(gameport, data)))
+		goto fail2;
+
+	for (j = 0; j < 2; j++)
+		if (tmdc->exists & (1 << j)) {
+
+			tmdc->mode[j] = data[j][TMDC_BYTE_ID];
+
+			for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
+
+			tmdc->abs[j] = models[m].axes;
+			tmdc->btn[j] = models[m].buttons;
+
+			if (!models[m].id) {
+				models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
+				for (k = 0; k < 4; k++)
+					models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
+			}
+
+			tmdc->absc[j] = models[m].abs;
+			for (k = 0; k < 4; k++) {
+				tmdc->btnc[j][k] = models[m].btnc[k];
+				tmdc->btno[j][k] = models[m].btno[k];
+			}
+
+			sprintf(tmdc->name[j], models[m].name, models[m].abs,
+				(data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
+
+			tmdc->dev[j].private = tmdc;
+			tmdc->dev[j].open = tmdc_open;
+			tmdc->dev[j].close = tmdc_close;
+
+			tmdc->dev[j].name = tmdc->name[j];
+			tmdc->dev[j].idbus = BUS_GAMEPORT;
+			tmdc->dev[j].idvendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
+			tmdc->dev[j].idproduct = models[m].id;
+			tmdc->dev[j].idversion = 0x0100;
+
+			tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+			for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
+				if (tmdc->abs[i] < 0) continue;
+				set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
+				tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
+				tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
+				tmdc->dev[j].absfuzz[tmdc->abs[j][i]] = 2;
+				tmdc->dev[j].absflat[tmdc->abs[j][i]] = 4;
+			}
+
+			for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++) {
+				set_bit(tmdc_abs_hat[i], tmdc->dev[j].absbit);
+				tmdc->dev[j].absmin[tmdc_abs_hat[i]] = -1;
+				tmdc->dev[j].absmax[tmdc_abs_hat[i]] = 1;
+			}
+
+			for (k = l = 0; k < 4; k++) {
+				for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
+					set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
+				l += models[m].btnc[k];
+			}
+
+			input_register_device(tmdc->dev + j);
+			printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
+				tmdc->dev[j].number, tmdc->name[j], gameport->number, j);
+		}
+
+	return;
+fail2:	gameport_close(gameport);
+fail1:	kfree(tmdc);
+}
+
+static void tmdc_disconnect(struct gameport *gameport)
+{
+	struct tmdc *tmdc = gameport->private;
+	int i;
+	for (i = 0; i < 2; i++)
+		if (tmdc->exists & (1 << i)) 
+			input_unregister_device(tmdc->dev + i);
+	gameport_close(gameport);
+	kfree(tmdc);
+}
+
+static struct gameport_dev tmdc_dev = {
+	connect:	tmdc_connect,
+	disconnect:	tmdc_disconnect,
+};
+
+int __init tmdc_init(void)
+{
+	gameport_register_device(&tmdc_dev);
+	return 0;
+}
+
+void __exit tmdc_exit(void)
+{
+	gameport_unregister_device(&tmdc_dev);
+}
+
+module_init(tmdc_init);
+module_exit(tmdc_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/turbografx.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,259 @@
+/*
+ * $Id: turbografx.c,v 1.8 2000/05/29 20:39:38 vojtech Exp $
+ *
+ *  Copyright (c) 1998-2000 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *	Steffen Schwenke
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * TurboGraFX parallel port interface driver for Linux.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/parport.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_LICENSE("GPL");
+MODULE_PARM(tgfx, "2-8i");
+MODULE_PARM(tgfx_2, "2-8i");
+MODULE_PARM(tgfx_3, "2-8i");
+
+#define TGFX_REFRESH_TIME	HZ/100	/* 10 ms */
+
+#define TGFX_TRIGGER		0x08
+#define TGFX_UP			0x10
+#define TGFX_DOWN		0x20	
+#define TGFX_LEFT		0x40
+#define TGFX_RIGHT		0x80
+
+#define TGFX_THUMB		0x02
+#define TGFX_THUMB2		0x04
+#define TGFX_TOP		0x01
+#define TGFX_TOP2		0x08
+
+static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+
+static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
+static char *tgfx_name = "TurboGraFX Multisystem joystick";
+
+struct tgfx {
+	struct pardevice *pd;
+	struct timer_list timer;
+	struct input_dev dev[7];
+	int sticks;
+	int used;
+} *tgfx_base[3];
+
+/*
+ * tgfx_timer() reads and analyzes TurboGraFX joystick data.
+ */
+
+static void tgfx_timer(unsigned long private)
+{
+	struct tgfx *tgfx = (void *) private;
+	struct input_dev *dev;
+	int data1, data2, i;
+
+	for (i = 0; i < 7; i++)
+		if (tgfx->sticks & (1 << i)) {
+
+ 			dev = tgfx->dev + i;
+
+			parport_write_data(tgfx->pd->port, ~(1 << i));
+			data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
+			data2 = parport_read_control(tgfx->pd->port) ^ 0x04;	/* CAVEAT parport */
+
+			input_report_abs(dev, ABS_X, !!(data1 & TGFX_RIGHT) - !!(data1 & TGFX_LEFT));
+			input_report_abs(dev, ABS_Y, !!(data1 & TGFX_DOWN ) - !!(data1 & TGFX_UP  ));
+
+			input_report_key(dev, BTN_TRIGGER, (data1 & TGFX_TRIGGER));
+			input_report_key(dev, BTN_THUMB,   (data2 & TGFX_THUMB  ));
+			input_report_key(dev, BTN_THUMB2,  (data2 & TGFX_THUMB2 ));
+			input_report_key(dev, BTN_TOP,     (data2 & TGFX_TOP    ));
+			input_report_key(dev, BTN_TOP2,    (data2 & TGFX_TOP2   ));
+		}
+
+	mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
+}
+
+static int tgfx_open(struct input_dev *dev)
+{
+        struct tgfx *tgfx = dev->private;
+        if (!tgfx->used++) {
+		parport_claim(tgfx->pd);
+		parport_write_control(tgfx->pd->port, 0x04);
+                mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); 
+	}
+        return 0;
+}
+
+static void tgfx_close(struct input_dev *dev)
+{
+        struct tgfx *tgfx = dev->private;
+        if (!--tgfx->used) {
+                del_timer(&tgfx->timer);
+		parport_write_control(tgfx->pd->port, 0x00);
+        	parport_release(tgfx->pd);
+	}
+}
+
+/*
+ * tgfx_probe() probes for tg gamepads.
+ */
+
+static struct tgfx __init *tgfx_probe(int *config)
+{
+	struct tgfx *tgfx;
+	struct parport *pp;
+	int i, j;
+
+	if (config[0] < 0)
+		return NULL;
+
+	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
+		config[0]--;
+
+	if (!pp) {
+		printk(KERN_ERR "turbografx.c: no such parport\n");
+		return NULL;
+	}
+
+	if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL)))
+		return NULL;
+	memset(tgfx, 0, sizeof(struct tgfx));
+
+	tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+
+	if (!tgfx->pd) {
+		printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
+		kfree(tgfx);
+		return NULL;
+	}
+
+	init_timer(&tgfx->timer);
+	tgfx->timer.data = (long) tgfx;
+	tgfx->timer.function = tgfx_timer;
+
+	tgfx->sticks = 0;
+
+	for (i = 0; i < 7; i++)
+		if (config[i+1] > 0 && config[i+1] < 6) {
+
+			tgfx->sticks |= (1 << i);
+
+			tgfx->dev[i].private = tgfx;
+			tgfx->dev[i].open = tgfx_open;
+			tgfx->dev[i].close = tgfx_close;
+
+			tgfx->dev[i].name = tgfx_name;
+			tgfx->dev[i].idbus = BUS_PARPORT;
+			tgfx->dev[i].idvendor = 0x0003;
+			tgfx->dev[i].idproduct = config[i+1];
+			tgfx->dev[i].idversion = 0x0100;
+
+			tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+			tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+
+			for (j = 0; j < config[i+1]; j++)
+				set_bit(tgfx_buttons[j], tgfx->dev[i].keybit); 
+
+			tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
+			tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
+
+			input_register_device(tgfx->dev + i);
+			printk(KERN_INFO "input%d: %d-button Multisystem joystick on %s\n",
+				tgfx->dev[i].number, config[i+1], tgfx->pd->port->name);
+		}
+
+        if (!tgfx->sticks) {
+		parport_unregister_device(tgfx->pd);
+		kfree(tgfx);
+		return NULL;
+        }
+		
+	return tgfx;
+}
+
+#ifndef MODULE
+int __init tgfx_setup(char *str)
+{
+	int i, ints[9];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 8; i++) tgfx[i] = ints[i + 1];
+	return 1;
+}
+int __init tgfx_setup_2(char *str)
+{
+	int i, ints[9];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 8; i++) tgfx_2[i] = ints[i + 1];
+	return 1;
+}
+int __init tgfx_setup_3(char *str)
+{
+	int i, ints[9];
+	get_options(str, ARRAY_SIZE(ints), ints);
+	for (i = 0; i <= ints[0] && i < 8; i++) tgfx_3[i] = ints[i + 1];
+	return 1;
+}
+__setup("tgfx=", tgfx_setup);
+__setup("tgfx_2=", tgfx_setup_2);
+__setup("tgfx_3=", tgfx_setup_3);
+#endif
+
+int __init tgfx_init(void)
+{
+	tgfx_base[0] = tgfx_probe(tgfx);
+	tgfx_base[1] = tgfx_probe(tgfx_2);
+	tgfx_base[2] = tgfx_probe(tgfx_3);
+
+	if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
+		return 0;
+
+	return -ENODEV;
+}
+
+void __exit tgfx_exit(void)
+{
+	int i, j;
+
+	for (i = 0; i < 3; i++) 
+		if (tgfx_base[i]) {
+			for (j = 0; j < 7; j++)
+				if (tgfx_base[i]->sticks & (1 << j))
+					input_unregister_device(tgfx_base[i]->dev + j);
+		parport_unregister_device(tgfx_base[i]->pd);
+	}
+}
+
+module_init(tgfx_init);
+module_exit(tgfx_exit);
diff -Nru a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/joystick/warrior.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,214 @@
+/*
+ * $Id: warrior.c,v 1.8 2000/05/31 13:17:12 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * Logitech WingMan Warrior joystick driver for Linux
+ */
+
+/*
+ * This program is free warftware; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ *  Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+/*
+ * Constants.
+ */
+
+#define WARRIOR_MAX_LENGTH	16
+static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 }; 
+static char *warrior_name = "Logitech WingMan Warrior";
+
+/*
+ * Per-Warrior data.
+ */
+
+struct warrior {
+	struct input_dev dev;
+	int idx, len;
+	unsigned char data[WARRIOR_MAX_LENGTH];
+};
+
+/*
+ * warrior_process_packet() decodes packets the driver receives from the
+ * Warrior. It updates the data accordingly.
+ */
+
+static void warrior_process_packet(struct warrior *warrior)
+{
+	struct input_dev *dev = &warrior->dev;
+	unsigned char *data = warrior->data;
+
+	if (!warrior->idx) return;
+
+	switch ((data[0] >> 4) & 7) {
+		case 1:					/* Button data */
+			input_report_key(dev, BTN_TRIGGER,  data[3]       & 1);
+			input_report_key(dev, BTN_THUMB,   (data[3] >> 1) & 1);
+			input_report_key(dev, BTN_TOP,     (data[3] >> 2) & 1);
+			input_report_key(dev, BTN_TOP2,    (data[3] >> 3) & 1);
+			return;
+		case 3:					/* XY-axis info->data */
+			input_report_abs(dev, ABS_X, ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5)));
+			input_report_abs(dev, ABS_Y, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
+			return;
+		case 5:					/* Throttle, spinner, hat info->data */
+			input_report_abs(dev, ABS_THROTTLE, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
+			input_report_abs(dev, ABS_HAT0X, (data[3] & 2 ? 1 : 0) - (data[3] & 1 ? 1 : 0));
+			input_report_abs(dev, ABS_HAT0Y, (data[3] & 8 ? 1 : 0) - (data[3] & 4 ? 1 : 0));
+			input_report_rel(dev, REL_DIAL,  (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5));
+			return;
+	}
+}
+
+/*
+ * warrior_interrupt() is called by the low level driver when characters
+ * are ready for us. We then buffer them for further processing, or call the
+ * packet processing routine.
+ */
+
+static void warrior_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+	struct warrior* warrior = serio->private;
+
+	if (data & 0x80) {
+		if (warrior->idx) warrior_process_packet(warrior);
+		warrior->idx = 0;
+		warrior->len = warrior_lengths[(data >> 4) & 7];
+	}
+
+	if (warrior->idx < warrior->len)
+		warrior->data[warrior->idx++] = data;
+
+	if (warrior->idx == warrior->len) {
+		if (warrior->idx) warrior_process_packet(warrior);	
+		warrior->idx = 0;
+		warrior->len = 0;
+	}
+}
+
+/*
+ * warrior_disconnect() is the opposite of warrior_connect()
+ */
+
+static void warrior_disconnect(struct serio *serio)
+{
+	struct warrior* warrior = serio->private;
+	input_unregister_device(&warrior->dev);
+	serio_close(serio);
+	kfree(warrior);
+}
+
+/*
+ * warrior_connect() is the routine that is called when someone adds a
+ * new serio device. It looks for the Warrior, and if found, registers
+ * it as an input device.
+ */
+
+static void warrior_connect(struct serio *serio, struct serio_dev *dev)
+{
+	struct warrior *warrior;
+	int i;
+
+	if (serio->type != (SERIO_RS232 | SERIO_WARRIOR))
+		return;
+
+	if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
+		return;
+
+	memset(warrior, 0, sizeof(struct warrior));
+
+	warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);	
+	warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
+	warrior->dev.relbit[0] = BIT(REL_DIAL);
+	warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
+
+	warrior->dev.name = warrior_name;
+	warrior->dev.idbus = BUS_RS232;
+	warrior->dev.idvendor = SERIO_WARRIOR;
+	warrior->dev.idproduct = 0x0001;
+	warrior->dev.idversion = 0x0100;
+
+	for (i = 0; i < 2; i++) {
+		warrior->dev.absmax[ABS_X+i] = -64;	
+		warrior->dev.absmin[ABS_X+i] =  64;	
+		warrior->dev.absflat[ABS_X+i] = 8;	
+	}
+
+	warrior->dev.absmax[ABS_THROTTLE] = -112;	
+	warrior->dev.absmin[ABS_THROTTLE] =  112;	
+
+	for (i = 0; i < 2; i++) {
+		warrior->dev.absmax[ABS_HAT0X+i] = -1;	
+		warrior->dev.absmin[ABS_HAT0X+i] =  1;	
+	}
+
+	warrior->dev.private = warrior;
+	
+	serio->private = warrior;
+
+	if (serio_open(serio, dev)) {
+		kfree(warrior);
+		return;
+	}
+
+	input_register_device(&warrior->dev);
+
+	printk(KERN_INFO "input%d: Logitech WingMan Warrior on serio%d\n", warrior->dev.number, serio->number);
+}
+
+/*
+ * The serio device structure.
+ */
+
+static struct serio_dev warrior_dev = {
+	interrupt:	warrior_interrupt,
+	connect:	warrior_connect,
+	disconnect:	warrior_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+int __init warrior_init(void)
+{
+	serio_register_device(&warrior_dev);
+	return 0;
+}
+
+void __exit warrior_exit(void)
+{
+	serio_unregister_device(&warrior_dev);
+}
+
+module_init(warrior_init);
+module_exit(warrior_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/keybdev.c b/drivers/input/keybdev.c
--- a/drivers/input/keybdev.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/input/keybdev.c	Sun Feb 10 19:58:05 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $
+ * $Id: keybdev.c,v 1.16 2002/01/09 04:21:41 lethal Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  Input driver to keyboard driver binding.
- *
- *  Sponsored by SuSE
+ *  Input core to console keyboard binding.
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <linux/config.h>
@@ -37,10 +35,16 @@
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core to console keyboard binding");
+MODULE_LICENSE("GPL");
+
+char keybdev_name[] = "keyboard";
+
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
     defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH) || \
     defined(CONFIG_PPC) || defined(__mc68000__) || defined(__hppa__) || \
-    defined(__arm__)
+    defined(__arm__) || defined(__x86_64__)
 
 static int x86_sysrq_alt = 0;
 #ifdef CONFIG_SPARC64
@@ -48,8 +52,6 @@
 extern void batten_down_hatches(void);
 #endif
 
-static int jp_kbd_109 = 1;	/* Yes, .jp is the default. See 51142. */
-
 static unsigned short x86_keycodes[256] =
 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -62,7 +64,7 @@
 	360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
 	103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
 	291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
-	118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
+	118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269,
 	271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
 	308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
 	332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
@@ -167,26 +169,38 @@
 	}
 }
 
+/* Tell the user who may be running in X and not see the console that we have 
+   panic'ed. This is to distingush panics from "real" lockups. 
+   Could in theory send the panic message as morse, but that is left as an
+   exercise for the reader.  */ 
+
+void panic_blink(void)
+{ 
+	static unsigned long last_jiffie;
+	static char led;
+	/* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is different. */
+	if (jiffies - last_jiffie > HZ/2) {
+		led ^= 0x01 | 0x04;
+		keybdev_ledfunc(led);
+		last_jiffie = jiffies;
+	}
+}  
+
 void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
 {
 	if (type != EV_KEY) return;
-
-	if (emulate_raw(code, down))
-		printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", code);
-
+	emulate_raw(code, down);
 	tasklet_schedule(&keyboard_tasklet);
 }
 
-static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct input_handle *handle;
 	int i;
 
-	if (!test_bit(EV_KEY, dev->evbit))
-		return NULL;
-
-	for (i = KEY_RESERVED; i < BTN_MISC; i++)
-		if (test_bit(i, dev->keybit)) break;
+	for (i = KEY_ESC; i < BTN_MISC; i++)
+		if (test_bit(i, dev->keybit))
+			break;
 
 	if (i == BTN_MISC)
  		return NULL;
@@ -196,41 +210,42 @@
 	memset(handle, 0, sizeof(struct input_handle));
 
 	handle->dev = dev;
+	handle->name = keybdev_name;
 	handle->handler = handler;
 
 	input_open_device(handle);
 
-//	printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number);
-
 	return handle;
 }
 
 static void keybdev_disconnect(struct input_handle *handle)
 {
-//	printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number);
 	input_close_device(handle);
 	kfree(handle);
 }
+
+static struct input_device_id keybdev_ids[] = {
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) },
+	},	
+	{ }, 	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, keybdev_ids);
 	
 static struct input_handler keybdev_handler = {
 	event:		keybdev_event,
 	connect:	keybdev_connect,
 	disconnect:	keybdev_disconnect,
+	name:		"keybdev",
+	id_table:	keybdev_ids,
 };
 
 static int __init keybdev_init(void)
 {
 	input_register_handler(&keybdev_handler);
 	kbd_ledfunc = keybdev_ledfunc;
-
-	if (jp_kbd_109) {
-		x86_keycodes[0xb5] = 0x73;	/* backslash, underscore */
-		x86_keycodes[0xb6] = 0x70;
-		x86_keycodes[0xb7] = 0x7d;	/* Yen, pipe */
-		x86_keycodes[0xb8] = 0x79;
-		x86_keycodes[0xb9] = 0x7b;
-	}
-
 	return 0;
 }
 
@@ -243,7 +258,3 @@
 module_init(keybdev_init);
 module_exit(keybdev_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input driver to keyboard driver binding");
-MODULE_PARM(jp_kbd_109, "i");
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c
--- a/drivers/input/mousedev.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/input/mousedev.c	Sun Feb 10 19:58:05 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: mousedev.c,v 1.24 2000/11/15 10:57:45 vojtech Exp $
+ * $Id: mousedev.c,v 1.38 2001/12/26 21:08:33 jsimmons Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  Input driver to ImExPS/2 device driver module.
- *
- *  Sponsored by SuSE
+ *  Input driver to ExplorerPS/2 device driver module.
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #define MOUSEDEV_MINOR_BASE 	32
@@ -41,6 +39,10 @@
 #include <linux/smp_lock.h>
 #include <linux/random.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
+MODULE_LICENSE("GPL");
+
 #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
 #define CONFIG_INPUT_MOUSEDEV_SCREEN_X	1024
 #endif
@@ -52,6 +54,7 @@
 	int exist;
 	int open;
 	int minor;
+	char name[16];
 	wait_queue_head_t wait;
 	struct mousedev_list *list;
 	struct input_handle handle;
@@ -89,8 +92,6 @@
 	struct mousedev_list *list;
 	int index, size;
 
-	add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
-
 	while (*mousedev) {
 		list = (*mousedev)->list;
 		while (list) {
@@ -101,13 +102,23 @@
 					switch (code) {
 						case ABS_X:	
 							size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
-							list->dx += (value * xres - list->oldx) / size;
-							list->oldx += list->dx * size;
+							if (size != 0) {
+								list->dx += (value * xres - list->oldx) / size;
+								list->oldx += list->dx * size;
+							} else {
+								list->dx += value - list->oldx;
+								list->oldx += list->dx;
+							}
 							break;
 						case ABS_Y:
 							size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
-							list->dy -= (value * yres - list->oldy) / size;
-							list->oldy -= list->dy * size;
+							if (size != 0) {
+								list->dy -= (value * yres - list->oldy) / size;
+								list->oldy -= list->dy * size;
+							} else {
+								list->dy -= value - list->oldy;
+								list->oldy -= list->dy;
+							}
 							break;
 					}
 					break;
@@ -169,7 +180,7 @@
 {
 	struct mousedev_list *list = file->private_data;
 	struct mousedev_list **listptr;
-	
+
 	listptr = &list->mousedev->list;
 	mousedev_fasync(-1, file, 0);
 
@@ -344,7 +355,7 @@
 	if (!list->ready && !list->buffer) {
 
 		add_wait_queue(&list->mousedev->wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		while (!list->ready) {
 
@@ -360,7 +371,7 @@
 			schedule();
 		}
 
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&list->mousedev->wait, &wait);
 	}
 
@@ -401,19 +412,11 @@
 	fasync:		mousedev_fasync,
 };
 
-static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct mousedev *mousedev;
 	int minor = 0;
 
-	if (!test_bit(EV_KEY, dev->evbit) ||
-	   (!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit)))
-		return NULL;
-
-	if ((!test_bit(EV_REL, dev->evbit) || !test_bit(REL_X, dev->relbit)) &&
-	    (!test_bit(EV_ABS, dev->evbit) || !test_bit(ABS_X, dev->absbit)))
-		return NULL;
-
 	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
 	if (minor == MOUSEDEV_MINORS) {
 		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
@@ -425,11 +428,12 @@
 	memset(mousedev, 0, sizeof(struct mousedev));
 	init_waitqueue_head(&mousedev->wait);
 
-	mousedev->exist = 1;
 	mousedev->minor = minor;
 	mousedev_table[minor] = mousedev;
+	sprintf(mousedev->name, "mouse%d", minor);
 
 	mousedev->handle.dev = dev;
+	mousedev->handle.name = mousedev->name;
 	mousedev->handle.handler = handler;
 	mousedev->handle.private = mousedev;
 
@@ -438,7 +442,7 @@
 	if (mousedev_mix.open)
 		input_open_device(&mousedev->handle);
 
-//	printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number);
+	mousedev->exist = 1;
 
 	return &mousedev->handle;
 }
@@ -459,6 +463,26 @@
 		kfree(mousedev);
 	}
 }
+
+static struct input_device_id mousedev_ids[] = {
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_REL) },
+		keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
+		relbit: { BIT(REL_X) | BIT(REL_Y) },
+	},	/* A mouse like device, at least one button, two relative axes */
+
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		keybit: { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+		absbit: { BIT(ABS_X) | BIT(ABS_Y) },
+	},	/* A tablet like device, at least touch detection, two absolute axes */
+
+	{ }, 	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, mousedev_ids);
 	
 static struct input_handler mousedev_handler = {
 	event:		mousedev_event,
@@ -466,6 +490,8 @@
 	disconnect:	mousedev_disconnect,
 	fops:		&mousedev_fops,
 	minor:		MOUSEDEV_MINOR_BASE,
+	name:		"mousedev",
+	id_table:	mousedev_ids,
 };
 
 static int __init mousedev_init(void)
@@ -492,10 +518,6 @@
 
 module_init(mousedev_init);
 module_exit(mousedev_exit);
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
-MODULE_LICENSE("GPL");
 
 MODULE_PARM(xres, "i");
 MODULE_PARM_DESC(xres, "Horizontal screen resolution");
diff -Nru a/drivers/input/serio/Config.help b/drivers/input/serio/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/serio/Config.help	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,26 @@
+CONFIG_SERIO
+  Say Yes here if you have any input device that uses serial I/O to
+  communicate with the system. This includes the 
+		* standard AT keyboard and PS/2 mouse *
+  as well as serial mice, Sun keyboards, some joysticks and 6dof
+  devices and more.
+
+  If unsure, say Y.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called serio.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_SERIO_SERPORT
+  Say Y here if you plan to use an input device (mouse, joystick,
+  tablet, 6dof) that communicates over the RS232 serial (COM) port.
+ 
+  More information is available: <file:Documentation/input/input.txt>
+
+  If unsure, say Y.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called serport.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/input/serio/Config.in b/drivers/input/serio/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/serio/Config.in	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,7 @@
+#
+# Input core configuration
+#
+
+tristate 'Serial i/o support' CONFIG_SERIO
+
+dep_tristate '  Serial port line discipline' CONFIG_SERIO_SERPORT $CONFIG_SERIO 
diff -Nru a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/serio/Makefile	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,20 @@
+#
+# Makefile for the input core drivers.
+#
+
+# The target object and module list name.
+
+O_TARGET	:= seriodrv.o
+
+# Objects that export symbols.
+
+export-objs	:= serio.o
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_SERIO)		+= serio.o
+obj-$(CONFIG_SERIO_SERPORT)	+= serport.o
+
+# The global Rules.make.
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/serio/serio.c	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,133 @@
+/*
+ * $Id: serio.c,v 1.5 2000/06/04 17:44:59 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ *  The Serio abstraction module
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(serio_register_port);
+EXPORT_SYMBOL(serio_unregister_port);
+EXPORT_SYMBOL(serio_register_device);
+EXPORT_SYMBOL(serio_unregister_device);
+EXPORT_SYMBOL(serio_open);
+EXPORT_SYMBOL(serio_close);
+EXPORT_SYMBOL(serio_rescan);
+
+static struct serio *serio_list;
+static struct serio_dev *serio_dev;
+static int serio_number;
+
+static void serio_find_dev(struct serio *serio)
+{
+        struct serio_dev *dev = serio_dev;
+
+        while (dev && !serio->dev) {
+		if (dev->connect)
+                	dev->connect(serio, dev);
+                dev = dev->next;
+        }
+}
+
+void serio_rescan(struct serio *serio)
+{
+	if (serio->dev && serio->dev->disconnect)
+		serio->dev->disconnect(serio);
+	serio_find_dev(serio);
+}
+
+void serio_register_port(struct serio *serio)
+{
+	serio->number = serio_number++;
+	serio->next = serio_list;	
+	serio_list = serio;
+	serio_find_dev(serio);
+}
+
+void serio_unregister_port(struct serio *serio)
+{
+        struct serio **serioptr = &serio_list;
+
+        while (*serioptr && (*serioptr != serio)) serioptr = &((*serioptr)->next);
+        *serioptr = (*serioptr)->next;
+
+	if (serio->dev && serio->dev->disconnect)
+		serio->dev->disconnect(serio);
+
+	serio_number--;
+}
+
+void serio_register_device(struct serio_dev *dev)
+{
+	struct serio *serio = serio_list;
+
+	dev->next = serio_dev;	
+	serio_dev = dev;
+
+	while (serio) {
+		if (!serio->dev && dev->connect)
+			dev->connect(serio, dev);
+		serio = serio->next;
+	}
+}
+
+void serio_unregister_device(struct serio_dev *dev)
+{
+        struct serio_dev **devptr = &serio_dev;
+	struct serio *serio = serio_list;
+
+        while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next);
+        *devptr = (*devptr)->next;
+
+	while (serio) {
+		if (serio->dev == dev && dev->disconnect)
+			dev->disconnect(serio);
+		serio_find_dev(serio);
+		serio = serio->next;
+	}
+}
+
+int serio_open(struct serio *serio, struct serio_dev *dev)
+{
+	if (serio->open(serio))
+		return -1;
+	serio->dev = dev;
+	return 0;
+}
+
+void serio_close(struct serio *serio)
+{
+	serio->close(serio);
+	serio->dev = NULL;
+}
diff -Nru a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/serio/serport.c	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,226 @@
+/*
+ * $Id: serport.c,v 1.7 2001/05/25 19:00:27 jdeneux Exp $
+ *
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * This is a module that converts a tty line into a much simpler
+ * 'serial io port' abstraction that the input device drivers use.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ *  Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <linux/tty.h>
+
+struct serport {
+	struct tty_struct *tty;
+	wait_queue_head_t wait;
+	struct serio serio;
+};
+
+/*
+ * Callback functions from the serio code.
+ */
+
+static int serport_serio_write(struct serio *serio, unsigned char data)
+{
+	struct serport *serport = serio->driver;
+	return -(serport->tty->driver.write(serport->tty, 0, &data, 1) != 1);
+}
+
+static int serport_serio_open(struct serio *serio)
+{
+        return 0;
+}
+
+static void serport_serio_close(struct serio *serio)
+{
+	struct serport *serport = serio->driver;
+	wake_up_interruptible(&serport->wait);
+}
+
+/*
+ * serport_ldisc_open() is the routine that is called upon setting our line
+ * discipline on a tty. It looks for the Mag, and if found, registers
+ * it as a joystick device.
+ */
+
+static int serport_ldisc_open(struct tty_struct *tty)
+{
+	struct serport *serport;
+
+	MOD_INC_USE_COUNT;
+
+	if (!(serport = kmalloc(sizeof(struct serport), GFP_KERNEL))) {
+		MOD_DEC_USE_COUNT;
+		return -ENOMEM;
+	}
+
+	memset(serport, 0, sizeof(struct serport));
+
+	serport->tty = tty;
+	tty->disc_data = serport;
+
+	serport->serio.type = SERIO_RS232;
+	serport->serio.write = serport_serio_write;
+	serport->serio.open = serport_serio_open;
+	serport->serio.close = serport_serio_close;
+	serport->serio.driver = serport;
+
+	init_waitqueue_head(&serport->wait);
+
+	return 0;
+}
+
+/*
+ * serport_ldisc_close() is the opposite of serport_ldisc_open()
+ */
+
+static void serport_ldisc_close(struct tty_struct *tty)
+{
+	struct serport *serport = (struct serport*) tty->disc_data;
+	kfree(serport);
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * serport_ldisc_receive() is called by the low level tty driver when characters
+ * are ready for us. We forward the characters, one by one to the 'interrupt'
+ * routine.
+ */
+
+static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+{
+	struct serport *serport = (struct serport*) tty->disc_data;
+	int i;
+	for (i = 0; i < count; i++)
+		if (serport->serio.dev)
+			serport->serio.dev->interrupt(&serport->serio, cp[i], 0);
+}
+
+/*
+ * serport_ldisc_room() reports how much room we do have for receiving data.
+ * Although we in fact have infinite room, we need to specify some value
+ * here, and 256 seems to be reasonable.
+ */
+
+static int serport_ldisc_room(struct tty_struct *tty)
+{
+	return 256;
+}
+
+/*
+ * serport_ldisc_read() just waits indefinitely if everything goes well. 
+ * However, when the serio driver closes the serio port, it finishes,
+ * returning 0 characters.
+ */
+
+static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char * buf, size_t nr)
+{
+	struct serport *serport = (struct serport*) tty->disc_data;
+	DECLARE_WAITQUEUE(wait, current);
+	char name[32];
+
+#ifdef CONFIG_DEVFS_FS
+	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);
+#endif
+
+	serio_register_port(&serport->serio);
+
+	printk(KERN_INFO "serio%d: Serial port %s\n", serport->serio.number, name);
+
+	add_wait_queue(&serport->wait, &wait);
+	current->state = TASK_INTERRUPTIBLE;
+
+	while(serport->serio.type && !signal_pending(current)) schedule();
+
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&serport->wait, &wait);
+
+	serio_unregister_port(&serport->serio);
+
+	return 0;
+}
+
+/*
+ * serport_ldisc_ioctl() allows to set the port protocol, and device ID
+ */
+
+static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	struct serport *serport = (struct serport*) tty->disc_data;
+	
+	switch (cmd) {
+		case SPIOCSTYPE:
+			return get_user(serport->serio.type, (unsigned long *) arg);
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * The line discipline structure.
+ */
+
+static struct tty_ldisc serport_ldisc = {
+	name:		"input",
+	open:		serport_ldisc_open,
+	close:		serport_ldisc_close,
+	read:		serport_ldisc_read,
+	ioctl:		serport_ldisc_ioctl,
+	receive_buf:	serport_ldisc_receive,
+	receive_room:	serport_ldisc_room,
+};
+
+/*
+ * The functions for insering/removing us as a module.
+ */
+
+int __init serport_init(void)
+{
+        if (tty_register_ldisc(N_MOUSE, &serport_ldisc)) {
+                printk(KERN_ERR "serport.c: Error registering line discipline.\n");
+		return -ENODEV;
+	}
+
+	return  0;
+}
+
+void __exit serport_exit(void)
+{
+	tty_register_ldisc(N_MOUSE, NULL);
+}
+
+module_init(serport_init);
+module_exit(serport_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/isdn/Makefile b/drivers/isdn/Makefile
--- a/drivers/isdn/Makefile	Sun Feb 10 19:58:06 2002
+++ b/drivers/isdn/Makefile	Sun Feb 10 19:58:06 2002
@@ -2,7 +2,7 @@
 
 # The target object and module list name.
 
-O_TARGET	:= isdn.a
+O_TARGET	:= vmlinux-obj.o
 
 # Objects that export symbols.
 
diff -Nru a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c
--- a/drivers/isdn/avmb1/capifs.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/isdn/avmb1/capifs.c	Sun Feb 10 19:58:05 2002
@@ -281,17 +281,12 @@
 	return 0;
 }
 
-struct super_block *capifs_read_super(struct super_block *s, void *data,
-				      int silent)
+static int capifs_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * root_inode;
 	struct dentry * root;
 	struct capifs_sb_info *sbi;
 
-	/* Super block already completed? */
-	if (s->s_root)
-		goto out;
-
 	sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
 	if ( !sbi )
 		goto fail;
@@ -317,7 +312,6 @@
 	s->s_blocksize_bits = 10;
 	s->s_magic = CAPIFS_SUPER_MAGIC;
 	s->s_op = &capifs_sops;
-	s->s_root = NULL;
 
 	/*
 	 * Get the root inode and dentry, but defer checking for errors.
@@ -332,15 +326,6 @@
 	} 
 	root = d_alloc_root(root_inode);
 
-	/*
-	 * Check whether somebody else completed the super block.
-	 */
-	if (s->s_root) {
-		if (root) dput(root);
-		else iput(root_inode);
-		goto out;
-	}
-
 	if (!root) {
 		printk("capifs: get root dentry failed\n");
 		/*
@@ -352,15 +337,6 @@
 		goto fail;
 	}
 
-	/*
-	 * Check whether somebody else completed the super block.
-	 */
-	if (s->s_root)
-		goto out;
-	
-	/*
-	 * Success! Install the root dentry now to indicate completion.
-	 */
 	s->s_root = root;
 
 	sbi->next = mounts;
@@ -368,11 +344,9 @@
 		SBI(sbi->next)->back = &(sbi->next);
 	sbi->back = &mounts;
 	mounts = s;
-
-out:	/* Success ... somebody else completed the super block for us. */ 
-	return s;
+	return 0;
 fail:
-	return NULL;
+	return -EINVAL;
 }
 
 static int capifs_statfs(struct super_block *sb, struct statfs *buf)
@@ -400,7 +374,17 @@
 	return inode;
 }
 
-static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
+static struct super_block *capifs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, capifs_fill_super);
+}
+
+static struct file_system_type capifs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"capifs",
+	get_sb:		capifs_get_sb,
+};
 
 void capifs_new_ncci(char type, unsigned int num, kdev_t device)
 {
diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
--- a/drivers/isdn/hisax/elsa.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/isdn/hisax/elsa.c	Sun Feb 10 19:58:04 2002
@@ -396,7 +396,8 @@
 	}
 	if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
 		val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
-		if (!(val & ELSA_PCI_IRQ_MASK))
+		if (!test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags) && 
+		    !(val & ELSA_PCI_IRQ_MASK))
 			return;
 	}
 #if ARCOFI_USE
@@ -868,7 +869,7 @@
 {
 	long flags;
 	int bytecnt;
-	u_char val;
+	u_char val, pci_rev;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
@@ -992,6 +993,7 @@
 			cs->irq = dev_qs1000->irq;
 			cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
 			cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
+			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
 		} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
 			if (pci_enable_device(dev_qs3000))
@@ -1000,6 +1002,7 @@
 			cs->irq = dev_qs3000->irq;
 			cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
 			cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
+			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
 		} else {
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
 			return(0);
@@ -1013,15 +1016,9 @@
 			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
 			return(0);
 		}
-		if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
-			printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
-			printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
-			printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
-			printk(KERN_WARNING "Elsa: Waiting 5 sec to sync discs\n");
-			save_flags(flags);
-			sti();
-			HZDELAY(500);	/* wait 500*10 ms */
-			restore_flags(flags);
+		if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
+			printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
+			set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
 		}
 		cs->hw.elsa.ale  = cs->hw.elsa.base;
 		cs->hw.elsa.isac = cs->hw.elsa.base +1;
diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
--- a/drivers/isdn/hisax/gazel.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/isdn/hisax/gazel.c	Sun Feb 10 19:58:03 2002
@@ -382,12 +382,16 @@
 			outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
 			break;
 		case R753:
-			plxcntrl = inl(addr + PLX_CNTRL);
+			if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags))
+				/* we can't read, assume the default */
+				plxcntrl = 0x18784db6;
+			else
+				plxcntrl = inl(addr + PLX_CNTRL);
 			plxcntrl |= (RESET_9050 + RESET_GAZEL);
 			outl(plxcntrl, addr + PLX_CNTRL);
-			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
 			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
 			HZDELAY(4);
+			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
 			outl(plxcntrl, addr + PLX_CNTRL);
 			HZDELAY(10);
 			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
@@ -549,6 +553,7 @@
 	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
 	u_char pci_irq = 0, found;
 	u_int nbseek, seekcard;
+	u_char pci_rev;
 
 	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
 
@@ -623,6 +628,18 @@
 			printk(KERN_INFO
 			    "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
 			cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+			/* 
+			 * Erratum for PLX9050, revision 1:
+			 * If bit 7 of BAR 0/1 is set, local config registers
+			 * can not be read (write is okay)
+			 */
+			if (cs->hw.gazel.cfg_reg & 0x80) {
+				pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
+				if (pci_rev == 1) {
+					printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n");
+					set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
+				}
+			}
 			break;
 	}
 
diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
--- a/drivers/isdn/hisax/hisax.h	Sun Feb 10 19:58:04 2002
+++ b/drivers/isdn/hisax/hisax.h	Sun Feb 10 19:58:04 2002
@@ -859,6 +859,7 @@
 #define FLG_ARCOFI_TIMER	8
 #define FLG_ARCOFI_ERROR	9
 #define FLG_HW_L1_UINT		10
+#define FLG_BUGGY_PLX9050       11
 
 struct IsdnCardState {
 	unsigned char typ;
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	Sun Feb 10 19:58:05 2002
@@ -20,6 +20,7 @@
  *
  * o POWER PC
  * o clean up debugging
+ * o tx_skb at PH_DEACTIVATE time
  */
 
 #include <linux/version.h>
@@ -368,10 +369,7 @@
 	unsigned long flags;
 	unsigned char *p;
 
-	DBG(0x40, "hdlc_fill_fifo");
-
-	if (!skb)
-		BUG();
+	DBG(0x40, "");
 
 	if (skb->len == 0)
 		BUG();
@@ -581,14 +579,14 @@
 		adapter->write_ctrl(bcs, 5);
 		break;
 	case L1_MODE_TRANS:
-		bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
-		adapter->write_ctrl(bcs, 5);
-		bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
-		adapter->write_ctrl(bcs, 1);
-		bcs->ctrl.sr.cmd = 0;
-		break;
 	case L1_MODE_HDLC:
-		bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+		bcs->rcvidx = 0;
+		bcs->tx_cnt = 0;
+		bcs->tx_skb = NULL;
+		if (mode == L1_MODE_TRANS)
+			bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
+		else
+			bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
 		adapter->write_ctrl(bcs, 5);
 		bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
 		adapter->write_ctrl(bcs, 1);
diff -Nru a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
--- a/drivers/isdn/hisax/st5481.h	Sun Feb 10 19:58:04 2002
+++ b/drivers/isdn/hisax/st5481.h	Sun Feb 10 19:58:04 2002
@@ -409,10 +409,10 @@
  * Submit an URB with error reporting. This is a macro so
  * the __FUNCTION__ returns the caller function name.
  */
-#define SUBMIT_URB(urb) \
+#define SUBMIT_URB(urb, mem_flags) \
 ({ \
 	int status; \
-	if ((status = usb_submit_urb(urb)) < 0) { \
+	if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \
 		WARN("usb_submit_urb failed,status=%d", status); \
 	} \
         status; \
diff -Nru a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
--- a/drivers/isdn/hisax/st5481_b.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/isdn/hisax/st5481_b.c	Sun Feb 10 19:58:05 2002
@@ -115,7 +115,7 @@
 
 	DBG_ISO_PACKET(0x200,urb);
 
-	SUBMIT_URB(urb);
+	SUBMIT_URB(urb, GFP_KERNEL);
 }
 
 /*
diff -Nru a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
--- a/drivers/isdn/hisax/st5481_d.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/isdn/hisax/st5481_d.c	Sun Feb 10 19:58:06 2002
@@ -356,10 +356,10 @@
 
 	DBG_ISO_PACKET(0x20,urb);
 
-	if (usb_submit_urb(urb) < 0) {
+	if (usb_submit_urb(urb, GFP_KERNEL) < 0) {
 		// There is another URB queued up
 		urb->transfer_flags = USB_ISO_ASAP;
-		SUBMIT_URB(urb);
+		SUBMIT_URB(urb, GFP_KERNEL);
 	}	
 }
 
@@ -450,7 +450,7 @@
 	urb->transfer_flags = USB_ISO_ASAP;
 
 	DBG_ISO_PACKET(0x20,urb);
-	SUBMIT_URB(urb);
+	SUBMIT_URB(urb, GFP_KERNEL);
 }
 
 static void dout_short_fifo(struct FsmInst *fsm, int event, void *arg)
diff -Nru a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
--- a/drivers/isdn/hisax/st5481_usb.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/isdn/hisax/st5481_usb.c	Sun Feb 10 19:58:04 2002
@@ -48,7 +48,7 @@
 	// Prepare the URB
 	urb->dev = adapter->usb_dev;
 
-	SUBMIT_URB(urb);
+	SUBMIT_URB(urb, GFP_KERNEL);
 }
 
 /*
@@ -357,7 +357,7 @@
 	adapter->leds = RED_LED; 
 
 	// Start receiving on the interrupt endpoint
-	SUBMIT_URB(intr->urb); 
+	SUBMIT_URB(intr->urb, GFP_KERNEL); 
 
 	while ((request = init_cmd_table[i++])) {
 		value = init_cmd_table[i++];
@@ -517,7 +517,7 @@
 	urb->dev = in->adapter->usb_dev;
 	urb->actual_length = 0;
 
-	SUBMIT_URB(urb);
+	SUBMIT_URB(urb, GFP_KERNEL);
 }
 
 int __devinit st5481_setup_in(struct st5481_in *in)
@@ -603,10 +603,10 @@
 	DBG(4,"");
 
 	in->urb[0]->dev = adapter->usb_dev;
-	SUBMIT_URB(in->urb[0]);
+	SUBMIT_URB(in->urb[0], GFP_KERNEL);
 
 	in->urb[1]->dev = adapter->usb_dev;
-	SUBMIT_URB(in->urb[1]);
+	SUBMIT_URB(in->urb[1], GFP_KERNEL);
 }
 
 void st5481_in_mode(struct st5481_in *in, int mode)
diff -Nru a/drivers/isdn/isdn_audio.c b/drivers/isdn/isdn_audio.c
--- a/drivers/isdn/isdn_audio.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/isdn/isdn_audio.c	Sun Feb 10 19:58:03 2002
@@ -227,8 +227,10 @@
 	:	"0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
 	:	"memory", "ax");
 #else
-	while (n--)
-		*buff++ = table[*(unsigned char *)buff];
+	while (n--) {
+		*buff = table[*buff];
+		buff++;
+	}
 #endif
 }
 
diff -Nru a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
--- a/drivers/isdn/isdn_common.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/isdn/isdn_common.c	Sun Feb 10 19:58:05 2002
@@ -2178,7 +2178,6 @@
 
 static void isdn_unregister_devfs(int k)
 {
-	devfs_unregister (dev->devfs_handle_isdnX[k]);
 	devfs_unregister (dev->devfs_handle_isdnctrlX[k]);
 }
 
@@ -2226,22 +2225,18 @@
 #else   /* CONFIG_DEVFS_FS */
 static void isdn_register_devfs(int dummy)
 {
-	return;
 }
 
 static void isdn_unregister_devfs(int dummy)
 {
-	return;
 }
 
 static void isdn_init_devfs(void)
 {
-    return;
 }
 
 static void isdn_cleanup_devfs(void)
 {
-    return;
 }
 
 #endif  /* CONFIG_DEVFS_FS */
diff -Nru a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
--- a/drivers/isdn/isdn_net.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/isdn/isdn_net.c	Sun Feb 10 19:58:06 2002
@@ -369,8 +369,7 @@
 							       l->name, l->chargetime, l->chargeint);
 							isdn_net_hangup(&p->dev);
 						}
-					} else
-						isdn_net_hangup(&p->dev);
+					}
 				} else if (l->hupflags & ISDN_INHUP)
 					isdn_net_hangup(&p->dev);
 			}
@@ -2872,7 +2871,7 @@
 		else
 			lp->hupflags &= ~ISDN_INHUP;
 		if (cfg->chargeint > 10) {
-			lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
+			lp->hupflags |= ISDN_HAVECHARGE | ISDN_MANCHARGE;
 			lp->chargeint = cfg->chargeint * HZ;
 		}
 		if (cfg->p_encap != lp->p_encap) {
diff -Nru a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
--- a/drivers/macintosh/nvram.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/macintosh/nvram.c	Sun Feb 10 19:58:04 2002
@@ -13,6 +13,7 @@
 #include <linux/fcntl.h>
 #include <linux/nvram.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 
@@ -20,6 +21,7 @@
 
 static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
 {
+	lock_kernel();
 	switch (origin) {
 	case 1:
 		offset += file->f_pos;
@@ -28,9 +30,12 @@
 		offset += NVRAM_SIZE;
 		break;
 	}
-	if (offset < 0)
+	if (offset < 0) {
+		unlock_kernel();
 		return -EINVAL;
+	}
 	file->f_pos = offset;
+	unlock_kernel();
 	return file->f_pos;
 }
 
diff -Nru a/drivers/media/video/Config.in b/drivers/media/video/Config.in
--- a/drivers/media/video/Config.in	Sun Feb 10 19:58:03 2002
+++ b/drivers/media/video/Config.in	Sun Feb 10 19:58:03 2002
@@ -22,10 +22,8 @@
    fi
 fi
 if [ "$CONFIG_PARPORT" != "n" ]; then
-   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      if [ "$CONFIG_PARPORT_1284" != "n" ]; then
-         dep_tristate '  Winbond W9966CF Webcam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_W9966 $CONFIG_VIDEO_DEV $CONFIG_PARPORT
-      fi
+   if [ "$CONFIG_PARPORT_1284" != "n" ]; then
+      dep_tristate '  W9966CF Webcam (FlyCam Supra and others) Video For Linux' CONFIG_VIDEO_W9966 $CONFIG_VIDEO_DEV $CONFIG_PARPORT
    fi
 fi
 dep_tristate '  CPiA Video For Linux' CONFIG_VIDEO_CPIA $CONFIG_VIDEO_DEV
diff -Nru a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
--- a/drivers/media/video/cpia_usb.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/media/video/cpia_usb.c	Sun Feb 10 19:58:03 2002
@@ -246,13 +246,13 @@
 	ucpia->sbuf[1].urb->next = ucpia->sbuf[0].urb;
 	ucpia->sbuf[0].urb->next = ucpia->sbuf[1].urb;
 	
-	err = usb_submit_urb(ucpia->sbuf[0].urb);
+	err = usb_submit_urb(ucpia->sbuf[0].urb, GFP_KERNEL);
 	if (err) {
 		printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n",
 			err);
 		goto error_urb1;
 	}
-	err = usb_submit_urb(ucpia->sbuf[1].urb);
+	err = usb_submit_urb(ucpia->sbuf[1].urb, GFP_KERNEL);
 	if (err) {
 		printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n",
 			err);
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/message/i2o/i2o_block.c	Sun Feb 10 19:58:04 2002
@@ -40,6 +40,8 @@
  *		Serial number scanning to find duplicates for FC multipathing
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/major.h>
 
 #include <linux/module.h>
diff -Nru a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
--- a/drivers/message/i2o/i2o_config.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/message/i2o/i2o_config.c	Sun Feb 10 19:58:05 2002
@@ -25,6 +25,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff -Nru a/drivers/message/i2o/i2o_core.c b/drivers/message/i2o/i2o_core.c
--- a/drivers/message/i2o/i2o_core.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/message/i2o/i2o_core.c	Sun Feb 10 19:58:04 2002
@@ -22,6 +22,8 @@
  * 
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff -Nru a/drivers/message/i2o/i2o_lan.c b/drivers/message/i2o/i2o_lan.c
--- a/drivers/message/i2o/i2o_lan.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/message/i2o/i2o_lan.c	Sun Feb 10 19:58:04 2002
@@ -25,6 +25,8 @@
  *	TODO:		tests for other LAN classes (Token Ring, Fibre Channel)
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/config.h>
 #include <linux/module.h>
 
diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
--- a/drivers/message/i2o/i2o_scsi.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/message/i2o/i2o_scsi.c	Sun Feb 10 19:58:05 2002
@@ -31,6 +31,8 @@
  *		Fix the resource management problems.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff -Nru a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
--- a/drivers/mtd/mtdchar.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/mtd/mtdchar.c	Sun Feb 10 19:58:04 2002
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 #ifdef CONFIG_DEVFS_FS
@@ -31,6 +32,7 @@
 {
 	struct mtd_info *mtd=(struct mtd_info *)file->private_data;
 
+	lock_kernel();
 	switch (orig) {
 	case 0:
 		/* SEEK_SET */
@@ -45,6 +47,7 @@
 		file->f_pos =mtd->size + offset;
 		break;
 	default:
+		unlock_kernel();
 		return -EINVAL;
 	}
 
@@ -53,6 +56,7 @@
 	else if (file->f_pos >= mtd->size)
 		file->f_pos = mtd->size - 1;
 
+	unlock_kernel();
 	return file->f_pos;
 }
 
diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c
--- a/drivers/net/3c501.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/net/3c501.c	Sun Feb 10 19:58:03 2002
@@ -87,8 +87,12 @@
  *
  */
 
+#define DRV_NAME	"3c501"
+#define DRV_VERSION	"2001/11/17"
+
+
 static const char version[] =
-    "3c501.c: 2000/02/08 Alan Cox (alan@redhat.com).\n";
+	DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@redhat.com).\n";
 
 /*
  *	Braindamage remaining:
@@ -108,7 +112,9 @@
 #include <linux/errno.h>
 #include <linux/config.h>	/* for CONFIG_IP_MULTICAST */
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
 
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -139,12 +145,14 @@
 static int  el1_close(struct net_device *dev);
 static struct net_device_stats *el1_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 #define EL1_IO_EXTENT	16
 
 #ifndef EL_DEBUG
 #define EL_DEBUG  0	/* use 0 for production, 1 for devel., >2 for debug */
 #endif			/* Anything above 5 is wordy death! */
+#define debug el_debug
 static int el_debug = EL_DEBUG;
 
 /*
@@ -377,6 +385,7 @@
 	dev->stop = &el1_close;
 	dev->get_stats = &el1_get_stats;
 	dev->set_multicast_list = &set_multicast_list;
+	dev->do_ioctl = netdev_ioctl;
 
 	/*
 	 *	Setup the generic properties
@@ -915,6 +924,86 @@
 	}
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 #ifdef MODULE
 
 static struct net_device dev_3c501 = {
diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c
--- a/drivers/net/3c503.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/3c503.c	Sun Feb 10 19:58:04 2002
@@ -29,11 +29,17 @@
     Paul Gortmaker	: add support for the 2nd 8kB of RAM on 16 bit cards.
     Paul Gortmaker	: multiple card support for module users.
     rjohnson@analogic.com : Fix up PIO interface for efficient operation.
+    Jeff Garzik		: ethtool support
 
 */
 
+#define DRV_NAME	"3c503"
+#define DRV_VERSION	"1.10a"
+#define DRV_RELDATE	"11/17/2001"
+
+
 static const char version[] =
-    "3c503.c:v1.10 9/23/93  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Donald Becker (becker@scyld.com)\n";
 
 #include <linux/module.h>
 
@@ -45,7 +51,9 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/ethtool.h>
 
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
@@ -74,6 +82,7 @@
 			   int ring_offset);
 static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 			 int ring_page);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 
 /* This routine probes for a memory-mapped 3c503 board by looking for
@@ -301,6 +310,7 @@
 
     dev->open = &el2_open;
     dev->stop = &el2_close;
+    dev->do_ioctl = &netdev_ioctl;
 
     if (dev->mem_start)
 	printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
@@ -607,6 +617,71 @@
     outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
     return;
 }
+
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
+
 #ifdef MODULE
 #define MAX_EL2_CARDS	4	/* Max number of EL2 cards per module */
 
diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c
--- a/drivers/net/3c505.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/3c505.c	Sun Feb 10 19:58:06 2002
@@ -35,8 +35,13 @@
  *                      Philip Blundell <Philip.Blundell@pobox.com>
  *              Multicard/soft configurable dma channel/rev 2 hardware support
  *                      by Christopher Collins <ccollins@pcug.org.au>
+ *		Ethtool support (jgarzik), 11/17/2001
  */
 
+#define DRV_NAME	"3c505"
+#define DRV_VERSION	"1.10a"
+
+
 /* Theory of operation:
  *
  * The 3c505 is quite an intelligent board.  All communication with it is done
@@ -103,6 +108,9 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -148,10 +156,11 @@
  *********************************************************/
 
 #ifdef ELP_DEBUG
-static const int elp_debug = ELP_DEBUG;
+static int elp_debug = ELP_DEBUG;
 #else
-static const int elp_debug;
+static int elp_debug;
 #endif
+#define debug elp_debug
 
 /*
  *  0 = no messages (well, some)
@@ -630,7 +639,7 @@
 	disable_dma(dev->dma);
 	clear_dma_ff(dev->dma);
 	set_dma_mode(dev->dma, 0x04);	/* dma read */
-	set_dma_addr(dev->dma, virt_to_bus(target));
+	set_dma_addr(dev->dma, isa_virt_to_bus(target));
 	set_dma_count(dev->dma, rlen);
 	enable_dma(dev->dma);
 	release_dma_lock(flags);
@@ -1029,10 +1038,10 @@
 
 	if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS) {
 		memcpy(adapter->dma_buffer, skb->data, nlen);
-		target = virt_to_bus(adapter->dma_buffer);
+		target = isa_virt_to_bus(adapter->dma_buffer);
 	}
 	else {
-		target = virt_to_bus(skb->data);
+		target = isa_virt_to_bus(skb->data);
 	}
 	adapter->current_dma.skb = skb;
 
@@ -1260,6 +1269,87 @@
 	}
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
+
 /******************************************************
  *
  * initialise Etherlink Plus board
@@ -1280,6 +1370,7 @@
 	dev->tx_timeout = elp_timeout;			/* local */
 	dev->watchdog_timeo = 10*HZ;
 	dev->set_multicast_list = elp_set_mc_list;	/* local */
+	dev->do_ioctl = netdev_ioctl;			/* local */
 
 	/* Setup the generic properties */
 	ether_setup(dev);
diff -Nru a/drivers/net/3c507.c b/drivers/net/3c507.c
--- a/drivers/net/3c507.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/3c507.c	Sun Feb 10 19:58:06 2002
@@ -25,8 +25,12 @@
 	The statistics need to be updated correctly.
 */
 
+#define DRV_NAME		"3c507"
+#define DRV_VERSION		"1.10a"
+#define DRV_RELDATE		"11/17/2001"
+
 static const char version[] =
-	"3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n";
 
 
 #include <linux/module.h>
@@ -52,6 +56,9 @@
 #include <linux/in.h>
 #include <linux/string.h>
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -70,6 +77,8 @@
 #define NET_DEBUG 1
 #endif
 static unsigned int net_debug = NET_DEBUG;
+#define debug net_debug
+
 
 /* A zero-terminated list of common I/O addresses to be probed. */
 static unsigned int netcard_portlist[] __initdata =
@@ -296,6 +305,7 @@
 
 static void hardware_send_packet(struct net_device *dev, void *buf, short length);
 static void init_82586_mem(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 
 /* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -427,6 +437,7 @@
 	dev->get_stats	= el16_get_stats;
 	dev->tx_timeout = el16_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->do_ioctl = netdev_ioctl;
 
 	ether_setup(dev);	/* Generic ethernet behaviour */
 
@@ -864,6 +875,88 @@
 	lp->rx_head = rx_head;
 	lp->rx_tail = rx_tail;
 }
+
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
+
 #ifdef MODULE
 static struct net_device dev_3c507;
 static int io = 0x300;
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/3c509.c	Sun Feb 10 19:58:04 2002
@@ -43,8 +43,14 @@
 		v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au>
 			- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
 			- Reviewed against 1.18 from scyld.com
+		v1.18 17Nov2001 Jeff Garzik <jgarzik@mandrakesoft.com>
+			- ethtool support
 */
 
+#define DRV_NAME	"3c509"
+#define DRV_VERSION	"1.18a"
+#define DRV_RELDATE	"17Nov2001"
+
 /* A few values that may be tweaked. */
 
 /* Time in jiffies before concluding the transmitter is hung. */
@@ -70,12 +76,14 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>	/* for udelay() */
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
 
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
-static char versionA[] __initdata = "3c509.c:1.18 12Mar2001 becker@scyld.com\n";
+static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE "becker@scyld.com\n";
 static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n";
 
 #ifdef EL3_DEBUG
@@ -84,6 +92,7 @@
 static int el3_debug = 2;
 #endif
 
+
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
    anyway if you want to understand driver details. */
@@ -158,6 +167,7 @@
 static int el3_close(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void el3_tx_timeout (struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 #ifdef CONFIG_MCA
 struct el3_mca_adapters_struct {
@@ -513,6 +523,7 @@
 	dev->set_multicast_list = &set_multicast_list;
 	dev->tx_timeout = el3_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->do_ioctl = netdev_ioctl;
 
 	/* Fill in the generic fields of the device structure. */
 	ether_setup(dev);
@@ -1003,6 +1014,85 @@
 	return 0;
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = el3_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		el3_debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 #ifdef MODULE
 /* Parameters that may be passed into the module. */
 static int debug = -1;
diff -Nru a/drivers/net/3c515.c b/drivers/net/3c515.c
--- a/drivers/net/3c515.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/3c515.c	Sun Feb 10 19:58:04 2002
@@ -16,9 +16,17 @@
 	2/2/00- Added support for kernel-level ISAPnP 
 		by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo
 	Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox.
+	
+	11/17/2001 - Added ethtool support (jgarzik)
+
 */
 
-static char *version = "3c515.c:v0.99-sn 2000/02/12 becker@cesdis.gsfc.nasa.gov and others\n";
+#define DRV_NAME		"3c515"
+#define DRV_VERSION		"0.99t"
+#define DRV_RELDATE		"17-Nov-2001"
+
+static char *version =
+DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n";
 
 #define CORKSCREW 1
 
@@ -63,6 +71,9 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -393,6 +404,7 @@
 static void update_stats(int addr, struct net_device *dev);
 static struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 
 /* 
@@ -721,6 +733,7 @@
 	dev->stop = &corkscrew_close;
 	dev->get_stats = &corkscrew_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
+	dev->do_ioctl = netdev_ioctl;
 
 	return 0;
 }
@@ -844,7 +857,7 @@
 			struct sk_buff *skb;
 			if (i < (RX_RING_SIZE - 1))
 				vp->rx_ring[i].next =
-				    virt_to_bus(&vp->rx_ring[i + 1]);
+				    isa_virt_to_bus(&vp->rx_ring[i + 1]);
 			else
 				vp->rx_ring[i].next = 0;
 			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
@@ -855,10 +868,10 @@
 				break;	/* Bad news!  */
 			skb->dev = dev;	/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = virt_to_bus(skb->tail);
+			vp->rx_ring[i].addr = isa_virt_to_bus(skb->tail);
 		}
-		vp->rx_ring[i - 1].next = virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
-		outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+		vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
+		outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
 	}
 	if (vp->full_bus_master_tx) {	/* Boomerang bus master Tx. */
 		vp->cur_tx = vp->dirty_tx = 0;
@@ -1053,7 +1066,7 @@
 		/* vp->tx_full = 1; */
 		vp->tx_skbuff[entry] = skb;
 		vp->tx_ring[entry].next = 0;
-		vp->tx_ring[entry].addr = virt_to_bus(skb->data);
+		vp->tx_ring[entry].addr = isa_virt_to_bus(skb->data);
 		vp->tx_ring[entry].length = skb->len | 0x80000000;
 		vp->tx_ring[entry].status = skb->len | 0x80000000;
 
@@ -1066,9 +1079,9 @@
 			    0) break;
 		if (prev_entry)
 			prev_entry->next =
-			    virt_to_bus(&vp->tx_ring[entry]);
+			    isa_virt_to_bus(&vp->tx_ring[entry]);
 		if (inl(ioaddr + DownListPtr) == 0) {
-			outl(virt_to_bus(&vp->tx_ring[entry]),
+			outl(isa_virt_to_bus(&vp->tx_ring[entry]),
 			     ioaddr + DownListPtr);
 			queued_packet++;
 		}
@@ -1205,7 +1218,7 @@
 			while (lp->cur_tx - dirty_tx > 0) {
 				int entry = dirty_tx % TX_RING_SIZE;
 				if (inl(ioaddr + DownListPtr) ==
-				    virt_to_bus(&lp->tx_ring[entry]))
+				    isa_virt_to_bus(&lp->tx_ring[entry]))
 					break;	/* It still hasn't been processed. */
 				if (lp->tx_skbuff[entry]) {
 					dev_kfree_skb_irq(lp->
@@ -1414,7 +1427,7 @@
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 				/* 'skb_put()' points to the start of sk_buff data area. */
 				memcpy(skb_put(skb, pkt_len),
-				       bus_to_virt(vp->rx_ring[entry].
+				       isa_bus_to_virt(vp->rx_ring[entry].
 						   addr), pkt_len);
 				rx_copy++;
 			} else {
@@ -1424,11 +1437,11 @@
 				vp->rx_skbuff[entry] = NULL;
 				temp = skb_put(skb, pkt_len);
 				/* Remove this checking code for final release. */
-				if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
+				if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp)
 					    printk("%s: Warning -- the skbuff addresses do not match"
 					     " in boomerang_rx: %p vs. %p / %p.\n",
 					     dev->name,
-					     bus_to_virt(vp->
+					     isa_bus_to_virt(vp->
 							 rx_ring[entry].
 							 addr), skb->head,
 					     temp);
@@ -1451,7 +1464,7 @@
 				break;	/* Bad news!  */
 			skb->dev = dev;	/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
+			vp->rx_ring[entry].addr = isa_virt_to_bus(skb->tail);
 			vp->rx_skbuff[entry] = skb;
 		}
 		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
@@ -1591,6 +1604,87 @@
 
 	outw(new_mode, ioaddr + EL3_CMD);
 }
+
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = corkscrew_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		corkscrew_debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 
 #ifdef MODULE
 void cleanup_module(void)
diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c
--- a/drivers/net/3c523.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/3c523.c	Sun Feb 10 19:58:06 2002
@@ -81,10 +81,15 @@
    added option to disable multicast as is causes problems
        Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk>
        Stuart Adamson <stuart.adamson@compsoc.net>
+   Nov 2001
+   added support for ethtool (jgarzik)
 	
    $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $
  */
 
+#define DRV_NAME		"3c523"
+#define DRV_VERSION		"17-Nov-2001"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -95,6 +100,9 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/mca.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -182,6 +190,7 @@
 #ifdef ELMC_MULTICAST
 static void set_multicast_list(struct net_device *dev);
 #endif
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 /* helper-functions */
 static int init586(struct net_device *dev);
@@ -304,13 +313,13 @@
 	char *iscp_addrs[2];
 	int i = 0;
 
-	p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
-	p->memtop = bus_to_virt((unsigned long)where) + size;
+	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000;
+	p->memtop = isa_bus_to_virt((unsigned long)where) + size;
 	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
 	memset((char *) p->scp, 0, sizeof(struct scp_struct));
 	p->scp->sysbus = SYSBUSVAL;	/* 1 = 8Bit-Bus, 0 = 16 Bit */
 
-	iscp_addrs[0] = bus_to_virt((unsigned long)where);
+	iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
 	iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
 
 	for (i = 0; i < 2; i++) {
@@ -347,7 +356,7 @@
 	DELAY(2);
 
 	p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
-	p->scb = (struct scb_struct *) bus_to_virt(dev->mem_start);
+	p->scb = (struct scb_struct *) isa_bus_to_virt(dev->mem_start);
 	p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
 
 	memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
@@ -529,8 +538,8 @@
 	}
 	dev->mem_end = dev->mem_start + size;	/* set mem_end showed by 'ifconfig' */
 
-	pr->memtop = bus_to_virt(dev->mem_start) + size;
-	pr->base = (unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
+	pr->memtop = isa_bus_to_virt(dev->mem_start) + size;
+	pr->base = (unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
 	alloc586(dev);
 
 	elmc_id_reset586();	/* make sure it doesn't generate spurious ints */
@@ -563,7 +572,8 @@
 #else
 	dev->set_multicast_list = NULL;
 #endif
-
+	dev->do_ioctl = netdev_ioctl;
+	
 	ether_setup(dev);
 
 	/* note that we haven't actually requested the IRQ from the kernel.
@@ -1214,6 +1224,69 @@
 }
 #endif
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "MCA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 /*************************************************************************/
 
 #ifdef MODULE
diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c
--- a/drivers/net/3c527.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/net/3c527.c	Sun Feb 10 19:58:03 2002
@@ -16,8 +16,12 @@
  *
  */
 
+#define DRV_NAME		"3c527"
+#define DRV_VERSION		"0.6a"
+#define DRV_RELDATE		"2001/11/17"
+
 static const char *version =
-	"3c527.c:v0.6 2001/03/03 Richard Proctor (rnp@netlink.co.nz)\n";
+DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Proctor (rnp@netlink.co.nz)\n";
 
 /**
  * DOC: Traps for the unwary
@@ -90,6 +94,9 @@
 #include <linux/in.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -108,7 +115,7 @@
  * The name of the card. Is used for messages and in the requests for
  * io regions, irqs and dma channels
  */
-static const char* cardname = "3c527";
+static const char* cardname = DRV_NAME;
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
@@ -213,6 +220,7 @@
 static struct	net_device_stats *mc32_get_stats(struct net_device *dev);
 static void	mc32_set_multicast_list(struct net_device *dev);
 static void	mc32_reset_multicast_list(struct net_device *dev);
+static int	netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 /**
  * mc32_probe 	-	Search for supported boards
@@ -470,16 +478,16 @@
 		base|=(inb(dev->base_addr)<<(8*i));
 	}
 	
-	lp->exec_box=bus_to_virt(dev->mem_start+base);
+	lp->exec_box=isa_bus_to_virt(dev->mem_start+base);
 	
 	base=lp->exec_box->data[1]<<16|lp->exec_box->data[0];  
 	
 	lp->base = dev->mem_start+base;
 	
-	lp->rx_box=bus_to_virt(lp->base + lp->exec_box->data[2]); 
-	lp->tx_box=bus_to_virt(lp->base + lp->exec_box->data[3]);
+	lp->rx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[2]); 
+	lp->tx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[3]);
 	
-	lp->stats = bus_to_virt(lp->base + lp->exec_box->data[5]);
+	lp->stats = isa_bus_to_virt(lp->base + lp->exec_box->data[5]);
 
 	/*
 	 *	Descriptor chains (card relative)
@@ -502,7 +510,7 @@
 	dev->set_multicast_list = mc32_set_multicast_list;
 	dev->tx_timeout		= mc32_timeout;
 	dev->watchdog_timeo	= HZ*5;	/* Board does all the work */
-
+	dev->do_ioctl		= netdev_ioctl;
 	
 	lp->xceiver_state = HALTED; 
 	
@@ -781,10 +789,10 @@
 			return -ENOBUFS;
 		}
 		
-		p=bus_to_virt(lp->base+rx_base);
+		p=isa_bus_to_virt(lp->base+rx_base);
 				
 		p->control=0;
-		p->data=virt_to_bus(lp->rx_ring[i].skb->data);
+		p->data=isa_virt_to_bus(lp->rx_ring[i].skb->data);
 		p->status=0;
 		p->length=1532;
 	
@@ -854,7 +862,7 @@
 
 	for(i=0;i<lp->tx_len;i++) 
 	{
-		p=bus_to_virt(lp->base+tx_base);
+		p=isa_bus_to_virt(lp->base+tx_base);
 		lp->tx_ring[i].p=p; 
 		lp->tx_ring[i].skb=NULL;
 
@@ -1080,7 +1088,7 @@
    	   
 	np->length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; 
 			
-	np->data	= virt_to_bus(skb->data);
+	np->data	= isa_virt_to_bus(skb->data);
 	np->status	= 0;
 	np->control     = CONTROL_EOP | CONTROL_EOL;     
 	wmb();
@@ -1197,7 +1205,7 @@
 				
 				skb_reserve(newskb,18); 
 				lp->rx_ring[rx_ring_tail].skb=newskb;  
-				p->data=virt_to_bus(newskb->data);  
+				p->data=isa_virt_to_bus(newskb->data);  
 			} 
 			else 
 			{
@@ -1644,6 +1652,86 @@
 	do_mc32_set_multicast_list(dev,1);
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "MCA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = mc32_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		mc32_debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 #ifdef MODULE
 
 static struct net_device this_device;
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/8139cp.c	Sun Feb 10 19:58:06 2002
@@ -20,7 +20,6 @@
 	TODO, in rough priority order:
 	* dev->tx_timeout
 	* LinkChg interrupt
-	* ETHTOOL_[GS]SET
 	* Support forcing media type with a module parameter,
 	  like dl2k.c/sundance.c
 	* Implement PCI suspend/resume
@@ -33,18 +32,19 @@
 	* Rx checksumming
 	* Tx checksumming
 	* ETHTOOL_GREGS, ETHTOOL_[GS]WOL,
-	  ETHTOOL_[GS]MSGLVL, ETHTOOL_NWAY_RST
 	* Jumbo frames / dev->change_mtu
 	* Investigate using skb->priority with h/w VLAN priority
 	* Investigate using High Priority Tx Queue with skb->priority
 	* Adjust Rx FIFO threshold and Max Rx DMA burst on Rx FIFO error
 	* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
+        * Implement Tx software interrupt mitigation via
+	          Tx descriptor bit
 
  */
 
 #define DRV_NAME		"8139cp"
-#define DRV_VERSION		"0.0.5"
-#define DRV_RELDATE		"Oct 19, 2001"
+#define DRV_VERSION		"0.0.6cvs"
+#define DRV_RELDATE		"Nov 19, 2001"
 
 
 #include <linux/module.h>
@@ -56,6 +56,7 @@
 #include <linux/delay.h>
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
+#include <linux/mii.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -94,10 +95,10 @@
 	(((CP)->tx_tail <= (CP)->tx_head) ?			\
 	  (CP)->tx_tail + (CP_TX_RING_SIZE - 1) - (CP)->tx_head :	\
 	  (CP)->tx_tail - (CP)->tx_head - 1)
-#define CP_CHIP_VERSION		0x76
 
 #define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer.*/
 #define RX_OFFSET		2
+#define CP_INTERNAL_PHY		32
 
 /* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
 #define RX_FIFO_THRESH		5	/* Rx buffer level before first PCI xfer.  */
@@ -126,6 +127,11 @@
 	Config3		= 0x59, /* Config3 */
 	Config4		= 0x5A, /* Config4 */
 	MultiIntr	= 0x5C, /* Multiple interrupt select */
+	BasicModeCtrl	= 0x62,	/* MII BMCR */
+	BasicModeStatus	= 0x64, /* MII BMSR */
+	NWayAdvert	= 0x66, /* MII ADVERTISE */
+	NWayLPAR	= 0x68, /* MII LPA */
+	NWayExpansion	= 0x6A, /* MII Expansion */
 	Config5		= 0xD8,	/* Config5 */
 	TxPoll		= 0xD9,	/* Tell chip to check Tx descriptors for work */
 	CpCmd		= 0xE0, /* C+ Command register (C+ mode only) */
@@ -279,6 +285,8 @@
 
 	struct sk_buff		*frag_skb;
 	unsigned		dropping_frag : 1;
+
+	struct mii_if_info	mii_if;
 };
 
 #define cpr8(reg)	readb(cp->regs + (reg))
@@ -985,6 +993,39 @@
 	return 0;
 }
 
+static char mii_2_8139_map[8] = {
+	BasicModeCtrl,
+	BasicModeStatus,
+	0,
+	0,
+	NWayAdvert,
+	NWayLPAR,
+	NWayExpansion,
+	0
+};
+
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+	struct cp_private *cp = dev->priv;
+
+	return location < 8 && mii_2_8139_map[location] ?
+	       readw(cp->regs + mii_2_8139_map[location]) : 0;
+}
+
+
+static void mdio_write(struct net_device *dev, int phy_id, int location,
+		       int value)
+{
+	struct cp_private *cp = dev->priv;
+
+	if (location == 0) {
+		cpw8(Cfg9346, Cfg9346_Unlock);
+		cpw16(BasicModeCtrl, value);
+		cpw8(Cfg9346, Cfg9346_Lock);
+	} else if (location < 8 && mii_2_8139_map[location])
+		cpw16(mii_2_8139_map[location], value);
+}
+
 static int cp_ethtool_ioctl (struct cp_private *cp, void *useraddr)
 {
 	u32 ethcmd;
@@ -992,21 +1033,71 @@
 	/* dev_ioctl() in ../../net/core/dev.c has already checked
 	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
 
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+	if (get_user(ethcmd, (u32 *)useraddr))
 		return -EFAULT;
 
 	switch (ethcmd) {
 
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, cp->pdev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, cp->pdev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&cp->lock);
+		mii_ethtool_gset(&cp->mii_if, &ecmd);
+		spin_unlock_irq(&cp->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&cp->lock);
+		r = mii_ethtool_sset(&cp->mii_if, &ecmd);
+		spin_unlock_irq(&cp->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&cp->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&cp->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = cp->msg_enable;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		cp->msg_enable = edata.data;
+		return 0;
+	}
 
 	default:
 		break;
@@ -1136,6 +1227,10 @@
 	cp->dev = dev;
 	cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
 	spin_lock_init (&cp->lock);
+	cp->mii_if.dev = dev;
+	cp->mii_if.mdio_read = mdio_read;
+	cp->mii_if.mdio_write = mdio_write;
+	cp->mii_if.phy_id = CP_INTERNAL_PHY;
 
 	rc = pci_enable_device(pdev);
 	if (rc)
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/net/8139too.c	Sun Feb 10 19:58:03 2002
@@ -92,7 +92,7 @@
 */
 
 #define DRV_NAME	"8139too"
-#define DRV_VERSION	"0.9.22"
+#define DRV_VERSION	"0.9.24"
 
 
 #include <linux/config.h>
@@ -160,6 +160,9 @@
    The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
 static int multicast_filter_limit = 32;
 
+/* bitmapped message enable number */
+static int debug = -1;
+
 /* Size of the in-memory receive ring. */
 #define RX_BUF_LEN_IDX	2	/* 0==8K, 1==16K, 2==32K, 3==64K */
 #define RX_BUF_LEN	(8192 << RX_BUF_LEN_IDX)
@@ -213,6 +216,7 @@
 	ADDTRON8139,
 	DFE538TX,
 	DFE690TXD,
+	FE2000VX,
 	RTL8129,
 } board_t;
 
@@ -230,6 +234,7 @@
 	{ "Addtron Technolgy 8139 10/100BaseTX", RTL8139_CAPS },
 	{ "D-Link DFE-538TX (RealTek RTL8139)", RTL8139_CAPS },
 	{ "D-Link DFE-690TXD (RealTek RTL8139)", RTL8139_CAPS },
+	{ "AboCom FE2000VX (RealTek RTL8139)", RTL8139_CAPS },
 	{ "RealTek RTL8129", RTL8129_CAPS },
 };
 
@@ -243,6 +248,7 @@
 	{0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
 	{0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE538TX },
 	{0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE690TXD },
+	{0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FE2000VX },
 
 #ifdef CONFIG_8139TOO_8129
 	{0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 },
@@ -254,6 +260,7 @@
 	 */
 	{PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 },
 	{PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, DFE538TX },
+	{PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, FE2000VX },
 
 	{0,}
 };
@@ -526,6 +533,7 @@
 	unsigned long early_rx;
 	unsigned long tx_buf_mapped;
 	unsigned long tx_timeouts;
+	unsigned long rx_lost_in_ring;
 };
 
 struct rtl8139_private {
@@ -544,12 +552,8 @@
 	dma_addr_t tx_bufs_dma;
 	signed char phys[4];		/* MII device addresses. */
 	char twistie, twist_row, twist_col;	/* Twister tune state. */
-	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
 	unsigned int default_port:4;	/* Last dev->if_port value. */
-	unsigned int media2:4;	/* Secondary monitored media port. */
 	unsigned int medialock:1;	/* Don't sense media type. */
-	unsigned int mediasense:1;	/* Media sensing in progress. */
 	spinlock_t lock;
 	chip_t chipset;
 	pid_t thr_pid;
@@ -558,6 +562,7 @@
 	u32 rx_config;
 	struct rtl_extra_stats xstats;
 	int time_to_die;
+	struct mii_if_info mii;
 };
 
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
@@ -568,6 +573,8 @@
 MODULE_PARM (max_interrupt_work, "i");
 MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
 MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
 MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt");
 MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
@@ -948,6 +955,9 @@
 	spin_lock_init (&tp->lock);
 	init_waitqueue_head (&tp->thr_wait);
 	init_completion (&tp->thr_exited);
+	tp->mii.dev = dev;
+	tp->mii.mdio_read = mdio_read;
+	tp->mii.mdio_write = mdio_write;
 
 	/* dev is fully set up and ready to use now */
 	DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
@@ -999,18 +1009,18 @@
 	/* The lower four bits are the media type. */
 	option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
 	if (option > 0) {
-		tp->full_duplex = (option & 0x210) ? 1 : 0;
+		tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
 		tp->default_port = option & 0xFF;
 		if (tp->default_port)
 			tp->medialock = 1;
 	}
 	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)
-		tp->full_duplex = full_duplex[board_idx];
-	if (tp->full_duplex) {
+		tp->mii.full_duplex = full_duplex[board_idx];
+	if (tp->mii.full_duplex) {
 		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
 		/* Changing the MII-advertised media because might prevent
 		   re-connection. */
-		tp->duplex_lock = 1;
+		tp->mii.duplex_lock = 1;
 	}
 	if (tp->default_port) {
 		printk(KERN_INFO "  Forcing %dMbps %s-duplex operation.\n",
@@ -1267,7 +1277,7 @@
 
 	}
 
-	tp->full_duplex = tp->duplex_lock;
+	tp->mii.full_duplex = tp->mii.duplex_lock;
 	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
 	tp->twistie = 1;
 	tp->time_to_die = 0;
@@ -1279,7 +1289,7 @@
 			" GP Pins %2.2x %s-duplex.\n",
 			dev->name, pci_resource_start (tp->pci_dev, 1),
 			dev->irq, RTL_R8 (MediaStatus),
-			tp->full_duplex ? "full" : "half");
+			tp->mii.full_duplex ? "full" : "half");
 
 	tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);
 	if (tp->thr_pid < 0)
@@ -1295,18 +1305,18 @@
 	struct rtl8139_private *tp = dev->priv;
 
 	if (tp->phys[0] >= 0) {
-		u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
-		if (mii_reg5 == 0xffff)
+		u16 mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA);
+		if (mii_lpa == 0xffff)
 			;					/* Not there */
-		else if ((mii_reg5 & 0x0100) == 0x0100
-				 || (mii_reg5 & 0x00C0) == 0x0040)
-			tp->full_duplex = 1;
+		else if ((mii_lpa & LPA_100FULL) == LPA_100FULL
+				 || (mii_lpa & 0x00C0) == LPA_10FULL)
+			tp->mii.full_duplex = 1;
 
 		printk (KERN_INFO"%s: Setting %s%s-duplex based on"
 				" auto-negotiated partner ability %4.4x.\n",
-		        dev->name, mii_reg5 == 0 ? "" :
-				(mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
-			tp->full_duplex ? "full" : "half", mii_reg5);
+		        dev->name, mii_lpa == 0 ? "" :
+				(mii_lpa & 0x0180) ? "100mbps " : "10mbps ",
+			tp->mii.full_duplex ? "full" : "half", mii_lpa);
 	}
 }
 
@@ -1494,30 +1504,30 @@
 				 struct rtl8139_private *tp,
 				 void *ioaddr)
 {
-	int mii_reg5;
+	int mii_lpa;
 
-	mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
 
-	if (!tp->duplex_lock && mii_reg5 != 0xffff) {
-		int duplex = (mii_reg5 & 0x0100)
-		    || (mii_reg5 & 0x01C0) == 0x0040;
-		if (tp->full_duplex != duplex) {
-			tp->full_duplex = duplex;
+	if (!tp->mii.duplex_lock && mii_lpa != 0xffff) {
+		int duplex = (mii_lpa & LPA_100FULL)
+		    || (mii_lpa & 0x01C0) == 0x0040;
+		if (tp->mii.full_duplex != duplex) {
+			tp->mii.full_duplex = duplex;
 
-			if (mii_reg5) {
+			if (mii_lpa) {
 				printk (KERN_INFO
 					"%s: Setting %s-duplex based on MII #%d link"
 					" partner ability of %4.4x.\n",
 					dev->name,
-					tp->full_duplex ? "full" : "half",
-					tp->phys[0], mii_reg5);
+					tp->mii.full_duplex ? "full" : "half",
+					tp->phys[0], mii_lpa);
 			} else {
 				printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",
 				       dev->name);
 			}
 #if 0
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
 			RTL_W8 (Cfg9346, Cfg9346_Lock);
 #endif
 		}
@@ -1750,23 +1760,36 @@
 			    struct rtl8139_private *tp, void *ioaddr)
 {
 	u8 tmp8;
+#ifndef CONFIG_8139_NEW_RX_RESET
 	int tmp_work;
+#endif
 
 	DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
 	         dev->name, rx_status);
-	if (rx_status & RxTooLong) {
-		DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
-			 dev->name, rx_status);
-		/* A.C.: The chip hangs here. */
-	}
 	tp->stats.rx_errors++;
-	if (rx_status & (RxBadSymbol | RxBadAlign))
-		tp->stats.rx_frame_errors++;
-	if (rx_status & (RxRunt | RxTooLong))
-		tp->stats.rx_length_errors++;
-	if (rx_status & RxCRCErr)
-		tp->stats.rx_crc_errors++;
+	if (!(rx_status & RxStatusOK)) {
+		if (rx_status & RxTooLong) {
+			DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
+			 	dev->name, rx_status);
+			/* A.C.: The chip hangs here. */
+		}
+		if (rx_status & (RxBadSymbol | RxBadAlign))
+			tp->stats.rx_frame_errors++;
+		if (rx_status & (RxRunt | RxTooLong))
+			tp->stats.rx_length_errors++;
+		if (rx_status & RxCRCErr)
+			tp->stats.rx_crc_errors++;
+	} else {
+		tp->xstats.rx_lost_in_ring++;
+	}
 
+#ifdef CONFIG_8139_NEW_RX_RESET
+	tmp8 = RTL_R8 (ChipCmd);
+	RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb);
+	RTL_W8 (ChipCmd, tmp8);
+	RTL_W32 (RxConfig, tp->rx_config);
+	tp->cur_rx = 0;
+#else
 	/* Reset the receiver, based on RealTek recommendation. (Bug?) */
 
 	/* disable receive */
@@ -1811,6 +1834,7 @@
 
 	/* A.C.: Reset the multicast list. */
 	__set_rx_mode (dev);
+#endif
 }
 
 static void rtl8139_rx_interrupt (struct net_device *dev,
@@ -1945,13 +1969,13 @@
 	    (tp->drv_flags & HAS_LNK_CHNG)) {
 		/* Really link-change on new chips. */
 		int lpar = RTL_R16 (NWayLPAR);
-		int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040
-				|| tp->duplex_lock;
-		if (tp->full_duplex != duplex) {
-			tp->full_duplex = duplex;
+		int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040
+				|| tp->mii.duplex_lock;
+		if (tp->mii.full_duplex != duplex) {
+			tp->mii.full_duplex = duplex;
 #if 0
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
 			RTL_W8 (Cfg9346, Cfg9346_Lock);
 #endif
 		}
@@ -2110,48 +2134,6 @@
 }
 
 
-/* Get the ethtool settings.  Assumes that eset points to kernel
-   memory, *eset has been initialized as {ETHTOOL_GSET}, and other
-   threads or interrupts aren't messing with the 8139.  */
-static void netdev_get_eset (struct net_device *dev, struct ethtool_cmd *eset)
-{
-	struct rtl8139_private *np = dev->priv;
-	void *ioaddr = np->mmio_addr;
-	u16 advert;
-
-	eset->supported = SUPPORTED_10baseT_Half
-		      	| SUPPORTED_10baseT_Full
-		      	| SUPPORTED_100baseT_Half
-		      	| SUPPORTED_100baseT_Full
-		      	| SUPPORTED_Autoneg
-		      	| SUPPORTED_TP;
-
-	eset->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
-	advert = mdio_read (dev, np->phys[0], 4);
-	if (advert & 0x0020)
-		eset->advertising |= ADVERTISED_10baseT_Half;
-	if (advert & 0x0040)
-		eset->advertising |= ADVERTISED_10baseT_Full;
-	if (advert & 0x0080)
-		eset->advertising |= ADVERTISED_100baseT_Half;
-	if (advert & 0x0100)
-		eset->advertising |= ADVERTISED_100baseT_Full;
-
-	eset->speed = (RTL_R8 (MediaStatus) & 0x08) ? 10 : 100;
-	/* (KON)FIXME: np->full_duplex is set or reset by the thread,
-	   which means this always shows half duplex if the interface
-	   isn't up yet, even if it has already autonegotiated.  */
-	eset->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	eset->port = PORT_TP;
-	/* (KON)FIXME: Is np->phys[0] correct?  starfire.c uses that.  */
-	eset->phy_address = np->phys[0];
-	eset->transceiver = XCVR_INTERNAL;
-	eset->autoneg = (mdio_read (dev, np->phys[0], 0) & 0x1000) != 0;
-	eset->maxtxpkt = 1;
-	eset->maxrxpkt = 1;
-}
-
-
 /* Get the ethtool Wake-on-LAN settings.  Assumes that wol points to
    kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and
    other threads or interrupts aren't messing with the 8139.  */
@@ -2226,7 +2208,6 @@
 	return 0;
 }
 
-
 static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
 {
 	struct rtl8139_private *np = dev->priv;
@@ -2235,33 +2216,71 @@
 	/* dev_ioctl() in ../../net/core/dev.c has already checked
 	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
 
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+	if (get_user(ethcmd, (u32 *)useraddr))
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GSET:
-		{
-			struct ethtool_cmd eset = { ETHTOOL_GSET };
-			spin_lock_irq (&np->lock);
-			netdev_get_eset (dev, &eset);
-			spin_unlock_irq (&np->lock);
-			if (copy_to_user (useraddr, &eset, sizeof (eset)))
-				return -EFAULT;
-			return 0;
-		}
 
-	/* TODO: ETHTOOL_SSET */
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
 
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, np->pci_dev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 
 	case ETHTOOL_GWOL:
 		{
@@ -2315,17 +2334,14 @@
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
 	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */
-	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */
 		data->phy_id = phy;
 		/* Fall Through */
 
 	case SIOCGMIIREG:	/* Read the specified MII register. */
-	case SIOCDEVPRIVATE+1:	/* binary compat, remove in 2.5 */
 		data->val_out = mdio_read (dev, data->phy_id, data->reg_num);
 		break;
 
 	case SIOCSMIIREG:	/* Write the specified MII register */
-	case SIOCDEVPRIVATE+2:	/* binary compat, remove in 2.5 */
 		if (!capable (CAP_NET_ADMIN)) {
 			rc = -EPERM;
 			break;
@@ -2338,9 +2354,9 @@
 				/* Check for autonegotiation on or reset. */
 				tp->medialock = (value & 0x9000) ? 0 : 1;
 				if (tp->medialock)
-					tp->full_duplex = (value & 0x0100) ? 1 : 0;
+					tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
-			case 4: /* tp->advertising = value; */ break;
+			case 4: tp->mii.advertising = value; break;
 			}
 		}
 		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
diff -Nru a/drivers/net/Config.help b/drivers/net/Config.help
--- a/drivers/net/Config.help	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/Config.help	Sun Feb 10 19:58:04 2002
@@ -1154,6 +1154,17 @@
   More specific information and updates are available from
   <http://www.scyld.com/network/natsemi.html>.
 
+CONFIG_NATSEMI_CABLE_MAGIC
+  Some systems see lots of errors with NatSemi ethernet controllers
+  on certain cables.  If you are seeing lots of errors, try turning
+  this option on.  Some boards have incorrect values for supporting
+  resistors that can cause this change to break.  If you turn this
+  option on and your network suddenly stops working, turn this
+  option off.
+
+  Say N unless you are certain you need this option.
+  Vendors should not enable this option by default.
+
 CONFIG_SK_G16
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
diff -Nru a/drivers/net/Config.in b/drivers/net/Config.in
--- a/drivers/net/Config.in	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/Config.in	Sun Feb 10 19:58:04 2002
@@ -73,7 +73,6 @@
    fi
    dep_tristate '  Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC $CONFIG_SBUS $CONFIG_EXPERIMENTAL
    dep_tristate '  Sun QuadEthernet support' CONFIG_SUNQE $CONFIG_SBUS
-   dep_tristate '  Sun LANCE support' CONFIG_SUNLANCE $CONFIG_SBUS
    dep_tristate '  Sun GEM support' CONFIG_SUNGEM $CONFIG_PCI
    bool '  3COM cards' CONFIG_NET_VENDOR_3COM
    if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
@@ -172,6 +171,9 @@
       dep_tristate '    Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL
       dep_tristate '    Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
       dep_tristate '    National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
+      if [ "$CONFIG_NATSEMI" = "y" -o "$CONFIG_NATSEMI" = "m" ]; then
+        bool       '      NatSemi workaround for high errors' CONFIG_NATSEMI_CABLE_MAGIC
+      fi
       dep_tristate '    PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI
       dep_tristate '    Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
       dep_tristate '    Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
@@ -180,6 +182,7 @@
       dep_mbool '      Use PIO instead of MMIO' CONFIG_8139TOO_PIO $CONFIG_8139TOO
       dep_mbool '      Support for automatic channel equalization (EXPERIMENTAL)' CONFIG_8139TOO_TUNE_TWISTER $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
       dep_mbool '      Support for older RTL-8129/8130 boards' CONFIG_8139TOO_8129 $CONFIG_8139TOO
+      dep_mbool '      Experiment for better RX reset (EXPERIMENTAL)' CONFIG_8139_NEW_RX_RESET $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
       dep_tristate '    SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI
       dep_tristate '    SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI
       dep_tristate '    Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/Makefile	Sun Feb 10 19:58:05 2002
@@ -68,7 +68,7 @@
 obj-$(CONFIG_PCNET32) += pcnet32.o
 obj-$(CONFIG_EEPRO100) += eepro100.o
 obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_EPIC100) += epic100.o mii.o
 obj-$(CONFIG_SIS900) += sis900.o
 obj-$(CONFIG_DM9102) += dmfe.o
 obj-$(CONFIG_YELLOWFIN) += yellowfin.o
@@ -77,7 +77,7 @@
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_NS83820) += ns83820.o
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
-obj-$(CONFIG_FEALNX) += fealnx.o
+obj-$(CONFIG_FEALNX) += fealnx.o mii.o
 
 ifeq ($(CONFIG_SK98LIN),y)
 obj-y += sk98lin/sk98lin.o
@@ -87,7 +87,7 @@
   obj-y += skfp/skfp.o
 endif
 
-obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o mii.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 
 #
@@ -100,7 +100,7 @@
 obj-$(CONFIG_AIRONET4500_PROC)	+= aironet4500_proc.o
 obj-$(CONFIG_AIRONET4500_CS)	+= aironet4500_proc.o
 
-obj-$(CONFIG_WINBOND_840) += winbond-840.o
+obj-$(CONFIG_WINBOND_840) += winbond-840.o mii.o
 obj-$(CONFIG_SUNDANCE) += sundance.o
 obj-$(CONFIG_HAMACHI) += hamachi.o
 obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
@@ -164,8 +164,8 @@
 obj-$(CONFIG_3C515) += 3c515.o
 obj-$(CONFIG_EEXPRESS) += eexpress.o
 obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_8139CP) += 8139cp.o
-obj-$(CONFIG_8139TOO) += 8139too.o
+obj-$(CONFIG_8139CP) += 8139cp.o mii.o
+obj-$(CONFIG_8139TOO) += 8139too.o mii.o
 obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
 obj-$(CONFIG_ZNET) += znet.o
 obj-$(CONFIG_LAN_SAA9730) += saa9730.o
diff -Nru a/drivers/net/ac3200.c b/drivers/net/ac3200.c
--- a/drivers/net/ac3200.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/ac3200.c	Sun Feb 10 19:58:04 2002
@@ -205,10 +205,10 @@
 	 *  the card mem within the region covered by `normal' RAM  !!!
 	 */
 	if (dev->mem_start > 1024*1024) {	/* phys addr > 1MB */
-		if (dev->mem_start < virt_to_bus(high_memory)) {
+		if (dev->mem_start < virt_to_phys(high_memory)) {
 			printk(KERN_CRIT "ac3200.c: Card RAM overlaps with normal memory!!!\n");
 			printk(KERN_CRIT "ac3200.c: Use EISA SCU to set card memory below 1MB,\n");
-			printk(KERN_CRIT "ac3200.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory));
+			printk(KERN_CRIT "ac3200.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
 			printk(KERN_CRIT "ac3200.c: Driver NOT installed.\n");
 			retval = -EINVAL;
 			goto out2;
diff -Nru a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c
--- a/drivers/net/aironet4500_proc.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/aironet4500_proc.c	Sun Feb 10 19:58:04 2002
@@ -33,15 +33,10 @@
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
 
-
 #ifdef CONFIG_PROC_FS
 
-#ifdef CONFIG_PROC_FS
 #include <linux/sysctl.h>
-#else
-#error awc driver needs CONFIG_PROC_FS
-#endif
-
+#include <linux/fs.h>
 
 #include "aironet4500.h"
 #include "aironet4500_rid.c"
@@ -602,6 +597,9 @@
 
 module_init(aironet_proc_init);
 module_exit(aironet_proc_exit);
+
+#else
+#error awc driver needs CONFIG_PROC_FS
 
 #endif // whole proc system styff
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
--- a/drivers/net/au1000_eth.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/net/au1000_eth.c	Sun Feb 10 19:58:03 2002
@@ -1135,12 +1135,14 @@
 
 	/* fixme */
 	switch(cmd) { 
-		case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		case SIOCGMIIPHY:		/* Get the address of the PHY in use. */
 		data[0] = PHY_ADDRESS;
-		case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+
+		case SIOCGMIIREG:		/* Read the specified MII register. */
 		//data[3] = mdio_read(ioaddr, data[0], data[1]); 
 		return 0;
-		case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+		case SIOCSMIIREG:		/* Write the specified MII register */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		//mdio_write(ioaddr, data[0], data[1], data[2]);
diff -Nru a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
--- a/drivers/net/bsd_comp.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/bsd_comp.c	Sun Feb 10 19:58:06 2002
@@ -73,6 +73,8 @@
 #include <linux/ppp-comp.h>
 #undef   PACKETPTR
 
+#include <asm/byteorder.h>
+
 /*
  * PPP "BSD compress" compression
  *  The differences between this compression and the classic BSD LZW
diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
--- a/drivers/net/cs89x0.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/cs89x0.c	Sun Feb 10 19:58:06 2002
@@ -1109,7 +1109,7 @@
 				printk(	"%s: dma %lx %lx\n",
 					dev->name,
 					(unsigned long)lp->dma_buff,
-					(unsigned long)virt_to_bus(lp->dma_buff));
+					(unsigned long)isa_virt_to_bus(lp->dma_buff));
 			}
 			if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||
 			    !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) {
@@ -1128,7 +1128,7 @@
 			disable_dma(dev->dma);
 			clear_dma_ff(dev->dma);
 			set_dma_mode(dev->dma, 0x14); /* auto_init as well */
-			set_dma_addr(dev->dma, virt_to_bus(lp->dma_buff));
+			set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
 			set_dma_count(dev->dma, lp->dmasize*1024);
 			enable_dma(dev->dma);
 			spin_unlock_irqrestore(&lp->lock, flags);
diff -Nru a/drivers/net/de4x5.c b/drivers/net/de4x5.c
--- a/drivers/net/de4x5.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/net/de4x5.c	Sun Feb 10 19:58:04 2002
@@ -3645,7 +3645,7 @@
     tmp = virt_to_bus(p->data);
     i = ((tmp + ALIGN) & ~ALIGN) - tmp;
     skb_reserve(p, i);
-    lp->rx_ring[index].buf = tmp + i;
+    lp->rx_ring[index].buf = cpu_to_le32(tmp + i);
 
     ret = lp->rx_skb[index];
     lp->rx_skb[index] = p;
@@ -5616,7 +5616,7 @@
 	if (!capable(CAP_NET_ADMIN)) return -EPERM;
 	omr = inl(DE4X5_OMR);
 	omr &= ~OMR_PR;
-	outb(omr, DE4X5_OMR);
+	outl(omr, DE4X5_OMR);
 	dev->flags &= ~IFF_PROMISC;
 	break;
 
diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c
--- a/drivers/net/defxx.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/net/defxx.c	Sun Feb 10 19:58:03 2002
@@ -199,6 +199,8 @@
  *		Feb 2001	davej		PCI enable cleanups.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 /* Include files */
 
 #include <linux/module.h>
diff -Nru a/drivers/net/dl2k.c b/drivers/net/dl2k.c
--- a/drivers/net/dl2k.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/dl2k.c	Sun Feb 10 19:58:06 2002
@@ -15,18 +15,24 @@
     0.01	2001/05/03	Created DL2000-based linux driver
     0.02	2001/05/21	Added VLAN and hardware checksum support.
     1.00	2001/06/26	Added jumbo frame support.
-    1.01	2001/08/21	Added two parameters, int_count and int_timeout.
+    1.01	2001/08/21	Added two parameters, rx_coalesce and rx_timeout.
     1.02	2001/10/08	Supported fiber media.
     				Added flow control parameters.
-    1.03	2001/10/12	Changed the default media to 1000mbps_fd for the 
-    				fiber devices.
-    1.04	2001/11/08	Fixed a bug which Tx stop when a very busy case.
-*/
+    1.03	2001/10/12	Changed the default media to 1000mbps_fd for 
+    				the fiber devices.
+    1.04	2001/11/08	Fixed Tx stopped when tx very busy.
+    1.05	2001/11/22	Fixed Tx stopped when unidirectional tx busy.
+    1.06	2001/12/13	Fixed disconnect bug at 10Mbps mode.
+    				Fixed tx_full flag incorrect.
+				Added tx_coalesce paramter.
+    1.07	2002/01/03	Fixed miscount of RX frame error.
+    1.08	2002/01/17	Fixed the multicast bug.
+ */
 
 #include "dl2k.h"
 
 static char version[] __devinitdata =
-    KERN_INFO "D-Link DL2000-based linux driver v1.04 2001/11/08\n";
+    KERN_INFO "D-Link DL2000-based linux driver v1.08 2002/01/17\n";
 
 #define MAX_UNITS 8
 static int mtu[MAX_UNITS];
@@ -36,11 +42,13 @@
 static int tx_flow[MAX_UNITS];
 static int rx_flow[MAX_UNITS];
 static int copy_thresh;
-static int int_count;		/* Rx frame count each interrupt */
-static int int_timeout;		/* Rx DMA wait time in 64ns increments */
+static int rx_coalesce = DEFAULT_RXC;
+static int rx_timeout = DEFAULT_RXT;	
+static int tx_coalesce = DEFAULT_TXC;	
 
 MODULE_AUTHOR ("Edward Peng");
 MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
+MODULE_LICENSE("GPL");
 MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s");
 MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i");
@@ -48,13 +56,16 @@
 MODULE_PARM (tx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (rx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (copy_thresh, "i");
-MODULE_PARM (int_count, "i");
-MODULE_PARM (int_timeout, "i");
+MODULE_PARM (rx_coalesce, "i");	/* Rx frame count each interrupt */
+MODULE_PARM (rx_timeout, "i");	/* Rx DMA wait time in 64ns increments */
+MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxComplete [1-8] */
+
 
 /* Enable the default interrupts */
+#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxComplete| \
+       UpdateStats | LinkEvent)
 #define EnableInt() \
-writew(RxDMAComplete | HostError | IntRequested | TxComplete| \
-       UpdateStats | LinkEvent, ioaddr + IntEnable)
+writew(DEFAULT_INTR, ioaddr + IntEnable)
 
 static int max_intrloop = 50;
 static int multicast_filter_limit = 0x40;
@@ -162,11 +173,11 @@
 				np->speed = 10;
 				np->full_duplex = 0;
 			} else if (strcmp (media[card_idx], "1000mbps_fd") == 0 ||
-				 strcmp (media[card_idx], "5") == 0) {
+				 strcmp (media[card_idx], "6") == 0) {
 				np->speed=1000;
 				np->full_duplex=1;
 			} else if (strcmp (media[card_idx], "1000mbps_hd") == 0 ||
-				 strcmp (media[card_idx], "6") == 0) {
+				 strcmp (media[card_idx], "5") == 0) {
 				np->speed = 1000;
 				np->full_duplex = 0;
 			} else {
@@ -175,7 +186,7 @@
 		}
 		if (jumbo[card_idx] != 0) {
 			np->jumbo = 1;
-			dev->mtu = 9000;
+			dev->mtu = MAX_JUMBO;
 		} else {
 			np->jumbo = 0;
 			if (mtu[card_idx] > 0 && mtu[card_idx] < PACKET_SIZE)
@@ -183,14 +194,17 @@
 		}
 		np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ?
 		    vlan[card_idx] : 0;
-		if (int_count != 0 && int_timeout != 0) {
-			np->int_count = int_count;
-			np->int_timeout = int_timeout;
+		if (rx_coalesce != 0 && rx_timeout != 0) {
+			np->rx_coalesce = rx_coalesce;
+			np->rx_timeout = rx_timeout;
 			np->coalesce = 1;
 		}
 		np->tx_flow = (tx_flow[card_idx]) ? 1 : 0;
 		np->rx_flow = (rx_flow[card_idx]) ? 1 : 0;
-		
+		if (tx_coalesce < 1)
+			tx_coalesce = 1;
+		if (tx_coalesce > 8)
+			tx_coalesce = 8;
 	}
 	dev->open = &rio_open;
 	dev->hard_start_xmit = &start_xmit;
@@ -201,8 +215,8 @@
 	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->change_mtu = &change_mtu;
-#ifdef TX_HW_CHECKSUM
-	dev->features = NETIF_F_SG | NETIF_F_HW_CSUM;
+#if 0
+	dev->features = NETIF_F_IP_CSUM;
 #endif
 	pci_set_drvdata (pdev, dev);
 
@@ -326,7 +340,7 @@
 	}
 
 	/* Check CRC */
- 	crc = ~ether_crc_le(256-4, sromdata);
+	crc = ~ether_crc_le(256 - 4, sromdata);
 	if (psrom->crc != crc) {
 		printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
 		return -1;
@@ -388,13 +402,12 @@
 	i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
 	if (i)
 		return i;
-
 	/* DebugCtrl bit 4, 5, 9 must set */
 	writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
 
 	/* Jumbo frame */
 	if (np->jumbo != 0)
-		writew (9014, ioaddr + MaxFrameSize);
+		writew (MAX_JUMBO+14, ioaddr + MaxFrameSize);
 
 	alloc_list (dev);
 
@@ -404,7 +417,7 @@
 
 	set_multicast (dev);
 	if (np->coalesce) {
-		writel (np->int_count | np->int_timeout << 16,
+		writel (np->rx_coalesce | np->rx_timeout << 16,
 			ioaddr + RxDMAIntCtrl);
 	}
 	/* Set RIO to poll every N*320nsec. */
@@ -441,13 +454,31 @@
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
 
-	printk (KERN_WARNING "%s: Transmit timed out, TxStatus %4.4x.\n",
+	printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
 		dev->name, readl (ioaddr + TxStatus));
+	/* Free used tx skbuffs */
+	for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
+		int entry = np->old_tx % TX_RING_SIZE;
+		struct sk_buff *skb;
+
+		if (!(np->tx_ring[entry].status & TFDDone))
+			break;
+		skb = np->tx_skbuff[entry];
+		pci_unmap_single (np->pdev,
+				  np->tx_ring[entry].fraginfo,
+				  skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq (skb);
+		np->tx_skbuff[entry] = 0;
+	}
 	dev->if_port = 0;
 	dev->trans_start = jiffies;
 	np->stats.tx_errors++;
-	if (!np->tx_full)
+	/* If the ring is no longer full, clear tx_full and 
+	   call netif_wake_queue() */
+	if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
+		np->tx_full = 0;
 		netif_wake_queue (dev);
+	}
 }
 
  /* allocate and initialize Tx and Rx descriptors */
@@ -465,16 +496,19 @@
 	/* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_skbuff[i] = 0;
-		np->tx_ring[i].status = 0;
+		np->tx_ring[i].status = cpu_to_le64 (TFDDone);
+		np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma +
+					      ((i+1)%TX_RING_SIZE) *
+					      sizeof (struct
+					      netdev_desc));
 	}
 
 	/* Initialize Rx descriptors */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].next_desc = cpu_to_le64 (np->rx_ring_dma +
-							((i +
-							  1) % RX_RING_SIZE) *
-							sizeof (struct
-								netdev_desc));
+						((i + 1) % RX_RING_SIZE) *
+						sizeof (struct
+						netdev_desc));
 		np->rx_ring[i].status = 0;
 		np->rx_ring[i].fraginfo = 0;
 		np->rx_skbuff[i] = 0;
@@ -522,13 +556,12 @@
 	entry = np->cur_tx % TX_RING_SIZE;
 	np->tx_skbuff[entry] = skb;
 	txdesc = &np->tx_ring[entry];
-	txdesc->next_desc = 0;
 
 	/* Set TFDDone to avoid TxDMA gather this descriptor */
 	txdesc->status = cpu_to_le64 (TFDDone);
 	txdesc->status |=
 	    cpu_to_le64 (entry | WordAlignDisable | (1 << FragCountShift));
-#ifdef TX_HW_CHECKSUM
+#if 0
 	if (skb->ip_summed == CHECKSUM_HW) {
 		txdesc->status |=
 		    cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable |
@@ -544,21 +577,13 @@
 
 	/* Send one packet each time at 10Mbps mode */
 	/* Tx coalescing loop do not exceed 8 */
-	if (entry % 0x08 == 0 || np->speed == 10)
+	if (entry % tx_coalesce == 0 || np->speed == 10)
 		txdesc->status |= cpu_to_le64 (TxIndicate);
 	txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data,
 							skb->len,
 							PCI_DMA_TODEVICE));
 	txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48;
 
-	/* Chain the last descriptor's pointer to this one */
-	if (np->last_tx)
-		np->last_tx->next_desc = cpu_to_le64 (np->tx_ring_dma +
-						      entry *
-						      sizeof (struct
-							      netdev_desc));
-	np->last_tx = txdesc;
-
 	/* Clear TFDDone, then TxDMA start to send this descriptor */
 	txdesc->status &= ~cpu_to_le64 (TFDDone);
 
@@ -570,8 +595,10 @@
 	if (np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1 && np->speed != 10) {
 		/* do nothing */
 	} else {
+		spin_lock_irqsave(&np->lock, flags);
 		np->tx_full = 1;
 		netif_stop_queue (dev);
+		spin_unlock_irqrestore (&np->lock, flags);
 	}
 
 	/* The first TFDListPtr */
@@ -580,15 +607,15 @@
 			dev->base_addr + TFDListPtr0);
 		writel (0, dev->base_addr + TFDListPtr1);
 	}
-
-	spin_lock_irqsave (&np->lock, flags);
+	
 	if (np->old_tx > TX_RING_SIZE) {
+		spin_lock_irqsave (&np->lock, flags);
 		tx_shift = TX_RING_SIZE;
 		np->old_tx -= tx_shift;
 		np->cur_tx -= tx_shift;
+		spin_unlock_irqrestore (&np->lock, flags);
 	}
-	spin_unlock_irqrestore (&np->lock, flags);
-
+	
 	/* NETDEV WATCHDOG timer */
 	dev->trans_start = jiffies;
 	return 0;
@@ -605,33 +632,24 @@
 
 	ioaddr = dev->base_addr;
 	np = dev->priv;
-	spin_lock (&np->lock);
+	spin_lock(&np->lock);
 	while (1) {
-		int_status = readw (ioaddr + IntStatus) &
-		    (HostError | TxComplete | IntRequested |
-		     UpdateStats | LinkEvent | RxDMAComplete);
-		writew (int_status & (HostError | TxComplete | RxComplete |
-				      IntRequested | UpdateStats | LinkEvent |
-				      TxDMAComplete | RxDMAComplete | RFDListEnd
-				      | RxDMAPriority), ioaddr + IntStatus);
+		int_status = readw (ioaddr + IntStatus); 
+		writew (int_status, ioaddr + IntStatus);
+		int_status &= DEFAULT_INTR;
 		if (int_status == 0)
 			break;
 		/* Processing received packets */
 		if (int_status & RxDMAComplete)
 			receive_packet (dev);
 		/* TxComplete interrupt */
-		if (int_status & TxComplete || np->tx_full) {
-			int tx_status = readl (ioaddr + TxStatus);
+		if ((int_status & TxComplete) || np->tx_full) {
+			int tx_status;
+			tx_status = readl (ioaddr + TxStatus);
 			if (tx_status & 0x01)
 				tx_error (dev, tx_status);
-			/* Send one packet each time at 10Mbps mode */
-			if (np->speed == 10) {
-				np->tx_full = 0;
-				netif_wake_queue (dev);
-			}
-
 			/* Free used tx skbuffs */
-			for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
+			for (;np->cur_tx - np->old_tx > 0; np->old_tx++) {
 				int entry = np->old_tx % TX_RING_SIZE;
 				struct sk_buff *skb;
 
@@ -648,9 +666,12 @@
 		/* If the ring is no longer full, clear tx_full and 
 		   call netif_wake_queue() */
 		if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
-			np->tx_full = 0;
-			netif_wake_queue (dev);
+			if (np->speed != 10 || int_status & TxComplete) {
+				np->tx_full = 0;
+				netif_wake_queue (dev);
+			}
 		}
+
 		/* Handle uncommon events */
 		if (int_status &
 		    (IntRequested | HostError | LinkEvent | UpdateStats))
@@ -665,7 +686,7 @@
 			break;
 		}
 	}
-	spin_unlock (&np->lock);
+	spin_unlock(&np->lock);
 }
 
 static void
@@ -741,7 +762,7 @@
 		np->stats.collisions++;
 #endif
 
-	/* Restart the Tx. */
+	/* Restart the Tx */
 	writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
 }
 
@@ -782,7 +803,7 @@
 			if (frame_status & 0x00300000)
 				np->stats.rx_length_errors++;
 			if (frame_status & 0x00010000)
-				np->stats.rx_fifo_errors++;
+	 			np->stats.rx_fifo_errors++;
 			if (frame_status & 0x00060000)
 				np->stats.rx_frame_errors++;
 			if (frame_status & 0x00080000)
@@ -807,7 +828,7 @@
 				skb_put (skb, pkt_len);
 			}
 			skb->protocol = eth_type_trans (skb, dev);
-#ifdef RX_HW_CHECKSUM
+#if 0
 			/* Checksum done by hw, but csum value unavailable. */
 			if (!(frame_status & (TCPError | UDPError | IPError))) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -898,7 +919,7 @@
 	/* PCI Error, a catastronphic error related to the bus interface 
 	   occurs, set GlobalReset and HostReset to reset. */
 	if (int_status & HostError) {
-		printk (KERN_ERR "%s: PCI Error! IntStatus %4.4x.\n",
+		printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
 			dev->name, int_status);
 		writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
 		mdelay (500);
@@ -913,8 +934,8 @@
 	u16 temp1;
 	u16 temp2;
 	int i;
-	/* All statistics registers need to acknowledge,
-	   else overflow could cause some problem */
+	/* All statistics registers need to be acknowledged,
+	   else statistic overflow could cause problems */
 	np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
 	np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
 	np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
@@ -931,11 +952,11 @@
 	    readl (ioaddr + FramesWDeferredXmt) + temp2;
 
 	/* detailed rx_error */
-	np->stats.rx_length_errors += readw (ioaddr + InRangeLengthErrors) +
-	    readw (ioaddr + FrameTooLongErrors);
+	np->stats.rx_length_errors += readw (ioaddr + FrameTooLongErrors);
 	np->stats.rx_crc_errors += readw (ioaddr + FrameCheckSeqError);
 
 	/* Clear all other statistic register. */
+	readw (ioaddr + InRangeLengthErrors);
 	readw (ioaddr + MacControlFramesXmtd);
 	readw (ioaddr + BcstFramesXmtdOk);
 	readl (ioaddr + McstFramesXmtdOk);
@@ -960,7 +981,7 @@
 change_mtu (struct net_device *dev, int new_mtu)
 {
 	struct netdev_private *np = dev->priv;
-	int max = (np->jumbo) ? 9000 : 1536;
+	int max = (np->jumbo) ? MAX_JUMBO : 1536;
 
 	if ((new_mtu < 68) || (new_mtu > max)) {
 		return -EINVAL;
@@ -978,36 +999,42 @@
 	u32 hash_table[2];
 	u16 rx_mode = 0;
 	int i;
+	int bit;
+	int index, crc;
 	struct dev_mc_list *mclist;
 	struct netdev_private *np = dev->priv;
-
-	/* Default: receive broadcast and unicast */
-	rx_mode = ReceiveBroadcast | ReceiveUnicast;
+	
+	hash_table[0] = hash_table[1] = 0;
+	/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
+	hash_table[1] |= 0x02000000;
 	if (dev->flags & IFF_PROMISC) {
 		/* Receive all frames promiscuously. */
-		rx_mode |= ReceiveAllFrames;
-	} else if (((dev->flags & IFF_MULTICAST)
-		    && (dev->mc_count > multicast_filter_limit))
-		   || (dev->flags & IFF_ALLMULTI)) {
+		rx_mode = ReceiveAllFrames;
+	} else if ((dev->flags & IFF_ALLMULTI) || 
+			(dev->mc_count > multicast_filter_limit)) {
 		/* Receive broadcast and multicast frames */
-		rx_mode |= ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
-	} else if ((dev->flags & IFF_MULTICAST) & (dev->mc_count > 0)) {
-		/* Receive broadcast frames and multicast frames filtering by Hashtable */
-		rx_mode |=
+		rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
+	} else if (dev->mc_count > 0) {
+		/* Receive broadcast frames and multicast frames filtering 
+		   by Hashtable */
+		rx_mode =
 		    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
+		for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count; 
+				i++, mclist=mclist->next) {
+			crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
+			for (index=0, bit=0; bit<6; bit++, crc<<=1) {
+				if (crc & 0x80000000) index |= 1 << bit;
+			}
+			hash_table[index / 32] |= (1 << (index % 32));
+		}
+	} else {
+		rx_mode = ReceiveBroadcast | ReceiveUnicast;
 	}
 	if (np->vlan) {
 		/* ReceiveVLANMatch field in ReceiveMode */
 		rx_mode |= ReceiveVLANMatch;
 	}
-	hash_table[0] = 0x00000000;
-	hash_table[1] = 0x00000000;
 
-	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-	     i++, mclist = mclist->next) {
-		set_bit (ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
-			 hash_table);
-	}
 	writel (hash_table[0], ioaddr + HashTable0);
 	writel (hash_table[1], ioaddr + HashTable1);
 	writew (rx_mode, ioaddr + ReceiveMode);
@@ -1677,8 +1704,9 @@
  
 Compile command: 
  
-gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2x.c
+gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.c
 
 Read Documentation/networking/dl2k.txt for details.
 
 */
+
diff -Nru a/drivers/net/dl2k.h b/drivers/net/dl2k.h
--- a/drivers/net/dl2k.h	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/dl2k.h	Sun Feb 10 19:58:05 2002
@@ -34,7 +34,7 @@
 #include <linux/spinlock.h>
 #include <linux/time.h>
 #define TX_RING_SIZE	128
-#define TX_QUEUE_LEN	96	/* Limit ring entries actually used.  */
+#define TX_QUEUE_LEN	120	/* Limit ring entries actually used.  */
 #define RX_RING_SIZE 	128
 #define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct netdev_desc)
 #define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct netdev_desc)
@@ -183,12 +183,12 @@
 
 /* Bits in the ReceiveMode register. */
 enum ReceiveMode_bits {
-	ReceiveIPMulticast = 0x0020,
-	ReceiveMulticastHash = 0x0010,
-	ReceiveAllFrames = 0x0008,
-	ReceiveBroadcast = 0x0004,
-	ReceiveMulticast = 0x0002,
 	ReceiveUnicast = 0x0001,
+	ReceiveMulticast = 0x0002,
+	ReceiveBroadcast = 0x0004,
+	ReceiveAllFrames = 0x0008,
+	ReceiveMulticastHash = 0x0010,
+	ReceiveIPMulticast = 0x0020,
 	ReceiveVLANMatch = 0x0100,
 	ReceiveVLANHash = 0x0200,
 };
@@ -650,20 +650,20 @@
 	struct pci_dev *pdev;
 	spinlock_t lock;
 	struct net_device_stats stats;
-	unsigned int rx_buf_sz;	/* Based on MTU+slack. */
-	unsigned int speed;	/* Operating speed */
-	unsigned int vlan;	/* VLAN Id */
-	unsigned int chip_id;	/* PCI table chip id */
-	unsigned int int_count; /* Maximum frames each RxDMAComplete intr */
-	unsigned int int_timeout; /* Wait time between RxDMAComplete intr */
-	unsigned int tx_full:1;	/* The Tx queue is full. */
+	unsigned int rx_buf_sz;		/* Based on MTU+slack. */
+	unsigned int speed;		/* Operating speed */
+	unsigned int vlan;		/* VLAN Id */
+	unsigned int chip_id;		/* PCI table chip id */
+	unsigned int rx_coalesce; 	/* Maximum frames each RxDMAComplete intr */
+	unsigned int rx_timeout; 	/* Wait time between RxDMAComplete intr */
+	unsigned int tx_full:1;		/* The Tx queue is full. */
 	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
 	unsigned int an_enable:2;	/* Auto-Negotiated Enable */
 	unsigned int jumbo:1;		/* Jumbo frame enable */
 	unsigned int coalesce:1;	/* Rx coalescing enable */
 	unsigned int tx_flow:1;		/* Tx flow control enable */
 	unsigned int rx_flow:1;		/* Rx flow control enable */
-	unsigned int phy_media:1;	/* 1: fiber, 0: copper */ 
+	unsigned int phy_media:1;	/* 1: fiber, 0: copper */
 	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
 	unsigned long cur_rx, old_rx;	/* Producer/consumer ring indices */
 	unsigned long cur_tx, old_tx;
@@ -698,7 +698,12 @@
 MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
 #define TX_TIMEOUT  (4*HZ)
 #define PACKET_SIZE		1536
+#define MAX_JUMBO		8000
 #define RIO_IO_SIZE             340
+#define DEFAULT_RXC		5
+#define DEFAULT_RXT		750
+#define DEFAULT_TXC		1
+#define MAX_TXC			8
 #ifdef RIO_DEBUG
 #define DEBUG_TFD_DUMP(x) debug_tfd_dump(x)
 #define DEBUG_RFD_DUMP(x,flag) debug_rfd_dump(x,flag)
@@ -792,6 +797,7 @@
 	}
 	if (np->rx_debug == 7) {
 
+#error Please convert me to Documentation/DMA-mapping.txt
 		phead =
 		    bus_to_virt (le64_to_cpu (desc->fraginfo & 0xffffffffff));
 		for (pchar = phead, i = 0; i < pkt_len; i++, pchar++) {
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/eepro100.c	Sun Feb 10 19:58:04 2002
@@ -162,13 +162,6 @@
 									(dev)->watchdog_timeo = (tm); \
 								} while(0)
 
-#ifndef PCI_DEVICE_ID_INTEL_ID1029
-#define PCI_DEVICE_ID_INTEL_ID1029 0x1029
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ID1030
-#define PCI_DEVICE_ID_INTEL_ID1030 0x1030
-#endif
-
 
 static int speedo_debug = 1;
 
@@ -833,6 +826,10 @@
 	sp->phy[0] = eeprom[6];
 	sp->phy[1] = eeprom[7];
 	sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1;
+	if (((pdev->device > 0x1030 && (pdev->device < 0x1039))) 
+	    || (pdev->device == 0x2449)) {
+	    	sp->chip_id = 1;
+	}
 
 	if (sp->rx_bug)
 		printk(KERN_INFO "  Receiver lock-up workaround activated.\n");
@@ -987,6 +984,11 @@
 	if ((sp->phy[0] & 0x8000) == 0)
 		sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4);
 
+	if (mdio_read(ioaddr, sp->phy[0] & 0x1f, MII_BMSR) & BMSR_LSTATUS)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
+
 	if (speedo_debug > 2) {
 		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
@@ -1098,10 +1100,10 @@
 			/* Clear sticky bit. */
 			mdio_read(ioaddr, phy_num, 1);
 			/* If link beat has returned... */
-			if (mdio_read(ioaddr, phy_num, 1) & 0x0004)
-				dev->flags |= IFF_RUNNING;
+			if (mdio_read(ioaddr, phy_num, MII_BMSR) & BMSR_LSTATUS)
+				netif_carrier_on(dev);
 			else
-				dev->flags &= ~IFF_RUNNING;
+				netif_carrier_off(dev);
 		}
 	}
 	if (speedo_debug > 3) {
@@ -1375,7 +1377,7 @@
 
 	/* workaround for hardware bug on 10 mbit half duplex */
 
-	if ((sp->partner==0) && (sp->chip_id==1)) {
+	if ((sp->partner == 0) || (sp->chip_id == 1)) {
 		wait_for_cmd_done(ioaddr + SCBCmd);
 		outb(0 , ioaddr + SCBCmd);
 	}
@@ -2263,18 +2265,24 @@
 static struct pci_device_id eepro100_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
 		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82562ET,
-		PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER,
 		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CAM,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1029,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1030,
-		PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_7,
 		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1228, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl);
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/epic100.c	Sun Feb 10 19:58:06 2002
@@ -53,11 +53,18 @@
 	LK1.1.10:
 	* revert MII transceiver init change (jgarzik)
 
+	LK1.1.11:
+	* implement ETHTOOL_[GS]SET, _NWAY_RST, _[GS]MSGLVL, _GLINK (jgarzik)
+	* replace some MII-related magic numbers with constants
+
+	LK1.1.12:
+	* fix power-up sequence
+
 */
 
 #define DRV_NAME	"epic100"
-#define DRV_VERSION	"1.11+LK1.1.10"
-#define DRV_RELDATE	"July 6, 2001"
+#define DRV_VERSION	"1.11+LK1.1.12"
+#define DRV_RELDATE	"Jan 18, 2002"
 
 
 /* The user-configurable values.
@@ -318,12 +325,9 @@
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
 	unsigned int cur_tx, dirty_tx;
-	struct descriptor  *last_tx_desc;
 
 	unsigned int cur_rx, dirty_rx;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
-	struct descriptor  *last_rx_desc;
-	long last_rx_time;					/* Last Rx, in jiffies. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
 	int chip_id, chip_flags;
@@ -335,13 +339,9 @@
 	signed char phys[4];				/* MII device addresses. */
 	u16 advertising;					/* NWay media advertisement */
 	int mii_phy_cnt;
+	struct mii_if_info mii;
 	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int full_duplex:1;			/* Current duplex setting. */
-	unsigned int duplex_lock:1;			/* Duplex forced by the user. */
 	unsigned int default_port:4;		/* Last dev->if_port value. */
-	unsigned int media2:4;				/* Secondary monitored media port. */
-	unsigned int medialock:1;			/* Don't sense media type. */
-	unsigned int mediasense:1;			/* Media sensing in progress. */
 };
 
 static int epic_open(struct net_device *dev);
@@ -420,6 +420,9 @@
 
 	pci_set_drvdata(pdev, dev);
 	ep = dev->priv;
+	ep->mii.dev = dev;
+	ep->mii.mdio_read = mdio_read;
+	ep->mii.mdio_write = mdio_write;
 
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
@@ -481,7 +484,7 @@
 	{
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
+			int mii_status = mdio_read(dev, phy, MII_BMSR);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				ep->phys[phy_idx++] = phy;
 				printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
@@ -492,16 +495,17 @@
 		ep->mii_phy_cnt = phy_idx;
 		if (phy_idx != 0) {
 			phy = ep->phys[0];
-			ep->advertising = mdio_read(dev, phy, 4);
+			ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
 			printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
 				   "partner %4.4x.\n",
-				   pdev->slot_name, ep->advertising, mdio_read(dev, phy, 5));
+				   pdev->slot_name, ep->mii.advertising, mdio_read(dev, phy, 5));
 		} else if ( ! (ep->chip_flags & NO_MII)) {
 			printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
 			       pdev->slot_name);
 			/* Use the known PHY address of the EPII. */
 			ep->phys[0] = 3;
 		}
+		ep->mii.phy_id = ep->phys[0];
 	}
 
 	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
@@ -511,13 +515,11 @@
 
 	/* The lower four bits are the media type. */
 	if (duplex) {
-		ep->duplex_lock = ep->full_duplex = 1;
+		ep->mii.duplex_lock = ep->mii.full_duplex = 1;
 		printk(KERN_INFO DRV_NAME "(%s):  Forced full duplex operation requested.\n",
 		       pdev->slot_name);
 	}
 	dev->if_port = ep->default_port = option;
-	if (ep->default_port)
-		ep->medialock = 1;
 
 	/* The Epic-specific entries in the device structure. */
 	dev->open = &epic_open;
@@ -676,9 +678,8 @@
 	   required by the details of which bits are reset and the transceiver
 	   wiring on the Ositech CardBus card.
 	*/
-#if 0
-	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
-#endif
+
+	outl(0x12, ioaddr + MIICfg);
 	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
@@ -700,29 +701,29 @@
 
 	if (media2miictl[dev->if_port & 15]) {
 		if (ep->mii_phy_cnt)
-			mdio_write(dev, ep->phys[0], 0, media2miictl[dev->if_port&15]);
+			mdio_write(dev, ep->phys[0], MII_BMCR, media2miictl[dev->if_port&15]);
 		if (dev->if_port == 1) {
 			if (debug > 1)
 				printk(KERN_INFO "%s: Using the 10base2 transceiver, MII "
 					   "status %4.4x.\n",
-					   dev->name, mdio_read(dev, ep->phys[0], 1));
+					   dev->name, mdio_read(dev, ep->phys[0], MII_BMSR));
 		}
 	} else {
-		int mii_reg5 = mdio_read(dev, ep->phys[0], 5);
-		if (mii_reg5 != 0xffff) {
-			if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
-				ep->full_duplex = 1;
-			else if (! (mii_reg5 & 0x4000))
-				mdio_write(dev, ep->phys[0], 0, 0x1200);
+		int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA);
+		if (mii_lpa != 0xffff) {
+			if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL)
+				ep->mii.full_duplex = 1;
+			else if (! (mii_lpa & LPA_LPACK))
+				mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
 			if (debug > 1)
 				printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
 					   " register read of %4.4x.\n", dev->name,
-					   ep->full_duplex ? "full" : "half",
-					   ep->phys[0], mii_reg5);
+					   ep->mii.full_duplex ? "full" : "half",
+					   ep->phys[0], mii_lpa);
 		}
 	}
 
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(ep->rx_ring_dma, ioaddr + PRxCDAR);
 	outl(ep->tx_ring_dma, ioaddr + PTxCDAR);
 
@@ -742,7 +743,7 @@
 		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
 			   "%s-duplex.\n",
 			   dev->name, ioaddr, dev->irq, (int)inl(ioaddr + GENCTL),
-			   ep->full_duplex ? "full" : "half");
+			   ep->mii.full_duplex ? "full" : "half");
 
 	/* Set the timer to switch to check for link beat and perhaps switch
 	   to an alternate media type. */
@@ -811,7 +812,7 @@
 
 	ep->tx_threshold = TX_FIFO_THRESH;
 	outl(ep->tx_threshold, ioaddr + TxThresh);
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(ep->rx_ring_dma + (ep->cur_rx%RX_RING_SIZE)*
 		sizeof(struct epic_rx_desc), ioaddr + PRxCDAR);
 	outl(ep->tx_ring_dma + (ep->dirty_tx%TX_RING_SIZE)*
@@ -837,20 +838,20 @@
 {
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], 5) : 0;
-	int negotiated = mii_reg5 & ep->advertising;
+	int mii_lpa = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], MII_LPA) : 0;
+	int negotiated = mii_lpa & ep->mii.advertising;
 	int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 
-	if (ep->duplex_lock)
+	if (ep->mii.duplex_lock)
 		return;
-	if (mii_reg5 == 0xffff)		/* Bogus read */
+	if (mii_lpa == 0xffff)		/* Bogus read */
 		return;
-	if (ep->full_duplex != duplex) {
-		ep->full_duplex = duplex;
+	if (ep->mii.full_duplex != duplex) {
+		ep->mii.full_duplex = duplex;
 		printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
 			   " partner capability of %4.4x.\n", dev->name,
-			   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
-		outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+			   ep->mii.full_duplex ? "full" : "half", ep->phys[0], mii_lpa);
+		outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	}
 }
 
@@ -914,7 +915,6 @@
 	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	ep->dirty_tx = ep->cur_tx = 0;
 	ep->cur_rx = ep->dirty_rx = 0;
-	ep->last_rx_time = jiffies;
 	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
 
 	/* Initialize all Rx descriptors. */
@@ -1351,17 +1351,66 @@
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, np->pci_dev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
 
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 	default:
 		break;
 	}
@@ -1380,12 +1429,10 @@
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ep->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		if (! netif_running(dev)) {
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
@@ -1400,7 +1447,6 @@
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (! netif_running(dev)) {
@@ -1412,11 +1458,11 @@
 			switch (data->reg_num) {
 			case 0:
 				/* Check for autonegotiation on or reset. */
-				ep->duplex_lock = (value & 0x9000) ? 0 : 1;
-				if (ep->duplex_lock)
-					ep->full_duplex = (value & 0x0100) ? 1 : 0;
+				ep->mii.duplex_lock = (value & 0x9000) ? 0 : 1;
+				if (ep->mii.duplex_lock)
+					ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
-			case 4: ep->advertising = value; break;
+			case 4: ep->mii.advertising = value; break;
 			}
 			/* Perhaps check_duplex(dev), depending on chip semantics. */
 		}
diff -Nru a/drivers/net/fealnx.c b/drivers/net/fealnx.c
--- a/drivers/net/fealnx.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/fealnx.c	Sun Feb 10 19:58:04 2002
@@ -15,8 +15,19 @@
 
 	Support information and updates available at
 	http://www.scyld.com/network/pci-skeleton.html
+
+	Linux kernel updates:
+
+	Version 2.51, Nov 17, 2001 (jgarzik):
+	- Add ethtool support
+	- Replace some MII-related magic numbers with constants
+
 */
 
+#define DRV_NAME	"fealnx"
+#define DRV_VERSION	"2.51"
+#define DRV_RELDATE	"Nov-17-2001"
+
 static int debug;		/* 1-> print debug message */
 static int max_interrupt_work = 20;
 
@@ -72,14 +83,16 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "fealnx.c:v2.50 1/17/2001\n";
+KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
 
 
 /* This driver was written to use PCI memory space, however some x86 systems
@@ -380,6 +393,8 @@
 	dma_addr_t rx_ring_dma;
 	dma_addr_t tx_ring_dma;
 
+	spinlock_t lock;
+
 	struct net_device_stats stats;
 
 	/* Media monitoring timer. */
@@ -404,19 +419,17 @@
 	unsigned int linkok;
 	unsigned int line_speed;
 	unsigned int duplexmode;
-	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
-	unsigned int medialock:1;	/* Do not sense media. */
 	unsigned int default_port:4;	/* Last dev->if_port value. */
 	unsigned int PHYType;
 
 	/* MII transceiver section. */
 	int mii_cnt;		/* MII device addresses. */
 	unsigned char phys[2];	/* MII device addresses. */
+	struct mii_if_info mii;
 };
 
 
-static unsigned int mdio_read(struct net_device *dev, int phy_id, int location);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int netdev_open(struct net_device *dev);
 static void getlinktype(struct net_device *dev);
@@ -539,9 +552,13 @@
 
 	/* Make certain the descriptor lists are aligned. */
 	np = dev->priv;
+	spin_lock_init(&np->lock);
 	np->pci_dev = pdev;
 	np->flags = skel_netdrv_tbl[chip_id].flags;
 	pci_set_drvdata(pdev, dev);
+	np->mii.dev = dev;
+	np->mii.mdio_read = mdio_read;
+	np->mii.mdio_write = mdio_write;
 
 	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space) {
@@ -606,6 +623,7 @@
 		else
 			np->PHYType = OtherPHY;
 	}
+	np->mii.phy_id = np->phys[0];
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -613,17 +631,14 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii.full_duplex = 1;
 		np->default_port = option & 15;
-
-		if (np->default_port)
-			np->medialock = 1;
 	}
 
 	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
-		np->full_duplex = full_duplex[card_idx];
+		np->mii.full_duplex = full_duplex[card_idx];
 
-	if (np->full_duplex) {
+	if (np->mii.full_duplex) {
 		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
 /* 89/6/13 add, (begin) */
 //      if (np->PHYType==MarvellPHY)
@@ -636,10 +651,10 @@
 		}
 /* 89/6/13 add, (end) */
 		if (np->flags == HAS_MII_XCVR)
-			mdio_write(dev, np->phys[0], 4, 0x141);
+			mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		else
-			writel(0x141, dev->base_addr + ANARANLPAR);
-		np->duplex_lock = 1;
+			writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR);
+		np->mii.duplex_lock = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -787,7 +802,7 @@
 }
 
 
-static unsigned int mdio_read(struct net_device *dev, int phyad, int regad)
+static int mdio_read(struct net_device *dev, int phyad, int regad)
 {
 	long miiport = dev->base_addr + MANAGEMENT;
 	ulong miir;
@@ -821,7 +836,7 @@
 	miir &= ~MASK_MIIR_MII_MDC;
 	writel(miir, miiport);
 
-	return data;
+	return data & 0xffff;
 }
 
 
@@ -941,7 +956,7 @@
 // 89/9/1 modify,
 //   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */
 	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */
-	np->full_duplex = np->duplex_lock;
+	np->mii.full_duplex = np->mii.duplex_lock;
 	getlinkstatus(dev);
 	if (np->linkok)
 		getlinktype(dev);
@@ -990,7 +1005,7 @@
 		}
 	} else {
 		for (i = 0; i < DelayTime; ++i) {
-			if (mdio_read(dev, np->phys[0], 1) & 0x4) {
+			if (mdio_read(dev, np->phys[0], MII_BMSR) & BMSR_LSTATUS) {
 				np->linkok = 1;
 				return;
 			}
@@ -1475,7 +1490,7 @@
 						np->stats.tx_window_errors++;
 					if (tx_status & UDF)
 						np->stats.tx_fifo_errors++;
-					if ((tx_status & HF) && np->full_duplex == 0)
+					if ((tx_status & HF) && np->mii.full_duplex == 0)
 						np->stats.tx_heartbeat_errors++;
 
 #ifdef ETHER_STATS
@@ -1751,24 +1766,100 @@
 	writel(np->crvalue, ioaddr + TCRRCR);
 }
 
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	struct netdev_private *np = dev->priv;
+	u32 ethcmd;
+
+	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
 
 	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c
--- a/drivers/net/hamachi.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/hamachi.c	Sun Feb 10 19:58:06 2002
@@ -1941,17 +1941,14 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		/* TODO: Check the sequencing of this.  Might need to stop and
 		 * restart Rx and Tx engines. -KDU
 		 */
diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c
--- a/drivers/net/hp100.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/hp100.c	Sun Feb 10 19:58:05 2002
@@ -83,6 +83,8 @@
 **
 */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #define HP100_DEFAULT_PRIORITY_TX 0
 
 #undef HP100_DEBUG
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/irda/irda-usb.c	Sun Feb 10 19:58:06 2002
@@ -278,7 +278,7 @@
 	urb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
 	urb->timeout = MSECS_TO_JIFFIES(100);
 
-	if ((ret = usb_submit_urb(urb))) {
+	if ((ret = usb_submit_urb(urb, GFP_KERNEL))) {
 		WARNING(__FUNCTION__ "(), failed Speed URB\n");
 	}
 	spin_unlock_irqrestore(&self->lock, flags);
@@ -451,7 +451,7 @@
 	}
 	
 	/* Ask USB to send the packet */
-	if ((res = usb_submit_urb(urb))) {
+	if ((res = usb_submit_urb(urb, GFP_KERNEL))) {
 		WARNING(__FUNCTION__ "(), failed Tx URB\n");
 		self->stats.tx_errors++;
 		/* Let USB recover : We will catch that in the watchdog */
@@ -730,7 +730,7 @@
 	urb->status = 0;
 	urb->next = NULL;	/* Don't auto resubmit URBs */
 	
-	ret = usb_submit_urb(urb);
+	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret) {
 		/* If this ever happen, we are in deep s***.
 		 * Basically, the Rx path will stop... */
diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c
--- a/drivers/net/lance.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/lance.c	Sun Feb 10 19:58:04 2002
@@ -495,15 +495,15 @@
 		lp->init_block.phys_addr[i] = dev->dev_addr[i];
 	lp->init_block.filter[0] = 0x00000000;
 	lp->init_block.filter[1] = 0x00000000;
-	lp->init_block.rx_ring = ((u32)virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
-	lp->init_block.tx_ring = ((u32)virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
+	lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
+	lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
 
 	outw(0x0001, ioaddr+LANCE_ADDR);
 	inw(ioaddr+LANCE_ADDR);
-	outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
+	outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
 	outw(0x0002, ioaddr+LANCE_ADDR);
 	inw(ioaddr+LANCE_ADDR);
-	outw(((u32)virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
+	outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
 	outw(0x0000, ioaddr+LANCE_ADDR);
 	inw(ioaddr+LANCE_ADDR);
 
@@ -704,16 +704,16 @@
 	if (lance_debug > 1)
 		printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n",
 			   dev->name, dev->irq, dev->dma,
-		           (u32) virt_to_bus(lp->tx_ring),
-		           (u32) virt_to_bus(lp->rx_ring),
-			   (u32) virt_to_bus(&lp->init_block));
+		           (u32) isa_virt_to_bus(lp->tx_ring),
+		           (u32) isa_virt_to_bus(lp->rx_ring),
+			   (u32) isa_virt_to_bus(&lp->init_block));
 
 	lance_init_ring(dev, GFP_KERNEL);
 	/* Re-initialize the LANCE, and start it when done. */
 	outw(0x0001, ioaddr+LANCE_ADDR);
-	outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
+	outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
 	outw(0x0002, ioaddr+LANCE_ADDR);
-	outw(((u32)virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
+	outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
 
 	outw(0x0004, ioaddr+LANCE_ADDR);
 	outw(0x0915, ioaddr+LANCE_DATA);
@@ -735,7 +735,7 @@
 
 	if (lance_debug > 2)
 		printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n",
-			   dev->name, i, (u32) virt_to_bus(&lp->init_block), inw(ioaddr+LANCE_DATA));
+			   dev->name, i, (u32) isa_virt_to_bus(&lp->init_block), inw(ioaddr+LANCE_DATA));
 
 	return 0;					/* Always succeed */
 }
@@ -799,7 +799,7 @@
 		if (rx_buff == NULL)
 			lp->rx_ring[i].base = 0;
 		else
-			lp->rx_ring[i].base = (u32)virt_to_bus(rx_buff) | 0x80000000;
+			lp->rx_ring[i].base = (u32)isa_virt_to_bus(rx_buff) | 0x80000000;
 		lp->rx_ring[i].buf_length = -PKT_BUF_SZ;
 	}
 	/* The Tx buffer address is filled in as needed, but we do need to clear
@@ -814,8 +814,8 @@
 		lp->init_block.phys_addr[i] = dev->dev_addr[i];
 	lp->init_block.filter[0] = 0x00000000;
 	lp->init_block.filter[1] = 0x00000000;
-	lp->init_block.rx_ring = ((u32)virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
-	lp->init_block.tx_ring = ((u32)virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
+	lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
+	lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
 }
 
 static void
@@ -904,17 +904,17 @@
 
 	/* If any part of this buffer is >16M we must copy it to a low-memory
 	   buffer. */
-	if ((u32)virt_to_bus(skb->data) + skb->len > 0x01000000) {
+	if ((u32)isa_virt_to_bus(skb->data) + skb->len > 0x01000000) {
 		if (lance_debug > 5)
 			printk("%s: bouncing a high-memory packet (%#x).\n",
-				   dev->name, (u32)virt_to_bus(skb->data));
+				   dev->name, (u32)isa_virt_to_bus(skb->data));
 		memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len);
 		lp->tx_ring[entry].base =
-			((u32)virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
+			((u32)isa_virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
 		dev_kfree_skb(skb);
 	} else {
 		lp->tx_skbuff[entry] = skb;
-		lp->tx_ring[entry].base = ((u32)virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
+		lp->tx_ring[entry].base = ((u32)isa_virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
 	}
 	lp->cur_tx++;
 
@@ -1112,7 +1112,7 @@
 				skb_reserve(skb,2);	/* 16 byte align */
 				skb_put(skb,pkt_len);	/* Make room */
 				eth_copy_and_sum(skb,
-					(unsigned char *)bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
+					(unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
 					pkt_len,0);
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
--- a/drivers/net/lasi_82596.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/lasi_82596.c	Sun Feb 10 19:58:04 2002
@@ -1184,7 +1184,7 @@
 			printk("%s: Couldn't get shared memory\n", dev->name);
 			return -ENOMEM;
 		}
-		dma_addr = virt_to_bus(dev->mem_start);
+		dma_addr = virt_to_phys(dev->mem_start);
 	}
 
 	ether_setup(dev);
diff -Nru a/drivers/net/lne390.c b/drivers/net/lne390.c
--- a/drivers/net/lne390.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/lne390.c	Sun Feb 10 19:58:05 2002
@@ -226,10 +226,10 @@
 	   the card mem within the region covered by `normal' RAM  !!!
 	*/
 	if (dev->mem_start > 1024*1024) {	/* phys addr > 1MB */
-		if (dev->mem_start < virt_to_bus(high_memory)) {
+		if (dev->mem_start < virt_to_phys(high_memory)) {
 			printk(KERN_CRIT "lne390.c: Card RAM overlaps with normal memory!!!\n");
 			printk(KERN_CRIT "lne390.c: Use EISA SCU to set card memory below 1MB,\n");
-			printk(KERN_CRIT "lne390.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory));
+			printk(KERN_CRIT "lne390.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
 			printk(KERN_CRIT "lne390.c: Driver NOT installed.\n");
 			ret = -EINVAL;
 			goto cleanup;
diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c
--- a/drivers/net/mii.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/mii.c	Sun Feb 10 19:58:05 2002
@@ -168,6 +168,10 @@
 	return r;
 }
 
+MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_DESCRIPTION ("MII hardware support library");
+MODULE_LICENSE("GPL");
+
 EXPORT_SYMBOL(mii_link_ok);
 EXPORT_SYMBOL(mii_nway_restart);
 EXPORT_SYMBOL(mii_ethtool_gset);
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/natsemi.c	Sun Feb 10 19:58:04 2002
@@ -394,7 +394,11 @@
 	SDCFG			= 0xF8
 };
 /* the values for the 'magic' registers above (PGSEL=1) */
+#ifdef CONFIG_NATSEMI_CABLE_MAGIC
+#define PMDCSR_VAL	0x1898
+#else
 #define PMDCSR_VAL	0x189C
+#endif
 #define TSTDAT_VAL	0x0
 #define DSPCFG_VAL	0x5040
 #define SDCFG_VAL	0x008c
@@ -1511,7 +1515,7 @@
 		if (intr_status == 0)
 			break;
 
-		if (intr_status & (IntrRxDone | IntrRxIntr))
+		if (intr_status & (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | IntrRxErr | IntrRxOverrun ))
 			netdev_rx(dev);
 
 		if (intr_status & (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr) ) {
diff -Nru a/drivers/net/ne3210.c b/drivers/net/ne3210.c
--- a/drivers/net/ne3210.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/ne3210.c	Sun Feb 10 19:58:05 2002
@@ -213,10 +213,10 @@
 	   the card mem within the region covered by `normal' RAM  !!!
 	*/
 	if (dev->mem_start > 1024*1024) {	/* phys addr > 1MB */
-		if (dev->mem_start < virt_to_bus(high_memory)) {
+		if (dev->mem_start < virt_to_phys(high_memory)) {
 			printk(KERN_CRIT "ne3210.c: Card RAM overlaps with normal memory!!!\n");
 			printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n");
-			printk(KERN_CRIT "ne3210.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory));
+			printk(KERN_CRIT "ne3210.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
 			printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n");
 			retval = -EINVAL;
 			goto out2;
diff -Nru a/drivers/net/ni52.c b/drivers/net/ni52.c
--- a/drivers/net/ni52.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/ni52.c	Sun Feb 10 19:58:04 2002
@@ -286,8 +286,8 @@
 	char *iscp_addrs[2];
 	int i;
 
-	p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
-	p->memtop = bus_to_virt((unsigned long)where) + size;
+	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000;
+	p->memtop = isa_bus_to_virt((unsigned long)where) + size;
 	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
 	memset((char *)p->scp,0, sizeof(struct scp_struct));
 	for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */
@@ -297,7 +297,7 @@
 	if(p->scp->sysbus != SYSBUSVAL)
 		return 0;
 
-	iscp_addrs[0] = bus_to_virt((unsigned long)where);
+	iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
 	iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
 
 	for(i=0;i<2;i++)
@@ -329,7 +329,7 @@
 	DELAY(1);
 
 	p->scp	= (struct scp_struct *)	(p->base + SCP_DEFAULT_ADDRESS);
-	p->scb	= (struct scb_struct *)	bus_to_virt(dev->mem_start);
+	p->scb	= (struct scb_struct *)	isa_bus_to_virt(dev->mem_start);
 	p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
 
 	memset((char *) p->iscp,0,sizeof(struct iscp_struct));
@@ -477,8 +477,8 @@
 																	/* warning: we don't free it on errors */
 	memset((char *) dev->priv,0,sizeof(struct priv));
 
-	((struct priv *) (dev->priv))->memtop = bus_to_virt(dev->mem_start) + size;
-	((struct priv *) (dev->priv))->base =	(unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
+	((struct priv *) (dev->priv))->memtop = isa_bus_to_virt(dev->mem_start) + size;
+	((struct priv *) (dev->priv))->base =	(unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
 	alloc586(dev);
 
 	/* set number of receive-buffs according to memsize */
diff -Nru a/drivers/net/ni65.c b/drivers/net/ni65.c
--- a/drivers/net/ni65.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/ni65.c	Sun Feb 10 19:58:05 2002
@@ -507,10 +507,10 @@
 		p->ib.filter[i] = filter;
 	p->ib.mode = mode;
 
-	p->ib.trp = (u32) virt_to_bus(p->tmdhead) | TMDNUMMASK;
-	p->ib.rrp = (u32) virt_to_bus(p->rmdhead) | RMDNUMMASK;
+	p->ib.trp = (u32) isa_virt_to_bus(p->tmdhead) | TMDNUMMASK;
+	p->ib.rrp = (u32) isa_virt_to_bus(p->rmdhead) | RMDNUMMASK;
 	writereg(0,CSR3);	/* busmaster/no word-swap */
-	pib = (u32) virt_to_bus(&p->ib);
+	pib = (u32) isa_virt_to_bus(&p->ib);
 	writereg(pib & 0xffff,CSR1);
 	writereg(pib >> 16,CSR2);
 
@@ -551,7 +551,7 @@
 			return NULL;
 		}
 	}
-	if( (u32) virt_to_bus(ptr+size) > 0x1000000) {
+	if( (u32) virt_to_phys(ptr+size) > 0x1000000) {
 		printk("%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
 		if(type)
 			kfree_skb(skb);
@@ -683,7 +683,7 @@
 #ifdef XMT_VIA_SKB
 			skb_save[i] = p->tmd_skb[i];
 #endif
-			buffer[i] = (u32) bus_to_virt(tmdp->u.buffer);
+			buffer[i] = (u32) isa_bus_to_virt(tmdp->u.buffer);
 			blen[i] = tmdp->blen;
 			tmdp->u.s.status = 0x0;
 		}
@@ -697,7 +697,7 @@
 
 		for(i=0;i<TMDNUM;i++) {
 			int num = (i + p->tmdlast) & (TMDNUM-1);
-			p->tmdhead[i].u.buffer = (u32) virt_to_bus((char *)buffer[num]); /* status is part of buffer field */
+			p->tmdhead[i].u.buffer = (u32) isa_virt_to_bus((char *)buffer[num]); /* status is part of buffer field */
 			p->tmdhead[i].blen = blen[num];
 			if(p->tmdhead[i].u.s.status & XMIT_OWN) {
 				 p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
@@ -766,9 +766,9 @@
 	 {
 		 struct rmd *rmdp = p->rmdhead + i;
 #ifdef RCV_VIA_SKB
-		 rmdp->u.buffer = (u32) virt_to_bus(p->recv_skb[i]->data);
+		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recv_skb[i]->data);
 #else
-		 rmdp->u.buffer = (u32) virt_to_bus(p->recvbounce[i]);
+		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recvbounce[i]);
 #endif
 		 rmdp->blen = -(R_BUF_SIZE-8);
 		 rmdp->mlen = 0;
@@ -1033,7 +1033,7 @@
 					struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
 					skb_put(skb,R_BUF_SIZE);
 					p->recv_skb[p->rmdnum] = skb;
-					rmdp->u.buffer = (u32) virt_to_bus(skb->data);
+					rmdp->u.buffer = (u32) isa_virt_to_bus(skb->data);
 					skb = skb1;
 					skb_trim(skb,len);
 				}
@@ -1115,7 +1115,7 @@
 			cli();
 
 			tmdp = p->tmdhead + p->tmdnum;
-			tmdp->u.buffer = (u32) virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
+			tmdp->u.buffer = (u32) isa_virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
 			p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1);
 
 #ifdef XMT_VIA_SKB
@@ -1125,7 +1125,7 @@
 			cli();
 
 			tmdp = p->tmdhead + p->tmdnum;
-			tmdp->u.buffer = (u32) virt_to_bus(skb->data);
+			tmdp->u.buffer = (u32) isa_virt_to_bus(skb->data);
 			p->tmd_skb[p->tmdnum] = skb;
 		}
 #endif
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/ns83820.c	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-#define VERSION "0.13"
+#define VERSION "0.14"
 /* ns83820.c by Benjamin LaHaise <bcrl@redhat.com>
  *
  * $Revision: 1.34.2.8 $
@@ -45,6 +45,7 @@
  *			0.12 - add statistics counters
  *			     - add allmulti/promisc support
  *	20011009	0.13 - hotplug support, other smaller pci api cleanups
+ *	20011117	0.14 - ethtool GDRVINFO, GLINK support
  *
  * Driver Overview
  * ===============
@@ -86,9 +87,11 @@
 #include <linux/in.h>	/* for IPPROTO_... */
 #include <linux/eeprom.h>
 #include <linux/compiler.h>
+#include <linux/ethtool.h>
 //#include <linux/skbrefill.h>
 
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* Dprintk is used for more interesting debug events */
 #undef Dprintk
@@ -1007,6 +1010,59 @@
 	return &dev->stats;
 }
 
+static int ns83820_ethtool_ioctl (struct ns83820 *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO:
+		{
+			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+			strcpy (info.driver, "ns83820");
+			strcpy (info.version, VERSION);
+			strcpy (info.bus_info, dev->pci_dev->slot_name);
+			if (copy_to_user (useraddr, &info, sizeof (info)))
+				return -EFAULT;
+			return 0;
+		}
+
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
+
+		if (cfg & CFG_LNKSTS)
+			edata.data = 1;
+		else
+			edata.data = 0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int ns83820_ioctl(struct net_device *_dev, struct ifreq *rq, int cmd)
+{
+	struct ns83820 *dev = _dev->priv;
+
+	switch(cmd) {
+	case SIOCETHTOOL:
+		return ns83820_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static void ns83820_irq(int foo, void *data, struct pt_regs *regs)
 {
 	struct ns83820 *dev = data;
@@ -1294,6 +1350,7 @@
 	dev->net_dev.get_stats = ns83820_get_stats;
 	dev->net_dev.change_mtu = ns83820_change_mtu;
 	dev->net_dev.set_multicast_list = ns83820_set_multicast;
+	dev->net_dev.do_ioctl = ns83820_ioctl;
 	//FIXME: dev->net_dev.tx_timeout = ns83820_tx_timeout;
 
 	pci_set_drvdata(pci_dev, dev);
diff -Nru a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
--- a/drivers/net/pci-skeleton.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/pci-skeleton.c	Sun Feb 10 19:58:04 2002
@@ -834,7 +834,7 @@
 		printk (KERN_INFO
 			"%s: Media type forced to Full Duplex.\n",
 			dev->name);
-		mdio_write (dev, tp->phys[0], 4, 0x141);
+		mdio_write (dev, tp->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		tp->duplex_lock = 1;
 	}
 
@@ -1235,20 +1235,20 @@
 	struct netdrv_private *tp = dev->priv;
 	void *ioaddr = tp->mmio_addr;
 	int next_tick = 60 * HZ;
-	int mii_reg5;
+	int mii_lpa;
 
-	mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
 
-	if (!tp->duplex_lock && mii_reg5 != 0xffff) {
-		int duplex = (mii_reg5 & 0x0100)
-		    || (mii_reg5 & 0x01C0) == 0x0040;
+	if (!tp->duplex_lock && mii_lpa != 0xffff) {
+		int duplex = (mii_lpa & LPA_100FULL)
+		    || (mii_lpa & 0x01C0) == 0x0040;
 		if (tp->full_duplex != duplex) {
 			tp->full_duplex = duplex;
 			printk (KERN_INFO
 				"%s: Setting %s-duplex based on MII #%d link"
 				" partner ability of %4.4x.\n", dev->name,
 				tp->full_duplex ? "full" : "half",
-				tp->phys[0], mii_reg5);
+				tp->phys[0], mii_lpa);
 			NETDRV_W8 (Cfg9346, Cfg9346_Unlock);
 			NETDRV_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
 			NETDRV_W8 (Cfg9346, Cfg9346_Lock);
@@ -1793,19 +1793,16 @@
 
 	switch (cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = tp->phys[0] & 0x3f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		spin_lock_irqsave (&tp->lock, flags);
 		data->val_out = mdio_read (dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		spin_unlock_irqrestore (&tp->lock, flags);
 		break;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable (CAP_NET_ADMIN)) {
 			rc = -EPERM;
 			break;
diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
--- a/drivers/net/pcmcia/3c589_cs.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/pcmcia/3c589_cs.c	Sun Feb 10 19:58:06 2002
@@ -17,6 +17,9 @@
 
 ======================================================================*/
 
+#define DRV_NAME	"3c589_cs"
+#define DRV_VERSION	"1.162"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -28,6 +31,9 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/delay.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -134,7 +140,7 @@
 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"3c589_cs.c 1.162 2001/10/13 00:08:50 (David Hinds)";
+DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -159,6 +165,7 @@
 static int el3_close(struct net_device *dev);
 static void el3_tx_timeout(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 static dev_info_t dev_info = "3c589_cs";
 
@@ -249,7 +256,8 @@
     dev->tx_timeout = el3_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
-    
+    dev->do_ioctl = netdev_ioctl;
+
     /* Register with Card Services */
     link->next = dev_list;
     dev_list = link;
@@ -638,6 +646,71 @@
 	 ioaddr + EL3_CMD);
     outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
 	 | AdapterFailure, ioaddr + EL3_CMD);
+}
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+#ifdef PCMCIA_DEBUG
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = pc_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		pc_debug = edata.data;
+		return 0;
+	}
+#endif
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
 }
 
 static int el3_config(struct net_device *dev, struct ifmap *map)
diff -Nru a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c
--- a/drivers/net/pcmcia/aironet4500_cs.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/pcmcia/aironet4500_cs.c	Sun Feb 10 19:58:04 2002
@@ -10,8 +10,11 @@
  *
  */
 
+#define DRV_NAME	"aironet4500_cs"
+#define DRV_VERSION	"0.1"
+
 static const char *awc_version =
-"aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
+DRV_NAME ".c v" DRV_VERSION " 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
 
 
 #include <linux/module.h>
@@ -24,6 +27,9 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -159,6 +165,66 @@
 	return ret;
 }
 
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+#ifdef PCMCIA_DEBUG
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = pc_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		pc_debug = edata.data;
+		return 0;
+	}
+#endif
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int awc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
 /*
 	awc_attach() creates an "instance" of the driver, allocating
 	local data structures for one device.  The device is registered
@@ -230,7 +296,8 @@
 //	dev->set_config = 		&awc_config_misiganes,aga mitte awc_config;
 	dev->get_stats = 		&awc_get_stats;
 //	dev->set_multicast_list = 	&awc_set_multicast_list;
-
+	dev->do_ioctl =			&awc_ioctl;
+	
 	strcpy(dev->name, ((struct awc_private *)dev->priv)->node.dev_name);
 
 	ether_setup(dev);
diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
--- a/drivers/net/pcmcia/fmvj18x_cs.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/pcmcia/fmvj18x_cs.c	Sun Feb 10 19:58:04 2002
@@ -28,6 +28,9 @@
    
 ======================================================================*/
 
+#define DRV_NAME	"fmvj18x_cs"
+#define DRV_VERSION	"2.6"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -39,6 +42,9 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/delay.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -74,7 +80,7 @@
 #ifdef PCMCIA_DEBUG
 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version = "fmvj18x_cs.c 2.6 2001/09/17";
+static char *version = DRV_NAME ".c " DRV_VERSION " 2001/09/17";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -104,6 +110,7 @@
 static struct net_device_stats *fjn_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static void fjn_tx_timeout(struct net_device *dev);
+static int fjn_ioctl(struct net_device *, struct ifreq *, int);
 
 static dev_info_t dev_info = "fmvj18x_cs";
 static dev_link_t *dev_list;
@@ -316,6 +323,7 @@
     dev->tx_timeout = fjn_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
+    dev->do_ioctl = fjn_ioctl;
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -1102,6 +1110,65 @@
 } /* fjn_rx */
 
 /*====================================================================*/
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+#ifdef PCMCIA_DEBUG
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = pc_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		pc_debug = edata.data;
+		return 0;
+	}
+#endif
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int fjn_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
 
 static int fjn_config(struct net_device *dev, struct ifmap *map){
     return 0;
diff -Nru a/drivers/net/pcmcia/xircom_tulip_cb.c b/drivers/net/pcmcia/xircom_tulip_cb.c
--- a/drivers/net/pcmcia/xircom_tulip_cb.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/pcmcia/xircom_tulip_cb.c	Sun Feb 10 19:58:04 2002
@@ -1472,21 +1472,18 @@
 
 	/* Legacy mii-diag interface */
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		if (tp->mii_cnt)
 			data[0] = phy;
 		else
 			return -ENODEV;
 		return 0;
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		save_flags(flags);
 		cli();
 		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
 		restore_flags(flags);
 		return 0;
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		save_flags(flags);
diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
--- a/drivers/net/pcnet32.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/pcnet32.c	Sun Feb 10 19:58:05 2002
@@ -65,15 +65,15 @@
 static const int max_interrupt_work = 80;
 static const int rx_copybreak = 200;
 
-#define PORT_AUI      0x00
-#define PORT_10BT     0x01
-#define PORT_GPSI     0x02
-#define PORT_MII      0x03
-
-#define PORT_PORTSEL  0x03
-#define PORT_ASEL     0x04
-#define PORT_100      0x40
-#define PORT_FD	      0x80
+#define PCNET32_PORT_AUI      0x00
+#define PCNET32_PORT_10BT     0x01
+#define PCNET32_PORT_GPSI     0x02
+#define PCNET32_PORT_MII      0x03
+
+#define PCNET32_PORT_PORTSEL  0x03
+#define PCNET32_PORT_ASEL     0x04
+#define PCNET32_PORT_100      0x40
+#define PCNET32_PORT_FD	      0x80
 
 #define PCNET32_DMA_MASK 0xffffffff
 
@@ -82,22 +82,22 @@
  * to internal options
  */
 static unsigned char options_mapping[] = {
-    PORT_ASEL,			   /*  0 Auto-select	  */
-    PORT_AUI,			   /*  1 BNC/AUI	  */
-    PORT_AUI,			   /*  2 AUI/BNC	  */ 
-    PORT_ASEL,			   /*  3 not supported	  */
-    PORT_10BT | PORT_FD,	   /*  4 10baseT-FD	  */
-    PORT_ASEL,			   /*  5 not supported	  */
-    PORT_ASEL,			   /*  6 not supported	  */
-    PORT_ASEL,			   /*  7 not supported	  */
-    PORT_ASEL,			   /*  8 not supported	  */
-    PORT_MII,			   /*  9 MII 10baseT	  */
-    PORT_MII | PORT_FD,		   /* 10 MII 10baseT-FD	  */
-    PORT_MII,			   /* 11 MII (autosel)	  */
-    PORT_10BT,			   /* 12 10BaseT	  */
-    PORT_MII | PORT_100,	   /* 13 MII 100BaseTx	  */
-    PORT_MII | PORT_100 | PORT_FD, /* 14 MII 100BaseTx-FD */
-    PORT_ASEL			   /* 15 not supported	  */
+    PCNET32_PORT_ASEL,			   /*  0 Auto-select	  */
+    PCNET32_PORT_AUI,			   /*  1 BNC/AUI	  */
+    PCNET32_PORT_AUI,			   /*  2 AUI/BNC	  */ 
+    PCNET32_PORT_ASEL,			   /*  3 not supported	  */
+    PCNET32_PORT_10BT | PCNET32_PORT_FD,	   /*  4 10baseT-FD	  */
+    PCNET32_PORT_ASEL,			   /*  5 not supported	  */
+    PCNET32_PORT_ASEL,			   /*  6 not supported	  */
+    PCNET32_PORT_ASEL,			   /*  7 not supported	  */
+    PCNET32_PORT_ASEL,			   /*  8 not supported	  */
+    PCNET32_PORT_MII,			   /*  9 MII 10baseT	  */
+    PCNET32_PORT_MII | PCNET32_PORT_FD,		   /* 10 MII 10baseT-FD	  */
+    PCNET32_PORT_MII,			   /* 11 MII (autosel)	  */
+    PCNET32_PORT_10BT,			   /* 12 10BaseT	  */
+    PCNET32_PORT_MII | PCNET32_PORT_100,	   /* 13 MII 100BaseTx	  */
+    PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD, /* 14 MII 100BaseTx-FD */
+    PCNET32_PORT_ASEL			   /* 15 not supported	  */
 };
 
 #define MAX_UNITS 8
@@ -709,12 +709,12 @@
     lp->ltint = ltint;
     lp->mii = mii;
     if (options[card_idx] > sizeof (options_mapping))
-	lp->options = PORT_ASEL;
+	lp->options = PCNET32_PORT_ASEL;
     else
 	lp->options = options_mapping[options[card_idx]];
     
-    if (fdx && !(lp->options & PORT_ASEL) && full_duplex[card_idx])
-	lp->options |= PORT_FD;
+    if (fdx && !(lp->options & PCNET32_PORT_ASEL) && full_duplex[card_idx])
+	lp->options |= PCNET32_PORT_FD;
     
     if (a == NULL) {
       printk(KERN_ERR "pcnet32: No access methods\n");
@@ -726,7 +726,7 @@
     
     /* detect special T1/E1 WAN card by checking for MAC address */
     if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75)
-	lp->options = PORT_FD | PORT_GPSI;
+	lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
 
     lp->init_block.mode = le16_to_cpu(0x0003);	/* Disable Rx and Tx. */
     lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); 
@@ -829,16 +829,16 @@
     
     /* set/reset autoselect bit */
     val = lp->a.read_bcr (ioaddr, 2) & ~2;
-    if (lp->options & PORT_ASEL)
+    if (lp->options & PCNET32_PORT_ASEL)
 	val |= 2;
     lp->a.write_bcr (ioaddr, 2, val);
     
     /* handle full duplex setting */
     if (lp->full_duplex) {
 	val = lp->a.read_bcr (ioaddr, 9) & ~3;
-	if (lp->options & PORT_FD) {
+	if (lp->options & PCNET32_PORT_FD) {
 	    val |= 1;
-	    if (lp->options == (PORT_FD | PORT_AUI))
+	    if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI))
 		val |= 2;
 	}
 	lp->a.write_bcr (ioaddr, 9, val);
@@ -846,19 +846,19 @@
     
     /* set/reset GPSI bit in test register */
     val = lp->a.read_csr (ioaddr, 124) & ~0x10;
-    if ((lp->options & PORT_PORTSEL) == PORT_GPSI)
+    if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)
 	val |= 0x10;
     lp->a.write_csr (ioaddr, 124, val);
     
-    if (lp->mii && !(lp->options & PORT_ASEL)) {
+    if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
 	val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */
-	if (lp->options & PORT_FD)
+	if (lp->options & PCNET32_PORT_FD)
 	    val |= 0x10;
-	if (lp->options & PORT_100)
+	if (lp->options & PCNET32_PORT_100)
 	    val |= 0x08;
 	lp->a.write_bcr (ioaddr, 32, val);
     } else {
-	if (lp->options & PORT_ASEL) {  /* enable auto negotiate, setup, disable fd */
+	if (lp->options & PCNET32_PORT_ASEL) {  /* enable auto negotiate, setup, disable fd */
 		val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
 		val |= 0x20;
 		lp->a.write_bcr(ioaddr, 32, val);
@@ -878,7 +878,7 @@
 	lp->a.write_csr (ioaddr, 5, val);
     }
    
-    lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
+    lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
     lp->init_block.filter[0] = 0x00000000;
     lp->init_block.filter[1] = 0x00000000;
     if (pcnet32_init_ring(dev))
@@ -1465,9 +1465,9 @@
     if (dev->flags&IFF_PROMISC) {
 	/* Log any net taps. */
 	printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
-	lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PORT_PORTSEL) << 7);
+	lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7);
     } else {
-	lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
+	lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
 	pcnet32_load_multicast (dev);
     }
     
diff -Nru a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
--- a/drivers/net/rcpci45.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/rcpci45.c	Sun Feb 10 19:58:05 2002
@@ -44,6 +44,8 @@
 **
 ***************************************************************************/
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c
--- a/drivers/net/rrunner.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/rrunner.c	Sun Feb 10 19:58:05 2002
@@ -21,6 +21,8 @@
  * ODS/Essential.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #define DEBUG 1
 #define RX_DMA_SKBUFF 1
 #define PKT_COPY_THRESHOLD 512
diff -Nru a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c
--- a/drivers/net/sk_g16.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/sk_g16.c	Sun Feb 10 19:58:06 2002
@@ -810,7 +810,7 @@
     SK_print_pos(dev, "POS registers after ROM, RAM config");
 #endif
 
-    board = (SK_RAM *) bus_to_virt(rom_addr);
+    board = (SK_RAM *) isa_bus_to_virt(rom_addr);
 
     /* Read in station address */
     for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c
--- a/drivers/net/slip.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/slip.c	Sun Feb 10 19:58:06 2002
@@ -483,7 +483,7 @@
 		 *      14 Oct 1994 Dmitry Gorodchanin.
 		 */
 #ifdef SL_CHECK_TRANSMIT
-		if (jiffies - dev->trans_start  < 20 * HZ)  {
+		if (time_before(jiffies, dev->trans_start + 20 * HZ))  {
 			/* 20 sec timeout not reached */
 			goto out;
 		}
@@ -1387,7 +1387,7 @@
 	int i;
 
 	if (slip_ctrls != NULL) {
-		unsigned long start = jiffies;
+		unsigned long timeout = jiffies + HZ;
 		int busy = 0;
 
 		/* First of all: check for active disciplines and hangup them.
@@ -1410,7 +1410,7 @@
 				spin_unlock(&slc->ctrl.lock);
 			}
 			local_bh_enable();
-		} while (busy && jiffies - start < 1*HZ);
+		} while (busy && time_before(jiffies, timeout));
 
 		busy = 0;
 		for (i = 0; i < slip_maxdev; i++) {
diff -Nru a/drivers/net/starfire.c b/drivers/net/starfire.c
--- a/drivers/net/starfire.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/starfire.c	Sun Feb 10 19:58:05 2002
@@ -93,13 +93,16 @@
 	- Fixed initialization timing problems
 	- Fixed interrupt mask definitions
 
+	LK1.3.5 (jgarzik)
+	- ethtool NWAY_RST, GLINK, [GS]MSGLVL support
+
 TODO:
 	- implement tx_timeout() properly
 */
 
 #define DRV_NAME	"starfire"
-#define DRV_VERSION	"1.03+LK1.3.4"
-#define DRV_RELDATE	"August 14, 2001"
+#define DRV_VERSION	"1.03+LK1.3.5"
+#define DRV_RELDATE	"November 17, 2001"
 
 #include <linux/version.h>
 #include <linux/module.h>
@@ -1767,6 +1770,47 @@
 		return 0;
 	}
 
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		int tmp;
+		int r = -EINVAL;
+		/* if autoneg is off, it's an error */
+		tmp = mdio_read(dev, np->phys[0], MII_BMCR);
+		if (tmp & BMCR_ANENABLE) {
+			tmp |= (BMCR_ANRESTART);
+			mdio_write(dev, np->phys[0], MII_BMCR, tmp);
+			r = 0;
+		}
+		return r;
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		if (mdio_read(dev, np->phys[0], MII_BMSR) & BMSR_LSTATUS)
+			edata.data = 1;
+		else
+			edata.data = 0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -1784,17 +1828,14 @@
 
 	/* Legacy mii-diag interface */
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (data->phy_id == np->phys[0]) {
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/sundance.c	Sun Feb 10 19:58:04 2002
@@ -21,11 +21,15 @@
 	Version 1.01a (jgarzik):
 	- Replace some MII-related magic numbers with constants
 
+	Version 1.02 (D-Link):
+	- Add new board to PCI ID list
+	- Fix multicast bug
+
 */
 
 #define DRV_NAME	"sundance"
-#define DRV_VERSION	"1.01a"
-#define DRV_RELDATE	"11-Nov-2001"
+#define DRV_VERSION	"1.02"
+#define DRV_RELDATE	"17-Jan-2002"
 
 
 /* The user-configurable values.
@@ -223,8 +227,9 @@
 	{0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0},
 	{0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1},
 	{0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2},
-	{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
-	{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3},
+	{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
@@ -247,6 +252,8 @@
 	 PCI_IOTYPE, 128, CanHaveMII},
 	{"D-Link DFE-580TX 4 port Server Adapter", {0x10121186, 0xffffffff,},
 	 PCI_IOTYPE, 128, CanHaveMII},
+	{"D-Link DFE-530TXS FAST Ethernet Adapter", {0x10021186, 0xffffffff,},
+	 PCI_IOTYPE, 128, CanHaveMII},
 	{"D-Link DL10050-based FAST Ethernet Adapter",
 	 {0x10021186, 0xffffffff,},
 	 PCI_IOTYPE, 128, CanHaveMII},
@@ -1287,11 +1294,16 @@
 		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
 	} else if (dev->mc_count) {
 		struct dev_mc_list *mclist;
-		memset(mc_filter, 0, sizeof(mc_filter));
+		int bit;
+		int index;
+		int crc;
+		memset (mc_filter, 0, sizeof (mc_filter));
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-			 i++, mclist = mclist->next) {
-			set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
-					mc_filter);
+		     i++, mclist = mclist->next) {
+			crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
+			for (index=0, bit=0; bit < 6; bit++, crc <<= 1)
+				if (crc & 0x80000000) index |= 1 << bit;
+			mc_filter[index/16] |= (1 << (index % 16));
 		}
 		rx_mode = AcceptBroadcast | AcceptMultiHash | AcceptMyPhys;
 	} else {
@@ -1335,17 +1347,14 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
diff -Nru a/drivers/net/tlan.c b/drivers/net/tlan.c
--- a/drivers/net/tlan.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/tlan.c	Sun Feb 10 19:58:04 2002
@@ -160,6 +160,7 @@
  *
  *******************************************************************************/
 
+#error Please convert me to Documentation/DMA-mapping.txt
                                                                                 
 #include <linux/module.h>
 
@@ -922,18 +923,15 @@
 
 	switch(cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 			data->phy_id = phy;
 
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 			TLan_MiiReadReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, &data->val_out);
 			return 0;
 		
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
 			TLan_MiiWriteReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
diff -Nru a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c
--- a/drivers/net/tulip/21142.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/tulip/21142.c	Sun Feb 10 19:58:05 2002
@@ -39,8 +39,13 @@
 		printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n",
 			   dev->name, csr12, medianame[dev->if_port]);
 	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
-		tulip_check_duplex(dev);
-		next_tick = 60*HZ;
+		if (tulip_check_duplex(dev) < 0) {
+			netif_carrier_off(dev);
+			next_tick = 3*HZ;
+		} else {
+			netif_carrier_on(dev);
+			next_tick = 60*HZ;
+		}
 	} else if (tp->nwayset) {
 		/* Don't screw up a negotiated session! */
 		if (tulip_debug > 1)
diff -Nru a/drivers/net/tulip/ChangeLog b/drivers/net/tulip/ChangeLog
--- a/drivers/net/tulip/ChangeLog	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/tulip/ChangeLog	Sun Feb 10 19:58:04 2002
@@ -1,3 +1,30 @@
+2002-01-28  Stefan Rompf  <srompf@isg.de>,
+            Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+        * 21142.c (t21142_timer):  Use return value of
+        tulip_check_duplex() to indicate to system whether or not
+        carrier is present.  Use carrier presence/absence to determine
+        when next the 21142 media timer should check for link beat.
+
+        * timer (tulip_timer):  Un-comment-out calls to
+        netif_carrier_{on,off}, as there is now value in
+        reporting link beta information to userspace.
+
+2002-01-28  Pavel Roskin  <proski@gnu.org>
+
+	* tulip_core.c (tulip_init_one): Use tp->eeprom instead of
+	allocating a buffer for EEPROM copy on the stack.
+
+	* tulip_core.c: Add support for Conexant RS7112 (a.k.a. CN7112)
+	chip.
+	* tulip.h: Likewise.  Increase EEPROM_SIZE to 512 bytes to
+	accomodate EEPROM on Conexant RS7112.
+
+2002-02-07  Uwe Bonnes  <bon@elektron.ikp.physik.tu-darmstadt.de>
+
+        * tulip_core (tulip_pci_tbl[]):
+        Add PCI id for comet tulip clone.
+
 2001-12-11  Jeff Garzik  <jgarzik@mandrakesoft.com>
 
 	* eeprom.c, timer.c, media.c, tulip_core.c:
diff -Nru a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c
--- a/drivers/net/tulip/timer.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/net/tulip/timer.c	Sun Feb 10 19:58:03 2002
@@ -83,10 +83,10 @@
 					       medianame[mleaf->media & MEDIA_MASK]);
 				if ((p[2] & 0x61) == 0x01)	/* Bogus Znyx board. */
 					goto actually_mii;
-				/* netif_carrier_on(dev); */
+				netif_carrier_on(dev);
 				break;
 			}
-			/* netif_carrier_off(dev); */
+			netif_carrier_off(dev);
 			if (tp->medialock)
 				break;
 	  select_next_media:
@@ -110,11 +110,13 @@
 		}
 		case 1:  case 3:		/* 21140, 21142 MII */
 		actually_mii:
-			if (tulip_check_duplex(dev) < 0)
-				{ /* netif_carrier_off(dev); */ }
-			else
-				{ /* netif_carrier_on(dev); */ }
-			next_tick = 60*HZ;
+			if (tulip_check_duplex(dev) < 0) {
+				netif_carrier_off(dev);
+				next_tick = 3*HZ;
+			} else {
+				netif_carrier_on(dev);
+				next_tick = 60*HZ;
+			}
 			break;
 		case 2:					/* 21142 serial block has no link beat. */
 		default:
diff -Nru a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
--- a/drivers/net/tulip/tulip.h	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/tulip/tulip.h	Sun Feb 10 19:58:05 2002
@@ -84,6 +84,7 @@
 	COMPEX9881,
 	I21145,
 	DM910X,
+	CONEXANT,
 };
 
 
@@ -290,7 +291,7 @@
 #define DESC_RING_WRAP 0x02000000
 
 
-#define EEPROM_SIZE 128 	/* 2 << EEPROM_ADDRLEN */
+#define EEPROM_SIZE 512 	/* 2 << EEPROM_ADDRLEN */
 
 
 #define RUN_AT(x) (jiffies + (x))
diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
--- a/drivers/net/tulip/tulip_core.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/tulip/tulip_core.c	Sun Feb 10 19:58:04 2002
@@ -15,8 +15,8 @@
 */
 
 #define DRV_NAME	"tulip"
-#define DRV_VERSION	"1.1.0"
-#define DRV_RELDATE	"Dec 11, 2001"
+#define DRV_VERSION	"1.1.11"
+#define DRV_RELDATE	"Feb 08, 2002"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -185,6 +185,10 @@
   { "Davicom DM9102/DM9102A", 128, 0x0001ebef,
 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
 	tulip_timer },
+
+  /* RS7112 */
+  { "Conexant LANfinity", 256, 0x0001ebef,
+	HAS_MII | HAS_ACPI, tulip_timer },
 };
 
 
@@ -202,6 +206,7 @@
 	{ 0x1317, 0x1985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x13D1, 0xAB02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x13D1, 0xAB03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+	{ 0x13D1, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x104A, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x104A, 0x2774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
@@ -211,6 +216,7 @@
 	{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
 	{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+	{ 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
 	{ } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
@@ -417,7 +423,7 @@
 		tp->csr6 = 0x01a80200;
 		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
 		outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
-	} else if (tp->chip_id == COMET) {
+	} else if (tp->chip_id == COMET || tp->chip_id == CONEXANT) {
 		/* Enable automatic Tx underrun recovery. */
 		outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
 		dev->if_port = tp->mii_cnt ? 11 : 0;
@@ -1253,7 +1259,7 @@
 	u8 chip_rev;
 	int i, irq;
 	unsigned short sum;
-	u8 ee_data[EEPROM_SIZE];
+	unsigned char *ee_data;
 	struct net_device *dev;
 	long ioaddr;
 	static int board_idx = -1;
@@ -1430,6 +1436,7 @@
 	   be polled, waiting for the value to be read bit serially from the
 	   EEPROM.
 	   */
+	ee_data = tp->eeprom;
 	sum = 0;
 	if (chip_idx == LC82C168) {
 		for (i = 0; i < 3; i++) {
@@ -1452,17 +1459,22 @@
 		int sa_offset = 0;
 		int ee_addr_size = tulip_read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
 
-		for (i = 0; i < sizeof(ee_data)/2; i++)
+		for (i = 0; i < sizeof(tp->eeprom)/2; i++)
 			((u16 *)ee_data)[i] =
 				le16_to_cpu(tulip_read_eeprom(ioaddr, i, ee_addr_size));
 
 		/* DEC now has a specification (see Notes) but early board makers
 		   just put the address in the first EEPROM locations. */
-		/* This does  memcmp(eedata, eedata+16, 8) */
+		/* This does  memcmp(ee_data, ee_data+16, 8) */
 		for (i = 0; i < 8; i ++)
 			if (ee_data[i] != ee_data[16+i])
 				sa_offset = 20;
-		if (ee_data[0] == 0xff  &&  ee_data[1] == 0xff &&  ee_data[2] == 0) {
+		if (chip_idx == CONEXANT) {
+			/* Check that the tuple type and length is correct. */
+			if (ee_data[0x198] == 0x04  &&  ee_data[0x199] == 6)
+				sa_offset = 0x19A;
+		} else if (ee_data[0] == 0xff  &&  ee_data[1] == 0xff &&
+				   ee_data[2] == 0) {
 			sa_offset = 2;		/* Grrr, damn Matrox boards. */
 			multiport_cnt = 4;
 		}
@@ -1555,8 +1567,6 @@
 	}
 
 	if (tp->flags & HAS_MEDIA_TABLE) {
-		memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
-
 		sprintf(dev->name, "tulip%d", board_idx);	/* hack */
 		tulip_parse_eeprom(dev);
 		strcpy(dev->name, "eth%d");			/* un-hack */
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/via-rhine.c	Sun Feb 10 19:58:06 2002
@@ -76,8 +76,17 @@
 
 	LK1.1.12:
 	- Martin Eriksson: Allow Memory-Mapped IO to be enabled.
+
+	LK1.1.13 (jgarzik):
+	- Add ethtool support
+	- Replace some MII-related magic numbers with constants
+	
 */
 
+#define DRV_NAME	"via-rhine"
+#define DRV_VERSION	"1.1.13"
+#define DRV_RELDATE	"Nov-17-2001"
+
 
 /* A few user-configurable values.
    These may be modified when a driver module is loaded. */
@@ -151,18 +160,20 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "via-rhine.c:v1.10-LK1.1.12  03/11/2001  Written by Donald Becker\n"
+KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION "  " DRV_RELDATE "  Written by Donald Becker\n"
 KERN_INFO "  http://www.scyld.com/network/via-rhine.html\n";
 
-static char shortname[] __devinitdata = "via-rhine";
+static char shortname[] __devinitdata = DRV_NAME;
 
 
 /* This driver was written to use PCI memory space, however most versions
@@ -471,6 +482,7 @@
 	unsigned char phys[MAX_MII_CNT];			/* MII device addresses. */
 	unsigned int mii_cnt;			/* number of MIIs found, but only the first one is used */
 	u16 mii_status;						/* last read MII status */
+	struct mii_if_info mii_if;
 };
 
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
@@ -486,7 +498,7 @@
 static void via_rhine_error(struct net_device *dev, int intr_status);
 static void via_rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  via_rhine_close(struct net_device *dev);
 static inline void clear_tally_counters(long ioaddr);
 
@@ -684,6 +696,9 @@
 	np->chip_id = chip_id;
 	np->drv_flags = via_rhine_chip_info[chip_id].drv_flags;
 	np->pdev = pdev;
+	np->mii_if.dev = dev;
+	np->mii_if.mdio_read = mdio_read;
+	np->mii_if.mdio_write = mdio_write;
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -691,16 +706,16 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		np->default_port = option & 15;
 	}
 	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 
-	if (np->full_duplex) {
+	if (np->mii_if.full_duplex) {
 		printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
 			   " disabled.\n", dev->name);
-		np->duplex_lock = 1;
+		np->mii_if.duplex_lock = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -709,7 +724,7 @@
 	dev->stop = via_rhine_close;
 	dev->get_stats = via_rhine_get_stats;
 	dev->set_multicast_list = via_rhine_set_rx_mode;
-	dev->do_ioctl = mii_ioctl;
+	dev->do_ioctl = via_rhine_ioctl;
 	dev->tx_timeout = via_rhine_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (np->drv_flags & ReqTxAlign)
@@ -736,10 +751,10 @@
 			int mii_status = mdio_read(dev, phy, 1);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				np->phys[phy_idx++] = phy;
-				np->advertising = mdio_read(dev, phy, 4);
+				np->mii_if.advertising = mdio_read(dev, phy, 4);
 				printk(KERN_INFO "%s: MII PHY found at address %d, status "
 					   "0x%4.4x advertising %4.4x Link %4.4x.\n",
-					   dev->name, phy, mii_status, np->advertising,
+					   dev->name, phy, mii_status, np->mii_if.advertising,
 					   mdio_read(dev, phy, 5));
 
 				/* set IFF_RUNNING */
@@ -750,12 +765,13 @@
 			}
 		}
 		np->mii_cnt = phy_idx;
+		np->mii_if.phy_id = np->phys[0];
 	}
 
 	/* Allow forcing the media type. */
 	if (option > 0) {
 		if (option & 0x220)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		np->default_port = option & 0x3ff;
 		if (np->default_port & 0x330) {
 			/* FIXME: shouldn't someone check this variable? */
@@ -969,7 +985,7 @@
 		   ioaddr + IntrEnable);
 
 	np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
-	if (np->duplex_lock)
+	if (np->mii_if.duplex_lock)
 		np->chip_cmd |= CmdFDuplex;
 	writew(np->chip_cmd, ioaddr + ChipCmd);
 
@@ -1011,12 +1027,12 @@
 		switch (regnum) {
 		case 0:							/* Is user forcing speed/duplex? */
 			if (value & 0x9000)			/* Autonegotiation. */
-				np->duplex_lock = 0;
+				np->mii_if.duplex_lock = 0;
 			else
-				np->full_duplex = (value & 0x0100) ? 1 : 0;
+				np->mii_if.full_duplex = (value & 0x0100) ? 1 : 0;
 			break;
 		case 4:
-			np->advertising = value;
+			np->mii_if.advertising = value;
 			break;
 		}
 	}
@@ -1060,7 +1076,7 @@
 		printk(KERN_DEBUG "%s: Done via_rhine_open(), status %4.4x "
 			   "MII status: %4.4x.\n",
 			   dev->name, readw(ioaddr + ChipCmd),
-			   mdio_read(dev, np->phys[0], 1));
+			   mdio_read(dev, np->phys[0], MII_BMSR));
 
 	netif_start_queue(dev);
 
@@ -1078,19 +1094,19 @@
 {
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
-	int mii_reg5 = mdio_read(dev, np->phys[0], 5);
-	int negotiated = mii_reg5 & np->advertising;
+	int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
+	int negotiated = mii_lpa & np->mii_if.advertising;
 	int duplex;
 
-	if (np->duplex_lock  ||  mii_reg5 == 0xffff)
+	if (np->mii_if.duplex_lock  ||  mii_lpa == 0xffff)
 		return;
 	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
-	if (np->full_duplex != duplex) {
-		np->full_duplex = duplex;
+	if (np->mii_if.full_duplex != duplex) {
+		np->mii_if.full_duplex = duplex;
 		if (debug)
 			printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
 				   " partner capability of %4.4x.\n", dev->name,
-				   duplex ? "full" : "half", np->phys[0], mii_reg5);
+				   duplex ? "full" : "half", np->phys[0], mii_lpa);
 		if (duplex)
 			np->chip_cmd |= CmdFDuplex;
 		else
@@ -1118,7 +1134,7 @@
 	via_rhine_check_duplex(dev);
 
 	/* make IFF_RUNNING follow the MII status bit "Link established" */
-	mii_status = mdio_read(dev, np->phys[0], 1);
+	mii_status = mdio_read(dev, np->phys[0], MII_BMSR);
 	if ( (mii_status & MIILink) != (np->mii_status & MIILink) ) {
 		if (mii_status & MIILink)
 			netif_carrier_on(dev);
@@ -1142,7 +1158,7 @@
 	printk (KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
 		"%4.4x, resetting...\n",
 		dev->name, readw (ioaddr + IntrStatus),
-		mdio_read (dev, np->phys[0], 1));
+		mdio_read (dev, np->phys[0], MII_BMSR));
 
 	dev->if_port = 0;
 
@@ -1457,14 +1473,14 @@
 		if (readb(ioaddr + MIIStatus) & 0x02) {
 			/* Link failed, restart autonegotiation. */
 			if (np->drv_flags & HasDavicomPhy)
-				mdio_write(dev, np->phys[0], 0, 0x3300);
+				mdio_write(dev, np->phys[0], MII_BMCR, 0x3300);
 		} else
 			via_rhine_check_duplex(dev);
 		if (debug)
 			printk(KERN_ERR "%s: MII status changed: Autonegotiation "
 				   "advertising %4.4x  partner %4.4x.\n", dev->name,
-			   mdio_read(dev, np->phys[0], 4),
-			   mdio_read(dev, np->phys[0], 5));
+			   mdio_read(dev, np->phys[0], MII_ADVERTISE),
+			   mdio_read(dev, np->phys[0], MII_LPA));
 	}
 	if (intr_status & IntrStatsMax) {
 		np->stats.rx_crc_errors	+= readw(ioaddr + RxCRCErrs);
@@ -1554,29 +1570,112 @@
 	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
 
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	struct netdev_private *np = dev->priv;
+	u32 ethcmd;
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pdev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		return mii_nway_restart(&np->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		edata.data = mii_link_ok(&np->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdev_private *np = dev->priv;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	unsigned long flags;
 	int retval;
 
+	if (cmd == SIOCETHTOOL)
+		return via_rhine_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
 	spin_lock_irqsave(&np->lock, flags);
 	retval = 0;
 
 	switch(cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		break;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN)) {
 			retval = -EPERM;
 			break;
diff -Nru a/drivers/net/wan/comx.c b/drivers/net/wan/comx.c
--- a/drivers/net/wan/comx.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/net/wan/comx.c	Sun Feb 10 19:58:06 2002
@@ -876,7 +876,7 @@
 
 static int comx_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	struct proc_dir_entry *entry = dentry->d_inode->u.generic_ip;
+	struct proc_dir_entry *entry = PDE(dentry->d_inode);
 	struct net_device *dev = entry->data;
 	struct comx_channel *ch = dev->priv;
 	int ret;
@@ -928,7 +928,7 @@
 	struct proc_dir_entry *de;
 	struct inode *inode = NULL;
 
-	if ((de = (struct proc_dir_entry *) dir->u.generic_ip) != NULL) {
+	if ((de = PDE(dir)) != NULL) {
 		for (de = de->subdir ; de ; de = de->next) {
 			if ((de && de->low_ino) && 
 			    (de->namelen == dentry->d_name.len) &&
diff -Nru a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
--- a/drivers/net/wan/lmc/lmc_main.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/wan/lmc/lmc_main.c	Sun Feb 10 19:58:05 2002
@@ -175,7 +175,7 @@
 
     case LMCIOCSINFO: /*fold01*/
         sp = &((struct ppp_device *) dev)->sppp;
-        if (!suser ()) {
+        if (!capable(CAP_NET_ADMIN)) {
             ret = -EPERM;
             break;
         }
@@ -210,7 +210,7 @@
             u_int16_t	old_type = sc->if_type;
             u_int16_t	new_type;
 
-	    if (!suser ()) {
+	    if (!capable(CAP_NET_ADMIN)) {
 		ret = -EPERM;
 		break;
 	    }
@@ -290,7 +290,7 @@
         break;
 
     case LMCIOCCLEARLMCSTATS: /*fold01*/
-        if (!suser ()){
+        if (!capable(CAP_NET_ADMIN)){
             ret = -EPERM;
             break;
         }
@@ -304,7 +304,7 @@
         break;
 
     case LMCIOCSETCIRCUIT: /*fold01*/
-        if (!suser ()){
+        if (!capable(CAP_NET_ADMIN)){
             ret = -EPERM;
             break;
         }
@@ -322,7 +322,7 @@
         break;
 
     case LMCIOCRESET: /*fold01*/
-        if (!suser ()){
+        if (!capable(CAP_NET_ADMIN)){
             ret = -EPERM;
             break;
         }
@@ -355,7 +355,7 @@
         {
             struct lmc_xilinx_control xc; /*fold02*/
 
-            if (!suser ()){
+            if (!capable(CAP_NET_ADMIN)){
                 ret = -EPERM;
                 break;
             }
diff -Nru a/drivers/net/winbond-840.c b/drivers/net/winbond-840.c
--- a/drivers/net/winbond-840.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/winbond-840.c	Sun Feb 10 19:58:05 2002
@@ -36,6 +36,8 @@
 		power management.
 		support for big endian descriptors
 			Copyright (C) 2001 Manfred Spraul
+  	* ethtool support (jgarzik)
+	* Replace some MII-related magic numbers with constants (jgarzik)
   
 	TODO:
 	* enable pci_power_off
@@ -43,8 +45,8 @@
 */
   
 #define DRV_NAME	"winbond-840"
-#define DRV_VERSION	"1.01-c"
-#define DRV_RELDATE	"6/30/2000"
+#define DRV_VERSION	"1.01-d"
+#define DRV_RELDATE	"Nov-17-2001"
 
 
 /* Automatically extracted configuration info:
@@ -345,7 +347,7 @@
 	struct w840_rx_desc *rx_ring;
 	dma_addr_t	rx_addr[RX_RING_SIZE];
 	struct w840_tx_desc *tx_ring;
-	dma_addr_t	tx_addr[RX_RING_SIZE];
+	dma_addr_t	tx_addr[TX_RING_SIZE];
 	dma_addr_t ring_dma_addr;
 	/* The addresses of receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
@@ -364,14 +366,11 @@
 	unsigned int cur_tx, dirty_tx;
 	unsigned int tx_q_bytes;
 	unsigned int tx_full;				/* The Tx queue is full. */
-	/* These values are keep track of the transceiver/media in use. */
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
 	/* MII transceiver section. */
 	int mii_cnt;						/* MII device addresses. */
-	u16 advertising;					/* NWay media advertisement */
 	unsigned char phys[MII_CNT];		/* MII device addresses, but only the first is used */
 	u32 mii;
+	struct mii_if_info mii_if;
 };
 
 static int  eeprom_read(long ioaddr, int location);
@@ -453,6 +452,9 @@
 	np->chip_id = chip_idx;
 	np->drv_flags = pci_id_tbl[chip_idx].drv_flags;
 	spin_lock_init(&np->lock);
+	np->mii_if.dev = dev;
+	np->mii_if.mdio_read = mdio_read;
+	np->mii_if.mdio_write = mdio_write;
 	
 	pci_set_drvdata(pdev, dev);
 
@@ -462,16 +464,16 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		if (option & 15)
 			printk(KERN_INFO "%s: ignoring user supplied media type %d",
 				dev->name, option & 15);
 	}
 	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 
-	if (np->full_duplex)
-		np->duplex_lock = 1;
+	if (np->mii_if.full_duplex)
+		np->mii_if.duplex_lock = 1;
 
 	/* The chip-specific entries in the device structure. */
 	dev->open = &netdev_open;
@@ -496,18 +498,19 @@
 	if (np->drv_flags & CanHaveMII) {
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
+			int mii_status = mdio_read(dev, phy, MII_BMSR);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				np->phys[phy_idx++] = phy;
-				np->advertising = mdio_read(dev, phy, 4);
-				np->mii = (mdio_read(dev, phy, 2) << 16)+
-						mdio_read(dev, phy, 3);
+				np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
+				np->mii = (mdio_read(dev, phy, MII_PHYSID1) << 16)+
+						mdio_read(dev, phy, MII_PHYSID2);
 				printk(KERN_INFO "%s: MII PHY %8.8xh found at address %d, status "
 					   "0x%4.4x advertising %4.4x.\n",
-					   dev->name, np->mii, phy, mii_status, np->advertising);
+					   dev->name, np->mii, phy, mii_status, np->mii_if.advertising);
 			}
 		}
 		np->mii_cnt = phy_idx;
+		np->mii_if.phy_id = np->phys[0];
 		if (phy_idx == 0) {
 				printk(KERN_WARNING "%s: MII PHY not found -- this device may "
 					   "not operate correctly.\n", dev->name);
@@ -654,7 +657,7 @@
 	int i;
 
 	if (location == 4  &&  phy_id == np->phys[0])
-		np->advertising = value;
+		np->mii_if.advertising = value;
 
 	if (mii_preamble_required)
 		mdio_sync(mdio_addr);
@@ -728,12 +731,12 @@
 	int duplex, fasteth, result, mii_reg;
 
 	/* BSMR */
-	mii_reg = mdio_read(dev, np->phys[0], 1);
+	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
 
 	if (mii_reg == 0xffff)
 		return np->csr6;
 	/* reread: the link status bit is sticky */
-	mii_reg = mdio_read(dev, np->phys[0], 1);
+	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
 	if (!(mii_reg & 0x4)) {
 		if (netif_carrier_ok(dev)) {
 			if (debug)
@@ -759,18 +762,18 @@
 		 * Instead bit 9 and 13 of the BMCR are updated to the result
 		 * of the negotiation..
 		 */
-		mii_reg = mdio_read(dev, np->phys[0], 0);
-		duplex = mii_reg & 0x100;
-		fasteth = mii_reg & 0x2000;
+		mii_reg = mdio_read(dev, np->phys[0], MII_BMCR);
+		duplex = mii_reg & BMCR_FULLDPLX;
+		fasteth = mii_reg & BMCR_SPEED100;
 	} else {
 		int negotiated;
-		mii_reg	= mdio_read(dev, np->phys[0], 5);
-		negotiated = mii_reg & np->advertising;
+		mii_reg	= mdio_read(dev, np->phys[0], MII_LPA);
+		negotiated = mii_reg & np->mii_if.advertising;
 
-		duplex = (negotiated & 0x0100) || ((negotiated & 0x02C0) == 0x0040);
+		duplex = (negotiated & LPA_100FULL) || ((negotiated & 0x02C0) == LPA_10FULL);
 		fasteth = negotiated & 0x380;
 	}
-	duplex |= np->duplex_lock;
+	duplex |= np->mii_if.duplex_lock;
 	/* remove fastether and fullduplex */
 	result = np->csr6 & ~0x20000200;
 	if (duplex)
@@ -822,7 +825,7 @@
 	/* and restart them with the new configuration */
 	writel(np->csr6, ioaddr + NetworkConfig);
 	if (new & 0x200)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 }
 
 static void netdev_timer(unsigned long data)
@@ -1131,7 +1134,7 @@
 			if (tx_status & 0x0C80) np->stats.tx_carrier_errors++;
 			if (tx_status & 0x0200) np->stats.tx_window_errors++;
 			if (tx_status & 0x0002) np->stats.tx_fifo_errors++;
-			if ((tx_status & 0x0080) && np->full_duplex == 0)
+			if ((tx_status & 0x0080) && np->mii_if.full_duplex == 0)
 				np->stats.tx_heartbeat_errors++;
 #ifdef ETHER_STATS
 			if (tx_status & 0x0100) np->stats.collisions16++;
@@ -1469,6 +1472,56 @@
 		return 0;
 	}
 
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
         }
 	
 	return -EOPNOTSUPP;
@@ -1483,19 +1536,16 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		spin_lock_irq(&np->lock);
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		spin_unlock_irq(&np->lock);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		spin_lock_irq(&np->lock);
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/net/wireless/airo.c	Sun Feb 10 19:58:04 2002
@@ -2280,7 +2280,7 @@
 
 static int proc_status_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *apriv = (struct airo_info *)dev->priv;
 	CapabilityRid cap_rid;
@@ -2289,8 +2289,6 @@
 
 	MOD_INC_USE_COUNT;
 
-	dp = inode->u.generic_ip;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -2364,7 +2362,7 @@
 				struct file *file,
 				u16 rid ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *apriv = (struct airo_info *)dev->priv;
 	StatsRid stats;
@@ -2372,9 +2370,6 @@
 	int *vals = stats.vals;
 	MOD_INC_USE_COUNT;
 
-
-	dp = inode->u.generic_ip;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -2433,7 +2428,7 @@
 
 static void proc_config_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data = file->private_data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	ConfigRid config;
@@ -2442,7 +2437,6 @@
 	int need_reset = 0;
 
 	if ( !data->writelen ) return;
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
 
 	disable_MAC(ai);
 	readConfigRid(ai, &config);
@@ -2629,7 +2623,7 @@
 
 static int proc_config_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	ConfigRid config;
@@ -2637,8 +2631,6 @@
 
 	MOD_INC_USE_COUNT;
 
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -2723,7 +2715,7 @@
 
 static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data = (struct proc_data *)file->private_data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	SsidRid SSID_rid;
@@ -2759,7 +2751,7 @@
 
 static void proc_APList_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data = (struct proc_data *)file->private_data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	APListRid APList_rid;
@@ -2852,7 +2844,7 @@
 
 static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	int i;
@@ -2862,7 +2854,6 @@
 
 	memset(key, 0, sizeof(key));
 
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
 	data = (struct proc_data *)file->private_data;
 	if ( !data->writelen ) return;
 
@@ -2894,7 +2885,7 @@
 
 static int proc_wepkey_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	char *ptr;
@@ -2905,8 +2896,6 @@
 
 	MOD_INC_USE_COUNT;
 
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -2948,7 +2937,7 @@
 
 static int proc_SSID_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	int i;
@@ -2957,8 +2946,6 @@
 
 	MOD_INC_USE_COUNT;
 
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -2996,7 +2983,7 @@
 
 static int proc_APList_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	int i;
@@ -3005,8 +2992,6 @@
 
 	MOD_INC_USE_COUNT;
 
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3048,7 +3033,7 @@
 
 static int proc_BSSList_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 	char *ptr;
@@ -3058,8 +3043,6 @@
 	int doLoseSync = -1;
 
 	MOD_INC_USE_COUNT;
-
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
 
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
--- a/drivers/net/yellowfin.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/net/yellowfin.c	Sun Feb 10 19:58:05 2002
@@ -1420,17 +1420,14 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (data->phy_id == np->phys[0]) {
diff -Nru a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
--- a/drivers/parport/ChangeLog	Sun Feb 10 19:58:04 2002
+++ b/drivers/parport/ChangeLog	Sun Feb 10 19:58:04 2002
@@ -1,3 +1,61 @@
+2002-01-21  Tim Waugh  <twaugh@redhat.com>
+
+	* daisy.c: Apply patch from Max Vorobiev to make parport_daisy_select
+	work for ECP/EPP modes.
+
+2002-01-04  Tim Waugh  <twaugh@redhat.com>
+
+	* share.c (parport_claim_or_block): Sleep interruptibly to prevent
+	a possible deadlock.
+
+2002-01-13  Niels Kristian Bech Jensen  <nkbj@image.dk>
+
+	* parport_pc.c: Change some occurrences of frob_set_mode to
+	ECR_WRITE.  This fixes PLIP.
+
+2001-10-25  Damian Gruszka  <damian.gruszka@VisionSystems.de>
+
+	* parport_pc.c (ECR_WRITE): Define.  If there are forbidden bits
+	in the ECR register for some chips, this will be a useful place to
+	put that knowledge.
+	(change_mode): Use ECR_WRITE.
+	(parport_pc_restore_state): Likewise.
+	(parport_ECPPS2_supported): Likewise.
+	(parport_ECPEPP_supported): Likewise.
+	(irq_probe_EPP): Likewise.
+	(programmable_irq_support): Likewise.
+	(programmable_dma_support): Likewise.
+	(parport_pc_probe_port): Likewise.
+
+	(frob_set_mode): New function.  Set the mode bits of the ECR.
+	(get_fifo_residue): Use frob_set_mode.
+	(parport_pc_ecpepp_read_data): Likewise.
+	(parport_pc_ecpepp_write_data): Likewise.
+	(parport_pc_ecpepp_read_addr): Likewise.
+	(parport_pc_ecpepp_write_addr): Likewise.
+	(parport_pc_compat_write_block_pio): Likewise.
+	(parport_pc_ecp_write_block_pio): Likewise.
+	(parport_ECR_present): Likewise.
+	(parport_ECP_supported): Likewise.
+	(parport_EPP_supported): Likewise.
+	(parport_ECPEPP_supported): Likewise.
+	(programmable_irq_support): Likewise.
+	(irq_probe_ECP): Likewise.
+	(programmable_dma_support): Likewise.
+
+	(parport_pc_enable_irq): Only enable interrupts if we know which
+	IRQ line they will come from.
+	(parport_pc_init_state): Set nErrIntrEn at initialisation.
+	(parport_pc_restore_state): Only write writable bits of CTR.
+	(parport_irq_probe): If no IRQ is found, take ackIntEn out of the
+	writable bit set.
+
+2001-10-25  Tim Waugh  <twaugh@redhat.com>
+
+	* parport_pc.c (parport_pc_fifo_write_block_pio): Correct typo.
+	(parport_pc_init_state): Only set ackIntEn if we know which IRQ
+	line the interrupts will come from.
+
 2001-12-07  Tim Waugh  <twaugh@redhat.com>
 
 	* ieee1284_ops.c (parport_ieee1284_epp_write_addr,
diff -Nru a/drivers/parport/daisy.c b/drivers/parport/daisy.c
--- a/drivers/parport/daisy.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/parport/daisy.c	Sun Feb 10 19:58:05 2002
@@ -406,8 +406,33 @@
 
 int parport_daisy_select (struct parport *port, int daisy, int mode)
 {
-	/* mode is currently ignored. FIXME? */
-	return cpp_daisy (port, 0xe0 + daisy) & PARPORT_STATUS_ERROR;
+	switch (mode)
+	{
+		// For these modes we should switch to EPP mode:
+		case IEEE1284_MODE_EPP:
+		case IEEE1284_MODE_EPPSL:
+		case IEEE1284_MODE_EPPSWE:
+			return (cpp_daisy (port, 0x20 + daisy) &
+				PARPORT_STATUS_ERROR);
+
+		// For these modes we should switch to ECP mode:
+		case IEEE1284_MODE_ECP:
+		case IEEE1284_MODE_ECPRLE:
+		case IEEE1284_MODE_ECPSWE: 
+			return (cpp_daisy (port, 0xd0 + daisy) &
+				PARPORT_STATUS_ERROR);
+
+		// Nothing was told for BECP in Daisy chain specification.
+		// May be it's wise to use ECP?
+		case IEEE1284_MODE_BECP:
+		// Others use compat mode
+		case IEEE1284_MODE_NIBBLE:
+		case IEEE1284_MODE_BYTE:
+		case IEEE1284_MODE_COMPAT:
+		default:
+			return (cpp_daisy (port, 0xe0 + daisy) &
+				PARPORT_STATUS_ERROR);
+	}
 }
 
 static int mux_present (struct parport *port)
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/parport/parport_pc.c	Sun Feb 10 19:58:06 2002
@@ -73,6 +73,8 @@
 #define ECR_VND 05
 #define ECR_TST 06
 #define ECR_CNF 07
+#define ECR_MODE_MASK 0xe0
+#define ECR_WRITE(p,v) frob_econtrol((p),0xff,(v))
 
 #undef DEBUG
 
@@ -100,13 +102,22 @@
 static void frob_econtrol (struct parport *pb, unsigned char m,
 			   unsigned char v)
 {
-	unsigned char ectr = inb (ECONTROL (pb));
+	unsigned char ectr = 0;
+
+	if (m != 0xff)
+		ectr = inb (ECONTROL (pb));
+
 	DPRINTK (KERN_DEBUG "frob_econtrol(%02x,%02x): %02x -> %02x\n",
 		m, v, ectr, (ectr & ~m) ^ v);
 
 	outb ((ectr & ~m) ^ v, ECONTROL (pb));
 }
 
+static void __inline__ frob_set_mode (struct parport *p, int mode)
+{
+	frob_econtrol (p, ECR_MODE_MASK, mode << 5);
+}
+
 #ifdef CONFIG_PARPORT_PC_FIFO
 /* Safely change the mode bits in the ECR 
    Returns:
@@ -117,7 +128,6 @@
 static int change_mode(struct parport *p, int m)
 {
 	const struct parport_pc_private *priv = p->physport->private_data;
-	int ecr = ECONTROL(p);
 	unsigned char oecr;
 	int mode;
 
@@ -129,7 +139,7 @@
 	}
 
 	/* Bits <7:5> contain the mode. */
-	oecr = inb (ecr);
+	oecr = inb (ECONTROL (p));
 	mode = (oecr >> 5) & 0x7;
 	if (mode == m) return 0;
 
@@ -166,13 +176,13 @@
 		/* We have to go through mode 001 */
 		oecr &= ~(7 << 5);
 		oecr |= ECR_PS2 << 5;
-		outb (oecr, ecr);
+		ECR_WRITE (p, oecr);
 	}
 
 	/* Set the mode. */
 	oecr &= ~(7 << 5);
 	oecr |= m << 5;
-	outb (oecr, ecr);
+	ECR_WRITE (p, oecr);
 	return 0;
 }
 
@@ -197,10 +207,10 @@
 		residue);
 
 	/* Reset the FIFO. */
-	frob_econtrol (p, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (p, ECR_PS2);
 
 	/* Now change to config mode and clean up. FIXME */
-	frob_econtrol (p, 0xe0, ECR_CNF << 5);
+	frob_set_mode (p, ECR_CNF);
 	cnfga = inb (CONFIGA (p));
 	printk (KERN_DEBUG "%s: cnfgA contains 0x%02x\n", p->name, cnfga);
 
@@ -213,7 +223,7 @@
 	 * PWord != 1 byte. */
 
 	/* Back to PS2 mode. */
-	frob_econtrol (p, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (p, ECR_PS2);
 
 	DPRINTK (KERN_DEBUG "*** get_fifo_residue: done residue collecting (ecr = 0x%2.2x)\n", inb (ECONTROL (p)));
 	return residue;
@@ -331,7 +341,8 @@
 
 void parport_pc_enable_irq(struct parport *p)
 {
-	__parport_pc_frob_control (p, 0x10, 0x10);
+	if (p->irq != PARPORT_IRQ_NONE)
+		__parport_pc_frob_control (p, 0x10, 0x10);
 }
 
 void parport_pc_data_forward (struct parport *p)
@@ -346,8 +357,14 @@
 
 void parport_pc_init_state(struct pardevice *dev, struct parport_state *s)
 {
-	s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
-	s->u.pc.ecr = 0x24;
+	s->u.pc.ctr = 0xc;
+	if (dev->irq_func &&
+	    dev->port->irq != PARPORT_IRQ_NONE)
+		/* Set ackIntEn */
+		s->u.pc.ctr |= 0x10;
+
+	s->u.pc.ecr = 0x34; /* NetMos chip can cause problems 0x24;
+			     * D.Gruszka VScom */
 }
 
 void parport_pc_save_state(struct parport *p, struct parport_state *s)
@@ -361,10 +378,11 @@
 void parport_pc_restore_state(struct parport *p, struct parport_state *s)
 {
 	struct parport_pc_private *priv = p->physport->private_data;
-	outb (s->u.pc.ctr, CONTROL (p));
-	priv->ctr = s->u.pc.ctr;
+	register unsigned char c = s->u.pc.ctr & priv->ctr_writable;
+	outb (c, CONTROL (p));
+	priv->ctr = c;
 	if (priv->ecr)
-		outb (s->u.pc.ecr, ECONTROL (p));
+		ECR_WRITE (p, s->u.pc.ecr);
 }
 
 #ifdef CONFIG_PARPORT_1284
@@ -516,11 +534,11 @@
 {
 	size_t got;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_data_reverse (port);
 	parport_pc_write_control (port, 0x4);
 	got = parport_pc_epp_read_data (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return got;
 }
@@ -531,11 +549,11 @@
 {
 	size_t written;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_write_control (port, 0x4);
 	parport_pc_data_forward (port);
 	written = parport_pc_epp_write_data (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return written;
 }
@@ -545,11 +563,11 @@
 {
 	size_t got;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_data_reverse (port);
 	parport_pc_write_control (port, 0x4);
 	got = parport_pc_epp_read_addr (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return got;
 }
@@ -560,11 +578,11 @@
 {
 	size_t written;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_write_control (port, 0x4);
 	parport_pc_data_forward (port);
 	written = parport_pc_epp_write_addr (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return written;
 }
@@ -612,7 +630,7 @@
 			/* FIFO is full. Wait for interrupt. */
 
 			/* Clear serviceIntr */
-			outb (ecrval & ~(1<<2), ECONTROL (port));
+			ECR_WRITE (port, ecrval & ~(1<<2));
 		false_alarm:
 			ret = parport_wait_event (port, HZ);
 			if (ret < 0) break;
@@ -663,7 +681,7 @@
 		left--;
         }
 
-dump_parport_state ("leave fifo_write_block_dma", port);
+dump_parport_state ("leave fifo_write_block_pio", port);
 	return length - left;
 }
 
@@ -837,7 +855,7 @@
 		printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
 		/* Prevent further data transfer. */
-		frob_econtrol (port, 0xe0, ECR_TST << 5);
+		frob_set_mode (port, ECR_TST);
 
 		/* Adjust for the contents of the FIFO. */
 		for (written -= priv->fifo_depth; ; written++) {
@@ -849,7 +867,7 @@
 		}
 
 		/* Reset the FIFO and return to PS2 mode. */
-		frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+		frob_set_mode (port, ECR_PS2);
 	}
 
 	r = parport_wait_peripheral (port,
@@ -934,7 +952,7 @@
 		printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
 		/* Prevent further data transfer. */
-		frob_econtrol (port, 0xe0, ECR_TST << 5);
+		frob_set_mode (port, ECR_TST);
 
 		/* Adjust for the contents of the FIFO. */
 		for (written -= priv->fifo_depth; ; written++) {
@@ -946,7 +964,7 @@
 		}
 
 		/* Reset the FIFO and return to PS2 mode. */
-		frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+		frob_set_mode (port, ECR_PS2);
 
 		/* Host transfer recovery. */
 		parport_pc_data_reverse (port); /* Must be in PS2 mode */
@@ -1113,7 +1131,7 @@
 			}
 
 			/* Clear serviceIntr */
-			outb (ecrval & ~(1<<2), ECONTROL (port));
+			ECR_WRITE (port, ecrval & ~(1<<2));
 		false_alarm:
 dump_parport_state ("waiting", port);
 			ret = parport_wait_event (port, HZ);
@@ -1716,7 +1734,7 @@
 	if ((inb (ECONTROL (pb)) & 0x3 ) != 0x1)
 		goto no_reg;
 
-	outb (0x34, ECONTROL (pb));
+	ECR_WRITE (pb, 0x34);
 	if (inb (ECONTROL (pb)) != 0x35)
 		goto no_reg;
 
@@ -1724,7 +1742,7 @@
 	outb (0xc, CONTROL (pb));
 	
 	/* Go to mode 000 */
-	frob_econtrol (pb, 0xe0, ECR_SPP << 5);
+	frob_set_mode (pb, ECR_SPP);
 
 	return 1;
 
@@ -1794,8 +1812,8 @@
 		return 0;
 
 	/* Find out FIFO depth */
-	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-	outb (ECR_TST << 5, ECONTROL (pb)); /* TEST FIFO */
+	ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */
+	ECR_WRITE (pb, ECR_TST << 5); /* TEST FIFO */
 	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++)
 		outb (0xaa, FIFO (pb));
 
@@ -1804,7 +1822,7 @@
 	 * it doesn't support ECP or FIFO MODE
 	 */
 	if (i == 1024) {
-		outb (ECR_SPP << 5, ECONTROL (pb));
+		ECR_WRITE (pb, ECR_SPP << 5);
 		return 0;
 	}
 
@@ -1834,9 +1852,9 @@
 	priv->writeIntrThreshold = i;
 
 	/* Find out readIntrThreshold */
-	frob_econtrol (pb, 0xe0, ECR_PS2 << 5); /* Reset FIFO and enable PS2 */
+	frob_set_mode (pb, ECR_PS2); /* Reset FIFO and enable PS2 */
 	parport_pc_data_reverse (pb); /* Must be in PS2 mode */
-	frob_econtrol (pb, 0xe0, ECR_TST << 5); /* Test FIFO */
+	frob_set_mode (pb, ECR_TST); /* Test FIFO */
 	frob_econtrol (pb, 1<<2, 1<<2);
 	frob_econtrol (pb, 1<<2, 0);
 	for (i = 1; i <= priv->fifo_depth; i++) {
@@ -1855,8 +1873,8 @@
 
 	priv->readIntrThreshold = i;
 
-	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-	outb (0xf4, ECONTROL (pb)); /* Configuration mode */
+	ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */
+	ECR_WRITE (pb, 0xf4); /* Configuration mode */
 	config = inb (CONFIGA (pb));
 	pword = (config >> 4) & 0x7;
 	switch (pword) {
@@ -1901,7 +1919,7 @@
 	}
 
 	/* Go back to mode 000 */
-	frob_econtrol (pb, 0xe0, ECR_SPP << 5);
+	frob_set_mode (pb, ECR_SPP);
 
 	return 1;
 }
@@ -1917,11 +1935,9 @@
 		return 0;
 
 	oecr = inb (ECONTROL (pb));
-	outb (ECR_PS2 << 5, ECONTROL (pb));
-	
+	ECR_WRITE (pb, ECR_PS2 << 5);
 	result = parport_PS2_supported(pb);
-
-	outb (oecr, ECONTROL (pb));
+	ECR_WRITE (pb, oecr);
 	return result;
 }
 
@@ -1953,7 +1969,7 @@
 	if (priv->ecr) {
 		unsigned char i;
 		for (i = 0x00; i < 0x80; i += 0x20) {
-			outb (i, ECONTROL (pb));
+			ECR_WRITE (pb, i);
 			if (clear_epp_timeout (pb)) {
 				/* Phony EPP in ECP. */
 				return 0;
@@ -1984,11 +2000,11 @@
 
 	oecr = inb (ECONTROL (pb));
 	/* Search for SMC style EPP+ECP mode */
-	outb (0x80, ECONTROL (pb));
+	ECR_WRITE (pb, 0x80);
 	outb (0x04, CONTROL (pb));
 	result = parport_EPP_supported(pb);
 
-	outb (oecr, ECONTROL (pb));
+	ECR_WRITE (pb, oecr);
 
 	if (result) {
 		/* Set up access functions to use ECP+EPP hardware. */
@@ -2025,12 +2041,12 @@
 		PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5
 	};
 
-	outb (ECR_CNF << 5, ECONTROL (pb)); /* Configuration MODE */
+	ECR_WRITE (pb, ECR_CNF << 5); /* Configuration MODE */
 
 	intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07;
 	irq = lookup[intrLine];
 
-	outb (oecr, ECONTROL (pb));
+	ECR_WRITE (pb, oecr);
 	return irq;
 }
 
@@ -2042,16 +2058,16 @@
 	sti();
 	irqs = probe_irq_on();
 		
-	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-	outb ((ECR_TST << 5) | 0x04, ECONTROL (pb));
-	outb (ECR_TST << 5, ECONTROL (pb));
+	ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */
+	ECR_WRITE (pb, (ECR_TST << 5) | 0x04);
+	ECR_WRITE (pb, ECR_TST << 5);
 
 	/* If Full FIFO sure that writeIntrThreshold is generated */
 	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) 
 		outb (0xaa, FIFO (pb));
 		
 	pb->irq = probe_irq_off(irqs);
-	outb (ECR_SPP << 5, ECONTROL (pb));
+	ECR_WRITE (pb, ECR_SPP << 5);
 
 	if (pb->irq <= 0)
 		pb->irq = PARPORT_IRQ_NONE;
@@ -2093,7 +2109,7 @@
 
 	pb->irq = probe_irq_off (irqs);
 	if (pb->modes & PARPORT_MODE_PCECR)
-		outb (oecr, ECONTROL (pb));
+		ECR_WRITE (pb, oecr);
 	parport_pc_write_control(pb, 0xc);
 
 	if (pb->irq <= 0)
@@ -2118,7 +2134,9 @@
  */
 static int __devinit parport_irq_probe(struct parport *pb)
 {
-	const struct parport_pc_private *priv = pb->private_data;
+	struct parport_pc_private *priv = pb->private_data;
+
+	priv->ctr_writable |= 0x10;
 
 	if (priv->ecr) {
 		pb->irq = programmable_irq_support(pb);
@@ -2144,6 +2162,9 @@
 	if (pb->irq == PARPORT_IRQ_NONE)
 		pb->irq = get_superio_irq(pb);
 
+	if (pb->irq == PARPORT_IRQ_NONE)
+		priv->ctr_writable &= ~0x10;
+
 	return pb->irq;
 }
 
@@ -2155,7 +2176,7 @@
 	unsigned char oecr = inb (ECONTROL (p));
 	int dma;
 
-	frob_econtrol (p, 0xe0, ECR_CNF << 5);
+	frob_set_mode (p, ECR_CNF);
 	
 	dma = inb (CONFIGB(p)) & 0x07;
 	/* 000: Indicates jumpered 8-bit DMA if read-only.
@@ -2163,7 +2184,7 @@
 	if ((dma & 0x03) == 0)
 		dma = PARPORT_DMA_NONE;
 
-	outb (oecr, ECONTROL (p));
+	ECR_WRITE (p, oecr);
 	return dma;
 }
 
@@ -2209,7 +2230,7 @@
 	}
 	memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
 	priv->ctr = 0xc;
-	priv->ctr_writable = 0xff;
+	priv->ctr_writable = ~0x10;
 	priv->ecr = 0;
 	priv->fifo_depth = 0;
 	priv->dma_buf = 0;
@@ -2371,7 +2392,7 @@
 		 * Put the ECP detected port in PS2 mode.
 		 * Do this also for ports that have ECR but don't do ECP.
 		 */
-		outb (0x34, ECONTROL (p));
+		ECR_WRITE (p, 0x34);
 
 	parport_pc_write_data(p, 0);
 	parport_pc_data_forward (p);
diff -Nru a/drivers/parport/share.c b/drivers/parport/share.c
--- a/drivers/parport/share.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/parport/share.c	Sun Feb 10 19:58:06 2002
@@ -1011,7 +1011,11 @@
 		/* If dev->waiting is clear now, an interrupt
 		   gave us the port and we would deadlock if we slept.  */
 		if (dev->waiting) {
-			sleep_on(&dev->wait_q);
+			interruptible_sleep_on (&dev->wait_q);
+			if (signal_pending (current)) {
+				restore_flags (flags);
+				return -EINTR;
+			}
 			r = 1;
 		} else {
 			r = 0;
@@ -1084,7 +1088,7 @@
 		if (pd->waiting & 2) { /* sleeping in claim_or_block */
 			parport_claim(pd);
 			if (waitqueue_active(&pd->wait_q))
-				wake_up(&pd->wait_q);
+				wake_up_interruptible(&pd->wait_q);
 			return;
 		} else if (pd->wakeup) {
 			pd->wakeup(pd->private);
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/pci/pci.c	Sun Feb 10 19:58:05 2002
@@ -1086,13 +1086,7 @@
 	child->parent = parent;
 	child->ops = parent->ops;
 	child->sysdata = parent->sysdata;
-
-	/* init generic fields */
-	child->iobus.self = &dev->dev;
-	child->iobus.parent = &parent->iobus;
-	dev->dev.subordinate = &child->iobus;
-
-	strcpy(child->iobus.name,dev->dev.name);
+	child->dev = &dev->dev;
 
 	/*
 	 * Set up the primary, secondary and subordinate
@@ -1361,16 +1355,11 @@
 	DBG("Scanning bus %02x\n", bus->number);
 	max = bus->secondary;
 
-	/* we should know for sure what the bus number is, so set the bus ID
-	 * for the bus and make sure it's registered in the device tree */
-	sprintf(bus->iobus.bus_id,"pci%d",bus->number);
-	iobus_register(&bus->iobus);
-
 	/* Create a device template */
 	memset(&dev0, 0, sizeof(dev0));
 	dev0.bus = bus;
 	dev0.sysdata = bus->sysdata;
-	dev0.dev.parent = &bus->iobus;
+	dev0.dev.parent = bus->dev;
 	dev0.dev.driver = &pci_device_driver;
 
 	/* Go find them, Rover! */
@@ -1430,9 +1419,11 @@
 		return NULL;
 	list_add_tail(&b->node, &pci_root_buses);
 
-	sprintf(b->iobus.bus_id,"pci%d",bus);
-	strcpy(b->iobus.name,"Host/PCI Bridge");
-	iobus_register(&b->iobus);
+	b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL);
+	memset(b->dev,0,sizeof(*(b->dev)));
+	sprintf(b->dev->bus_id,"pci%d",bus);
+	strcpy(b->dev->name,"Host/PCI Bridge");
+	device_register(b->dev);
 
 	b->number = b->secondary = bus;
 	b->resource[0] = &ioport_resource;
diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c
--- a/drivers/pci/proc.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/pci/proc.c	Sun Feb 10 19:58:04 2002
@@ -12,6 +12,7 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -21,8 +22,9 @@
 static loff_t
 proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
 {
-	loff_t new;
+	loff_t new = -1;
 
+	lock_kernel();
 	switch (whence) {
 	case 0:
 		new = off;
@@ -33,9 +35,8 @@
 	case 2:
 		new = PCI_CFG_SPACE_SIZE + off;
 		break;
-	default:
-		return -EINVAL;
 	}
+	unlock_kernel();
 	if (new < 0 || new > PCI_CFG_SPACE_SIZE)
 		return -EINVAL;
 	return (file->f_pos = new);
@@ -45,7 +46,7 @@
 proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
 {
 	const struct inode *ino = file->f_dentry->d_inode;
-	const struct proc_dir_entry *dp = ino->u.generic_ip;
+	const struct proc_dir_entry *dp = PDE(ino);
 	struct pci_dev *dev = dp->data;
 	unsigned int pos = *ppos;
 	unsigned int cnt, size;
@@ -127,7 +128,7 @@
 proc_bus_pci_write(struct file *file, const char *buf, size_t nbytes, loff_t *ppos)
 {
 	const struct inode *ino = file->f_dentry->d_inode;
-	const struct proc_dir_entry *dp = ino->u.generic_ip;
+	const struct proc_dir_entry *dp = PDE(ino);
 	struct pci_dev *dev = dp->data;
 	int pos = *ppos;
 	int cnt;
@@ -199,7 +200,7 @@
 
 static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	const struct proc_dir_entry *dp = PDE(inode);
 	struct pci_dev *dev = dp->data;
 #ifdef HAVE_PCI_MMAP
 	struct pci_filp_private *fpriv = file->private_data;
@@ -241,7 +242,7 @@
 static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	const struct proc_dir_entry *dp = PDE(inode);
 	struct pci_dev *dev = dp->data;
 	struct pci_filp_private *fpriv = file->private_data;
 	int ret;
@@ -371,6 +372,47 @@
 
 static struct proc_dir_entry *proc_bus_pci_dir;
 
+/* driverfs files */
+static ssize_t pci_show_irq(struct device * dev, char * buf, size_t count, loff_t off)
+{
+	struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+	return off ? 0 : sprintf(buf,"%u",pci_dev->irq);
+}
+
+static struct driver_file_entry pci_irq_entry = {
+	name:	"irq",
+	mode:	S_IRUGO,
+	show:	pci_show_irq,
+};
+
+static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off)
+{
+	struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+	char * str = buf;
+	int i;
+
+	if (off && off < DEVICE_COUNT_RESOURCE) {
+		str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n",
+				       pci_resource_start(pci_dev,off),
+				       pci_resource_end(pci_dev,off),
+				       pci_resource_flags(pci_dev,off));
+	} else if (!off) {
+		for (i = 0; i < DEVICE_COUNT_RESOURCE && pci_resource_start(pci_dev,i); i++) {
+			str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n",
+				       pci_resource_start(pci_dev,i),
+				       pci_resource_end(pci_dev,i),
+				       pci_resource_flags(pci_dev,i));
+		}
+	}
+	return (str - buf);
+}
+
+static struct driver_file_entry pci_resource_entry = {
+	name:	"resources",
+	mode:	S_IRUGO,
+	show:	pci_show_resources,
+};
+
 int pci_proc_attach_device(struct pci_dev *dev)
 {
 	struct pci_bus *bus = dev->bus;
@@ -390,6 +432,9 @@
 	e->proc_fops = &proc_bus_pci_operations;
 	e->data = dev;
 	e->size = PCI_CFG_SPACE_SIZE;
+
+	device_create_file(&dev->dev,&pci_irq_entry);
+	device_create_file(&dev->dev,&pci_resource_entry);
 	return 0;
 }
 
diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/pcmcia/cardbus.c	Sun Feb 10 19:58:05 2002
@@ -281,6 +281,11 @@
 
 		pci_setup_device(dev);
 
+		dev->dev.parent = bus->dev;
+		strcpy(dev->dev.name, dev->name);
+		strcpy(dev->dev.bus_id, dev->slot_name);
+		device_register(&dev->dev);
+
 		/* FIXME: Do we need to enable the expansion ROM? */
 		for (r = 0; r < 7; r++) {
 			struct resource *res = dev->resource + r;
diff -Nru a/drivers/pnp/isapnp_proc.c b/drivers/pnp/isapnp_proc.c
--- a/drivers/pnp/isapnp_proc.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/pnp/isapnp_proc.c	Sun Feb 10 19:58:05 2002
@@ -84,18 +84,26 @@
 
 static loff_t isapnp_info_entry_lseek(struct file *file, loff_t offset, int orig)
 {
+	loff_t ret;
+
+	lock_kernel();
+
 	switch (orig) {
 	case 0:	/* SEEK_SET */
 		file->f_pos = offset;
-		return file->f_pos;
+		ret = file->f_pos;
+		break;
 	case 1:	/* SEEK_CUR */
 		file->f_pos += offset;
-		return file->f_pos;
+		ret = file->f_pos;
+		break;
 	case 2:	/* SEEK_END */
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
-	return -ENXIO;
+
+	unlock_kernel();
+	return ret;
 }
 
 static ssize_t isapnp_info_entry_read(struct file *file, char *buffer,
@@ -211,8 +219,9 @@
 
 static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
 {
-	loff_t new;
-	
+	loff_t new = -1;
+
+	lock_kernel();
 	switch (whence) {
 	case 0:
 		new = off;
@@ -223,18 +232,19 @@
 	case 2:
 		new = 256 + off;
 		break;
-	default:
-		return -EINVAL;
 	}
-	if (new < 0 || new > 256)
+	if (new < 0 || new > 256) {
+		unlock_kernel();
 		return -EINVAL;
+	}
+	unlock_kernel();
 	return (file->f_pos = new);
 }
 
 static ssize_t isapnp_proc_bus_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
 {
 	struct inode *ino = file->f_dentry->d_inode;
-	struct proc_dir_entry *dp = ino->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(ino);
 	struct pci_dev *dev = dp->data;
 	int pos = *ppos;
 	int cnt, size = 256;
diff -Nru a/drivers/pnp/pnpbios_core.c b/drivers/pnp/pnpbios_core.c
--- a/drivers/pnp/pnpbios_core.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/pnp/pnpbios_core.c	Sun Feb 10 19:58:04 2002
@@ -45,6 +45,7 @@
 #include <linux/completion.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
+#include <asm/byteorder.h>
 
 
 /*
diff -Nru a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
--- a/drivers/sbus/char/flash.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/sbus/char/flash.c	Sun Feb 10 19:58:03 2002
@@ -83,6 +83,7 @@
 static long long
 flash_llseek(struct file *file, long long offset, int origin)
 {
+	lock_kernel();
 	switch (origin) {
 		case 0:
 			file->f_pos = offset;
@@ -96,8 +97,10 @@
 			file->f_pos = flash.read_size;
 			break;
 		default:
+			unlock_kernel();
 			return -EINVAL;
 	}
+	unlock_kernel();
 	return file->f_pos;
 }
 
diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
--- a/drivers/sbus/char/jsflash.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/sbus/char/jsflash.c	Sun Feb 10 19:58:06 2002
@@ -259,16 +259,23 @@
  */
 static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
 {
+	loff_t ret;
+
+	lock_kernel();
 	switch (orig) {
 		case 0:
 			file->f_pos = offset;
-			return file->f_pos;
+			ret = file->f_pos;
+			break;
 		case 1:
 			file->f_pos += offset;
-			return file->f_pos;
+			ret = file->f_pos;
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
 	}
+	unlock_kernel();
+	return ret;
 }
 
 /*
diff -Nru a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c
--- a/drivers/sbus/char/sunkbd.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/sbus/char/sunkbd.c	Sun Feb 10 19:58:04 2002
@@ -1338,7 +1338,7 @@
 		spin_unlock_irqrestore(&kbd_queue_lock, flags);
 
 #ifdef CONFIG_SPARC32_COMPAT
-		if (current->thread.flags & SPARC_FLAG_32BIT) {
+		if (test_thread_flag(TIF_32BIT)) {
 			if (copy_to_user((Firm_event *)p, &this_event,
 					 sizeof(Firm_event)-sizeof(struct timeval)))
 				return -EFAULT;
diff -Nru a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c
--- a/drivers/sbus/char/sunmouse.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/sbus/char/sunmouse.c	Sun Feb 10 19:58:06 2002
@@ -462,7 +462,7 @@
 			spin_unlock_irqrestore(&sunmouse.lock, flags);
 
 #ifdef CONFIG_SPARC32_COMPAT
-			if (current->thread.flags & SPARC_FLAG_32BIT) {
+			if (test_thread_flag(TIF_32BIT)) {
 				if ((end - p) <
 				    ((sizeof(Firm_event) - sizeof(struct timeval) +
 				      (sizeof(u32) * 2))))
diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
--- a/drivers/scsi/3w-xxxx.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/3w-xxxx.c	Sun Feb 10 19:58:05 2002
@@ -108,6 +108,8 @@
                  Fix get_param for specific units.
 */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 MODULE_AUTHOR ("3ware Inc.");
diff -Nru a/drivers/scsi/53c7,8xx.c b/drivers/scsi/53c7,8xx.c
--- a/drivers/scsi/53c7,8xx.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/53c7,8xx.c	Sun Feb 10 19:58:04 2002
@@ -62,6 +62,8 @@
  *  the fourth byte from 50 to 25.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/config.h>
 
 #ifdef CONFIG_SCSI_NCR53C7xx_sync
diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/53c700.c	Sun Feb 10 19:58:04 2002
@@ -51,6 +51,14 @@
 
 /* CHANGELOG
  *
+ * Version 2.7
+ *
+ * Fixed scripts problem which caused certain devices (notably CDRWs)
+ * to hang on initial INQUIRY.  Updated NCR_700_readl/writel to use
+ * __raw_readl/writel for parisc compatibility (Thomas
+ * Bogendoerfer). Added missing SCp->request_bufflen initialisation
+ * for sense requests (Ryan Bradetich).
+ *
  * Version 2.6
  *
  * Following test of the 64 bit parisc kernel by Richard Hirst,
@@ -96,7 +104,7 @@
  * Initial modularisation from the D700.  See NCR_D700.c for the rest of
  * the changelog.
  * */
-#define NCR_700_VERSION "2.6"
+#define NCR_700_VERSION "2.7"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -310,7 +318,6 @@
 	hostdata->pScript = pScript;
 	NCR_700_dma_cache_wback((unsigned long)script, sizeof(SCRIPT));
 	hostdata->state = NCR_700_HOST_FREE;
-	spin_lock_init(&hostdata->lock);
 	hostdata->cmd = NULL;
 	host->max_id = 7;
 	host->max_lun = NCR_700_MAX_LUNS;
@@ -1048,6 +1055,7 @@
 						    slot->pCmd,
 						    SCp->cmd_len,
 						    PCI_DMA_TODEVICE);
+				SCp->request_bufflen = sizeof(SCp->sense_buffer);
 				slot->dma_handle = pci_map_single(hostdata->pci_dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), PCI_DMA_FROMDEVICE);
 				slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer));
 				slot->SG[0].pAddr = bS_to_host(slot->dma_handle);
@@ -1508,6 +1516,11 @@
 	__u8 pun = 0xff, lun = 0xff;
 	unsigned long flags;
 
+	/* Use the host lock to serialise acess to the 53c700
+	 * hardware.  Note: In future, we may need to take the queue
+	 * lock to enter the done routines.  When that happens, we
+	 * need to ensure that for this driver, the host lock and the
+	 * queue lock point to the same thing. */
 	spin_lock_irqsave(host->host_lock, flags);
 	if((istat = NCR_700_readb(host, ISTAT_REG))
 	      & (SCSI_INT_PENDING | DMA_INT_PENDING)) {
diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
--- a/drivers/scsi/53c700.h	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/53c700.h	Sun Feb 10 19:58:04 2002
@@ -210,7 +210,7 @@
 struct NCR_700_Host_Parameters {
 	/* These must be filled in by the calling driver */
 	int	clock;			/* board clock speed in MHz */
-	__u32	base;			/* the base for the port (copied to host) */
+	unsigned long	base;		/* the base for the port (copied to host) */
 	struct pci_dev	*pci_dev;
 	__u32	dmode_extra;	/* adjustable bus settings */
 	__u32	differential:1;	/* if we are differential */
@@ -234,10 +234,6 @@
 	__u32	*script;		/* pointer to script location */
 	__u32	pScript;		/* physical mem addr of script */
 
-	/* This will be the host lock.  Unfortunately, we can't use it
-	 * at the moment because of the necessity of holding the
-	 * io_request_lock */
-	spinlock_t lock;
 	enum NCR_700_Host_State state; /* protected by state lock */
 	Scsi_Cmnd *cmd;
 	/* Note: pScript contains the single consistent block of
@@ -503,7 +499,7 @@
 static inline __u32
 NCR_700_readl(struct Scsi_Host *host, __u32 reg)
 {
-	__u32 value = readl(host->base + reg);
+	__u32 value = __raw_readl(host->base + reg);
 	const struct NCR_700_Host_Parameters *hostdata __attribute__((unused))
 		= (struct NCR_700_Host_Parameters *)host->hostdata[0];
 #if 1
@@ -536,7 +532,7 @@
 		BUG();
 #endif
 
-	writel(bS_to_host(value), host->base + reg);
+	__raw_writel(bS_to_host(value), host->base + reg);
 }
 #elif defined(CONFIG_53C700_IO_MAPPED)
 static inline __u8
diff -Nru a/drivers/scsi/53c700.scr b/drivers/scsi/53c700.scr
--- a/drivers/scsi/53c700.scr	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/53c700.scr	Sun Feb 10 19:58:04 2002
@@ -242,7 +242,7 @@
 
 SendIdentifyMsg:
 	CALL	SendMessage
-	JUMP	SendCommand
+	CLEAR	ATN
 
 IgnoreMsgBeforeCommand:
 	CLEAR	ACK
diff -Nru a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c
--- a/drivers/scsi/AM53C974.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/AM53C974.c	Sun Feb 10 19:58:06 2002
@@ -1,3 +1,5 @@
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/signal.h>
diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
--- a/drivers/scsi/BusLogic.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/BusLogic.c	Sun Feb 10 19:58:06 2002
@@ -29,6 +29,7 @@
 #define BusLogic_DriverVersion		"2.1.15"
 #define BusLogic_DriverDate		"17 August 1998"
 
+#error Please convert me to Documentation/DMA-mapping.txt
 
 #include <linux/version.h>
 #include <linux/module.h>
diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
--- a/drivers/scsi/NCR_D700.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/NCR_D700.c	Sun Feb 10 19:58:04 2002
@@ -36,6 +36,10 @@
 
 /* CHANGELOG 
  *
+ * Version 2.2
+ *
+ * Added mca_set_adapter_name().
+ *
  * Version 2.1
  *
  * Modularise the driver into a Board piece (this file) and a chip
@@ -86,7 +90,7 @@
  * disconnections and reselections are being processed correctly.
  * */
 
-#define NCR_D700_VERSION "2.1"
+#define NCR_D700_VERSION "2.2"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -299,6 +303,7 @@
 				continue;
 			}
 			found++;
+			mca_set_adapter_name(slot, "NCR D700 SCSI Adapter (version " NCR_D700_VERSION ")");
 		}
 	}
 
diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
--- a/drivers/scsi/advansys.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/advansys.c	Sun Feb 10 19:58:05 2002
@@ -752,6 +752,7 @@
 
 */
 
+#error Please convert me to Documentation/DMA-mapping.txt
 
 /*
  * --- Linux Version
diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
--- a/drivers/scsi/aha1542.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/scsi/aha1542.c	Sun Feb 10 19:58:03 2002
@@ -51,13 +51,14 @@
 
 #include "aha1542.h"
 
-#define SCSI_PA(address) virt_to_bus(address)
+#define SCSI_BUF_PA(address)	isa_virt_to_bus(address)
+#define SCSI_SG_PA(sgent)	(isa_page_to_bus((sgent)->page) + (sgent)->offset)
 
 static void BAD_DMA(void *address, unsigned int length)
 {
 	printk(KERN_CRIT "buf vaddress %p paddress 0x%lx length %d\n",
 	       address,
-	       SCSI_PA(address),
+	       SCSI_BUF_PA(address),
 	       length);
 	panic("Buffer at physical address > 16Mb used for aha1542");
 }
@@ -67,10 +68,10 @@
 		       int nseg,
 		       int badseg)
 {
-	printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%lx length %d\n",
+	printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%x length %d\n",
 	       badseg, nseg,
 	       page_address(sgpnt[badseg].page) + sgpnt[badseg].offset,
-	       (unsigned long)page_to_bus(sgpnt[badseg].page) + sgpnt[badseg].offset,
+	       SCSI_SG_PA(&sgpnt[badseg]),
 	       sgpnt[badseg].length);
 
 	/*
@@ -511,7 +512,7 @@
 			return;
 		};
 
-		mbo = (scsi2int(mb[mbi].ccbptr) - (SCSI_PA(&ccb[0]))) / sizeof(struct ccb);
+		mbo = (scsi2int(mb[mbi].ccbptr) - (SCSI_BUF_PA(&ccb[0]))) / sizeof(struct ccb);
 		mbistatus = mb[mbi].status;
 		mb[mbi].status = 0;
 		HOSTDATA(shost)->aha1542_last_mbi_used = mbi;
@@ -681,7 +682,7 @@
 	printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done);
 #endif
 
-	any2scsi(mb[mbo].ccbptr, SCSI_PA(&ccb[mbo]));	/* This gets trashed for some reason */
+	any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo]));	/* This gets trashed for some reason */
 
 	memset(&ccb[mbo], 0, sizeof(struct ccb));
 
@@ -715,7 +716,8 @@
 				printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i);
 				for (i = 0; i < SCpnt->use_sg; i++) {
 					printk(KERN_CRIT "%d: %p %d\n", i,
-					       page_address(sgpnt[i].page) + sgpnt[i].offset,
+					       (page_address(sgpnt[i].page) +
+						sgpnt[i].offset),
 					       sgpnt[i].length);
 				};
 				printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr);
@@ -724,13 +726,13 @@
 					printk("%02x ", ptr[i]);
 				panic("Foooooooood fight!");
 			};
-			any2scsi(cptr[i].dataptr, page_to_bus(sgpnt[i].page) + sgpnt[i].offset);
-			if (page_to_bus(sgpnt[i].page) + sgpnt[i].offset + sgpnt[i].length - 1 > ISA_DMA_THRESHOLD)
+			any2scsi(cptr[i].dataptr, SCSI_SG_PA(&sgpnt[i]));
+			if (SCSI_SG_PA(&sgpnt[i]) + sgpnt[i].length - 1 > ISA_DMA_THRESHOLD)
 				BAD_SG_DMA(SCpnt, sgpnt, SCpnt->use_sg, i);
 			any2scsi(cptr[i].datalen, sgpnt[i].length);
 		};
 		any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
-		any2scsi(ccb[mbo].dataptr, SCSI_PA(cptr));
+		any2scsi(ccb[mbo].dataptr, SCSI_BUF_PA(cptr));
 #ifdef DEBUG
 		printk("cptr %x: ", cptr);
 		ptr = (unsigned char *) cptr;
@@ -741,9 +743,9 @@
 		ccb[mbo].op = 0;	/* SCSI Initiator Command */
 		SCpnt->host_scribble = NULL;
 		any2scsi(ccb[mbo].datalen, bufflen);
-		if (buff && SCSI_PA(buff + bufflen - 1) > ISA_DMA_THRESHOLD)
+		if (buff && SCSI_BUF_PA(buff + bufflen - 1) > ISA_DMA_THRESHOLD)
 			BAD_DMA(buff, bufflen);
-		any2scsi(ccb[mbo].dataptr, SCSI_PA(buff));
+		any2scsi(ccb[mbo].dataptr, SCSI_BUF_PA(buff));
 	};
 	ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7);	/*SCSI Target Id */
 	ccb[mbo].rsalen = 16;
@@ -803,10 +805,10 @@
 
 	for (i = 0; i < AHA1542_MAILBOXES; i++) {
 		mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
-		any2scsi(mb[i].ccbptr, SCSI_PA(&ccb[i]));
+		any2scsi(mb[i].ccbptr, SCSI_BUF_PA(&ccb[i]));
 	};
 	aha1542_intr_reset(bse);	/* reset interrupts, so they don't block */
-	any2scsi((cmd + 2), SCSI_PA(mb));
+	any2scsi((cmd + 2), SCSI_BUF_PA(mb));
 	aha1542_out(bse, cmd, 5);
 	WAIT(INTRFLAGS(bse), INTRMASK, HACC, 0);
 	while (0) {
@@ -1186,7 +1188,7 @@
 				continue;
 			/* For now we do this - until kmalloc is more intelligent
 			   we are resigned to stupid hacks like this */
-			if (SCSI_PA(shpnt) >= ISA_DMA_THRESHOLD) {
+			if (SCSI_BUF_PA(shpnt) >= ISA_DMA_THRESHOLD) {
 				printk(KERN_ERR "Invalid address for shpnt with 1542.\n");
 				goto unregister;
 			}
@@ -1399,7 +1401,7 @@
 	HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo;
 	restore_flags(flags);
 
-	any2scsi(mb[mbo].ccbptr, SCSI_PA(&ccb[mbo]));	/* This gets trashed for some reason */
+	any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo]));	/* This gets trashed for some reason */
 
 	memset(&ccb[mbo], 0, sizeof(struct ccb));
 
diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
--- a/drivers/scsi/aha1740.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/aha1740.c	Sun Feb 10 19:58:05 2002
@@ -232,7 +232,7 @@
     {
 	DEB(printk("aha1740_intr top of loop.\n"));
 	adapstat = inb(G2INTST(base));
-	ecbptr = (struct ecb *) bus_to_virt(inl(MBOXIN0(base)));
+	ecbptr = (struct ecb *) isa_bus_to_virt(inl(MBOXIN0(base)));
 	outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */
       
 	switch ( adapstat & G2INTST_MASK )
@@ -397,10 +397,10 @@
 	for(i=0; i<SCpnt->use_sg; i++)
 	{
 	    cptr[i].datalen = sgpnt[i].length;
-	    cptr[i].dataptr = virt_to_bus(sgpnt[i].address);
+	    cptr[i].dataptr = isa_virt_to_bus(sgpnt[i].address);
 	}
 	host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);
-	host->ecb[ecbno].dataptr = virt_to_bus(cptr);
+	host->ecb[ecbno].dataptr = isa_virt_to_bus(cptr);
 #ifdef DEBUG
 	printk("cptr %x: ",cptr);
 	ptr = (unsigned char *) cptr;
@@ -411,15 +411,15 @@
     {
 	SCpnt->host_scribble = NULL;
 	host->ecb[ecbno].datalen = bufflen;
-	host->ecb[ecbno].dataptr = virt_to_bus(buff);
+	host->ecb[ecbno].dataptr = isa_virt_to_bus(buff);
     }
     host->ecb[ecbno].lun = SCpnt->lun;
     host->ecb[ecbno].ses = 1;	/* Suppress underrun errors */
     host->ecb[ecbno].dir = direction;
     host->ecb[ecbno].ars = 1;  /* Yes, get the sense on an error */
     host->ecb[ecbno].senselen = 12;
-    host->ecb[ecbno].senseptr = virt_to_bus(host->ecb[ecbno].sense);
-    host->ecb[ecbno].statusptr = virt_to_bus(host->ecb[ecbno].status);
+    host->ecb[ecbno].senseptr = isa_virt_to_bus(host->ecb[ecbno].sense);
+    host->ecb[ecbno].statusptr = isa_virt_to_bus(host->ecb[ecbno].status);
     host->ecb[ecbno].done = done;
     host->ecb[ecbno].SCpnt = SCpnt;
 #ifdef DEBUG
@@ -459,7 +459,7 @@
 	    if (loopcnt == LOOPCNT_MAX)
 		panic("aha1740.c: mbxout busy!\n");
 	}
-	outl(virt_to_bus(host->ecb + ecbno), MBOXOUT0(base));
+	outl(isa_virt_to_bus(host->ecb + ecbno), MBOXOUT0(base));
 	for (loopcnt = 0; ; loopcnt++) {
 	    if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
 	    if (loopcnt == LOOPCNT_WARN) {
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/aic7xxx_old.c	Sun Feb 10 19:58:06 2002
@@ -254,12 +254,6 @@
 
 #include <linux/config.h>        /* for CONFIG_PCI */
 
-/*
- * To generate the correct addresses for the controller to issue
- * on the bus.  Originally added for DEC Alpha support.
- */
-#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a))
-
 #define AIC7XXX_C_VERSION  "5.2.4"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
@@ -2841,17 +2835,9 @@
         char *buffer;
 
         if(cmd->use_sg)
-        {
-          struct scatterlist *sg;
-
-          sg = (struct scatterlist *)cmd->request_buffer;
-          buffer = (char *)sg[0].address;
-        }
-        else
-        {
-          buffer = (char *)cmd->request_buffer;
-        }
+          BUG();
 
+        buffer = (char *)cmd->request_buffer;
 
         if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
              (p->features & AHC_WIDE) )
diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
--- a/drivers/scsi/atp870u.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/atp870u.c	Sun Feb 10 19:58:05 2002
@@ -14,6 +14,8 @@
  *		   support atp880 chip lvd u160 2001/05/15 (7.1)
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 #include <linux/kernel.h>
diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
--- a/drivers/scsi/dpt_i2o.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/dpt_i2o.c	Sun Feb 10 19:58:05 2002
@@ -28,6 +28,8 @@
 
 #define ADDR32 (0)
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/version.h>
 #include <linux/module.h>
 
diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c
--- a/drivers/scsi/eata.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/eata.c	Sun Feb 10 19:58:05 2002
@@ -401,6 +401,8 @@
  *  the driver sets host->wish_block = TRUE for all ISA boards.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/version.h>
 
 #ifndef LinuxVersionCode
diff -Nru a/drivers/scsi/eata_dma.c b/drivers/scsi/eata_dma.c
--- a/drivers/scsi/eata_dma.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/eata_dma.c	Sun Feb 10 19:58:04 2002
@@ -63,6 +63,8 @@
 
 /* Look in eata_dma.h for configuration and revision information */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c
--- a/drivers/scsi/esp.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/esp.c	Sun Feb 10 19:58:06 2002
@@ -813,7 +813,7 @@
 	 * sanely maintain.
 	 */
 	if (request_irq(esp->ehost->irq, esp_intr,
-			SA_SHIRQ, "ESP SCSI", esp->ehost)) {
+			SA_SHIRQ, "ESP SCSI", esp)) {
 		printk("esp%d: Cannot acquire irq line\n",
 		       esp->esp_id);
 		return -1;
diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
--- a/drivers/scsi/gdth.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/gdth.c	Sun Feb 10 19:58:04 2002
@@ -295,6 +295,8 @@
  * phase:                       Service/parameter/return code special command
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 #include <linux/version.h>
diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
--- a/drivers/scsi/ibmmca.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/ibmmca.c	Sun Feb 10 19:58:04 2002
@@ -766,12 +766,12 @@
       scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
       last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
       last_scsi_type(host_index)[ldn] = IM_SCB;
-      scb->sys_buf_adr = virt_to_bus(buf);
+      scb->sys_buf_adr = isa_virt_to_bus(buf);
       scb->sys_buf_length = 255; /* maximum bufferlength gives max info */
-      scb->tsb_adr = virt_to_bus(tsb);
+      scb->tsb_adr = isa_virt_to_bus(tsb);
       /* issue scb to passed ldn, and busy wait for interrupt */
       got_interrupt(host_index) = 0;
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
       while (!got_interrupt(host_index))
 	barrier ();
 
@@ -804,12 +804,12 @@
       scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
       last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
       last_scsi_type(host_index)[ldn] = IM_SCB;
-      scb->sys_buf_adr = virt_to_bus(buf);
+      scb->sys_buf_adr = isa_virt_to_bus(buf);
       scb->sys_buf_length = 8;
-      scb->tsb_adr = virt_to_bus(tsb);
+      scb->tsb_adr = isa_virt_to_bus(tsb);
       /*issue scb to passed ldn, and busy wait for interrupt */
       got_interrupt(host_index) = 0;
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
       while (!got_interrupt(host_index))
 	barrier ();
 
@@ -842,15 +842,15 @@
       scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
       last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
       last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;
-      scb->sys_buf_adr = virt_to_bus(buf);
+      scb->sys_buf_adr = isa_virt_to_bus(buf);
       if (special(host_index)==IBM_SCSI2_FW)
 	scb->sys_buf_length = 256; /* get all info from F/W adapter */
       else
 	scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */
-      scb->tsb_adr = virt_to_bus(tsb);
+      scb->tsb_adr = isa_virt_to_bus(tsb);
       /*issue scb to ldn=15, and busy wait for interrupt */
       got_interrupt(host_index) = 0;
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
       while (!got_interrupt(host_index))
 	barrier ();
 
@@ -1992,7 +1992,7 @@
    scb = &(ld(host_index)[ldn].scb);
    ld(host_index)[ldn].tsb.dev_status = 0;
    scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
-   scb->tsb_adr = virt_to_bus(&(ld(host_index)[ldn].tsb));
+   scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb));
    scsi_cmd = cmd->cmnd[0];
 
    if (cmd->use_sg) {
@@ -2001,14 +2001,14 @@
       if (i > 16)
 	panic ("IBM MCA SCSI: scatter-gather list too long.\n");
       while (--i >= 0) {
-	 ld(host_index)[ldn].sge[i].address = (void *)(virt_to_bus(sl[i].address));
+	 ld(host_index)[ldn].sge[i].address = (void *)(isa_page_to_bus(sl[i].page) + sl[i].offset);
 	 ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
       }
       scb->enable |= IM_POINTER_TO_LIST;
-      scb->sys_buf_adr = virt_to_bus(&(ld(host_index)[ldn].sge[0]));
+      scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0]));
       scb->sys_buf_length = cmd->use_sg * sizeof (struct im_sge);
    } else {
-      scb->sys_buf_adr = virt_to_bus(cmd->request_buffer);
+      scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer);
       /* recent Linux midlevel SCSI places 1024 byte for inquiry
        * command. Far too much for old PS/2 hardware. */
       switch (scsi_cmd) {
@@ -2165,10 +2165,10 @@
      PS2_DISK_LED_ON (shpnt->host_no, target);
 
    if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) {
-      issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
       IBM_DS(host_index).long_scbs++;
    } else {
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
       IBM_DS(host_index).scbs++;
    }
    return 0;
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/ide-scsi.c	Sun Feb 10 19:58:04 2002
@@ -130,6 +130,7 @@
 static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
 {
 	int count;
+	char *buf;
 
 	while (bcount) {
 		if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
@@ -138,7 +139,8 @@
 			return;
 		}
 		count = IDE_MIN (pc->sg->length - pc->b_count, bcount);
-		atapi_input_bytes (drive, pc->sg->address + pc->b_count, count);
+		buf = page_address(pc->sg->page) + pc->sg->offset;
+		atapi_input_bytes (drive, buf + pc->b_count, count);
 		bcount -= count; pc->b_count += count;
 		if (pc->b_count == pc->sg->length) {
 			pc->sg++;
@@ -150,6 +152,7 @@
 static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
 {
 	int count;
+	char *buf;
 
 	while (bcount) {
 		if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
@@ -158,7 +161,8 @@
 			return;
 		}
 		count = IDE_MIN (pc->sg->length - pc->b_count, bcount);
-		atapi_output_bytes (drive, pc->sg->address + pc->b_count, count);
+		buf = page_address(pc->sg->page) + pc->sg->offset;
+		atapi_output_bytes (drive, buf + pc->b_count, count);
 		bcount -= count; pc->b_count += count;
 		if (pc->b_count == pc->sg->length) {
 			pc->sg++;
@@ -750,25 +754,11 @@
 		printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10);
 #endif /* IDESCSI_DEBUG_LOG */
 		while (segments--) {
-			struct page *page = sg->page;
-			int offset = sg->offset;
-
-			if (!page) {
-				BUG_ON(!sg->address);
-				page = virt_to_page(sg->address);
-				offset = (unsigned long) sg->address & ~PAGE_MASK;
-			}
-				
-			bh->bi_io_vec[0].bv_page = page;
+			bh->bi_io_vec[0].bv_page = sg->page;
 			bh->bi_io_vec[0].bv_len = sg->length;
-			bh->bi_io_vec[0].bv_offset = offset;
+			bh->bi_io_vec[0].bv_offset = sg->offset;
 			bh->bi_size = sg->length;
 			bh = bh->bi_next;
-			/*
-			 * just until scsi_merge is fixed up...
-			 */
-			BUG_ON(PageHighMem(page));
-			sg->address = page_address(page) + offset;
 			sg++;
 		}
 	} else {
diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c
--- a/drivers/scsi/ini9100u.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/ini9100u.c	Sun Feb 10 19:58:05 2002
@@ -108,6 +108,8 @@
 
 #define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #ifndef LINUX_VERSION_CODE
 #include <linux/version.h>
 #endif
diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c
--- a/drivers/scsi/inia100.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/inia100.c	Sun Feb 10 19:58:05 2002
@@ -67,6 +67,8 @@
 #include <linux/version.h>
 #endif
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 #include <stdarg.h>
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/scsi/ips.c	Sun Feb 10 19:58:03 2002
@@ -140,6 +140,8 @@
  * ioctlsize            - Initial size of the IOCTL buffer
  */
  
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/page.h>
diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
--- a/drivers/scsi/lasi700.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/lasi700.c	Sun Feb 10 19:58:04 2002
@@ -136,7 +136,6 @@
 lasi700_driver_callback(struct parisc_device *dev)
 {
 	unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET;
-	int irq = busdevice_alloc_irq(dev);
 	char *driver_name;
 	struct Scsi_Host *host;
 	struct NCR_700_Host_Parameters *hostdata =
@@ -170,14 +169,15 @@
 		hostdata->chip710 = 1;
 		hostdata->dmode_extra = DMODE_FC2;
 	}
+	hostdata->pci_dev = ccio_get_fake(dev);
 	if((host = NCR_700_detect(host_tpnt, hostdata)) == NULL) {
 		kfree(hostdata);
 		release_mem_region(host->base, 64);
 		return 1;
 	}
-	host->irq = irq;
-	if(request_irq(irq, NCR_700_intr, SA_SHIRQ, driver_name, host)) {
-		printk(KERN_ERR "%s: irq problem, detatching\n",
+	host->irq = dev->irq;
+	if(request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, driver_name, host)) {
+		printk(KERN_ERR "%s: irq problem, detaching\n",
 		       driver_name);
 		scsi_unregister(host);
 		NCR_700_release(host);
@@ -197,6 +197,7 @@
 	kfree(hostdata);
 	free_irq(host->irq, host);
 	release_mem_region(host->base, 64);
+	unregister_parisc_driver(&lasi700_driver);
 	return 1;
 }
 
diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
--- a/drivers/scsi/mca_53c9x.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/mca_53c9x.c	Sun Feb 10 19:58:05 2002
@@ -227,7 +227,7 @@
 
 			esp->esp_command = (volatile unsigned char*)
 			  cmd_buffer;
-	 		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
+	 		esp->esp_command_dvma = isa_virt_to_bus(cmd_buffer);
 
 			/* SCSI chip speed */
 
diff -Nru a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
--- a/drivers/scsi/megaraid.h	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/megaraid.h	Sun Feb 10 19:58:06 2002
@@ -30,7 +30,7 @@
 #define M_RD_IOCTL_CMD_NEW		0x81
 #define M_RD_DRIVER_IOCTL_INTERFACE	0x82
 
-#define MEGARAID_VERSION "v1.18 (Release Date: Thu Oct 11 15:02:53 EDT 2001\n)"
+#define MEGARAID_VERSION "v1.18 (Release Date: Thu Oct 11 15:02:53 EDT 2001)\n"
 
 #define MEGARAID_IOCTL_VERSION 	114
 
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/osst.c	Sun Feb 10 19:58:06 2002
@@ -125,8 +125,8 @@
 #define OSST_TIMEOUT (200 * HZ)
 #define OSST_LONG_TIMEOUT (1800 * HZ)
 
-#define TAPE_NR(x) (MINOR(x) & ~(128 | ST_MODE_MASK))
-#define TAPE_MODE(x) ((MINOR(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
+#define TAPE_NR(x) (minor(x) & ~(128 | ST_MODE_MASK))
+#define TAPE_MODE(x) ((minor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
 
 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
    24 bits) */
@@ -479,7 +479,8 @@
 	if (STp->raw) {
 		if (STp->buffer->syscall_result) {
 			for (i=0; i < STp->buffer->sg_segs; i++)
-				memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length);
+				memset(page_address(STp->buffer->sg[i].page),
+				       0, STp->buffer->sg[i].length);
 			strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
 		}
 		return 1;
@@ -4021,7 +4022,7 @@
 		if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
 			STp->rew_at_close = 0;
 		else if (cmd_in == MTLOAD) {
-/*      		STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;  FIXME */
+/*      		STp->rew_at_close = (minor(inode->i_rdev) & 0x80) == 0;  FIXME */
 			for (i=0; i < ST_NBR_PARTITIONS; i++) {
 			    STp->ps[i].rw = ST_IDLE;
 			    STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
@@ -4103,7 +4104,7 @@
 		return (-EBUSY);
 	}
 	STp->in_use       = 1;
-	STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+	STp->rew_at_close = (minor(inode->i_rdev) & 0x80) == 0;
 
 	if (STp->device->host->hostt->module)
 		 __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
@@ -4124,7 +4125,7 @@
 	flags = filp->f_flags;
 	STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
 
-	STp->raw = (MINOR(inode->i_rdev) & 0x40) != 0;
+	STp->raw = (minor(inode->i_rdev) & 0x40) != 0;
 
 	/* Allocate a buffer for this user */
 	need_dma_buffer = STp->restr_dma;
@@ -4375,12 +4376,12 @@
 		for (i = 0, b_size = 0; 
 		     i < STp->buffer->sg_segs && (b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE; 
 		     b_size += STp->buffer->sg[i++].length);
-		STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size);
+		STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
 #if DEBUG
 		printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev,
-			STp->buffer->b_data, STp->buffer->sg[0].address);
+			STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
 		printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev,
-			 STp->buffer->aux, i, STp->buffer->sg[i].address);
+			 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
 #endif
 	} else
 		STp->buffer->aux = NULL; /* this had better never happen! */
@@ -4933,15 +4934,14 @@
 		     b_size *= 2,                 order++ );
 
 		for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
-			tb->sg[0].address =
-			    (unsigned char *)__get_free_pages(priority, order);
-			if (tb->sg[0].address != NULL) {
-			    tb->sg[0].page = NULL;
+			tb->sg[0].page = alloc_pages(priority, order);
+			tb->sg[0].offset = 0;
+			if (tb->sg[0].page != NULL) {
 			    tb->sg[0].length = b_size;
 			    break;
 			}
 		}
-		if (tb->sg[segs].address == NULL) {
+		if (tb->sg[segs].page == NULL) {
 			kfree(tb);
 			tb = NULL;
 		}
@@ -4953,9 +4953,9 @@
 
 			for (segs=1, got=tb->sg[0].length;
 			     got < osst_buffer_size && segs < OSST_FIRST_SG; ) {
-			    tb->sg[segs].address =
-				(unsigned char *)__get_free_pages(priority, order);
-			    if (tb->sg[segs].address == NULL) {
+			    tb->sg[segs].page = alloc_pages(priority, order);
+			    tb->sg[segs].offset = 0;
+			    if (tb->sg[segs].page == NULL) {
 				if (osst_buffer_size - got <=
 				    (OSST_FIRST_SG - segs) * b_size / 2) {
 				    b_size /= 2; /* Large enough for the rest of the buffers */
@@ -4985,7 +4985,7 @@
 		return NULL;
 	}
 	tb->sg_segs = tb->orig_sg_segs = segs;
-	tb->b_data = tb->sg[0].address;
+	tb->b_data = page_address(tb->sg[0].page);
 
 #if DEBUG
 	if (debugging) {
@@ -5030,9 +5030,9 @@
 
 	for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
 	     segs < max_segs && got < new_size; ) {
-		STbuffer->sg[segs].address =
-			  (unsigned char *)__get_free_pages(priority, order);
-		if (STbuffer->sg[segs].address == NULL) {
+		STbuffer->sg[segs].page = alloc_pages(priority, order);
+		STbuffer->sg[segs].offset = 0;
+		if (STbuffer->sg[segs].page == NULL) {
 			if (new_size - got <= (max_segs - segs) * b_size / 2) {
 				b_size /= 2;  /* Large enough for the rest of the buffers */
 				order--;
@@ -5080,7 +5080,7 @@
 		     b_size < STbuffer->sg[i].length;
 		     b_size *= 2, order++);
 
-		free_pages((unsigned long)STbuffer->sg[i].address, order);
+		__free_pages(STbuffer->sg[i].page, order);
 		STbuffer->buffer_size -= STbuffer->sg[i].length;
 	}
 #if DEBUG
@@ -5108,7 +5108,7 @@
 	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		      st_bp->sg[i].length - offset : do_count;
-		res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
+		res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
@@ -5141,7 +5141,7 @@
 	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		      st_bp->sg[i].length - offset : do_count;
-		res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
+		res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
@@ -5174,7 +5174,7 @@
 	     i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		      st_bp->sg[i].length - offset : do_count ;
-		memset(st_bp->sg[i].address + offset, 0, cnt);
+		memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
 		do_count -= cnt;
 		offset = 0;
 	}
@@ -5194,7 +5194,7 @@
 	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length < do_count ?
 		      st_bp->sg[i].length : do_count ;
-		memcpy(st_bp->sg[i].address, ptr, cnt);
+		memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
 		do_count -= cnt;
 		ptr      += cnt;
 	}
@@ -5215,7 +5215,7 @@
 	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length < do_count ?
 		      st_bp->sg[i].length : do_count ;
-		memcpy(ptr, st_bp->sg[i].address, cnt);
+		memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
 		do_count -= cnt;
 		ptr      += cnt;
 	}
@@ -5407,7 +5407,7 @@
 #endif
 
 	tpnt->device = SDp;
-	tpnt->devt = MKDEV(MAJOR_NR, i);
+	tpnt->devt = mk_kdev(MAJOR_NR, i);
 	tpnt->dirty = 0;
 	tpnt->in_use = 0;
 	tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
--- a/drivers/scsi/pci2220i.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/scsi/pci2220i.c	Sun Feb 10 19:58:03 2002
@@ -34,6 +34,8 @@
  *
  ****************************************************************************/
 
+#error Convert me to understand page+offset based scatterlists
+
 //#define DEBUG 1
 
 #include <linux/module.h>
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/qla1280.c	Sun Feb 10 19:58:06 2002
@@ -182,6 +182,7 @@
     -   Initial Beta Release.  
 *****************************************************************************/
 
+#error Please convert me to Documentation/DMA-mapping.txt
 
 #ifdef MODULE
 #include <linux/module.h>
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/scsi.c	Sun Feb 10 19:58:06 2002
@@ -87,13 +87,16 @@
 
 struct scsi_host_sg_pool {
 	int size;
+	char *name; 
 	kmem_cache_t *slab;
 	mempool_t *pool;
 };
 
-static const int scsi_host_sg_pool_sizes[SG_MEMPOOL_NR] = { 8, 16, 32, 64, MAX_PHYS_SEGMENTS };
-struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR];
-
+#define SP(x) { x, "sgpool-" #x } 
+struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR] = { 
+	SP(8), SP(16), SP(32), SP(64), SP(MAX_PHYS_SEGMENTS)
+}; 	
+#undef SP 	
 /*
    static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/scsi.c,v 1.38 1997/01/19 23:07:18 davem Exp $";
  */
@@ -2489,7 +2492,6 @@
 static int __init init_scsi(void)
 {
 	struct proc_dir_entry *generic;
-	char name[16];
 	int i;
 
 	printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
@@ -2499,18 +2501,15 @@
 	 */
 	for (i = 0; i < SG_MEMPOOL_NR; i++) {
 		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
-		int size = scsi_host_sg_pool_sizes[i] * sizeof(struct scatterlist);
+		int size = sgp->size * sizeof(struct scatterlist);
 
-		snprintf(name, sizeof(name) - 1, "sgpool-%d", scsi_host_sg_pool_sizes[i]);
-		sgp->slab = kmem_cache_create(name, size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+		sgp->slab = kmem_cache_create(sgp->name, size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 		if (!sgp->slab)
 			panic("SCSI: can't init sg slab\n");
 
 		sgp->pool = mempool_create(SG_MEMPOOL_SIZE, scsi_pool_alloc, scsi_pool_free, sgp->slab);
 		if (!sgp->pool)
 			panic("SCSI: can't init sg mempool\n");
-
-		sgp->size = size;
 	}
 
 	/*
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/scsi.h	Sun Feb 10 19:58:05 2002
@@ -734,7 +734,6 @@
 
 	struct timer_list eh_timeout;	/* Used to time out the command. */
 	void *request_buffer;		/* Actual requested buffer */
-        void **bounce_buffers;		/* Array of bounce buffers when using scatter-gather */
 
 	/* These elements define the operation we ultimately want to perform */
 	unsigned char data_cmnd[MAX_COMMAND_SIZE];
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/scsi_lib.c	Sun Feb 10 19:58:06 2002
@@ -450,18 +450,8 @@
 	 */
 	if (SCpnt->use_sg) {
 		struct scatterlist *sgpnt;
-		void **bbpnt;
-		int i;
 
 		sgpnt = (struct scatterlist *) SCpnt->request_buffer;
-		bbpnt = SCpnt->bounce_buffers;
-
-		if (bbpnt) {
-			for (i = 0; i < SCpnt->use_sg; i++) {
-				if (bbpnt[i])
-					kfree(sgpnt[i].address);
-			}
-		}
 		scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len);
 	} else {
 		if (SCpnt->request_buffer != req->buffer)
@@ -525,24 +515,8 @@
 	 */
 	if (SCpnt->use_sg) {
 		struct scatterlist *sgpnt;
-		void **bbpnt;
-		int i;
 
 		sgpnt = (struct scatterlist *) SCpnt->buffer;
-		bbpnt = SCpnt->bounce_buffers;
-
-		if (bbpnt) {
-			for (i = 0; i < SCpnt->use_sg; i++) {
-				if (bbpnt[i]) {
-					if (rq_data_dir(req) == READ) {
-						memcpy(bbpnt[i],
-						       sgpnt[i].address,
-						       sgpnt[i].length);
-					}
-					kfree(sgpnt[i].address);
-				}
-			}
-		}
 		scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len);
 	} else {
 		if (SCpnt->buffer != req->buffer) {
diff -Nru a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
--- a/drivers/scsi/scsiiom.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/scsiiom.c	Sun Feb 10 19:58:04 2002
@@ -6,6 +6,8 @@
  ***********************************************************************/
 /* $Id: scsiiom.c,v 2.55.2.17 2000/12/20 00:39:37 garloff Exp $ */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 static void __inline__
 dc390_freetag (PDCB pDCB, PSRB pSRB)
 {
diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
--- a/drivers/scsi/seagate.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/seagate.c	Sun Feb 10 19:58:06 2002
@@ -1061,8 +1061,9 @@
 				     hostno, nobuffs);
 				for (i = 0; i < nobuffs; ++i)
 					printk
-					    ("scsi%d : buffer %d address = %08x length = %d\n",
-					     hostno, i, buffer[i].address,
+					    ("scsi%d : buffer %d address = %p length = %d\n",
+					     hostno, i,
+					     page_address(buffer[i].page) + buffer[i].offset,
 					     buffer[i].length);
 			}
 #endif
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/sg.c	Sun Feb 10 19:58:06 2002
@@ -76,8 +76,6 @@
 #include <linux/version.h>
 #endif /* LINUX_VERSION_CODE */
 
-#define SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
-
 #define SG_ALLOW_DIO_DEF 0
 #define SG_ALLOW_DIO_CODE	/* compile out be commenting this define */
 #ifdef SG_ALLOW_DIO_CODE
@@ -1714,9 +1712,6 @@
 						rem_sz;
 	sclp->page = kp->maplist[k];
 	sclp->offset = offset;
-#ifdef SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
-	sclp->address = page_address(kp->maplist[k]) + offset;
-#endif
 	sclp->length = num;
 	mem_src_arr[k] = SG_USER_MEM;
 	rem_sz -= num;
@@ -1804,9 +1799,6 @@
             }
             sclp->page = virt_to_page(p);
             sclp->offset = (unsigned long)p & ~PAGE_MASK;
-#ifdef SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
-            sclp->address = p;
-#endif
             sclp->length = ret_sz;
 	    mem_src_arr[k] = mem_src;
 
@@ -1967,9 +1959,6 @@
             sg_free(sg_scatg2virt(sclp), sclp->length, mem_src);
 	    sclp->page = NULL;
             sclp->offset = 0;
-#ifdef SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
-	    sclp->address = 0;
-#endif
             sclp->length = 0;
         }
 	sg_free(schp->buffer, schp->sglist_len, schp->buffer_mem_src);
diff -Nru a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
--- a/drivers/scsi/sgiwd93.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/sgiwd93.c	Sun Feb 10 19:58:06 2002
@@ -120,9 +120,13 @@
 #endif
 		for(i = 0; i <= cmd->SCp.buffers_residual; i++) {
 #ifdef DEBUG_DMA
-			printk("[%p,%d]", slp[i].address, slp[i].length);
-#endif
-			fill_hpc_entries (&hcp, slp[i].address, slp[i].length);
+			printk("[%p,%d]",
+			       page_address(slp[i].page) + slp[i].offset,
+			       slp[i].length);
+#endif
+			fill_hpc_entries (&hcp,
+					  page_address(slp[i].page) + slp[i].offset,
+					  slp[i].length);
 			totlen += slp[i].length;
 		}
 #ifdef DEBUG_DMA
@@ -227,7 +231,7 @@
 		}
 		SCpnt->SCp.buffer = &slp[i];
 		SCpnt->SCp.buffers_residual = SCpnt->SCp.buffers_residual - i;
-		SCpnt->SCp.ptr = (char *) slp[i].address;
+		SCpnt->SCp.ptr = (char *) page_address(slp[i].page) + slp[i].offset;
 		SCpnt->SCp.this_residual = slp[i].length;
 	}
 #ifdef DEBUG_DMA
diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
--- a/drivers/scsi/sim710.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/scsi/sim710.c	Sun Feb 10 19:58:05 2002
@@ -572,11 +572,11 @@
     hostdata->running = NULL;
     memcpy (hostdata->script, SCRIPT, sizeof(SCRIPT));
     for (i = 0; i < PATCHES; i++)
-	hostdata->script[LABELPATCHES[i]] += virt_to_bus(hostdata->script);
+	hostdata->script[LABELPATCHES[i]] += isa_virt_to_bus(hostdata->script);
     patch_abs_32 (hostdata->script, 0, reselected_identify, 
-    	virt_to_bus((void *)&(hostdata->reselected_identify)));
+    	isa_virt_to_bus((void *)&(hostdata->reselected_identify)));
     patch_abs_32 (hostdata->script, 0, msgin_buf, 
-    	virt_to_bus((void *)&(hostdata->msgin_buf[0])));
+    	isa_virt_to_bus((void *)&(hostdata->msgin_buf[0])));
     hostdata->state = STATE_INITIALISED;
     hostdata->negotiate = 0xff;
 }
@@ -670,7 +670,7 @@
     struct sim710_target *targdata = hostdata->target + cmd->target;
     u32 resume_offset = 0, index;
 
-    index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
+    index = (u32)((u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
 
     switch (index) {
     case Ent_wait_disc_complete/4 + 2:
@@ -717,7 +717,7 @@
     unsigned char sbcl;
 
     sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
-    index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
+    index = (u32)((u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
 
     DEB(DEB_PMM, printk("scsi%d: Phase mismatch, phase %s (%x) at script[0x%x]\n",
 	host->host_no, sbcl_to_phase(sbcl), sbcl, index));
@@ -754,7 +754,7 @@
 
 	sg_id = (index - Ent_patch_input_data/4 - 4) / 2;
 	targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
-		virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_id * 2 + 2);
+		isa_virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_id * 2 + 2);
 	olen  = targdata->dsa[DSA_DATAIN + sg_id * 2];
 	oaddr = targdata->dsa[DSA_DATAIN + sg_id * 2 + 1];
 	residual = datapath_residual (host);
@@ -783,7 +783,7 @@
 
 	sg_id = (index - Ent_patch_output_data/4 - 4) / 2;
 	targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
-		virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_id * 2 + 2);
+		isa_virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_id * 2 + 2);
 	olen  = targdata->dsa[DSA_DATAOUT + sg_id * 2];
 	oaddr = targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1];
 	residual = datapath_residual (host);
@@ -860,7 +860,7 @@
     case A_int_reselected:
 	hostdata->script[Ent_patch_output_data/4+1] = targdata->data_out_jump;
 	hostdata->script[Ent_patch_input_data/4+1] = targdata->data_in_jump;
-	NCR_write32(DSA_REG, virt_to_bus(targdata->dsa));
+	NCR_write32(DSA_REG, isa_virt_to_bus(targdata->dsa));
 	resume_offset = targdata->resume_offset;
 	break;
     case A_int_data_bad_phase:
@@ -944,7 +944,7 @@
 	DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
 		"dstat %02x, dsp [%04x], scratch %02x\n",
 	    host->host_no, sim710_intrs, istat, sstat0, dstat,
-	    (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
+	    (u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
 	    NCR_read32(SCRATCH_REG)));
 	if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) {
 	    /* Reselected.  Identify the target from LCRC_REG, and
@@ -991,7 +991,7 @@
 	    printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
 		"dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n",
 		host->host_no, sim710_intrs, istat, sstat0, dstat,
-		(u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
+		(u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
 		NCR_read32(SCRATCH_REG), dsps);
 	    /* resume_offset is zero, which will cause a host reset */
 	}
@@ -1044,7 +1044,7 @@
 #ifdef DEBUG_LIMIT_INTS
 	if (sim710_intrs < DEBUG_LIMIT_INTS)
 #endif
-	NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4));
+	NCR_write32(DSP_REG, isa_virt_to_bus(hostdata->script+resume_offset/4));
 	if (resume_offset == Ent_reselect)
 	    run_process_issue_queue(hostdata);
     }
@@ -1122,48 +1122,47 @@
     targdata->dsa_status[0] = 0xff;
 
     targdata->dsa[DSA_SELECT]		= (1 << cmd->target) << 16;
-    targdata->dsa[DSA_MSGOUT+1]		= virt_to_bus(targdata->dsa_msgout);
+    targdata->dsa[DSA_MSGOUT+1]		= isa_virt_to_bus(targdata->dsa_msgout);
     targdata->dsa[DSA_CMND]		= cmd->cmd_len;
-    targdata->dsa[DSA_CMND+1]		= virt_to_bus(targdata->dsa_cdb);
+    targdata->dsa[DSA_CMND+1]		= isa_virt_to_bus(targdata->dsa_cdb);
     targdata->dsa[DSA_STATUS]		= 1;
-    targdata->dsa[DSA_STATUS+1]		= virt_to_bus(targdata->dsa_status);
+    targdata->dsa[DSA_STATUS+1]		= isa_virt_to_bus(targdata->dsa_status);
     targdata->dsa[DSA_MSGIN]		= 1;
-    targdata->dsa[DSA_MSGIN+1]		= virt_to_bus(targdata->dsa_msgin);
+    targdata->dsa[DSA_MSGIN+1]		= isa_virt_to_bus(targdata->dsa_msgin);
 
     sg_start = (MAX_SG - (cmd->use_sg ? cmd->use_sg : 1)) * 2;
     dip = targdata->dsa + DSA_DATAIN + sg_start;
     dop = targdata->dsa + DSA_DATAOUT + sg_start;
 
     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {
-	u32 vbuf = cmd->use_sg ?
-		(u32)(((struct scatterlist *)cmd->buffer)[i].address) :
-		(u32)(cmd->request_buffer);
-	u32 bbuf = virt_to_bus((void *)vbuf);
-	u32 cnt = cmd->use_sg ?
-		((struct scatterlist *)cmd->buffer)[i].length :
-		cmd->request_bufflen;
+	struct scatterlist *sgl = &((struct scatterlist *)cmd->buffer)[i];
+	void *vbuf = cmd->use_sg ?
+		(page_address(sgl->page) + sgl->offset) :
+		(cmd->request_buffer);
+	u32 bbuf = isa_virt_to_bus(vbuf);
+	u32 cnt = cmd->use_sg ? sgl->length : cmd->request_bufflen;
 
 	if (datain) {
 #ifdef CONFIG_TP34V_SCSI
-	    cache_clear(virt_to_phys((void *)vbuf), cnt);
+	    cache_clear(virt_to_phys(vbuf, cnt);
 #endif
 	    *dip++	= cnt;
 	    *dip++	= bbuf;
 	}
 	if (dataout) {
 #ifdef CONFIG_TP34V_SCSI
-	    cache_push(virt_to_phys((void *)vbuf), cnt);
+	    cache_push(virt_to_phys(vbuf, cnt);
 #endif
 	    *dop++	= cnt;
 	    *dop++	= bbuf;
 	}
     }
     targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
-	virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);
+	isa_virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);
     targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
-	virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);
+	isa_virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);
 
-    for (i = 0, dsa = virt_to_bus(targdata->dsa); i < 4; i++) {
+    for (i = 0, dsa = isa_virt_to_bus(targdata->dsa); i < 4; i++) {
 	u32 v = hostdata->script[Ent_patch_new_dsa/4 + i * 2];
 
 	v &= ~0x0000ff00;
@@ -1508,7 +1507,7 @@
 #endif
 	    chips++;
 	}
-	NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
+	NCR_write32(DSP_REG, isa_virt_to_bus(hostdata->script+Ent_reselect/4));
 	hostdata->state = STATE_IDLE;
     }
     return chips;
@@ -1562,7 +1561,7 @@
     ncr_halt(host);
     printk("scsi%d: dsp = %08x (script[0x%04x]), scratch = %08x\n",
 	host->host_no, NCR_read32(DSP_REG),
-	((u32)bus_to_virt(NCR_read32(DSP_REG)) - (u32)hostdata->script)/4,
+	((u32)isa_bus_to_virt(NCR_read32(DSP_REG)) - (u32)hostdata->script)/4,
 	NCR_read32(SCRATCH_REG));
 
     for (target = 0; target < 7; target++) {
@@ -1578,7 +1577,7 @@
     sim710_soft_reset(host);
     sim710_driver_init(host);
 
-    NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
+    NCR_write32(DSP_REG, isa_virt_to_bus(hostdata->script+Ent_reselect/4));
     hostdata->state = STATE_IDLE;
 
     run_process_issue_queue(hostdata);
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/scsi/st.c	Sun Feb 10 19:58:04 2002
@@ -3404,15 +3404,14 @@
 		     order++, b_size *= 2)
 			;
 		for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
-			tb->sg[0].address =
-			    (unsigned char *) __get_free_pages(priority, order);
-			if (tb->sg[0].address != NULL) {
+			tb->sg[0].page = alloc_pages(priority, order);
+			tb->sg[0].offset = 0;
+			if (tb->sg[0].page != NULL) {
 				tb->sg[0].length = b_size;
 				break;
 			}
 		}
-		tb->sg[0].page = NULL;
-		if (tb->sg[segs].address == NULL) {
+		if (tb->sg[segs].page == NULL) {
 			kfree(tb);
 			tb = NULL;
 		} else {	/* Got something, continue */
@@ -3424,10 +3423,9 @@
 				;
 			for (segs = 1, got = tb->sg[0].length;
 			     got < st_buffer_size && segs < ST_FIRST_SG;) {
-				tb->sg[segs].address =
-					(unsigned char *) __get_free_pages(priority,
-									   order);
-				if (tb->sg[segs].address == NULL) {
+				tb->sg[segs].page = alloc_pages(priority, order);
+				tb->sg[segs].offset = 0;
+				if (tb->sg[segs].page == NULL) {
 					if (st_buffer_size - got <=
 					    (ST_FIRST_SG - segs) * b_size / 2) {
 						b_size /= 2; /* Large enough for the
@@ -3443,7 +3441,6 @@
 					tb = NULL;
 					break;
 				}
-				tb->sg[segs].page = NULL;
 				tb->sg[segs].length = b_size;
 				got += b_size;
 				segs++;
@@ -3457,7 +3454,7 @@
 		return NULL;
 	}
 	tb->sg_segs = tb->orig_sg_segs = segs;
-	tb->b_data = tb->sg[0].address;
+	tb->b_data = page_address(tb->sg[0].page);
 
         DEBC(printk(ST_DEB_MSG
                     "st: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
@@ -3503,9 +3500,9 @@
 
 	for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size;
 	     segs < max_segs && got < new_size;) {
-		STbuffer->sg[segs].address =
-			(unsigned char *) __get_free_pages(priority, order);
-		if (STbuffer->sg[segs].address == NULL) {
+		STbuffer->sg[segs].page = alloc_pages(priority, order);
+		STbuffer->sg[segs].offset = 0;
+		if (STbuffer->sg[segs].page == NULL) {
 			if (new_size - got <= (max_segs - segs) * b_size / 2) {
 				b_size /= 2; /* Large enough for the rest of the buffers */
 				order--;
@@ -3517,7 +3514,6 @@
 			normalize_buffer(STbuffer);
 			return FALSE;
 		}
-		STbuffer->sg[segs].page = NULL;
 		STbuffer->sg[segs].length = b_size;
 		STbuffer->sg_segs += 1;
 		got += b_size;
@@ -3541,13 +3537,13 @@
 		for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length;
 		     order++, b_size *= 2)
 			; /* empty */
-		free_pages((unsigned long)(STbuffer->sg[i].address), order);
+		__free_pages(STbuffer->sg[i].page, order);
 		STbuffer->buffer_size -= STbuffer->sg[i].length;
 	}
         DEB(
 	if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
 		printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d).\n",
-		       STbuffer->sg[0].address, STbuffer->buffer_size,
+		       page_address(STbuffer->sg[0].page), STbuffer->buffer_size,
 		       STbuffer->sg_segs);
         ) /* end DEB */
 	STbuffer->sg_segs = STbuffer->orig_sg_segs;
@@ -3570,7 +3566,7 @@
 	for (; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		    st_bp->sg[i].length - offset : do_count;
-		res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
+		res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
@@ -3603,7 +3599,7 @@
 	for (; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		    st_bp->sg[i].length - offset : do_count;
-		res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
+		res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
--- a/drivers/scsi/ultrastor.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/scsi/ultrastor.c	Sun Feb 10 19:58:03 2002
@@ -667,12 +667,12 @@
 	sl = (struct scatterlist *) SCpnt->request_buffer;
 	max = SCpnt->use_sg;
 	for (i = 0; i < max; i++) {
-		mscp->sglist[i].address = virt_to_bus(sl[i].address);
+		mscp->sglist[i].address = isa_page_to_bus(sl[i].page) + sl[i].offset;
 		mscp->sglist[i].num_bytes = sl[i].length;
 		transfer_length += sl[i].length;
 	}
 	mscp->number_of_sg_list = max;
-	mscp->transfer_data = virt_to_bus(mscp->sglist);
+	mscp->transfer_data = isa_virt_to_bus(mscp->sglist);
 	/* ??? May not be necessary.  Docs are unclear as to whether transfer
 	   length field is ignored or whether it should be set to the total
 	   number of bytes of the transfer.  */
@@ -728,7 +728,7 @@
     } else {
 	/* Unset scatter/gather flag in SCSI command packet */
 	my_mscp->sg = FALSE;
-	my_mscp->transfer_data = virt_to_bus(SCpnt->request_buffer);
+	my_mscp->transfer_data = isa_virt_to_bus(SCpnt->request_buffer);
 	my_mscp->transfer_data_length = SCpnt->request_bufflen;
     }
     my_mscp->command_link = 0;		/*???*/
@@ -738,7 +738,7 @@
     memcpy(my_mscp->scsi_cdbs, SCpnt->cmnd, my_mscp->length_of_scsi_cdbs);
     my_mscp->adapter_status = 0;
     my_mscp->target_status = 0;
-    my_mscp->sense_data = virt_to_bus(&SCpnt->sense_buffer);
+    my_mscp->sense_data = isa_virt_to_bus(&SCpnt->sense_buffer);
     my_mscp->done = done;
     my_mscp->SCint = SCpnt;
     SCpnt->host_scribble = (unsigned char *)my_mscp;
@@ -796,7 +796,7 @@
     }
 
     /* Store pointer in OGM address bytes */
-    outl(virt_to_bus(my_mscp), config.ogm_address);
+    outl(isa_virt_to_bus(my_mscp), config.ogm_address);
 
     /* Issue OGM interrupt */
     if (config.slot) {
@@ -872,9 +872,9 @@
 	out[28 + i * 3] = '\n';
 	out[29 + i * 3] = 0;
 	ogm_status = inb(port0 + 22);
-	ogm_addr = (unsigned int)bus_to_virt(inl(port0 + 23));
+	ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23));
 	icm_status = inb(port0 + 27);
-	icm_addr = (unsigned int)bus_to_virt(inl(port0 + 28));
+	icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28));
 	restore_flags(flags);
       }
 
@@ -910,7 +910,7 @@
 
 	save_flags(flags);
 	cli();
-	outl(virt_to_bus(&config.mscp[mscp_index]), config.ogm_address);
+	outl(isa_virt_to_bus(&config.mscp[mscp_index]), config.ogm_address);
 	inb(0xc80);	/* delay */
 	outb(0x80, config.ogm_address - 1);
 	outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address));
@@ -1043,7 +1043,7 @@
 #if ULTRASTOR_MAX_CMDS == 1
     mscp = &config.mscp[0];
 #else
-    mscp = (struct mscp *)bus_to_virt(inl(config.icm_address));
+    mscp = (struct mscp *)isa_bus_to_virt(inl(config.icm_address));
     mscp_index = mscp - config.mscp;
     if (mscp_index >= ULTRASTOR_MAX_CMDS) {
 	printk("Ux4F interrupt: bad MSCP address %x\n", (unsigned int) mscp);
diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
--- a/drivers/scsi/wd7000.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/scsi/wd7000.c	Sun Feb 10 19:58:06 2002
@@ -1111,7 +1111,7 @@
 		return;
 	    }
 	    /* Aaaargh! (Zaga) */
-	    scb = bus_to_virt(scsi2int ((unchar *) icmbs[icmb].scbptr));
+	    scb = isa_bus_to_virt(scsi2int ((unchar *) icmbs[icmb].scbptr));
 	    icmbs[icmb].status = 0;
 	    if (!(scb->op & ICB_OP_MASK)) {	/* an SCB is done */
 		SCpnt = scb->SCpnt;
@@ -1187,13 +1187,14 @@
 	any2scsi (scb->maxlen, SCpnt->use_sg * sizeof (Sgb));
 
 	for (i = 0; i < SCpnt->use_sg; i++) {
-	    any2scsi (sgb[i].ptr, (int) sg[i].address);
+	    any2scsi (sgb[i].ptr,
+		      isa_page_to_bus(sg[i].page) + sg[i].offset);
 	    any2scsi (sgb[i].len, sg[i].length);
 	}
     }
     else {
 	scb->op = 0;
-	any2scsi (scb->dataptr, (int) SCpnt->request_buffer);
+	any2scsi (scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer));
 	any2scsi (scb->maxlen, SCpnt->request_bufflen);
     }
 
diff -Nru a/drivers/sound/Config.in b/drivers/sound/Config.in
--- a/drivers/sound/Config.in	Sun Feb 10 19:58:04 2002
+++ b/drivers/sound/Config.in	Sun Feb 10 19:58:04 2002
@@ -34,14 +34,14 @@
 dep_mbool    '    Creative SBLive! MIDI' CONFIG_MIDI_EMU10K1 $CONFIG_SOUND_EMU10K1 $CONFIG_EXPERIMENTAL
 dep_tristate '  Crystal SoundFusion (CS4280/461x)' CONFIG_SOUND_FUSION $CONFIG_SOUND
 dep_tristate '  Crystal Sound CS4281' CONFIG_SOUND_CS4281 $CONFIG_SOUND
-dep_tristate '  Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND $CONFIG_PCI
-dep_tristate '  Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND $CONFIG_PCI
-dep_tristate '  ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND
+dep_tristate '  Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND $CONFIG_PCI $CONFIG_SOUND_GAMEPORT
+dep_tristate '  Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND $CONFIG_PCI $CONFIG_SOUND_GAMEPORT
+dep_tristate '  ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND $CONFIG_SOUND_GAMEPORT
 dep_tristate '  ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
 dep_tristate '  ESS Maestro3/Allegro driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO3 $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL
 dep_tristate '  Intel ICH (i8xx) audio support' CONFIG_SOUND_ICH $CONFIG_PCI
 dep_tristate '  RME Hammerfall (RME96XX) support' CONFIG_SOUND_RME96XX $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL
-dep_tristate '  S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
+dep_tristate '  S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND $CONFIG_SOUND_GAMEPORT
 if [ "$CONFIG_VISWS" = "y" ]; then
     dep_tristate '  SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND
 fi
diff -Nru a/drivers/sound/cs4281/cs4281m.c b/drivers/sound/cs4281/cs4281m.c
--- a/drivers/sound/cs4281/cs4281m.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/sound/cs4281/cs4281m.c	Sun Feb 10 19:58:06 2002
@@ -75,6 +75,7 @@
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
+#include <linux/fs.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 //#include "cs_dm.h"
diff -Nru a/drivers/sound/ite8172.c b/drivers/sound/ite8172.c
--- a/drivers/sound/ite8172.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/sound/ite8172.c	Sun Feb 10 19:58:05 2002
@@ -824,12 +824,6 @@
 
 /* --------------------------------------------------------------------- */
 
-static loff_t it8172_llseek(struct file *file, loff_t offset, int origin)
-{
-    return -ESPIPE;
-}
-
-
 static int it8172_open_mixdev(struct inode *inode, struct file *file)
 {
     int minor = MINOR(inode->i_rdev);
@@ -870,7 +864,7 @@
 
 static /*const*/ struct file_operations it8172_mixer_fops = {
     owner:	THIS_MODULE,
-    llseek:	it8172_llseek,
+    llseek:	no_llseek,
     ioctl:	it8172_ioctl_mixdev,
     open:	it8172_open_mixdev,
     release:	it8172_release_mixdev,
@@ -1633,7 +1627,7 @@
 
 static /*const*/ struct file_operations it8172_audio_fops = {
     owner:	THIS_MODULE,
-    llseek:	it8172_llseek,
+    llseek:	no_llseek,
     read:	it8172_read,
     write:	it8172_write,
     poll:	it8172_poll,
diff -Nru a/drivers/sound/nec_vrc5477.c b/drivers/sound/nec_vrc5477.c
--- a/drivers/sound/nec_vrc5477.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/sound/nec_vrc5477.c	Sun Feb 10 19:58:05 2002
@@ -805,12 +805,6 @@
 
 /* --------------------------------------------------------------------- */
 
-static loff_t vrc5477_ac97_llseek(struct file *file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-
-
 static int vrc5477_ac97_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
@@ -852,7 +846,7 @@
 
 static /*const*/ struct file_operations vrc5477_ac97_mixer_fops = {
 	owner:		THIS_MODULE,
-	llseek:		vrc5477_ac97_llseek,
+	llseek:		no_llseek,
 	ioctl:		vrc5477_ac97_ioctl_mixdev,
 	open:		vrc5477_ac97_open_mixdev,
 	release:	vrc5477_ac97_release_mixdev,
@@ -1618,7 +1612,7 @@
 
 static /*const*/ struct file_operations vrc5477_ac97_audio_fops = {
 	owner:	THIS_MODULE,
-	llseek:		vrc5477_ac97_llseek,
+	llseek:		no_llseek,
 	read:		vrc5477_ac97_read,
 	write:		vrc5477_ac97_write,
 	poll:		vrc5477_ac97_poll,
diff -Nru a/drivers/sound/opl3sa2.c b/drivers/sound/opl3sa2.c
--- a/drivers/sound/opl3sa2.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/sound/opl3sa2.c	Sun Feb 10 19:58:03 2002
@@ -55,6 +55,7 @@
  *                         sb_card.c and awe_wave.c. (Dec 12, 2000)
  * Scott Murray            Some small cleanups to the init code output.
  *                         (Jan 7, 2001)
+ * Zwane Mwaikambo	   Added PM support. (Dec 4 2001)
  *
  */
 
@@ -62,13 +63,15 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/isapnp.h>
-
+#include <linux/delay.h>
+#include <linux/pm.h>
 #include "sound_config.h"
 
 #include "ad1848.h"
 #include "mpu401.h"
 
 /* Useful control port indexes: */
+#define OPL3SA2_PM	     0x01
 #define OPL3SA2_SYS_CTRL     0x02
 #define OPL3SA2_IRQ_CONFIG   0x03
 #define OPL3SA2_DMA_CONFIG   0x06
@@ -86,6 +89,11 @@
 #define DEFAULT_MIC    50
 #define DEFAULT_TIMBRE 0
 
+/* Power saving modes */
+#define OPL3SA2_PM_MODE1	0x05
+#define OPL3SA2_PM_MODE2	0x04
+#define OPL3SA2_PM_MODE3	0x03
+
 /* For checking against what the card returns: */
 #define VERSION_UNKNOWN 0
 #define VERSION_YMF711  1
@@ -121,6 +129,10 @@
 typedef struct opl3sa2_mixerdata_tag {
 	unsigned short cfg_port;
 	unsigned short padding;
+	unsigned char  reg;
+	unsigned int   in_suspend;
+	struct pm_dev  *pmdev;
+	unsigned int   card;
 	unsigned int   volume_l;
 	unsigned int   volume_r;
 	unsigned int   mic;
@@ -328,6 +340,20 @@
 }
 
 
+static void opl3sa2_mixer_restore(opl3sa2_mixerdata* devc, int card)
+{
+	if (devc) {
+		opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
+		opl3sa2_set_mic(devc, devc->mic);
+
+		if (chipset[card] == CHIPSET_OPL3SA3) {
+			opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);
+			opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);
+		}
+	}
+}
+
+
 static inline void arg_to_vol_mono(unsigned int vol, int* value)
 {
 	int left;
@@ -892,6 +918,77 @@
 
 /* End of component functions */
 
+/* Power Management support functions */
+static int opl3sa2_suspend(struct pm_dev *pdev, unsigned char pm_mode)
+{
+	unsigned long flags;
+	opl3sa2_mixerdata *p;
+
+	if (!pdev)
+		return -EINVAL;
+
+	save_flags(flags);
+	cli();
+
+	p = (opl3sa2_mixerdata *) pdev->data;
+	p->in_suspend = 1;
+	switch (pm_mode) {
+	case 1:
+		pm_mode = OPL3SA2_PM_MODE1;
+		break;
+	case 2:
+		pm_mode = OPL3SA2_PM_MODE2;
+		break;
+	case 3:
+		pm_mode = OPL3SA2_PM_MODE3;
+		break;
+	default:
+		pm_mode = OPL3SA2_PM_MODE3;
+		break;
+	}
+
+	/* its supposed to automute before suspending, so we wont bother */
+	opl3sa2_read(p->cfg_port, OPL3SA2_PM, &p->reg);
+	opl3sa2_write(p->cfg_port, OPL3SA2_PM, p->reg | pm_mode);
+
+	restore_flags(flags);
+	return 0;
+}
+
+static int opl3sa2_resume(struct pm_dev *pdev)
+{
+	unsigned long flags;
+	opl3sa2_mixerdata *p;
+
+	if (!pdev)
+		return -EINVAL;
+
+	p = (opl3sa2_mixerdata *) pdev->data;
+	save_flags(flags);
+	cli();
+
+	/* I don't think this is necessary */
+	opl3sa2_write(p->cfg_port, OPL3SA2_PM, p->reg);
+	opl3sa2_mixer_restore(p, p->card);
+	p->in_suspend = 0;
+
+	restore_flags(flags);
+	return 0;
+}
+
+static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
+{
+	unsigned char mode = (unsigned  char)data;
+
+	switch (rqst) {
+		case PM_SUSPEND:
+			return opl3sa2_suspend(pdev, mode);
+
+		case PM_RESUME:
+			return opl3sa2_resume(pdev);
+	}
+	return 0;
+}
 
 /*
  * Install OPL3-SA2 based card(s).
@@ -989,6 +1086,12 @@
 		attach_opl3sa2_mss(&cfg_mss[card]);
 		attach_opl3sa2_mixer(&cfg[card], card);
 
+		opl3sa2_data[card].card = card;
+		/* register our power management capabilities */
+		opl3sa2_data[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback);
+		if (opl3sa2_data[card].pmdev)
+			opl3sa2_data[card].pmdev->data = &opl3sa2_data[card];
+
 		/*
 		 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
 		 * it's supported.
@@ -1033,6 +1136,9 @@
 	int card;
 
 	for(card = 0; card < opl3sa2_cards_num; card++) {
+		if (opl3sa2_data[card].pmdev)
+			pm_unregister(opl3sa2_data[card].pmdev);
+
 	        if(cfg_mpu[card].slots[1] != -1) {
 			unload_opl3sa2_mpu(&cfg_mpu[card]);
 		}
diff -Nru a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c
--- a/drivers/sound/ymfpci.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/sound/ymfpci.c	Sun Feb 10 19:58:04 2002
@@ -55,6 +55,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff -Nru a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
--- a/drivers/telephony/phonedev.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/telephony/phonedev.c	Sun Feb 10 19:58:04 2002
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
diff -Nru a/drivers/usb/CDCEther.c b/drivers/usb/CDCEther.c
--- a/drivers/usb/CDCEther.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/CDCEther.c	Sun Feb 10 19:58:04 2002
@@ -132,7 +132,7 @@
 			
 	// Give this to the USB subsystem so it can tell us 
 	// when more data arrives.
-	if ( (res = usb_submit_urb(ether_dev->rx_urb)) ) {
+	if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) ) {
 		warn( __FUNCTION__ " failed submint rx_urb %d", res);
 	}
 	
@@ -302,7 +302,7 @@
 	ether_dev->tx_urb->transfer_buffer_length = count;
 	
 	// Send the URB on its merry way.
-	if ((res = usb_submit_urb(ether_dev->tx_urb)))  {
+	if ((res = usb_submit_urb(ether_dev->tx_urb, GFP_KERNEL)))  {
 		// Hmm...  It didn't go. Tell someone...
 		warn("failed tx_urb %d", res);
 		// update some stats...
@@ -350,7 +350,7 @@
 			read_bulk_callback, ether_dev );
 
 	// Put it out there so the device can send us stuff
-	if ( (res = usb_submit_urb(ether_dev->rx_urb)) )
+	if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) )
 	{
 		// Hmm...  Okay...
 		warn( __FUNCTION__ " failed rx_urb %d", res );
diff -Nru a/drivers/usb/Config.help b/drivers/usb/Config.help
--- a/drivers/usb/Config.help	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/Config.help	Sun Feb 10 19:58:05 2002
@@ -578,14 +578,14 @@
   Support for anything but the X6 is experimental.
   Please report failures and successes.
   The scanner will appear as a scsi generic device to the rest
-  of the system. Scsi support is required for this driver to compile
-  and work. SANE 1.0.4 or newer is needed to make use of your scanner.
-  This driver can be compiled as a module.
+  of the system. Scsi support is required.
+  This driver can be compiled as a module, called microtek.o.
 
 CONFIG_USB_HPUSBSCSI
   Say Y here if you want support for the HP 53xx series of scanners
   and the Minolta Scan Dual. This driver is experimental.
   The scanner will be accessible as a SCSI device.
+  This can be compiled as a module, called hpusbscsi.o.
 
 CONFIG_USB_BLUETOOTH
   Say Y here if you want to connect a USB Bluetooth device to your
diff -Nru a/drivers/usb/acm.c b/drivers/usb/acm.c
--- a/drivers/usb/acm.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/acm.c	Sun Feb 10 19:58:04 2002
@@ -57,6 +57,7 @@
 #include <linux/smp_lock.h>
 #undef DEBUG
 #include <linux/usb.h>
+#include <asm/byteorder.h>
 
 /*
  * Version Information
@@ -261,7 +262,7 @@
 	urb->actual_length = 0;
 	urb->dev = acm->dev;
 
-	if (usb_submit_urb(urb))
+	if (usb_submit_urb(urb, GFP_KERNEL))
 		dbg("failed resubmitting read urb");
 }
 
@@ -316,11 +317,11 @@
         unlock_kernel();
 
 	acm->ctrlurb.dev = acm->dev;
-	if (usb_submit_urb(&acm->ctrlurb))
+	if (usb_submit_urb(&acm->ctrlurb, GFP_KERNEL))
 		dbg("usb_submit_urb(ctrl irq) failed");
 
 	acm->readurb.dev = acm->dev;
-	if (usb_submit_urb(&acm->readurb))
+	if (usb_submit_urb(&acm->readurb, GFP_KERNEL))
 		dbg("usb_submit_urb(read bulk) failed");
 
 	acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
@@ -371,7 +372,7 @@
 	acm->writeurb.transfer_buffer_length = count;
 	acm->writeurb.dev = acm->dev;
 
-	if (usb_submit_urb(&acm->writeurb))
+	if (usb_submit_urb(&acm->writeurb, GFP_KERNEL))
 		dbg("usb_submit_urb(write bulk) failed");
 
 	return count;
diff -Nru a/drivers/usb/audio.c b/drivers/usb/audio.c
--- a/drivers/usb/audio.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/audio.c	Sun Feb 10 19:58:06 2002
@@ -917,7 +917,7 @@
 	if (!usbin_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbin_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == 0) {
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -982,7 +982,7 @@
 	if (!usbin_sync_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbin_sync_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == 0) {
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -1055,7 +1055,7 @@
 		urb->number_of_packets = DESCFRAMES;
 		urb->context = as;
 		urb->complete = usbin_completed;
-		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb))
+		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 			u->flags |= FLG_URB0RUNNING;
 		else
 			u->flags &= ~FLG_RUNNING;
@@ -1068,7 +1068,7 @@
 		urb->number_of_packets = DESCFRAMES;
 		urb->context = as;
 		urb->complete = usbin_completed;
-		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb))
+		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 			u->flags |= FLG_URB1RUNNING;
 		else
 			u->flags &= ~FLG_RUNNING;
@@ -1083,7 +1083,7 @@
 			urb->context = as;
 			urb->complete = usbin_sync_completed;
 			/* stride: u->syncinterval */
-			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 				u->flags |= FLG_SYNC0RUNNING;
 			else
 				u->flags &= ~FLG_RUNNING;
@@ -1097,7 +1097,7 @@
 			urb->context = as;
 			urb->complete = usbin_sync_completed;
 			/* stride: u->syncinterval */
-			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 				u->flags |= FLG_SYNC1RUNNING;
 			else
 				u->flags &= ~FLG_RUNNING;
@@ -1275,7 +1275,7 @@
 	if (!usbout_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbout_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == 0) {
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -1347,7 +1347,7 @@
 	if (!usbout_sync_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbout_sync_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == 0) {
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -1420,7 +1420,7 @@
 		urb->number_of_packets = DESCFRAMES;
 		urb->context = as;
 		urb->complete = usbout_completed;
-		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb))
+		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 			u->flags |= FLG_URB0RUNNING;
 		else
 			u->flags &= ~FLG_RUNNING;
@@ -1433,7 +1433,7 @@
 		urb->number_of_packets = DESCFRAMES;
 		urb->context = as;
 		urb->complete = usbout_completed;
-		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb))
+		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 			u->flags |= FLG_URB1RUNNING;
 		else
 			u->flags &= ~FLG_RUNNING;
@@ -1448,7 +1448,7 @@
 			urb->context = as;
 			urb->complete = usbout_sync_completed;
 			/* stride: u->syncinterval */
-			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 				u->flags |= FLG_SYNC0RUNNING;
 			else
 				u->flags &= ~FLG_RUNNING;
@@ -1462,7 +1462,7 @@
 			urb->context = as;
 			urb->complete = usbout_sync_completed;
 			/* stride: u->syncinterval */
-			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
 				u->flags |= FLG_SYNC1RUNNING;
 			else
 				u->flags &= ~FLG_RUNNING;
diff -Nru a/drivers/usb/auerswald.c b/drivers/usb/auerswald.c
--- a/drivers/usb/auerswald.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/auerswald.c	Sun Feb 10 19:58:05 2002
@@ -25,6 +25,7 @@
 
 /* Standard Linux module include files */
 #include <asm/uaccess.h>
+#include <asm/byteorder.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -49,7 +50,7 @@
 
 /*-------------------------------------------------------------------*/
 /* Version Information */
-#define DRIVER_VERSION "0.9.9"
+#define DRIVER_VERSION "0.9.11"
 #define DRIVER_AUTHOR  "Wolfgang Mües <wmues@nexgo.de>"
 #define DRIVER_DESC    "Auerswald PBX/System Telephone usb driver"
 
@@ -191,6 +192,13 @@
         struct list_head free_list;     /* list of available elements */
 } auerchain_t,*pauerchain_t;
 
+/* urb blocking completion helper struct */
+typedef struct
+{
+	wait_queue_head_t wqh;    	/* wait for completion */
+	unsigned int done;		/* completion flag */
+} auerchain_chs_t,*pauerchain_chs_t;
+
 /* ...................................................................*/
 /* buffer element */
 struct  auerbufctl;                     /* forward */
@@ -330,7 +338,7 @@
                 urb    = acep->urbp;
                 dbg ("auerchain_complete: submitting next urb from chain");
 		urb->status = 0;	/* needed! */
-		result = usb_submit_urb( urb);
+		result = usb_submit_urb(urb, GFP_KERNEL);
 
                 /* check for submit errors */
                 if (result) {
@@ -408,7 +416,7 @@
         if (acep) {
                 dbg("submitting urb immediate");
 		urb->status = 0;	/* needed! */
-                result = usb_submit_urb( urb);
+                result = usb_submit_urb(urb, GFP_KERNEL);
                 /* check for submit errors */
                 if (result) {
                         urb->status = result;
@@ -600,8 +608,10 @@
 /* completion handler for synchronous chained URBs */
 static void auerchain_blocking_completion (struct urb *urb)
 {
-	wait_queue_head_t *wakeup = (wait_queue_head_t *)urb->context;
-	wake_up (wakeup);
+	pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
+	pchs->done = 1;
+	wmb();
+	wake_up (&pchs->wqh);
 }
 
 
@@ -609,36 +619,43 @@
 static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length)
 {
 	DECLARE_WAITQUEUE (wait, current);
-	DECLARE_WAIT_QUEUE_HEAD (wqh);
+	auerchain_chs_t chs;
 	int status;
 
 	dbg ("auerchain_start_wait_urb called");
-	init_waitqueue_head (&wqh);
-	current->state = TASK_INTERRUPTIBLE;
-	add_wait_queue (&wqh, &wait);
-	urb->context = &wqh;
-	status = auerchain_submit_urb ( acp, urb);
+	init_waitqueue_head (&chs.wqh);
+	chs.done = 0;
+
+	set_current_state (TASK_UNINTERRUPTIBLE);
+	add_wait_queue (&chs.wqh, &wait);
+	urb->context = &chs;
+	status = auerchain_submit_urb (acp, urb);
 	if (status) {
 		/* something went wrong */
-		current->state = TASK_RUNNING;
-		remove_wait_queue (&wqh, &wait);
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&chs.wqh, &wait);
 		return status;
 	}
 
-	if (urb->status == -EINPROGRESS) {
-		while (timeout && urb->status == -EINPROGRESS)
-			status = timeout = schedule_timeout (timeout);
-	} else
-		status = 1;
-
-	current->state = TASK_RUNNING;
-	remove_wait_queue (&wqh, &wait);
+	while (timeout && !chs.done)
+	{
+		timeout = schedule_timeout (timeout);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		rmb();
+	}
 
-	if (!status) {
-		/* timeout */
-		dbg ("auerchain_start_wait_urb: timeout");
-		auerchain_unlink_urb (acp, urb);  /* remove urb safely */
-		status = -ETIMEDOUT;
+	set_current_state (TASK_RUNNING);
+	remove_wait_queue (&chs.wqh, &wait);
+
+	if (!timeout && !chs.done) {
+		if (urb->status != -EINPROGRESS) {	/* No callback?!! */
+			dbg ("auerchain_start_wait_urb: raced timeout");
+			status = urb->status;
+		} else {
+			dbg ("auerchain_start_wait_urb: timeout");
+			auerchain_unlink_urb (acp, urb);  /* remove urb safely */
+			status = -ETIMEDOUT;
+		}
 	} else
 		status = urb->status;
 
@@ -932,6 +949,8 @@
 			/* reuse the buffer */
 			err ("control read: transmission error %d, can not retry", urb->status);
 			auerbuf_releasebuf (bp);
+			/* Wake up all processes waiting for a buffer */
+			wake_up (&cp->bufferwait);
 			return;
 		}
 		bp->retries++;
@@ -1128,7 +1147,7 @@
         FILL_INT_URB (cp->inturbp, cp->usbdev, usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp, irqsize, auerswald_int_complete, cp, ep->bInterval);
         /* start the urb */
 	cp->inturbp->status = 0;	/* needed! */
-	ret = usb_submit_urb (cp->inturbp);
+	ret = usb_submit_urb (cp->inturbp, GFP_KERNEL);
 
 intoend:
         if (ret < 0) {
@@ -1376,9 +1395,6 @@
 	}
 	up (&dev_table_mutex);
 
-	/* prevent module unloading */
-	MOD_INC_USE_COUNT;
-
 	/* we have access to the device. Now lets allocate memory */
 	ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
 	if (ccp == NULL) {
@@ -1415,7 +1431,6 @@
 	/* Error exit */
 ofail:	up (&cp->mutex);
 	auerchar_delete (ccp);
-  	MOD_DEC_USE_COUNT;
 	return ret;
 }
 
@@ -1553,21 +1568,14 @@
 	return ret;
 }
 
-
-/* Seek is not supported */
-static loff_t auerchar_llseek (struct file *file, loff_t offset, int origin)
-{
-        dbg ("auerchar_seek");
-        return -ESPIPE;
-}
-
-
 /* Read data from the device */
 static ssize_t auerchar_read (struct file *file, char *buf, size_t count, loff_t * ppos)
 {
         unsigned long flags;
 	pauerchar_t ccp = (pauerchar_t) file->private_data;
         pauerbuf_t   bp = NULL;
+	wait_queue_t wait;
+
         dbg ("auerchar_read");
 
 	/* Error checking */
@@ -1630,6 +1638,11 @@
 
 	/* a read buffer is not available. Try to get the next data block. */
 doreadlist:
+	/* Preparing for sleep */
+	init_waitqueue_entry (&wait, current);
+	set_current_state (TASK_INTERRUPTIBLE);
+	add_wait_queue (&ccp->readwait, &wait);
+
 	bp = NULL;
 	spin_lock_irqsave (&ccp->bufctl.lock, flags);
         if (!list_empty (&ccp->bufctl.rec_buff_list)) {
@@ -1644,20 +1657,25 @@
 	if (bp) {
 		ccp->readbuf = bp;
 		ccp->readoffset = AUH_SIZE; /* for headerbyte */
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&ccp->readwait, &wait);
 		goto doreadbuf;		  /* now we can read! */
 	}
 
 	/* no data available. Should we wait? */
 	if (file->f_flags & O_NONBLOCK) {
                 dbg ("No read buffer available, returning -EAGAIN");
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&ccp->readwait, &wait);
 		up (&ccp->readmutex);
 		up (&ccp->mutex);
-                return -EAGAIN;  /* nonblocking, no data available */
+		return -EAGAIN;  /* nonblocking, no data available */
         }
 
 	/* yes, we should wait! */
 	up (&ccp->mutex); /* allow other operations while we wait */
-	interruptible_sleep_on (&ccp->readwait);
+	schedule();
+	remove_wait_queue (&ccp->readwait, &wait);
 	if (signal_pending (current)) {
 		/* waked up by a signal */
 		up (&ccp->readmutex);
@@ -1688,6 +1706,7 @@
         pauerbuf_t bp;
         unsigned long flags;
 	int ret;
+	wait_queue_t wait;
 
         dbg ("auerchar_write %d bytes", len);
 
@@ -1724,6 +1743,11 @@
 		up (&ccp->mutex);
 		return -EIO;
 	}
+	/* Prepare for sleep */
+	init_waitqueue_entry (&wait, current);
+	set_current_state (TASK_INTERRUPTIBLE);
+	add_wait_queue (&cp->bufferwait, &wait);
+
 	/* Try to get a buffer from the device pool.
 	   We can't use a buffer from ccp->bufctl because the write
 	   command will last beond a release() */
@@ -1744,16 +1768,22 @@
 
 		/* NONBLOCK: don't wait */
 		if (file->f_flags & O_NONBLOCK) {
+			set_current_state (TASK_RUNNING);
+			remove_wait_queue (&cp->bufferwait, &wait);
 			return -EAGAIN;
 		}
 
 		/* BLOCKING: wait */
-		interruptible_sleep_on (&cp->bufferwait);
+		schedule();
+		remove_wait_queue (&cp->bufferwait, &wait);
 		if (signal_pending (current)) {
 			/* waked up by a signal */
 			return -ERESTARTSYS;
 		}
 		goto write_again;
+	} else {
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&cp->bufferwait, &wait);
 	}
 
 	/* protect against too big write requests */
@@ -1763,6 +1793,8 @@
 	if (copy_from_user ( bp->bufp+AUH_SIZE, buf, len)) {
 		dbg ("copy_from_user failed");
 		auerbuf_releasebuf (bp);
+		/* Wake up all processes waiting for a buffer */
+		wake_up (&cp->bufferwait);
 		up (&cp->mutex);
 		up (&ccp->mutex);
 		return -EIO;
@@ -1787,6 +1819,8 @@
 	if (ret) {
 		dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
 		auerbuf_releasebuf (bp);
+		/* Wake up all processes waiting for a buffer */
+		wake_up (&cp->bufferwait);
 		up (&ccp->mutex);
 		return -EIO;
 	}
@@ -1831,9 +1865,6 @@
 	up (&ccp->mutex);
 	auerchar_delete (ccp);
 
-	/* release the module */
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -1843,7 +1874,7 @@
 static struct file_operations auerswald_fops =
 {
 	owner:		THIS_MODULE,
-	llseek:		auerchar_llseek,
+	llseek:		no_llseek,
 	read:		auerchar_read,
 	write:          auerchar_write,
 	ioctl:		auerchar_ioctl,
@@ -2154,3 +2185,4 @@
 module_exit (auerswald_cleanup);
 
 /* --------------------------------------------------------------------- */
+
diff -Nru a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c
--- a/drivers/usb/bluetooth.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/bluetooth.c	Sun Feb 10 19:58:05 2002
@@ -335,7 +335,7 @@
 			  (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
 
 	/* send it down the pipe */
-	status = usb_submit_urb(urb);
+	status = usb_submit_urb(urb, GFP_KERNEL);
 	if (status)
 		dbg(__FUNCTION__ " - usb_submit_urb(control) failed with status = %d", status);
 	
@@ -390,7 +390,7 @@
 			       bluetooth->bulk_in_buffer,
 			       bluetooth->bulk_in_buffer_size,
 			       bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb);
+		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
 		if (result)
 			dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
 #endif
@@ -400,7 +400,7 @@
 			      bluetooth->interrupt_in_buffer_size,
 			      bluetooth_int_callback, bluetooth,
 			      bluetooth->interrupt_in_interval);
-		result = usb_submit_urb(bluetooth->interrupt_in_urb);
+		result = usb_submit_urb(bluetooth->interrupt_in_urb, GFP_KERNEL);
 		if (result)
 			dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
 	}
@@ -540,7 +540,7 @@
 				urb->transfer_flags |= USB_QUEUE_BULK;
 
 				/* send it down the pipe */
-				retval = usb_submit_urb(urb);
+				retval = usb_submit_urb(urb, GFP_KERNEL);
 				if (retval) {
 					dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with error = %d", retval);
 					goto exit;
@@ -730,7 +730,7 @@
 			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
 			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
 			      bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb);
+		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
 		if (result)
 			err (__FUNCTION__ " - failed submitting read urb, error %d", result);
 	}
@@ -921,7 +921,7 @@
 			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
 			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
 			      bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb);
+		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
 		if (result)
 			err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 
@@ -982,7 +982,7 @@
 		      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
 		      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
 		      bluetooth_read_bulk_callback, bluetooth);
-	result = usb_submit_urb(bluetooth->read_urb);
+	result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
 	if (result)
 		err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 
diff -Nru a/drivers/usb/catc.c b/drivers/usb/catc.c
--- a/drivers/usb/catc.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/catc.c	Sun Feb 10 19:58:06 2002
@@ -257,7 +257,7 @@
 
 	if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) {
 		catc->rx_urb->dev = catc->usbdev;
-		if ((status = usb_submit_urb(catc->rx_urb)) < 0) {
+		if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
 			err("submit(rx_urb) status %d", status);
 			return;
 		} 
@@ -286,7 +286,7 @@
 	catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
 	catc->tx_urb->dev = catc->usbdev;
 
-	if ((status = usb_submit_urb(catc->tx_urb)) < 0)
+	if ((status = usb_submit_urb(catc->tx_urb, GFP_KERNEL)) < 0)
 		err("submit(tx_urb), status %d", status);
 
 	catc->tx_idx = !catc->tx_idx;
@@ -402,7 +402,7 @@
 	if (!q->dir && q->buf && q->len)
 		memcpy(catc->ctrl_buf, q->buf, q->len);
 
-	if ((status = usb_submit_urb(catc->ctrl_urb)))
+	if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL)))
 		err("submit(ctrl_urb) status %d", status);
 }
 
@@ -625,7 +625,7 @@
 	int status;
 
 	catc->irq_urb->dev = catc->usbdev;
-	if ((status = usb_submit_urb(catc->irq_urb)) < 0) {
+	if ((status = usb_submit_urb(catc->irq_urb, GFP_KERNEL)) < 0) {
 		err("submit(irq_urb) status %d", status);
 		return -1;
 	}
diff -Nru a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c
--- a/drivers/usb/dabusb.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/usb/dabusb.c	Sun Feb 10 19:58:03 2002
@@ -458,7 +458,7 @@
 
 			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
 
-			ret = usb_submit_urb (end->purb);
+			ret = usb_submit_urb (end->purb, GFP_KERNEL);
 			if (ret) {
 				err("usb_submit_urb returned:%d", ret);
 				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
diff -Nru a/drivers/usb/devices.c b/drivers/usb/devices.c
--- a/drivers/usb/devices.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/devices.c	Sun Feb 10 19:58:06 2002
@@ -554,21 +554,26 @@
 
 static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
 {
+	loff_t ret;
+
+	lock_kernel();
+
 	switch (orig) {
 	case 0:
 		file->f_pos = offset;
-		return file->f_pos;
-
+		ret = file->f_pos;
+		break;
 	case 1:
 		file->f_pos += offset;
-		return file->f_pos;
-
+		ret = file->f_pos;
+		break;
 	case 2:
-		return -EINVAL;
-
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+
+	unlock_kernel();
+	return ret;
 }
 
 struct file_operations usbdevfs_devices_fops = {
diff -Nru a/drivers/usb/devio.c b/drivers/usb/devio.c
--- a/drivers/usb/devio.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/devio.c	Sun Feb 10 19:58:06 2002
@@ -44,6 +44,7 @@
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
 #include <asm/uaccess.h>
+#include <asm/byteorder.h>
 
 
 struct async {
@@ -58,21 +59,26 @@
 
 static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
 {
+	loff_t ret;
+
+	lock_kernel();
+
 	switch (orig) {
 	case 0:
 		file->f_pos = offset;
-		return file->f_pos;
-
+		ret = file->f_pos;
+		break;
 	case 1:
 		file->f_pos += offset;
-		return file->f_pos;
-
+		ret = file->f_pos;
+		break;
 	case 2:
-		return -EINVAL;
-
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+
+	unlock_kernel();
+	return ret;
 }
 
 static ssize_t usbdev_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos)
@@ -364,7 +370,7 @@
 	if (test_bit(intf, &ps->ifclaimed))
 		return 0;
 	/* if not yet claimed, claim it for the driver */
-	printk(KERN_WARNING "usbdevfs: process %d (%s) did not claim interface %u before use\n",
+	printk(KERN_WARNING "usbfs: process %d (%s) did not claim interface %u before use\n",
 	       current->pid, current->comm, intf);
 	return claimintf(ps, intf);
 }
@@ -563,7 +569,7 @@
 	}
 	free_page((unsigned long)tbuf);
 	if (i<0) {
-		printk(KERN_DEBUG "usbdevfs: USBDEVFS_CONTROL failed dev %d rqt %u rq %u len %u ret %d\n", 
+		printk(KERN_DEBUG "usbfs: USBDEVFS_CONTROL failed dev %d rqt %u rq %u len %u ret %d\n", 
 		       dev->devnum, ctrl.bRequestType, ctrl.bRequest, ctrl.wLength, i);
 	}
 	return i;
@@ -619,7 +625,7 @@
 	}
 	free_page((unsigned long)tbuf);
 	if (i < 0) {
-		printk(KERN_WARNING "usbdevfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n", 
+		printk(KERN_WARNING "usbfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n", 
 		       dev->devnum, bulk.ep, bulk.len, i);
 		return i;
 	}
@@ -906,8 +912,8 @@
 		}
 	}
         async_newpending(as);
-        if ((ret = usb_submit_urb(as->urb))) {
-		printk(KERN_DEBUG "usbdevfs: usb_submit_urb returned %d\n", ret);
+        if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
+		printk(KERN_DEBUG "usbfs: usb_submit_urb returned %d\n", ret);
                 async_removepending(as);
                 free_async(as);
                 return ret;
diff -Nru a/drivers/usb/drivers.c b/drivers/usb/drivers.c
--- a/drivers/usb/drivers.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/drivers.c	Sun Feb 10 19:58:04 2002
@@ -38,6 +38,7 @@
 #include <linux/mm.h>
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 
 /*****************************************************************/
@@ -96,21 +97,24 @@
 
 static loff_t usb_driver_lseek(struct file * file, loff_t offset, int orig)
 {
+	loff_t ret;
+
+	lock_kernel();
 	switch (orig) {
 	case 0:
 		file->f_pos = offset;
-		return file->f_pos;
-
+		ret = file->f_pos;
+		break;
 	case 1:
 		file->f_pos += offset;
-		return file->f_pos;
-
+		ret = file->f_pos;
+		break;
 	case 2:
-		return -EINVAL;
-
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+	unlock_kernel();
+	return ret;
 }
 
 struct file_operations usbdevfs_drivers_fops = {
diff -Nru a/drivers/usb/hcd/ehci-hcd.c b/drivers/usb/hcd/ehci-hcd.c
--- a/drivers/usb/hcd/ehci-hcd.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/hcd/ehci-hcd.c	Sun Feb 10 19:58:04 2002
@@ -277,7 +277,7 @@
 	 */
 	usb_connect (udev);
 	udev->speed = USB_SPEED_HIGH;
-	if (usb_new_device (udev) != 0) {
+	if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) {
 		if (hcd->state == USB_STATE_RUNNING)
 			ehci_ready (ehci);
 		while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
diff -Nru a/drivers/usb/hcd/ehci-hub.c b/drivers/usb/hcd/ehci-hub.c
--- a/drivers/usb/hcd/ehci-hub.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/hcd/ehci-hub.c	Sun Feb 10 19:58:06 2002
@@ -18,6 +18,8 @@
 
 /* this file is part of ehci-hcd.c */
 
+#include <asm/byteorder.h>
+
 /*-------------------------------------------------------------------------*/
 
 /*
diff -Nru a/drivers/usb/hcd/ehci-mem.c b/drivers/usb/hcd/ehci-mem.c
--- a/drivers/usb/hcd/ehci-mem.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/hcd/ehci-mem.c	Sun Feb 10 19:58:05 2002
@@ -18,6 +18,8 @@
 
 /* this file is part of ehci-hcd.c */
 
+#include <asm/byteorder.h>
+
 /*-------------------------------------------------------------------------*/
 
 /*
diff -Nru a/drivers/usb/hcd/ehci-q.c b/drivers/usb/hcd/ehci-q.c
--- a/drivers/usb/hcd/ehci-q.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/hcd/ehci-q.c	Sun Feb 10 19:58:05 2002
@@ -18,6 +18,8 @@
 
 /* this file is part of ehci-hcd.c */
 
+#include <asm/byteorder.h>
+
 /*-------------------------------------------------------------------------*/
 
 /*
diff -Nru a/drivers/usb/hcd/ehci-sched.c b/drivers/usb/hcd/ehci-sched.c
--- a/drivers/usb/hcd/ehci-sched.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/hcd/ehci-sched.c	Sun Feb 10 19:58:05 2002
@@ -20,6 +20,8 @@
 
 /*-------------------------------------------------------------------------*/
 
+#include "ehci.h"
+
 /*
  * EHCI scheduled transaction support:  interrupt, iso, split iso
  * These are called "periodic" transactions in the EHCI spec.
diff -Nru a/drivers/usb/hcd/ohci-dbg.c b/drivers/usb/hcd/ohci-dbg.c
--- a/drivers/usb/hcd/ohci-dbg.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/hcd/ohci-dbg.c	Sun Feb 10 19:58:05 2002
@@ -2,9 +2,9 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-dbg.c,v 1.2 2002/01/19 00:15:45 dbrownell Exp $
  */
  
@@ -74,27 +74,34 @@
 static inline struct ed *
 dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma);
 
+#ifdef OHCI_VERBOSE_DEBUG
 /* print non-empty branches of the periodic ed tree */
-void ep_print_int_eds (struct ohci_hcd *ohci, char * str)
+void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
 {
 	int i, j;
-	 __u32 * ed_p;
+	u32 *ed_p;
+	int printed = 0;
+
 	for (i= 0; i < 32; i++) {
 		j = 5;
 		ed_p = &(ohci->hcca->int_table [i]);
 		if (*ed_p == 0)
-		    continue;
-		printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):",
-				str, i, i);
+			continue;
+		printed = 1;
+		printk (KERN_DEBUG "%s, ohci %s frame %2d:",
+				label, ohci->hcd.bus_name, i);
 		while (*ed_p != 0 && j--) {
 			struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
-			printk (" ed: %4x;", ed->hwINFO);
+			printk (" %p/%08x;", ed, ed->hwINFO);
 			ed_p = &ed->hwNextED;
 		}
 		printk ("\n");
 	}
+	if (!printed)
+		printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n",
+				label, ohci->hcd.bus_name);
 }
-
+#endif
 
 static void ohci_dump_intr_mask (char *label, __u32 mask)
 {
@@ -137,8 +144,9 @@
 	__u32			temp;
 
 	temp = readl (&regs->revision) & 0xff;
-	if (temp != 0x10)
-		dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+	dbg ("OHCI %d.%d, %s legacy support registers",
+		0x03 & (temp >> 4), (temp & 0x0f),
+		(temp & 0x10) ? "with" : "NO");
 
 	temp = readl (&regs->control);
 	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
@@ -225,8 +233,10 @@
 
 	// dumps some of the state we know about
 	ohci_dump_status (controller);
+#ifdef OHCI_VERBOSE_DEBUG
 	if (verbose)
-		ep_print_int_eds (controller, "hcca");
+		ohci_dump_periodic (controller, "hcca");
+#endif
 	dbg ("hcca frame #%04x", controller->hcca->frame_no);
 	ohci_dump_roothub (controller, 1);
 }
diff -Nru a/drivers/usb/hcd/ohci-hcd.c b/drivers/usb/hcd/ohci-hcd.c
--- a/drivers/usb/hcd/ohci-hcd.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/hcd/ohci-hcd.c	Sun Feb 10 19:58:04 2002
@@ -2,7 +2,7 @@
  * OHCI HCD (Host Controller Driver) for USB.
  *
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
  * [ Initialisation is based on Linus'  ]
  * [ uhci code and gregs ohci fragments ]
@@ -55,7 +55,7 @@
  * v2.0 1999/05/04 
  * v1.0 1999/04/27 initial release
  *
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-hcd.c,v 1.7 2002/01/19 00:20:56 dbrownell Exp $
  */
  
@@ -74,10 +74,6 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>  /* for in_interrupt () */
 
-#ifndef CONFIG_USB_DEBUG
-	#define CONFIG_USB_DEBUG	/* this is still experimental! */
-#endif
-
 #ifdef CONFIG_USB_DEBUG
 	#define DEBUG
 #else
@@ -91,6 +87,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
+#include <asm/byteorder.h>
 
 #ifdef CONFIG_PMAC_PBOOK
 #include <asm/machdep.h>
@@ -258,7 +255,9 @@
 	if (ed->state != ED_OPER)
 		ep_link (ohci, ed);
 
-	/* fill the TDs and link it to the ed */
+	/* fill the TDs and link them to the ed; and
+	 * enable that part of the schedule, if needed
+	 */
 	td_submit_urb (urb);
 
 	spin_unlock_irqrestore (&ohci->lock, flags);
@@ -357,7 +356,9 @@
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
+#ifdef	OHCI_VERBOSE_DEBUG
 	dbg ("%s: ohci_get_frame", hcd->bus_name);
+#endif
 	return le16_to_cpu (ohci->hcca->frame_no);
 }
 
@@ -469,7 +470,7 @@
 
 	usb_connect (udev);
 	udev->speed = USB_SPEED_FULL;
-	if (usb_new_device (udev) != 0) {
+	if (usb_register_root_hub (udev, &ohci->hcd.pdev->dev) != 0) {
 		usb_free_dev (udev); 
 		ohci->disabled = 1;
 // FIXME cleanup
@@ -841,9 +842,10 @@
 			dl_done_list (ohci, dl_reverse_done_list (ohci));
 		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
 
-//		writel (OHCI_BLF, &ohci->regs->cmdstatus);
-//		writel (OHCI_CLF, &ohci->regs->cmdstatus);
-ohci_dump_status (ohci);
+		/* assume there are TDs on the bulk and control lists */
+		writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
+
+// ohci_dump_status (ohci);
 dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled);
 		break;
 
diff -Nru a/drivers/usb/hcd/ohci-hub.c b/drivers/usb/hcd/ohci-hub.c
--- a/drivers/usb/hcd/ohci-hub.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/hcd/ohci-hub.c	Sun Feb 10 19:58:04 2002
@@ -2,7 +2,7 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
  * This file is licenced under GPL
  * $Id: ohci-hub.c,v 1.2 2002/01/19 00:21:49 dbrownell Exp $
diff -Nru a/drivers/usb/hcd/ohci-mem.c b/drivers/usb/hcd/ohci-mem.c
--- a/drivers/usb/hcd/ohci-mem.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/hcd/ohci-mem.c	Sun Feb 10 19:58:04 2002
@@ -2,9 +2,9 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-mem.c,v 1.2 2002/01/19 00:22:13 dbrownell Exp $
  */
 
@@ -42,7 +42,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEBUG
+#ifdef	CONFIG_DEBUG_SLAB
 #	define OHCI_MEM_FLAGS	SLAB_POISON
 #else
 #	define OHCI_MEM_FLAGS	0
@@ -64,16 +64,17 @@
 	return scan->virt;
 }
 
-static inline struct ed *
+static struct ed *
 dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma)
 {
 	return (struct ed *) dma_to_ed_td(&(hc->ed_hash [ED_HASH_FUNC(ed_dma)]),
 				      ed_dma);
 }
 
-static inline struct td *
+static struct td *
 dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
 {
+	td_dma &= TD_MASK;
 	return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]),
 				      td_dma);
 }
@@ -214,7 +215,7 @@
 	return td;
 }
 
-static inline void
+static void
 td_free (struct ohci_hcd *hc, struct td *td)
 {
 	hash_free_td (hc, td);
@@ -242,7 +243,7 @@
 	return ed;
 }
 
-static inline void
+static void
 ed_free (struct ohci_hcd *hc, struct ed *ed)
 {
 	hash_free_ed (hc, ed);
diff -Nru a/drivers/usb/hcd/ohci-q.c b/drivers/usb/hcd/ohci-q.c
--- a/drivers/usb/hcd/ohci-q.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/hcd/ohci-q.c	Sun Feb 10 19:58:05 2002
@@ -2,11 +2,13 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-q.c,v 1.6 2002/01/19 00:23:15 dbrownell Exp $
  */
+
+#include <asm/byteorder.h>
  
 static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
 {
@@ -95,11 +97,11 @@
 	urb_print (urb, "RET", usb_pipeout (urb->pipe));
 #endif
 
-// FIXME:  but if urb->status says it was was unlinked ...
-
 	switch (usb_pipetype (urb->pipe)) {
   		case PIPE_INTERRUPT:
 #ifdef CONFIG_PCI
+// FIXME rewrite this resubmit path.  use pci_dma_sync_single()
+// and requeue more cheaply, and only if needed.
 			pci_unmap_single (hc->hcd.pdev,
 				urb_priv->td [0]->data_dma,
 				urb->transfer_buffer_length,
@@ -107,16 +109,22 @@
 					? PCI_DMA_TODEVICE
 					: PCI_DMA_FROMDEVICE);
 #endif
+			/* FIXME: MP race.  If another CPU partially unlinks
+			 * this URB (urb->status was updated, hasn't yet told
+			 * us to dequeue) before we call complete() here, an
+			 * extra "unlinked" completion will be reported...
+			 */
 			urb->complete (urb);
 
-			/* implicitly requeued */
+			/* always requeued, but ED_SKIP if complete() unlinks.
+			 * removed from periodic table only at SOF intr.
+			 */
   			urb->actual_length = 0;
-  			urb->status = -EINPROGRESS;
-  			if (urb_priv->state != URB_DEL) {
-				spin_lock_irqsave (&hc->lock, flags);
-  				td_submit_urb (urb);
-  				spin_unlock_irqrestore (&hc->lock, flags);
-			}
+			if (urb_priv->state != URB_DEL)
+				urb->status = -EINPROGRESS;
+			spin_lock_irqsave (&hc->lock, flags);
+			td_submit_urb (urb);
+			spin_unlock_irqrestore (&hc->lock, flags);
   			break;
 
 		case PIPE_ISOCHRONOUS:
@@ -126,7 +134,7 @@
 				continue;
 			if (urbt) { /* send the reply and requeue URB */	
 #ifdef CONFIG_PCI
-// FIXME this style unmap is only done on this route ...
+// FIXME rewrite this resubmit path too
 				pci_unmap_single (hc->hcd.pdev,
 					urb_priv->td [0]->data_dma,
 					urb->transfer_buffer_length,
@@ -290,8 +298,8 @@
 			ed->hwNextED = *ed_p; 
 			*ed_p = cpu_to_le32 (ed->dma);
 		}
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "LINK_INT");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "LINK_INT");
 #endif
 		break;
 
@@ -313,8 +321,8 @@
 			ed->ed_prev = NULL;
 		}	
 		ohci->ed_isotail = edi;  
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "LINK_ISO");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "LINK_ISO");
 #endif
 		break;
 	}	 	
@@ -336,7 +344,7 @@
 	int	interval;
 	__u32	*ed_p;
 
-	ed->hwINFO |= __constant_cpu_to_le32 (OHCI_ED_SKIP);
+	ed->hwINFO |= ED_SKIP;
 
 	switch (ed->type) {
 	case PIPE_CONTROL:
@@ -394,8 +402,8 @@
 		}
 		for (i = int_branch; i < NUM_INTS; i += interval)
 		    ohci->ohci_int_load [i] -= ed->int_load;
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "UNLINK_INT");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "UNLINK_INT");
 #endif
 		break;
 
@@ -421,11 +429,15 @@
 				}
 			}	
 		}	
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "UNLINK_ISO");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "UNLINK_ISO");
 #endif
 		break;
 	}
+
+	/* FIXME ED's "unlink" state is indeterminate;
+	 * the HC might still be caching it (till SOF).
+	 */
 	ed->state = ED_UNLINK;
 	return 0;
 }
@@ -478,7 +490,7 @@
 	}
 
 	if (ed->state == ED_NEW) {
-		ed->hwINFO = __constant_cpu_to_le32 (OHCI_ED_SKIP);
+		ed->hwINFO = ED_SKIP;
   		/* dummy td; end of td list for ed */
 		td = td_alloc (ohci, SLAB_ATOMIC);
  		if (!td) {
@@ -492,8 +504,6 @@
 		ed->type = usb_pipetype (pipe);
 	}
 
-	ohci->dev [usb_pipedevice (pipe)] = udev;
-
 // FIXME:  don't do this if it's linked to the HC,
 // we might clobber data toggle or other state ...
 
@@ -531,7 +541,7 @@
 		return;
 	ed->state |= ED_URB_DEL;
 
-	ed->hwINFO |= __constant_cpu_to_le32 (OHCI_ED_SKIP);
+	ed->hwINFO |= ED_SKIP;
 
 	switch (ed->type) {
 		case PIPE_CONTROL: /* stop control list */
@@ -582,7 +592,7 @@
 
 	/* fill the old dummy TD */
 	td = urb_priv->td [index] = dma_to_td (ohci,
-			le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf);
+			le32_to_cpup (&urb_priv->ed->hwTailP));
 
 	td->ed = urb_priv->ed;
 	td->next_dl_td = NULL;
@@ -795,7 +805,7 @@
 
   	spin_lock_irqsave (&ohci->lock, flags);
 
-	td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0;
+	td_list_hc = le32_to_cpup (&ohci->hcca->done_head);
 	ohci->hcca->done_head = 0;
 
 	while (td_list_hc) {		
@@ -806,26 +816,24 @@
 			dbg (" USB-error/status: %x : %p", 
 				TD_CC_GET (le32_to_cpup (&td_list->hwINFO)),
 				td_list);
-			if (td_list->ed->hwHeadP
-					& __constant_cpu_to_le32 (0x1)) {
+			/* typically the endpoint halted too */
+			if (td_list->ed->hwHeadP & ED_H) {
 				if (urb_priv && ((td_list->index + 1)
 						< urb_priv->length)) {
 					td_list->ed->hwHeadP = 
 			    (urb_priv->td [urb_priv->length - 1]->hwNextTD
-				    & __constant_cpu_to_le32 (0xfffffff0))
-			    | (td_list->ed->hwHeadP
-				    & __constant_cpu_to_le32 (0x2));
+				    & __constant_cpu_to_le32 (TD_MASK))
+			    | (td_list->ed->hwHeadP & ED_C);
 					urb_priv->td_cnt += urb_priv->length
 						- td_list->index - 1;
 				} else 
-					td_list->ed->hwHeadP &=
-					__constant_cpu_to_le32 (0xfffffff2);
+					td_list->ed->hwHeadP &= ~ED_H;
 			}
 		}
 
 		td_list->next_dl_td = td_rev;	
 		td_rev = td_list;
-		td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;	
+		td_list_hc = le32_to_cpup (&td_list->hwNextTD);
 	}	
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	return td_list;
@@ -851,10 +859,8 @@
 
 	for (ed = ohci->ed_rm_list [frame]; ed != NULL; ed = ed->ed_rm_list) {
 
-		tdTailP = dma_to_td (ohci,
-			le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
-		tdHeadP = dma_to_td (ohci,
-			le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
+		tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP));
+		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
 		edINFO = le32_to_cpup (&ed->hwINFO);
 		td_p = &ed->hwHeadP;
 
@@ -863,7 +869,7 @@
 			urb_priv_t *urb_priv = td->urb->hcpriv;
 
 			td_next = dma_to_td (ohci,
-				le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
+				le32_to_cpup (&td->hwNextTD));
 			if ((urb_priv->state == URB_DEL)) {
 				tdINFO = le32_to_cpup (&td->hwINFO);
 				if (TD_CC_GET (tdINFO) < 0xE)
@@ -882,17 +888,16 @@
 		}
 
 		ed->state &= ~ED_URB_DEL;
-		tdHeadP = dma_to_td (ohci,
-			le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
+		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
 
 		if (tdHeadP == tdTailP) {
 			if (ed->state == ED_OPER)
 				ep_unlink (ohci, ed);
 			td_free (ohci, tdTailP);
-			ed->hwINFO = __constant_cpu_to_le32 (OHCI_ED_SKIP);
+			ed->hwINFO = ED_SKIP;
 			ed->state = ED_NEW;
 		} else
-			ed->hwINFO &= ~__constant_cpu_to_le32 (OHCI_ED_SKIP);
+			ed->hwINFO &= ~ED_SKIP;
 
 		switch (ed->type) {
 			case PIPE_CONTROL:
@@ -938,7 +943,7 @@
 	int		cc = 0;
 	struct urb	*urb;
 	urb_priv_t	*urb_priv;
- 	__u32		tdINFO, edHeadP, edTailP;
+ 	__u32		tdINFO;
 
  	unsigned long flags;
 
@@ -968,7 +973,7 @@
 			/*
 			 * Except for periodic transfers, both branches do
 			 * the same thing.  Periodic urbs get reissued until
-			 * they're "deleted" with usb_unlink_urb.
+			 * they're "deleted" (in SOF intr) by usb_unlink_urb.
 			 */
 			if ((ed->state & (ED_OPER | ED_UNLINK))
 					&& (urb_priv->state != URB_DEL)) {
@@ -983,13 +988,11 @@
 
   		spin_lock_irqsave (&ohci->lock, flags);
   		if (ed->state != ED_NEW) { 
-  			edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
-  			edTailP = le32_to_cpup (&ed->hwTailP);
-
-// FIXME:  ED_UNLINK is very fuzzy w.r.t. what the hc knows...
+  			u32 edHeadP = ed->hwHeadP;
 
 			/* unlink eds if they are not busy */
-     			if ((edHeadP == edTailP) && (ed->state == ED_OPER)) 
+			edHeadP &= __constant_cpu_to_le32 (ED_MASK);
+     			if ((edHeadP == ed->hwTailP) && (ed->state == ED_OPER)) 
      				ep_unlink (ohci, ed);
      		}	
      		spin_unlock_irqrestore (&ohci->lock, flags);
diff -Nru a/drivers/usb/hcd/ohci.h b/drivers/usb/hcd/ohci.h
--- a/drivers/usb/hcd/ohci.h	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/hcd/ohci.h	Sun Feb 10 19:58:06 2002
@@ -2,86 +2,102 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci.h,v 1.5 2002/01/19 00:24:01 dbrownell Exp $
  */
  
-static const int cc_to_error [16] = { 
-
-/* map OHCI status to errno values */ 
-	/* No  Error  */               0,
-	/* CRC Error  */               -EILSEQ,
-	/* Bit Stuff  */               -EPROTO,
-	/* Data Togg  */               -EILSEQ,
-	/* Stall      */               -EPIPE,
-	/* DevNotResp */               -ETIMEDOUT,
-	/* PIDCheck   */               -EPROTO,
-	/* UnExpPID   */               -EPROTO,
-	/* DataOver   */               -EOVERFLOW,
-	/* DataUnder  */               -EREMOTEIO,
-	/* (for hw)   */               -EIO,
-	/* (for hw)   */               -EIO,
-	/* BufferOver */               -ECOMM,
-	/* BuffUnder  */               -ENOSR,
-	/* (for HCD)  */               -EALREADY,
-	/* (for HCD)  */               -EALREADY 
-};
-
-
-/* ED States */
-
+/*
+ * OHCI Endpoint Descriptor (ED) ... holds TD queue
+ * See OHCI spec, section 4.2
+ */
+struct ed {
+	/* first fields are hardware-specified, le32 */
+	__u32			hwINFO;       	/* endpoint config bitmap */
+#define ED_ISO		__constant_cpu_to_le32(1 << 15)
+#define ED_SKIP		__constant_cpu_to_le32(1 << 14)
+#define ED_LOWSPEED	__constant_cpu_to_le32(1 << 13)
+#define ED_OUT		__constant_cpu_to_le32(0x01 << 11)
+#define ED_IN		__constant_cpu_to_le32(0x10 << 11)
+	__u32			hwTailP;	/* tail of TD list */
+	__u32			hwHeadP;	/* head of TD list */
+#define ED_C		__constant_cpu_to_le32(0x02)	/* toggle carry */
+#define ED_H		__constant_cpu_to_le32(0x01)	/* halted */
+	__u32			hwNextED;	/* next ED in list */
+
+	/* rest are purely for the driver's use */
+	struct ed		*ed_prev;  
+	__u8			int_period;
+	__u8			int_branch;
+	__u8			int_load; 
+	__u8			int_interval;
+	__u8			state;			// ED_{NEW,UNLINK,OPER}
 #define ED_NEW 		0x00		/* unused, no dummy td */
 #define ED_UNLINK 	0x01		/* dummy td, maybe linked to hc */
 #define ED_OPER		0x02		/* dummy td, _is_ linked to hc */
+#define ED_URB_DEL  	0x08		/* for unlinking; masked in */
 
-#define ED_URB_DEL  	0x08		/* masked in */
+	__u8			type; 
+	__u16			last_iso;
+	struct ed		*ed_rm_list;
 
-/* usb_ohci_ed */
-struct ed {
-	/* first fields are hardware-specified */
-	__u32 hwINFO;       
-	__u32 hwTailP;
-	__u32 hwHeadP;
-	__u32 hwNextED;
-
-	struct ed * ed_prev;  
-	__u8 int_period;
-	__u8 int_branch;
-	__u8 int_load; 
-	__u8 int_interval;
-	__u8 state;			// ED_{NEW,UNLINK,OPER}
-	__u8 type; 
-	__u16 last_iso;
-	struct ed * ed_rm_list;
-
-	dma_addr_t dma;
-	__u32 unused [3];
-} __attribute((aligned(16)));
+	dma_addr_t		dma;			/* addr of ED */
+} __attribute__ ((aligned(16)));
+
+#define ED_MASK	((u32)~0x0f)		/* strip hw status in low addr bits */
 
  
-/* TD info field */
-#define TD_CC       0xf0000000
+/*
+ * OHCI Transfer Descriptor (TD) ... one per transfer segment
+ * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
+ * and 4.3.2 (iso)
+ */
+struct td {
+	/* first fields are hardware-specified, le32 */
+	__u32		hwINFO;		/* transfer info bitmask */
+#define TD_CC       0xf0000000			/* condition code */
 #define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
-#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
-#define TD_EC       0x0C000000
-#define TD_T        0x03000000
-#define TD_T_DATA0  0x02000000
-#define TD_T_DATA1  0x03000000
-#define TD_T_TOGGLE 0x00000000
-#define TD_R        0x00040000
-#define TD_DI       0x00E00000
-#define TD_DI_SET(X) (((X) & 0x07)<< 21)
-#define TD_DP       0x00180000
-#define TD_DP_SETUP 0x00000000
-#define TD_DP_IN    0x00100000
-#define TD_DP_OUT   0x00080000
+//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC       0x0C000000			/* error count */
+#define TD_T        0x03000000			/* data toggle state */
+#define TD_T_DATA0  0x02000000				/* DATA0 */
+#define TD_T_DATA1  0x03000000				/* DATA1 */
+#define TD_T_TOGGLE 0x00000000				/* uses ED_C */
+#define TD_DI       0x00E00000			/* frames before interrupt */
+//#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP       0x00180000			/* direction/pid */
+#define TD_DP_SETUP 0x00000000			/* SETUP pid */
+#define TD_DP_IN    0x00100000				/* IN pid */
+#define TD_DP_OUT   0x00080000				/* OUT pid */
+							/* 0x00180000 rsvd */
+#define TD_R        0x00040000			/* round: short packets OK? */
+					/* bits 0x1ffff are defined by HCD */
+#define TD_ISO	    0x00010000			/* copy of ED_ISO */
+
+  	__u32		hwCBP;		/* Current Buffer Pointer (or 0) */
+  	__u32		hwNextTD;	/* Next TD Pointer */
+  	__u32		hwBE;		/* Memory Buffer End Pointer */
+
+	/* PSW is only for ISO */
+#define MAXPSW 1		/* hardware allows 8 */
+  	__u16		hwPSW [MAXPSW];
 
-#define TD_ISO	    0x00010000
-#define TD_DEL      0x00020000
+	/* rest are purely for the driver's use */
+  	__u8		index;
+  	struct ed	*ed;
+  	struct td	*next_dl_td;
+  	struct urb	*urb;
 
-/* CC Codes */
+	dma_addr_t	td_dma;		/* addr of this TD */
+	dma_addr_t	data_dma;	/* addr of data it points to */
+} __attribute__ ((aligned(32)));	/* c/b/i need 16; only iso needs 32 */
+
+#define TD_MASK	((u32)~0x1f)		/* strip hw status in low addr bits */
+
+/*
+ * Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW
+ */
 #define TD_CC_NOERROR      0x00
 #define TD_CC_CRC          0x01
 #define TD_CC_BITSTUFFING  0x02
@@ -99,57 +115,50 @@
 #define TD_NOTACCESSED     0x0F
 
 
-#define MAXPSW 1
-
-struct td {
-	/* first hardware fields are in all tds */
-	__u32		hwINFO;
-  	__u32		hwCBP;		/* Current Buffer Pointer */
-  	__u32		hwNextTD;	/* Next TD Pointer */
-  	__u32		hwBE;		/* Memory Buffer End Pointer */
-
-  	__u16		hwPSW [MAXPSW];	/* PSW is only for ISO */
-
-  	__u8		unused;
-  	__u8		index;
-  	struct ed	*ed;
-  	struct td	*next_dl_td;
-  	struct urb	*urb;
-
-	dma_addr_t	td_dma;
-	dma_addr_t	data_dma;
-	__u32		unused2 [2];
-} __attribute((aligned(32)));		/* iso needs 32 */
+/* map OHCI TD status codes (CC) to errno values */ 
+static const int cc_to_error [16] = { 
+	/* No  Error  */               0,
+	/* CRC Error  */               -EILSEQ,
+	/* Bit Stuff  */               -EPROTO,
+	/* Data Togg  */               -EILSEQ,
+	/* Stall      */               -EPIPE,
+	/* DevNotResp */               -ETIMEDOUT,
+	/* PIDCheck   */               -EPROTO,
+	/* UnExpPID   */               -EPROTO,
+	/* DataOver   */               -EOVERFLOW,
+	/* DataUnder  */               -EREMOTEIO,
+	/* (for hw)   */               -EIO,
+	/* (for hw)   */               -EIO,
+	/* BufferOver */               -ECOMM,
+	/* BuffUnder  */               -ENOSR,
+	/* (for HCD)  */               -EALREADY,
+	/* (for HCD)  */               -EALREADY 
+};
 
-#define OHCI_ED_SKIP	(1 << 14)
 
 /*
  * The HCCA (Host Controller Communications Area) is a 256 byte
- * structure defined in the OHCI spec. The host controller is
+ * structure defined section 4.4.1 of the OHCI spec. The HC is
  * told the base address of it.  It must be 256-byte aligned.
  */
-#define NUM_INTS 32	/* part of the OHCI standard */
 struct ohci_hcca {
-	__u32	int_table [NUM_INTS];	/* Interrupt ED table */
+#define NUM_INTS 32
+	__u32	int_table [NUM_INTS];	/* periodic schedule */
 	__u16	frame_no;		/* current frame number */
 	__u16	pad1;			/* set to 0 on each frame_no change */
 	__u32	done_head;		/* info returned for an interrupt */
 	u8	reserved_for_hc [116];
-} __attribute((aligned(256)));
+	u8	what [4];		/* spec only identifies 252 bytes :) */
+} __attribute__ ((aligned(256)));
 
   
 /*
- * Maximum number of root hub ports.  
- */
-#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports */
-
-/*
- * This is the structure of the OHCI controller's memory mapped I/O
- * region.  This is Memory Mapped I/O.  You must use the readl() and
- * writel() macros defined in asm/io.h to access these!!
+ * This is the structure of the OHCI controller's memory mapped I/O region.
+ * You must use readl() and writel() (in <asm/io.h>) to access these fields!!
+ * Layout is in section 7 (and appendix B) of the spec.
  */
 struct ohci_regs {
-	/* control and status registers */
+	/* control and status registers (section 7.1) */
 	__u32	revision;
 	__u32	control;
 	__u32	cmdstatus;
@@ -157,7 +166,7 @@
 	__u32	intrenable;
 	__u32	intrdisable;
 
-	/* memory pointers */
+	/* memory pointers (section 7.2) */
 	__u32	hcca;
 	__u32	ed_periodcurrent;
 	__u32	ed_controlhead;
@@ -166,23 +175,25 @@
 	__u32	ed_bulkcurrent;
 	__u32	donehead;
 
-	/* frame counters */
+	/* frame counters (section 7.3) */
 	__u32	fminterval;
 	__u32	fmremaining;
 	__u32	fmnumber;
 	__u32	periodicstart;
 	__u32	lsthresh;
 
-	/* Root hub ports */
+	/* Root hub ports (section 7.4) */
 	struct	ohci_roothub_regs {
 		__u32	a;
 		__u32	b;
 		__u32	status;
+#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports (RH_A_NDP) */
 		__u32	portstatus [MAX_ROOT_PORTS];
 	} roothub;
 
-	/* and some optional registers for legacy compatibility */
-} __attribute((aligned(32)));
+	/* and optional "legacy support" registers (appendix B) at 0x0100 */
+
+} __attribute__ ((aligned(32)));
 
 
 /* OHCI CONTROL AND STATUS REGISTER MASKS */
@@ -270,9 +281,8 @@
 #define	RH_A_POTPGT	(0xff << 24)		/* power on to power good time */
 
 
-/* urb */
-typedef struct urb_priv
-{
+/* hcd-private per-urb state */
+typedef struct urb_priv {
 	struct ed		*ed;
 	__u16			length;		// # tds in this request
 	__u16			td_cnt;		// tds already serviced
@@ -345,7 +355,6 @@
 	int			sleeping;
 	int			ohci_int_load [NUM_INTS];
 	u32 			hc_control;	/* copy of hc control reg */
-	struct usb_device	*dev [128];
 
 	unsigned long		flags;		/* for HC bugs */
 #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
diff -Nru a/drivers/usb/hcd.c b/drivers/usb/hcd.c
--- a/drivers/usb/hcd.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/hcd.c	Sun Feb 10 19:58:04 2002
@@ -50,6 +50,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
+#include <asm/byteorder.h>
 
 
 /*-------------------------------------------------------------------------*/
@@ -916,14 +917,13 @@
 /* may be called in any context with a valid urb->dev usecount */
 /* caller surrenders "ownership" of urb (and chain at urb->next).  */
 
-static int hcd_submit_urb (struct urb *urb)
+static int hcd_submit_urb (struct urb *urb, int mem_flags)
 {
 	int			status;
 	struct usb_hcd		*hcd;
 	struct hcd_dev		*dev;
 	unsigned long		flags;
 	int			pipe;
-	int			mem_flags;
 
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
@@ -947,11 +947,6 @@
 			usb_pipeout (pipe)))
 		return -EPIPE;
 
-	// FIXME paging/swapping requests over USB should not use GFP_KERNEL
-	// and might even need to use GFP_NOIO ... that flag actually needs
-	// to be passed from the higher level.
-	mem_flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
-
 #ifdef DEBUG
 	{
 	unsigned int	orig_flags = urb->transfer_flags;
@@ -1316,7 +1311,7 @@
 	else if (urb->next) {
 		int 	status;
 
-		status = usb_submit_urb (urb->next);
+		status = usb_submit_urb (urb->next, GFP_ATOMIC);
 		if (status) {
 			dbg ("urb %p chain fail, %d", urb->next, status);
 			urb->next->status = -ENOTCONN;
diff -Nru a/drivers/usb/hid-core.c b/drivers/usb/hid-core.c
--- a/drivers/usb/hid-core.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/hid-core.c	Sun Feb 10 19:58:04 2002
@@ -39,6 +39,7 @@
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <asm/unaligned.h>
+#include <asm/byteorder.h>
 #include <linux/input.h>
 
 #undef DEBUG
@@ -992,7 +993,7 @@
 	hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr);
 	hid->urbout.dev = hid->dev;
 
-	if (usb_submit_urb(&hid->urbout)) {
+	if (usb_submit_urb(&hid->urbout, GFP_KERNEL)) {
 		err("usb_submit_urb(out) failed");
 		return -1;
 	}
@@ -1036,7 +1037,7 @@
 
 	hid->urb.dev = hid->dev;
 
-	if (usb_submit_urb(&hid->urb))
+	if (usb_submit_urb(&hid->urb, GFP_KERNEL))
 		return -EIO;
 
 	return 0;
diff -Nru a/drivers/usb/hpusbscsi.c b/drivers/usb/hpusbscsi.c
--- a/drivers/usb/hpusbscsi.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/hpusbscsi.c	Sun Feb 10 19:58:06 2002
@@ -245,7 +245,7 @@
 			desc->interrupt_interval
 	);
 
-	if ( 0  >  usb_submit_urb(desc->controlurb)) {
+	if ( 0  >  usb_submit_urb(desc->controlurb, GFP_KERNEL)) {
 		kfree(sht->proc_name);
 		return 0;
 	}
@@ -321,7 +321,7 @@
 	hpusbscsi->scallback = callback;
 	hpusbscsi->srb = srb;
 
-	res = usb_submit_urb(hpusbscsi->dataurb);
+	res = usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC);
 	if (unlikely(res)) {
 		hpusbscsi->state = HP_STATE_FREE;
 		TRACE_STATE;
@@ -454,13 +454,14 @@
                 u,
                 hpusbscsi->dev,
                 hpusbscsi->current_data_pipe,
-                sg[hpusbscsi->fragment].address,
+                page_address(sg[hpusbscsi->fragment].page) +
+		sg[hpusbscsi->fragment].offset,
                 sg[hpusbscsi->fragment++].length,
                 callback,
                 hpusbscsi
         );
 
-        res = usb_submit_urb(u);
+        res = usb_submit_urb(u, GFP_ATOMIC);
         if (unlikely(res))
                 hpusbscsi->state = HP_STATE_ERROR;
 	TRACE_STATE;
@@ -509,7 +510,7 @@
 		hpusbscsi
 	);
 
-	res = usb_submit_urb(u);
+	res = usb_submit_urb(u, GFP_ATOMIC);
 	if (unlikely(res)) {
                 handle_usb_error(hpusbscsi);
 		return;
diff -Nru a/drivers/usb/hub.c b/drivers/usb/hub.c
--- a/drivers/usb/hub.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/hub.c	Sun Feb 10 19:58:06 2002
@@ -312,7 +312,7 @@
 
 	FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
 		hub, endpoint->bInterval);
-	ret = usb_submit_urb(hub->urb);
+	ret = usb_submit_urb(hub->urb, GFP_KERNEL);
 	if (ret) {
 		err("usb_submit_urb failed (%d)", ret);
 		kfree(hub->descriptor);
@@ -498,7 +498,7 @@
 		return -1;
 
 	hub->urb->dev = dev;                                                    
-	if (usb_submit_urb(hub->urb))
+	if (usb_submit_urb(hub->urb, GFP_KERNEL))
 		return -1;
 
 	usb_hub_power_on(hub);
@@ -720,6 +720,20 @@
 				dev->bus->busnum, dev->devnum, dev->devpath);
 		info("new USB device on bus %d path %s, assigned address %d",
 			dev->bus->busnum, dev->devpath, dev->devnum);
+
+		/* put the device in the global device tree */
+		dev->dev.parent = &dev->parent->dev;
+		sprintf (&dev->dev.name[0], "USB device %04x:%04x",
+			 dev->descriptor.idVendor,
+			 dev->descriptor.idProduct);
+		/* find the number of the port this device is connected to */
+		sprintf (&dev->dev.bus_id[0], "unknown_port_%03d", dev->devnum);
+		for (i = 0; i < USB_MAXCHILDREN; ++i) {
+			if (dev->parent->children[i] == dev) {
+				sprintf (&dev->dev.bus_id[0], "%02d", i);
+				break;
+			}
+		}
 
 		/* Run it through the hoops (find a driver, etc) */
 		if (!usb_new_device(dev))
diff -Nru a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c
--- a/drivers/usb/ibmcam.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/ibmcam.c	Sun Feb 10 19:58:05 2002
@@ -1,7 +1,8 @@
 /*
  * USB IBM C-It Video Camera driver
  *
- * Supports IBM C-It Video Camera.
+ * Supports Xirlink C-It Video Camera, IBM PC Camera,
+ * IBM NetCamera and Veo Stingray.
  *
  * This driver is based on earlier work of:
  *
@@ -33,9 +34,11 @@
 
 #include "usbvideo.h"
 
-#define	IBMCAM_VENDOR_ID	0x0545
-#define	IBMCAM_PRODUCT_ID	0x8080
+#define IBMCAM_VENDOR_ID	0x0545
+#define IBMCAM_PRODUCT_ID	0x8080
 #define NETCAM_PRODUCT_ID	0x8002	/* IBM NetCamera, close to model 2 */
+#define VEO_800C_PRODUCT_ID	0x800C	/* Veo Stingray, repackaged Model 2 */
+#define VEO_800D_PRODUCT_ID	0x800D	/* Veo Stingray, repackaged Model 4 */
 
 #define MAX_IBMCAM		4	/* How many devices we allow to connect */
 #define USES_IBMCAM_PUTPIXEL    0       /* 0=Fast/oops 1=Slow/secure */
@@ -3671,6 +3674,8 @@
 	if (dev->descriptor.idVendor != IBMCAM_VENDOR_ID)
 		return NULL;
 	if ((dev->descriptor.idProduct != IBMCAM_PRODUCT_ID) &&
+	    (dev->descriptor.idProduct != VEO_800C_PRODUCT_ID) &&
+	    (dev->descriptor.idProduct != VEO_800D_PRODUCT_ID) &&
 	    (dev->descriptor.idProduct != NETCAM_PRODUCT_ID))
 		return NULL;
 
@@ -3684,7 +3689,8 @@
 	case 0x030A:
 		if (ifnum != 0)
 			return NULL;
-		if (dev->descriptor.idProduct == NETCAM_PRODUCT_ID)
+		if ((dev->descriptor.idProduct == NETCAM_PRODUCT_ID) ||
+		    (dev->descriptor.idProduct == VEO_800D_PRODUCT_ID))
 			model = IBMCAM_MODEL_4;
 		else
 			model = IBMCAM_MODEL_2;
@@ -3699,8 +3705,28 @@
 			dev->descriptor.bcdDevice);
 		return NULL;
 	}
-	info("IBM USB camera found (model %d, rev. 0x%04x)",
-		model, dev->descriptor.bcdDevice);
+
+	/* Print detailed info on what we found so far */
+	do {
+		char *brand = NULL;
+		switch (dev->descriptor.idProduct) {
+		case NETCAM_PRODUCT_ID:
+			brand = "IBM NetCamera";
+			break;
+		case VEO_800C_PRODUCT_ID:
+			brand = "Veo Stingray [800C]";
+			break;
+		case VEO_800D_PRODUCT_ID:
+			brand = "Veo Stingray [800D]";
+			break;
+		case IBMCAM_PRODUCT_ID:
+		default:
+			brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
+			break;
+		}
+		info("%s USB camera found (model %d, rev. 0x%04x)",
+		     brand, model, dev->descriptor.bcdDevice);
+	} while (0);
 
 	/* Validate found interface: must have one ISO endpoint */
 	nas = dev->actconfig->interface[ifnum].num_altsetting;
@@ -3908,18 +3934,16 @@
 	usbvideo_Deregister(&cams);
 }
 
-#if defined(usb_device_id_ver)
-
 static __devinitdata struct usb_device_id id_table[] = {
 	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },	/* Model 1 */
 	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
 	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },	/* Model 3 */
 	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
 	{ }  /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
-
-#endif /* defined(usb_device_id_ver) */
 
 module_init(ibmcam_init);
 module_exit(ibmcam_cleanup);
diff -Nru a/drivers/usb/ibmcam.h b/drivers/usb/ibmcam.h
--- a/drivers/usb/ibmcam.h	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,240 +0,0 @@
-/*
- * Header file for USB IBM C-It Video Camera driver.
- *
- * Supports IBM C-It Video Camera.
- *
- * This driver is based on earlier work of:
- *
- * (C) Copyright 1999 Johannes Erdfelt
- * (C) Copyright 1999 Randy Dunlap
- */
-
-#ifndef __LINUX_IBMCAM_H
-#define __LINUX_IBMCAM_H
-
-#include <linux/list.h>
-
-#define USES_IBMCAM_PUTPIXEL    0       /* 0=Fast/oops 1=Slow/secure */
-
-/* Video Size 384 x 288 x 3 bytes for RGB */
-/* 384 because xawtv tries to grab 384 even though we tell it 352 is our max */
-#define V4L_FRAME_WIDTH         384
-#define V4L_FRAME_WIDTH_USED	352
-#define V4L_FRAME_HEIGHT        288
-#define V4L_BYTES_PER_PIXEL     3
-#define MAX_FRAME_SIZE          (V4L_FRAME_WIDTH * V4L_FRAME_HEIGHT * V4L_BYTES_PER_PIXEL)
-
-/* Camera capabilities (maximum) */
-#define CAMERA_IMAGE_WIDTH      352
-#define CAMERA_IMAGE_HEIGHT     288
-#define CAMERA_IMAGE_LINE_SZ    ((CAMERA_IMAGE_WIDTH * 3) / 2) /* Bytes */
-#define CAMERA_URB_FRAMES       32
-#define CAMERA_MAX_ISO_PACKET   1023 /* 1022 actually sent by camera */
-
-#define IBMCAM_NUMFRAMES	2
-#define IBMCAM_NUMSBUF		2
-
-#define FRAMES_PER_DESC		(CAMERA_URB_FRAMES)
-#define FRAME_SIZE_PER_DESC	(CAMERA_MAX_ISO_PACKET)
-
-/* This macro restricts an int variable to an inclusive range */
-#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
-
-/*
- * This macro performs bounds checking - use it when working with
- * new formats, or else you may get oopses all over the place.
- * If pixel falls out of bounds then it gets shoved back (as close
- * to place of offence as possible) and is painted bright red.
- */
-#define IBMCAM_PUTPIXEL(fr, ix, iy, vr, vg, vb) { \
-	register unsigned char *pf; \
-	int limiter = 0, mx, my; \
-	mx = ix; \
-	my = iy; \
-	if (mx < 0) { \
-		mx=0; \
-		limiter++; \
-	} else if (mx >= 352) { \
-		mx=351; \
-		limiter++; \
-	} \
-	if (my < 0) { \
-		my = 0; \
-		limiter++; \
-	} else if (my >= V4L_FRAME_HEIGHT) { \
-		my = V4L_FRAME_HEIGHT - 1; \
-		limiter++; \
-	} \
-	pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*352 + (ix)); \
-	if (limiter) { \
-		*pf++ = 0; \
-		*pf++ = 0; \
-		*pf++ = 0xFF; \
-	} else { \
-		*pf++ = (vb); \
-		*pf++ = (vg); \
-		*pf++ = (vr); \
-	} \
-}
-
-/*
- * We use macros to do YUV -> RGB conversion because this is
- * very important for speed and totally unimportant for size.
- *
- * YUV -> RGB Conversion
- * ---------------------
- *
- * B = 1.164*(Y-16)		    + 2.018*(V-128)
- * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
- * R = 1.164*(Y-16) + 1.596*(U-128)
- *
- * If you fancy integer arithmetics (as you should), hear this:
- *
- * 65536*B = 76284*(Y-16)		  + 132252*(V-128)
- * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
- * 65536*R = 76284*(Y-16) + 104595*(U-128)
- *
- * Make sure the output values are within [0..255] range.
- */
-#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
-#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
-    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
-    mm_y = (my) - 16;  \
-    mm_u = (mu) - 128; \
-    mm_v = (mv) - 128; \
-    mm_yc= mm_y * 76284; \
-    mm_b = (mm_yc		+ 132252*mm_v	) >> 16; \
-    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v	) >> 16; \
-    mm_r = (mm_yc + 104595*mm_u			) >> 16; \
-    mb = LIMIT_RGB(mm_b); \
-    mg = LIMIT_RGB(mm_g); \
-    mr = LIMIT_RGB(mm_r); \
-}
-
-/* Debugging aid */
-#define IBMCAM_SAY_AND_WAIT(what) { \
-	wait_queue_head_t wq; \
-	init_waitqueue_head(&wq); \
-	printk(KERN_INFO "Say: %s\n", what); \
-	interruptible_sleep_on_timeout (&wq, HZ*3); \
-}
-
-/*
- * This macro checks if ibmcam is still operational. The 'ibmcam'
- * pointer must be valid, ibmcam->dev must be valid, we are not
- * removing the device and the device has not erred on us.
- */
-#define IBMCAM_IS_OPERATIONAL(ibm_cam) (\
-	(ibm_cam != NULL) && \
-	((ibm_cam)->dev != NULL) && \
-	((ibm_cam)->last_error == 0) && \
-	(!(ibm_cam)->remove_pending))
-
-enum {
-	STATE_SCANNING,		/* Scanning for header */
-	STATE_LINES,		/* Parsing lines */
-};
-
-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 */
-};
-
-struct usb_device;
-
-struct ibmcam_sbuf {
-	char *data;
-	struct urb *urb;
-};
-
-struct ibmcam_frame {
-	char *data;		/* Frame buffer */
-	int order_uv;		/* True=UV False=VU */
-	int order_yc;		/* True=Yc False=cY ('c'=either U or V) */
-	unsigned char hdr_sig;	/* "00 FF 00 ??" where 'hdr_sig' is '??' */
-
-	int width;		/* Width application is expecting */
-	int height;		/* Height */
-
-	int frmwidth;		/* Width the frame actually is */
-	int frmheight;		/* Height */
-
-	volatile int grabstate;	/* State of grabbing */
-	int scanstate;		/* State of scanning */
-
-	int curline;		/* Line of frame we're working on */
-
-	long scanlength;	/* uncompressed, raw data length of frame */
-	long bytes_read;	/* amount of scanlength that has been read from *data */
-
-	wait_queue_head_t wq;	/* Processes waiting */
-};
-
-#define	IBMCAM_MODEL_1	1	/* XVP-501, 3 interfaces, rev. 0.02 */
-#define IBMCAM_MODEL_2	2	/* KSX-X9903, 2 interfaces, rev. 3.0a */
-
-struct usb_ibmcam {
-	struct video_device vdev;
-
-	/* Device structure */
-	struct usb_device *dev;
-
-	unsigned char iface;                            /* Video interface number */
-	unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */
-
-	struct semaphore lock;
-	int user;		/* user count for exclusive use */
-
-	int ibmcam_used;        /* Is this structure in use? */
-	int initialized;	/* Had we already sent init sequence? */
-	int camera_model;	/* What type of IBM camera we got? */
-	int streaming;		/* Are we streaming Isochronous? */
-	int grabbing;		/* Are we grabbing? */
-	int last_error;		/* What calamity struck us? */
-
-	int compress;		/* Should the next frame be compressed? */
-
-	char *fbuf;		/* Videodev buffer area */
-	int fbuf_size;		/* Videodev buffer size */
-
-	int curframe;
-	struct ibmcam_frame frame[IBMCAM_NUMFRAMES];	/* Double buffering */
-
-	int cursbuf;		/* Current receiving sbuf */
-	struct ibmcam_sbuf sbuf[IBMCAM_NUMSBUF];	/* Double buffering */
-	volatile int remove_pending;	/* If set then about to exit */
-
-        /*
-	 * Scratch space from the Isochronous pipe.
-	 * Scratch buffer should contain at least one pair of lines
-	 * (CAMERA_IMAGE_LINE_SZ). We set it to two pairs here.
-	 * This will be approximately 2 KB. HOWEVER in reality this
-	 * buffer must be as large as hundred of KB because otherwise
-	 * you'll get lots of overflows because V4L client may request
-	 * frames not as uniformly as USB sources them.
-	 */
-	unsigned char *scratch;
-	int scratchlen;
-
-	struct video_picture vpic, vpic_old;	/* Picture settings */
-	struct video_capability vcap;		/* Video capabilities */
-	struct video_channel vchan;	/* May be used for tuner support */
-	unsigned char video_endp;	/* 0x82 for IBM camera */
-        int has_hdr;
-        int frame_num;
-	int iso_packet_len;		/* Videomode-dependent, saves bus bandwidth */
-
-	/* Statistics that can be overlayed on screen */
-        unsigned long urb_count;        /* How many URBs we received so far */
-        unsigned long urb_length;       /* Length of last URB */
-        unsigned long data_count;       /* How many bytes we received */
-        unsigned long header_count;     /* How many frame headers we found */
-	unsigned long scratch_ovf_count;/* How many times we overflowed scratch */
-	unsigned long iso_skip_count;	/* How many empty ISO packets received */
-	unsigned long iso_err_count;	/* How many bad ISO packets received */
-};
-
-#endif /* __LINUX_IBMCAM_H */
diff -Nru a/drivers/usb/inode.c b/drivers/usb/inode.c
--- a/drivers/usb/inode.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/inode.c	Sun Feb 10 19:58:04 2002
@@ -36,7 +36,8 @@
 #include <linux/proc_fs.h>
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
-
+#include <linux/smp_lock.h>
+#include <asm/byteorder.h>
 
 static struct super_operations usbfs_ops;
 static struct address_space_operations usbfs_aops;
@@ -295,6 +296,7 @@
 {
 	loff_t retval = -EINVAL;
 
+	lock_kernel();
 	switch(orig) {
 	case 0:
 		if (offset > 0) {
@@ -311,6 +313,7 @@
 	default:
 		break;
 	}
+	unlock_kernel();
 	return retval;
 }
 
@@ -362,15 +365,14 @@
 	put_inode:	force_delete,
 };
 
-static struct super_block *usbfs_read_super (struct super_block *sb, void *data, 
-					     int silent)
+static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
 	struct dentry *root;
 
 	if (parse_options(sb, data)) {
 		warn("usbfs: mount parameter error:");
-		return NULL;
+		return -EINVAL;
 	}
 
 	sb->s_blocksize = PAGE_CACHE_SIZE;
@@ -381,17 +383,17 @@
 
 	if (!inode) {
 		dbg("%s: could not get inode!\n",__FUNCTION__);
-		return NULL;
+		return -ENOMEM;
 	}
 
 	root = d_alloc_root(inode);
 	if (!root) {
 		dbg("%s: could not get root dentry!\n",__FUNCTION__);
 		iput(inode);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root = root;
-	return sb;
+	return 0;
 }
 
 /**
@@ -520,8 +522,24 @@
  * It will be removed when the 2.7.x development cycle is started.
  * You have been warned :)
  */
-static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbfs_read_super, FS_SINGLE);
-static DECLARE_FSTYPE(usb_fs_type,       "usbfs",    usbfs_read_super, FS_SINGLE);
+
+static struct super_block *usb_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, usbfs_fill_super);
+}
+
+static struct file_system_type usbdevice_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"usbdevfs",
+	get_sb:		usb_get_sb,
+};
+
+static struct file_system_type usb_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"usbfs",
+	get_sb:		usb_get_sb,
+};
 
 /* --------------------------------------------------------------------- */
 static int get_mount (void)
diff -Nru a/drivers/usb/kaweth.c b/drivers/usb/kaweth.c
--- a/drivers/usb/kaweth.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/kaweth.c	Sun Feb 10 19:58:04 2002
@@ -55,6 +55,7 @@
 #include <linux/usb.h>
 #include <linux/types.h>
 #include <asm/semaphore.h>
+#include <asm/byteorder.h>
 
 #define DEBUG
 
@@ -155,6 +156,7 @@
  *     kaweth_driver
  ****************************************************************/
 static struct usb_driver kaweth_driver = {
+	owner:		THIS_MODULE,
 	name:		"kaweth",
 	probe:		kaweth_probe,
 	disconnect:	kaweth_disconnect,
@@ -238,8 +240,7 @@
 		return -EBUSY;
 	}
 
-	dr = kmalloc(sizeof(struct usb_ctrlrequest), 
-                     in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
 
 	if (!dr) {
 		kaweth_dbg("kmalloc() failed");
@@ -447,7 +448,8 @@
 /****************************************************************
  *     kaweth_resubmit_rx_urb
  ****************************************************************/
-static inline void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth)
+static inline void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
+						int mem_flags)
 {
 	int result;
 
@@ -461,7 +463,7 @@
 		      kaweth_usb_receive,
 		      kaweth);
 
-	if((result = usb_submit_urb(kaweth->rx_urb))) {
+	if((result = usb_submit_urb(kaweth->rx_urb, mem_flags))) {
 		kaweth_err("resubmitting rx_urb %d failed", result);
 	}
 }
@@ -493,7 +495,7 @@
 			   urb->status,
 			   count, 
 			   (int)pkt_len);
-		kaweth_resubmit_rx_urb(kaweth);
+		kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
                 return;
 	}
 
@@ -502,12 +504,12 @@
 			kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count);
 			kaweth_err("Packet len & 2047: %x", pkt_len & 2047);
 			kaweth_err("Count 2: %x", count2);
-		        kaweth_resubmit_rx_urb(kaweth);
+		        kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
                         return;
                 }
 		
 		if(!(skb = dev_alloc_skb(pkt_len+2))) {
-		        kaweth_resubmit_rx_urb(kaweth);
+		        kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
                         return;
 		}
 
@@ -525,7 +527,7 @@
 		kaweth->stats.rx_bytes += pkt_len;
 	}
 
-	kaweth_resubmit_rx_urb(kaweth);
+	kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
 }
 
 /****************************************************************
@@ -539,11 +541,11 @@
 
 	kaweth_dbg("Opening network device.");
 
-	kaweth_resubmit_rx_urb(kaweth);
+	MOD_INC_USE_COUNT;
 
-	netif_start_queue(net);
+	kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL);
 
-	MOD_INC_USE_COUNT;
+	netif_start_queue(net);
 
 	kaweth_async_set_rx_mode(kaweth);
 	return 0;
@@ -586,14 +588,10 @@
 {
 	struct kaweth_device *kaweth = urb->context;
 
-	spin_lock(&kaweth->device_lock);
-
-	if (urb->status)
+	if (unlikely(urb->status != 0))
 		kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
 
 	netif_wake_queue(kaweth->net);
-
-	spin_unlock(&kaweth->device_lock);
 }
 
 /****************************************************************
@@ -625,7 +623,7 @@
 		      kaweth_usb_transmit_complete,
 		      kaweth);
 
-	if((res = usb_submit_urb(kaweth->tx_urb)))
+	if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
 	{
 		kaweth_warn("kaweth failed tx_urb %d", res);
 		kaweth->stats.tx_errors++;
@@ -757,9 +755,7 @@
 	memset(kaweth, 0, sizeof(struct kaweth_device));
 
 	kaweth->dev = dev;
-	kaweth->status = 0;
-	kaweth->net = NULL;
-	kaweth->device_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&kaweth->device_lock);
 		
 	kaweth_dbg("Resetting.");
 
@@ -824,6 +820,7 @@
 
 		/* Device will now disappear for a moment...  */
 		kaweth_info("Firmware loaded.  I'll be back...");
+		kfree(kaweth);
 		return NULL;
 	}
 
@@ -925,6 +922,8 @@
 		kaweth_warn("unregistering non-existant device");
 		return;
 	}
+	usb_unlink_urb(kaweth->tx_urb);
+	usb_unlink_urb(kaweth->rx_urb);
 
 	if(kaweth->net) {
 		if(kaweth->net->flags & IFF_UP) {
@@ -978,7 +977,7 @@
         set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&awd.wqh, &wait);
         urb->context = &awd;
-        status = usb_submit_urb(urb);
+        status = usb_submit_urb(urb, GFP_KERNEL);
         if (status) {
                 // something went wrong
                 usb_free_urb(urb);
diff -Nru a/drivers/usb/mdc800.c b/drivers/usb/mdc800.c
--- a/drivers/usb/mdc800.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/usb/mdc800.c	Sun Feb 10 19:58:03 2002
@@ -98,6 +98,7 @@
 #include <linux/smp_lock.h>
 
 #include <linux/usb.h>
+#include <linux/fs.h>
 
 /*
  * Version Information
@@ -605,7 +606,7 @@
 
 	retval=0;
 	mdc800->irq_urb->dev = mdc800->dev;
-	if (usb_submit_urb (mdc800->irq_urb))
+	if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL))
 	{
 		err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
 		errn = -EIO;
@@ -694,7 +695,7 @@
 
 				/* Download -> Request new bytes */
 				mdc800->download_urb->dev = mdc800->dev;
-				if (usb_submit_urb (mdc800->download_urb))
+				if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL))
 				{
 					err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
 					up (&mdc800->io_lock);
@@ -808,7 +809,7 @@
 			mdc800->state=WORKING;
 			memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8);
 			mdc800->write_urb->dev = mdc800->dev;
-			if (usb_submit_urb (mdc800->write_urb))
+			if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL))
 			{
 				err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
 				up (&mdc800->io_lock);
diff -Nru a/drivers/usb/microtek.c b/drivers/usb/microtek.c
--- a/drivers/usb/microtek.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/microtek.c	Sun Feb 10 19:58:06 2002
@@ -499,7 +499,7 @@
 
 	transfer->status = 0;
 
-	res = usb_submit_urb( transfer );
+	res = usb_submit_urb( transfer, GFP_ATOMIC );
 	if ( unlikely(res) ) {
 		MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res );
 		context->srb->result = DID_ERROR << 16;
@@ -609,10 +609,11 @@
 	sg = context->srb->buffer;
 	context->fragment++;
 	mts_int_submit_urb(transfer,
-			context->data_pipe,
-			sg[context->fragment].address,
-			sg[context->fragment].length,
-			context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
+			   context->data_pipe,
+			   page_address(sg[context->fragment].page) +
+			   sg[context->fragment].offset,
+			   sg[context->fragment].length,
+			   context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
 	return;
 }
 
@@ -654,7 +655,7 @@
 	} else {
 		MTS_DEBUG("Using scatter/gather\n");
 		sg = srb->buffer;
-		desc->context.data = sg[0].address;
+		desc->context.data = page_address(sg[0].page) + sg[0].offset;
 		desc->context.data_length = sg[0].length;
 	}
 
@@ -719,7 +720,8 @@
 	mts_build_transfer_context( srb, desc );
 	desc->context.final_callback = callback;
 	
-	res=usb_submit_urb(desc->urb);
+	/* here we need ATOMIC as we are called with the iolock */
+	res=usb_submit_urb(desc->urb, GFP_ATOMIC);
 
 	if(unlikely(res)){
 		MTS_ERROR("error %d submitting URB\n",(int)res);
diff -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c
--- a/drivers/usb/ov511.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/ov511.c	Sun Feb 10 19:58:05 2002
@@ -4457,7 +4457,7 @@
 
 	for (n = 0; n < OV511_NUMSBUF; n++) {
 		ov511->sbuf[n].urb->dev = ov511->dev;
-		err = usb_submit_urb(ov511->sbuf[n].urb);
+		err = usb_submit_urb(ov511->sbuf[n].urb, GFP_KERNEL);
 		if (err)
 			err("init isoc: usb_submit_urb(%d) ret %d", n, err);
 	}
@@ -5618,7 +5618,7 @@
 	void *arg = (void *) ularg;
 	int rc;
 
-	pde = (struct proc_dir_entry *) inode->u.generic_ip;
+	pde = PDE(inode);
 	if (!pde)
 		return -ENOENT;
 
diff -Nru a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c
--- a/drivers/usb/pegasus.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/pegasus.c	Sun Feb 10 19:58:06 2002
@@ -48,12 +48,13 @@
 #include <linux/etherdevice.h>
 #include <linux/usb.h>
 #include <linux/module.h>
+#include <asm/byteorder.h>
 #include "pegasus.h"
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.4.22 (2001/12/07)"
+#define DRIVER_VERSION "v0.4.23 (2002/02/01)"
 #define DRIVER_AUTHOR "Petko Manolov <pmanolov@lnxw.com>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -115,7 +116,7 @@
 		case -ENOENT:
 			break;
 		default:
-			warn( __FUNCTION__ " status %d", urb->status);
+			warn("%s: status %d", __FUNCTION__, urb->status);
 	}
 	pegasus->flags &= ~ETH_REGS_CHANGED;
 	wake_up(&pegasus->ctrl_wait );
@@ -157,8 +158,9 @@
 	add_wait_queue( &pegasus->ctrl_wait, &wait );
 	set_current_state( TASK_UNINTERRUPTIBLE );
 
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) {
-		err( __FUNCTION__ " BAD CTRLs %d", ret);
+	/* using ATOMIC, we'd never wake up if we slept */
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
+		err("%s: BAD CTRLs %d", __FUNCTION__, ret);
 		goto out;
 	}
 
@@ -207,8 +209,8 @@
 	add_wait_queue( &pegasus->ctrl_wait, &wait );
 	set_current_state( TASK_UNINTERRUPTIBLE );
 
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) {
-		err( __FUNCTION__ " BAD CTRL %d", ret);
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
+		err("%s: BAD CTRL %d", __FUNCTION__, ret);
 		goto out;
 	}
 	
@@ -257,8 +259,8 @@
 	add_wait_queue( &pegasus->ctrl_wait, &wait );
 	set_current_state( TASK_UNINTERRUPTIBLE );
 
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) {
-		err( __FUNCTION__ " BAD CTRL %d", ret);
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
+		err("%s: BAD CTRL %d", __FUNCTION__, ret);
 		goto out;
 	}
 
@@ -287,8 +289,8 @@
 			  (char *)&pegasus->dr,
 			  pegasus->eth_regs, 3, ctrl_callback, pegasus );
 
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) )
-		err( __FUNCTION__ " BAD CTRL %d, flags %x",ret,pegasus->flags );
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) )
+		err("%s: BAD CTRL %d, flgs %x",__FUNCTION__,ret,pegasus->flags);
 
 	return	ret;
 }
@@ -313,7 +315,7 @@
 		*regd = le16_to_cpu(regdi);
 		return	0;
 	}
-	warn( __FUNCTION__ " failed" );
+	warn("%s: failed", __FUNCTION__);
 	
 	return 1;
 }
@@ -335,7 +337,7 @@
 	}
 	if ( i < REG_TIMEOUT )
 		return	0;
-	warn( __FUNCTION__ " failed" );
+	warn("%s: failed", __FUNCTION__);
 
 	return 1;
 }
@@ -361,7 +363,7 @@
 		*retdata = le16_to_cpu (retdatai);
 		return	0;
 	}
-	warn( __FUNCTION__ " failed" );
+	warn("%s: failed", __FUNCTION__);
 
 	return -1;
 }
@@ -405,7 +407,7 @@
 	disable_eprom_write( pegasus );
 	if ( i < REG_TIMEOUT )
 		return	0;
-	warn( __FUNCTION__ " failed" );
+	warn("%s: failed", __FUNCTION__);
 	return	-1;
 }
 #endif	/* PEGASUS_WRITE_EEPROM */
@@ -573,8 +575,8 @@
 			usb_rcvbulkpipe(pegasus->usb, 1),
 			pegasus->rx_buff, PEGASUS_MAX_MTU, 
 			read_bulk_callback, pegasus );
-	if ( (res = usb_submit_urb(pegasus->rx_urb)) )
-		warn( __FUNCTION__ " failed submint rx_urb %d", res);
+	if ( (res = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) )
+		warn("%s: failed submint rx_urb %d", __FUNCTION__, res);
 	pegasus->flags &= ~PEGASUS_RX_BUSY;
 }
 
@@ -661,7 +663,7 @@
 			pegasus->tx_buff, PEGASUS_MAX_MTU, 
 			write_bulk_callback, pegasus );
 	pegasus->tx_urb->transfer_buffer_length = count;
-	if ((res = usb_submit_urb(pegasus->tx_urb))) {
+	if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
 		warn("failed tx_urb %d", res);
 		pegasus->stats.tx_errors++;
 		netif_start_queue( net );
@@ -721,15 +723,15 @@
 			usb_rcvbulkpipe(pegasus->usb, 1),
 			pegasus->rx_buff, PEGASUS_MAX_MTU, 
 			read_bulk_callback, pegasus );
-	if ( (res = usb_submit_urb(pegasus->rx_urb)) )
-		warn( __FUNCTION__ " failed rx_urb %d", res );
+	if ( (res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)) )
+		warn("%s: failed rx_urb %d", __FUNCTION__, res);
 #ifdef	PEGASUS_USE_INTR
 	FILL_INT_URB( pegasus->intr_urb, pegasus->usb,
 			usb_rcvintpipe(pegasus->usb, 3),
 			pegasus->intr_buff, sizeof(pegasus->intr_buff),
 			intr_callback, pegasus, pegasus->intr_interval );
-	if ( (res = usb_submit_urb(pegasus->intr_urb)) )
-		warn( __FUNCTION__ " failed intr_urb %d", res);
+	if ( (res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)) )
+		warn("%s: failed intr_urb %d", __FUNCTION__, res);
 #endif
 	netif_start_queue( net );
 	pegasus->flags |= PEGASUS_RUNNING;
@@ -885,6 +887,9 @@
 
 	net = init_etherdev( NULL, 0 );
 	if ( !net ) {
+		usb_free_urb (pegasus->tx_urb);
+		usb_free_urb (pegasus->rx_urb);
+		usb_free_urb (pegasus->ctrl_urb);
 		kfree( pegasus );
 		return	NULL;
 	}
@@ -910,6 +915,9 @@
 	if ( reset_mac(pegasus) ) {
 		err("can't reset MAC");
 		unregister_netdev( pegasus->net );
+		usb_free_urb (pegasus->tx_urb);
+		usb_free_urb (pegasus->rx_urb);
+		usb_free_urb (pegasus->ctrl_urb);
 		kfree(pegasus->net);
 		kfree(pegasus);
 		pegasus = NULL;
@@ -947,10 +955,14 @@
 	pegasus->flags |= PEGASUS_UNPLUG;
 	unregister_netdev( pegasus->net );
 	usb_dec_dev_use( dev );
-	usb_free_urb (pegasus->intr_urb);
-	usb_free_urb (pegasus->tx_urb);
-	usb_free_urb (pegasus->rx_urb);
-	usb_free_urb (pegasus->ctrl_urb);
+	usb_unlink_urb(pegasus->intr_urb);
+	usb_unlink_urb(pegasus->tx_urb);
+	usb_unlink_urb(pegasus->rx_urb);
+	usb_unlink_urb(pegasus->ctrl_urb);
+	usb_free_urb(pegasus->intr_urb);
+	usb_free_urb(pegasus->tx_urb);
+	usb_free_urb(pegasus->rx_urb);
+	usb_free_urb(pegasus->ctrl_urb);
 	kfree( pegasus->net );
 	kfree( pegasus );
 	pegasus = NULL;
diff -Nru a/drivers/usb/printer.c b/drivers/usb/printer.c
--- a/drivers/usb/printer.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/printer.c	Sun Feb 10 19:58:04 2002
@@ -20,6 +20,7 @@
  *	v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
  *	v0.8 - add devfs support
  *	v0.9 - fix unplug-while-open paths
+ *	v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
  */
 
 /*
@@ -54,7 +55,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.8"
+#define DRIVER_VERSION "v0.10"
 #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"
 #define DRIVER_DESC "USB Printer Device Class driver"
 
@@ -95,6 +96,8 @@
 	int			readcount;		/* Counter for reads */
 	int			ifnum;			/* Interface number */
 	int			minor;			/* minor number of device */
+	int			wcomplete;		/* writing is completed */
+	int			rcomplete;		/* reading is completed */		
 	unsigned int		quirks;			/* quirks flags */
 	unsigned char		used;			/* True if open */
 	unsigned char		bidir;			/* interface is bidirectional */
@@ -151,17 +154,31 @@
  * URB callback.
  */
 
-static void usblp_bulk(struct urb *urb)
+static void usblp_bulk_read(struct urb *urb)
 {
 	struct usblp *usblp = urb->context;
 
 	if (!usblp || !usblp->dev || !usblp->used)
 		return;
 
-	if (urb->status)
+	if (unlikely(urb->status))
 		warn("usblp%d: nonzero read/write bulk status received: %d",
 			usblp->minor, urb->status);
+	usblp->rcomplete = 1;
+	wake_up_interruptible(&usblp->wait);
+}
 
+static void usblp_bulk_write(struct urb *urb)
+{
+	struct usblp *usblp = urb->context;
+
+	if (!usblp || !usblp->dev || !usblp->used)
+		return;
+
+	if (unlikely(urb->status))
+		warn("usblp%d: nonzero read/write bulk status received: %d",
+			usblp->minor, urb->status);
+	usblp->wcomplete = 1;
 	wake_up_interruptible(&usblp->wait);
 }
 
@@ -238,11 +255,13 @@
 
 	usblp->writeurb.transfer_buffer_length = 0;
 	usblp->writeurb.status = 0;
+	usblp->wcomplete = 1; /* we begin writeable */
+	usblp->rcomplete = 0;
 
 	if (usblp->bidir) {
 		usblp->readcount = 0;
 		usblp->readurb.dev = usblp->dev;
-		if (usb_submit_urb(&usblp->readurb) < 0) {
+		if (usb_submit_urb(&usblp->readurb, GFP_KERNEL) < 0) {
 			retval = -EIO;
 			usblp->used = 0;
 			file->private_data = NULL;
@@ -369,26 +388,33 @@
 
 static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
+	DECLARE_WAITQUEUE(wait, current);
 	struct usblp *usblp = file->private_data;
 	int timeout, err = 0, writecount = 0;
 
 	while (writecount < count) {
-
-		// FIXME:  only use urb->status inside completion
-		// callbacks; this way is racey...
-		if (usblp->writeurb.status == -EINPROGRESS) {
-
+		if (!usblp->wcomplete) {
+			barrier();
 			if (file->f_flags & O_NONBLOCK)
 				return -EAGAIN;
 
 			timeout = USBLP_WRITE_TIMEOUT;
-			while (timeout && usblp->writeurb.status == -EINPROGRESS) {
+			add_wait_queue(&usblp->wait, &wait);
+			while ( 1==1 ) {
 
-				if (signal_pending(current))
+				if (signal_pending(current)) {
+					remove_wait_queue(&usblp->wait, &wait);
 					return writecount ? writecount : -EINTR;
-
-				timeout = interruptible_sleep_on_timeout(&usblp->wait, timeout);
+				}
+				set_current_state(TASK_INTERRUPTIBLE);
+				if (timeout && !usblp->wcomplete) {
+					timeout = schedule_timeout(timeout);
+				} else {
+					set_current_state(TASK_RUNNING);
+					break;
+				}
 			}
+			remove_wait_queue(&usblp->wait, &wait);
 		}
 
 		down (&usblp->sem);
@@ -399,7 +425,7 @@
 
 		if (usblp->writeurb.status != 0) {
 			if (usblp->quirks & USBLP_QUIRK_BIDIR) {
-				if (usblp->writeurb.status != -EINPROGRESS)
+				if (!usblp->wcomplete)
 					err("usblp%d: error %d writing to printer",
 						usblp->minor, usblp->writeurb.status);
 				err = usblp->writeurb.status;
@@ -429,7 +455,12 @@
 				usblp->writeurb.transfer_buffer_length)) return -EFAULT;
 
 		usblp->writeurb.dev = usblp->dev;
-		usb_submit_urb(&usblp->writeurb);
+		usblp->wcomplete = 0;
+		if (usb_submit_urb(&usblp->writeurb, GFP_KERNEL)) {
+			count = -EIO;
+			up (&usblp->sem);
+			break;
+		}
 		up (&usblp->sem);
 	}
 
@@ -439,6 +470,7 @@
 static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct usblp *usblp = file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
 
 	if (!usblp->bidir)
 		return -EINVAL;
@@ -449,7 +481,8 @@
 		goto done;
 	}
 
-	if (usblp->readurb.status == -EINPROGRESS) {
+	if (!usblp->rcomplete) {
+		barrier();
 
 		if (file->f_flags & O_NONBLOCK) {
 			count = -EAGAIN;
@@ -458,15 +491,24 @@
 
 		// FIXME:  only use urb->status inside completion
 		// callbacks; this way is racey...
-		while (usblp->readurb.status == -EINPROGRESS) {
+		add_wait_queue(&usblp->wait, &wait);
+		while (1==1) {
 			if (signal_pending(current)) {
 				count = -EINTR;
+				remove_wait_queue(&usblp->wait, &wait);
 				goto done;
 			}
 			up (&usblp->sem);
-			interruptible_sleep_on(&usblp->wait);
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (!usblp->rcomplete) {
+				schedule();
+			} else {
+				set_current_state(TASK_RUNNING);
+				break;
+			}
 			down (&usblp->sem);
 		}
+		remove_wait_queue(&usblp->wait, &wait);
 	}
 
 	if (!usblp->dev) {
@@ -479,7 +521,7 @@
 			usblp->minor, usblp->readurb.status);
 		usblp->readurb.dev = usblp->dev;
  		usblp->readcount = 0;
-		usb_submit_urb(&usblp->readurb);
+		usb_submit_urb(&usblp->readurb, GFP_KERNEL);
 		count = -EIO;
 		goto done;
 	}
@@ -495,7 +537,11 @@
 	if ((usblp->readcount += count) == usblp->readurb.actual_length) {
 		usblp->readcount = 0;
 		usblp->readurb.dev = usblp->dev;
-		usb_submit_urb(&usblp->readurb);
+		usblp->rcomplete = 0;
+		if (usb_submit_urb(&usblp->readurb, GFP_KERNEL)) {
+			count = -EIO;
+			goto done;
+		}
 	}
 
 done:
@@ -636,11 +682,11 @@
 	}
 
 	FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
-		buf, 0, usblp_bulk, usblp);
+		buf, 0, usblp_bulk_write, usblp);
 
 	if (bidir)
 		FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
-			buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp);
+			buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk_read, usblp);
 
 	/* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */
 	err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
@@ -715,6 +761,7 @@
 MODULE_DEVICE_TABLE (usb, usblp_ids);
 
 static struct usb_driver usblp_driver = {
+	owner:		THIS_MODULE,
 	name:		"usblp",
 	probe:		usblp_probe,
 	disconnect:	usblp_disconnect,
diff -Nru a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
--- a/drivers/usb/pwc-if.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/pwc-if.c	Sun Feb 10 19:58:06 2002
@@ -869,7 +869,7 @@
 
 	/* link */
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		ret = usb_submit_urb(pdev->sbuf[i].urb);
+		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
 		if (ret)
 			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
 		else
diff -Nru a/drivers/usb/scanner.c b/drivers/usb/scanner.c
--- a/drivers/usb/scanner.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/scanner.c	Sun Feb 10 19:58:05 2002
@@ -328,6 +328,8 @@
  *      24 Bit Color ~ 70 secs - 3.6 Mbit/sec
  *       8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */
 
+#include <asm/byteorder.h>
+
 /* 
  * Scanner definitions, macros, module info, 
  * debug/ioctl/data_dump enable, and other constants.
@@ -992,7 +994,7 @@
 			     // endpoint[(int)have_intr].bInterval);
 			     250);
 
-	        if (usb_submit_urb(scn->scn_irq)) {
+	        if (usb_submit_urb(scn->scn_irq, GFP_KERNEL)) {
 			err("probe_scanner(%d): Unable to allocate INT URB.", scn_minor);
                 	kfree(scn);
 			up(&scn_mutex);
diff -Nru a/drivers/usb/se401.c b/drivers/usb/se401.c
--- a/drivers/usb/se401.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/se401.c	Sun Feb 10 19:58:05 2002
@@ -556,7 +556,7 @@
 	/* Resubmit urb for new data */
 	urb->status=0;
 	urb->dev=se401->dev;
-	if(usb_submit_urb(urb))
+	if(usb_submit_urb(urb, GFP_KERNEL))
 		info("urb burned down");
 	return;
 }
@@ -657,7 +657,7 @@
 
 		se401->urb[i]=urb;
 
-		err=usb_submit_urb(se401->urb[i]);
+		err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
 		if(err)
 			err("urb burned down");
 	}
@@ -1477,7 +1477,7 @@
 	    se401,
 	    HZ/10
 	);
-	if (usb_submit_urb(se401->inturb)) {
+	if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
 		info("int urb burned down");
 		return 1;
 	}
diff -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/serial/belkin_sa.c	Sun Feb 10 19:58:04 2002
@@ -217,14 +217,14 @@
 		 *       enhance buffering.  Win trace shows 16 initial read URBs.
 		 */
 		port->read_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->read_urb);
+		retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (retval) {
 			err("usb_submit_urb(read bulk) failed");
 			goto exit;
 		}
 
 		port->interrupt_in_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->interrupt_in_urb);
+		retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 		if (retval)
 			err(" usb_submit_urb(read int) failed");
 	}
diff -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/serial/cyberjack.c	Sun Feb 10 19:58:05 2002
@@ -173,7 +173,7 @@
 		usb_unlink_urb (port->interrupt_in_urb);
 
 		port->interrupt_in_urb->dev = port->serial->dev;
-		result = usb_submit_urb(port->interrupt_in_urb);
+		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 		if (result)
 			err(" usb_submit_urb(read int) failed");
 		dbg(__FUNCTION__ " - usb_submit_urb(int urb)");
@@ -271,7 +271,7 @@
 			      port);
 
 		/* send the data out the bulk port */
-		result = usb_submit_urb(port->write_urb);
+		result = usb_submit_urb(port->write_urb, GFP_KERNEL);
 		if (result) {
 			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
 			/* Throw away data. No better idea what to do with it. */
@@ -342,7 +342,7 @@
 
 		if( !old_rdtodo ) {
 			port->read_urb->dev = port->serial->dev;
-			result = usb_submit_urb(port->read_urb);
+			result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 			if( result )
 				err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 			dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
@@ -398,7 +398,7 @@
 	/* Continue to read if we have still urbs to do. */
 	if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
 		port->read_urb->dev = port->serial->dev;
-		result = usb_submit_urb(port->read_urb);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result)
 			err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 		dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
@@ -453,7 +453,7 @@
 			      port);
 
 		/* send the data out the bulk port */
-		result = usb_submit_urb(port->write_urb);
+		result = usb_submit_urb(port->write_urb, GFP_KERNEL);
 		if (result) {
 			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
 			/* Throw away data. No better idea what to do with it. */
diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
--- a/drivers/usb/serial/digi_acceleport.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/serial/digi_acceleport.c	Sun Feb 10 19:58:06 2002
@@ -676,7 +676,7 @@
 		oob_port->write_urb->transfer_buffer_length = len;
 		oob_port->write_urb->dev = port->serial->dev;
 
-		if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) {
+		if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
 			oob_priv->dp_write_urb_in_use = 1;
 			count -= len;
 			buf += len;
@@ -764,7 +764,7 @@
 		}
 		port->write_urb->dev = port->serial->dev;
 
-		if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
+		if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
 			priv->dp_write_urb_in_use = 1;
 			priv->dp_out_buf_len = 0;
 			count -= len;
@@ -841,7 +841,7 @@
 	oob_port->write_urb->transfer_buffer_length = 8;
 	oob_port->write_urb->dev = port->serial->dev;
 
-	if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) {
+	if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
 		oob_priv->dp_write_urb_in_use = 1;
 		port_priv->dp_modem_signals =
 			(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
@@ -962,7 +962,7 @@
 	/* restart read chain */
 	if( priv->dp_throttle_restart ) {
 		port->read_urb->dev = port->serial->dev;
-		ret = usb_submit_urb( port->read_urb );
+		ret = usb_submit_urb( port->read_urb, GFP_KERNEL );
 	}
 
 	/* turn throttle off */
@@ -1323,7 +1323,7 @@
 	/* copy in new data */
 	memcpy( data, from_user ? user_buf : buf, new_len );
 
-	if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
+	if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
 		priv->dp_write_urb_in_use = 1;
 		ret = new_len;
 		priv->dp_out_buf_len = 0;
@@ -1399,7 +1399,7 @@
 		memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf,
 			priv->dp_out_buf_len );
 
-		if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
+		if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
 			priv->dp_write_urb_in_use = 1;
 			priv->dp_out_buf_len = 0;
 		}
@@ -1677,7 +1677,7 @@
 
 		port->write_urb->dev = port->serial->dev;
 
-		if( (ret=usb_submit_urb(port->read_urb)) != 0 ) {
+		if( (ret=usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0 ) {
 			err(
 			__FUNCTION__ ": usb_submit_urb failed, ret=%d, port=%d",
 			ret, i );
@@ -1837,7 +1837,7 @@
 
 	/* continue read */
 	urb->dev = port->serial->dev;
-	if( (ret=usb_submit_urb(urb)) != 0 ) {
+	if( (ret=usb_submit_urb(urb, GFP_KERNEL)) != 0 ) {
 		err( __FUNCTION__ ": failed resubmitting urb, ret=%d, port=%d",
 			ret, priv->dp_port_num );
 	}
diff -Nru a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
--- a/drivers/usb/serial/empeg.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/serial/empeg.c	Sun Feb 10 19:58:06 2002
@@ -182,7 +182,7 @@
 
 		port->read_urb->transfer_flags |= USB_QUEUE_BULK;
 
-		result = usb_submit_urb(port->read_urb);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 
 		if (result)
 			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
@@ -296,7 +296,7 @@
 		urb->transfer_flags |= USB_QUEUE_BULK;
 
 		/* send it down the pipe */
-		status = usb_submit_urb(urb);
+		status = usb_submit_urb(urb, GFP_KERNEL);
 		if (status) {
 			err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
 			bytes_sent = status;
@@ -449,7 +449,7 @@
 
 	port->read_urb->transfer_flags |= USB_QUEUE_BULK;
 
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -484,7 +484,7 @@
 
 	port->read_urb->dev = port->serial->dev;
 
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 
 	if (result)
 		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/serial/ftdi_sio.c	Sun Feb 10 19:58:05 2002
@@ -356,7 +356,7 @@
 			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
 			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 			      ftdi_sio_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result)
 			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 	}
@@ -479,7 +479,7 @@
 		      port->write_urb->transfer_buffer, count,
 		      ftdi_sio_write_bulk_callback, port);
 		
-	result = usb_submit_urb(port->write_urb);
+	result = usb_submit_urb(port->write_urb, GFP_KERNEL);
 	if (result) {
 		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
 		up (&port->sem);
@@ -644,7 +644,7 @@
 		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 		      ftdi_sio_read_bulk_callback, port);
 
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/serial/io_edgeport.c	Sun Feb 10 19:58:04 2002
@@ -787,7 +787,7 @@
 
 					/* we have pending bytes on the bulk in pipe, send a request */
 					edge_serial->read_urb->dev = edge_serial->serial->dev;
-					result = usb_submit_urb(edge_serial->read_urb);
+					result = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
 					if (result) {
 						dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result);
 					}
@@ -864,7 +864,7 @@
 
 			/* there is, so resubmit our urb */
 			edge_serial->read_urb->dev = edge_serial->serial->dev;
-			status = usb_submit_urb(edge_serial->read_urb);
+			status = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
 			if (status) {
 				err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status);
 			}
@@ -1031,7 +1031,7 @@
 
 			/* start interrupt read for this edgeport
 			 * this interrupt will continue as long as the edgeport is connected */
-			response = usb_submit_urb (edge_serial->interrupt_read_urb);
+			response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
 			if (response) {
 				err(__FUNCTION__" - Error %d submitting control urb", response);
 			}
@@ -1471,7 +1471,7 @@
 	urb->transfer_flags |= USB_QUEUE_BULK;
 
 	urb->dev = edge_serial->serial->dev;
-	status = usb_submit_urb(urb);
+	status = usb_submit_urb(urb, GFP_KERNEL);
 	if (status) {
 		/* something went wrong */
 		dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
@@ -2477,7 +2477,7 @@
 	urb->transfer_flags |= USB_QUEUE_BULK;
 
 	edge_port->commandPending = TRUE;
-	status = usb_submit_urb(urb);
+	status = usb_submit_urb(urb, GFP_KERNEL);
 
 	if (status) {
 		/* something went wrong */
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/serial/ipaq.c	Sun Feb 10 19:58:05 2002
@@ -171,7 +171,7 @@
 			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
 			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 			      ipaq_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result) {
 			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 		}
@@ -288,7 +288,7 @@
 		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
 		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 		      ipaq_read_bulk_callback, port);
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 	return;
@@ -403,7 +403,7 @@
 		      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
 		      port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
 		      port);
-	result = usb_submit_urb(urb);
+	result = usb_submit_urb(urb, GFP_KERNEL);
 	if (result) {
 		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
 	}
diff -Nru a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
--- a/drivers/usb/serial/ir-usb.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/serial/ir-usb.c	Sun Feb 10 19:58:06 2002
@@ -289,7 +289,7 @@
 			ir_read_bulk_callback,
 			port);
 		port->read_urb->transfer_flags = USB_QUEUE_BULK;
-		result = usb_submit_urb(port->read_urb);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result)
 			err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
 	}
@@ -382,7 +382,7 @@
 		= USB_QUEUE_BULK
 		| USB_ZERO_PACKET;
 
-	result = usb_submit_urb (port->write_urb);
+	result = usb_submit_urb (port->write_urb, GFP_KERNEL);
 	if (result)
 		err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 	else
@@ -492,7 +492,7 @@
 
 			port->read_urb->transfer_flags = USB_QUEUE_BULK;
 
-			result = usb_submit_urb(port->read_urb);
+			result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 
 			if (result)
 				err("%s - failed resubmitting read urb, error %d",
@@ -591,7 +591,7 @@
 			= USB_QUEUE_BULK
 			| USB_ZERO_PACKET;
 
-		result = usb_submit_urb (port->write_urb);
+		result = usb_submit_urb (port->write_urb, GFP_KERNEL);
 		if (result)
 			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 	}
diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
--- a/drivers/usb/serial/keyspan.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/serial/keyspan.c	Sun Feb 10 19:58:04 2002
@@ -378,7 +378,7 @@
 
 		this_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
 		this_urb->dev = port->serial->dev;
-		if ((err = usb_submit_urb(this_urb)) != 0) {
+		if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) {
 			dbg("usb_submit_urb(write bulk) failed (%d)\n", err);
 		}
 		p_priv->tx_start_time[flip] = jiffies;
@@ -436,7 +436,7 @@
 				
 		/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if ((err = usb_submit_urb(urb)) != 0) {
+	if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
 	}
 	return;
@@ -535,7 +535,7 @@
 exit:
 	/* Resubmit urb so we continue receiving */
 	urb->dev = serial->dev;
-	if ((err = usb_submit_urb(urb)) != 0) {
+	if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
 	}
 }
@@ -586,7 +586,7 @@
 
 		/* Resubmit urb so we continue receiving */
 		urb->dev = port->serial->dev;
-		if ((err = usb_submit_urb(urb)) != 0) {
+		if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
 			dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n",
 err);
 		}
@@ -671,7 +671,7 @@
 exit:	
 		/* Resubmit urb so we continue receiving */
 	urb->dev = serial->dev;
-	if ((err = usb_submit_urb(urb)) != 0) {
+	if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
 	}
 }
@@ -764,7 +764,7 @@
 		/* Resubmit urb so we continue receiving */
 	urb->dev = serial->dev;
 
-	if ((err = usb_submit_urb(urb)) != 0) {
+	if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
 	}
 }
@@ -819,7 +819,7 @@
 				
 		/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if ((err = usb_submit_urb(urb)) != 0) {
+	if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
 	}
 }
@@ -880,7 +880,7 @@
 		if ((urb = p_priv->in_urbs[i]) == NULL)
 			continue;
 		urb->dev = serial->dev;
-		if ((err = usb_submit_urb(urb)) != 0) {
+		if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
 			dbg(__FUNCTION__ " submit urb %d failed (%d)\n", i, err);
 		}
 	}
@@ -1408,7 +1408,7 @@
 	this_urb->transfer_buffer_length = sizeof(msg);
 
 	this_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(this_urb)) != 0) {
+	if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ " usb_submit_urb(setup) failed (%d)\n", err);
 	}
 #if 0
@@ -1494,7 +1494,7 @@
 	this_urb->transfer_buffer_length = sizeof(msg);
 
 	this_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(this_urb)) != 0) {
+	if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ " usb_submit_urb(setup) failed\n");
 	}
 #if 0
@@ -1622,7 +1622,7 @@
 	this_urb->transfer_buffer_length = sizeof(msg);
 
 	this_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(this_urb)) != 0) {
+	if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ " usb_submit_urb(setup) failed (%d)\n", err);
 	}
 #if 0
@@ -1708,7 +1708,7 @@
 	keyspan_setup_urbs(serial);
 
 	s_priv->instat_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(s_priv->instat_urb)) != 0) {
+	if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) {
 		dbg(__FUNCTION__ " submit instat urb failed %d\n", err);
 	}
 			
diff -Nru a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
--- a/drivers/usb/serial/keyspan_pda.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/serial/keyspan_pda.c	Sun Feb 10 19:58:04 2002
@@ -292,7 +292,7 @@
 	/* just restart the receive interrupt URB */
 	dbg("keyspan_pda_rx_unthrottle port %d", port->number);
 	port->interrupt_in_urb->dev = port->serial->dev;
-	if (usb_submit_urb(port->interrupt_in_urb))
+	if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
 		dbg(" usb_submit_urb(read urb) failed");
 	return;
 }
@@ -584,7 +584,7 @@
 		priv->tx_room -= count;
 
 		port->write_urb->dev = port->serial->dev;
-		rc = usb_submit_urb(port->write_urb);
+		rc = usb_submit_urb(port->write_urb, GFP_KERNEL);
 		if (rc) {
 			dbg(" usb_submit_urb(write bulk) failed");
 			goto exit;
@@ -699,7 +699,7 @@
 
 		/*Start reading from the device*/
 		port->interrupt_in_urb->dev = serial->dev;
-		rc = usb_submit_urb(port->interrupt_in_urb);
+		rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 		if (rc) {
 			dbg(__FUNCTION__" - usb_submit_urb(read int) failed");
 			goto error;
diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
--- a/drivers/usb/serial/kl5kusb105.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/usb/serial/kl5kusb105.c	Sun Feb 10 19:58:03 2002
@@ -404,7 +404,7 @@
 			      port);
 		port->read_urb->transfer_flags |= USB_QUEUE_BULK;
 
-		rc = usb_submit_urb(port->read_urb);
+		rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (rc) {
 			err(__FUNCTION__ 
 			    " - failed submitting read urb, error %d", rc);
@@ -567,7 +567,7 @@
 
 
 		/* send the data out the bulk port */
-		result = usb_submit_urb(urb);
+		result = usb_submit_urb(urb, GFP_KERNEL);
 		if (result) {
 			err(__FUNCTION__
 			    " - failed submitting write urb, error %d", result);
@@ -734,7 +734,7 @@
 		      port->read_urb->transfer_buffer_length,
 		      klsi_105_read_bulk_callback,
 		      port);
-	rc = usb_submit_urb(port->read_urb);
+	rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (rc)
 		err(__FUNCTION__ 
 		    " - failed resubmitting read urb, error %d", rc);
@@ -1041,7 +1041,7 @@
 	down (&port->sem);
 
 	port->read_urb->dev = port->serial->dev;
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed submitting read urb, error %d",
 		    result);
diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/serial/mct_u232.c	Sun Feb 10 19:58:04 2002
@@ -384,14 +384,14 @@
 		}
 
 		port->read_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->read_urb);
+		retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (retval) {
 			err("usb_submit_urb(read bulk) failed");
 			goto exit;
 		}
 
 		port->interrupt_in_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->interrupt_in_urb);
+		retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 		if (retval)
 			err(" usb_submit_urb(read int) failed");
 
@@ -482,7 +482,7 @@
 			      port);
 		
 		/* send the data out the bulk port */
-		result = usb_submit_urb(port->write_urb);
+		result = usb_submit_urb(port->write_urb, GFP_KERNEL);
 		if (result) {
 			err(__FUNCTION__
 			    " - failed submitting write urb, error %d", result);
diff -Nru a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
--- a/drivers/usb/serial/omninet.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/serial/omninet.c	Sun Feb 10 19:58:05 2002
@@ -179,7 +179,7 @@
 			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
 			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 			      omninet_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result)
 			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 	}
@@ -274,7 +274,7 @@
 		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
 		      urb->transfer_buffer, urb->transfer_buffer_length,
 		      omninet_read_bulk_callback, port);
-	result = usb_submit_urb(urb);
+	result = usb_submit_urb(urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 
@@ -325,7 +325,7 @@
 	wport->write_urb->transfer_buffer_length = 64;
 
 	wport->write_urb->dev = serial->dev;
-	result = usb_submit_urb(wport->write_urb);
+	result = usb_submit_urb(wport->write_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
 	else
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/serial/pl2303.c	Sun Feb 10 19:58:06 2002
@@ -195,7 +195,7 @@
 
 	port->write_urb->transfer_buffer_length = count;
 	port->write_urb->dev = port->serial->dev;
-	result = usb_submit_urb (port->write_urb);
+	result = usb_submit_urb (port->write_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
 	else
@@ -404,7 +404,7 @@
 
 		dbg (__FUNCTION__ " - submitting read urb");
 		port->read_urb->dev = serial->dev;
-		result = usb_submit_urb (port->read_urb);
+		result = usb_submit_urb (port->read_urb, GFP_KERNEL);
 		if (result) {
 			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 			up (&port->sem);
@@ -414,7 +414,7 @@
 
 		dbg (__FUNCTION__ " - submitting interrupt urb");
 		port->interrupt_in_urb->dev = serial->dev;
-		result = usb_submit_urb (port->interrupt_in_urb);
+		result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
 		if (result) {
 			err(__FUNCTION__ " - failed submitting interrupt urb, error %d", result);
 			up (&port->sem);
@@ -652,7 +652,7 @@
 			dbg (__FUNCTION__ " - caught -EPROTO, resubmitting the urb");
 			urb->status = 0;
 			urb->dev = serial->dev;
-			result = usb_submit_urb(urb);
+			result = usb_submit_urb(urb, GFP_KERNEL);
 			if (result)
 				err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 			return;
@@ -677,7 +677,7 @@
 	/* Schedule the next read _if_ we are still open */
 	if (port->open_count) {
 		urb->dev = serial->dev;
-		result = usb_submit_urb(urb);
+		result = usb_submit_urb(urb, GFP_KERNEL);
 		if (result)
 			err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 	}
@@ -706,7 +706,7 @@
 		dbg (__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
 		port->write_urb->transfer_buffer_length = 1;
 		port->write_urb->dev = port->serial->dev;
-		result = usb_submit_urb (port->write_urb);
+		result = usb_submit_urb (port->write_urb, GFP_KERNEL);
 		if (result)
 			err(__FUNCTION__ " - failed resubmitting write urb, error %d", result);
 
diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
--- a/drivers/usb/serial/usbserial.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/serial/usbserial.c	Sun Feb 10 19:58:06 2002
@@ -813,7 +813,7 @@
 					     serial->type->read_bulk_callback :
 					     generic_read_bulk_callback),
 					   port);
-			result = usb_submit_urb(port->read_urb);
+			result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 			if (result)
 				err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 		}
@@ -894,7 +894,7 @@
 				     generic_write_bulk_callback), port);
 
 		/* send the data out the bulk port */
-		result = usb_submit_urb(port->write_urb);
+		result = usb_submit_urb(port->write_urb, GFP_KERNEL);
 		if (result)
 			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
 		else
@@ -987,7 +987,7 @@
 			   ((serial->type->read_bulk_callback) ? 
 			     serial->type->read_bulk_callback : 
 			     generic_read_bulk_callback), port);
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 }
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/serial/visor.c	Sun Feb 10 19:58:05 2002
@@ -274,7 +274,7 @@
 				   port->read_urb->transfer_buffer,
 				   port->read_urb->transfer_buffer_length,
 				   visor_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result)
 			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 	}
@@ -388,7 +388,7 @@
 		urb->transfer_flags |= USB_QUEUE_BULK;
 
 		/* send it down the pipe */
-		status = usb_submit_urb(urb);
+		status = usb_submit_urb(urb, GFP_KERNEL);
 		if (status) {
 			err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
 			bytes_sent = status;
@@ -520,7 +520,7 @@
 			   port->read_urb->transfer_buffer,
 			   port->read_urb->transfer_buffer_length,
 			   visor_read_bulk_callback, port);
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 	return;
@@ -551,7 +551,7 @@
 	down (&port->sem);
 
 	port->read_urb->dev = port->serial->dev;
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/serial/whiteheat.c	Sun Feb 10 19:58:05 2002
@@ -240,7 +240,7 @@
 		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
 		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 		      command_port_read_callback, port);
-	result = usb_submit_urb(port->read_urb);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 }
@@ -265,7 +265,7 @@
 	memcpy (&transfer_buffer[1], data, datasize);
 	port->write_urb->transfer_buffer_length = datasize + 1;
 	port->write_urb->dev = serial->dev;
-	retval = usb_submit_urb (port->write_urb);
+	retval = usb_submit_urb (port->write_urb, GFP_KERNEL);
 	if (retval) {
 		dbg (__FUNCTION__" - submit urb failed");
 		goto exit;
@@ -327,7 +327,7 @@
 			command_port->read_urb->complete = command_port_read_callback;
 			command_port->read_urb->dev = port->serial->dev;
 			command_port->tty = port->tty;		/* need this to "fake" our our sanity check macros */
-			retval = usb_submit_urb (command_port->read_urb);
+			retval = usb_submit_urb (command_port->read_urb, GFP_KERNEL);
 			if (retval) {
 				err(__FUNCTION__ " - failed submitting read urb, error %d", retval);
 				goto error_exit;
@@ -336,7 +336,7 @@
 		
 		/* Start reading from the device */
 		port->read_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->read_urb);
+		retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (retval) {
 			err(__FUNCTION__ " - failed submitting read urb, error %d", retval);
 			goto error_exit;
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/storage/freecom.c	Sun Feb 10 19:58:06 2002
@@ -144,11 +144,11 @@
 			if (transfer_amount - total_transferred >= 
 					sg[i].length) {
 				result = usb_stor_transfer_partial(us,
-						sg[i].address, sg[i].length);
+						page_address(sg[i].page) + sg[i].offset, sg[i].length);
 				total_transferred += sg[i].length;
 			} else {
 				result = usb_stor_transfer_partial(us,
-						sg[i].address,
+						page_address(sg[i].page) + sg[i].offset,
 						transfer_amount - total_transferred);
 				total_transferred += transfer_amount - total_transferred;
 			}
diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/storage/isd200.c	Sun Feb 10 19:58:06 2002
@@ -518,13 +518,13 @@
                             sg[i].length) {
                                 result = isd200_transfer_partial(us, 
                                                                  srb->sc_data_direction,
-                                                                 sg[i].address, 
+                                                                 page_address(sg[i].page) + sg[i].offset, 
                                                                  sg[i].length);
                                 total_transferred += sg[i].length;
                         } else
                                 result = isd200_transfer_partial(us, 
                                                                  srb->sc_data_direction,                            
-                                                                 sg[i].address,
+                                                                 page_address(sg[i].page) + sg[i].offset,
                                                                  transfer_amount - total_transferred);
 
                         /* if we get an error, end the loop here */
@@ -1415,10 +1415,10 @@
 				/* transfer the lesser of the next buffer or the
 				 * remaining data */
 				if (len - total >= sg[i].length) {
-					memcpy(sg[i].address, src + total, sg[i].length);
+					memcpy(page_address(sg[i].page) + sg[i].offset, src + total, sg[i].length);
 					total += sg[i].length;
 				} else {
-					memcpy(sg[i].address, src + total, len - total);
+					memcpy(page_address(sg[i].page) + sg[i].offset, src + total, len - total);
 					total = len;
 				}
 			} 
diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/usb/storage/protocol.c	Sun Feb 10 19:58:03 2002
@@ -67,13 +67,10 @@
 	US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
 
 	/* find the location of the data */
-	if (srb->use_sg) {
-		struct scatterlist *sg;
+	if (srb->use_sg)
+		BUG();
 
-		sg = (struct scatterlist *) srb->request_buffer;
-		data_ptr = (unsigned char *) sg[0].address;
-	} else
-		data_ptr = (unsigned char *)srb->request_buffer;
+	data_ptr = (unsigned char *) srb->request_buffer;
 
 	/* Change the SCSI revision number */
 	data_ptr[2] = (data_ptr[2] & ~7) | 2;
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/storage/scsiglue.c	Sun Feb 10 19:58:06 2002
@@ -278,7 +278,7 @@
 	if (us->protocol == US_PR_CBI) {
 		down(&(us->irq_urb_sem));
 		us->irq_urb->dev = us->pusb_dev;
-		result = usb_submit_urb(us->irq_urb);
+		result = usb_submit_urb(us->irq_urb, GFP_NOIO);
 		US_DEBUGP("usb_submit_urb() returns %d\n", result);
 		up(&(us->irq_urb_sem));
 	}
@@ -564,7 +564,12 @@
 	    }
 
 	  /* copy one byte */
-	  sg[db].address[di] = sg[sb].address[si];
+	  {
+		  char *src = page_address(sg[sb].page) + sg[sb].offset + si;
+		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+
+		  *dst = *src;
+	  }
 
 	  /* get next destination */
 	  if ( sg[db].length-1 == di )
@@ -602,7 +607,7 @@
 	      break;
 	    }
 
-	  sg[db].address[di] = 0;
+	  *(char *)(page_address(sg[db].page) + sg[db].offset) = 0;
 
 	  /* get next destination */
 	  if ( sg[db].length-1 == di )
@@ -752,7 +757,12 @@
 	    }
 
 	  /* copy one byte */
-	  sg[db].address[di] = sg[sb].address[si];
+	  {
+		  char *src = page_address(sg[sb].page) + sg[sb].offset + si;
+		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+
+		  *dst = *src;
+	  }
 
 	  /* get next destination */
 	  if ( di == 0 )
@@ -789,7 +799,11 @@
 	      break;
 	    }
 
-	  sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
+	  {
+		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+
+		  *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
+	  }
 
 	  /* get next destination */
 	  if ( di == 0 )
@@ -839,13 +853,19 @@
 		  if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
 		    {
 		      /* fill in the pointers for both header types */
-		      the6->array[element] = &(sg[i].address[j]);
-		      the10->array[element] = &(sg[i].address[j]);
+		      the6->array[element] =
+			      page_address(sg[i].page) +
+			      sg[i].offset + j;
+		      the10->array[element] =
+			      page_address(sg[i].page) +
+			      sg[i].offset + j;
 		    }
 		  else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
 		    {
 		      /* only the longer headers still cares now */
-		      the10->array[element] = &(sg[i].address[j]);
+		      the10->array[element] =
+			      page_address(sg[i].page) +
+			      sg[i].offset + j;
 		    }
 		  /* increase element counter */
 		  element++;
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/storage/sddr09.c	Sun Feb 10 19:58:06 2002
@@ -239,7 +239,7 @@
 		sg = (struct scatterlist *)data;
 		for (i=0; i<use_sg && transferred<len; i++) {
 			result = sddr09_raw_bulk(us, direction,
-				sg[i].address, 
+				page_address(sg[i].page) + sg[i].offset, 
 				len-transferred > sg[i].length ?
 					sg[i].length : len-transferred);
 			if (result!=US_BULK_TRANSFER_GOOD)
@@ -384,7 +384,7 @@
 	if (use_sg) {
 		transferred = 0;
 		for (i=0; i<use_sg && transferred<len; i++) {
-			memcpy(sg[i].address, buffer+transferred,
+			memcpy(page_address(sg[i].page) + sg[i].offset, buffer+transferred,
 				len-transferred > sg[i].length ?
 					sg[i].length : len-transferred);
 			transferred += sg[i].length;
@@ -636,21 +636,24 @@
 
 	for (i=0; i<alloc_blocks; i++) {
 		if (i<alloc_blocks-1) {
-			sg[i].address = kmalloc( (1<<17), GFP_NOIO );
-			sg[i].page = NULL;
+			char *vaddr = kmalloc(1 << 17, GFP_NOIO);
+			sg[i].page = virt_to_page(vaddr);
+			sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
 			sg[i].length = (1<<17);
 		} else {
-			sg[i].address = kmalloc(alloc_len, GFP_NOIO);
-			sg[i].page = NULL;
+			char *vaddr = kmalloc(alloc_len, GFP_NOIO);
+			sg[i].page = virt_to_page(vaddr);
+			sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
 			sg[i].length = alloc_len;
 		}
 		alloc_len -= sg[i].length;
 	}
+
 	for (i=0; i<alloc_blocks; i++)
-		if (sg[i].address == NULL) {
+		if (sg[i].page == NULL) {
 			for (i=0; i<alloc_blocks; i++)
-				if (sg[i].address != NULL)
-					kfree(sg[i].address);
+				if (sg[i].page != NULL)
+					kfree(page_address(sg[i].page) + sg[i].offset);
 			kfree(sg);
 			return 0;
 		}
@@ -661,7 +664,7 @@
 			(unsigned char *)sg, alloc_blocks)) !=
 			USB_STOR_TRANSPORT_GOOD) {
 		for (i=0; i<alloc_blocks; i++)
-			kfree(sg[i].address);
+			kfree(page_address(sg[i].page) + sg[i].offset);
 		kfree(sg);
 		return -1;
 	}
@@ -683,7 +686,7 @@
 		info->lba_to_pba = NULL;
 		info->pba_to_lba = NULL;
 		for (i=0; i<alloc_blocks; i++)
-			kfree(sg[i].address);
+			kfree(page_address(sg[i].page) + sg[i].offset);
 		kfree(sg);
 		return 0;
 	}
@@ -695,7 +698,7 @@
 	// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
 
 	for (i=0; i<numblocks; i++) {
-		ptr = sg[i>>11].address+((i&0x7ff)<<6);
+		ptr = page_address(sg[i>>11].page)+sg[i>>11].offset+((i&0x7ff)<<6);
 		if (ptr[0]!=0xFF || ptr[1]!=0xFF || ptr[2]!=0xFF ||
 		    ptr[3]!=0xFF || ptr[4]!=0xFF || ptr[5]!=0xFF) {
 			US_DEBUGP("PBA %04X has no logical mapping: reserved area = "
@@ -748,7 +751,7 @@
 	}
 
 	for (i=0; i<alloc_blocks; i++)
-		kfree(sg[i].address);
+		kfree(page_address(sg[i].page)+sg[i].offset);
 	kfree(sg);
 	return 0;
 }
diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
--- a/drivers/usb/storage/shuttle_usbat.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/usb/storage/shuttle_usbat.c	Sun Feb 10 19:58:03 2002
@@ -214,7 +214,7 @@
 		sg = (struct scatterlist *)data;
 		for (i=0; i<use_sg && transferred<len; i++) {
 			result = usbat_raw_bulk(us, direction,
-				sg[i].address, 
+				page_address(sg[i].page) + sg[i].offset,
 				len-transferred > sg[i].length ?
 					sg[i].length : len-transferred);
 			if (result!=US_BULK_TRANSFER_GOOD)
@@ -733,17 +733,19 @@
 			while (amount<len) {
 				if (len - amount >= 
 					  sg[sg_segment].length-sg_offset) {
-				  memcpy(sg[sg_segment].address + sg_offset,
-					buffer + amount,
-					sg[sg_segment].length - sg_offset);
+				  memcpy(page_address(sg[sg_segment].page) +
+					 sg[sg_segment].offset + sg_offset,
+					 buffer + amount,
+					 sg[sg_segment].length - sg_offset);
 				  amount += 
 					  sg[sg_segment].length-sg_offset;
 				  sg_segment++;
 				  sg_offset=0;
 				} else {
-				  memcpy(sg[sg_segment].address + sg_offset,
-					buffer + amount,
-					len - amount);
+				  memcpy(page_address(sg[sg_segment].page) +
+					 sg[sg_segment].offset + sg_offset,
+					 buffer + amount,
+					 len - amount);
 				  sg_offset += (len - amount);
 				  amount = len;
 				}
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/storage/transport.c	Sun Feb 10 19:58:05 2002
@@ -414,7 +414,7 @@
 	us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
 
 	/* submit the URB */
-	status = usb_submit_urb(us->current_urb);
+	status = usb_submit_urb(us->current_urb, GFP_NOIO);
 	if (status) {
 		/* something went wrong */
 		up(&(us->current_urb_sem));
@@ -461,7 +461,7 @@
 	us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
 
 	/* submit the URB */
-	status = usb_submit_urb(us->current_urb);
+	status = usb_submit_urb(us->current_urb, GFP_NOIO);
 	if (status) {
 		/* something went wrong */
 		up(&(us->current_urb_sem));
@@ -584,11 +584,11 @@
 			if (transfer_amount - total_transferred >= 
 					sg[i].length) {
 				result = usb_stor_transfer_partial(us,
-						sg[i].address, sg[i].length);
+						page_address(sg[i].page) + sg[i].offset, sg[i].length);
 				total_transferred += sg[i].length;
 			} else
 				result = usb_stor_transfer_partial(us,
-						sg[i].address,
+						page_address(sg[i].page) + sg[i].offset,
 						transfer_amount - total_transferred);
 
 			/* if we get an error, end the loop here */
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/storage/usb.c	Sun Feb 10 19:58:05 2002
@@ -288,13 +288,13 @@
 	if (us->srb->use_sg) {
 		sg = (struct scatterlist *)us->srb->request_buffer;
 		for (i=0; i<us->srb->use_sg; i++)
-			memset(sg[i].address, 0, sg[i].length);
+			memset(page_address(sg[i].page) + sg[i].offset, 0, sg[i].length);
 		for (i=0, transferred=0; 
 				i<us->srb->use_sg && transferred < len;
 				i++) {
 			amt = sg[i].length > len-transferred ? 
 					len-transferred : sg[i].length;
-			memcpy(sg[i].address, data+transferred, amt);
+			memcpy(page_address(sg[i].page) + sg[i].offset, data+transferred, amt);
 			transferred -= amt;
 		}
 	} else {
@@ -534,7 +534,7 @@
 		     usb_stor_CBI_irq, ss, ss->ep_int->bInterval); 
 
 	/* submit the URB for processing */
-	result = usb_submit_urb(ss->irq_urb);
+	result = usb_submit_urb(ss->irq_urb, GFP_KERNEL);
 	US_DEBUGP("usb_submit_urb() returns %d\n", result);
 	if (result) {
 		usb_free_urb(ss->irq_urb);
diff -Nru a/drivers/usb/stv680.c b/drivers/usb/stv680.c
--- a/drivers/usb/stv680.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/stv680.c	Sun Feb 10 19:58:04 2002
@@ -50,6 +50,12 @@
  *                         improve quality. Got rid of green line around 
  *                         frame. Fix brightness reset when changing size 
  *                         bug. Adjusted gamma filters slightly.
+ *
+ * ver 0.25 Jan, 2002 (kjs)
+ *			   Fixed a bug in which the driver sometimes attempted
+ *			   to set to a non-supported size. This allowed
+ *			   gnomemeeting to work.
+ *			   Fixed proc entry removal bug.
  */
 
 #include <linux/config.h>
@@ -87,7 +93,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.24"
+#define DRIVER_VERSION "v0.25"
 #define DRIVER_AUTHOR "Kevin Sisson <kjsisson@bellsouth.net>"
 #define DRIVER_DESC "STV0680 USB Camera Driver"
 
@@ -659,7 +665,7 @@
 	if (stv680_proc_entry == NULL)
 		return;
 
-	remove_proc_entry ("stv", video_proc_entry);
+	remove_proc_entry ("stv680", video_proc_entry);
 }
 #endif				/* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
 
@@ -759,7 +765,7 @@
 	/* Resubmit urb for new data */
 	urb->status = 0;
 	urb->dev = stv680->udev;
-	if (usb_submit_urb (urb))
+	if (usb_submit_urb (urb, GFP_KERNEL))
 		PDEBUG (0, "STV(e): urb burned down in video irq");
 	return;
 }				/*  _video_irq  */
@@ -810,7 +816,7 @@
 		urb->timeout = PENCAM_TIMEOUT * 2;
 		urb->transfer_flags |= USB_QUEUE_BULK;
 		stv680->urb[i] = urb;
-		err = usb_submit_urb (stv680->urb[i]);
+		err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
 		if (err)
 			PDEBUG (0, "STV(e): urb burned down in start stream");
 	}			/* i STV680_NUMSBUF */
@@ -862,20 +868,23 @@
 	if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) {
 		width = stv680->maxwidth / 2;
 		height = stv680->maxheight / 2;
-	} else if ((width >= 158) && (width <= 166)) {
+	} else if ((width >= 158) && (width <= 166) && (stv680->QVGA == 1)) {
 		width = 160;
 		height = 120;
-	} else if ((width >= 172) && (width <= 180)) {
+	} else if ((width >= 172) && (width <= 180) && (stv680->CIF == 1)) {
 		width = 176;
 		height = 144;
-	} else if ((width >= 318) && (width <= 350)) {
+	} else if ((width >= 318) && (width <= 350) && (stv680->QVGA == 1)) {
 		width = 320;
 		height = 240;
-	} else if ((width >= 350) && (width <= 358)) {
+	} else if ((width >= 350) && (width <= 358) && (stv680->CIF == 1)) {
 		width = 352;
 		height = 288;
+	} else {
+		PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
+		return 1;
 	}
-
+	
 	/* Stop a current stream and start it again at the new size */
 	if (wasstreaming)
 		stv680_stop_stream (stv680);
diff -Nru a/drivers/usb/uhci-debug.h b/drivers/usb/uhci-debug.h
--- a/drivers/usb/uhci-debug.h	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/uhci-debug.h	Sun Feb 10 19:58:05 2002
@@ -12,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
 #include <asm/io.h>
 
 #include "uhci.h"
@@ -476,7 +477,7 @@
 
 static int uhci_proc_open(struct inode *inode, struct file *file)
 {
-	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	const struct proc_dir_entry *dp = PDE(inode);
 	struct uhci *uhci = dp->data;
 	struct uhci_proc *up;
 	unsigned long flags;
@@ -507,8 +508,11 @@
 
 static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence)
 {
-	struct uhci_proc *up = file->private_data;
-	loff_t new;
+	struct uhci_proc *up;
+	loff_t new = -1;
+
+	lock_kernel();
+	up = file->private_data;
 
 	switch (whence) {
 	case 0:
@@ -517,12 +521,12 @@
 	case 1:
 		new = file->f_pos + off;
 		break;
-	case 2:
-	default:
-		return -EINVAL;
 	}
-	if (new < 0 || new > up->size)
+	if (new < 0 || new > up->size) {
+		unlock_kernel();
 		return -EINVAL;
+	}
+	unlock_kernel();
 	return (file->f_pos = new);
 }
 
diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c
--- a/drivers/usb/uhci.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/uhci.c	Sun Feb 10 19:58:05 2002
@@ -1476,7 +1476,7 @@
 	return u;
 }
 
-static int uhci_submit_urb(struct urb *urb)
+static int uhci_submit_urb(struct urb *urb, int mem_flags)
 {
 	int ret = -EINVAL;
 	struct uhci *uhci;
@@ -1823,11 +1823,11 @@
 }
 
 struct usb_operations uhci_device_operations = {
-	uhci_alloc_dev,
-	uhci_free_dev,
-	uhci_get_current_frame_number,
-	uhci_submit_urb,
-	uhci_unlink_urb
+	allocate:		uhci_alloc_dev,
+	deallocate:		uhci_free_dev,
+	get_frame_number:	uhci_get_current_frame_number,
+	submit_urb:		uhci_submit_urb,
+	unlink_urb:		uhci_unlink_urb,
 };
 
 /* Virtual Root Hub */
@@ -2294,7 +2294,7 @@
 	} else {
 		if (is_ring && !killed) {
 			urb->dev = dev;
-			uhci_submit_urb(urb);
+			uhci_submit_urb(urb, GFP_KERNEL);
 		} else {
 			/* We decrement the usage count after we're done */
 			/*  with everything */
@@ -2842,7 +2842,7 @@
 
 	usb_connect(uhci->rh.dev);
 
-	if (usb_new_device(uhci->rh.dev) != 0) {
+	if (usb_register_root_hub(uhci->rh.dev, &dev->dev) != 0) {
 		err("unable to start root hub");
 		retval = -ENOMEM;
 		goto err_start_root_hub;
diff -Nru a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c
--- a/drivers/usb/usb-ohci.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/usb-ohci.c	Sun Feb 10 19:58:05 2002
@@ -68,6 +68,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
+#include <asm/byteorder.h>
 
 #define OHCI_USE_NPS		// force NoPowerSwitching mode
 // #define OHCI_VERBOSE_DEBUG	/* not always helpful */
@@ -532,7 +533,7 @@
 
 /* get a transfer request */
  
-static int sohci_submit_urb (struct urb * urb)
+static int sohci_submit_urb (struct urb * urb, int mem_flags)
 {
 	ohci_t * ohci;
 	ed_t * ed;
@@ -542,7 +543,6 @@
 	int i, size = 0;
 	unsigned long flags;
 	int bustime = 0;
-	int mem_flags = ALLOC_FLAGS;
 	
 	if (!urb->dev || !urb->dev->bus)
 		return -ENODEV;
@@ -612,8 +612,7 @@
 	}
 
 	/* allocate the private part of the URB */
-	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), 
-							in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), mem_flags);
 	if (!urb_priv) {
 		usb_dec_dev_use (urb->dev);	
 		return -ENOMEM;
@@ -919,11 +918,11 @@
 /*-------------------------------------------------------------------------*/
 
 struct usb_operations sohci_device_operations = {
-	sohci_alloc_dev,
-	sohci_free_dev,
-	sohci_get_current_frame_number,
-	sohci_submit_urb,
-	sohci_unlink_urb
+	allocate:		sohci_alloc_dev,
+	deallocate:		sohci_free_dev,
+	get_frame_number:	sohci_get_current_frame_number,
+	submit_urb:		sohci_submit_urb,
+	unlink_urb:		sohci_unlink_urb,
 };
 
 /*-------------------------------------------------------------------------*
@@ -2233,7 +2232,7 @@
 	dev = usb_to_ohci (usb_dev);
 	ohci->bus->root_hub = usb_dev;
 	usb_connect (usb_dev);
-	if (usb_new_device (usb_dev) != 0) {
+	if (usb_register_root_hub (usb_dev, &ohci->ohci_dev->dev) != 0) {
 		usb_free_dev (usb_dev); 
 		ohci->disabled = 1;
 		return -ENODEV;
diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
--- a/drivers/usb/usb-skeleton.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/usb-skeleton.c	Sun Feb 10 19:58:06 2002
@@ -431,7 +431,9 @@
 		      skel_write_bulk_callback, dev);
 
 	/* send the data out the bulk port */
-	retval = usb_submit_urb(dev->write_urb);
+	/* a character device write uses GFP_KERNEL,
+	 unless a spinlock is held */
+	retval = usb_submit_urb(dev->write_urb, GFP_KERNEL);
 	if (retval) {
 		err(__FUNCTION__ " - failed submitting write urb, error %d",
 		    retval);
diff -Nru a/drivers/usb/usb-uhci-debug.h b/drivers/usb/usb-uhci-debug.h
--- a/drivers/usb/usb-uhci-debug.h	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/usb-uhci-debug.h	Sun Feb 10 19:58:04 2002
@@ -78,60 +78,6 @@
 #endif
 
 #ifdef DEBUG
-static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td)
-{
-	//dbg("uhci_show_td_queue %p (%08lX):", td, td->dma_addr);
-#if 1
-	return;
-#else
-	while (1) {
-		uhci_show_td (td);
-		if (td->hw.td.link & UHCI_PTR_TERM)
-			break;
-		if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS))
-			td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS);
-		else {
-			dbg("td points to itself!");
-			break;
-		}
-	}
-#endif
-}
-
-static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh)
-{
-#if 0
-	uhci_desc_t *start_qh=qh;
-#endif
-
-	dbg("uhci_show_queue %p:", qh);
-#if 1
-	return;
-#else
-	while (1) {
-		uhci_show_qh (qh);
-
-		if (!(qh->hw.qh.element & UHCI_PTR_TERM))
-			uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS));
-
-		if (qh->hw.qh.head & UHCI_PTR_TERM)
-			break;
-
-		if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS))
-			qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS);
-		else {
-			dbg("qh points to itself!");
-			break;
-		}
-		
-		if (qh==start_qh) { // avoid loop
-			dbg("Loop detect");
-			break;
-		}
-	}		
-#endif
-}
-
 static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status)
 {
 	dbg("  stat%d     =     %04x   %s%s%s%s%s%s%s%s",
diff -Nru a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
--- a/drivers/usb/usb-uhci.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/usb-uhci.c	Sun Feb 10 19:58:06 2002
@@ -40,6 +40,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/byteorder.h>
 
 /* This enables more detailed sanity checks in submit_iso */
 //#define ISO_SANITY_CHECK
@@ -87,7 +88,6 @@
 #endif
 
 #define SLAB_FLAG     (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL)
-#define KMALLOC_FLAG  (in_interrupt ()? GFP_ATOMIC : GFP_KERNEL)
 
 /* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth
  * Reclamation: feature that puts loop on descriptor loop when
@@ -685,7 +685,6 @@
 	insert_td_horizontal (s, s->int_chain[5], td);
 
 	mb();
-	//uhci_show_queue(s->control_chain);   
 	dbg("init_skel exit");
 	return 0;
 
@@ -800,7 +799,6 @@
 
 	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);
 
-	//uhci_show_queue(qh);
 	/* Start it up... put low speed first */
 	if (urb->dev->speed == USB_SPEED_LOW)
 		insert_qh (s, s->control_chain, qh, 0);
@@ -949,7 +947,6 @@
 			insert_qh (s, s->chain_end, qh, 0);
 	}
 	
-	//uhci_show_queue(s->bulk_chain);
 	//dbg("uhci_submit_bulk_urb: exit\n");
 	return 0;
 }
@@ -1502,7 +1499,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_iso_urb (struct urb *urb)
+_static int uhci_submit_iso_urb (struct urb *urb, int mem_flags)
 {
 	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
 	urb_priv_t *urb_priv = urb->hcpriv;
@@ -1522,7 +1519,7 @@
 	if (ret)
 		goto err;
 
-	tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), KMALLOC_FLAG);
+	tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), mem_flags);
 
 	if (!tdm) {
 		ret = -ENOMEM;
@@ -1619,7 +1616,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_urb (struct urb *urb)
+_static int uhci_submit_urb (struct urb *urb, int mem_flags)
 {
 	uhci_t *s;
 	urb_priv_t *urb_priv;
@@ -1676,7 +1673,7 @@
 #ifdef DEBUG_SLAB
 	urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG);
 #else
-	urb_priv = kmalloc (sizeof (urb_priv_t), KMALLOC_FLAG);
+	urb_priv = kmalloc (sizeof (urb_priv_t), mem_flags);
 #endif
 	if (!urb_priv) {
 		usb_dec_dev_use (urb->dev);
@@ -1729,12 +1726,12 @@
 				if (bustime < 0) 
 					ret = bustime;
 				else {
-					ret = uhci_submit_iso_urb(urb);
+					ret = uhci_submit_iso_urb(urb, mem_flags);
 					if (ret == 0)
 						usb_claim_bandwidth (urb->dev, urb, bustime, 1);
 				}
 			} else {        /* bandwidth is already set */
-				ret = uhci_submit_iso_urb(urb);
+				ret = uhci_submit_iso_urb(urb, mem_flags);
 			}
 			break;
 		case PIPE_INTERRUPT:
@@ -2279,11 +2276,11 @@
 
 struct usb_operations uhci_device_operations =
 {
-	uhci_alloc_dev,
-	uhci_free_dev,
-	uhci_get_current_frame_number,
-	uhci_submit_urb,
-	uhci_unlink_urb
+	allocate:		uhci_alloc_dev,
+	deallocate:		uhci_free_dev,
+	get_frame_number:	uhci_get_current_frame_number,
+	submit_urb:		uhci_submit_urb,
+	unlink_urb:		uhci_unlink_urb,
 };
 
 _static void correct_data_toggles(struct urb *urb)
@@ -2697,7 +2694,10 @@
 
 						spin_unlock(&s->urb_list_lock);
 
-						ret_submit=uhci_submit_urb(next_urb);
+						// FIXME!!!
+						// We need to know the real state, so 
+						// GFP_ATOMIC is probably not correct
+						ret_submit=uhci_submit_urb(next_urb, GFP_ATOMIC);
 						spin_lock(&s->urb_list_lock);
 						
 						if (ret_submit)
@@ -2721,7 +2721,10 @@
 				// Re-submit the URB if ring-linked
 				if (is_ring && !was_unlinked && !contains_killed) {
 					urb->dev=usb_dev;
-					uhci_submit_urb (urb);
+					// FIXME!!!
+					// We need to know the real state, so 
+					// GFP_ATOMIC is probably not correct
+					uhci_submit_urb (urb, GFP_ATOMIC);
 				}
 				spin_lock(&s->urb_list_lock);
 			}
@@ -2902,7 +2905,7 @@
 	s->bus->root_hub = usb_dev;
 	usb_connect (usb_dev);
 
-	if (usb_new_device (usb_dev) != 0) {
+	if (usb_register_root_hub (usb_dev, &s->uhci_pci->dev) != 0) {
 		usb_free_dev (usb_dev);
 		return -1;
 	}
diff -Nru a/drivers/usb/usb-uhci.h b/drivers/usb/usb-uhci.h
--- a/drivers/usb/usb-uhci.h	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/usb-uhci.h	Sun Feb 10 19:58:04 2002
@@ -100,7 +100,6 @@
 
 #define uhci_status_bits(ctrl_sts)	(ctrl_sts & 0xFE0000)
 #define uhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK)	/* 1-based */
-#define uhci_ptr_to_virt(x)	bus_to_virt(x & ~UHCI_PTR_BITS)
 
 /*
  * for TD <flags>:
diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c
--- a/drivers/usb/usb.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/usb.c	Sun Feb 10 19:58:06 2002
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/spinlock.h>
+#include <asm/byteorder.h>
 
 #ifdef CONFIG_USB_DEBUG
 	#define DEBUG
@@ -980,8 +981,16 @@
 	unsigned claimed = 0;
 
 	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
+		struct usb_interface *interface = &dev->actconfig->interface[ifnum];
+		
+		/* register this interface with driverfs */
+		interface->dev.parent = &dev->dev;
+		sprintf (&interface->dev.bus_id[0], "%03d", ifnum);
+		sprintf (&interface->dev.name[0], "figure out some name...");
+		device_register (&interface->dev);
+
 		/* if this interface hasn't already been claimed */
-		if (!usb_interface_claimed(dev->actconfig->interface + ifnum)) {
+		if (!usb_interface_claimed(interface)) {
 			if (usb_find_interface_driver(dev, ifnum))
 				rejected++;
 			else
@@ -1100,7 +1109,7 @@
 	}
 
 	memset(urb, 0, sizeof(*urb));
-	atomic_inc(&urb->count);
+	urb->count = (atomic_t)ATOMIC_INIT(1);
 	spin_lock_init(&urb->lock);
 
 	return urb;
@@ -1148,6 +1157,7 @@
 /**
  * usb_submit_urb - asynchronously issue a transfer request for an endpoint
  * @urb: pointer to the urb describing the request
+ * @mem_flags: the type of memory to allocate, see kmalloc() for a list of valid options for this.
  *
  * This submits a transfer request, and transfers control of the URB
  * describing that request to the USB subsystem.  Request completion will
@@ -1197,12 +1207,49 @@
  *
  * If the USB subsystem can't reserve sufficient bandwidth to perform
  * the periodic request, and bandwidth reservation is being done for
- * this controller, submitting such a periodic request will fail. 
+ * this controller, submitting such a periodic request will fail.
+ *
+ * Memory Flags:
+ *
+ * General rules for how to decide which mem_flags to use:
+ * 
+ * Basically the rules are the same as for kmalloc.  There are four
+ * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
+ * GFP_ATOMIC.
+ *
+ * GFP_NOFS is not ever used, as it has not been implemented yet.
+ *
+ * There are three situations you must use GFP_ATOMIC.
+ *    a) you are inside a completion handler, an interrupt, bottom half,
+ *       tasklet or timer.
+ *    b) you are holding a spinlock or rwlock (does not apply to
+ *       semaphores)
+ *    c) current->state != TASK_RUNNING, this is the case only after
+ *       you've changed it.
+ * 
+ * GFP_NOIO is used in the block io path and error handling of storage
+ * devices.
+ *
+ * All other situations use GFP_KERNEL.
+ *
+ * Specfic rules for how to decide which mem_flags to use:
+ *
+ *    - start_xmit, timeout, and receive methods of network drivers must
+ *      use GFP_ATOMIC (spinlock)
+ *    - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
+ *    - If you use a kernel thread with a network driver you must use
+ *      GFP_NOIO, unless b) or c) apply
+ *    - After you have done a down() you use GFP_KERNEL, unless b) or c)
+ *      apply or your are in a storage driver's block io path
+ *    - probe and disconnect use GFP_KERNEL unless b) or c) apply
+ *    - Changing firmware on a running storage or net device uses
+ *      GFP_NOIO, unless b) or c) apply
+ *
  */
-int usb_submit_urb(struct urb *urb)
+int usb_submit_urb(struct urb *urb, int mem_flags)
 {
 	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
-		return urb->dev->bus->op->submit_urb(urb);
+		return urb->dev->bus->op->submit_urb(urb, mem_flags);
 	else
 		return -ENODEV;
 }
@@ -1272,7 +1319,7 @@
 	add_wait_queue(&awd.wqh, &wait);
 
 	urb->context = &awd;
-	status = usb_submit_urb(urb);
+	status = usb_submit_urb(urb, GFP_KERNEL);
 	if (status) {
 		// something went wrong
 		usb_free_urb(urb);
@@ -1931,8 +1978,10 @@
 				if (driver->owner)
 					__MOD_DEC_USE_COUNT(driver->owner);
 				/* if driver->disconnect didn't release the interface */
-				if (interface->driver)
+				if (interface->driver) {
+					put_device (&interface->dev);
 					usb_driver_release_interface(driver, interface);
+				}
 			}
 		}
 	}
@@ -1951,6 +2000,7 @@
 	if (dev->devnum > 0) {
 		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
 		usbfs_remove_device(dev);
+		put_device(&dev->dev);
 	}
 
 	/* Free up the device itself */
@@ -2283,7 +2333,7 @@
 	/* 9.4.10 says devices don't need this, if the interface
 	   only has one alternate setting */
 	if (iface->num_altsetting == 1) {
-		warn("ignoring set_interface for dev %d, iface %d, alt %d",
+		dbg("ignoring set_interface for dev %d, iface %d, alt %d",
 			dev->devnum, interface, alternate);
 		return 0;
 	}
@@ -2677,6 +2727,11 @@
 		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 #endif
 
+	/* register this device in the driverfs tree */
+	err = device_register (&dev->dev);
+	if (err)
+		return err;
+
 	/* now that the basic setup is over, add a /proc/bus/usb entry */
 	usbfs_add_device(dev);
 
@@ -2689,6 +2744,29 @@
 	return 0;
 }
 
+/**
+ * usb_register_root_hub - called by a usb host controller to register the root hub device in the system
+ * @usb_dev: the usb root hub device to be registered.
+ * @parent_dev: the parent device of this root hub.
+ *
+ * The USB host controller calls this function to register the root hub
+ * properly with the USB subsystem.  It sets up the device properly in
+ * the driverfs tree, and then calls usb_new_device() to register the
+ * usb device.
+ */
+int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
+{
+	int retval;
+
+	usb_dev->dev.parent = parent_dev;
+	strcpy (&usb_dev->dev.name[0], "usb_name");
+	strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
+	retval = usb_new_device (usb_dev);
+	if (retval)
+		put_device (&usb_dev->dev);
+	return retval;
+}
+
 static int usb_open(struct inode * inode, struct file * file)
 {
 	int minor = minor(inode->i_rdev);
@@ -2794,6 +2872,7 @@
 EXPORT_SYMBOL(usb_free_bus);
 EXPORT_SYMBOL(usb_register_bus);
 EXPORT_SYMBOL(usb_deregister_bus);
+EXPORT_SYMBOL(usb_register_root_hub);
 EXPORT_SYMBOL(usb_alloc_dev);
 EXPORT_SYMBOL(usb_free_dev);
 EXPORT_SYMBOL(usb_inc_dev_use);
diff -Nru a/drivers/usb/usbkbd.c b/drivers/usb/usbkbd.c
--- a/drivers/usb/usbkbd.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/usbkbd.c	Sun Feb 10 19:58:06 2002
@@ -129,7 +129,7 @@
 
 	kbd->leds = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->led))
+	if (usb_submit_urb(kbd->led, GFP_KERNEL))
 		err("usb_submit_urb(leds) failed");
 
 	return 0;
@@ -147,7 +147,7 @@
 
 	kbd->leds = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->led))
+	if (usb_submit_urb(kbd->led, GFP_KERNEL))
 		err("usb_submit_urb(leds) failed");
 }
 
@@ -159,7 +159,7 @@
 		return 0;
 
 	kbd->irq->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->irq))
+	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
 		return -EIO;
 
 	return 0;
diff -Nru a/drivers/usb/usbmouse.c b/drivers/usb/usbmouse.c
--- a/drivers/usb/usbmouse.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/usbmouse.c	Sun Feb 10 19:58:05 2002
@@ -85,7 +85,7 @@
 		return 0;
 
 	mouse->irq->dev = mouse->usbdev;
-	if (usb_submit_urb(mouse->irq))
+	if (usb_submit_urb(mouse->irq, GFP_KERNEL))
 		return -EIO;
 
 	return 0;
diff -Nru a/drivers/usb/usbnet.c b/drivers/usb/usbnet.c
--- a/drivers/usb/usbnet.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/usb/usbnet.c	Sun Feb 10 19:58:03 2002
@@ -373,7 +373,7 @@
 	// issue usb interrupt read
 	if (priv && priv->irq_urb) {
 		// submit urb
-		if ((retval = usb_submit_urb (priv->irq_urb)) != 0)
+		if ((retval = usb_submit_urb (priv->irq_urb, GFP_KERNEL)) != 0)
 			dbg ("gl_interrupt_read: submit fail - %X...", retval);
 		else
 			dbg ("gl_interrupt_read: submit success...");
@@ -1281,7 +1281,7 @@
 	spin_lock_irqsave (&dev->rxq.lock, lockflags);
 
 	if (netif_running (&dev->net)) {
-		if ((retval = usb_submit_urb (urb)) != 0) {
+		if ((retval = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
 			dbg ("%s rx submit, %d", dev->net.name, retval);
 			tasklet_schedule (&dev->bh);
 		} else {
@@ -1642,7 +1642,7 @@
 #endif	/* CONFIG_USB_NET1080 */
 
 	netif_stop_queue (net);
-	if ((retval = usb_submit_urb (urb)) != 0) {
+	if ((retval = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
 		netif_start_queue (net);
 		dbg ("%s tx: submit urb err %d", net->name, retval);
 	} else {
diff -Nru a/drivers/usb/usbvideo.c b/drivers/usb/usbvideo.c
--- a/drivers/usb/usbvideo.c	Sun Feb 10 19:58:06 2002
+++ b/drivers/usb/usbvideo.c	Sun Feb 10 19:58:06 2002
@@ -1916,7 +1916,7 @@
 
 	/* Submit all URBs */
 	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		errFlag = usb_submit_urb(uvd->sbuf[i].urb);
+		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
 		if (errFlag)
 			err("%s: usb_submit_isoc(%d) ret %d", proc, i, errFlag);
 	}
diff -Nru a/drivers/usb/vicam.c b/drivers/usb/vicam.c
--- a/drivers/usb/vicam.c	Sun Feb 10 19:58:05 2002
+++ b/drivers/usb/vicam.c	Sun Feb 10 19:58:05 2002
@@ -79,7 +79,7 @@
 static struct usb_driver vicam_driver;
 
 static char *buf, *buf2;
-static int change_pending = 0; 
+static volatile int change_pending = 0; 
 
 static int vicam_parameters(struct usb_vicam *vicam);
 
@@ -330,8 +330,14 @@
 
 static void synchronize(struct usb_vicam *vicam)
 {
+	DECLARE_WAITQUEUE(wait, current);
 	change_pending = 1;
-	interruptible_sleep_on(&vicam->wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&vicam->wait, &wait);
+	if (change_pending)
+		schedule();
+	remove_wait_queue(&vicam->wait, &wait);
+	set_current_state(TASK_RUNNING);
 	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
 	mdelay(10);
 	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
@@ -344,7 +350,7 @@
 	synchronize(vicam);
 	mdelay(10);
 	vicam_parameters(vicam);
-	printk("Submiting urb: %d\n", usb_submit_urb(vicam->readurb));
+	printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
 #endif
 }
 
@@ -759,7 +765,7 @@
 		memcpy(vicam->fbuf, buf+64, 0x1e480);
 
 	if (!change_pending) {
-		if (usb_submit_urb(urb))
+		if (usb_submit_urb(urb, GFP_ATOMIC))
 			dbg("failed resubmitting read urb");
 	} else {
 		change_pending = 0;
@@ -843,7 +849,7 @@
 
 	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));
+	printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
 
 	return 0;
 error:
diff -Nru a/drivers/usb/wacom.c b/drivers/usb/wacom.c
--- a/drivers/usb/wacom.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/usb/wacom.c	Sun Feb 10 19:58:04 2002
@@ -336,7 +336,7 @@
 		return 0;
 
 	wacom->irq->dev = wacom->usbdev;
-	if (usb_submit_urb(wacom->irq))
+	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
 		return -EIO;
 
 	return 0;
diff -Nru a/drivers/video/Config.in b/drivers/video/Config.in
--- a/drivers/video/Config.in	Sun Feb 10 19:58:06 2002
+++ b/drivers/video/Config.in	Sun Feb 10 19:58:06 2002
@@ -121,14 +121,14 @@
 	 if [ "$CONFIG_FB_MATROX" != "n" ]; then
 	    bool '    Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
 	    bool '    Mystique support' CONFIG_FB_MATROX_MYSTIQUE
-	    bool '    G100/G200/G400/G450 support' CONFIG_FB_MATROX_G100
+	    bool '    G100/G200/G400/G450/G550 support' CONFIG_FB_MATROX_G100
             if [ "$CONFIG_I2C" != "n" ]; then
 	       dep_tristate '      Matrox I2C support' CONFIG_FB_MATROX_I2C $CONFIG_FB_MATROX $CONFIG_I2C_ALGOBIT
 	       if [ "$CONFIG_FB_MATROX_G100" = "y" ]; then
 	          dep_tristate '      G400 second head support' CONFIG_FB_MATROX_MAVEN $CONFIG_FB_MATROX_I2C
 	       fi
             fi
-            dep_tristate '      G450 second head support' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100
+            dep_tristate '      G450/G550 second head support' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100
 	    bool '    Multihead support' CONFIG_FB_MATROX_MULTIHEAD
 	 fi
 	 tristate '  ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY
diff -Nru a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
--- a/drivers/video/aty/mach64_accel.c	Sun Feb 10 19:58:03 2002
+++ b/drivers/video/aty/mach64_accel.c	Sun Feb 10 19:58:03 2002
@@ -3,6 +3,7 @@
  *  ATI Mach64 Hardware Acceleration
  */
 
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 
diff -Nru a/drivers/video/neofb.c b/drivers/video/neofb.c
--- a/drivers/video/neofb.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/video/neofb.c	Sun Feb 10 19:58:04 2002
@@ -46,7 +46,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
diff -Nru a/drivers/zorro/proc.c b/drivers/zorro/proc.c
--- a/drivers/zorro/proc.c	Sun Feb 10 19:58:04 2002
+++ b/drivers/zorro/proc.c	Sun Feb 10 19:58:04 2002
@@ -14,6 +14,7 @@
 #include <linux/zorro.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/amigahw.h>
 #include <asm/setup.h>
@@ -21,8 +22,9 @@
 static loff_t
 proc_bus_zorro_lseek(struct file *file, loff_t off, int whence)
 {
-	loff_t new;
+	loff_t new = -1;
 
+	lock_kernel();
 	switch (whence) {
 	case 0:
 		new = off;
@@ -33,11 +35,12 @@
 	case 2:
 		new = sizeof(struct ConfigDev) + off;
 		break;
-	default:
-		return -EINVAL;
 	}
-	if (new < 0 || new > sizeof(struct ConfigDev))
+	if (new < 0 || new > sizeof(struct ConfigDev)) {
+		unlock_kernel();
 		return -EINVAL;
+	}
+	unlock_kernel();
 	return (file->f_pos = new);
 }
 
@@ -45,7 +48,7 @@
 proc_bus_zorro_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
 {
 	struct inode *ino = file->f_dentry->d_inode;
-	struct proc_dir_entry *dp = ino->u.generic_ip;
+	struct proc_dir_entry *dp = PDE(ino);
 	struct zorro_dev *dev = dp->data;
 	struct ConfigDev cd;
 	int pos = *ppos;
diff -Nru a/fs/Config.in b/fs/Config.in
--- a/fs/Config.in	Sun Feb 10 19:58:04 2002
+++ b/fs/Config.in	Sun Feb 10 19:58:04 2002
@@ -8,9 +8,9 @@
 tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
 tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
 
-dep_tristate 'Reiserfs support' CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
-dep_mbool '  Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
-dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
+tristate 'Reiserfs support' CONFIG_REISERFS_FS
+dep_mbool '  Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS
+dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS
 
 dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
 dep_mbool '  ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
diff -Nru a/fs/adfs/dir.c b/fs/adfs/dir.c
--- a/fs/adfs/dir.c	Sun Feb 10 19:58:04 2002
+++ b/fs/adfs/dir.c	Sun Feb 10 19:58:04 2002
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/spinlock.h>
 
diff -Nru a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
--- a/fs/adfs/dir_f.c	Sun Feb 10 19:58:04 2002
+++ b/fs/adfs/dir_f.c	Sun Feb 10 19:58:04 2002
@@ -13,7 +13,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/spinlock.h>
 
diff -Nru a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c
--- a/fs/adfs/dir_fplus.c	Sun Feb 10 19:58:04 2002
+++ b/fs/adfs/dir_fplus.c	Sun Feb 10 19:58:04 2002
@@ -11,7 +11,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/spinlock.h>
 
diff -Nru a/fs/adfs/file.c b/fs/adfs/file.c
--- a/fs/adfs/file.c	Sun Feb 10 19:58:05 2002
+++ b/fs/adfs/file.c	Sun Feb 10 19:58:05 2002
@@ -23,7 +23,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/fcntl.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 
 #include "adfs.h"
diff -Nru a/fs/adfs/inode.c b/fs/adfs/inode.c
--- a/fs/adfs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/adfs/inode.c	Sun Feb 10 19:58:05 2002
@@ -11,7 +11,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/adfs/super.c b/fs/adfs/super.c
--- a/fs/adfs/super.c	Sun Feb 10 19:58:03 2002
+++ b/fs/adfs/super.c	Sun Feb 10 19:58:03 2002
@@ -13,7 +13,7 @@
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
@@ -346,7 +346,7 @@
 	return discsize;
 }
 
-struct super_block *adfs_read_super(struct super_block *sb, void *data, int silent)
+static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct adfs_discrecord *dr;
 	struct buffer_head *bh;
@@ -467,15 +467,26 @@
 		goto error;
 	} else
 		sb->s_root->d_op = &adfs_dentry_operations;
-	return sb;
+	return 0;
 
 error_free_bh:
 	brelse(bh);
 error:
-	return NULL;
+	return -EINVAL;
+}
+
+static struct super_block *adfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super);
 }
 
-static DECLARE_FSTYPE_DEV(adfs_fs_type, "adfs", adfs_read_super);
+static struct file_system_type adfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"adfs",
+	get_sb:		adfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_adfs_fs(void)
 {
diff -Nru a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
--- a/fs/affs/amigaffs.c	Sun Feb 10 19:58:05 2002
+++ b/fs/affs/amigaffs.c	Sun Feb 10 19:58:05 2002
@@ -10,7 +10,7 @@
 
 #include <stdarg.h>
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/affs_fs.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/affs/bitmap.c b/fs/affs/bitmap.c
--- a/fs/affs/bitmap.c	Sun Feb 10 19:58:06 2002
+++ b/fs/affs/bitmap.c	Sun Feb 10 19:58:06 2002
@@ -7,7 +7,7 @@
  *  block allocation, deallocation, calculation of free space.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/affs_fs.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
diff -Nru a/fs/affs/file.c b/fs/affs/file.c
--- a/fs/affs/file.c	Sun Feb 10 19:58:06 2002
+++ b/fs/affs/file.c	Sun Feb 10 19:58:06 2002
@@ -15,7 +15,7 @@
 #include <asm/div64.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/affs_fs.h>
 #include <linux/fcntl.h>
 #include <linux/kernel.h>
diff -Nru a/fs/affs/inode.c b/fs/affs/inode.c
--- a/fs/affs/inode.c	Sun Feb 10 19:58:06 2002
+++ b/fs/affs/inode.c	Sun Feb 10 19:58:06 2002
@@ -15,7 +15,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/affs_fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -Nru a/fs/affs/namei.c b/fs/affs/namei.c
--- a/fs/affs/namei.c	Sun Feb 10 19:58:05 2002
+++ b/fs/affs/namei.c	Sun Feb 10 19:58:05 2002
@@ -8,7 +8,7 @@
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/affs_fs.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -Nru a/fs/affs/super.c b/fs/affs/super.c
--- a/fs/affs/super.c	Sun Feb 10 19:58:04 2002
+++ b/fs/affs/super.c	Sun Feb 10 19:58:04 2002
@@ -15,7 +15,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/affs_fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -265,15 +265,13 @@
  * hopefully have the guts to do so. Until then: sorry for the mess.
  */
 
-static struct super_block *
-affs_read_super(struct super_block *sb, void *data, int silent)
+static int affs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct buffer_head	*root_bh = NULL;
 	struct buffer_head	*boot_bh;
 	struct inode		*root_inode = NULL;
-	kdev_t			 dev = sb->s_dev;
 	s32			 root_block;
-	int			 blocks, size, blocksize;
+	int			 size, blocksize;
 	u32			 chksum;
 	int			 num_bm;
 	int			 i, j;
@@ -294,7 +292,7 @@
 				&blocksize,&AFFS_SB->s_prefix,
 				AFFS_SB->s_volume, &mount_flags)) {
 		printk(KERN_ERR "AFFS: Error parsing options\n");
-		return NULL;
+		return -EINVAL;
 	}
 	/* N.B. after this point s_prefix must be released */
 
@@ -309,12 +307,7 @@
 	 * blocks, we will have to change it.
 	 */
 
-	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;
-	}
-	size = (BLOCK_SIZE / 512) * blocks;
+	size = sb->s_bdev->bd_inode->i_size >> 9;
 	pr_debug("AFFS: initial blksize=%d, blocks=%d\n", 512, blocks);
 
 	affs_set_blocksize(sb, PAGE_SIZE);
@@ -462,7 +455,7 @@
 	sb->s_root->d_op = &affs_dentry_operations;
 
 	pr_debug("AFFS: s_flags=%lX\n",sb->s_flags);
-	return sb;
+	return 0;
 
 	/*
 	 * Begin the cascaded cleanup ...
@@ -475,7 +468,7 @@
 	affs_brelse(root_bh);
 	if (AFFS_SB->s_prefix)
 		kfree(AFFS_SB->s_prefix);
-	return NULL;
+	return -EINVAL;
 }
 
 static int
@@ -533,7 +526,18 @@
 	return 0;
 }
 
-static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);
+static struct super_block *affs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super);
+}
+
+static struct file_system_type affs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"affs",
+	get_sb:		affs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_affs_fs(void)
 {
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c	Sun Feb 10 19:58:04 2002
+++ b/fs/attr.c	Sun Feb 10 19:58:04 2002
@@ -5,7 +5,7 @@
  *  changes by Thomas Schoebel-Theuer
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
diff -Nru a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
--- a/fs/autofs/autofs_i.h	Sun Feb 10 19:58:04 2002
+++ b/fs/autofs/autofs_i.h	Sun Feb 10 19:58:04 2002
@@ -20,7 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/string.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
@@ -145,7 +145,7 @@
 
 /* Initializing function */
 
-struct super_block *autofs_read_super(struct super_block *, void *,int);
+int autofs_fill_super(struct super_block *, void *, int);
 
 /* Queue management functions */
 
diff -Nru a/fs/autofs/init.c b/fs/autofs/init.c
--- a/fs/autofs/init.c	Sun Feb 10 19:58:04 2002
+++ b/fs/autofs/init.c	Sun Feb 10 19:58:04 2002
@@ -14,7 +14,17 @@
 #include <linux/init.h>
 #include "autofs_i.h"
 
-static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs_read_super, 0);
+static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, autofs_fill_super);
+}
+
+static struct file_system_type autofs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"autofs",
+	get_sb:		autofs_get_sb,
+};
 
 static int __init init_autofs_fs(void)
 {
diff -Nru a/fs/autofs/inode.c b/fs/autofs/inode.c
--- a/fs/autofs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/autofs/inode.c	Sun Feb 10 19:58:05 2002
@@ -111,8 +111,7 @@
 	return (*pipefd < 0);
 }
 
-struct super_block *autofs_read_super(struct super_block *s, void *data,
-				      int silent)
+int autofs_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * root_inode;
 	struct dentry * root;
@@ -175,7 +174,7 @@
 	 * Success! Install the root dentry now to indicate completion.
 	 */
 	s->s_root = root;
-	return s;
+	return 0;
 
 fail_fput:
 	printk("autofs: pipe file descriptor does not contain proper ops\n");
@@ -189,7 +188,7 @@
 fail_free:
 	kfree(sbi);
 fail_unlock:
-	return NULL;
+	return -EINVAL;
 }
 
 static int autofs_statfs(struct super_block *sb, struct statfs *buf)
diff -Nru a/fs/autofs/root.c b/fs/autofs/root.c
--- a/fs/autofs/root.c	Sun Feb 10 19:58:06 2002
+++ b/fs/autofs/root.c	Sun Feb 10 19:58:06 2002
@@ -13,7 +13,7 @@
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/param.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/smp_lock.h>
 #include "autofs_i.h"
 
diff -Nru a/fs/autofs/waitq.c b/fs/autofs/waitq.c
--- a/fs/autofs/waitq.c	Sun Feb 10 19:58:05 2002
+++ b/fs/autofs/waitq.c	Sun Feb 10 19:58:05 2002
@@ -11,7 +11,7 @@
  * ------------------------------------------------------------------------- */
 
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/signal.h>
 #include <linux/file.h>
 #include "autofs_i.h"
diff -Nru a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
--- a/fs/autofs4/autofs_i.h	Sun Feb 10 19:58:04 2002
+++ b/fs/autofs4/autofs_i.h	Sun Feb 10 19:58:04 2002
@@ -21,7 +21,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/string.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
@@ -144,7 +144,7 @@
 
 /* Initializing function */
 
-struct super_block *autofs4_read_super(struct super_block *, void *,int);
+int autofs4_fill_super(struct super_block *, void *, int);
 struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info *sbi, mode_t mode);
 
 /* Queue management functions */
diff -Nru a/fs/autofs4/init.c b/fs/autofs4/init.c
--- a/fs/autofs4/init.c	Sun Feb 10 19:58:04 2002
+++ b/fs/autofs4/init.c	Sun Feb 10 19:58:04 2002
@@ -14,7 +14,17 @@
 #include <linux/init.h>
 #include "autofs_i.h"
 
-static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs4_read_super, 0);
+static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, autofs4_fill_super);
+}
+
+static struct file_system_type autofs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"autofs",
+	get_sb:		autofs_get_sb,
+};
 
 static int __init init_autofs4_fs(void)
 {
diff -Nru a/fs/autofs4/inode.c b/fs/autofs4/inode.c
--- a/fs/autofs4/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/autofs4/inode.c	Sun Feb 10 19:58:05 2002
@@ -173,8 +173,7 @@
 	return ino;
 }
 
-struct super_block *autofs4_read_super(struct super_block *s, void *data,
-				      int silent)
+int autofs4_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * root_inode;
 	struct dentry * root;
@@ -251,7 +250,7 @@
 	 * Success! Install the root dentry now to indicate completion.
 	 */
 	s->s_root = root;
-	return s;
+	return 0;
 	
 	/*
 	 * Failure ... clean up.
@@ -278,7 +277,7 @@
 fail_free:
 	kfree(sbi);
 fail_unlock:
-	return NULL;
+	return -EINVAL;
 }
 
 static int autofs4_statfs(struct super_block *sb, struct statfs *buf)
diff -Nru a/fs/autofs4/root.c b/fs/autofs4/root.c
--- a/fs/autofs4/root.c	Sun Feb 10 19:58:03 2002
+++ b/fs/autofs4/root.c	Sun Feb 10 19:58:03 2002
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/param.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/smp_lock.h>
 #include "autofs_i.h"
 
diff -Nru a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
--- a/fs/autofs4/waitq.c	Sun Feb 10 19:58:05 2002
+++ b/fs/autofs4/waitq.c	Sun Feb 10 19:58:05 2002
@@ -11,7 +11,7 @@
  * ------------------------------------------------------------------------- */
 
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/signal.h>
 #include <linux/file.h>
 #include "autofs_i.h"
diff -Nru a/fs/bad_inode.c b/fs/bad_inode.c
--- a/fs/bad_inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/bad_inode.c	Sun Feb 10 19:58:05 2002
@@ -8,7 +8,7 @@
 
 #include <linux/fs.h>
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 
 /*
  * The follow_link operation is special: it must behave as a no-op
diff -Nru a/fs/bfs/dir.c b/fs/bfs/dir.c
--- a/fs/bfs/dir.c	Sun Feb 10 19:58:06 2002
+++ b/fs/bfs/dir.c	Sun Feb 10 19:58:06 2002
@@ -4,7 +4,7 @@
  *	Copyright (C) 1999,2000  Tigran Aivazian <tigran@veritas.com>
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/string.h>
 #include <linux/bfs_fs.h>
 #include <linux/locks.h>
diff -Nru a/fs/bfs/inode.c b/fs/bfs/inode.c
--- a/fs/bfs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/bfs/inode.c	Sun Feb 10 19:58:05 2002
@@ -279,8 +279,7 @@
 #endif
 }
 
-static struct super_block * bfs_read_super(struct super_block * s, 
-	void * data, int silent)
+static int bfs_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct buffer_head * bh;
 	struct bfs_super_block * bfs_sb;
@@ -355,14 +354,25 @@
 		s->s_dirt = 1;
 	} 
 	dump_imap("read_super", s);
-	return s;
+	return 0;
 
 out:
 	brelse(bh);
-	return NULL;
+	return -EINVAL;
 }
 
-static DECLARE_FSTYPE_DEV(bfs_fs_type, "bfs", bfs_read_super);
+static struct super_block *bfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super);
+}
+
+static struct file_system_type bfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"bfs",
+	get_sb:		bfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_bfs_fs(void)
 {
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c	Sun Feb 10 19:58:05 2002
+++ b/fs/binfmt_aout.c	Sun Feb 10 19:58:05 2002
@@ -6,7 +6,7 @@
 
 #include <linux/module.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Sun Feb 10 19:58:06 2002
+++ b/fs/binfmt_elf.c	Sun Feb 10 19:58:06 2002
@@ -13,7 +13,7 @@
 
 #include <linux/fs.h>
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/a.out.h>
diff -Nru a/fs/binfmt_misc.c b/fs/binfmt_misc.c
--- a/fs/binfmt_misc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/binfmt_misc.c	Sun Feb 10 19:58:05 2002
@@ -656,7 +656,7 @@
 	clear_inode:	bm_clear_inode,
 };
 
-static struct super_block *bm_read_super(struct super_block * sb, void * data, int silent)
+static int bm_fill_super(struct super_block * sb, void * data, int silent)
 {
 	struct qstr names[2] = {{name:"status"}, {name:"register"}};
 	struct inode * inode;
@@ -675,13 +675,13 @@
 
 	inode = bm_get_inode(sb, S_IFDIR | 0755);
 	if (!inode)
-		return NULL;
+		return -ENOMEM;
 	inode->i_op = &bm_dir_inode_operations;
 	inode->i_fop = &bm_dir_operations;
 	dentry[0] = d_alloc_root(inode);
 	if (!dentry[0]) {
 		iput(inode);
-		return NULL;
+		return -ENOMEM;
 	}
 	dentry[1] = d_alloc(dentry[0], &names[0]);
 	if (!dentry[1])
@@ -701,7 +701,7 @@
 	d_add(dentry[2], inode);
 
 	sb->s_root = dentry[0];
-	return sb;
+	return 0;
 
 out3:
 	dput(dentry[2]);
@@ -709,14 +709,26 @@
 	dput(dentry[1]);
 out1:
 	dput(dentry[0]);
-	return NULL;
+	return -ENOMEM;
+}
+
+static struct super_block *bm_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, bm_fill_super);
 }
 
 static struct linux_binfmt misc_format = {
-	NULL, THIS_MODULE, load_misc_binary, NULL, NULL, 0
+	module: THIS_MODULE,
+	load_binary: load_misc_binary,
 };
 
-static DECLARE_FSTYPE(bm_fs_type, "binfmt_misc", bm_read_super, FS_SINGLE|FS_LITTER);
+static struct file_system_type bm_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"binfmt_misc",
+	get_sb:		bm_get_sb,
+	fs_flags:	FS_LITTER,
+};
 
 static int __init init_misc_binfmt(void)
 {
diff -Nru a/fs/binfmt_script.c b/fs/binfmt_script.c
--- a/fs/binfmt_script.c	Sun Feb 10 19:58:04 2002
+++ b/fs/binfmt_script.c	Sun Feb 10 19:58:04 2002
@@ -13,6 +13,8 @@
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/smp_lock.h>
+#include <linux/err.h>
+#include <linux/fs.h>
 
 static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
 {
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	Sun Feb 10 19:58:04 2002
+++ b/fs/bio.c	Sun Feb 10 19:58:04 2002
@@ -33,20 +33,24 @@
 
 struct biovec_pool {
 	int size;
+	char *name; 
 	kmem_cache_t *slab;
 	mempool_t *pool;
 };
 
-static struct biovec_pool bvec_array[BIOVEC_NR_POOLS];
-
 /*
  * if you change this list, also change bvec_alloc or things will
  * break badly! cannot be bigger than what you can fit into an
  * unsigned short
  */
-static const int bvec_pool_sizes[BIOVEC_NR_POOLS] = { 1, 4, 16, 64, 128, 256 };
 
-#define BIO_MAX_PAGES	(bvec_pool_sizes[BIOVEC_NR_POOLS - 1])
+#define BV(x) { x, "biovec-" #x }
+static struct biovec_pool bvec_array[BIOVEC_NR_POOLS] = { 
+	BV(1), BV(4), BV(16), BV(64), BV(128), BV(256)
+}; 
+#undef BV
+
+#define BIO_MAX_PAGES	(bvec_array[BIOVEC_NR_POOLS - 1].size)
 
 static void *slab_pool_alloc(int gfp_mask, void *data)
 {
@@ -64,7 +68,7 @@
 	struct bio_vec *bvl;
 
 	/*
-	 * see comment near bvec_pool_sizes define!
+	 * see comment near bvec_array define!
 	 */
 	switch (nr) {
 		case   1        : *idx = 0; break;
@@ -452,21 +456,17 @@
 
 static void __init biovec_init_pool(void)
 {
-	char name[16];
 	int i, size;
 
-	memset(&bvec_array, 0, sizeof(bvec_array));
-
 	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
 		struct biovec_pool *bp = bvec_array + i;
 
-		size = bvec_pool_sizes[i] * sizeof(struct bio_vec);
+		size = bp->size * sizeof(struct bio_vec);
 
 		printk("biovec: init pool %d, %d entries, %d bytes\n", i,
-						bvec_pool_sizes[i], size);
+						bp->size, size);
 
-		snprintf(name, sizeof(name) - 1,"biovec-%d",bvec_pool_sizes[i]);
-		bp->slab = kmem_cache_create(name, size, 0,
+		bp->slab = kmem_cache_create(bp->name, size, 0,
 						SLAB_HWCACHE_ALIGN, NULL, NULL);
 		if (!bp->slab)
 			panic("biovec: can't init slab cache\n");
@@ -474,7 +474,7 @@
 					slab_pool_free, bp->slab);
 		if (!bp->pool)
 			panic("biovec: can't init mempool\n");
-		bp->size = size;
+		bp->size = size;	
 	}
 }
 
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Sun Feb 10 19:58:06 2002
+++ b/fs/block_dev.c	Sun Feb 10 19:58:06 2002
@@ -220,7 +220,7 @@
  * pseudo-fs
  */
 
-static struct super_block *bd_read_super(struct super_block *sb, void *data, int silent)
+static int bd_fill_super(struct super_block *sb, void *data, int silent)
 {
 	static struct super_operations sops = {};
 	struct inode *root;
@@ -232,22 +232,32 @@
 	sb->s_op = &sops;
 	root = new_inode(sb);
 	if (!root)
-		return NULL;
+		return -ENOMEM;
 	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
 	root->i_uid = root->i_gid = 0;
 	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
 	sb->s_root = d_alloc(NULL, &(const struct qstr) { "bdev:", 5, 0 });
 	if (!sb->s_root) {
 		iput(root);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root->d_sb = sb;
 	sb->s_root->d_parent = sb->s_root;
 	d_instantiate(sb->s_root, root);
-	return sb;
+	return 0;
 }
 
-static DECLARE_FSTYPE(bd_type, "bdev", bd_read_super, FS_NOMOUNT);
+static struct super_block *bd_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, bd_fill_super);
+}
+
+static struct file_system_type bd_type = {
+	name:		"bdev",
+	get_sb:		bd_get_sb,
+	fs_flags:	FS_NOMOUNT,
+};
 
 static struct vfsmount *bd_mnt;
 
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Sun Feb 10 19:58:03 2002
+++ b/fs/buffer.c	Sun Feb 10 19:58:03 2002
@@ -29,7 +29,7 @@
 /* async buffer flushing, 1999 Andrea Arcangeli <andrea@suse.de> */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/locks.h>
diff -Nru a/fs/coda/cache.c b/fs/coda/cache.c
--- a/fs/coda/cache.c	Sun Feb 10 19:58:06 2002
+++ b/fs/coda/cache.c	Sun Feb 10 19:58:06 2002
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
diff -Nru a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
--- a/fs/coda/coda_linux.c	Sun Feb 10 19:58:03 2002
+++ b/fs/coda/coda_linux.c	Sun Feb 10 19:58:03 2002
@@ -10,7 +10,7 @@
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
diff -Nru a/fs/coda/dir.c b/fs/coda/dir.c
--- a/fs/coda/dir.c	Sun Feb 10 19:58:04 2002
+++ b/fs/coda/dir.c	Sun Feb 10 19:58:04 2002
@@ -10,7 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/stat.h>
diff -Nru a/fs/coda/file.c b/fs/coda/file.c
--- a/fs/coda/file.c	Sun Feb 10 19:58:05 2002
+++ b/fs/coda/file.c	Sun Feb 10 19:58:05 2002
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
diff -Nru a/fs/coda/inode.c b/fs/coda/inode.c
--- a/fs/coda/inode.c	Sun Feb 10 19:58:06 2002
+++ b/fs/coda/inode.c	Sun Feb 10 19:58:06 2002
@@ -33,7 +33,6 @@
 #include <linux/coda_cache.h>
 
 /* VFS super_block ops */
-static struct super_block *coda_read_super(struct super_block *, void *, int);
 static void coda_read_inode(struct inode *);
 static void coda_clear_inode(struct inode *);
 static void coda_put_super(struct super_block *);
@@ -140,8 +139,7 @@
 	return idx;
 }
 
-static struct super_block * coda_read_super(struct super_block *sb, 
-					    void *data, int silent)
+static int coda_fill_super(struct super_block *sb, void *data, int silent)
 {
         struct inode *root = 0; 
 	struct coda_sb_info *sbi = NULL;
@@ -161,17 +159,17 @@
 	vc = &coda_comms[idx];
 	if (!vc->vc_inuse) {
 		printk("coda_read_super: No pseudo device\n");
-		return NULL;
+		return -EINVAL;
 	}
 
         if ( vc->vc_sb ) {
 		printk("coda_read_super: Device already mounted\n");
-		return NULL;
+		return -EBUSY;
 	}
 
 	sbi = kmalloc(sizeof(struct coda_sb_info), GFP_KERNEL);
 	if(!sbi) {
-		return NULL;
+		return -ENOMEM;
 	}
 
 	vc->vc_sb = sb;
@@ -192,7 +190,7 @@
 	        printk("coda_read_super: coda_get_rootfid failed with %d\n",
 		       error);
 		goto error;
-	}	  
+	}
 	printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
 	
 	/* make root inode */
@@ -205,7 +203,7 @@
 	printk("coda_read_super: rootinode is %ld dev %x\n", 
 	       root->i_ino, kdev_val(root->i_dev));
 	sb->s_root = d_alloc_root(root);
-        return sb;
+        return 0;
 
  error:
 	if (sbi) {
@@ -216,7 +214,7 @@
 	if (root)
                 iput(root);
 
-        return NULL;
+        return -EINVAL;
 }
 
 static void coda_put_super(struct super_block *sb)
@@ -313,5 +311,14 @@
 
 /* init_coda: used by filesystems.c to register coda */
 
-DECLARE_FSTYPE( coda_fs_type, "coda", coda_read_super, 0);
+static struct super_block *coda_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, coda_fill_super);
+}
 
+struct file_system_type coda_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"coda",
+	get_sb:		coda_get_sb,
+};
diff -Nru a/fs/coda/pioctl.c b/fs/coda/pioctl.c
--- a/fs/coda/pioctl.c	Sun Feb 10 19:58:04 2002
+++ b/fs/coda/pioctl.c	Sun Feb 10 19:58:04 2002
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
diff -Nru a/fs/coda/psdev.c b/fs/coda/psdev.c
--- a/fs/coda/psdev.c	Sun Feb 10 19:58:04 2002
+++ b/fs/coda/psdev.c	Sun Feb 10 19:58:04 2002
@@ -21,7 +21,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/lp.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
diff -Nru a/fs/coda/symlink.c b/fs/coda/symlink.c
--- a/fs/coda/symlink.c	Sun Feb 10 19:58:05 2002
+++ b/fs/coda/symlink.c	Sun Feb 10 19:58:05 2002
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
diff -Nru a/fs/coda/sysctl.c b/fs/coda/sysctl.c
--- a/fs/coda/sysctl.c	Sun Feb 10 19:58:05 2002
+++ b/fs/coda/sysctl.c	Sun Feb 10 19:58:05 2002
@@ -12,7 +12,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 #include <linux/swapctl.h>
diff -Nru a/fs/coda/upcall.c b/fs/coda/upcall.c
--- a/fs/coda/upcall.c	Sun Feb 10 19:58:06 2002
+++ b/fs/coda/upcall.c	Sun Feb 10 19:58:06 2002
@@ -21,7 +21,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/stat.h>
diff -Nru a/fs/cramfs/inode.c b/fs/cramfs/inode.c
--- a/fs/cramfs/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/cramfs/inode.c	Sun Feb 10 19:58:04 2002
@@ -188,12 +188,11 @@
 }
 			
 
-static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
+static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	int i;
 	struct cramfs_super super;
 	unsigned long root_offset;
-	struct super_block * retval = NULL;
 
 	sb_set_blocksize(sb, PAGE_CACHE_SIZE);
 
@@ -252,9 +251,9 @@
 	/* Set it all up.. */
 	sb->s_op = &cramfs_ops;
 	sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
-	retval = sb;
+	return 0;
 out:
-	return retval;
+	return -EINVAL;
 }
 
 static int cramfs_statfs(struct super_block *sb, struct statfs *buf)
@@ -442,7 +441,18 @@
 	statfs:		cramfs_statfs,
 };
 
-static DECLARE_FSTYPE_DEV(cramfs_fs_type, "cramfs", cramfs_read_super);
+static struct super_block *cramfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super);
+}
+
+static struct file_system_type cramfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"cramfs",
+	get_sb:		cramfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_cramfs_fs(void)
 {
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	Sun Feb 10 19:58:04 2002
+++ b/fs/dcache.c	Sun Feb 10 19:58:04 2002
@@ -1283,6 +1283,7 @@
 
 	dcache_init(mempages);
 	inode_init(mempages);
+	files_init(mempages); 
 	mnt_init(mempages);
 	bdev_cache_init();
 	cdev_cache_init();
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Sun Feb 10 19:58:04 2002
+++ b/fs/devfs/base.c	Sun Feb 10 19:58:04 2002
@@ -615,7 +615,7 @@
 */
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/tty.h>
 #include <linux/timer.h>
 #include <linux/config.h>
@@ -3218,8 +3218,7 @@
     setattr:        devfs_notify_change,
 };
 
-static struct super_block *devfs_read_super (struct super_block *sb,
-					     void *data, int silent)
+static int devfs_fill_super (struct super_block *sb, void *data, int silent)
 {
     struct inode *root_inode = NULL;
 
@@ -3238,17 +3237,24 @@
     sb->s_root = d_alloc_root (root_inode);
     if (!sb->s_root) goto out_no_root;
     DPRINTK (DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->u.generic_sbp);
-    return sb;
+    return 0;
 
 out_no_root:
     PRINTK ("(): get root inode failed\n");
     if (root_inode) iput (root_inode);
-    return NULL;
+    return -EINVAL;
 }   /*  End Function devfs_read_super  */
 
+static struct super_block *devfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, devfs_fill_super);
+}
 
-static DECLARE_FSTYPE (devfs_fs_type, DEVFS_NAME, devfs_read_super, FS_SINGLE);
-
+static struct file_system_type devfs_fs_type = {
+	name:		DEVFS_NAME,
+	get_sb:		devfs_get_sb,
+};
 
 /*  File operations for devfsd follow  */
 
diff -Nru a/fs/devices.c b/fs/devices.c
--- a/fs/devices.c	Sun Feb 10 19:58:06 2002
+++ b/fs/devices.c	Sun Feb 10 19:58:06 2002
@@ -13,7 +13,7 @@
 #include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/string.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
diff -Nru a/fs/devpts/inode.c b/fs/devpts/inode.c
--- a/fs/devpts/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/devpts/inode.c	Sun Feb 10 19:58:05 2002
@@ -118,9 +118,9 @@
 	return 0;
 }
 
-struct super_block *devpts_read_super(struct super_block *s, void *data,
-				      int silent)
+static int devpts_fill_super(struct super_block *s, void *data, int silent)
 {
+	int error = -ENOMEM;
 	struct inode * inode;
 	struct devpts_sb_info *sbi;
 
@@ -136,6 +136,7 @@
 	memset(sbi->inodes, 0, sizeof(struct inode *) * sbi->max_ptys);
 
 	if ( devpts_parse_options(data,sbi) && !silent) {
+		error = -EINVAL;
 		printk("devpts: called with bogus options\n");
 		goto fail_free;
 	}
@@ -160,14 +161,14 @@
 
 	s->s_root = d_alloc_root(inode);
 	if (s->s_root)
-		return s;
+		return 0;
 	
 	printk("devpts: get root dentry failed\n");
 	iput(inode);
 fail_free:
 	kfree(sbi);
 fail:
-	return NULL;
+	return error;
 }
 
 static int devpts_statfs(struct super_block *sb, struct statfs *buf)
@@ -178,7 +179,17 @@
 	return 0;
 }
 
-static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, FS_SINGLE);
+static struct super_block *devpts_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, devpts_fill_super);
+}
+
+static struct file_system_type devpts_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"devpts",
+	get_sb:		devpts_get_sb,
+};
 
 void devpts_pty_new(int number, kdev_t device)
 {
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	Sun Feb 10 19:58:04 2002
+++ b/fs/dquot.c	Sun Feb 10 19:58:04 2002
@@ -51,7 +51,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
@@ -289,7 +289,7 @@
 					sizeof(struct dqblk), &offset);
 	if (ret != sizeof(struct dqblk))
 		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
-			kdevname(dquot->dq_sb->s_dev));
+			dquot->dq_sb->s_id);
 
 	set_fs(fs);
 	up(sem);
@@ -440,7 +440,7 @@
 	if (!dquot->dq_count) {
 		printk("VFS: dqput: trying to free free dquot\n");
 		printk("VFS: device %s, dquot of %s %d\n",
-			kdevname(dquot->dq_sb->s_dev),
+			dquot->dq_sb->s_id,
 			quotatypes[dquot->dq_type],
 			dquot->dq_id);
 		return;
@@ -715,7 +715,7 @@
 	if (!need_print_warning(dquot, flag))
 		return;
 	dquot->dq_flags |= flag;
-	tty_write_message(current->tty, (char *)bdevname(dquot->dq_sb->s_dev));
+	tty_write_message(current->tty, dquot->dq_sb->s_id);
 	if (warntype == ISOFTWARN || warntype == BSOFTWARN)
 		tty_write_message(current->tty, ": warning, ");
 	else
diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
--- a/fs/driverfs/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/driverfs/inode.c	Sun Feb 10 19:58:04 2002
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
@@ -244,6 +245,9 @@
 	if (!entry->show)
 		return 0;
 
+	if (count > PAGE_SIZE)
+		count = PAGE_SIZE;
+
 	dev = list_entry(entry->parent,struct device, dir);
 
 	page = (unsigned char*)__get_free_page(GFP_KERNEL);
@@ -259,7 +263,8 @@
 			if (len < 0)
 				retval = len;
 			break;
-		}
+		} else if (len > count)
+			len = count;
 
 		if (copy_to_user(buf,page,len)) {
 			retval = -EFAULT;
@@ -341,6 +346,7 @@
 {
 	loff_t retval = -EINVAL;
 
+	lock_kernel();
 	switch(orig) {
 	case 0:
 		if (offset > 0) {
@@ -357,6 +363,7 @@
 	default:
 		break;
 	}
+	unlock_kernel();
 	return retval;
 }
 
@@ -446,8 +453,7 @@
 	put_inode:	force_delete,
 };
 
-static struct super_block*
-driverfs_read_super(struct super_block *sb, void *data, int silent)
+static int driverfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
 	struct dentry *root;
@@ -460,20 +466,31 @@
 
 	if (!inode) {
 		DBG("%s: could not get inode!\n",__FUNCTION__);
-		return NULL;
+		return -ENOMEM;
 	}
 
 	root = d_alloc_root(inode);
 	if (!root) {
 		DBG("%s: could not get root dentry!\n",__FUNCTION__);
 		iput(inode);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root = root;
-	return sb;
+	return 0;
+}
+
+static struct super_block *driverfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, driverfs_fill_super);
 }
 
-static DECLARE_FSTYPE(driverfs_fs_type, "driverfs", driverfs_read_super, FS_SINGLE | FS_LITTER);
+static struct file_system_type driverfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"driverfs",
+	get_sb:		driverfs_get_sb,
+	fs_flags:	FS_LITTER,
+};
 
 static int get_mount(void)
 {
@@ -684,7 +701,8 @@
 
 	vfs_unlink(dentry->d_parent->d_inode,dentry);
 
-	unlock_dir(dentry);
+	up(&dentry->d_inode->i_sem);
+	dput(dentry);
 
 	/* remove reference count from when file was created */
 	dput(dentry);
@@ -724,7 +742,8 @@
 		}
 		node = node->next;
 	}
-	unlock_dir(dentry);
+	up(&dentry->d_inode->i_sem);
+	dput(dentry);
 }
 
 /**
@@ -743,8 +762,9 @@
 	if (!dir->dentry)
 		goto done;
 
-	/* lock the directory while we remove the files */
 	dentry = dget(dir->dentry);
+	dget(dentry->d_parent);
+	down(&dentry->d_parent->d_inode->i_sem);
 	down(&dentry->d_inode->i_sem);
 
 	node = dir->files.next;
@@ -759,11 +779,9 @@
 		node = dir->files.next;
 	}
 
-	/* now lock the parent, so we can remove this directory */
-	lock_parent(dentry);
-
 	vfs_rmdir(dentry->d_parent->d_inode,dentry);
-	double_unlock(dentry,dentry->d_parent);
+	up(&dentry->d_parent->d_inode->i_sem);
+	up(&dentry->d_inode->i_sem);
 
 	/* remove reference count from when directory was created */
 	dput(dentry);
diff -Nru a/fs/efs/inode.c b/fs/efs/inode.c
--- a/fs/efs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/efs/inode.c	Sun Feb 10 19:58:05 2002
@@ -10,6 +10,7 @@
 #include <linux/efs_fs.h>
 #include <linux/efs_fs_sb.h>
 #include <linux/module.h>
+#include <linux/fs.h>
 
 
 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
diff -Nru a/fs/efs/super.c b/fs/efs/super.c
--- a/fs/efs/super.c	Sun Feb 10 19:58:05 2002
+++ b/fs/efs/super.c	Sun Feb 10 19:58:05 2002
@@ -14,7 +14,18 @@
 #include <linux/efs_fs_sb.h>
 #include <linux/slab.h>
 
-static DECLARE_FSTYPE_DEV(efs_fs_type, "efs", efs_read_super);
+static struct super_block *efs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super);
+}
+
+static struct file_system_type efs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"efs",
+	get_sb:		efs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static kmem_cache_t * efs_inode_cachep;
 
@@ -188,7 +199,8 @@
 	return 0;    
 }
 
-struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
+int efs_fill_super(struct super_block *s, void *d, int silent)
+{
 	struct efs_sb_info *sb;
 	struct buffer_head *bh;
 
@@ -246,11 +258,11 @@
 		goto out_no_fs;
 	}
 
-	return(s);
+	return 0;
 
 out_no_fs_ul:
 out_no_fs:
-	return(NULL);
+	return -EINVAL;
 }
 
 int efs_statfs(struct super_block *s, struct statfs *buf) {
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Sun Feb 10 19:58:05 2002
+++ b/fs/exec.c	Sun Feb 10 19:58:05 2002
@@ -35,6 +35,7 @@
 #include <linux/highmem.h>
 #include <linux/spinlock.h>
 #include <linux/personality.h>
+#include <linux/binfmts.h>
 #define __NO_VERSION__
 #include <linux/module.h>
 
@@ -420,8 +421,8 @@
 		active_mm = current->active_mm;
 		current->mm = mm;
 		current->active_mm = mm;
-		task_unlock(current);
 		activate_mm(active_mm, mm);
+		task_unlock(current);
 		mm_release();
 		if (old_mm) {
 			if (active_mm != old_mm) BUG();
diff -Nru a/fs/ext2/balloc.c b/fs/ext2/balloc.c
--- a/fs/ext2/balloc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ext2/balloc.c	Sun Feb 10 19:58:05 2002
@@ -32,15 +32,15 @@
  */
 
 
-#define in_range(b, first, len)		((b) >= (first) && (b) <= (first) + (len) - 1)
+#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
 
 struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
 					     unsigned int block_group,
 					     struct buffer_head ** bh)
 {
 	unsigned long group_desc;
-	unsigned long desc;
-	struct ext2_group_desc * gdp;
+	unsigned long offset;
+	struct ext2_group_desc * desc;
 	struct ext2_sb_info *sbi = &sb->u.ext2_sb;
 
 	if (block_group >= sbi->s_groups_count) {
@@ -53,19 +53,19 @@
 	}
 	
 	group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
-	desc = block_group % EXT2_DESC_PER_BLOCK(sb);
+	offset = block_group % EXT2_DESC_PER_BLOCK(sb);
 	if (!sbi->s_group_desc[group_desc]) {
 		ext2_error (sb, "ext2_get_group_desc",
 			    "Group descriptor not loaded - "
 			    "block_group = %d, group_desc = %lu, desc = %lu",
-			     block_group, group_desc, desc);
+			     block_group, group_desc, offset);
 		return NULL;
 	}
 	
-	gdp = (struct ext2_group_desc *) sbi->s_group_desc[group_desc]->b_data;
+	desc = (struct ext2_group_desc *) sbi->s_group_desc[group_desc]->b_data;
 	if (bh)
 		*bh = sbi->s_group_desc[group_desc];
-	return gdp + desc;
+	return desc + offset;
 }
 
 /*
@@ -78,18 +78,18 @@
 static struct buffer_head *read_block_bitmap(struct super_block *sb,
 						unsigned int block_group)
 {
-	struct ext2_group_desc * gdp;
+	struct ext2_group_desc * desc;
 	struct buffer_head * bh = NULL;
 	
-	gdp = ext2_get_group_desc (sb, block_group, NULL);
-	if (!gdp)
+	desc = ext2_get_group_desc (sb, block_group, NULL);
+	if (!desc)
 		goto error_out;
-	bh = sb_bread(sb, le32_to_cpu(gdp->bg_block_bitmap));
+	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
 	if (!bh)
 		ext2_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %lu",
-			    block_group, (unsigned long) gdp->bg_block_bitmap);
+			    block_group, (unsigned long) desc->bg_block_bitmap);
 error_out:
 	return bh;
 }
@@ -135,7 +135,7 @@
 			goto read_it;
 		if (sbi->s_block_bitmap_number[slot] == slot)
 			goto found;
-		ext2_panic (sb, "__load_block_bitmap",
+		ext2_panic (sb, "load_block_bitmap",
 			    "block_group != block_bitmap_number");
 	}
 
@@ -166,6 +166,73 @@
 	return bh;
 }
 
+static inline int reserve_blocks(struct super_block *sb, int count)
+{
+	struct ext2_sb_info * sbi = EXT2_SB(sb);
+	struct ext2_super_block * es = sbi->s_es;
+	unsigned free_blocks = le32_to_cpu(es->s_free_blocks_count);
+	unsigned root_blocks = le32_to_cpu(es->s_r_blocks_count);
+
+	if (free_blocks < count)
+		count = free_blocks;
+
+	if (free_blocks < root_blocks + count && !capable(CAP_SYS_RESOURCE) &&
+	    sbi->s_resuid != current->fsuid &&
+	    (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+		/*
+		 * We are too close to reserve and we are not privileged.
+		 * Can we allocate anything at all?
+		 */
+		if (free_blocks > root_blocks)
+			count = free_blocks - root_blocks;
+		else
+			return 0;
+	}
+
+	es->s_free_blocks_count = cpu_to_le32(free_blocks - count);
+	mark_buffer_dirty(sbi->s_sbh);
+	sb->s_dirt = 1;
+	return count;
+}
+
+static inline void release_blocks(struct super_block *sb, int count)
+{
+	if (count) {
+		struct ext2_sb_info * sbi = EXT2_SB(sb);
+		struct ext2_super_block * es = sbi->s_es;
+		unsigned free_blocks = le32_to_cpu(es->s_free_blocks_count);
+		es->s_free_blocks_count = cpu_to_le32(free_blocks + count);
+		mark_buffer_dirty(sbi->s_sbh);
+		sb->s_dirt = 1;
+	}
+}
+
+static inline int group_reserve_blocks(struct ext2_group_desc *desc,
+				    struct buffer_head *bh, int count)
+{
+	unsigned free_blocks;
+
+	if (!desc->bg_free_blocks_count)
+		return 0;
+
+	free_blocks = le16_to_cpu(desc->bg_free_blocks_count);
+	if (free_blocks < count)
+		count = free_blocks;
+	desc->bg_free_blocks_count = cpu_to_le16(free_blocks - count);
+	mark_buffer_dirty(bh);
+	return count;
+}
+
+static inline void group_release_blocks(struct ext2_group_desc *desc,
+				    struct buffer_head *bh, int count)
+{
+	if (count) {
+		unsigned free_blocks = le16_to_cpu(desc->bg_free_blocks_count);
+		desc->bg_free_blocks_count = cpu_to_le16(free_blocks + count);
+		mark_buffer_dirty(bh);
+	}
+}
+
 /* Free given blocks, update quota and i_blocks field */
 void ext2_free_blocks (struct inode * inode, unsigned long block,
 		       unsigned long count)
@@ -176,15 +243,11 @@
 	unsigned long bit;
 	unsigned long i;
 	unsigned long overflow;
-	struct super_block * sb;
-	struct ext2_group_desc * gdp;
+	struct super_block * sb = inode->i_sb;
+	struct ext2_group_desc * desc;
 	struct ext2_super_block * es;
+	unsigned freed = 0, group_freed;
 
-	sb = inode->i_sb;
-	if (!sb) {
-		printk ("ext2_free_blocks: nonexistent device");
-		return;
-	}
 	lock_super (sb);
 	es = sb->u.ext2_sb.s_es;
 	if (block < le32_to_cpu(es->s_first_data_block) || 
@@ -214,53 +277,99 @@
 	bh = load_block_bitmap (sb, block_group);
 	if (IS_ERR(bh))
 		goto error_return;
-	
-	gdp = ext2_get_group_desc (sb, block_group, &bh2);
-	if (!gdp)
+
+	desc = ext2_get_group_desc (sb, block_group, &bh2);
+	if (!desc)
 		goto error_return;
 
-	if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
-	    in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
-	    in_range (block, le32_to_cpu(gdp->bg_inode_table),
+	if (in_range (le32_to_cpu(desc->bg_block_bitmap), block, count) ||
+	    in_range (le32_to_cpu(desc->bg_inode_bitmap), block, count) ||
+	    in_range (block, le32_to_cpu(desc->bg_inode_table),
 		      sb->u.ext2_sb.s_itb_per_group) ||
-	    in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
+	    in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
 		      sb->u.ext2_sb.s_itb_per_group))
 		ext2_error (sb, "ext2_free_blocks",
 			    "Freeing blocks in system zones - "
 			    "Block = %lu, count = %lu",
 			    block, count);
 
-	for (i = 0; i < count; i++) {
+	for (i = 0, group_freed = 0; i < count; i++) {
 		if (!ext2_clear_bit (bit + i, bh->b_data))
 			ext2_error (sb, "ext2_free_blocks",
 				      "bit already cleared for block %lu",
 				      block + i);
-		else {
-			DQUOT_FREE_BLOCK(inode, 1);
-			gdp->bg_free_blocks_count =
-				cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1);
-			es->s_free_blocks_count =
-				cpu_to_le32(le32_to_cpu(es->s_free_blocks_count)+1);
-		}
+		else
+			group_freed++;
 	}
-	
-	mark_buffer_dirty(bh2);
-	mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
 
 	mark_buffer_dirty(bh);
 	if (sb->s_flags & MS_SYNCHRONOUS) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
 	}
+
+	group_release_blocks(desc, bh2, group_freed);
+	freed += group_freed;
+
 	if (overflow) {
 		block += count;
 		count = overflow;
 		goto do_more;
 	}
-	sb->s_dirt = 1;
 error_return:
+	release_blocks(sb, freed);
 	unlock_super (sb);
-	return;
+	DQUOT_FREE_BLOCK(inode, freed);
+}
+
+static int grab_block(char *map, unsigned size, int goal)
+{
+	int k;
+	char *p, *r;
+
+	if (!ext2_test_bit(goal, map))
+		goto got_it;
+	if (goal) {
+		/*
+		 * The goal was occupied; search forward for a free 
+		 * block within the next XX blocks.
+		 *
+		 * end_goal is more or less random, but it has to be
+		 * less than EXT2_BLOCKS_PER_GROUP. Aligning up to the
+		 * next 64-bit boundary is simple..
+		 */
+		k = (goal + 63) & ~63;
+		goal = ext2_find_next_zero_bit(map, k, goal);
+		if (goal < k)
+			goto got_it;
+		/*
+		 * Search in the remainder of the current group.
+		 */
+	}
+
+	p = map + (goal >> 3);
+	r = memscan(p, 0, (size - goal + 7) >> 3);
+	k = (r - map) << 3;
+	if (k < size) {
+		/* 
+		 * We have succeeded in finding a free byte in the block
+		 * bitmap.  Now search backwards to find the start of this
+		 * group of free blocks - won't take more than 7 iterations.
+		 */
+		for (goal = k; goal && !ext2_test_bit (goal - 1, map); goal--)
+			;
+		goto got_it;
+	}
+
+	k = ext2_find_next_zero_bit ((u32 *)map, size, goal);
+	if (k < size) {
+		goal = k;
+		goto got_it;
+	}
+	return -1;
+got_it:
+	ext2_set_bit(goal, map);
+	return goal;
 }
 
 /*
@@ -274,224 +383,148 @@
 int ext2_new_block (struct inode * inode, unsigned long goal,
     u32 * prealloc_count, u32 * prealloc_block, int * err)
 {
-	struct buffer_head * bh;
-	struct buffer_head * bh2;
-	char * p, * r;
+	struct buffer_head *bh;
+	struct buffer_head *bh2;
+	struct ext2_group_desc *desc;
 	int i, j, k, tmp;
-	struct super_block * sb;
-	struct ext2_group_desc * gdp;
-	struct ext2_super_block * es;
-#ifdef EXT2FS_DEBUG
-	static int goal_hits = 0, goal_attempts = 0;
-#endif
+	int block = 0;
+	struct super_block *sb = inode->i_sb;
+	struct ext2_sb_info *sbi = EXT2_SB(sb);
+	struct ext2_super_block *es = sbi->s_es;
+	unsigned group_size = EXT2_BLOCKS_PER_GROUP(sb);
+	unsigned prealloc_goal = es->s_prealloc_blocks;
+	unsigned group_alloc = 0, es_alloc, dq_alloc;
+
+	if (!prealloc_goal--)
+		prealloc_goal = EXT2_DEFAULT_PREALLOC_BLOCKS - 1;
+	if (!prealloc_count || *prealloc_count)
+		prealloc_goal = 0;
+
+	*err = -EDQUOT;
+	if (DQUOT_ALLOC_BLOCK(inode, 1))
+		goto out;
+
+	while (prealloc_goal && DQUOT_PREALLOC_BLOCK(inode, prealloc_goal))
+		prealloc_goal--;
+
+	dq_alloc = prealloc_goal + 1;
+
 	*err = -ENOSPC;
-	sb = inode->i_sb;
-	if (!sb) {
-		printk ("ext2_new_block: nonexistent device");
-		return 0;
-	}
 
 	lock_super (sb);
-	es = sb->u.ext2_sb.s_es;
-	if (le32_to_cpu(es->s_free_blocks_count) <= le32_to_cpu(es->s_r_blocks_count) &&
-	    ((sb->u.ext2_sb.s_resuid != current->fsuid) &&
-	     (sb->u.ext2_sb.s_resgid == 0 ||
-	      !in_group_p (sb->u.ext2_sb.s_resgid)) && 
-	     !capable(CAP_SYS_RESOURCE)))
-		goto out;
+
+	es_alloc = reserve_blocks(sb, dq_alloc);
+	if (!es_alloc)
+		goto out_unlock;
 
 	ext2_debug ("goal=%lu.\n", goal);
 
-repeat:
-	/*
-	 * First, test whether the goal block is free.
-	 */
 	if (goal < le32_to_cpu(es->s_first_data_block) ||
 	    goal >= le32_to_cpu(es->s_blocks_count))
 		goal = le32_to_cpu(es->s_first_data_block);
-	i = (goal - le32_to_cpu(es->s_first_data_block)) / EXT2_BLOCKS_PER_GROUP(sb);
-	gdp = ext2_get_group_desc (sb, i, &bh2);
-	if (!gdp)
+	i = (goal - le32_to_cpu(es->s_first_data_block)) / group_size;
+	desc = ext2_get_group_desc (sb, i, &bh2);
+	if (!desc)
 		goto io_error;
 
-	if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {
-		j = ((goal - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb));
-#ifdef EXT2FS_DEBUG
-		if (j)
-			goal_attempts++;
-#endif
+	group_alloc = group_reserve_blocks(desc, bh2, es_alloc);
+	if (group_alloc) {
+		j = ((goal - le32_to_cpu(es->s_first_data_block)) % group_size);
 		bh = load_block_bitmap (sb, i);
 		if (IS_ERR(bh))
 			goto io_error;
 		
 		ext2_debug ("goal is at %d:%d.\n", i, j);
 
-		if (!ext2_test_bit(j, bh->b_data)) {
-			ext2_debug("goal bit allocated, %d hits\n",++goal_hits);
+		j = grab_block(bh->b_data, group_size, j);
+		if (j >= 0)
 			goto got_block;
-		}
-		if (j) {
-			/*
-			 * The goal was occupied; search forward for a free 
-			 * block within the next XX blocks.
-			 *
-			 * end_goal is more or less random, but it has to be
-			 * less than EXT2_BLOCKS_PER_GROUP. Aligning up to the
-			 * next 64-bit boundary is simple..
-			 */
-			int end_goal = (j + 63) & ~63;
-			j = ext2_find_next_zero_bit(bh->b_data, end_goal, j);
-			if (j < end_goal)
-				goto got_block;
-		}
-	
-		ext2_debug ("Bit not found near goal\n");
-
-		/*
-		 * There has been no free block found in the near vicinity
-		 * of the goal: do a search forward through the block groups,
-		 * searching in each group first for an entire free byte in
-		 * the bitmap and then for any free bit.
-		 * 
-		 * Search first in the remainder of the current group; then,
-		 * cyclicly search through the rest of the groups.
-		 */
-		p = ((char *) bh->b_data) + (j >> 3);
-		r = memscan(p, 0, (EXT2_BLOCKS_PER_GROUP(sb) - j + 7) >> 3);
-		k = (r - ((char *) bh->b_data)) << 3;
-		if (k < EXT2_BLOCKS_PER_GROUP(sb)) {
-			j = k;
-			goto search_back;
-		}
-
-		k = ext2_find_next_zero_bit ((unsigned long *) bh->b_data, 
-					EXT2_BLOCKS_PER_GROUP(sb),
-					j);
-		if (k < EXT2_BLOCKS_PER_GROUP(sb)) {
-			j = k;
-			goto got_block;
-		}
+		group_release_blocks(desc, bh2, group_alloc);
+		group_alloc = 0;
 	}
 
 	ext2_debug ("Bit not found in block group %d.\n", i);
 
 	/*
 	 * Now search the rest of the groups.  We assume that 
-	 * i and gdp correctly point to the last group visited.
+	 * i and desc correctly point to the last group visited.
 	 */
-	for (k = 0; k < sb->u.ext2_sb.s_groups_count; k++) {
+	for (k = 0; !group_alloc && k < sbi->s_groups_count; k++) {
 		i++;
-		if (i >= sb->u.ext2_sb.s_groups_count)
+		if (i >= sbi->s_groups_count)
 			i = 0;
-		gdp = ext2_get_group_desc (sb, i, &bh2);
-		if (!gdp)
+		desc = ext2_get_group_desc (sb, i, &bh2);
+		if (!desc)
 			goto io_error;
-		if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
-			break;
+		group_alloc = group_reserve_blocks(desc, bh2, es_alloc);
 	}
-	if (k >= sb->u.ext2_sb.s_groups_count)
-		goto out;
+	if (k >= sbi->s_groups_count)
+		goto out_release;
 	bh = load_block_bitmap (sb, i);
 	if (IS_ERR(bh))
 		goto io_error;
 	
-	r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
-	j = (r - bh->b_data) << 3;
-	if (j < EXT2_BLOCKS_PER_GROUP(sb))
-		goto search_back;
-	else
-		j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
-					 EXT2_BLOCKS_PER_GROUP(sb));
-	if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
+	j = grab_block(bh->b_data, group_size, 0);
+	if (j < 0) {
 		ext2_error (sb, "ext2_new_block",
 			    "Free blocks count corrupted for block group %d", i);
-		goto out;
+		group_alloc = 0;
+		goto out_release;
 	}
 
-search_back:
-	/* 
-	 * We have succeeded in finding a free byte in the block
-	 * bitmap.  Now search backwards up to 7 bits to find the
-	 * start of this group of free blocks.
-	 */
-	for (k = 0; k < 7 && j > 0 && !ext2_test_bit (j - 1, bh->b_data); k++, j--);
-	
 got_block:
+	ext2_debug("using block group %d(%d)\n", i, desc->bg_free_blocks_count);
 
-	ext2_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);
+	tmp = j + i * group_size + le32_to_cpu(es->s_first_data_block);
 
-	/*
-	 * Check quota for allocation of this block.
-	 */
-	if(DQUOT_ALLOC_BLOCK(inode, 1)) {
-		*err = -EDQUOT;
-		goto out;
-	}
-
-	tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block);
-
-	if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
-	    tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
-	    in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
-		      sb->u.ext2_sb.s_itb_per_group))
+	if (tmp == le32_to_cpu(desc->bg_block_bitmap) ||
+	    tmp == le32_to_cpu(desc->bg_inode_bitmap) ||
+	    in_range (tmp, le32_to_cpu(desc->bg_inode_table),
+		      sbi->s_itb_per_group))
 		ext2_error (sb, "ext2_new_block",
 			    "Allocating block in system zone - "
 			    "block = %u", tmp);
 
-	if (ext2_set_bit (j, bh->b_data)) {
-		ext2_warning (sb, "ext2_new_block",
-			      "bit already set for block %d", j);
-		DQUOT_FREE_BLOCK(inode, 1);
-		goto repeat;
+	if (tmp >= le32_to_cpu(es->s_blocks_count)) {
+		ext2_error (sb, "ext2_new_block",
+			    "block(%d) >= blocks count(%d) - "
+			    "block_group = %d, es == %p ",j,
+			le32_to_cpu(es->s_blocks_count), i, es);
+		goto out_release;
 	}
+	block = tmp;
 
+	/* OK, we _had_ allocated something */
 	ext2_debug ("found bit %d\n", j);
 
+	dq_alloc--;
+	es_alloc--;
+	group_alloc--;
+
 	/*
 	 * Do block preallocation now if required.
 	 */
-#ifdef EXT2_PREALLOCATE
 	/* Writer: ->i_prealloc* */
-	if (prealloc_count && !*prealloc_count) {
-		int	prealloc_goal;
-		unsigned long next_block = tmp + 1;
-
-		prealloc_goal = es->s_prealloc_blocks ?
-			es->s_prealloc_blocks : EXT2_DEFAULT_PREALLOC_BLOCKS;
+	if (group_alloc && !*prealloc_count) {
+		unsigned long next_block = block + 1;
 
 		*prealloc_block = next_block;
 		/* Writer: end */
-		for (k = 1;
-		     k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb);
-		     k++, next_block++) {
-			if (DQUOT_PREALLOC_BLOCK(inode, 1))
-				break;
+		while (group_alloc && ++j < group_size) {
 			/* Writer: ->i_prealloc* */
 			if (*prealloc_block + *prealloc_count != next_block ||
-			    ext2_set_bit (j + k, bh->b_data)) {
+			    ext2_set_bit (j, bh->b_data)) {
 				/* Writer: end */
-				DQUOT_FREE_BLOCK(inode, 1);
  				break;
 			}
 			(*prealloc_count)++;
 			/* Writer: end */
+			next_block++;
+			es_alloc--;
+			dq_alloc--;
+			group_alloc--;
 		}	
-		/*
-		 * As soon as we go for per-group spinlocks we'll need these
-		 * done inside the loop above.
-		 */
-		gdp->bg_free_blocks_count =
-			cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -
-			       (k - 1));
-		es->s_free_blocks_count =
-			cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) -
-			       (k - 1));
-		ext2_debug ("Preallocated a further %lu bits.\n",
-			       (k - 1));
 	}
-#endif
-
-	j = tmp;
 
 	mark_buffer_dirty(bh);
 	if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -499,32 +532,21 @@
 		wait_on_buffer (bh);
 	}
 
-	if (j >= le32_to_cpu(es->s_blocks_count)) {
-		ext2_error (sb, "ext2_new_block",
-			    "block(%d) >= blocks count(%d) - "
-			    "block_group = %d, es == %p ",j,
-			le32_to_cpu(es->s_blocks_count), i, es);
-		goto out;
-	}
-
-	ext2_debug ("allocating block %d. "
-		    "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
+	ext2_debug ("allocating block %d. ", block);
 
-	gdp->bg_free_blocks_count = cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1);
-	mark_buffer_dirty(bh2);
-	es->s_free_blocks_count = cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - 1);
-	mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
-	sb->s_dirt = 1;
-	unlock_super (sb);
+out_release:
+	group_release_blocks(desc, bh2, group_alloc);
+	release_blocks(sb, es_alloc);
 	*err = 0;
-	return j;
-	
+out_unlock:
+	unlock_super (sb);
+	DQUOT_FREE_BLOCK(inode, dq_alloc);
+out:
+	return block;
+
 io_error:
 	*err = -EIO;
-out:
-	unlock_super (sb);
-	return 0;
-	
+	goto out_release;
 }
 
 unsigned long ext2_count_free_blocks (struct super_block * sb)
@@ -532,27 +554,27 @@
 #ifdef EXT2FS_DEBUG
 	struct ext2_super_block * es;
 	unsigned long desc_count, bitmap_count, x;
-	struct ext2_group_desc * gdp;
+	struct ext2_group_desc * desc;
 	int i;
 	
 	lock_super (sb);
 	es = sb->u.ext2_sb.s_es;
 	desc_count = 0;
 	bitmap_count = 0;
-	gdp = NULL;
+	desc = NULL;
 	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
 		struct buffer_head *bh;
-		gdp = ext2_get_group_desc (sb, i, NULL);
-		if (!gdp)
+		desc = ext2_get_group_desc (sb, i, NULL);
+		if (!desc)
 			continue;
-		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
+		desc_count += le16_to_cpu(desc->bg_free_blocks_count);
 		bh = load_block_bitmap (sb, i);
 		if (IS_ERR(bh))
 			continue;
 		
 		x = ext2_count_free (bh, sb->s_blocksize);
 		printk ("group %d: stored = %d, counted = %lu\n",
-			i, le16_to_cpu(gdp->bg_free_blocks_count), x);
+			i, le16_to_cpu(desc->bg_free_blocks_count), x);
 		bitmap_count += x;
 	}
 	printk("ext2_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
@@ -632,18 +654,18 @@
 	struct ext2_super_block * es;
 	unsigned long desc_count, bitmap_count, x, j;
 	unsigned long desc_blocks;
-	struct ext2_group_desc * gdp;
+	struct ext2_group_desc * desc;
 	int i;
 
 	es = sb->u.ext2_sb.s_es;
 	desc_count = 0;
 	bitmap_count = 0;
-	gdp = NULL;
+	desc = NULL;
 	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-		gdp = ext2_get_group_desc (sb, i, NULL);
-		if (!gdp)
+		desc = ext2_get_group_desc (sb, i, NULL);
+		if (!desc)
 			continue;
-		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
+		desc_count += le16_to_cpu(desc->bg_free_blocks_count);
 		bh = load_block_bitmap (sb, i);
 		if (IS_ERR(bh))
 			continue;
@@ -659,28 +681,28 @@
 					   "Descriptor block #%ld in group "
 					   "%d is marked free", j, i);
 
-		if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data))
+		if (!block_in_use (le32_to_cpu(desc->bg_block_bitmap), sb, bh->b_data))
 			ext2_error (sb, "ext2_check_blocks_bitmap",
 				    "Block bitmap for group %d is marked free",
 				    i);
 
-		if (!block_in_use (le32_to_cpu(gdp->bg_inode_bitmap), sb, bh->b_data))
+		if (!block_in_use (le32_to_cpu(desc->bg_inode_bitmap), sb, bh->b_data))
 			ext2_error (sb, "ext2_check_blocks_bitmap",
 				    "Inode bitmap for group %d is marked free",
 				    i);
 
 		for (j = 0; j < sb->u.ext2_sb.s_itb_per_group; j++)
-			if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j, sb, bh->b_data))
+			if (!block_in_use (le32_to_cpu(desc->bg_inode_table) + j, sb, bh->b_data))
 				ext2_error (sb, "ext2_check_blocks_bitmap",
 					    "Block #%ld of the inode table in "
 					    "group %d is marked free", j, i);
 
 		x = ext2_count_free (bh, sb->s_blocksize);
-		if (le16_to_cpu(gdp->bg_free_blocks_count) != x)
+		if (le16_to_cpu(desc->bg_free_blocks_count) != x)
 			ext2_error (sb, "ext2_check_blocks_bitmap",
 				    "Wrong free blocks count for group %d, "
 				    "stored = %d, counted = %lu", i,
-				    le16_to_cpu(gdp->bg_free_blocks_count), x);
+				    le16_to_cpu(desc->bg_free_blocks_count), x);
 		bitmap_count += x;
 	}
 	if (le32_to_cpu(es->s_free_blocks_count) != bitmap_count)
diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h
--- a/fs/ext2/ext2.h	Sun Feb 10 19:58:06 2002
+++ b/fs/ext2/ext2.h	Sun Feb 10 19:58:06 2002
@@ -96,7 +96,6 @@
 extern void ext2_put_super (struct super_block *);
 extern void ext2_write_super (struct super_block *);
 extern int ext2_remount (struct super_block *, int *, char *);
-extern struct super_block * ext2_read_super (struct super_block *,void *,int);
 extern int ext2_statfs (struct super_block *, struct statfs *);
 
 /*
diff -Nru a/fs/ext2/file.c b/fs/ext2/file.c
--- a/fs/ext2/file.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ext2/file.c	Sun Feb 10 19:58:05 2002
@@ -19,7 +19,7 @@
  */
 
 #include "ext2.h"
-#include <linux/sched.h>
+#include <linux/time.h>
 
 /*
  * Called when an inode is released. Note that this is different
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ext2/inode.c	Sun Feb 10 19:58:04 2002
@@ -25,7 +25,7 @@
 #include "ext2.h"
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/highuid.h>
 #include <linux/quotaops.h>
 #include <linux/module.h>
diff -Nru a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
--- a/fs/ext2/ioctl.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ext2/ioctl.c	Sun Feb 10 19:58:06 2002
@@ -8,7 +8,7 @@
  */
 
 #include "ext2.h"
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <asm/uaccess.h>
 
 
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ext2/super.c	Sun Feb 10 19:58:04 2002
@@ -441,8 +441,7 @@
 	return res;
 }
 
-struct super_block * ext2_read_super (struct super_block * sb, void * data,
-				      int silent)
+static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct buffer_head * bh;
 	struct ext2_super_block * es;
@@ -465,14 +464,13 @@
 
 	sb->u.ext2_sb.s_mount_opt = 0;
 	if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
-	    &sb->u.ext2_sb.s_mount_opt)) {
-		return NULL;
-	}
+	    &sb->u.ext2_sb.s_mount_opt))
+		return -EINVAL;
 
 	blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
 	if (!blocksize) {
 		printk ("EXT2-fs: unable to set blocksize\n");
-		return NULL;
+		return -EINVAL;
 	}
 
 	/*
@@ -487,7 +485,7 @@
 
 	if (!(bh = sb_bread(sb, logic_sb_block))) {
 		printk ("EXT2-fs: unable to read superblock\n");
-		return NULL;
+		return -EINVAL;
 	}
 	/*
 	 * Note: s_es must be initialized as soon as possible because
@@ -533,7 +531,7 @@
 
 		if (!sb_set_blocksize(sb, blocksize)) {
 			printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n");
-			return NULL;
+			return -EINVAL;
 		}
 
 		logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
@@ -684,14 +682,14 @@
 		goto failed_mount2;
 	}
 	ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-	return sb;
+	return 0;
 failed_mount2:
 	for (i = 0; i < db_count; i++)
 		brelse(sb->u.ext2_sb.s_group_desc[i]);
 	kfree(sb->u.ext2_sb.s_group_desc);
 failed_mount:
 	brelse(bh);
-	return NULL;
+	return -EINVAL;
 }
 
 static void ext2_commit_super (struct super_block * sb,
@@ -843,7 +841,18 @@
 	return 0;
 }
 
-static DECLARE_FSTYPE_DEV(ext2_fs_type, "ext2", ext2_read_super);
+static struct super_block *ext2_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
+}
+
+static struct file_system_type ext2_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"ext2",
+	get_sb:		ext2_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_ext2_fs(void)
 {
diff -Nru a/fs/ext3/balloc.c b/fs/ext3/balloc.c
--- a/fs/ext3/balloc.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ext3/balloc.c	Sun Feb 10 19:58:04 2002
@@ -12,7 +12,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
diff -Nru a/fs/ext3/file.c b/fs/ext3/file.c
--- a/fs/ext3/file.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ext3/file.c	Sun Feb 10 19:58:06 2002
@@ -18,7 +18,7 @@
  *	(jj@sunsite.ms.mff.cuni.cz)
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/locks.h>
 #include <linux/jbd.h>
diff -Nru a/fs/ext3/fsync.c b/fs/ext3/fsync.c
--- a/fs/ext3/fsync.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ext3/fsync.c	Sun Feb 10 19:58:06 2002
@@ -22,7 +22,7 @@
  * we can depend on generic_block_fdatasync() to sync the data blocks.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
--- a/fs/ext3/ialloc.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ext3/ialloc.c	Sun Feb 10 19:58:06 2002
@@ -12,7 +12,7 @@
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ext3/inode.c	Sun Feb 10 19:58:04 2002
@@ -23,7 +23,7 @@
  */
 
 #include <linux/fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/ext3_jbd.h>
 #include <linux/jbd.h>
 #include <linux/locks.h>
diff -Nru a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
--- a/fs/ext3/ioctl.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ext3/ioctl.c	Sun Feb 10 19:58:05 2002
@@ -11,7 +11,7 @@
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <asm/uaccess.h>
 
 
diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
--- a/fs/ext3/namei.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ext3/namei.c	Sun Feb 10 19:58:04 2002
@@ -20,7 +20,7 @@
 
 #include <linux/fs.h>
 #include <linux/jbd.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
 #include <linux/fcntl.h>
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ext3/super.c	Sun Feb 10 19:58:05 2002
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
@@ -934,8 +934,7 @@
 	return res;
 }
 
-struct super_block * ext3_read_super (struct super_block * sb, void * data,
-				      int silent)
+static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 {
 	struct buffer_head * bh;
 	struct ext3_super_block *es = 0;
@@ -1054,7 +1053,7 @@
 		if (!bh) {
 			printk(KERN_ERR 
 			       "EXT3-fs: Can't read superblock on 2nd try.\n");
-			return NULL;
+			return -EINVAL;
 		}
 		es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
 		sbi->s_es = es;
@@ -1252,7 +1251,7 @@
 		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
 		"writeback");
 
-	return sb;
+	return 0;
 
 failed_mount3:
 	journal_destroy(sbi->s_journal);
@@ -1264,7 +1263,7 @@
 	ext3_blkdev_remove(sbi);
 	brelse(bh);
 out_fail:
-	return NULL;
+	return -EINVAL;
 }
 
 static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
@@ -1769,7 +1768,18 @@
 	return 0;
 }
 
-static DECLARE_FSTYPE_DEV(ext3_fs_type, "ext3", ext3_read_super);
+static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super);
+}
+
+static struct file_system_type ext3_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"ext3",
+	get_sb:		ext3_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_ext3_fs(void)
 {
diff -Nru a/fs/fat/dir.c b/fs/fat/dir.c
--- a/fs/fat/dir.c	Sun Feb 10 19:58:04 2002
+++ b/fs/fat/dir.c	Sun Feb 10 19:58:04 2002
@@ -14,7 +14,7 @@
  */
 
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/msdos_fs.h>
 #include <linux/dirent.h>
 
diff -Nru a/fs/fat/fatfs_syms.c b/fs/fat/fatfs_syms.c
--- a/fs/fat/fatfs_syms.c	Sun Feb 10 19:58:04 2002
+++ b/fs/fat/fatfs_syms.c	Sun Feb 10 19:58:04 2002
@@ -47,5 +47,10 @@
 	return fat_init_inodecache();
 }
 
+static void __exit exit_fat_fs(void)
+{
+	fat_destroy_inodecache();
+}
+
 module_init(init_fat_fs)
-module_exit(fat_destroy_inodecache)
+module_exit(exit_fat_fs)
diff -Nru a/fs/fat/file.c b/fs/fat/file.c
--- a/fs/fat/file.c	Sun Feb 10 19:58:05 2002
+++ b/fs/fat/file.c	Sun Feb 10 19:58:05 2002
@@ -6,7 +6,7 @@
  *  regular file handling primitives for fat-based filesystems
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/locks.h>
 #include <linux/msdos_fs.h>
 #include <linux/fat_cvf.h>
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	Sun Feb 10 19:58:06 2002
+++ b/fs/fat/inode.c	Sun Feb 10 19:58:06 2002
@@ -11,7 +11,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/locks.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
diff -Nru a/fs/fifo.c b/fs/fifo.c
--- a/fs/fifo.c	Sun Feb 10 19:58:05 2002
+++ b/fs/fifo.c	Sun Feb 10 19:58:05 2002
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
+#include <linux/fs.h>
 
 static void wait_for_partner(struct inode* inode, unsigned int* cnt)
 {
diff -Nru a/fs/file.c b/fs/file.c
--- a/fs/file.c	Sun Feb 10 19:58:04 2002
+++ b/fs/file.c	Sun Feb 10 19:58:04 2002
@@ -8,7 +8,7 @@
 
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/file.h>
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Sun Feb 10 19:58:04 2002
+++ b/fs/file_table.c	Sun Feb 10 19:58:04 2002
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/iobuf.h>
+#include <linux/fs.h>
 
 /* sysctl tunables... */
 struct files_stat_struct files_stat = {0, 0, NR_FILE};
@@ -186,3 +187,17 @@
 	file_list_unlock();
 	return 0;
 }
+
+void __init files_init(unsigned long mempages)
+{ 
+	int n; 
+	/* One file with associated inode and dcache is very roughly 1K. 
+	 * Per default don't use more than 10% of our memory for files. 
+	 */ 
+
+	n = (mempages * (PAGE_SIZE / 1024)) / 10;
+	files_stat.max_files = n; 
+	if (files_stat.max_files < NR_FILE)
+		files_stat.max_files = NR_FILE;
+} 
+
diff -Nru a/fs/filesystems.c b/fs/filesystems.c
--- a/fs/filesystems.c	Sun Feb 10 19:58:05 2002
+++ b/fs/filesystems.c	Sun Feb 10 19:58:05 2002
@@ -8,10 +8,11 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/smp_lock.h>
 #include <linux/kmod.h>
 #include <linux/nfsd/interface.h>
+#include <linux/linkage.h>
 
 #if defined(CONFIG_NFSD_MODULE)
 struct nfsd_linkage *nfsd_linkage = NULL;
diff -Nru a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
--- a/fs/freevxfs/vxfs_lookup.c	Sun Feb 10 19:58:06 2002
+++ b/fs/freevxfs/vxfs_lookup.c	Sun Feb 10 19:58:06 2002
@@ -33,7 +33,7 @@
  * Veritas filesystem driver - lookup and other directory related code.
  */
 #include <linux/fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/kernel.h>
diff -Nru a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
--- a/fs/freevxfs/vxfs_super.c	Sun Feb 10 19:58:05 2002
+++ b/fs/freevxfs/vxfs_super.c	Sun Feb 10 19:58:05 2002
@@ -135,8 +135,7 @@
  * Locking:
  *   We are under the bkl and @sbp->s_lock.
  */
-static struct super_block *
-vxfs_read_super(struct super_block *sbp, void *dp, int silent)
+static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 {
 	struct vxfs_sb_info	*infp;
 	struct vxfs_sb		*rsbp;
@@ -146,7 +145,7 @@
 	infp = kmalloc(sizeof(*infp), GFP_KERNEL);
 	if (!infp) {
 		printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
-		return NULL;
+		return -ENOMEM;
 	}
 	memset(infp, 0, sizeof(*infp));
 
@@ -213,7 +212,7 @@
 		goto out_free_ilist;
 	}
 
-	return (sbp);
+	return 0;
 	
 out_free_ilist:
 	vxfs_put_fake_inode(infp->vsi_fship);
@@ -222,13 +221,24 @@
 out:
 	brelse(bp);
 	kfree(infp);
-	return NULL;
+	return -EINVAL;
 }
 
 /*
  * The usual module blurb.
  */
-static DECLARE_FSTYPE_DEV(vxfs_fs_type, "vxfs", vxfs_read_super);
+static struct super_block *vxfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
+}
+
+static struct file_system_type vxfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"vxfs",
+	get_sb:		vxfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init
 vxfs_init(void)
diff -Nru a/fs/hfs/catalog.c b/fs/hfs/catalog.c
--- a/fs/hfs/catalog.c	Sun Feb 10 19:58:04 2002
+++ b/fs/hfs/catalog.c	Sun Feb 10 19:58:04 2002
@@ -1346,13 +1346,6 @@
 		return -EINVAL;
 	}
 
-	while (mdb->rename_lock) {
-		hfs_sleep_on(&mdb->rename_wait);
-	}
-	spin_lock(&entry_lock);
-	mdb->rename_lock = 1; /* XXX: should be atomic_inc */
-	spin_unlock(&entry_lock);
-
 	/* keep readers from getting confused by changing dir size */
 	start_write(new_dir);
 	if (old_dir != new_dir) {
@@ -1567,11 +1560,6 @@
 		end_write(old_dir);
 	}
 	end_write(new_dir);
-	spin_lock(&entry_lock);
-	mdb->rename_lock = 0; /* XXX: should use atomic_dec */
-	hfs_wake_up(&mdb->rename_wait);
-	spin_unlock(&entry_lock);
-
 	return error;
 }
 
diff -Nru a/fs/hfs/extent.c b/fs/hfs/extent.c
--- a/fs/hfs/extent.c	Sun Feb 10 19:58:06 2002
+++ b/fs/hfs/extent.c	Sun Feb 10 19:58:06 2002
@@ -48,10 +48,7 @@
  * Get an exclusive lock on the B-tree bitmap.
  */
 static inline void lock_bitmap(struct hfs_mdb *mdb) {
-	while (mdb->bitmap_lock) {
-		hfs_sleep_on(&mdb->bitmap_wait);
-	}
-	mdb->bitmap_lock = 1;
+	down(&mdb->bitmap_sem);
 }
 
 /*
@@ -60,8 +57,7 @@
  * Relinquish an exclusive lock on the B-tree bitmap.
  */
 static inline void unlock_bitmap(struct hfs_mdb *mdb) {
-	mdb->bitmap_lock = 0;
-	hfs_wake_up(&mdb->bitmap_wait);
+	up(&mdb->bitmap_sem);
 }
 
 /*
diff -Nru a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c
--- a/fs/hfs/file_cap.c	Sun Feb 10 19:58:03 2002
+++ b/fs/hfs/file_cap.c	Sun Feb 10 19:58:03 2002
@@ -24,6 +24,7 @@
 #include <linux/hfs_fs_sb.h>
 #include <linux/hfs_fs_i.h>
 #include <linux/hfs_fs.h>
+#include <linux/smp_lock.h>
 
 /*================ Forward declarations ================*/
 static loff_t      cap_info_llseek(struct file *, loff_t,
diff -Nru a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c
--- a/fs/hfs/file_hdr.c	Sun Feb 10 19:58:04 2002
+++ b/fs/hfs/file_hdr.c	Sun Feb 10 19:58:04 2002
@@ -29,6 +29,7 @@
 #include <linux/hfs_fs_sb.h>
 #include <linux/hfs_fs_i.h>
 #include <linux/hfs_fs.h>
+#include <linux/smp_lock.h>
 
 /* prodos types */
 #define PRODOSI_FTYPE_DIR   0x0F
diff -Nru a/fs/hfs/hfs.h b/fs/hfs/hfs.h
--- a/fs/hfs/hfs.h	Sun Feb 10 19:58:06 2002
+++ b/fs/hfs/hfs.h	Sun Feb 10 19:58:06 2002
@@ -271,10 +271,7 @@
 						   512-byte blocks per
 						   "allocation block" */
 	hfs_u16			attrib;		/* Attribute word */
-	hfs_wait_queue		rename_wait;
-	int			rename_lock;
-	hfs_wait_queue		bitmap_wait;
-	int			bitmap_lock;
+	struct semaphore	bitmap_sem;
         struct list_head        entry_dirty;
 };
 
diff -Nru a/fs/hfs/mdb.c b/fs/hfs/mdb.c
--- a/fs/hfs/mdb.c	Sun Feb 10 19:58:05 2002
+++ b/fs/hfs/mdb.c	Sun Feb 10 19:58:05 2002
@@ -100,8 +100,7 @@
 	mdb->magic = HFS_MDB_MAGIC;
 	mdb->sys_mdb = sys_mdb;
 	INIT_LIST_HEAD(&mdb->entry_dirty);
-	hfs_init_waitqueue(&mdb->rename_wait);
-	hfs_init_waitqueue(&mdb->bitmap_wait);
+	init_MUTEX(&mdb->bitmap_sem);
 
 	/* See if this is an HFS filesystem */
 	buf = hfs_buffer_get(sys_mdb, part_start + HFS_MDB_BLK, 1);
diff -Nru a/fs/hfs/super.c b/fs/hfs/super.c
--- a/fs/hfs/super.c	Sun Feb 10 19:58:05 2002
+++ b/fs/hfs/super.c	Sun Feb 10 19:58:05 2002
@@ -95,7 +95,18 @@
 
 /*================ File-local variables ================*/
 
-static DECLARE_FSTYPE_DEV(hfs_fs, "hfs", hfs_read_super);
+static struct super_block *hfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super);
+}
+
+static struct file_system_type hfs_fs = {
+	owner:		THIS_MODULE,
+	name:		"hfs",
+	get_sb:		hfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 /*================ File-local functions ================*/
 
@@ -429,8 +440,7 @@
  * hfs_btree_init() to get the necessary data about the extents and
  * catalog B-trees and, finally, reading the root inode into memory.
  */
-struct super_block *hfs_read_super(struct super_block *s, void *data,
-				   int silent)
+int hfs_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct hfs_mdb *mdb;
 	struct hfs_cat_key key;
@@ -501,7 +511,7 @@
 	s->s_root->d_op = &hfs_dentry_operations;
 
 	/* everything's okay */
-	return s;
+	return 0;
 
 bail_no_root: 
 	hfs_warn("hfs_fs: get root inode failed.\n");
@@ -511,7 +521,7 @@
 bail2:
 	set_blocksize(dev, BLOCK_SIZE);
 bail3:
-	return NULL;	
+	return -EINVAL;	
 }
 
 static int __init init_hfs_fs(void)
diff -Nru a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
--- a/fs/hpfs/buffer.c	Sun Feb 10 19:58:06 2002
+++ b/fs/hpfs/buffer.c	Sun Feb 10 19:58:06 2002
@@ -14,8 +14,7 @@
 #ifdef DEBUG_LOCKS
 	printk("lock creation\n");
 #endif
-	while (s->s_hpfs_creation_de_lock) sleep_on(&s->s_hpfs_creation_de);
-	s->s_hpfs_creation_de_lock = 1;
+	down(&s->u.hpfs_sb.hpfs_creation_de);
 }
 
 void hpfs_unlock_creation(struct super_block *s)
@@ -23,8 +22,7 @@
 #ifdef DEBUG_LOCKS
 	printk("unlock creation\n");
 #endif
-	s->s_hpfs_creation_de_lock = 0;
-	wake_up(&s->s_hpfs_creation_de);
+	up(&s->u.hpfs_sb.hpfs_creation_de);
 }
 
 void hpfs_lock_iget(struct super_block *s, int mode)
diff -Nru a/fs/hpfs/dir.c b/fs/hpfs/dir.c
--- a/fs/hpfs/dir.c	Sun Feb 10 19:58:05 2002
+++ b/fs/hpfs/dir.c	Sun Feb 10 19:58:05 2002
@@ -7,7 +7,7 @@
  */
 
 #include "hpfs_fn.h"
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/smp_lock.h>
 
 int hpfs_dir_release(struct inode *inode, struct file *filp)
diff -Nru a/fs/hpfs/file.c b/fs/hpfs/file.c
--- a/fs/hpfs/file.c	Sun Feb 10 19:58:06 2002
+++ b/fs/hpfs/file.c	Sun Feb 10 19:58:06 2002
@@ -7,7 +7,7 @@
  */
 
 #include <linux/string.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
diff -Nru a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
--- a/fs/hpfs/hpfs_fn.h	Sun Feb 10 19:58:04 2002
+++ b/fs/hpfs/hpfs_fn.h	Sun Feb 10 19:58:04 2002
@@ -15,7 +15,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/locks.h>
 #include <linux/stat.h>
 #include <linux/string.h>
diff -Nru a/fs/hpfs/inode.c b/fs/hpfs/inode.c
--- a/fs/hpfs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/hpfs/inode.c	Sun Feb 10 19:58:05 2002
@@ -6,7 +6,7 @@
  *  inode VFS functions
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
diff -Nru a/fs/hpfs/super.c b/fs/hpfs/super.c
--- a/fs/hpfs/super.c	Sun Feb 10 19:58:04 2002
+++ b/fs/hpfs/super.c	Sun Feb 10 19:58:04 2002
@@ -405,8 +405,7 @@
 	return 0;
 }
 
-struct super_block *hpfs_read_super(struct super_block *s, void *options,
-				    int silent)
+static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 {
 	struct buffer_head *bh0, *bh1, *bh2;
 	struct hpfs_boot_block *bootblock;
@@ -427,8 +426,8 @@
 	s->s_hpfs_bmp_dir = NULL;
 	s->s_hpfs_cp_table = NULL;
 
-	s->s_hpfs_creation_de_lock = s->s_hpfs_rd_inode = 0;
-	init_waitqueue_head(&s->s_hpfs_creation_de);
+	s->s_hpfs_rd_inode = 0;
+	init_MUTEX(&s->u.hpfs_sb.hpfs_creation_de);
 	init_waitqueue_head(&s->s_hpfs_iget_q);
 
 	uid = current->uid;
@@ -598,7 +597,7 @@
 	}
 	if (de) hpfs_brelse4(&qbh);
 
-	return s;
+	return 0;
 
 bail4:	brelse(bh2);
 bail3:	brelse(bh1);
@@ -607,10 +606,21 @@
 bail0:
 	if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir);
 	if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table);
-	return NULL;
+	return -EINVAL;
 }
 
-DECLARE_FSTYPE_DEV(hpfs_fs_type, "hpfs", hpfs_read_super);
+static struct super_block *hpfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super);
+}
+
+static struct file_system_type hpfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"hpfs",
+	get_sb:		hpfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_hpfs_fs(void)
 {
diff -Nru a/fs/inflate_fs/infutil.h b/fs/inflate_fs/infutil.h
--- a/fs/inflate_fs/infutil.h	Sun Feb 10 19:58:05 2002
+++ b/fs/inflate_fs/infutil.h	Sun Feb 10 19:58:05 2002
@@ -11,7 +11,7 @@
 #ifndef _INFUTIL_H
 #define _INFUTIL_H
 
-#include "zconf.h"
+#include <linux/zconf.h>
 #include "inftrees.h"
 #include "infcodes.h"
 
diff -Nru a/fs/inflate_fs/zconf.h b/fs/inflate_fs/zconf.h
--- a/fs/inflate_fs/zconf.h	Sun Feb 10 19:58:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,90 +0,0 @@
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#ifndef _ZCONF_H
-#define _ZCONF_H
-
-#if defined(__GNUC__) || defined(__386__) || defined(i386)
-#  ifndef __32BIT__
-#    define __32BIT__
-#  endif
-#endif
-
-#if defined(__STDC__) || defined(__cplusplus)
-#  ifndef STDC
-#    define STDC
-#  endif
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  define MAX_MEM_LEVEL 9
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-#ifndef ZEXPORT
-#  define ZEXPORT
-#endif
-#ifndef ZEXPORTVA
-#  define ZEXPORTVA
-#endif
-#ifndef ZEXTERN
-#  define ZEXTERN extern
-#endif
-#ifndef FAR
-#   define FAR
-#endif
-
-typedef unsigned char  Byte;  /* 8 bits */
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-typedef Byte  FAR Bytef;
-typedef char  FAR charf;
-typedef int   FAR intf;
-typedef uInt  FAR uIntf;
-typedef uLong FAR uLongf;
-
-typedef void FAR *voidpf;
-typedef void     *voidp;
-
-#include <linux/types.h> /* for off_t */
-#include <linux/unistd.h>    /* for SEEK_* and off_t */
-#define z_off_t  off_t
-
-#endif /* _ZCONF_H */
diff -Nru a/fs/intermezzo/cache.c b/fs/intermezzo/cache.c
--- a/fs/intermezzo/cache.c	Sun Feb 10 19:58:06 2002
+++ b/fs/intermezzo/cache.c	Sun Feb 10 19:58:06 2002
@@ -19,7 +19,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/intermezzo/dcache.c b/fs/intermezzo/dcache.c
--- a/fs/intermezzo/dcache.c	Sun Feb 10 19:58:05 2002
+++ b/fs/intermezzo/dcache.c	Sun Feb 10 19:58:05 2002
@@ -10,7 +10,7 @@
 #define __NO_VERSION__
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c
--- a/fs/intermezzo/dir.c	Sun Feb 10 19:58:05 2002
+++ b/fs/intermezzo/dir.c	Sun Feb 10 19:58:05 2002
@@ -21,7 +21,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/intermezzo/file.c b/fs/intermezzo/file.c
--- a/fs/intermezzo/file.c	Sun Feb 10 19:58:04 2002
+++ b/fs/intermezzo/file.c	Sun Feb 10 19:58:04 2002
@@ -28,7 +28,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/intermezzo/journal_ext2.c b/fs/intermezzo/journal_ext2.c
--- a/fs/intermezzo/journal_ext2.c	Sun Feb 10 19:58:05 2002
+++ b/fs/intermezzo/journal_ext2.c	Sun Feb 10 19:58:05 2002
@@ -5,7 +5,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff -Nru a/fs/intermezzo/journal_ext3.c b/fs/intermezzo/journal_ext3.c
--- a/fs/intermezzo/journal_ext3.c	Sun Feb 10 19:58:06 2002
+++ b/fs/intermezzo/journal_ext3.c	Sun Feb 10 19:58:06 2002
@@ -10,7 +10,7 @@
 #include <linux/types.h>
 #include <linux/param.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff -Nru a/fs/intermezzo/journal_obdfs.c b/fs/intermezzo/journal_obdfs.c
--- a/fs/intermezzo/journal_obdfs.c	Sun Feb 10 19:58:03 2002
+++ b/fs/intermezzo/journal_obdfs.c	Sun Feb 10 19:58:03 2002
@@ -10,7 +10,7 @@
 #include <linux/types.h>
 #include <linux/param.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff -Nru a/fs/intermezzo/journal_reiserfs.c b/fs/intermezzo/journal_reiserfs.c
--- a/fs/intermezzo/journal_reiserfs.c	Sun Feb 10 19:58:05 2002
+++ b/fs/intermezzo/journal_reiserfs.c	Sun Feb 10 19:58:05 2002
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/param.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff -Nru a/fs/intermezzo/journal_xfs.c b/fs/intermezzo/journal_xfs.c
--- a/fs/intermezzo/journal_xfs.c	Sun Feb 10 19:58:05 2002
+++ b/fs/intermezzo/journal_xfs.c	Sun Feb 10 19:58:05 2002
@@ -5,7 +5,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff -Nru a/fs/intermezzo/methods.c b/fs/intermezzo/methods.c
--- a/fs/intermezzo/methods.c	Sun Feb 10 19:58:05 2002
+++ b/fs/intermezzo/methods.c	Sun Feb 10 19:58:05 2002
@@ -20,7 +20,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/intermezzo/presto.c b/fs/intermezzo/presto.c
--- a/fs/intermezzo/presto.c	Sun Feb 10 19:58:04 2002
+++ b/fs/intermezzo/presto.c	Sun Feb 10 19:58:04 2002
@@ -10,7 +10,7 @@
  */
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
diff -Nru a/fs/intermezzo/psdev.c b/fs/intermezzo/psdev.c
--- a/fs/intermezzo/psdev.c	Sun Feb 10 19:58:05 2002
+++ b/fs/intermezzo/psdev.c	Sun Feb 10 19:58:05 2002
@@ -32,7 +32,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/lp.h>
 #include <linux/slab.h>
 #include <asm/ioctls.h>
diff -Nru a/fs/intermezzo/super.c b/fs/intermezzo/super.c
--- a/fs/intermezzo/super.c	Sun Feb 10 19:58:06 2002
+++ b/fs/intermezzo/super.c	Sun Feb 10 19:58:06 2002
@@ -20,7 +20,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/intermezzo/sysctl.c b/fs/intermezzo/sysctl.c
--- a/fs/intermezzo/sysctl.c	Sun Feb 10 19:58:04 2002
+++ b/fs/intermezzo/sysctl.c	Sun Feb 10 19:58:04 2002
@@ -5,7 +5,7 @@
 #define __NO_VERSION__
 #include <linux/config.h> /* for CONFIG_PROC_FS */
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 #include <linux/swapctl.h>
diff -Nru a/fs/intermezzo/upcall.c b/fs/intermezzo/upcall.c
--- a/fs/intermezzo/upcall.c	Sun Feb 10 19:58:06 2002
+++ b/fs/intermezzo/upcall.c	Sun Feb 10 19:58:06 2002
@@ -28,7 +28,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
diff -Nru a/fs/ioctl.c b/fs/ioctl.c
--- a/fs/ioctl.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ioctl.c	Sun Feb 10 19:58:05 2002
@@ -7,6 +7,7 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/file.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
diff -Nru a/fs/isofs/compress.c b/fs/isofs/compress.c
--- a/fs/isofs/compress.c	Sun Feb 10 19:58:04 2002
+++ b/fs/isofs/compress.c	Sun Feb 10 19:58:04 2002
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/iso_fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
diff -Nru a/fs/isofs/dir.c b/fs/isofs/dir.c
--- a/fs/isofs/dir.c	Sun Feb 10 19:58:05 2002
+++ b/fs/isofs/dir.c	Sun Feb 10 19:58:05 2002
@@ -18,7 +18,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/locks.h>
 #include <linux/config.h>
 
diff -Nru a/fs/isofs/inode.c b/fs/isofs/inode.c
--- a/fs/isofs/inode.c	Sun Feb 10 19:58:06 2002
+++ b/fs/isofs/inode.c	Sun Feb 10 19:58:06 2002
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/iso_fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
@@ -510,8 +510,7 @@
  * Note: a check_disk_change() has been done immediately prior
  * to this call, so we don't need to check again.
  */
-static struct super_block *isofs_read_super(struct super_block *s, void *data,
-					    int silent)
+static int isofs_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct buffer_head	      * bh = NULL, *pri_bh = NULL;
 	struct hs_primary_descriptor  * h_pri = NULL;
@@ -843,16 +842,16 @@
 	if (opt.check == 'r') table++;
 	s->s_root->d_op = &isofs_dentry_ops[table];
 
-	return s;
+	return 0;
 
 	/*
 	 * Display error messages and free resources.
 	 */
 out_bad_root:
-	printk(KERN_WARNING "isofs_read_super: root inode not initialized\n");
+	printk(KERN_WARNING "isofs_fill_super: root inode not initialized\n");
 	goto out_iput;
 out_no_root:
-	printk(KERN_WARNING "isofs_read_super: get root inode failed\n");
+	printk(KERN_WARNING "isofs_fill_super: get root inode failed\n");
 out_iput:
 	iput(inode);
 #ifdef CONFIG_JOLIET
@@ -861,7 +860,7 @@
 #endif
 	goto out_unlock;
 out_no_read:
-	printk(KERN_WARNING "isofs_read_super: "
+	printk(KERN_WARNING "isofs_fill_super: "
 		"bread failed, dev=%s, iso_blknum=%d, block=%d\n",
 		s->s_id, iso_blknum, block);
 	goto out_unlock;
@@ -885,7 +884,7 @@
 out_freebh:
 	brelse(bh);
 out_unlock:
-	return NULL;
+	return -EINVAL;
 }
 
 static int isofs_statfs (struct super_block *sb, struct statfs *buf)
@@ -1395,7 +1394,18 @@
 
 #endif
 
-static DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);
+static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
+}
+
+static struct file_system_type iso9660_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"iso9660",
+	get_sb:		isofs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_iso9660_fs(void)
 {
diff -Nru a/fs/isofs/namei.c b/fs/isofs/namei.c
--- a/fs/isofs/namei.c	Sun Feb 10 19:58:04 2002
+++ b/fs/isofs/namei.c	Sun Feb 10 19:58:04 2002
@@ -6,7 +6,7 @@
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/iso_fs.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -Nru a/fs/isofs/rock.c b/fs/isofs/rock.c
--- a/fs/isofs/rock.c	Sun Feb 10 19:58:03 2002
+++ b/fs/isofs/rock.c	Sun Feb 10 19:58:03 2002
@@ -7,7 +7,7 @@
  */
 
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/iso_fs.h>
 #include <linux/string.h>
 #include <linux/mm.h>
diff -Nru a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
--- a/fs/jbd/checkpoint.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jbd/checkpoint.c	Sun Feb 10 19:58:05 2002
@@ -17,7 +17,7 @@
  * reused.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
diff -Nru a/fs/jbd/commit.c b/fs/jbd/commit.c
--- a/fs/jbd/commit.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jbd/commit.c	Sun Feb 10 19:58:05 2002
@@ -13,7 +13,7 @@
  * part of the ext2fs journaling system.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c
--- a/fs/jbd/journal.c	Sun Feb 10 19:58:04 2002
+++ b/fs/jbd/journal.c	Sun Feb 10 19:58:04 2002
@@ -23,14 +23,13 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
diff -Nru a/fs/jbd/recovery.c b/fs/jbd/recovery.c
--- a/fs/jbd/recovery.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jbd/recovery.c	Sun Feb 10 19:58:05 2002
@@ -16,7 +16,7 @@
 #ifndef __KERNEL__
 #include "jfs_user.h"
 #else
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
diff -Nru a/fs/jbd/revoke.c b/fs/jbd/revoke.c
--- a/fs/jbd/revoke.c	Sun Feb 10 19:58:04 2002
+++ b/fs/jbd/revoke.c	Sun Feb 10 19:58:04 2002
@@ -60,7 +60,7 @@
 #ifndef __KERNEL__
 #include "jfs_user.h"
 #else
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c
--- a/fs/jbd/transaction.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jbd/transaction.c	Sun Feb 10 19:58:05 2002
@@ -17,7 +17,7 @@
  * filesystem).
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
--- a/fs/jffs/inode-v23.c	Sun Feb 10 19:58:04 2002
+++ b/fs/jffs/inode-v23.c	Sun Feb 10 19:58:04 2002
@@ -32,7 +32,7 @@
    dwmw2
 */
 #define __KERNEL_SYSCALLS__
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/unistd.h>
 
 #include <linux/module.h>
@@ -71,8 +71,7 @@
 kmem_cache_t     *fm_cache = NULL;
 
 /* Called by the VFS at mount time to initialize the whole file system.  */
-static struct super_block *
-jffs_read_super(struct super_block *sb, void *data, int silent)
+static int jffs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	kdev_t dev = sb->s_dev;
 	struct inode *root_inode;
@@ -84,7 +83,7 @@
 	if (major(dev) != MTD_BLOCK_MAJOR) {
 		printk(KERN_WARNING "JFFS: Trying to mount a "
 		       "non-mtd device.\n");
-		return 0;
+		return -EINVAL;
 	}
 
 	sb->s_blocksize = PAGE_CACHE_SIZE;
@@ -145,7 +144,7 @@
 
 	D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
 	       sb->s_id));
-	return sb;
+	return 0;
 
 jffs_sb_err3:
 	iput(root_inode);
@@ -154,7 +153,7 @@
 jffs_sb_err1:
 	printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
 	       sb->s_id);
-	return 0;
+	return -EINVAL;
 }
 
 
@@ -1730,8 +1729,18 @@
 	statfs:       jffs_statfs,
 };
 
+static struct super_block *jffs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super);
+}
 
-static DECLARE_FSTYPE_DEV(jffs_fs_type, "jffs", jffs_read_super);
+static struct file_system_type jffs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"jffs",
+	get_sb:		jffs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init
 init_jffs_fs(void)
diff -Nru a/fs/jffs/intrep.c b/fs/jffs/intrep.c
--- a/fs/jffs/intrep.c	Sun Feb 10 19:58:04 2002
+++ b/fs/jffs/intrep.c	Sun Feb 10 19:58:04 2002
@@ -68,7 +68,7 @@
 #include <asm/byteorder.h>
 #include <linux/version.h>
 #include <linux/smp_lock.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/ctype.h>
 
 #include "intrep.h"
diff -Nru a/fs/jffs/jffs_proc.c b/fs/jffs/jffs_proc.c
--- a/fs/jffs/jffs_proc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jffs/jffs_proc.c	Sun Feb 10 19:58:05 2002
@@ -26,7 +26,7 @@
 #include <linux/jffs.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/types.h>
 #include "jffs_fm.h"
 #include "jffs_proc.h"
diff -Nru a/fs/jffs2/background.c b/fs/jffs2/background.c
--- a/fs/jffs2/background.c	Sun Feb 10 19:58:03 2002
+++ b/fs/jffs2/background.c	Sun Feb 10 19:58:03 2002
@@ -38,7 +38,7 @@
 #define __KERNEL_SYSCALLS__
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/unistd.h>
 #include <linux/jffs2.h>
 #include <linux/mtd/mtd.h>
diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c
--- a/fs/jffs2/dir.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jffs2/dir.c	Sun Feb 10 19:58:05 2002
@@ -42,7 +42,7 @@
 #include <linux/jffs2.h>
 #include <linux/jffs2_fs_i.h>
 #include <linux/jffs2_fs_sb.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include "nodelist.h"
 
 static int jffs2_readdir (struct file *, void *, filldir_t);
diff -Nru a/fs/jffs2/gc.c b/fs/jffs2/gc.c
--- a/fs/jffs2/gc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jffs2/gc.c	Sun Feb 10 19:58:05 2002
@@ -39,7 +39,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/slab.h>
 #include <linux/jffs2.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/interrupt.h>
 #include <linux/pagemap.h>
 #include <linux/crc32.h>
diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c
--- a/fs/jffs2/super.c	Sun Feb 10 19:58:05 2002
+++ b/fs/jffs2/super.c	Sun Feb 10 19:58:05 2002
@@ -195,7 +195,7 @@
 	return 0;
 }
 
-static struct super_block *jffs2_read_super(struct super_block *sb, void *data, int silent)
+static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct jffs2_sb_info *c;
 	struct inode *root_i;
@@ -206,7 +206,7 @@
 	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;
+		return -EINVAL;
 	}
 
 	c = JFFS2_SB_INFO(sb);
@@ -215,7 +215,7 @@
 	c->mtd = get_mtd_device(NULL, minor(sb->s_dev));
 	if (!c->mtd) {
 		D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev)));
-		return NULL;
+		return -EINVAL;
 	}
 	c->sector_size = c->mtd->erasesize;
 	c->free_size = c->flash_size = c->mtd->size;
@@ -275,7 +275,7 @@
 	sb->s_magic = JFFS2_SUPER_MAGIC;
 	if (!(sb->s_flags & MS_RDONLY))
 		jffs2_start_garbage_collect_thread(c);
-	return sb;
+	return 0;
 
  out_root_i:
 	iput(root_i);
@@ -285,7 +285,7 @@
 	kfree(c->blocks);
  out_mtd:
 	put_mtd_device(c->mtd);
-	return NULL;
+	return -EINVAL;
 }
 
 void jffs2_put_super (struct super_block *sb)
@@ -340,8 +340,18 @@
 	jffs2_mark_erased_blocks(c);
 }
 
+static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, jffs2_fill_super);
+}
 
-static DECLARE_FSTYPE_DEV(jffs2_fs_type, "jffs2", jffs2_read_super);
+static struct file_system_type jffs2_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"jffs2",
+	get_sb:		jffs2_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_jffs2_fs(void)
 {
diff -Nru a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
--- a/fs/lockd/clntlock.c	Sun Feb 10 19:58:05 2002
+++ b/fs/lockd/clntlock.c	Sun Feb 10 19:58:05 2002
@@ -10,7 +10,7 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/nfs_fs.h>
 #include <linux/unistd.h>
 #include <linux/sunrpc/clnt.h>
diff -Nru a/fs/lockd/lockd_syms.c b/fs/lockd/lockd_syms.c
--- a/fs/lockd/lockd_syms.c	Sun Feb 10 19:58:03 2002
+++ b/fs/lockd/lockd_syms.c	Sun Feb 10 19:58:03 2002
@@ -16,7 +16,7 @@
 
 #include <linux/types.h>
 #include <linux/socket.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/uio.h>
 #include <linux/unistd.h>
 
diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c
--- a/fs/lockd/svc.c	Sun Feb 10 19:58:04 2002
+++ b/fs/lockd/svc.c	Sun Feb 10 19:58:04 2002
@@ -304,7 +304,7 @@
 	 * Wait for the lockd process to exit, but since we're holding
 	 * the lockd semaphore, we can't wait around forever ...
 	 */
-	current->work.sigpending = 0;
+	clear_thread_flag(TIF_SIGPENDING);
 	interruptible_sleep_on_timeout(&lockd_exit, HZ);
 	if (nlmsvc_pid) {
 		printk(KERN_WARNING 
diff -Nru a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
--- a/fs/lockd/svc4proc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/lockd/svc4proc.c	Sun Feb 10 19:58:05 2002
@@ -8,7 +8,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/svc.h>
diff -Nru a/fs/lockd/svclock.c b/fs/lockd/svclock.c
--- a/fs/lockd/svclock.c	Sun Feb 10 19:58:05 2002
+++ b/fs/lockd/svclock.c	Sun Feb 10 19:58:05 2002
@@ -306,9 +306,8 @@
 	struct nlm_block	*block;
 	int			error;
 
-	dprintk("lockd: nlmsvc_lock(%02x:%02x/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
-				major(file->f_file.f_dentry->d_inode->i_dev),
-				minor(file->f_file.f_dentry->d_inode->i_dev),
+	dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
+				file->f_file.f_dentry->d_inode->i_sb->s_id,
 				file->f_file.f_dentry->d_inode->i_ino,
 				lock->fl.fl_type, lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
@@ -386,9 +385,8 @@
 {
 	struct file_lock	*fl;
 
-	dprintk("lockd: nlmsvc_testlock(%02x:%02x/%ld, ty=%d, %Ld-%Ld)\n",
-				major(file->f_file.f_dentry->d_inode->i_dev),
-				minor(file->f_file.f_dentry->d_inode->i_dev),
+	dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
+				file->f_file.f_dentry->d_inode->i_sb->s_id,
 				file->f_file.f_dentry->d_inode->i_ino,
 				lock->fl.fl_type,
 				(long long)lock->fl.fl_start,
@@ -419,9 +417,8 @@
 {
 	int	error;
 
-	dprintk("lockd: nlmsvc_unlock(%02x:%02x/%ld, pi=%d, %Ld-%Ld)\n",
-				major(file->f_file.f_dentry->d_inode->i_dev),
-				minor(file->f_file.f_dentry->d_inode->i_dev),
+	dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
+				file->f_file.f_dentry->d_inode->i_sb->s_id,
 				file->f_file.f_dentry->d_inode->i_ino,
 				lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
@@ -448,9 +445,8 @@
 {
 	struct nlm_block	*block;
 
-	dprintk("lockd: nlmsvc_cancel(%02x:%02x/%ld, pi=%d, %Ld-%Ld)\n",
-				major(file->f_file.f_dentry->d_inode->i_dev),
-				minor(file->f_file.f_dentry->d_inode->i_dev),
+	dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
+				file->f_file.f_dentry->d_inode->i_sb->s_id,
 				file->f_file.f_dentry->d_inode->i_ino,
 				lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
diff -Nru a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
--- a/fs/lockd/svcproc.c	Sun Feb 10 19:58:04 2002
+++ b/fs/lockd/svcproc.c	Sun Feb 10 19:58:04 2002
@@ -9,7 +9,7 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/svc.h>
diff -Nru a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
--- a/fs/lockd/svcshare.c	Sun Feb 10 19:58:04 2002
+++ b/fs/lockd/svcshare.c	Sun Feb 10 19:58:04 2002
@@ -6,7 +6,7 @@
  * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/unistd.h>
 #include <linux/string.h>
 #include <linux/slab.h>
diff -Nru a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
--- a/fs/lockd/svcsubs.c	Sun Feb 10 19:58:04 2002
+++ b/fs/lockd/svcsubs.c	Sun Feb 10 19:58:04 2002
@@ -9,7 +9,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/in.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
@@ -128,7 +128,7 @@
 	struct nlm_file	**fp, *f;
 
 	dprintk("lockd: closing file %s/%ld\n",
-		kdevname(inode->i_dev), inode->i_ino);
+		inode->i_sb->s_id, inode->i_ino);
 	fp = nlm_files + file->f_hash;
 	while ((f = *fp) != NULL) {
 		if (f == file) {
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Sun Feb 10 19:58:05 2002
+++ b/fs/locks.c	Sun Feb 10 19:58:05 2002
@@ -120,7 +120,8 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/capability.h>
-#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/fs.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
diff -Nru a/fs/minix/inode.c b/fs/minix/inode.c
--- a/fs/minix/inode.c	Sun Feb 10 19:58:03 2002
+++ b/fs/minix/inode.c	Sun Feb 10 19:58:03 2002
@@ -163,8 +163,7 @@
 	return 0;
 }
 
-static struct super_block *minix_read_super(struct super_block *s, void *data,
-				     int silent)
+static int minix_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct buffer_head *bh;
 	struct buffer_head **map;
@@ -273,7 +272,7 @@
  	else if (sbi->s_mount_state & MINIX_ERROR_FS)
 		printk ("MINIX-fs: mounting file system with errors, "
 			"running fsck is recommended.\n");
-	return s;
+	return 0;
 
 out_iput:
 	iput(root_inode);
@@ -314,7 +313,7 @@
 out_bad_sb:
 	printk("MINIX-fs: unable to read superblock\n");
  out:
-	return NULL;
+	return -EINVAL;
 }
 
 static int minix_statfs(struct super_block *sb, struct statfs *buf)
@@ -558,7 +557,18 @@
 		V2_minix_truncate(inode);
 }
 
-static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
+static struct super_block *minix_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super);
+}
+
+static struct file_system_type minix_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"minix",
+	get_sb:		minix_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_minix_fs(void)
 {
diff -Nru a/fs/msdos/msdosfs_syms.c b/fs/msdos/msdosfs_syms.c
--- a/fs/msdos/msdosfs_syms.c	Sun Feb 10 19:58:04 2002
+++ b/fs/msdos/msdosfs_syms.c	Sun Feb 10 19:58:04 2002
@@ -25,7 +25,18 @@
 EXPORT_SYMBOL(msdos_unlink);
 EXPORT_SYMBOL(msdos_put_super);
 
-static DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
+static struct super_block *msdos_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
+}
+
+static struct file_system_type msdos_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"msdos",
+	get_sb:		msdos_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_msdos_fs(void)
 {
diff -Nru a/fs/msdos/namei.c b/fs/msdos/namei.c
--- a/fs/msdos/namei.c	Sun Feb 10 19:58:06 2002
+++ b/fs/msdos/namei.c	Sun Feb 10 19:58:06 2002
@@ -10,7 +10,7 @@
 #define __NO_VERSION__
 #include <linux/module.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/msdos_fs.h>
 
 #define MSDOS_DEBUG 0
@@ -579,21 +579,21 @@
 	setattr:	fat_notify_change,
 };
 
-struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
+int msdos_fill_super(struct super_block *sb,void *data, int silent)
 {
 	struct super_block *res;
 
 	MSDOS_SB(sb)->options.isvfat = 0;
 	res = fat_read_super(sb, data, silent, &msdos_dir_inode_operations);
 	if (IS_ERR(res))
-		return NULL;
+		return PTR_ERR(res);
 	if (res == NULL) {
 		if (!silent)
 			printk(KERN_INFO "VFS: Can't find a valid"
 			       " MSDOS filesystem on dev %s.\n", sb->s_id);
-		return NULL;
+		return -EINVAL;
 	}
 
 	sb->s_root->d_op = &msdos_dentry_operations;
-	return res;
+	return 0;
 }
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	Sun Feb 10 19:58:04 2002
+++ b/fs/namespace.c	Sun Feb 10 19:58:04 2002
@@ -1048,15 +1048,9 @@
 	if (!mnt_cache)
 		panic("Cannot create vfsmount cache");
 
-	mempages >>= (16 - PAGE_SHIFT);
-	mempages *= sizeof(struct list_head);
-	for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
-		;
-
-	do {
-		mount_hashtable = (struct list_head *)
-			__get_free_pages(GFP_ATOMIC, order);
-	} while (mount_hashtable == NULL && --order >= 0);
+	order = 0; 
+	mount_hashtable = (struct list_head *)
+		__get_free_pages(GFP_ATOMIC, order);
 
 	if (!mount_hashtable)
 		panic("Failed to allocate mount hash table\n");
diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
--- a/fs/ncpfs/dir.c	Sun Feb 10 19:58:03 2002
+++ b/fs/ncpfs/dir.c	Sun Feb 10 19:58:03 2002
@@ -11,7 +11,7 @@
 
 #include <linux/config.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
diff -Nru a/fs/ncpfs/file.c b/fs/ncpfs/file.c
--- a/fs/ncpfs/file.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ncpfs/file.c	Sun Feb 10 19:58:04 2002
@@ -9,7 +9,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -18,6 +18,7 @@
 #include <linux/locks.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
 
 #include <linux/ncp_fs.h>
 #include "ncplib_kernel.h"
@@ -281,7 +282,7 @@
 
 struct file_operations ncp_file_operations =
 {
-	llseek:		generic_file_llseek,
+	llseek:		remote_llseek,
 	read:		ncp_file_read,
 	write:		ncp_file_write,
 	ioctl:		ncp_ioctl,
diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
--- a/fs/ncpfs/inode.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ncpfs/inode.c	Sun Feb 10 19:58:06 2002
@@ -15,7 +15,7 @@
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -300,8 +300,7 @@
 	clear_inode(inode);
 }
 
-struct super_block *
-ncp_read_super(struct super_block *sb, void *raw_data, int silent)
+static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 {
 	struct ncp_mount_data_kernel data;
 	struct ncp_server *server;
@@ -365,7 +364,7 @@
 	sock_inode = ncp_filp->f_dentry->d_inode;
 	if (!S_ISSOCK(sock_inode->i_mode))
 		goto out_bad_file2;
-	sock = &sock_inode->u.socket_i;
+	sock = SOCKET_I(sock_inode);
 	if (!sock)
 		goto out_bad_file2;
 		
@@ -434,7 +433,7 @@
 	ncp_unlock_server(server);
 	if (error < 0)
 		goto out_no_connect;
-	DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
+	DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
 
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
 	if (ncp_negotiate_size_and_options(server, default_bufsize,
@@ -486,31 +485,31 @@
         root_inode = ncp_iget(sb, &finfo);
         if (!root_inode)
 		goto out_no_root;
-	DPRINTK("ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
+	DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
 	sb->s_root = d_alloc_root(root_inode);
         if (!sb->s_root)
 		goto out_no_root;
 	sb->s_root->d_op = &ncp_dentry_operations;
-	return sb;
+	return 0;
 
 out_no_root:
-	printk(KERN_ERR "ncp_read_super: get root inode failed\n");
+	printk(KERN_ERR "ncp_fill_super: get root inode failed\n");
 	iput(root_inode);
 	goto out_disconnect;
 out_no_bufsize:
-	printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
+	printk(KERN_ERR "ncp_fill_super: could not get bufsize\n");
 out_disconnect:
 	ncp_lock_server(server);
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
 	goto out_free_packet;
 out_no_connect:
-	printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
+	printk(KERN_ERR "ncp_fill_super: Failed connection, error=%d\n", error);
 out_free_packet:
 	vfree(server->packet);
 	goto out_free_server;
 out_no_packet:
-	printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
+	printk(KERN_ERR "ncp_fill_super: could not alloc packet\n");
 out_free_server:
 #ifdef CONFIG_NCPFS_NLS
 	unload_nls(server->nls_io);
@@ -527,16 +526,16 @@
 out_bad_file2:
 	fput(ncp_filp);
 out_bad_file:
-	printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
+	printk(KERN_ERR "ncp_fill_super: invalid ncp socket\n");
 	goto out;
 out_bad_mount:
-	printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
+	printk(KERN_INFO "ncp_fill_super: kernel requires mount version %d\n",
 		NCP_MOUNT_VERSION);
 	goto out;
 out_no_data:
-	printk(KERN_ERR "ncp_read_super: missing data argument\n");
+	printk(KERN_ERR "ncp_fill_super: missing data argument\n");
 out:
-	return NULL;
+	return -EINVAL;
 }
 
 static void ncp_put_super(struct super_block *sb)
@@ -750,7 +749,17 @@
 int ncp_current_malloced;
 #endif
 
-static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
+static struct super_block *ncp_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, ncp_fill_super);
+}
+
+static struct file_system_type ncp_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"ncpfs",
+	get_sb:		ncp_get_sb,
+};
 
 static int __init init_ncp_fs(void)
 {
diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
--- a/fs/ncpfs/ioctl.c	Sun Feb 10 19:58:03 2002
+++ b/fs/ncpfs/ioctl.c	Sun Feb 10 19:58:03 2002
@@ -13,7 +13,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/highuid.h>
 #include <linux/vmalloc.h>
diff -Nru a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
--- a/fs/ncpfs/mmap.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ncpfs/mmap.c	Sun Feb 10 19:58:04 2002
@@ -7,7 +7,7 @@
  */
 
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/shm.h>
diff -Nru a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
--- a/fs/ncpfs/sock.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ncpfs/sock.c	Sun Feb 10 19:58:05 2002
@@ -10,7 +10,7 @@
 
 #include <linux/config.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/socket.h>
 #include <linux/fcntl.h>
@@ -101,7 +101,7 @@
 	struct ncp_reply_header reply;
 
 	file = server->ncp_filp;
-	sock = &file->f_dentry->d_inode->u.socket_i;
+	sock = SOCKET_I(file->f_dentry->d_inode);
 
 	init_timeout = server->m.time_out;
 	max_timeout = NCP_MAX_RPC_TIMEOUT;
@@ -269,7 +269,7 @@
 	int result = 0;
 	
 	file = server->ncp_filp;
-	sock = &file->f_dentry->d_inode->u.socket_i;
+	sock = SOCKET_I(file->f_dentry->d_inode);
 	
 	dataread = 0;
 
@@ -348,7 +348,7 @@
 	*((struct ncp_request_header *) (server->packet));
 
 	file = server->ncp_filp;
-	sock = &file->f_dentry->d_inode->u.socket_i;
+	sock = SOCKET_I(file->f_dentry->d_inode);
 	
 	ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC);
 	ncptcp_xmit_hdr[1] = htonl(size + 16);
@@ -444,7 +444,7 @@
 	}
 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
 	file = server->ncp_filp;
-	sock = &file->f_dentry->d_inode->u.socket_i;
+	sock = SOCKET_I(file->f_dentry->d_inode);
 	/* N.B. this isn't needed ... check socket type? */
 	if (!sock) {
 		printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n");
diff -Nru a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
--- a/fs/ncpfs/symlink.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ncpfs/symlink.c	Sun Feb 10 19:58:06 2002
@@ -25,7 +25,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ncp_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/stat.h>
 #include "ncplib_kernel.h"
diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c
--- a/fs/nfs/dir.c	Sun Feb 10 19:58:06 2002
+++ b/fs/nfs/dir.c	Sun Feb 10 19:58:06 2002
@@ -17,7 +17,7 @@
  *  6 Jun 1999	Cache readdir lookups in the page cache. -DaveM
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
@@ -402,6 +402,21 @@
 }
 
 /*
+ * A check for whether or not the parent directory has changed.
+ * In the case it has, we assume that the dentries are untrustworthy
+ * and may need to be looked up again.
+ */
+static inline
+int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
+{
+	if (IS_ROOT(dentry))
+		return 1;
+	if (nfs_revalidate_inode(NFS_SERVER(dir), dir))
+		return 0;
+	return time_after(dentry->d_time, NFS_MTIME_UPDATE(dir));
+}
+
+/*
  * Whenever an NFS operation succeeds, we know that the dentry
  * is valid, so we update the revalidation timestamp.
  */
@@ -410,48 +425,31 @@
 	dentry->d_time = jiffies;
 }
 
-static inline int nfs_dentry_force_reval(struct dentry *dentry, int flags)
+static inline
+int nfs_lookup_verify_inode(struct inode *inode, int flags)
 {
-	struct inode *inode = dentry->d_inode;
-	unsigned long timeout = NFS_ATTRTIMEO(inode);
-
+	struct nfs_server *server = NFS_SERVER(inode);
 	/*
-	 * If it's the last lookup in a series, we use a stricter
-	 * cache consistency check by looking at the parent mtime.
-	 *
-	 * If it's been modified in the last hour, be really strict.
-	 * (This still means that we can avoid doing unnecessary
-	 * work on directories like /usr/share/bin etc which basically
-	 * never change).
+	 * If we're interested in close-to-open cache consistency,
+	 * then we revalidate the inode upon lookup.
 	 */
-	if (!(flags & LOOKUP_CONTINUE)) {
-		long diff = CURRENT_TIME - dentry->d_parent->d_inode->i_mtime;
-
-		if (diff < 15*60)
-			timeout = 0;
-	}
-	
-	return time_after(jiffies,dentry->d_time + timeout);
+	if (!(server->flags & NFS_MOUNT_NOCTO) && !(flags & LOOKUP_CONTINUE))
+		NFS_CACHEINV(inode);
+	return nfs_revalidate_inode(server, inode);
 }
 
 /*
  * We judge how long we want to trust negative
  * dentries by looking at the parent inode mtime.
  *
- * If mtime is close to present time, we revalidate
- * more often.
+ * If parent mtime has changed, we revalidate, else we wait for a
+ * period corresponding to the parent's attribute cache timeout value.
  */
-#define NFS_REVALIDATE_NEGATIVE (1 * HZ)
-static inline int nfs_neg_need_reval(struct dentry *dentry)
+static inline int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry)
 {
-	struct inode *dir = dentry->d_parent->d_inode;
-	unsigned long timeout = NFS_ATTRTIMEO(dir);
-	long diff = CURRENT_TIME - dir->i_mtime;
-
-	if (diff < 5*60 && timeout > NFS_REVALIDATE_NEGATIVE)
-		timeout = NFS_REVALIDATE_NEGATIVE;
-
-	return time_after(jiffies, dentry->d_time + timeout);
+	if (!nfs_check_verifier(dir, dentry))
+		return 1;
+	return time_after(jiffies, dentry->d_time + NFS_ATTRTIMEO(dir));
 }
 
 /*
@@ -462,9 +460,8 @@
  * NOTE! The hit can be a negative hit too, don't assume
  * we have an inode!
  *
- * If the dentry is older than the revalidation interval, 
- * we do a new lookup and verify that the dentry is still
- * correct.
+ * If the parent directory is seen to have changed, we throw out the
+ * cached dentry and do a new lookup.
  */
 static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
 {
@@ -477,13 +474,9 @@
 	lock_kernel();
 	dir = dentry->d_parent->d_inode;
 	inode = dentry->d_inode;
-	/*
-	 * If we don't have an inode, let's look at the parent
-	 * directory mtime to get a hint about how often we
-	 * should validate things..
-	 */
+
 	if (!inode) {
-		if (nfs_neg_need_reval(dentry))
+		if (nfs_neg_need_reval(dir, dentry))
 			goto out_bad;
 		goto out_valid;
 	}
@@ -494,48 +487,39 @@
 		goto out_bad;
 	}
 
-	if (!nfs_dentry_force_reval(dentry, flags))
+	/* Force a full look up iff the parent directory has changed */
+	if (nfs_check_verifier(dir, dentry)) {
+		if (nfs_lookup_verify_inode(inode, flags))
+			goto out_bad;
 		goto out_valid;
-
-	if (IS_ROOT(dentry)) {
-		__nfs_revalidate_inode(NFS_SERVER(inode), inode);
-		goto out_valid_renew;
 	}
 
-	/*
-	 * Do a new lookup and check the dentry attributes.
-	 */
+	if (NFS_STALE(inode))
+		goto out_bad;
+
 	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
 	if (error)
 		goto out_bad;
-
-	/* Inode number matches? */
-	if (!(fattr.valid & NFS_ATTR_FATTR) ||
-	    NFS_FSID(inode) != fattr.fsid ||
-	    NFS_FILEID(inode) != fattr.fileid)
+	if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
 		goto out_bad;
-
-	/* Ok, remember that we successfully checked it.. */
-	nfs_refresh_inode(inode, &fattr);
-
-	if (nfs_inode_is_stale(inode, &fhandle, &fattr))
+	if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
 		goto out_bad;
 
- out_valid_renew:
 	nfs_renew_times(dentry);
-out_valid:
+ out_valid:
 	unlock_kernel();
 	return 1;
-out_bad:
-	shrink_dcache_parent(dentry);
-	/* If we have submounts, don't unhash ! */
-	if (have_submounts(dentry))
-		goto out_valid;
-	d_drop(dentry);
-	/* Purge readdir caches. */
-	nfs_zap_caches(dir);
-	if (inode && S_ISDIR(inode->i_mode))
+ out_bad:
+	NFS_CACHEINV(dir);
+	if (inode && S_ISDIR(inode->i_mode)) {
+		/* Purge readdir caches. */
 		nfs_zap_caches(inode);
+		/* If we have submounts, don't unhash ! */
+		if (have_submounts(dentry))
+			goto out_valid;
+		shrink_dcache_parent(dentry);
+	}
+	d_drop(dentry);
 	unlock_kernel();
 	return 0;
 }
@@ -565,6 +549,7 @@
 {
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 		lock_kernel();
+		inode->i_nlink--;
 		nfs_complete_unlink(dentry);
 		unlock_kernel();
 	}
@@ -604,9 +589,9 @@
 		if (inode) {
 	    no_entry:
 			d_add(dentry, inode);
-			nfs_renew_times(dentry);
 			error = 0;
 		}
+		nfs_renew_times(dentry);
 	}
 out:
 	return ERR_PTR(error);
diff -Nru a/fs/nfs/file.c b/fs/nfs/file.c
--- a/fs/nfs/file.c	Sun Feb 10 19:58:04 2002
+++ b/fs/nfs/file.c	Sun Feb 10 19:58:04 2002
@@ -16,7 +16,7 @@
  *  nfs regular file handling functions
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -41,7 +41,7 @@
 static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
 
 struct file_operations nfs_file_operations = {
-	llseek:		generic_file_llseek,
+	llseek:		remote_llseek,
 	read:		nfs_file_read,
 	write:		nfs_file_write,
 	mmap:		nfs_file_mmap,
diff -Nru a/fs/nfs/flushd.c b/fs/nfs/flushd.c
--- a/fs/nfs/flushd.c	Sun Feb 10 19:58:04 2002
+++ b/fs/nfs/flushd.c	Sun Feb 10 19:58:04 2002
@@ -28,7 +28,7 @@
 #include <linux/pagemap.h>
 #include <linux/file.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/clnt.h>
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfs/inode.c	Sun Feb 10 19:58:05 2002
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -245,8 +245,7 @@
  * and the root file handle obtained from the server's mount
  * daemon. We stash these away in the private superblock fields.
  */
-struct super_block *
-nfs_read_super(struct super_block *sb, void *raw_data, int silent)
+int nfs_fill_super(struct super_block *sb, void *raw_data, int silent)
 {
 	struct nfs_mount_data	*data = (struct nfs_mount_data *) raw_data;
 	struct nfs_server	*server;
@@ -455,6 +454,8 @@
                 server->namelen = maxlen;
 
 	sb->s_maxbytes = fsinfo.maxfilesize;
+	if (sb->s_maxbytes > MAX_LFS_FILESIZE) 
+		sb->s_maxbytes = MAX_LFS_FILESIZE; 
 
 	/* Fire up the writeback cache */
 	if (nfs_reqlist_alloc(server) < 0) {
@@ -467,7 +468,7 @@
 	/* Check whether to start the lockd process */
 	if (!(server->flags & NFS_MOUNT_NONLM))
 		lockd_up();
-	return sb;
+	return 0;
 
 	/* Yargs. It didn't work out. */
  failure_kill_reqlist:
@@ -506,7 +507,7 @@
 	printk("nfs_read_super: missing data argument\n");
 
 out_fail:
-	return NULL;
+	return -EINVAL;
 }
 
 static int
@@ -630,39 +631,18 @@
 	struct nfs_fh		*fh = desc->fh;
 	struct nfs_fattr	*fattr = desc->fattr;
 
-	if (NFS_FSID(inode) != fattr->fsid)
-		return 0;
 	if (NFS_FILEID(inode) != fattr->fileid)
 		return 0;
 	if (memcmp(NFS_FH(inode), fh, sizeof(struct nfs_fh)) != 0)
 		return 0;
+	if (is_bad_inode(inode))
+		return 0;
 	/* Force an attribute cache update if inode->i_count == 0 */
 	if (!atomic_read(&inode->i_count))
 		NFS_CACHEINV(inode);
 	return 1;
 }
 
-int
-nfs_inode_is_stale(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr)
-{
-	/* Empty inodes are not stale */
-	if (!inode->i_mode)
-		return 0;
-
-	if ((fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
-		return 1;
-
-	if (is_bad_inode(inode) || NFS_STALE(inode))
-		return 1;
-
-	/* Has the filehandle changed? If so is the old one stale? */
-	if (memcmp(NFS_FH(inode), fh, sizeof(struct nfs_fh)) != 0 &&
-	    __nfs_revalidate_inode(NFS_SERVER(inode),inode) == -ESTALE)
-		return 1;
-
-	return 0;
-}
-
 /*
  * This is our own version of iget that looks up inodes by file handle
  * instead of inode number.  We use this technique instead of using
@@ -713,7 +693,6 @@
 		/* We can't support UPDATE_ATIME(), since the server will reset it */
 		NFS_FLAGS(inode) &= ~NFS_INO_NEW;
 		NFS_FILEID(inode) = fattr->fileid;
-		NFS_FSID(inode) = fattr->fsid;
 		memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh));
 		inode->i_flags |= S_NOATIME;
 		inode->i_mode = fattr->mode;
@@ -787,7 +766,7 @@
 	/*
 	 * Make sure the inode is up-to-date.
 	 */
-	error = nfs_revalidate(dentry);
+	error = nfs_revalidate_inode(NFS_SERVER(inode),inode);
 	if (error) {
 #ifdef NFS_PARANOIA
 printk("nfs_notify_change: revalidate failed, error=%d\n", error);
@@ -1025,12 +1004,11 @@
 			inode->i_sb->s_id, inode->i_ino,
 			atomic_read(&inode->i_count), fattr->valid);
 
-	if (NFS_FSID(inode) != fattr->fsid ||
-	    NFS_FILEID(inode) != fattr->fileid) {
+	if (NFS_FILEID(inode) != fattr->fileid) {
 		printk(KERN_ERR "nfs_refresh_inode: inode number mismatch\n"
-		       "expected (0x%Lx/0x%Lx), got (0x%Lx/0x%Lx)\n",
-		       (long long)NFS_FSID(inode), (long long)NFS_FILEID(inode),
-		       (long long)fattr->fsid, (long long)fattr->fileid);
+		       "expected (%s/0x%Lx), got (%s/0x%Lx)\n",
+		       inode->i_sb->s_id, (long long)NFS_FILEID(inode),
+		       inode->i_sb->s_id, (long long)fattr->fileid);
 		goto out_err;
 	}
 
@@ -1100,8 +1078,11 @@
 
 	inode->i_atime = new_atime;
 
-	NFS_CACHE_MTIME(inode) = new_mtime;
-	inode->i_mtime = nfs_time_to_secs(new_mtime);
+	if (NFS_CACHE_MTIME(inode) != new_mtime) {
+		NFS_MTIME_UPDATE(inode) = jiffies;
+		NFS_CACHE_MTIME(inode) = new_mtime;
+		inode->i_mtime = nfs_time_to_secs(new_mtime);
+	}
 
 	NFS_CACHE_ISIZE(inode) = new_size;
 	inode->i_size = new_isize;
@@ -1157,7 +1138,25 @@
 /*
  * File system information
  */
-static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, FS_ODD_RENAME);
+
+/*
+ *  Right now we are using get_sb_nodev, but we ought to switch to
+ *  get_anon_super() with appropriate comparison function.  The only
+ *  question being, when two NFS mounts are the same?  Identical IP
+ *  of server + identical root fhandle?  Trond?
+ */
+static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, nfs_fill_super);
+}
+
+static struct file_system_type nfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"nfs",
+	get_sb:		nfs_get_sb,
+	fs_flags:	FS_ODD_RENAME,
+};
 
 extern int nfs_init_nfspagecache(void);
 extern void nfs_destroy_nfspagecache(void);
@@ -1175,10 +1174,6 @@
 	if (!nfsi)
 		return NULL;
 	nfsi->flags = NFS_INO_NEW;
-	/* do we need the next 4 lines? */
-	nfsi->hash_next = NULL;
-	nfsi->hash_prev = NULL;
-	nfsi->nextscan = 0;
 	nfsi->mm_cred = NULL;
 	return &nfsi->vfs_inode;
 }
diff -Nru a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
--- a/fs/nfs/nfs2xdr.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfs/nfs2xdr.c	Sun Feb 10 19:58:05 2002
@@ -10,7 +10,7 @@
  */
 
 #include <linux/param.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/utsname.h>
diff -Nru a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
--- a/fs/nfs/nfs3proc.c	Sun Feb 10 19:58:06 2002
+++ b/fs/nfs/nfs3proc.c	Sun Feb 10 19:58:06 2002
@@ -80,7 +80,8 @@
 		status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
 			 fhandle, fattr, 0);
 	dprintk("NFS reply lookup: %d\n", status);
-	nfs_refresh_inode(dir, &dir_attr);
+	if (status >= 0)
+		status = nfs_refresh_inode(dir, &dir_attr);
 	return status;
 }
 
diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
--- a/fs/nfs/nfs3xdr.c	Sun Feb 10 19:58:06 2002
+++ b/fs/nfs/nfs3xdr.c	Sun Feb 10 19:58:06 2002
@@ -7,7 +7,7 @@
  */
 
 #include <linux/param.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/utsname.h>
diff -Nru a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
--- a/fs/nfs/nfsroot.c	Sun Feb 10 19:58:04 2002
+++ b/fs/nfs/nfsroot.c	Sun Feb 10 19:58:04 2002
@@ -70,7 +70,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/sunrpc/clnt.h>
@@ -453,7 +453,7 @@
 
 /*
  *  Get the NFS port numbers and file handle, and return the prepared 'data'
- *  argument for ->read_super() if everything went OK. Return NULL otherwise.
+ *  argument for mount() if everything went OK. Return NULL otherwise.
  */
 void * __init nfs_root_data(void)
 {
diff -Nru a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
--- a/fs/nfs/pagelist.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfs/pagelist.c	Sun Feb 10 19:58:05 2002
@@ -53,7 +53,7 @@
 
 /**
  * nfs_create_request - Create an NFS read/write request.
- * @file: file that owns this request
+ * @cred: RPC credential to use
  * @inode: inode to which the request is attached
  * @page: page to write
  * @offset: starting offset within the page for the write
@@ -66,7 +66,7 @@
  * User should ensure it is safe to sleep in this function.
  */
 struct nfs_page *
-nfs_create_request(struct file *file, struct inode *inode,
+nfs_create_request(struct rpc_cred *cred, struct inode *inode,
 		   struct page *page,
 		   unsigned int offset, unsigned int count)
 {
@@ -107,34 +107,49 @@
 	req->wb_offset  = offset;
 	req->wb_bytes   = count;
 
-	/* If we have a struct file, use its cached credentials */
-	if (file) {
-		req->wb_file    = file;
-		get_file(file);
-		req->wb_cred	= nfs_file_cred(file);
-	}
+	if (cred)
+		req->wb_cred = get_rpccred(cred);
 	req->wb_inode   = inode;
 	req->wb_count   = 1;
 
 	return req;
 }
 
+/**
+ * nfs_clear_request - Free up all resources allocated to the request
+ * @req:
+ *
+ * Release all resources associated with a write request after it
+ * has completed.
+ */
+void nfs_clear_request(struct nfs_page *req)
+{
+	/* Release struct file or cached credential */
+	if (req->wb_file) {
+		fput(req->wb_file);
+		req->wb_file = NULL;
+	}
+	if (req->wb_cred) {
+		put_rpccred(req->wb_cred);
+		req->wb_cred = NULL;
+	}
+	if (req->wb_page) {
+		page_cache_release(req->wb_page);
+		req->wb_page = NULL;
+		atomic_dec(&NFS_REQUESTLIST(req->wb_inode)->nr_requests);
+	}
+}
+
 
 /**
  * nfs_release_request - Release the count on an NFS read/write request
  * @req: request to release
  *
- * Release all resources associated with a write request after it
- * has been committed to stable storage
- *
  * Note: Should never be called with the spinlock held!
  */
 void
 nfs_release_request(struct nfs_page *req)
 {
-	struct inode		*inode = req->wb_inode;
-	struct nfs_reqlist	*cache = NFS_REQUESTLIST(inode);
-
 	spin_lock(&nfs_wreq_lock);
 	if (--req->wb_count) {
 		spin_unlock(&nfs_wreq_lock);
@@ -142,7 +157,6 @@
 	}
 	__nfs_del_lru(req);
 	spin_unlock(&nfs_wreq_lock);
-	atomic_dec(&cache->nr_requests);
 
 #ifdef NFS_PARANOIA
 	if (!list_empty(&req->wb_list))
@@ -151,16 +165,12 @@
 		BUG();
 	if (NFS_WBACK_BUSY(req))
 		BUG();
-	if (atomic_read(&cache->nr_requests) < 0)
+	if (atomic_read(&NFS_REQUESTLIST(req->wb_inode)->nr_requests) < 0)
 		BUG();
 #endif
 
 	/* Release struct file or cached credential */
-	if (req->wb_file)
-		fput(req->wb_file);
-	else if (req->wb_cred)
-		put_rpccred(req->wb_cred);
-	page_cache_release(req->wb_page);
+	nfs_clear_request(req);
 	nfs_page_free(req);
 }
 
diff -Nru a/fs/nfs/proc.c b/fs/nfs/proc.c
--- a/fs/nfs/proc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfs/proc.c	Sun Feb 10 19:58:05 2002
@@ -30,7 +30,7 @@
 #include <linux/types.h>
 #include <linux/param.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/errno.h>
diff -Nru a/fs/nfs/read.c b/fs/nfs/read.c
--- a/fs/nfs/read.c	Sun Feb 10 19:58:03 2002
+++ b/fs/nfs/read.c	Sun Feb 10 19:58:03 2002
@@ -16,7 +16,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -171,7 +171,7 @@
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_page	*new;
 
-	new = nfs_create_request(file, inode, page, 0, PAGE_CACHE_SIZE);
+	new = nfs_create_request(nfs_file_cred(file), inode, page, 0, PAGE_CACHE_SIZE);
 	if (IS_ERR(new))
 		return PTR_ERR(new);
 	nfs_mark_request_read(new);
@@ -227,8 +227,9 @@
 		nfs_list_remove_request(req);
 		SetPageError(page);
 		UnlockPage(page);
-		nfs_unlock_request(req);
+		nfs_clear_request(req);
 		nfs_release_request(req);
+		nfs_unlock_request(req);
 	}
 }
 
@@ -433,6 +434,7 @@
                         (long long)NFS_FILEID(req->wb_inode),
                         req->wb_bytes,
                         (long long)(page_offset(page) + req->wb_offset));
+		nfs_clear_request(req);
 		nfs_release_request(req);
 		nfs_unlock_request(req);
 	}
@@ -450,18 +452,8 @@
 int
 nfs_readpage(struct file *file, struct page *page)
 {
-	struct inode *inode;
+	struct inode *inode = page->mapping->host;
 	int		error;
-
-	if (!file) {
-		struct address_space *mapping = page->mapping;
-		if (!mapping)
-			BUG();
-		inode = mapping->host;
-	} else
-		inode = file->f_dentry->d_inode;
-	if (!inode)
-		BUG();
 
 	dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
 		page, PAGE_CACHE_SIZE, page->index);
diff -Nru a/fs/nfs/symlink.c b/fs/nfs/symlink.c
--- a/fs/nfs/symlink.c	Sun Feb 10 19:58:03 2002
+++ b/fs/nfs/symlink.c	Sun Feb 10 19:58:03 2002
@@ -11,7 +11,7 @@
  */
 
 #define NFS_NEED_XDR_TYPES
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs.h>
diff -Nru a/fs/nfs/write.c b/fs/nfs/write.c
--- a/fs/nfs/write.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfs/write.c	Sun Feb 10 19:58:05 2002
@@ -239,17 +239,11 @@
 int
 nfs_writepage(struct page *page)
 {
-	struct inode *inode;
+	struct inode *inode = page->mapping->host;
 	unsigned long end_index;
 	unsigned offset = PAGE_CACHE_SIZE;
 	int err;
-	struct address_space *mapping = page->mapping;
 
-	if (!mapping)
-		BUG();
-	inode = mapping->host;
-	if (!inode)
-		BUG();
 	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 
 	/* Ensure we've flushed out any previous writes */
@@ -354,6 +348,7 @@
 		iput(inode);
 	} else
 		spin_unlock(&nfs_wreq_lock);
+	nfs_clear_request(req);
 	nfs_release_request(req);
 }
 
@@ -684,9 +679,13 @@
 		}
 		spin_unlock(&nfs_wreq_lock);
 
-		new = nfs_create_request(file, inode, page, offset, bytes);
+		new = nfs_create_request(nfs_file_cred(file), inode, page, offset, bytes);
 		if (IS_ERR(new))
 			return new;
+		if (file) {
+			new->wb_file = file;
+			get_file(file);
+		}
 		/* If the region is locked, adjust the timeout */
 		if (region_locked(inode, new))
 			new->wb_timeout = jiffies + NFS_WRITEBACK_LOCKDELAY;
@@ -764,7 +763,7 @@
 int
 nfs_flush_incompatible(struct file *file, struct page *page)
 {
-	struct inode	*inode = file->f_dentry->d_inode;
+	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
 	int		status = 0;
 	/*
@@ -794,7 +793,7 @@
 nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsigned int count)
 {
 	struct dentry	*dentry = file->f_dentry;
-	struct inode	*inode = dentry->d_inode;
+	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
 	loff_t		end;
 	int		status = 0;
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	Sun Feb 10 19:58:04 2002
+++ b/fs/nfsd/export.c	Sun Feb 10 19:58:04 2002
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/in.h>
+#include <linux/seq_file.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -32,10 +33,9 @@
 typedef struct svc_client	svc_client;
 typedef struct svc_export	svc_export;
 
-static svc_export *	exp_find(svc_client *clp, kdev_t dev);
-static svc_export *	exp_parent(svc_client *clp, kdev_t dev,
+static svc_export *	exp_parent(svc_client *clp, struct super_block *sb,
 					struct dentry *dentry);
-static svc_export *	exp_child(svc_client *clp, kdev_t dev,
+static svc_export *	exp_child(svc_client *clp, struct super_block *sb,
 					struct dentry *dentry);
 static void		exp_unexport_all(svc_client *clp);
 static void		exp_do_unexport(svc_export *unexp);
@@ -66,40 +66,43 @@
 static int			hash_count;
 static DECLARE_WAIT_QUEUE_HEAD(	hash_wait );
 
-
 /*
- * Find a client's export for a device.
+ * Find the client's export entry matching xdev/xino.
  */
-static inline svc_export *
-exp_find(svc_client *clp, kdev_t dev)
+svc_export *
+exp_get(svc_client *clp, kdev_t dev, ino_t ino)
 {
-	svc_export *	exp;
+	struct list_head *head, *p;
+	svc_export *exp = NULL;
 
-	exp = clp->cl_export[EXPORT_HASH(dev)];
-	while (exp && !kdev_same(exp->ex_dev, dev))
-		exp = exp->ex_next;
+	if (!clp)
+		return NULL;
+
+	head = &clp->cl_export[EXPORT_HASH(dev)];
+	list_for_each(p, head) {
+		exp = list_entry(p, svc_export, ex_hash);
+		if (exp->ex_ino == ino && kdev_same(exp->ex_dev, dev))
+			break;
+	}
 	return exp;
 }
 
-/*
- * Find the client's export entry matching xdev/xino.
- */
 svc_export *
-exp_get(svc_client *clp, kdev_t dev, ino_t ino)
+exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry)
 {
-	svc_export *	exp;
+	struct list_head *head, *p;
+	int hash = EXPORT_HASH(mnt->mnt_sb->s_dev);
+	svc_export *exp = NULL;
 
 	if (!clp)
 		return NULL;
 
-	exp = clp->cl_export[EXPORT_HASH(dev)];
-	if (exp)
-		do {
-			if (exp->ex_ino == ino && kdev_same(exp->ex_dev, dev))
-				goto out;
-		} while (NULL != (exp = exp->ex_next));
-	exp = NULL;
-out:
+	head = &clp->cl_export[hash];
+	list_for_each(p, head) {
+		exp = list_entry(p, svc_export, ex_hash);
+		if (exp->ex_dentry == dentry && exp->ex_mnt == mnt)
+			break;
+	}
 	return exp;
 }
 
@@ -107,16 +110,17 @@
  * Find the export entry for a given dentry.  <gam3@acm.org>
  */
 static svc_export *
-exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry)
+exp_parent(svc_client *clp, struct super_block *sb, struct dentry *dentry)
 {
-	svc_export      *exp;
+	struct list_head *head = &clp->cl_export[EXPORT_HASH(sb->s_dev)];
+	struct list_head *p;
+	svc_export *exp = NULL;
 
-	if (clp == NULL)
-		return NULL;
-
-	for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next)
+	list_for_each(p, head) {
+		exp = list_entry(p, svc_export, ex_hash);
 		if (is_subdir(dentry, exp->ex_dentry))
 			break;
+	}
 	return exp;
 }
 
@@ -126,21 +130,35 @@
  * <gam3@acm.org>
  */
 static svc_export *
-exp_child(svc_client *clp, kdev_t dev, struct dentry *dentry)
+exp_child(svc_client *clp, struct super_block *sb, struct dentry *dentry)
 {
-	svc_export      *exp;
-
-	if (clp == NULL)
-		return NULL;
-
-	for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) {
-		struct dentry	*ndentry = exp->ex_dentry;
+	struct list_head *head = &clp->cl_export[EXPORT_HASH(sb->s_dev)];
+	struct list_head *p;
+	svc_export *exp = NULL;
+	struct dentry *ndentry;
+
+	list_for_each(p, head) {
+		exp = list_entry(p, svc_export, ex_hash);
+		ndentry = exp->ex_dentry;
 		if (ndentry && is_subdir(ndentry->d_parent, dentry))
 			break;
 	}
 	return exp;
 }
 
+/* Update parent pointers of all exports */
+static void exp_change_parents(svc_client *clp, svc_export *old, svc_export *new)
+{
+	struct list_head *head = &clp->cl_list;
+	struct list_head *p;
+
+	list_for_each(p, head) {
+		svc_export *exp = list_entry(p, svc_export, ex_list);
+		if (exp->ex_parent == old)
+			exp->ex_parent = new;
+	}
+}
+
 /*
  * Export a file system.
  */
@@ -149,10 +167,9 @@
 {
 	svc_client	*clp;
 	svc_export	*exp, *parent;
-	svc_export	**head;
 	struct nameidata nd;
 	struct inode	*inode = NULL;
-	int		i, err;
+	int		err;
 	kdev_t		dev;
 	ino_t		ino;
 
@@ -221,12 +238,12 @@
 		goto finish;
 	}
 
-	if ((parent = exp_child(clp, dev, nd.dentry)) != NULL) {
+	if ((parent = exp_child(clp, inode->i_sb, nd.dentry)) != NULL) {
 		dprintk("exp_export: export not valid (Rule 3).\n");
 		goto finish;
 	}
 	/* Is this is a sub-export, must be a proper subset of FS */
-	if ((parent = exp_parent(clp, dev, nd.dentry)) != NULL) {
+	if ((parent = exp_parent(clp, inode->i_sb, nd.dentry)) != NULL) {
 		dprintk("exp_export: sub-export not valid (Rule 2).\n");
 		goto finish;
 	}
@@ -248,21 +265,11 @@
 	exp->ex_anon_gid = nxp->ex_anon_gid;
 
 	/* Update parent pointers of all exports */
-	if (parent) {
-		for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-			svc_export *temp = clp->cl_export[i];
-
-			while (temp) {
-				if (temp->ex_parent == parent)
-					temp->ex_parent = exp;
-				temp = temp->ex_next;
-			}
-		}
-	}
+	if (parent)
+		exp_change_parents(clp, parent, exp);
 
-	head = clp->cl_export + EXPORT_HASH(dev);
-	exp->ex_next = *head;
-	*head = exp;
+	list_add(&exp->ex_hash, clp->cl_export + EXPORT_HASH(dev));
+	list_add_tail(&exp->ex_list, &clp->cl_list);
 
 	err = 0;
 
@@ -285,21 +292,12 @@
 static void
 exp_do_unexport(svc_export *unexp)
 {
-	svc_export	*exp;
-	svc_client	*clp;
 	struct dentry	*dentry;
 	struct vfsmount *mnt;
 	struct inode	*inode;
-	int		i;
 
 	/* Update parent pointers. */
-	clp = unexp->ex_client;
-	for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-		for (exp = clp->cl_export[i]; exp; exp = exp->ex_next)
-			if (exp->ex_parent == unexp)
-				exp->ex_parent = unexp->ex_parent;
-	}
-
+	exp_change_parents(unexp->ex_client, unexp, unexp->ex_parent);
 	dentry = unexp->ex_dentry;
 	mnt = unexp->ex_mnt;
 	inode = dentry->d_inode;
@@ -319,18 +317,15 @@
 static void
 exp_unexport_all(svc_client *clp)
 {
-	svc_export	*exp;
-	int		i;
+	struct list_head *p = &clp->cl_list;
 
 	dprintk("unexporting all fs's for clnt %p\n", clp);
-	for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-		exp = clp->cl_export[i];
-		clp->cl_export[i] = NULL;
-		while (exp) {
-			svc_export *next = exp->ex_next;
-			exp_do_unexport(exp);
-			exp = next;
-		}
+
+	while (!list_empty(p)) {
+		svc_export *exp = list_entry(p->next, svc_export, ex_list);
+		list_del(&exp->ex_list);
+		list_del(&exp->ex_hash);
+		exp_do_unexport(exp);
 	}
 }
 
@@ -341,7 +336,6 @@
 exp_unexport(struct nfsctl_export *nxp)
 {
 	svc_client	*clp;
-	svc_export	**expp, *exp = NULL;
 	int		err;
 
 	/* Consistency check */
@@ -355,17 +349,12 @@
 	clp = exp_getclientbyname(nxp->ex_client);
 	if (clp) {
 		kdev_t ex_dev = to_kdev_t(nxp->ex_dev);
-		expp = clp->cl_export + EXPORT_HASH(ex_dev);
-		while ((exp = *expp) != NULL) {
-			if (kdev_same(exp->ex_dev, ex_dev)) {
-				if (exp->ex_ino == nxp->ex_ino) {
-					*expp = exp->ex_next;
-					exp_do_unexport(exp);
-					err = 0;
-					break;
-				}
-			}
-			expp = &(exp->ex_next);
+		svc_export *exp = exp_get(clp, ex_dev, nxp->ex_ino);
+		if (exp) {
+			list_del(&exp->ex_hash);
+			list_del(&exp->ex_list);
+			exp_do_unexport(exp);
+			err = 0;
 		}
 	}
 
@@ -380,8 +369,7 @@
  * since its harder to fool a kernel module than a user space program.
  */
 int
-exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
-	   char *path, struct knfsd_fh *f, int maxsize)
+exp_rootfh(struct svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
 {
 	struct svc_export	*exp;
 	struct nameidata	nd;
@@ -390,45 +378,23 @@
 	int			err;
 
 	err = -EPERM;
-	if (path) {
-		if (path_init(path, LOOKUP_POSITIVE, &nd) &&
-		    path_walk(path, &nd)) {
-			printk("nfsd: exp_rootfh path not found %s", path);
-			return err;
-		}
-		dev = nd.dentry->d_inode->i_dev;
-		ino = nd.dentry->d_inode->i_ino;
-	
-		dprintk("nfsd: exp_rootfh(%s [%p] %s:%02x:%02x/%ld)\n",
-		         path, nd.dentry, clp->cl_ident,
-		         major(dev), minor(dev), (long) ino);
-		exp = exp_parent(clp, dev, nd.dentry);
-	} else {
-		dprintk("nfsd: exp_rootfh(%s:%02x:%02x/%ld)\n",
-		         clp->cl_ident, major(dev), minor(dev), (long) ino);
-		if ((exp = exp_get(clp, dev, ino))) {
-			nd.mnt = mntget(exp->ex_mnt);
-			nd.dentry = dget(exp->ex_dentry);
-		}
+	/* NB: we probably ought to check that it's NUL-terminated */
+	if (path_init(path, LOOKUP_POSITIVE, &nd) &&
+	    path_walk(path, &nd)) {
+		printk("nfsd: exp_rootfh path not found %s", path);
+		return err;
 	}
+	inode = nd.dentry->d_inode;
+
+	dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
+		 path, nd.dentry, clp->cl_ident,
+		 inode->i_sb->s_id, inode->i_ino);
+	exp = exp_parent(clp, inode->i_sb, nd.dentry);
 	if (!exp) {
 		dprintk("nfsd: exp_rootfh export not found.\n");
 		goto out;
 	}
 
-	inode = nd.dentry->d_inode;
-	if (!inode) {
-		printk("exp_rootfh: Aieee, NULL d_inode\n");
-		goto out;
-	}
-	if (!kdev_same(inode->i_dev, dev) || inode->i_ino != ino) {
-		printk("exp_rootfh: Aieee, ino/dev mismatch\n");
-		printk("exp_rootfh: arg[dev(%02x:%02x):ino(%ld)]"
-		       " inode[dev(%02x:%02x):ino(%ld)]\n",
-		       major(dev), minor(dev), (long) ino,
-		       major(inode->i_dev), minor(inode->i_dev), (long) inode->i_ino);
-	}
-
 	/*
 	 * fh must be initialized before calling fh_compose
 	 */
@@ -468,7 +434,7 @@
 		return 0;
 	}
 
-	current->work.sigpending = 0;
+	clear_thread_flag(TIF_SIGPENDING);
 	want_lock++;
 	while (hash_count || hash_lock) {
 		interruptible_sleep_on(&hash_wait);
@@ -547,6 +513,67 @@
 	return NULL;
 }
 
+/* Iterator */
+
+static void *e_start(struct seq_file *m, loff_t *pos)
+{
+	loff_t n = *pos;
+	unsigned client, export;
+	svc_client *clp;
+	struct list_head *p;
+	
+	exp_readlock();
+	if (!n--)
+		return (void *)1;
+	client = n >> 32;
+	export = n & ((1LL<<32) - 1);
+	for (clp = clients; client && clp; clp = clp->cl_next, client--)
+		;
+	if (!clp)
+		return NULL;
+	list_for_each(p, &clp->cl_list)
+		if (!export--)
+			return list_entry(p, svc_export, ex_list);
+	n &= ~((1LL<<32) - 1);
+	do {
+		clp = clp->cl_next;
+		n += 1LL<<32;
+	} while(clp && list_empty(&clp->cl_list));
+	if (!clp)
+		return NULL;
+	*pos = n+1;
+	return list_entry(clp->cl_list.next, svc_export, ex_list);
+}
+
+static void *e_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	svc_export *exp = p;
+	svc_client *clp;
+
+	if (p == (void *)1)
+		clp = clients;
+	else if (exp->ex_list.next == &exp->ex_client->cl_list)
+		clp = exp->ex_client->cl_next;
+	else {
+		++*pos;
+		return list_entry(exp->ex_list.next, svc_export, ex_list);
+	}
+	*pos &= ~((1LL<<32) - 1);
+	while (clp && list_empty(&clp->cl_list)) {
+		clp = clp->cl_next;
+		*pos += 1LL<<32;
+	}
+	if (!clp)
+		return NULL;
+	++*pos;
+	return list_entry(clp->cl_list.next, svc_export, ex_list);
+}
+
+static void e_stop(struct seq_file *m, void *p)
+{
+	exp_unlock();
+}
+
 struct flags {
 	int flag;
 	char *name[2];
@@ -569,128 +596,77 @@
 	{ 0, {"", ""}}
 };
 
-static int
-exp_flags(char *buffer, int flag)
+static void exp_flags(struct seq_file *m, int flag)
 {
-    int len = 0, first = 0;
-    struct flags *flg = expflags;
+	int first = 0;
+	struct flags *flg;
 
-    for (;flg->flag;flg++) {
-        int state = (flg->flag & flag)?0:1;
-        if (!flg->flag)
-		break;
-        if (*flg->name[state]) {
-		len += sprintf(buffer + len, "%s%s",
-                               first++?",":"", flg->name[state]);
-        }
-    }
-    return len;
+	for (flg = expflags; flg->flag; flg++) {
+		int state = (flg->flag & flag)?0:1;
+		if (*flg->name[state])
+			seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
+	}
 }
 
-
-
-/* mangling borrowed from fs/super.c */
-/* Use octal escapes, like mount does, for embedded spaces etc. */
-static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
-
-static int
-mangle(const unsigned char *s, char *buf, int len) {
-        char *sp;
-        int n;
-
-        sp = buf;
-        while(*s && sp-buf < len-3) {
-                for (n = 0; n < sizeof(need_escaping); n++) {
-                        if (*s == need_escaping[n]) {
-                                *sp++ = '\\';
-                                *sp++ = '0' + ((*s & 0300) >> 6);
-                                *sp++ = '0' + ((*s & 070) >> 3);
-                                *sp++ = '0' + (*s & 07);
-                                goto next;
-                        }
-                }
-                *sp++ = *s;
-        next:
-                s++;
-        }
-        return sp - buf;	/* no trailing NUL */
+static inline void mangle(struct seq_file *m, const char *s)
+{
+	seq_escape(m, s, " \t\n\\");
 }
 
-#define FREEROOM	((int)PAGE_SIZE-200-len)
-#define MANGLE(s)	len += mangle((s), buffer+len, FREEROOM);
-
-int
-exp_procfs_exports(char *buffer, char **start, off_t offset,
-                             int length, int *eof, void *data)
+static int e_show(struct seq_file *m, void *p)
 {
-	struct svc_clnthash	**hp, **head, *tmp;
-	struct svc_client	*clp;
-	svc_export *exp;
-	off_t	pos = 0;
-        off_t	begin = 0;
-        int	len = 0;
-	int	i,j;
+	struct svc_export *exp = p;
+	struct svc_client *clp;
+	int j, first = 0;
 
-        len += sprintf(buffer, "# Version 1.1\n");
-        len += sprintf(buffer+len, "# Path Client(Flags) # IPs\n");
-
-	for (clp = clients; clp; clp = clp->cl_next) {
-		for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-			exp = clp->cl_export[i];
-			while (exp) {
-				int first = 0;
-				MANGLE(exp->ex_path);
-				buffer[len++]='\t';
-				MANGLE(clp->cl_ident);
-				buffer[len++]='(';
-
-				len += exp_flags(buffer+len, exp->ex_flags);
-				len += sprintf(buffer+len, ") # ");
-				for (j = 0; j < clp->cl_naddr; j++) {
-					struct in_addr	addr = clp->cl_addr[j]; 
-
-					head = &clnt_hash[CLIENT_HASH(addr.s_addr)];
-					for (hp = head; (tmp = *hp) != NULL; hp = &(tmp->h_next)) {
-						if (tmp->h_addr.s_addr == addr.s_addr) {
-							if (first++) len += sprintf(buffer+len, "%s", " ");
-							if (tmp->h_client != clp)
-								len += sprintf(buffer+len, "(");
-							len += sprintf(buffer+len, "%d.%d.%d.%d",
-									htonl(addr.s_addr) >> 24 & 0xff,
-									htonl(addr.s_addr) >> 16 & 0xff,
-									htonl(addr.s_addr) >>  8 & 0xff,
-									htonl(addr.s_addr) >>  0 & 0xff);
-							if (tmp->h_client != clp)
-							  len += sprintf(buffer+len, ")");
-							break;
-						}
-					}
-				}
-				exp = exp->ex_next;
-
-				buffer[len++]='\n';
-
-				pos=begin+len;
-				if(pos<offset) {
-					len=0;
-					begin=pos;
-				}
-				if (pos > offset + length)
-					goto done;
-			}
-		}
+	if (p == (void *)1) {
+		seq_puts(m, "# Version 1.1\n");
+		seq_puts(m, "# Path Client(Flags) # IPs\n");
+		return 0;
 	}
 
-	*eof = 1;
+	clp = exp->ex_client;
 
-done:
-	*start = buffer + (offset - begin);
-	len -= (offset - begin);
-	if ( len > length )
-		len = length;
-	return len;
+	mangle(m, exp->ex_path);
+	seq_putc(m, '\t');
+	mangle(m, clp->cl_ident);
+	seq_putc(m, '(');
+	exp_flags(m, exp->ex_flags);
+	seq_puts(m, ") # ");
+	for (j = 0; j < clp->cl_naddr; j++) {
+		struct svc_clnthash **hp, **head, *tmp;
+		struct in_addr addr = clp->cl_addr[j]; 
+
+		head = &clnt_hash[CLIENT_HASH(addr.s_addr)];
+		for (hp = head; (tmp = *hp) != NULL; hp = &(tmp->h_next)) {
+			if (tmp->h_addr.s_addr == addr.s_addr)
+				break;
+		}
+		if (tmp) {
+			if (first++)
+				seq_putc(m, ' ');
+			if (tmp->h_client != clp)
+				seq_putc(m, '(');
+			seq_printf(m, "%d.%d.%d.%d",
+				htonl(addr.s_addr) >> 24 & 0xff,
+				htonl(addr.s_addr) >> 16 & 0xff,
+				htonl(addr.s_addr) >>  8 & 0xff,
+				htonl(addr.s_addr) >>  0 & 0xff);
+			if (tmp->h_client != clp)
+				seq_putc(m, ')');
+		}
+	}
+	seq_putc(m, '\n');
+	return 0;
 }
 
+struct seq_operations nfs_exports_op = {
+	start:	e_start,
+	next:	e_next,
+	stop:	e_stop,
+	show:	e_show,
+};
+
 /*
  * Add or modify a client.
  * Change requests may involve the list of host addresses. The list of
@@ -726,6 +702,9 @@
 		if (!(clp = kmalloc(sizeof(*clp), GFP_KERNEL)))
 			goto out_unlock;
 		memset(clp, 0, sizeof(*clp));
+		for (i = 0; i < NFSCLNT_EXPMAX; i++)
+			INIT_LIST_HEAD(&clp->cl_export[i]);
+		INIT_LIST_HEAD(&clp->cl_list);
 
 		dprintk("created client %s (%p)\n", ncp->cl_ident, clp);
 
diff -Nru a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
--- a/fs/nfsd/nfs3proc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfsd/nfs3proc.c	Sun Feb 10 19:58:05 2002
@@ -7,7 +7,7 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
--- a/fs/nfsd/nfs3xdr.c	Sun Feb 10 19:58:03 2002
+++ b/fs/nfsd/nfs3xdr.c	Sun Feb 10 19:58:03 2002
@@ -7,7 +7,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/nfs3.h>
 
 #include <linux/sunrpc/xdr.h>
diff -Nru a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
--- a/fs/nfsd/nfscache.c	Sun Feb 10 19:58:06 2002
+++ b/fs/nfsd/nfscache.c	Sun Feb 10 19:58:06 2002
@@ -11,7 +11,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 
diff -Nru a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
--- a/fs/nfsd/nfsctl.c	Sun Feb 10 19:58:04 2002
+++ b/fs/nfsd/nfsctl.c	Sun Feb 10 19:58:04 2002
@@ -11,7 +11,7 @@
 #include <linux/version.h>
 
 #include <linux/linkage.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/fcntl.h>
@@ -20,6 +20,7 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <linux/nfs.h>
 #include <linux/sunrpc/svc.h>
@@ -37,7 +38,6 @@
 static int	nfsctl_delclient(struct nfsctl_client *data);
 static int	nfsctl_export(struct nfsctl_export *data);
 static int	nfsctl_unexport(struct nfsctl_export *data);
-static int	nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
 static int	nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
 static int	nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
 #ifdef notyet
@@ -46,17 +46,28 @@
 
 static int	initialized;
 
-int exp_procfs_exports(char *buffer, char **start, off_t offset,
-                             int length, int *eof, void *data);
+extern struct seq_operations nfs_exports_op;
+static int exports_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &nfs_exports_op);
+}
+static struct file_operations exports_operations = {
+	open:		exports_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
 
 void proc_export_init(void)
 {
+	struct proc_dir_entry *entry;
 	if (!proc_mkdir("fs/nfs", 0))
 		return;
-	create_proc_read_entry("fs/nfs/exports", 0, 0, exp_procfs_exports,NULL);
+	entry = create_proc_entry("fs/nfs/exports", 0, NULL);
+	if (entry)
+		entry->proc_fops =  &exports_operations;
 }
 
-
 /*
  * Initialize nfsd
  */
@@ -125,7 +136,7 @@
 	if (!(clp = exp_getclient(sin)))
 		err = -EPERM;
 	else
-		err = exp_rootfh(clp, NODEV, 0, data->gd_path, res, data->gd_maxlen);
+		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
 	exp_unlock();
 	return err;
 }
@@ -148,40 +159,7 @@
 	if (!(clp = exp_getclient(sin)))
 		err = -EPERM;
 	else
-		err = exp_rootfh(clp, NODEV, 0, data->gd_path, &fh, NFS_FHSIZE);
-	exp_unlock();
-
-	if (err == 0) {
-		if (fh.fh_size > NFS_FHSIZE)
-			err = -EINVAL;
-		else {
-			memset(res,0, NFS_FHSIZE);
-			memcpy(res, &fh.fh_base, fh.fh_size);
-		}
-	}
-
-	return err;
-}
-
-static inline int
-nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
-{
-	struct sockaddr_in	*sin;
-	struct svc_client	*clp;
-	int			err = 0;
-	struct knfsd_fh		fh;
-
-	if (data->gf_addr.sa_family != AF_INET)
-		return -EPROTONOSUPPORT;
-	if (data->gf_version < 2 || data->gf_version > NFSSVC_MAXVERS)
-		return -EINVAL;
-	sin = (struct sockaddr_in *)&data->gf_addr;
-
-	exp_readlock();
-	if (!(clp = exp_getclient(sin)))
-		err = -EPERM;
-	else
-		err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
+		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
 	exp_unlock();
 
 	if (err == 0) {
@@ -277,9 +255,6 @@
 		err = nfsctl_ugidupdate(&arg->ca_umap);
 		break;
 #endif
-	case NFSCTL_GETFH:
-		err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
-		break;
 	case NFSCTL_GETFD:
 		err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
 		break;
diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
--- a/fs/nfsd/nfsfh.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfsd/nfsfh.c	Sun Feb 10 19:58:05 2002
@@ -424,8 +424,7 @@
 	/* It's a directory, or we are required to confirm the file's
 	 * location in the tree.
 	 */
-	dprintk("nfs_fh: need to look harder for %02x:%02x/%d\n",
-		major(sb->s_dev), minor(sb->s_dev), datap[0]);
+	dprintk("nfs_fh: need to look harder for %s/%d\n", sb->s_id, datap[0]);
 
 	if (!S_ISDIR(result->d_inode->i_mode)) {
 		nfsdstats.fh_nocache_nondir++;
diff -Nru a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
--- a/fs/nfsd/nfsproc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfsd/nfsproc.c	Sun Feb 10 19:58:05 2002
@@ -8,7 +8,7 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c	Sun Feb 10 19:58:03 2002
+++ b/fs/nfsd/nfssvc.c	Sun Feb 10 19:58:03 2002
@@ -12,7 +12,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/nfs.h>
 #include <linux/in.h>
diff -Nru a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
--- a/fs/nfsd/nfsxdr.c	Sun Feb 10 19:58:04 2002
+++ b/fs/nfsd/nfsxdr.c	Sun Feb 10 19:58:04 2002
@@ -7,7 +7,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/nfs.h>
 
 #include <linux/sunrpc/xdr.h>
diff -Nru a/fs/nfsd/stats.c b/fs/nfsd/stats.c
--- a/fs/nfsd/stats.c	Sun Feb 10 19:58:03 2002
+++ b/fs/nfsd/stats.c	Sun Feb 10 19:58:03 2002
@@ -24,7 +24,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #define __NO_VERSION__
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Sun Feb 10 19:58:05 2002
+++ b/fs/nfsd/vfs.c	Sun Feb 10 19:58:05 2002
@@ -18,7 +18,7 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/string.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
@@ -114,35 +114,30 @@
 	if (isdotent(name, len)) {
 		if (len==1)
 			dentry = dget(dparent);
-		else  { /* must be ".." */
+		else if (dparent != exp->ex_dentry)
+			dentry = dget(dparent->d_parent);
+		else  if (!EX_CROSSMNT(exp))
+			dentry = dget(dparent); /* .. == . just like at / */
+		else {
 			/* checking mountpoint crossing is very different when stepping up */
-			if (dparent == exp->ex_dentry) {
-				if (!EX_CROSSMNT(exp))
-					dentry = dget(dparent); /* .. == . just like at / */
-				else
-				{
-					struct svc_export *exp2 = NULL;
-					struct dentry *dp;
-					struct vfsmount *mnt = mntget(exp->ex_mnt);
-					dentry = dget(dparent);
-					while(follow_up(&mnt, &dentry))
-						;
-					dp = dget(dentry->d_parent);
-					dput(dentry);
-					dentry = dp;
-					for ( ; exp2 == NULL && dp->d_parent != dp;
-					      dp=dp->d_parent)
-						exp2 = exp_get(exp->ex_client, dp->d_inode->i_dev, dp->d_inode->i_ino);
-					if (exp2==NULL) {
-						dput(dentry);
-						dentry = dget(dparent);
-					} else {
-						exp = exp2;
-					}
-					mntput(mnt);
-				}
-			} else
-				dentry = dget(dparent->d_parent);
+			struct svc_export *exp2 = NULL;
+			struct dentry *dp;
+			struct vfsmount *mnt = mntget(exp->ex_mnt);
+			dentry = dget(dparent);
+			while(follow_up(&mnt, &dentry))
+				;
+			dp = dget(dentry->d_parent);
+			dput(dentry);
+			dentry = dp;
+			for ( ; !exp2 && dp->d_parent != dp; dp=dp->d_parent)
+				exp2 = exp_get_by_name(exp->ex_client, mnt, dp);
+			if (!exp2) {
+				dput(dentry);
+				dentry = dget(dparent);
+			} else {
+				exp = exp2;
+			}
+			mntput(mnt);
 		}
 	} else {
 		fh_lock(fhp);
@@ -159,9 +154,7 @@
 			struct dentry *mounts = dget(dentry);
 			while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts))
 				;
-			exp2 = exp_get(rqstp->rq_client,
-				       mounts->d_inode->i_dev,
-				       mounts->d_inode->i_ino);
+			exp2 = exp_get_by_name(rqstp->rq_client, mnt, mounts);
 			if (exp2 && EX_CROSSMNT(exp2)) {
 				/* successfully crossed mount point */
 				exp = exp2;
@@ -591,6 +584,7 @@
 	mm_segment_t	oldfs;
 	int		err;
 	struct file	file;
+	struct inode	*inode;
 
 	err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
 	if (err)
@@ -598,14 +592,15 @@
 	err = nfserr_perm;
 	if (!file.f_op->read)
 		goto out_close;
+	inode = file.f_dentry->d_inode;
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
-		(!lock_may_read(file.f_dentry->d_inode, offset, *count)))
+		(!lock_may_read(inode, offset, *count)))
 		goto out_close;
 #endif
 
 	/* Get readahead parameters */
-	ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);
+	ra = nfsd_get_raparms(inode->i_dev, inode->i_ino);
 	if (ra) {
 		file.f_reada = ra->p_reada;
 		file.f_ramax = ra->p_ramax;
@@ -1415,8 +1410,8 @@
 		oldlen = cd.buflen;
 
 		/*
-		dprintk("nfsd: f_op->readdir(%x/%ld @ %d) buflen = %d (%d)\n",
-			file.f_inode->i_dev, file.f_inode->i_ino,
+		dprintk("nfsd: f_op->readdir(%s/%ld @ %d) buflen = %d (%d)\n",
+			file.f_inode->i_sb->s_id, file.f_inode->i_ino,
 			(int) file.f_pos, (int) oldlen, (int) cd.buflen);
 		 */
 		err = file.f_op->readdir(&file, &cd, (filldir_t) func);
diff -Nru a/fs/ntfs/fs.c b/fs/ntfs/fs.c
--- a/fs/ntfs/fs.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ntfs/fs.c	Sun Feb 10 19:58:04 2002
@@ -1050,8 +1050,7 @@
  *
  * NOTE : A context switch can happen in kernel code only if the code blocks
  * (= calls schedule() in kernel/sched.c). */
-struct super_block *ntfs_read_super(struct super_block *sb, void *options,
-		int silent)
+static int ntfs_fill_super(struct super_block *sb, void *options, int silent)
 {
 	ntfs_volume *vol;
 	struct buffer_head *bh;
@@ -1130,7 +1129,7 @@
 	/* Inform the kernel about which super operations are available. */
 	sb->s_op = &ntfs_super_operations;
 	sb->s_magic = NTFS_SUPER_MAGIC;
-	sb->s_maxbytes = ~0ULL >> 1;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
 	ntfs_debug(DEBUG_OTHER, "Reading special files\n");
 	if (ntfs_load_special_files(vol)) {
 		ntfs_error("Error loading special files\n");
@@ -1142,19 +1141,28 @@
 		ntfs_error("Could not get root dir inode\n");
 		goto ntfs_read_super_mft;
 	}
-ntfs_read_super_ret:
-	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
-	return sb;
+	return 0;
 ntfs_read_super_mft:
 	ntfs_free(vol->mft);
 ntfs_read_super_unl:
 ntfs_read_super_vol:
-	sb = NULL;
-	goto ntfs_read_super_ret;
+	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
+	return -EINVAL;
 }
 
 /* Define the filesystem */
-static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
+static struct super_block *ntfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super);
+}
+
+static struct file_system_type ntfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"ntfs",
+	get_sb:		ntfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_ntfs_fs(void)
 {
diff -Nru a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
--- a/fs/openpromfs/inode.c	Sun Feb 10 19:58:06 2002
+++ b/fs/openpromfs/inode.c	Sun Feb 10 19:58:06 2002
@@ -998,8 +998,7 @@
 	statfs:		openprom_statfs,
 };
 
-struct super_block *openprom_read_super(struct super_block *s,void *data, 
-				    int silent)
+static int openprom_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * root_inode;
 
@@ -1013,15 +1012,25 @@
 	s->s_root = d_alloc_root(root_inode);
 	if (!s->s_root)
 		goto out_no_root;
-	return s;
+	return 0;
 
 out_no_root:
-	printk("openprom_read_super: get root inode failed\n");
+	printk("openprom_fill_super: get root inode failed\n");
 	iput(root_inode);
-	return NULL;
+	return -ENOMEM;
 }
 
-static DECLARE_FSTYPE(openprom_fs_type, "openpromfs", openprom_read_super, 0);
+static struct super_block *openprom_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, openprom_fill_super);
+}
+
+static struct file_system_type openprom_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"openpromfs",
+	get_sb:		openprom_get_sb,
+};
 
 static int __init init_openprom_fs(void)
 {
diff -Nru a/fs/pipe.c b/fs/pipe.c
--- a/fs/pipe.c	Sun Feb 10 19:58:03 2002
+++ b/fs/pipe.c	Sun Feb 10 19:58:03 2002
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -246,12 +247,6 @@
 	return -EPIPE;
 }
 
-static loff_t
-pipe_lseek(struct file *file, loff_t offset, int orig)
-{
-	return -ESPIPE;
-}
-
 static ssize_t
 bad_pipe_r(struct file *filp, char *buf, size_t count, loff_t *ppos)
 {
@@ -381,7 +376,7 @@
  * are also used in linux/fs/fifo.c to do operations on FIFOs.
  */
 struct file_operations read_fifo_fops = {
-	llseek:		pipe_lseek,
+	llseek:		no_llseek,
 	read:		pipe_read,
 	write:		bad_pipe_w,
 	poll:		fifo_poll,
@@ -391,7 +386,7 @@
 };
 
 struct file_operations write_fifo_fops = {
-	llseek:		pipe_lseek,
+	llseek:		no_llseek,
 	read:		bad_pipe_r,
 	write:		pipe_write,
 	poll:		fifo_poll,
@@ -401,7 +396,7 @@
 };
 
 struct file_operations rdwr_fifo_fops = {
-	llseek:		pipe_lseek,
+	llseek:		no_llseek,
 	read:		pipe_read,
 	write:		pipe_write,
 	poll:		fifo_poll,
@@ -411,7 +406,7 @@
 };
 
 struct file_operations read_pipe_fops = {
-	llseek:		pipe_lseek,
+	llseek:		no_llseek,
 	read:		pipe_read,
 	write:		bad_pipe_w,
 	poll:		pipe_poll,
@@ -421,7 +416,7 @@
 };
 
 struct file_operations write_pipe_fops = {
-	llseek:		pipe_lseek,
+	llseek:		no_llseek,
 	read:		bad_pipe_r,
 	write:		pipe_write,
 	poll:		pipe_poll,
@@ -431,7 +426,7 @@
 };
 
 struct file_operations rdwr_pipe_fops = {
-	llseek:		pipe_lseek,
+	llseek:		no_llseek,
 	read:		pipe_read,
 	write:		pipe_write,
 	poll:		pipe_poll,
@@ -606,7 +601,7 @@
 	statfs:		pipefs_statfs,
 };
 
-static struct super_block * pipefs_read_super(struct super_block *sb, void *data, int silent)
+static int pipefs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *root;
 
@@ -616,22 +611,32 @@
 	sb->s_op	= &pipefs_ops;
 	root = new_inode(sb);
 	if (!root)
-		return NULL;
+		return -ENOMEM;
 	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
 	root->i_uid = root->i_gid = 0;
 	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
 	sb->s_root = d_alloc(NULL, &(const struct qstr) { "pipe:", 5, 0 });
 	if (!sb->s_root) {
 		iput(root);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root->d_sb = sb;
 	sb->s_root->d_parent = sb->s_root;
 	d_instantiate(sb->s_root, root);
-	return sb;
+	return 0;
 }
 
-static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, FS_NOMOUNT);
+static struct super_block *pipefs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, pipefs_fill_super);
+}
+
+static struct file_system_type pipe_fs_type = {
+	name:		"pipefs",
+	get_sb:		pipefs_get_sb,
+	fs_flags:	FS_NOMOUNT,
+};
 
 static int __init init_pipe_fs(void)
 {
diff -Nru a/fs/proc/array.c b/fs/proc/array.c
--- a/fs/proc/array.c	Sun Feb 10 19:58:04 2002
+++ b/fs/proc/array.c	Sun Feb 10 19:58:04 2002
@@ -55,7 +55,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
 #include <linux/tty.h>
@@ -391,7 +391,7 @@
 		task->nswap,
 		task->cnswap,
 		task->exit_signal,
-		task->cpu);
+		task->thread_info->cpu);
 	if(mm)
 		mmput(mm);
 	return res;
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	Sun Feb 10 19:58:04 2002
+++ b/fs/proc/base.c	Sun Feb 10 19:58:04 2002
@@ -17,7 +17,7 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
@@ -37,6 +37,11 @@
 
 #define fake_ino(pid,ino) (((pid)<<16)|(ino))
 
+static inline struct task_struct *proc_task(struct inode *inode)
+{
+	return PROC_I(inode)->task;
+}
+
 ssize_t proc_pid_read_maps(struct task_struct*,struct file*,char*,size_t,loff_t*);
 int proc_pid_stat(struct task_struct*,char*);
 int proc_pid_status(struct task_struct*,char*);
@@ -45,9 +50,10 @@
 
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-	if (inode->u.proc_i.file) {
-		*mnt = mntget(inode->u.proc_i.file->f_vfsmnt);
-		*dentry = dget(inode->u.proc_i.file->f_dentry);
+	struct file *file = PROC_I(inode)->file;
+	if (file) {
+		*mnt = mntget(file->f_vfsmnt);
+		*dentry = dget(file->f_dentry);
 		return 0;
 	}
 	return -ENOENT;
@@ -58,7 +64,7 @@
 	struct mm_struct * mm;
 	struct vm_area_struct * vma;
 	int result = -ENOENT;
-	struct task_struct *task = inode->u.proc_i.task;
+	struct task_struct *task = proc_task(inode);
 
 	task_lock(task);
 	mm = task->mm;
@@ -89,11 +95,11 @@
 {
 	struct fs_struct *fs;
 	int result = -ENOENT;
-	task_lock(inode->u.proc_i.task);
-	fs = inode->u.proc_i.task->fs;
+	task_lock(proc_task(inode));
+	fs = proc_task(inode)->fs;
 	if(fs)
 		atomic_inc(&fs->count);
-	task_unlock(inode->u.proc_i.task);
+	task_unlock(proc_task(inode));
 	if (fs) {
 		read_lock(&fs->lock);
 		*mnt = mntget(fs->pwdmnt);
@@ -109,11 +115,11 @@
 {
 	struct fs_struct *fs;
 	int result = -ENOENT;
-	task_lock(inode->u.proc_i.task);
-	fs = inode->u.proc_i.task->fs;
+	task_lock(proc_task(inode));
+	fs = proc_task(inode)->fs;
 	if(fs)
 		atomic_inc(&fs->count);
-	task_unlock(inode->u.proc_i.task);
+	task_unlock(proc_task(inode));
 	if (fs) {
 		read_lock(&fs->lock);
 		*mnt = mntget(fs->rootmnt);
@@ -238,7 +244,7 @@
 			      size_t count, loff_t *ppos)
 {
 	struct inode * inode = file->f_dentry->d_inode;
-	struct task_struct *task = inode->u.proc_i.task;
+	struct task_struct *task = proc_task(inode);
 	ssize_t res;
 
 	res = proc_pid_read_maps(task, file, buf, count, ppos);
@@ -252,7 +258,7 @@
 extern struct seq_operations mounts_op;
 static int mounts_open(struct inode *inode, struct file *file)
 {
-	struct task_struct *task = inode->u.proc_i.task;
+	struct task_struct *task = proc_task(inode);
 	int ret = seq_open(file, &mounts_op);
 
 	if (!ret) {
@@ -298,14 +304,14 @@
 	unsigned long page;
 	ssize_t length;
 	ssize_t end;
-	struct task_struct *task = inode->u.proc_i.task;
+	struct task_struct *task = proc_task(inode);
 
 	if (count > PROC_BLOCK_SIZE)
 		count = PROC_BLOCK_SIZE;
 	if (!(page = __get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
 
-	length = inode->u.proc_i.op.proc_read(task, (char*)page);
+	length = PROC_I(inode)->op.proc_read(task, (char*)page);
 
 	if (length < 0) {
 		free_page(page);
@@ -342,7 +348,7 @@
 static ssize_t mem_read(struct file * file, char * buf,
 			size_t count, loff_t *ppos)
 {
-	struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task;
+	struct task_struct *task = proc_task(file->f_dentry->d_inode);
 	char *page;
 	unsigned long src = *ppos;
 	int copied = 0;
@@ -404,7 +410,7 @@
 {
 	int copied = 0;
 	char *page;
-	struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task;
+	struct task_struct *task = proc_task(file->f_dentry->d_inode);
 	unsigned long dst = *ppos;
 
 	if (!MAY_PTRACE(task))
@@ -463,7 +469,7 @@
 	if (error)
 		goto out;
 
-	error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
+	error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
 	nd->last_type = LAST_BIND;
 out:
 	return error;
@@ -503,7 +509,7 @@
 	if (error)
 		goto out;
 
-	error = inode->u.proc_i.op.proc_get_link(inode, &de, &mnt);
+	error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt);
 	if (error)
 		goto out;
 
@@ -570,7 +576,7 @@
 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
-	struct task_struct *p = inode->u.proc_i.task;
+	struct task_struct *p = proc_task(inode);
 	unsigned int fd, pid, ino;
 	int retval;
 	char buf[NUMBUF];
@@ -598,6 +604,7 @@
 			task_unlock(p);
 			if (!files)
 				goto out;
+			read_lock(&files->file_lock);
 			for (fd = filp->f_pos-2;
 			     fd < files->max_fds;
 			     fd++, filp->f_pos++) {
@@ -605,6 +612,7 @@
 
 				if (!fcheck_files(files, fd))
 					continue;
+				read_unlock(&files->file_lock);
 
 				j = NUMBUF;
 				i = fd;
@@ -617,7 +625,9 @@
 				ino = fake_ino(pid, PROC_PID_FD_DIR + fd);
 				if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0)
 					break;
+				read_lock(&files->file_lock);
 			}
+			read_unlock(&files->file_lock);
 			put_files_struct(files);
 	}
 out:
@@ -632,7 +642,7 @@
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct pid_entry *p;
 
-	pid = inode->u.proc_i.task->pid;
+	pid = proc_task(inode)->pid;
 	if (!pid)
 		return -ENOENT;
 	i = filp->f_pos;
@@ -684,6 +694,7 @@
 static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino)
 {
 	struct inode * inode;
+	struct proc_inode *ei;
 
 	/* We need a new inode */
 	
@@ -692,7 +703,9 @@
 		goto out;
 
 	/* Common stuff */
-
+	ei = PROC_I(inode);
+	ei->task = NULL;
+	ei->file = NULL;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_ino = fake_ino(task->pid, ino);
 
@@ -703,7 +716,7 @@
 	 * grab the reference to task.
 	 */
 	get_task_struct(task);
-	inode->u.proc_i.task = task;
+	ei->task = task;
 	inode->i_uid = 0;
 	inode->i_gid = 0;
 	if (ino == PROC_PID_INO || task_dumpable(task)) {
@@ -733,7 +746,7 @@
  */
 static int pid_base_revalidate(struct dentry * dentry, int flags)
 {
-	if (dentry->d_inode->u.proc_i.task->pid)
+	if (proc_task(dentry->d_inode)->pid)
 		return 1;
 	d_drop(dentry);
 	return 0;
@@ -767,10 +780,11 @@
 static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
 {
 	unsigned int fd, c;
-	struct task_struct *task = dir->u.proc_i.task;
+	struct task_struct *task = proc_task(dir);
 	struct file * file;
 	struct files_struct * files;
 	struct inode *inode;
+	struct proc_inode *ei;
 	const char *name;
 	int len;
 
@@ -792,6 +806,7 @@
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd);
 	if (!inode)
 		goto out;
+	ei = PROC_I(inode);
 	task_lock(task);
 	files = task->files;
 	if (files)
@@ -800,7 +815,7 @@
 	if (!files)
 		goto out_unlock;
 	read_lock(&files->file_lock);
-	file = inode->u.proc_i.file = fcheck_files(files, fd);
+	file = ei->file = fcheck_files(files, fd);
 	if (!file)
 		goto out_unlock2;
 	get_file(file);
@@ -809,7 +824,7 @@
 	inode->i_op = &proc_pid_link_inode_operations;
 	inode->i_size = 64;
 	inode->i_mode = S_IFLNK;
-	inode->u.proc_i.op.proc_get_link = proc_fd_link;
+	ei->op.proc_get_link = proc_fd_link;
 	if (file->f_mode & 1)
 		inode->i_mode |= S_IRUSR | S_IXUSR;
 	if (file->f_mode & 2)
@@ -844,8 +859,9 @@
 {
 	struct inode *inode;
 	int error;
-	struct task_struct *task = dir->u.proc_i.task;
+	struct task_struct *task = proc_task(dir);
 	struct pid_entry *p;
+	struct proc_inode *ei;
 
 	error = -ENOENT;
 	inode = NULL;
@@ -864,6 +880,7 @@
 	if (!inode)
 		goto out;
 
+	ei = PROC_I(inode);
 	inode->i_mode = p->mode;
 	/*
 	 * Yes, it does not scale. And it should not. Don't add
@@ -877,35 +894,35 @@
 			break;
 		case PROC_PID_EXE:
 			inode->i_op = &proc_pid_link_inode_operations;
-			inode->u.proc_i.op.proc_get_link = proc_exe_link;
+			ei->op.proc_get_link = proc_exe_link;
 			break;
 		case PROC_PID_CWD:
 			inode->i_op = &proc_pid_link_inode_operations;
-			inode->u.proc_i.op.proc_get_link = proc_cwd_link;
+			ei->op.proc_get_link = proc_cwd_link;
 			break;
 		case PROC_PID_ROOT:
 			inode->i_op = &proc_pid_link_inode_operations;
-			inode->u.proc_i.op.proc_get_link = proc_root_link;
+			ei->op.proc_get_link = proc_root_link;
 			break;
 		case PROC_PID_ENVIRON:
 			inode->i_fop = &proc_info_file_operations;
-			inode->u.proc_i.op.proc_read = proc_pid_environ;
+			ei->op.proc_read = proc_pid_environ;
 			break;
 		case PROC_PID_STATUS:
 			inode->i_fop = &proc_info_file_operations;
-			inode->u.proc_i.op.proc_read = proc_pid_status;
+			ei->op.proc_read = proc_pid_status;
 			break;
 		case PROC_PID_STAT:
 			inode->i_fop = &proc_info_file_operations;
-			inode->u.proc_i.op.proc_read = proc_pid_stat;
+			ei->op.proc_read = proc_pid_stat;
 			break;
 		case PROC_PID_CMDLINE:
 			inode->i_fop = &proc_info_file_operations;
-			inode->u.proc_i.op.proc_read = proc_pid_cmdline;
+			ei->op.proc_read = proc_pid_cmdline;
 			break;
 		case PROC_PID_STATM:
 			inode->i_fop = &proc_info_file_operations;
-			inode->u.proc_i.op.proc_read = proc_pid_statm;
+			ei->op.proc_read = proc_pid_statm;
 			break;
 		case PROC_PID_MAPS:
 			inode->i_fop = &proc_maps_operations;
@@ -913,7 +930,7 @@
 #ifdef CONFIG_SMP
 		case PROC_PID_CPU:
 			inode->i_fop = &proc_info_file_operations;
-			inode->u.proc_i.op.proc_read = proc_pid_cpu;
+			ei->op.proc_read = proc_pid_cpu;
 			break;
 #endif
 		case PROC_PID_MEM:
@@ -973,6 +990,7 @@
 	struct task_struct *task;
 	const char *name;
 	struct inode *inode;
+	struct proc_inode *ei;
 	int len;
 
 	pid = 0;
@@ -982,10 +1000,10 @@
 		inode = new_inode(dir->i_sb);
 		if (!inode)
 			return ERR_PTR(-ENOMEM);
+		ei = PROC_I(inode);
 		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 		inode->i_ino = fake_ino(0, PROC_PID_INO);
-		inode->u.proc_i.file = NULL;
-		inode->u.proc_i.task = NULL;
+		ei->pde = NULL;
 		inode->i_mode = S_IFLNK|S_IRWXUGO;
 		inode->i_uid = inode->i_gid = 0;
 		inode->i_size = 64;
@@ -1016,7 +1034,7 @@
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO);
 
-	free_task_struct(task);
+	put_task_struct(task);
 
 	if (!inode)
 		goto out;
@@ -1035,10 +1053,10 @@
 
 void proc_pid_delete_inode(struct inode *inode)
 {
-	if (inode->u.proc_i.file)
-		fput(inode->u.proc_i.file);
-	if (inode->u.proc_i.task)
-		free_task_struct(inode->u.proc_i.task);
+	if (PROC_I(inode)->file)
+		fput(PROC_I(inode)->file);
+	if (proc_task(inode))
+		put_task_struct(proc_task(inode));
 }
 
 #define PROC_NUMBUF 10
diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c
--- a/fs/proc/generic.c	Sun Feb 10 19:58:06 2002
+++ b/fs/proc/generic.c	Sun Feb 10 19:58:06 2002
@@ -11,7 +11,7 @@
 #include <asm/uaccess.h>
 
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #define __NO_VERSION__
@@ -58,7 +58,7 @@
 	char	*start;
 	struct proc_dir_entry * dp;
 
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
+	dp = PDE(inode);
 	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
 
@@ -128,7 +128,7 @@
 	struct inode *inode = file->f_dentry->d_inode;
 	struct proc_dir_entry * dp;
 	
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
+	dp = PDE(inode);
 
 	if (!dp->write_proc)
 		return -EIO;
@@ -221,13 +221,13 @@
 
 static int proc_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
-	char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
+	char *s=PDE(dentry->d_inode)->data;
 	return vfs_readlink(dentry, buffer, buflen, s);
 }
 
 static int proc_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
+	char *s=PDE(dentry->d_inode)->data;
 	return vfs_follow_link(nd, s);
 }
 
@@ -264,7 +264,7 @@
 
 	error = -ENOENT;
 	inode = NULL;
-	de = (struct proc_dir_entry *) dir->u.generic_ip;
+	de = PDE(dir);
 	if (de) {
 		for (de = de->subdir; de ; de = de->next) {
 			if (!de || !de->low_ino)
@@ -306,7 +306,7 @@
 	struct inode *inode = filp->f_dentry->d_inode;
 
 	ino = inode->i_ino;
-	de = (struct proc_dir_entry *) inode->u.generic_ip;
+	de = PDE(inode);
 	if (!de)
 		return -EINVAL;
 	i = filp->f_pos;
@@ -413,7 +413,7 @@
 		if (dentry->d_op != &proc_dentry_operations)
 			continue;
 		inode = dentry->d_inode;
-		if (inode->u.generic_ip != de)
+		if (PDE(inode) != de)
 			continue;
 		fops = filp->f_op;
 		filp->f_op = NULL;
diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c
--- a/fs/proc/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/proc/inode.c	Sun Feb 10 19:58:05 2002
@@ -4,7 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -16,6 +16,7 @@
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/smp_lock.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -58,7 +59,7 @@
  */
 static void proc_delete_inode(struct inode *inode)
 {
-	struct proc_dir_entry *de = inode->u.generic_ip;
+	struct proc_dir_entry *de = PDE(inode);
 
 	inode->i_state = I_CLEAR;
 
@@ -91,14 +92,51 @@
 	return 0;
 }
 
+static kmem_cache_t * proc_inode_cachep;
+
+static struct inode *proc_alloc_inode(struct super_block *sb)
+{
+	struct proc_inode *ei;
+	ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void proc_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(proc_inode_cachep, PROC_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct proc_inode *ei = (struct proc_inode *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+int __init proc_init_inodecache(void)
+{
+	proc_inode_cachep = kmem_cache_create("proc_inode_cache",
+					     sizeof(struct proc_inode),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (proc_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
 static struct super_operations proc_sops = { 
+	alloc_inode:	proc_alloc_inode,
+	destroy_inode:	proc_destroy_inode,
 	read_inode:	proc_read_inode,
 	put_inode:	force_delete,
 	delete_inode:	proc_delete_inode,
 	statfs:		proc_statfs,
 };
 
-
 static int parse_options(char *options,uid_t *uid,gid_t *gid)
 {
 	char *this_char,*value;
@@ -147,7 +185,7 @@
 	if (!inode)
 		goto out_fail;
 	
-	inode->u.generic_ip = (void *) de;
+	PROC_I(inode)->pde = de;
 	if (de) {
 		if (de->mode) {
 			inode->i_mode = de->mode;
@@ -176,8 +214,7 @@
 	goto out;
 }			
 
-struct super_block *proc_read_super(struct super_block *s,void *data, 
-				    int silent)
+int proc_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * root_inode;
 	struct task_struct *p;
@@ -200,11 +237,11 @@
 	if (!s->s_root)
 		goto out_no_root;
 	parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
-	return s;
+	return 0;
 
 out_no_root:
 	printk("proc_read_super: get root inode failed\n");
 	iput(root_inode);
-	return NULL;
+	return -ENOMEM;
 }
 MODULE_LICENSE("GPL");
diff -Nru a/fs/proc/kmsg.c b/fs/proc/kmsg.c
--- a/fs/proc/kmsg.c	Sun Feb 10 19:58:06 2002
+++ b/fs/proc/kmsg.c	Sun Feb 10 19:58:06 2002
@@ -7,9 +7,10 @@
 
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/poll.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -Nru a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
--- a/fs/proc/proc_devtree.c	Sun Feb 10 19:58:05 2002
+++ b/fs/proc/proc_devtree.c	Sun Feb 10 19:58:05 2002
@@ -4,7 +4,7 @@
  * Copyright 1997 Paul Mackerras
  */
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/string.h>
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Sun Feb 10 19:58:04 2002
+++ b/fs/proc/proc_misc.c	Sun Feb 10 19:58:04 2002
@@ -17,7 +17,7 @@
 
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
 #include <linux/tty.h>
@@ -50,9 +50,6 @@
  * have a way to deal with that gracefully. Right now I used straightforward
  * wrappers, but this needs further analysis wrt potential overflows.
  */
-#ifdef CONFIG_MODULES
-extern int get_module_list(char *);
-#endif
 extern int get_device_list(char *);
 extern int get_partition_list(char *, char **, off_t, int);
 extern int get_filesystem_list(char *);
@@ -203,13 +200,17 @@
 };
 
 #ifdef CONFIG_MODULES
-static int modules_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
+extern struct seq_operations modules_op;
+static int modules_open(struct inode *inode, struct file *file)
 {
-	int len = get_module_list(page);
-	return proc_calc_metrics(page, start, off, count, eof, len);
+	return seq_open(file, &modules_op);
 }
-
+static struct file_operations proc_modules_operations = {
+	open:		modules_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
 extern struct seq_operations ksyms_op;
 static int ksyms_open(struct inode *inode, struct file *file)
 {
@@ -223,6 +224,20 @@
 };
 #endif
 
+extern struct seq_operations slabinfo_op;
+extern ssize_t slabinfo_write(struct file *, const char *, size_t, loff_t *);
+static int slabinfo_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &slabinfo_op);
+}
+static struct file_operations proc_slabinfo_operations = {
+	open:		slabinfo_open,
+	read:		seq_read,
+	write:		slabinfo_write,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
+
 static int kstat_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
@@ -521,9 +536,6 @@
 		{"uptime",	uptime_read_proc},
 		{"meminfo",	meminfo_read_proc},
 		{"version",	version_read_proc},
-#ifdef CONFIG_MODULES
-		{"modules",	modules_read_proc},
-#endif
 		{"stat",	kstat_read_proc},
 		{"devices",	devices_read_proc},
 		{"partitions",	partitions_read_proc},
@@ -551,7 +563,9 @@
 		entry->proc_fops = &proc_kmsg_operations;
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
 	create_seq_entry("interrupts", 0, &proc_interrupts_operations);
+	create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 #ifdef CONFIG_MODULES
+	create_seq_entry("modules", 0, &proc_modules_operations);
 	create_seq_entry("ksyms", 0, &proc_ksyms_operations);
 #endif
 	proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
@@ -575,8 +589,4 @@
 			entry->proc_fops = &ppc_htab_operations;
 	}
 #endif
-	entry = create_proc_read_entry("slabinfo", S_IWUSR | S_IRUGO, NULL,
-				       slabinfo_read_proc, NULL);
-	if (entry)
-		entry->write_proc = slabinfo_write_proc;
 }
diff -Nru a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
--- a/fs/proc/proc_tty.c	Sun Feb 10 19:58:05 2002
+++ b/fs/proc/proc_tty.c	Sun Feb 10 19:58:05 2002
@@ -8,7 +8,7 @@
 
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/tty.h>
diff -Nru a/fs/proc/root.c b/fs/proc/root.c
--- a/fs/proc/root.c	Sun Feb 10 19:58:05 2002
+++ b/fs/proc/root.c	Sun Feb 10 19:58:05 2002
@@ -9,7 +9,7 @@
 #include <asm/uaccess.h>
 
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/config.h>
@@ -23,11 +23,24 @@
 struct proc_dir_entry *proc_sys_root;
 #endif
 
-static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE);
+static struct super_block *proc_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, proc_fill_super);
+}
+
+static struct file_system_type proc_fs_type = {
+	name:		"proc",
+	get_sb:		proc_get_sb,
+};
 
+extern int __init proc_init_inodecache(void);
 void __init proc_root_init(void)
 {
-	int err = register_filesystem(&proc_fs_type);
+	int err = proc_init_inodecache();
+	if (err)
+		return;
+	err = register_filesystem(&proc_fs_type);
 	if (err)
 		return;
 	proc_mnt = kern_mount(&proc_fs_type);
diff -Nru a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c
--- a/fs/qnx4/bitmap.c	Sun Feb 10 19:58:03 2002
+++ b/fs/qnx4/bitmap.c	Sun Feb 10 19:58:03 2002
@@ -14,7 +14,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/fs.h>
 #include <linux/qnx4_fs.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
diff -Nru a/fs/qnx4/file.c b/fs/qnx4/file.c
--- a/fs/qnx4/file.c	Sun Feb 10 19:58:05 2002
+++ b/fs/qnx4/file.c	Sun Feb 10 19:58:05 2002
@@ -15,7 +15,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/qnx4_fs.h>
 
 /*
diff -Nru a/fs/qnx4/fsync.c b/fs/qnx4/fsync.c
--- a/fs/qnx4/fsync.c	Sun Feb 10 19:58:05 2002
+++ b/fs/qnx4/fsync.c	Sun Feb 10 19:58:05 2002
@@ -12,7 +12,7 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/locks.h>
diff -Nru a/fs/qnx4/inode.c b/fs/qnx4/inode.c
--- a/fs/qnx4/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/qnx4/inode.c	Sun Feb 10 19:58:05 2002
@@ -119,7 +119,6 @@
 
 #endif
 
-static struct super_block *qnx4_read_super(struct super_block *, void *, int);
 static void qnx4_put_super(struct super_block *sb);
 static struct inode *qnx4_alloc_inode(struct super_block *sb);
 static void qnx4_destroy_inode(struct inode *inode);
@@ -337,8 +336,7 @@
 	return NULL;
 }
 
-static struct super_block *qnx4_read_super(struct super_block *s,
-					   void *data, int silent)
+static int qnx4_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct buffer_head *bh;
 	struct inode *root;
@@ -396,7 +394,7 @@
 
 	brelse(bh);
 
-	return s;
+	return 0;
 
       outi:
 	iput(root);
@@ -404,7 +402,7 @@
 	brelse(bh);
       outnobh:
 
-	return NULL;
+	return -EINVAL;
 }
 
 static void qnx4_put_super(struct super_block *sb)
@@ -541,7 +539,18 @@
 		       "qnx4_inode_cache: not all structures were freed\n");
 }
 
-static DECLARE_FSTYPE_DEV(qnx4_fs_type, "qnx4", qnx4_read_super);
+static struct super_block *qnx4_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super);
+}
+
+static struct file_system_type qnx4_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"qnx4",
+	get_sb:		qnx4_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_qnx4_fs(void)
 {
diff -Nru a/fs/qnx4/namei.c b/fs/qnx4/namei.c
--- a/fs/qnx4/namei.c	Sun Feb 10 19:58:04 2002
+++ b/fs/qnx4/namei.c	Sun Feb 10 19:58:04 2002
@@ -13,7 +13,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/fs.h>
 #include <linux/qnx4_fs.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c
--- a/fs/ramfs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ramfs/inode.c	Sun Feb 10 19:58:05 2002
@@ -302,7 +302,7 @@
 	put_inode:	force_delete,
 };
 
-static struct super_block *ramfs_read_super(struct super_block * sb, void * data, int silent)
+static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
 {
 	struct inode * inode;
 	struct dentry * root;
@@ -313,19 +313,33 @@
 	sb->s_op = &ramfs_ops;
 	inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0);
 	if (!inode)
-		return NULL;
+		return -ENOMEM;
 
 	root = d_alloc_root(inode);
 	if (!root) {
 		iput(inode);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root = root;
-	return sb;
+	return 0;
 }
 
-static DECLARE_FSTYPE(ramfs_fs_type, "ramfs", ramfs_read_super, FS_LITTER);
-static DECLARE_FSTYPE(rootfs_fs_type, "rootfs", ramfs_read_super, FS_NOMOUNT|FS_LITTER);
+static struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super);
+}
+
+static struct file_system_type ramfs_fs_type = {
+	name:		"ramfs",
+	get_sb:		ramfs_get_sb,
+	fs_flags:	FS_LITTER,
+};
+static struct file_system_type rootfs_fs_type = {
+	name:		"rootfs",
+	get_sb:		ramfs_get_sb,
+	fs_flags:	FS_NOMOUNT|FS_LITTER,
+};
 
 static int __init init_ramfs_fs(void)
 {
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	Sun Feb 10 19:58:04 2002
+++ b/fs/read_write.c	Sun Feb 10 19:58:04 2002
@@ -51,6 +51,31 @@
 	return retval;
 }
 
+loff_t remote_llseek(struct file *file, loff_t offset, int origin)
+{
+	long long retval;
+
+	lock_kernel();
+	switch (origin) {
+		case 2:
+			offset += file->f_dentry->d_inode->i_size;
+			break;
+		case 1:
+			offset += file->f_pos;
+	}
+	retval = -EINVAL;
+	if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
+		if (offset != file->f_pos) {
+			file->f_pos = offset;
+			file->f_reada = 0;
+			file->f_version = ++event;
+		}
+		retval = offset;
+	}
+	unlock_kernel();
+	return retval;
+}
+
 loff_t no_llseek(struct file *file, loff_t offset, int origin)
 {
 	return -ESPIPE;
diff -Nru a/fs/readdir.c b/fs/readdir.c
--- a/fs/readdir.c	Sun Feb 10 19:58:06 2002
+++ b/fs/readdir.c	Sun Feb 10 19:58:06 2002
@@ -4,12 +4,13 @@
  *  Copyright (C) 1995  Linus Torvalds
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/file.h>
 #include <linux/smp_lock.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 
diff -Nru a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
--- a/fs/reiserfs/bitmap.c	Sun Feb 10 19:58:04 2002
+++ b/fs/reiserfs/bitmap.c	Sun Feb 10 19:58:04 2002
@@ -3,7 +3,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/locks.h>
 #include <asm/bitops.h>
diff -Nru a/fs/reiserfs/buffer2.c b/fs/reiserfs/buffer2.c
--- a/fs/reiserfs/buffer2.c	Sun Feb 10 19:58:05 2002
+++ b/fs/reiserfs/buffer2.c	Sun Feb 10 19:58:05 2002
@@ -3,7 +3,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/locks.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
diff -Nru a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
--- a/fs/reiserfs/dir.c	Sun Feb 10 19:58:03 2002
+++ b/fs/reiserfs/dir.c	Sun Feb 10 19:58:03 2002
@@ -76,7 +76,7 @@
 		
 	/* we must have found item, that is item of this directory, */
 	RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key),
-		"vs-9000: found item %h does not match to dir we readdir %k",
+		"vs-9000: found item %h does not match to dir we readdir %K",
 		ih, &pos_key);
 	RFALSE( item_num > B_NR_ITEMS (bh) - 1,
 		"vs-9005 item_num == %d, item amount == %d", 
diff -Nru a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
--- a/fs/reiserfs/do_balan.c	Sun Feb 10 19:58:04 2002
+++ b/fs/reiserfs/do_balan.c	Sun Feb 10 19:58:04 2002
@@ -18,7 +18,7 @@
 
 #include <linux/config.h>
 #include <asm/uaccess.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 
 #ifdef CONFIG_REISERFS_CHECK
diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c
--- a/fs/reiserfs/file.c	Sun Feb 10 19:58:03 2002
+++ b/fs/reiserfs/file.c	Sun Feb 10 19:58:03 2002
@@ -3,7 +3,7 @@
  */
 
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
 
diff -Nru a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
--- a/fs/reiserfs/fix_node.c	Sun Feb 10 19:58:05 2002
+++ b/fs/reiserfs/fix_node.c	Sun Feb 10 19:58:05 2002
@@ -36,7 +36,7 @@
 
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/reiserfs_fs.h>
@@ -2356,7 +2356,6 @@
     for ( n_h = 0; n_h < MAX_HEIGHT && p_s_tb->insert_size[n_h]; n_h++ ) { 
 	if ( (n_ret_value = get_direct_parent(p_s_tb, n_h)) != CARRY_ON ) {
 	    goto repeat;
-	    return n_ret_value;
 	}
 
 	if ( (n_ret_value = check_balance (n_op_mode, p_s_tb, n_h, n_item_num,
@@ -2365,7 +2364,6 @@
 		/* No balancing for higher levels needed. */
 		if ( (n_ret_value = get_neighbors(p_s_tb, n_h)) != CARRY_ON ) {
 		    goto repeat;
-		    return n_ret_value;
 		}
 		if ( n_h != MAX_HEIGHT - 1 )  
 		    p_s_tb->insert_size[n_h + 1] = 0;
@@ -2373,17 +2371,14 @@
 		break;
 	    }
 	    goto repeat;
-	    return n_ret_value;
 	}
 
 	if ( (n_ret_value = get_neighbors(p_s_tb, n_h)) != CARRY_ON ) {
 	    goto repeat;
-	    return n_ret_value;
 	}
 
 	if ( (n_ret_value = get_empty_nodes(p_s_tb, n_h)) != CARRY_ON ) {
-	    goto repeat;
-	    return n_ret_value; /* No disk space, or schedule occurred and
+	    goto repeat;        /* No disk space, or schedule occurred and
 				   analysis may be invalid and needs to be redone. */
 	}
     
diff -Nru a/fs/reiserfs/ibalance.c b/fs/reiserfs/ibalance.c
--- a/fs/reiserfs/ibalance.c	Sun Feb 10 19:58:03 2002
+++ b/fs/reiserfs/ibalance.c	Sun Feb 10 19:58:03 2002
@@ -5,7 +5,7 @@
 #include <linux/config.h>
 #include <asm/uaccess.h>
 #include <linux/string.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 
 /* this is one and only function that is used outside (do_balance.c) */
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	Sun Feb 10 19:58:05 2002
+++ b/fs/reiserfs/inode.c	Sun Feb 10 19:58:05 2002
@@ -3,7 +3,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
@@ -743,7 +743,8 @@
 
 		retval = convert_tail_for_hole(inode, bh_result, tail_offset) ;
 		if (retval) {
-		    printk("clm-6004: convert tail failed inode %lu, error %d\n", inode->i_ino, retval) ;
+		    if ( retval != -ENOSPC )
+			printk("clm-6004: convert tail failed inode %lu, error %d\n", inode->i_ino, retval) ;
 		    if (allocated_block_nr)
 			reiserfs_free_block (&th, allocated_block_nr);
 		    goto failure ;
@@ -888,6 +889,15 @@
     copy_key (INODE_PKEY (inode), &(ih->ih_key));
     inode->i_blksize = PAGE_SIZE;
 
+    INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list ));
+    REISERFS_I(inode)->i_flags = 0;
+    REISERFS_I(inode)->i_prealloc_block = 0;
+    REISERFS_I(inode)->i_prealloc_count = 0;
+    REISERFS_I(inode)->i_trans_id = 0;
+    REISERFS_I(inode)->i_trans_index = 0;
+    /* nopack = 0, by default */
+    REISERFS_I(inode)->i_flags &= ~i_nopack_mask;
+
     if (stat_data_v1 (ih)) {
 	struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
 	unsigned long blocks;
@@ -947,13 +957,6 @@
 	    set_inode_item_key_version (inode, KEY_FORMAT_3_6);
 	REISERFS_I(inode)->i_first_direct_byte = 0;
     }
-    REISERFS_I(inode)->i_flags = 0;
-    REISERFS_I(inode)->i_prealloc_block = 0;
-    REISERFS_I(inode)->i_prealloc_count = 0;
-    REISERFS_I(inode)->i_trans_id = 0;
-    REISERFS_I(inode)->i_trans_index = 0;
-    /* nopack = 0, by default */
-    REISERFS_I(inode)->i_flags &= ~i_nopack_mask;
 
     pathrelse (path);
     if (S_ISREG (inode->i_mode)) {
@@ -1152,6 +1155,7 @@
 	/* a stale NFS handle can trigger this without it being an error */
 	pathrelse (&path_to_sd);
 	make_bad_inode(inode) ;
+	inode->i_nlink = 0;
 	return;
     }
 
@@ -1184,6 +1188,27 @@
 
 }
 
+/**
+ * reiserfs_find_actor() - "find actor" reiserfs supplies to iget4().
+ *
+ * @inode:    inode from hash table to check
+ * @inode_no: inode number we are looking for
+ * @opaque:   "cookie" passed to iget4(). This is &reiserfs_iget4_args.
+ *
+ * This function is called by iget4() to distinguish reiserfs inodes
+ * having the same inode numbers. Such inodes can only exist due to some
+ * error condition. One of them should be bad. Inodes with identical
+ * inode numbers (objectids) are distinguished by parent directory ids.
+ *
+ */
+static int reiserfs_find_actor( struct inode *inode, 
+				unsigned long inode_no, void *opaque )
+{
+    struct reiserfs_iget4_args *args;
+
+    args = opaque;
+    return INODE_PKEY( inode ) -> k_dir_id == args -> objectid;
+}
 
 struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key)
 {
@@ -1191,7 +1216,8 @@
     struct reiserfs_iget4_args args ;
 
     args.objectid = key->on_disk_key.k_dir_id ;
-    inode = iget4 (s, key->on_disk_key.k_objectid, 0, (void *)(&args));
+    inode = iget4 (s, key->on_disk_key.k_objectid, 
+		   reiserfs_find_actor, (void *)(&args));
     if (!inode) 
 	return ERR_PTR(-ENOMEM) ;
 
@@ -1532,6 +1558,7 @@
     REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 : 
       U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/;
 
+    INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list ));
     REISERFS_I(inode)->i_flags = 0;
     REISERFS_I(inode)->i_prealloc_block = 0;
     REISERFS_I(inode)->i_prealloc_count = 0;
diff -Nru a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
--- a/fs/reiserfs/ioctl.c	Sun Feb 10 19:58:05 2002
+++ b/fs/reiserfs/ioctl.c	Sun Feb 10 19:58:05 2002
@@ -4,7 +4,7 @@
 
 #include <linux/fs.h>
 #include <linux/reiserfs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <asm/uaccess.h>
 #include <linux/smp_lock.h>
 #include <linux/locks.h>
diff -Nru a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c
--- a/fs/reiserfs/item_ops.c	Sun Feb 10 19:58:04 2002
+++ b/fs/reiserfs/item_ops.c	Sun Feb 10 19:58:04 2002
@@ -2,7 +2,7 @@
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 
 // this contains item handlers for old item types: sd, direct,
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	Sun Feb 10 19:58:04 2002
+++ b/fs/reiserfs/journal.c	Sun Feb 10 19:58:04 2002
@@ -45,7 +45,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <asm/semaphore.h>
 
 #include <linux/vmalloc.h>
@@ -797,7 +797,7 @@
   while(cn) {
     if (cn->blocknr != 0) {
       if (debug) {
-        printk("block %lu, bh is %d, state %d\n", cn->blocknr, cn->bh ? 1: 0, 
+        printk("block %lu, bh is %d, state %ld\n", cn->blocknr, cn->bh ? 1: 0, 
 	        cn->state) ;
       }
       cn->state = 0 ;
diff -Nru a/fs/reiserfs/lbalance.c b/fs/reiserfs/lbalance.c
--- a/fs/reiserfs/lbalance.c	Sun Feb 10 19:58:06 2002
+++ b/fs/reiserfs/lbalance.c	Sun Feb 10 19:58:06 2002
@@ -5,7 +5,7 @@
 #include <linux/config.h>
 #include <asm/uaccess.h>
 #include <linux/string.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 
 /* these are used in do_balance.c */
diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
--- a/fs/reiserfs/namei.c	Sun Feb 10 19:58:03 2002
+++ b/fs/reiserfs/namei.c	Sun Feb 10 19:58:03 2002
@@ -12,7 +12,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/bitops.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
@@ -470,7 +470,7 @@
     if (gen_number != 0) {	/* we need to re-search for the insertion point */
       if (search_by_entry_key (dir->i_sb, &entry_key, &path, &de) != NAME_NOT_FOUND) {
             reiserfs_warning ("vs-7032: reiserfs_add_entry: "
-                            "entry with this key (%k) already exists\n", &entry_key);
+                            "entry with this key (%K) already exists\n", &entry_key);
 
 	    if (buffer != small_buf)
 		reiserfs_kfree (buffer, buflen, dir->i_sb);
diff -Nru a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c
--- a/fs/reiserfs/objectid.c	Sun Feb 10 19:58:05 2002
+++ b/fs/reiserfs/objectid.c	Sun Feb 10 19:58:05 2002
@@ -6,7 +6,7 @@
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/random.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_fs_sb.h>
 
diff -Nru a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
--- a/fs/reiserfs/prints.c	Sun Feb 10 19:58:04 2002
+++ b/fs/reiserfs/prints.c	Sun Feb 10 19:58:04 2002
@@ -3,7 +3,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/string.h>
diff -Nru a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
--- a/fs/reiserfs/procfs.c	Sun Feb 10 19:58:05 2002
+++ b/fs/reiserfs/procfs.c	Sun Feb 10 19:58:05 2002
@@ -12,7 +12,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <asm/uaccess.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_fs_sb.h>
@@ -465,7 +465,7 @@
  			"jp_journal_max_trans_age: \t%i\n"
 			/* incore fields */
 			"j_1st_reserved_block: \t%i\n"	  
-			"j_state: \t%i\n"			
+			"j_state: \t%li\n"			
 			"j_trans_id: \t%lu\n"
 			"j_mount_id: \t%lu\n"
 			"j_start: \t%lu\n"
diff -Nru a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
--- a/fs/reiserfs/stree.c	Sun Feb 10 19:58:04 2002
+++ b/fs/reiserfs/stree.c	Sun Feb 10 19:58:04 2002
@@ -54,7 +54,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/pagemap.h>
@@ -126,19 +126,19 @@
   retval = comp_short_keys (le_key, cpu_key);
   if (retval)
       return retval;
-  if (le_key_k_offset (cpu_key->version, le_key) < cpu_key_k_offset (cpu_key))
+  if (le_key_k_offset (le_key_version(le_key), le_key) < cpu_key_k_offset (cpu_key))
       return -1;
-  if (le_key_k_offset (cpu_key->version, le_key) > cpu_key_k_offset (cpu_key))
+  if (le_key_k_offset (le_key_version(le_key), le_key) > cpu_key_k_offset (cpu_key))
       return 1;
 
   if (cpu_key->key_length == 3)
       return 0;
 
   /* this part is needed only when tail conversion is in progress */
-  if (le_key_k_type (cpu_key->version, le_key) < cpu_key_k_type (cpu_key))
+  if (le_key_k_type (le_key_version(le_key), le_key) < cpu_key_k_type (cpu_key))
     return -1;
 
-  if (le_key_k_type (cpu_key->version, le_key) > cpu_key_k_type (cpu_key))
+  if (le_key_k_type (le_key_version(le_key), le_key) > cpu_key_k_type (cpu_key))
     return 1;
 
   return 0;
@@ -166,7 +166,7 @@
     if (cpu_key_k_offset (key1) > cpu_key_k_offset (key2))
 	return 1;
 
-    reiserfs_warning ("comp_cpu_keys: type are compared for %k and %k\n",
+    reiserfs_warning ("comp_cpu_keys: type are compared for %K and %K\n",
 		      key1, key2);
 
     if (cpu_key_k_type (key1) < cpu_key_k_type (key2))
@@ -1338,8 +1338,10 @@
 	}
 	if (retval != ITEM_FOUND) {
 	    pathrelse (&path);
-	    reiserfs_warning ("vs-5355: reiserfs_delete_solid_item: %k not found",
-			      key);
+	    // No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir
+	    if ( !( (unsigned long long) GET_HASH_VALUE (le_key_k_offset (le_key_version (key), key)) == 0 && \
+		 (unsigned long long) GET_GENERATION_NUMBER (le_key_k_offset (le_key_version (key), key)) == 1 ) )
+		reiserfs_warning ("vs-5355: reiserfs_delete_solid_item: %k not found", key);
 	    break;
 	}
 	if (!tb_init) {
@@ -1522,7 +1524,7 @@
 	    set_cpu_key_k_offset (p_s_item_key, n_new_file_size + 1);
 	    if ( search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND ){
 		print_block (PATH_PLAST_BUFFER (p_s_path), 3, PATH_LAST_POSITION (p_s_path) - 1, PATH_LAST_POSITION (p_s_path) + 1);
-		reiserfs_panic(p_s_sb, "PAP-5580: reiserfs_cut_from_item: item to convert does not exist (%k)", p_s_item_key);
+		reiserfs_panic(p_s_sb, "PAP-5580: reiserfs_cut_from_item: item to convert does not exist (%K)", p_s_item_key);
 	    }
 	    continue;
 	}
@@ -1716,7 +1718,7 @@
 	}
 
 	RFALSE( n_deleted > n_file_size,
-		"PAP-5670: reiserfs_truncate_file returns too big number: deleted %d, file_size %lu, item_key %k",
+		"PAP-5670: reiserfs_truncate_file returns too big number: deleted %d, file_size %lu, item_key %K",
 		n_deleted, n_file_size, &s_item_key);
 
 	/* Change key to search the last file item. */
diff -Nru a/fs/reiserfs/super.c b/fs/reiserfs/super.c
--- a/fs/reiserfs/super.c	Sun Feb 10 19:58:06 2002
+++ b/fs/reiserfs/super.c	Sun Feb 10 19:58:06 2002
@@ -13,7 +13,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <asm/uaccess.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
@@ -284,7 +284,8 @@
     /* look for its place in the tree */
     retval = search_item (inode->i_sb, &key, &path);
     if (retval != ITEM_NOT_FOUND) {
-	reiserfs_warning ("vs-2100: add_save_link:"
+	if ( retval != -ENOSPC )
+	    reiserfs_warning ("vs-2100: add_save_link:"
 			  "search_by_key (%K) returned %d\n", &key, retval);
 	pathrelse (&path);
 	return;
@@ -748,6 +749,14 @@
 	return 1;
     }
 
+    if ( rs->s_v1.s_root_block == -1 ) {
+       brelse(bh) ;
+       printk("dev %s: Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
+              "reiserfsck --rebuild-tree and wait for a completion. If that fais\n"
+              "get newer reiserfsprogs package\n", kdevname (s->s_dev));
+       return 1;
+    }
+
     SB_BUFFER_WITH_SB (s) = bh;
     SB_DISK_SUPER_BLOCK (s) = rs;
 
@@ -956,7 +965,7 @@
 // at the ext2 code and comparing. It's subfunctions contain no code
 // used as a template unless they are so labeled.
 //
-static struct super_block * reiserfs_read_super (struct super_block * s, void * data, int silent)
+static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 {
     int size;
     struct inode *root_inode;
@@ -972,12 +981,12 @@
     memset (&s->u.reiserfs_sb, 0, sizeof (struct reiserfs_sb_info));
     jdev_name = NULL;
     if (parse_options ((char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks, &jdev_name) == 0) {
-	return NULL;
+	return -EINVAL;
     }
 
     if (blocks) {
   	printk("reserfs: resize option for remount only\n");
-	return NULL;
+	return -EINVAL;
     }	
 
     size = block_size(s->s_dev);
@@ -988,14 +997,14 @@
       old_format = 1;
     /* try new format (64-th 1k block), which can contain reiserfs super block */
     else if (read_super_block (s, REISERFS_DISK_OFFSET_IN_BYTES)) {
-      printk("sh-2021: reiserfs_read_super: can not find reiserfs on %s\n", s->s_id);
+      printk("sh-2021: reiserfs_fill_super: can not find reiserfs on %s\n", s->s_id);
       goto error;    
     }
     s->u.reiserfs_sb.s_mount_state = SB_REISERFS_STATE(s);
     s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ;
 
     if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) { 
-	printk ("reiserfs_read_super: unable to read bitmap\n");
+	printk ("reiserfs_fill_super: unable to read bitmap\n");
 	goto error;
     }
 #ifdef CONFIG_REISERFS_CHECK
@@ -1005,7 +1014,7 @@
 
     // set_device_ro(s->s_dev, 1) ;
     if( journal_init(s, jdev_name, old_format) ) {
-	printk("sh-2022: reiserfs_read_super: unable to initialize journal space\n") ;
+	printk("sh-2022: reiserfs_fill_super: unable to initialize journal space\n") ;
 	goto error ;
     } else {
 	jinit_done = 1 ; /* once this is set, journal_release must be called
@@ -1013,7 +1022,7 @@
 			 */
     }
     if (reread_meta_blocks(s)) {
-	printk("reiserfs_read_super: unable to reread meta blocks after journal init\n") ;
+	printk("reiserfs_fill_super: unable to reread meta blocks after journal init\n") ;
 	goto error ;
     }
 
@@ -1027,7 +1036,7 @@
     args.objectid = REISERFS_ROOT_PARENT_OBJECTID ;
     root_inode = iget4 (s, REISERFS_ROOT_OBJECTID, 0, (void *)(&args));
     if (!root_inode) {
-	printk ("reiserfs_read_super: get root inode failed\n");
+	printk ("reiserfs_fill_super: get root inode failed\n");
 	goto error;
     }
 
@@ -1106,7 +1115,7 @@
     reiserfs_proc_register( s, "journal", reiserfs_journal_in_proc );
     init_waitqueue_head (&(s->u.reiserfs_sb.s_wait));
 
-    return s;
+    return 0;
 
  error:
     if (jinit_done) { /* kill the commit thread, free journal ram */
@@ -1123,7 +1132,7 @@
     if (SB_BUFFER_WITH_SB (s))
 	brelse(SB_BUFFER_WITH_SB (s));
 
-    return NULL;
+    return -EINVAL;
 }
 
 
@@ -1150,7 +1159,18 @@
   return 0;
 }
 
-static DECLARE_FSTYPE_DEV(reiserfs_fs_type,"reiserfs",reiserfs_read_super);
+static struct super_block *reiserfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super);
+}
+
+static struct file_system_type reiserfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"reiserfs",
+	get_sb:		reiserfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 //
 // this is exactly what 2.3.99-pre9's init_ext2_fs is
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
--- a/fs/reiserfs/tail_conversion.c	Sun Feb 10 19:58:06 2002
+++ b/fs/reiserfs/tail_conversion.c	Sun Feb 10 19:58:06 2002
@@ -3,7 +3,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/pagemap.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/locks.h>
@@ -90,10 +90,10 @@
            last item of the file */
 	if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND )
 	    reiserfs_panic (sb, "PAP-14050: direct2indirect: "
-			    "direct item (%k) not found", &end_key);
+			    "direct item (%K) not found", &end_key);
 	p_le_ih = PATH_PITEM_HEAD (path);
 	RFALSE( !is_direct_le_ih (p_le_ih),
-	        "vs-14055: direct item expected(%k), found %h",
+	        "vs-14055: direct item expected(%K), found %h",
                 &end_key, p_le_ih);
         tail_size = (le_ih_k_offset (p_le_ih) & (n_blk_size - 1))
             + ih_item_len(p_le_ih) - 1;
@@ -228,7 +228,7 @@
 	/* re-search indirect item */
 	if ( search_for_position_by_key (p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND )
 	    reiserfs_panic(p_s_sb, "PAP-5520: indirect2direct: "
-			   "item to be converted %k does not exist", p_s_item_key);
+			   "item to be converted %K does not exist", p_s_item_key);
 	copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
 #ifdef CONFIG_REISERFS_CHECK
 	pos = le_ih_k_offset (&s_ih) - 1 + 
diff -Nru a/fs/romfs/inode.c b/fs/romfs/inode.c
--- a/fs/romfs/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/romfs/inode.c	Sun Feb 10 19:58:04 2002
@@ -92,8 +92,7 @@
 
 static struct super_operations romfs_ops;
 
-static struct super_block *
-romfs_read_super(struct super_block *s, void *data, int silent)
+static int romfs_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct buffer_head *bh;
 	struct romfs_super_block *rsb;
@@ -150,10 +149,10 @@
 out:
 		brelse(bh);
 outnobh:
-		s = NULL;
+		return -EINVAL;
 	}
 
-	return s;
+	return 0;
 }
 
 /* That's simple too. */
@@ -529,7 +528,18 @@
 	statfs:		romfs_statfs,
 };
 
-static DECLARE_FSTYPE_DEV(romfs_fs_type, "romfs", romfs_read_super);
+static struct super_block *romfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super);
+}
+
+static struct file_system_type romfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"romfs",
+	get_sb:		romfs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_romfs_fs(void)
 {
diff -Nru a/fs/select.c b/fs/select.c
--- a/fs/select.c	Sun Feb 10 19:58:04 2002
+++ b/fs/select.c	Sun Feb 10 19:58:04 2002
@@ -19,6 +19,7 @@
 #include <linux/poll.h>
 #include <linux/personality.h> /* for STICKY_TIMEOUTS */
 #include <linux/file.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 
diff -Nru a/fs/smbfs/cache.c b/fs/smbfs/cache.c
--- a/fs/smbfs/cache.c	Sun Feb 10 19:58:03 2002
+++ b/fs/smbfs/cache.c	Sun Feb 10 19:58:03 2002
@@ -9,7 +9,7 @@
  * Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -Nru a/fs/smbfs/dir.c b/fs/smbfs/dir.c
--- a/fs/smbfs/dir.c	Sun Feb 10 19:58:06 2002
+++ b/fs/smbfs/dir.c	Sun Feb 10 19:58:06 2002
@@ -7,7 +7,7 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
diff -Nru a/fs/smbfs/file.c b/fs/smbfs/file.c
--- a/fs/smbfs/file.c	Sun Feb 10 19:58:06 2002
+++ b/fs/smbfs/file.c	Sun Feb 10 19:58:06 2002
@@ -7,7 +7,7 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -381,7 +381,7 @@
 
 struct file_operations smb_file_operations =
 {
-	llseek:		generic_file_llseek,
+	llseek:		remote_llseek,
 	read:		smb_file_read,
 	write:		smb_file_write,
 	ioctl:		smb_ioctl,
diff -Nru a/fs/smbfs/inode.c b/fs/smbfs/inode.c
--- a/fs/smbfs/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/smbfs/inode.c	Sun Feb 10 19:58:04 2002
@@ -9,7 +9,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -460,8 +460,7 @@
 	}
 }
 
-struct super_block *
-smb_read_super(struct super_block *sb, void *raw_data, int silent)
+int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
 {
 	struct smb_sb_info *server = &sb->u.smbfs_sb;
 	struct smb_mount_data_kernel *mnt;
@@ -561,7 +560,7 @@
 		goto out_no_root;
 	smb_new_dentry(sb->s_root);
 
-	return sb;
+	return 0;
 
 out_no_root:
 	iput(root_inode);
@@ -573,15 +572,15 @@
 	smb_vfree(server->packet);
 out_no_mem:
 	if (!server->mnt)
-		printk(KERN_ERR "smb_read_super: allocation failure\n");
+		printk(KERN_ERR "smb_fill_super: allocation failure\n");
 	goto out_fail;
 out_wrong_data:
 	printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
 	goto out_fail;
 out_no_data:
-	printk(KERN_ERR "smb_read_super: missing data argument\n");
+	printk(KERN_ERR "smb_fill_super: missing data argument\n");
 out_fail:
-	return NULL;
+	return -EINVAL;
 }
 
 static int
@@ -706,7 +705,17 @@
 int smb_current_vmalloced;
 #endif
 
-static DECLARE_FSTYPE( smb_fs_type, "smbfs", smb_read_super, 0);
+static struct super_block *smb_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, smb_fill_super);
+}
+
+static struct file_system_type smb_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"smbfs",
+	get_sb:		smb_get_sb,
+};
 
 static int __init init_smb_fs(void)
 {
diff -Nru a/fs/smbfs/ioctl.c b/fs/smbfs/ioctl.c
--- a/fs/smbfs/ioctl.c	Sun Feb 10 19:58:04 2002
+++ b/fs/smbfs/ioctl.c	Sun Feb 10 19:58:04 2002
@@ -10,7 +10,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/highuid.h>
 
diff -Nru a/fs/smbfs/proto.h b/fs/smbfs/proto.h
--- a/fs/smbfs/proto.h	Sun Feb 10 19:58:04 2002
+++ b/fs/smbfs/proto.h	Sun Feb 10 19:58:04 2002
@@ -53,7 +53,6 @@
 extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
 extern void smb_invalidate_inodes(struct smb_sb_info *server);
 extern int smb_revalidate_inode(struct dentry *dentry);
-extern struct super_block *smb_read_super(struct super_block *sb, void *raw_data, int silent);
 extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
 /* file.c */
 extern struct address_space_operations smb_file_aops;
diff -Nru a/fs/smbfs/sock.c b/fs/smbfs/sock.c
--- a/fs/smbfs/sock.c	Sun Feb 10 19:58:05 2002
+++ b/fs/smbfs/sock.c	Sun Feb 10 19:58:05 2002
@@ -7,7 +7,8 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
-#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/socket.h>
 #include <linux/fcntl.h>
@@ -176,7 +177,7 @@
 smb_valid_socket(struct inode * inode)
 {
 	return (inode && S_ISSOCK(inode->i_mode) && 
-		inode->u.socket_i.type == SOCK_STREAM);
+		SOCKET_I(inode)->type == SOCK_STREAM);
 }
 
 static struct socket *
@@ -190,7 +191,7 @@
 		if (!smb_valid_socket(file->f_dentry->d_inode))
 			PARANOIA("bad socket!\n");
 #endif
-		return &file->f_dentry->d_inode->u.socket_i;
+		return SOCKET_I(file->f_dentry->d_inode);
 	}
 	return NULL;
 }
diff -Nru a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c	Sun Feb 10 19:58:04 2002
+++ b/fs/stat.c	Sun Feb 10 19:58:04 2002
@@ -10,6 +10,7 @@
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/highuid.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 
@@ -25,68 +26,28 @@
 	return 0;
 }
 
-
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
-
-/*
- * For backward compatibility?  Maybe this should be moved
- * into arch/i386 instead?
- */
-static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
+static int do_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-	static int warncount = 5;
-	struct __old_kernel_stat tmp;
-
-	if (warncount > 0) {
-		warncount--;
-		printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
-			current->comm);
-	} else if (warncount < 0) {
-		/* it's laughable, but... */
-		warncount = 0;
-	}
-
-	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
-	tmp.st_ino = inode->i_ino;
-	tmp.st_mode = inode->i_mode;
-	tmp.st_nlink = inode->i_nlink;
-	SET_OLDSTAT_UID(tmp, inode->i_uid);
-	SET_OLDSTAT_GID(tmp, inode->i_gid);
-	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
-#if BITS_PER_LONG == 32
-	if (inode->i_size > MAX_NON_LFS)
-		return -EOVERFLOW;
-#endif	
-	tmp.st_size = inode->i_size;
-	tmp.st_atime = inode->i_atime;
-	tmp.st_mtime = inode->i_mtime;
-	tmp.st_ctime = inode->i_ctime;
-	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
-}
-
-#endif
-
-static int cp_new_stat(struct inode * inode, struct stat * statbuf)
-{
-	struct stat tmp;
+	int res = 0;
 	unsigned int blocks, indirect;
+	struct inode *inode = dentry->d_inode;
 
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
-	tmp.st_ino = inode->i_ino;
-	tmp.st_mode = inode->i_mode;
-	tmp.st_nlink = inode->i_nlink;
-	SET_STAT_UID(tmp, inode->i_uid);
-	SET_STAT_GID(tmp, inode->i_gid);
-	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
-#if BITS_PER_LONG == 32
-	if (inode->i_size > MAX_NON_LFS)
-		return -EOVERFLOW;
-#endif	
-	tmp.st_size = inode->i_size;
-	tmp.st_atime = inode->i_atime;
-	tmp.st_mtime = inode->i_mtime;
-	tmp.st_ctime = inode->i_ctime;
+	res = do_revalidate(dentry);
+	if (res)
+		return res;
+
+	stat->dev = kdev_t_to_nr(inode->i_dev);
+	stat->ino = inode->i_ino;
+	stat->mode = inode->i_mode;
+	stat->nlink = inode->i_nlink;
+	stat->uid = inode->i_uid;
+	stat->gid = inode->i_gid;
+	stat->rdev = kdev_t_to_nr(inode->i_rdev);
+	stat->atime = inode->i_atime;
+	stat->mtime = inode->i_mtime;
+	stat->ctime = inode->i_ctime;
+	stat->ctime = inode->i_ctime;
+	stat->size = inode->i_size;
 /*
  * st_blocks and st_blksize are approximated with a simple algorithm if
  * they aren't supported directly by the filesystem. The minix and msdos
@@ -106,7 +67,7 @@
 #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
 
 	if (!inode->i_blksize) {
-		blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+		blocks = (stat->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
 		if (blocks > D_B) {
 			indirect = (blocks - D_B + I_B - 1) / I_B;
 			blocks += indirect;
@@ -117,130 +78,178 @@
 					blocks++;
 			}
 		}
-		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-		tmp.st_blksize = BLOCK_SIZE;
+		stat->blocks = (BLOCK_SIZE / 512) * blocks;
+		stat->blksize = BLOCK_SIZE;
 	} else {
-		tmp.st_blocks = inode->i_blocks;
-		tmp.st_blksize = inode->i_blksize;
+		stat->blocks = inode->i_blocks;
+		stat->blksize = inode->i_blksize;
 	}
-	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+	return 0;
 }
 
-
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
-/*
- * For backward compatibility?  Maybe this should be moved
- * into arch/i386 instead?
- */
-asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
+int vfs_stat(char *name, struct kstat *stat)
 {
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(filename, &nd);
+	error = user_path_walk(name, &nd);
 	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_old_stat(nd.dentry->d_inode, statbuf);
+		error = do_getattr(nd.mnt, nd.dentry, stat);
 		path_release(&nd);
 	}
 	return error;
 }
-#endif
 
-asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
+int vfs_lstat(char *name, struct kstat *stat)
 {
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(filename, &nd);
+	error = user_path_walk_link(name, &nd);
 	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat(nd.dentry->d_inode, statbuf);
+		error = do_getattr(nd.mnt, nd.dentry, stat);
 		path_release(&nd);
 	}
 	return error;
 }
 
+int vfs_fstat(unsigned int fd, struct kstat *stat)
+{
+	struct file *f = fget(fd);
+	int error = -EBADF;
+
+	if (f) {
+		error = do_getattr(f->f_vfsmnt, f->f_dentry, stat);
+		fput(f);
+	}
+	return error;
+}
+
 #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
 
 /*
  * For backward compatibility?  Maybe this should be moved
  * into arch/i386 instead?
  */
-asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
+static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat * statbuf)
 {
-	struct nameidata nd;
-	int error;
+	static int warncount = 5;
+	struct __old_kernel_stat tmp;
 
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_old_stat(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
+	if (warncount > 0) {
+		warncount--;
+		printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
+			current->comm);
+	} else if (warncount < 0) {
+		/* it's laughable, but... */
+		warncount = 0;
 	}
-	return error;
-}
 
-#endif
+	tmp.st_dev = stat->dev;
+	tmp.st_ino = stat->ino;
+	tmp.st_mode = stat->mode;
+	tmp.st_nlink = stat->nlink;
+	SET_OLDSTAT_UID(tmp, stat->uid);
+	SET_OLDSTAT_GID(tmp, stat->gid);
+	tmp.st_rdev = stat->rdev;
+#if BITS_PER_LONG == 32
+	if (stat->size > MAX_NON_LFS)
+		return -EOVERFLOW;
+#endif	
+	tmp.st_size = stat->size;
+	tmp.st_atime = stat->atime;
+	tmp.st_mtime = stat->mtime;
+	tmp.st_ctime = stat->ctime;
+	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
 
-asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
+asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
+
+	if (!error)
+		error = cp_old_stat(&stat, statbuf);
 
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
 	return error;
 }
+asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
+{
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
 
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
+	if (!error)
+		error = cp_old_stat(&stat, statbuf);
 
-/*
- * For backward compatibility?  Maybe this should be moved
- * into arch/i386 instead?
- */
+	return error;
+}
 asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
 {
-	struct file * f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
+	if (!error)
+		error = cp_old_stat(&stat, statbuf);
 
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_old_stat(dentry->d_inode, statbuf);
-		fput(f);
-	}
-	return err;
+	return error;
 }
 
 #endif
 
+static int cp_new_stat(struct kstat *stat, struct stat *statbuf)
+{
+	struct stat tmp;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.st_dev = stat->dev;
+	tmp.st_ino = stat->ino;
+	tmp.st_mode = stat->mode;
+	tmp.st_nlink = stat->nlink;
+	SET_STAT_UID(tmp, stat->uid);
+	SET_STAT_GID(tmp, stat->gid);
+	tmp.st_rdev = stat->rdev;
+#if BITS_PER_LONG == 32
+	if (stat->size > MAX_NON_LFS)
+		return -EOVERFLOW;
+#endif	
+	tmp.st_size = stat->size;
+	tmp.st_atime = stat->atime;
+	tmp.st_mtime = stat->mtime;
+	tmp.st_ctime = stat->ctime;
+	tmp.st_blocks = stat->blocks;
+	tmp.st_blksize = stat->blksize;
+	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
+{
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
+
+	if (!error)
+		error = cp_new_stat(&stat, statbuf);
+
+	return error;
+}
+asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
+{
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
+
+	if (!error)
+		error = cp_new_stat(&stat, statbuf);
+
+	return error;
+}
 asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf)
 {
-	struct file * f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
+	if (!error)
+		error = cp_new_stat(&stat, statbuf);
 
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_new_stat(dentry->d_inode, statbuf);
-		fput(f);
-	}
-	return err;
+	return error;
 }
 
 asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
@@ -270,110 +279,59 @@
 /* ---------- LFS-64 ----------- */
 #if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X)
 
-static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
+static long cp_new_stat64(struct kstat *stat, struct stat64 *statbuf)
 {
 	struct stat64 tmp;
-	unsigned int blocks, indirect;
 
 	memset(&tmp, 0, sizeof(tmp));
-	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
-	tmp.st_ino = inode->i_ino;
+	tmp.st_dev = stat->dev;
+	tmp.st_ino = stat->ino;
 #ifdef STAT64_HAS_BROKEN_ST_INO
-	tmp.__st_ino = inode->i_ino;
+	tmp.__st_ino = stat->ino;
 #endif
-	tmp.st_mode = inode->i_mode;
-	tmp.st_nlink = inode->i_nlink;
-	tmp.st_uid = inode->i_uid;
-	tmp.st_gid = inode->i_gid;
-	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
-	tmp.st_atime = inode->i_atime;
-	tmp.st_mtime = inode->i_mtime;
-	tmp.st_ctime = inode->i_ctime;
-	tmp.st_size = inode->i_size;
-/*
- * st_blocks and st_blksize are approximated with a simple algorithm if
- * they aren't supported directly by the filesystem. The minix and msdos
- * filesystems don't keep track of blocks, so they would either have to
- * be counted explicitly (by delving into the file itself), or by using
- * this simple algorithm to get a reasonable (although not 100% accurate)
- * value.
- */
-
-/*
- * Use minix fs values for the number of direct and indirect blocks.  The
- * count is now exact for the minix fs except that it counts zero blocks.
- * Everything is in units of BLOCK_SIZE until the assignment to
- * tmp.st_blksize.
- */
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-
-	if (!inode->i_blksize) {
-		blocks = (tmp.st_size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
-		if (blocks > D_B) {
-			indirect = (blocks - D_B + I_B - 1) / I_B;
-			blocks += indirect;
-			if (indirect > 1) {
-				indirect = (indirect - 1 + I_B - 1) / I_B;
-				blocks += indirect;
-				if (indirect > 1)
-					blocks++;
-			}
-		}
-		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-		tmp.st_blksize = BLOCK_SIZE;
-	} else {
-		tmp.st_blocks = inode->i_blocks;
-		tmp.st_blksize = inode->i_blksize;
-	}
+	tmp.st_mode = stat->mode;
+	tmp.st_nlink = stat->nlink;
+	tmp.st_uid = stat->uid;
+	tmp.st_gid = stat->gid;
+	tmp.st_rdev = stat->rdev;
+	tmp.st_atime = stat->atime;
+	tmp.st_mtime = stat->mtime;
+	tmp.st_ctime = stat->ctime;
+	tmp.st_size = stat->size;
+	tmp.st_blocks = stat->blocks;
+	tmp.st_blksize = stat->blksize;
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
 asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_stat(filename, &stat);
+
+	if (!error)
+		error = cp_new_stat64(&stat, statbuf);
 
-	error = user_path_walk(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
 	return error;
 }
-
 asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags)
 {
-	struct nameidata nd;
-	int error;
+	struct kstat stat;
+	int error = vfs_lstat(filename, &stat);
+
+	if (!error)
+		error = cp_new_stat64(&stat, statbuf);
 
-	error = user_path_walk_link(filename, &nd);
-	if (!error) {
-		error = do_revalidate(nd.dentry);
-		if (!error)
-			error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-		path_release(&nd);
-	}
 	return error;
 }
-
 asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags)
 {
-	struct file * f;
-	int err = -EBADF;
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat);
 
-	f = fget(fd);
-	if (f) {
-		struct dentry * dentry = f->f_dentry;
+	if (!error)
+		error = cp_new_stat64(&stat, statbuf);
 
-		err = do_revalidate(dentry);
-		if (!err)
-			err = cp_new_stat64(dentry->d_inode, statbuf);
-		fput(f);
-	}
-	return err;
+	return error;
 }
 
 #endif /* LFS-64 */
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	Sun Feb 10 19:58:06 2002
+++ b/fs/super.c	Sun Feb 10 19:58:06 2002
@@ -597,11 +597,8 @@
  *
  *	Rather than duplicating all that logics every time when
  *	we want something that doesn't fit "nodev" and "single" we pull
- *	the relevant code into common helper and let get_sb_...() call
+ *	the relevant code into common helper and let ->get_sb() call
  *	it.
- *
- *	NB: get_sb_...() is going to become an fs type method, with
- *	current ->read_super() becoming a callback used by common instances.
  */
 struct super_block *get_anon_super(struct file_system_type *type,
 	int (*compare)(struct super_block *,void *), void *data)
@@ -641,8 +638,9 @@
 	return s;
 }
 
-static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
-	int flags, char *dev_name, void * data)
+struct super_block *get_sb_bdev(struct file_system_type *fs_type,
+	int flags, char *dev_name, void * data,
+	int (*fill_super)(struct super_block *, void *, int))
 {
 	struct inode *inode;
 	struct block_device *bdev;
@@ -698,7 +696,7 @@
 
 	list_for_each(p, &super_blocks) {
 		struct super_block *old = sb_entry(p);
-		if (!kdev_same(old->s_dev, dev))
+		if (old->s_bdev != bdev)
 			continue;
 		if (old->s_type != fs_type ||
 		    ((flags ^ old->s_flags) & MS_RDONLY)) {
@@ -718,8 +716,8 @@
 	s->s_flags = flags;
 	insert_super(s, fs_type);
 	strncpy(s->s_id, bdevname(dev), sizeof(s->s_id));
-	error = -EINVAL;
-	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
+	error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
+	if (error)
 		goto failed;
 	s->s_flags |= MS_ACTIVE;
 	path_release(&nd);
@@ -736,19 +734,23 @@
 	return ERR_PTR(error);
 }
 
-static struct super_block *get_sb_nodev(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+	int flags, void *data,
+	int (*fill_super)(struct super_block *, void *, int))
 {
+	int error;
 	struct super_block *s = get_anon_super(fs_type, NULL, NULL);
 
 	if (IS_ERR(s))
 		return s;
 
 	s->s_flags = flags;
-	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
+
+	error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
+	if (error) {
 		deactivate_super(s);
 		remove_super(s);
-		return ERR_PTR(-EINVAL);
+		return ERR_PTR(error);
 	}
 	s->s_flags |= MS_ACTIVE;
 	return s;
@@ -759,19 +761,22 @@
 	return 1;
 }
 
-static struct super_block *get_sb_single(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+struct super_block *get_sb_single(struct file_system_type *fs_type,
+	int flags, void *data,
+	int (*fill_super)(struct super_block *, void *, int))
 {
+	int error;
 	struct super_block *s = get_anon_super(fs_type, compare_single, NULL);
 
 	if (IS_ERR(s))
 		return s;
 	if (!s->s_root) {
 		s->s_flags = flags;
-		if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
+		error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
+		if (error) {
 			deactivate_super(s);
 			remove_super(s);
-			return ERR_PTR(-EINVAL);
+			return ERR_PTR(error);
 		}
 		s->s_flags |= MS_ACTIVE;
 	}
@@ -792,12 +797,7 @@
 	mnt = alloc_vfsmnt(name);
 	if (!mnt)
 		goto out;
-	if (type->fs_flags & FS_REQUIRES_DEV)
-		sb = get_sb_bdev(type, flags, name, data);
-	else if (type->fs_flags & FS_SINGLE)
-		sb = get_sb_single(type, flags, name, data);
-	else
-		sb = get_sb_nodev(type, flags, name, data);
+	sb = type->get_sb(type, flags, name, data);
 	if (IS_ERR(sb))
 		goto out_mnt;
 	if (type->fs_flags & FS_NOMOUNT)
diff -Nru a/fs/sysv/ChangeLog b/fs/sysv/ChangeLog
--- a/fs/sysv/ChangeLog	Sun Feb 10 19:58:03 2002
+++ b/fs/sysv/ChangeLog	Sun Feb 10 19:58:03 2002
@@ -1,13 +1,18 @@
+Thu Feb  7 2002  Alexander Viro  <viro@math.psu.edu>
+
+	* super.c: switched to ->get_sb()
+	* ChangeLog: fixed dates ;-)
+
 2002-01-24  David S. Miller  <davem@redhat.com>
 
 	* inode.c: Include linux/init.h
 
-Mon Jan 21 2001  Alexander Viro  <viro@math.psu.edu>
+Mon Jan 21 2002  Alexander Viro  <viro@math.psu.edu>
 	* ialloc.c (sysv_new_inode): zero SYSV_I(inode)->i_data out.
 	* i_vnode renamed to vfs_inode.  Sorry, but let's keep that
 	  consistent.
 
-Sat Jan 19 2001  Christoph Hellwig  <hch@infradead.org>
+Sat Jan 19 2002  Christoph Hellwig  <hch@infradead.org>
 
 	* include/linux/sysv_fs.h (SYSV_I): Get fs-private inode data using
 		list_entry() instead of inode->u.
@@ -19,7 +24,7 @@
 		in the case of failed register_filesystem for V7.
 	(exit_sysv_fs): Destroy inode cache.
 
-Sat Jan 19 2001  Christoph Hellwig  <hch@infradead.org>
+Sat Jan 19 2002  Christoph Hellwig  <hch@infradead.org>
 
 	* include/linux/sysv_fs.h: Include <linux/sysv_fs_i.h>, declare SYSV_I().
 	* dir.c (sysv_find_entry): Use SYSV_I() instead of ->u.sysv_i to
@@ -32,7 +37,7 @@
 	* symlink.c (sysv_readlink): Likewise.
 	(sysv_follow_link): Likewise.
 
-Fri Jan  4 2001  Alexander Viro  <viro@math.psu.edu>
+Fri Jan  4 2002  Alexander Viro  <viro@math.psu.edu>
 
 	* ialloc.c (sysv_free_inode): Use sb->s_id instead of bdevname().
 	* inode.c (sysv_read_inode): Likewise.
diff -Nru a/fs/sysv/super.c b/fs/sysv/super.c
--- a/fs/sysv/super.c	Sun Feb 10 19:58:04 2002
+++ b/fs/sysv/super.c	Sun Feb 10 19:58:04 2002
@@ -340,8 +340,7 @@
 	return 1;
 }
 
-static struct super_block *sysv_read_super(struct super_block *sb,
-					   void *data, int silent)
+static int sysv_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct buffer_head *bh1;
 	struct buffer_head *bh = NULL;
@@ -397,7 +396,7 @@
 		sb->sv_bh1 = bh1;
 		sb->sv_bh2 = bh;
 		if (complete_read_super(sb, silent, size))
-			return sb;
+			return 0;
 	}
 
 	brelse(bh1);
@@ -405,7 +404,7 @@
 	sb_set_blocksize(sb, BLOCK_SIZE);
 	printk("oldfs: cannot read superblock\n");
 failed:
-	return NULL;
+	return -EINVAL;
 
 Eunknown:
 	brelse(bh);
@@ -421,8 +420,7 @@
 	goto failed;
 }
 
-static struct super_block *v7_read_super(struct super_block *sb,void *data,
-				  int silent)
+static int v7_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct buffer_head *bh, *bh2 = NULL;
 	struct v7_super_block *v7sb;
@@ -466,18 +464,41 @@
 	sb->sv_bh1 = bh;
 	sb->sv_bh2 = bh;
 	if (complete_read_super(sb, silent, 1))
-		return sb;
+		return 0;
 
 failed:
 	brelse(bh2);
 	brelse(bh);
-	return NULL;
+	return -EINVAL;
 }
 
 /* Every kernel module contains stuff like this. */
 
-static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
-static DECLARE_FSTYPE_DEV(v7_fs_type, "v7", v7_read_super);
+static struct super_block *sysv_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super);
+}
+
+static struct super_block *v7_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super);
+}
+
+static struct file_system_type sysv_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"sysv",
+	get_sb:		sysv_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
+
+static struct file_system_type v7_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"v7",
+	get_sb:		v7_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 extern int sysv_init_icache(void) __init;
 extern void sysv_destroy_icache(void);
diff -Nru a/fs/udf/super.c b/fs/udf/super.c
--- a/fs/udf/super.c	Sun Feb 10 19:58:04 2002
+++ b/fs/udf/super.c	Sun Feb 10 19:58:04 2002
@@ -76,7 +76,7 @@
 static char error_buf[1024];
 
 /* These are the "meat" - everything else is stuffing */
-static struct super_block *udf_read_super(struct super_block *, void *, int);
+static int udf_fill_super(struct super_block *, void *, int);
 static void udf_put_super(struct super_block *);
 static void udf_write_super(struct super_block *);
 static int udf_remount_fs(struct super_block *, int *, char *);
@@ -96,7 +96,18 @@
 static int udf_statfs(struct super_block *, struct statfs *);
 
 /* UDF filesystem type */
-static DECLARE_FSTYPE_DEV(udf_fstype, "udf", udf_read_super);
+static struct super_block *udf_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super);
+}
+
+static struct file_system_type udf_fstype = {
+	owner:		THIS_MODULE,
+	name:		"udf",
+	get_sb:		udf_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static kmem_cache_t * udf_inode_cachep;
 
@@ -1387,8 +1398,7 @@
  *	July 1, 1997 - Andrew E. Mileski
  *	Written, tested, and released.
  */
-static struct super_block *
-udf_read_super(struct super_block *sb, void *options, int silent)
+static int udf_fill_super(struct super_block *sb, void *options, int silent)
 {
 	int i;
 	struct inode *inode=NULL;
@@ -1544,8 +1554,8 @@
 		iput(inode);
 		goto error_out;
 	}
-	sb->s_maxbytes = ~0ULL;
-	return sb;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
+	return 0;
 
 error_out:
 	if (UDF_SB_VAT(sb))
@@ -1588,7 +1598,7 @@
 		udf_close_lvid(sb);
 	udf_release_data(UDF_SB_LVIDBH(sb));
 	UDF_SB_FREE(sb);
-	return NULL;
+	return -EINVAL;
 }
 
 void udf_error(struct super_block *sb, const char *function,
diff -Nru a/fs/udf/symlink.c b/fs/udf/symlink.c
--- a/fs/udf/symlink.c	Sun Feb 10 19:58:05 2002
+++ b/fs/udf/symlink.c	Sun Feb 10 19:58:05 2002
@@ -29,7 +29,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/udf_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/stat.h>
 #include <linux/slab.h>
diff -Nru a/fs/ufs/balloc.c b/fs/ufs/balloc.c
--- a/fs/ufs/balloc.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ufs/balloc.c	Sun Feb 10 19:58:04 2002
@@ -9,7 +9,7 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/stat.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/quotaops.h>
diff -Nru a/fs/ufs/cylinder.c b/fs/ufs/cylinder.c
--- a/fs/ufs/cylinder.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ufs/cylinder.c	Sun Feb 10 19:58:04 2002
@@ -10,7 +10,7 @@
 
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/ufs/dir.c b/fs/ufs/dir.c
--- a/fs/ufs/dir.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ufs/dir.c	Sun Feb 10 19:58:05 2002
@@ -13,7 +13,7 @@
  * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
diff -Nru a/fs/ufs/file.c b/fs/ufs/file.c
--- a/fs/ufs/file.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ufs/file.c	Sun Feb 10 19:58:05 2002
@@ -30,45 +30,12 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/fcntl.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-
-/*
- * Make sure the offset never goes beyond the 32-bit mark..
- */
-static long long ufs_file_lseek(
-	struct file *file,
-	long long offset,
-	int origin )
-{
-	long long retval;
-	struct inode *inode = file->f_dentry->d_inode;
-
-	lock_kernel();
-
-	switch (origin) {
-		case 2:
-			offset += inode->i_size;
-			break;
-		case 1:
-			offset += file->f_pos;
-	}
-	retval = -EINVAL;
-	/* make sure the offset fits in 32 bits */
-	if (((unsigned long long) offset >> 32) == 0) {
-		if (offset != file->f_pos) {
-			file->f_pos = offset;
-			file->f_reada = 0;
-			file->f_version = ++event;
-		}
-		retval = offset;
-	}
-	unlock_kernel();
-	return retval;
-}
+#include <linux/smp_lock.h>
 
 /*
  * We have mostly NULL's here: the current defaults are ok for
@@ -76,7 +43,7 @@
  */
  
 struct file_operations ufs_file_operations = {
-	llseek:		ufs_file_lseek,
+	llseek:		generic_file_llseek,
 	read:		generic_file_read,
 	write:		generic_file_write,
 	mmap:		generic_file_mmap,
diff -Nru a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
--- a/fs/ufs/ialloc.c	Sun Feb 10 19:58:05 2002
+++ b/fs/ufs/ialloc.c	Sun Feb 10 19:58:05 2002
@@ -22,7 +22,7 @@
 
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/ufs/inode.c b/fs/ufs/inode.c
--- a/fs/ufs/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/ufs/inode.c	Sun Feb 10 19:58:05 2002
@@ -31,7 +31,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
diff -Nru a/fs/ufs/namei.c b/fs/ufs/namei.c
--- a/fs/ufs/namei.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ufs/namei.c	Sun Feb 10 19:58:06 2002
@@ -24,7 +24,7 @@
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 
diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c
--- a/fs/ufs/super.c	Sun Feb 10 19:58:03 2002
+++ b/fs/ufs/super.c	Sun Feb 10 19:58:03 2002
@@ -74,7 +74,7 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
@@ -434,8 +434,7 @@
 	UFSD(("EXIT\n"))
 }
 
-struct super_block * ufs_read_super (struct super_block * sb, void * data,
-	int silent)
+static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
@@ -807,7 +806,7 @@
 			goto failed;
 
 	UFSD(("EXIT\n"))
-	return(sb);
+	return 0;
 
 dalloc_failed:
 	iput(inode);
@@ -815,7 +814,7 @@
 	if (ubh) ubh_brelse_uspi (uspi);
 	if (uspi) kfree (uspi);
 	UFSD(("EXIT (FAILED)\n"))
-	return(NULL);
+	return -EINVAL;
 }
 
 void ufs_write_super (struct super_block * sb) {
@@ -1009,7 +1008,18 @@
 	remount_fs:	ufs_remount,
 };
 
-static DECLARE_FSTYPE_DEV(ufs_fs_type, "ufs", ufs_read_super);
+static struct super_block *ufs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super);
+}
+
+static struct file_system_type ufs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"ufs",
+	get_sb:		ufs_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_ufs_fs(void)
 {
diff -Nru a/fs/ufs/truncate.c b/fs/ufs/truncate.c
--- a/fs/ufs/truncate.c	Sun Feb 10 19:58:06 2002
+++ b/fs/ufs/truncate.c	Sun Feb 10 19:58:06 2002
@@ -33,7 +33,7 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/fcntl.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/string.h>
diff -Nru a/fs/umsdos/dir.c b/fs/umsdos/dir.c
--- a/fs/umsdos/dir.c	Sun Feb 10 19:58:06 2002
+++ b/fs/umsdos/dir.c	Sun Feb 10 19:58:06 2002
@@ -7,7 +7,7 @@
  *  Extended MS-DOS directory handling functions
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/string.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
diff -Nru a/fs/umsdos/emd.c b/fs/umsdos/emd.c
--- a/fs/umsdos/emd.c	Sun Feb 10 19:58:05 2002
+++ b/fs/umsdos/emd.c	Sun Feb 10 19:58:05 2002
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/msdos_fs.h>
diff -Nru a/fs/umsdos/inode.c b/fs/umsdos/inode.c
--- a/fs/umsdos/inode.c	Sun Feb 10 19:58:04 2002
+++ b/fs/umsdos/inode.c	Sun Feb 10 19:58:04 2002
@@ -11,7 +11,7 @@
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <linux/string.h>
diff -Nru a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c
--- a/fs/umsdos/ioctl.c	Sun Feb 10 19:58:04 2002
+++ b/fs/umsdos/ioctl.c	Sun Feb 10 19:58:04 2002
@@ -10,7 +10,7 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
diff -Nru a/fs/umsdos/namei.c b/fs/umsdos/namei.c
--- a/fs/umsdos/namei.c	Sun Feb 10 19:58:05 2002
+++ b/fs/umsdos/namei.c	Sun Feb 10 19:58:05 2002
@@ -13,7 +13,7 @@
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
diff -Nru a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
--- a/fs/umsdos/rdir.c	Sun Feb 10 19:58:05 2002
+++ b/fs/umsdos/rdir.c	Sun Feb 10 19:58:05 2002
@@ -7,7 +7,7 @@
  *  (For directory without EMD file).
  */
 
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
 #include <linux/errno.h>
diff -Nru a/fs/vfat/namei.c b/fs/vfat/namei.c
--- a/fs/vfat/namei.c	Sun Feb 10 19:58:04 2002
+++ b/fs/vfat/namei.c	Sun Feb 10 19:58:04 2002
@@ -1254,20 +1254,19 @@
 	setattr:	fat_notify_change,
 };
 
-struct super_block *vfat_read_super(struct super_block *sb,void *data,
-				    int silent)
+int vfat_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct super_block *res;
   
 	MSDOS_SB(sb)->options.isvfat = 1;
 	res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
 	if (IS_ERR(res))
-		return NULL;
+		return PTR_ERR(res);
 	if (res == NULL) {
 		if (!silent)
 			printk(KERN_INFO "VFS: Can't find a valid"
 			       " VFAT filesystem on dev %s.\n", sb->s_id);
-		return NULL;
+		return -EINVAL;
 	}
 
 	if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
@@ -1281,6 +1280,5 @@
 			sb->s_root->d_op = &vfat_dentry_ops[2];
 		}
 	}
-
-	return res;
+	return 0;
 }
diff -Nru a/fs/vfat/vfatfs_syms.c b/fs/vfat/vfatfs_syms.c
--- a/fs/vfat/vfatfs_syms.c	Sun Feb 10 19:58:05 2002
+++ b/fs/vfat/vfatfs_syms.c	Sun Feb 10 19:58:05 2002
@@ -11,14 +11,24 @@
 #include <linux/mm.h>
 #include <linux/msdos_fs.h>
 
-DECLARE_FSTYPE_DEV(vfat_fs_type, "vfat", vfat_read_super);
+static struct super_block *vfat_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
+}
+
+static struct file_system_type vfat_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"vfat",
+	get_sb:		vfat_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 EXPORT_SYMBOL(vfat_create);
 EXPORT_SYMBOL(vfat_unlink);
 EXPORT_SYMBOL(vfat_mkdir);
 EXPORT_SYMBOL(vfat_rmdir);
 EXPORT_SYMBOL(vfat_rename);
-EXPORT_SYMBOL(vfat_read_super);
 EXPORT_SYMBOL(vfat_lookup);
 
 static int __init init_vfat_fs(void)
diff -Nru a/include/asm-alpha/scatterlist.h b/include/asm-alpha/scatterlist.h
--- a/include/asm-alpha/scatterlist.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-alpha/scatterlist.h	Sun Feb 10 19:58:04 2002
@@ -4,11 +4,6 @@
 #include <asm/page.h>
   
 struct scatterlist {
-	/* This will disappear in 2.5.x */
-	char *address;
-
-	/* These two are only valid if ADDRESS member of this
-	   struct is NULL.  */
 	struct page *page;
 	unsigned int offset;
 
diff -Nru a/include/asm-alpha/siginfo.h b/include/asm-alpha/siginfo.h
--- a/include/asm-alpha/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-alpha/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -107,6 +107,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-alpha/unistd.h	Sun Feb 10 19:58:06 2002
@@ -318,6 +318,7 @@
 #define __NR_gettid			378
 #define __NR_readahead			379
 #define __NR_security			380 /* syscall for security modules */
+#define __NR_tkill			381
 
 #if defined(__GNUC__)
 
diff -Nru a/include/asm-arm/scatterlist.h b/include/asm-arm/scatterlist.h
--- a/include/asm-arm/scatterlist.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-arm/scatterlist.h	Sun Feb 10 19:58:06 2002
@@ -4,9 +4,8 @@
 #include <asm/types.h>
 
 struct scatterlist {
-	char		*address;	/* virtual address		 */
-	struct page	*page;		/* Location for highmem page, if any */
-	unsigned int	offset;		/* for highmem, page offset	 */
+	struct page	*page;		/* buffer page			 */
+	unsigned int	offset;		/* buffer offset		 */
 	dma_addr_t	dma_address;	/* dma address			 */
 	unsigned int	length;		/* length			 */
 	char		*__address;	/* for set_dma_addr		 */
diff -Nru a/include/asm-arm/siginfo.h b/include/asm-arm/siginfo.h
--- a/include/asm-arm/siginfo.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-arm/siginfo.h	Sun Feb 10 19:58:03 2002
@@ -107,6 +107,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL        -6              /* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-cris/siginfo.h b/include/asm-cris/siginfo.h
--- a/include/asm-cris/siginfo.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-cris/siginfo.h	Sun Feb 10 19:58:03 2002
@@ -107,6 +107,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
--- a/include/asm-cris/unistd.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-cris/unistd.h	Sun Feb 10 19:58:05 2002
@@ -230,6 +230,7 @@
 #define __NR_security           223     /* syscall for security modules */
 #define __NR_gettid             224
 #define __NR_readahead          225
+#define __NR_tkill              226
 
 /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
 #define _syscall0(type,name) \
diff -Nru a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
--- a/include/asm-i386/cpufeature.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/cpufeature.h	Sun Feb 10 19:58:04 2002
@@ -47,6 +47,7 @@
 /* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
 /* Don't duplicate feature flags which are redundant with Intel! */
 #define X86_FEATURE_SYSCALL	(1*32+11) /* SYSCALL/SYSRET */
+#define X86_FEATURE_MP		(1*32+19) /* MP Capable. */
 #define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
 #define X86_FEATURE_LM		(1*32+29) /* Long Mode (x86-64) */
 #define X86_FEATURE_3DNOWEXT	(1*32+30) /* AMD 3DNow! extensions */
diff -Nru a/include/asm-i386/current.h b/include/asm-i386/current.h
--- a/include/asm-i386/current.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/current.h	Sun Feb 10 19:58:05 2002
@@ -1,14 +1,14 @@
 #ifndef _I386_CURRENT_H
 #define _I386_CURRENT_H
 
+#include <asm/thread_info.h>
+
 struct task_struct;
 
 static inline struct task_struct * get_current(void)
 {
-	struct task_struct *current;
-	__asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
-	return current;
- }
+	return current_thread_info()->task;
+}
  
 #define current get_current()
 
diff -Nru a/include/asm-i386/floppy.h b/include/asm-i386/floppy.h
--- a/include/asm-i386/floppy.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/floppy.h	Sun Feb 10 19:58:05 2002
@@ -216,7 +216,7 @@
 {
 	if(can_use_virtual_dma == 2) {
 		if((unsigned int) addr >= (unsigned int) high_memory ||
-		   virt_to_bus(addr) >= 0x1000000 ||
+		   isa_virt_to_bus(addr) >= 0x1000000 ||
 		   _CROSS_64KB(addr, size, 0))
 			use_virtual_dma = 1;
 		else
@@ -252,7 +252,7 @@
 	doing_pdma = 0;
 	clear_dma_ff(FLOPPY_DMA);
 	set_dma_mode(FLOPPY_DMA,mode);
-	set_dma_addr(FLOPPY_DMA,virt_to_bus(addr));
+	set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr));
 	set_dma_count(FLOPPY_DMA,size);
 	enable_dma(FLOPPY_DMA);
 	return 0;
diff -Nru a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
--- a/include/asm-i386/hardirq.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/hardirq.h	Sun Feb 10 19:58:05 2002
@@ -36,6 +36,8 @@
 
 #define synchronize_irq()	barrier()
 
+#define release_irqlock(cpu)	do { } while (0)
+
 #else
 
 #include <asm/atomic.h>
diff -Nru a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
--- a/include/asm-i386/highmem.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/highmem.h	Sun Feb 10 19:58:04 2002
@@ -88,6 +88,7 @@
 	enum fixed_addresses idx;
 	unsigned long vaddr;
 
+	preempt_disable();
 	if (page < highmem_start_page)
 		return page_address(page);
 
@@ -109,8 +110,10 @@
 	unsigned long vaddr = (unsigned long) kvaddr;
 	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-	if (vaddr < FIXADDR_START) // FIXME
+	if (vaddr < FIXADDR_START) { // FIXME
+		preempt_enable();
 		return;
+	}
 
 	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
 		BUG();
@@ -122,6 +125,8 @@
 	pte_clear(kmap_pte-idx);
 	__flush_tlb_one(vaddr);
 #endif
+
+	preempt_enable();
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
--- a/include/asm-i386/hw_irq.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-i386/hw_irq.h	Sun Feb 10 19:58:06 2002
@@ -96,6 +96,18 @@
 #define __STR(x) #x
 #define STR(x) __STR(x)
 
+#define GET_THREAD_INFO \
+	"movl $-8192, %ebx\n\t" \
+	"andl %esp, %ebx\n\t"
+
+#ifdef CONFIG_PREEMPT
+#define BUMP_LOCK_COUNT \
+	GET_THREAD_INFO \
+	"incl 16(%ebx)\n\t"
+#else
+#define BUMP_LOCK_COUNT
+#endif
+
 #define SAVE_ALL \
 	"cld\n\t" \
 	"pushl %es\n\t" \
@@ -109,14 +121,16 @@
 	"pushl %ebx\n\t" \
 	"movl $" STR(__KERNEL_DS) ",%edx\n\t" \
 	"movl %edx,%ds\n\t" \
-	"movl %edx,%es\n\t"
+	"movl %edx,%es\n\t" \
+	BUMP_LOCK_COUNT
 
 #define IRQ_NAME2(nr) nr##_interrupt(void)
 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
 
 #define GET_CURRENT \
 	"movl %esp, %ebx\n\t" \
-	"andl $-8192, %ebx\n\t"
+	"andl $-8192, %ebx\n\t" \
+	"movl (%ebx),%ebx\n\t"
 
 /*
  *	SMP has a few special interrupts for IPI messages
diff -Nru a/include/asm-i386/i387.h b/include/asm-i386/i387.h
--- a/include/asm-i386/i387.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/i387.h	Sun Feb 10 19:58:05 2002
@@ -12,6 +12,7 @@
 #define __ASM_I386_I387_H
 
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
 #include <asm/user.h>
@@ -24,20 +25,21 @@
 extern void restore_fpu( struct task_struct *tsk );
 
 extern void kernel_fpu_begin(void);
-#define kernel_fpu_end() stts()
+#define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
 
 
 #define unlazy_fpu( tsk ) do { \
-	if ( tsk->flags & PF_USEDFPU ) \
+	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) \
 		save_init_fpu( tsk ); \
 } while (0)
 
-#define clear_fpu( tsk ) do { \
-	if ( tsk->flags & PF_USEDFPU ) { \
-		asm volatile("fwait"); \
-		tsk->flags &= ~PF_USEDFPU; \
-		stts(); \
-	} \
+#define clear_fpu( tsk )					\
+do {								\
+	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {		\
+		asm volatile("fwait");				\
+		clear_tsk_thread_flag(tsk, TIF_USEDFPU);	\
+		stts();						\
+	}							\
 } while (0)
 
 /*
diff -Nru a/include/asm-i386/io.h b/include/asm-i386/io.h
--- a/include/asm-i386/io.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-i386/io.h	Sun Feb 10 19:58:06 2002
@@ -95,11 +95,20 @@
 extern void iounmap(void *addr);
 
 /*
- * IO bus memory addresses are also 1:1 with the physical address
+ * ISA I/O bus memory addresses are 1:1 with the physical address.
  */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-#define page_to_bus page_to_phys
+#define isa_virt_to_bus virt_to_phys
+#define isa_page_to_bus page_to_phys
+#define isa_bus_to_virt phys_to_virt
+
+/*
+ * However PCI ones are not necessarily 1:1 and therefore these interfaces
+ * are forbidden in portable PCI drivers.
+ */
+extern unsigned long virt_to_bus_not_defined_use_pci_map(volatile void *addr);
+#define virt_to_bus virt_to_bus_not_defined_use_pci_map
+extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
+#define bus_to_virt bus_to_virt_not_defined_use_pci_map
 
 /*
  * readX/writeX() are used to access memory mapped devices. On some
diff -Nru a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
--- a/include/asm-i386/io_apic.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/io_apic.h	Sun Feb 10 19:58:04 2002
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <asm/types.h>
+#include <asm/mpspec.h>
 
 /*
  * Intel IO-APIC support for SMP and UP systems.
diff -Nru a/include/asm-i386/pci.h b/include/asm-i386/pci.h
--- a/include/asm-i386/pci.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-i386/pci.h	Sun Feb 10 19:58:06 2002
@@ -75,7 +75,7 @@
 	if (direction == PCI_DMA_NONE)
 		BUG();
 	flush_write_buffers();
-	return virt_to_bus(ptr);
+	return virt_to_phys(ptr);
 }
 
 /* Unmap a single streaming mode DMA translation.  The dma_addr and size
@@ -118,7 +118,7 @@
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
 #define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
 #define pci_unmap_len(PTR, LEN_NAME)		(0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
@@ -144,22 +144,14 @@
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
- 
- 	/*
- 	 * temporary 2.4 hack
- 	 */
- 	for (i = 0; i < nents; i++ ) {
- 		if (sg[i].address && sg[i].page)
- 			BUG();
- 		else if (!sg[i].address && !sg[i].page)
- 			BUG();
- 
- 		if (sg[i].address)
- 			sg[i].dma_address = virt_to_bus(sg[i].address);
- 		else
- 			sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
- 	}
- 
+
+	for (i = 0; i < nents; i++ ) {
+		if (!sg[i].page)
+			BUG();
+
+		sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+	}
+
 	flush_write_buffers();
 	return nents;
 }
@@ -233,7 +225,7 @@
 static __inline__ dma64_addr_t
 pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
 {
-	return ((dma64_addr_t) page_to_bus(page) +
+	return ((dma64_addr_t) page_to_phys(page) +
 		(dma64_addr_t) offset);
 }
 
diff -Nru a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
--- a/include/asm-i386/pgalloc.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/pgalloc.h	Sun Feb 10 19:58:04 2002
@@ -75,20 +75,26 @@
 {
 	unsigned long *ret;
 
+	preempt_disable();
 	if ((ret = pgd_quicklist) != NULL) {
 		pgd_quicklist = (unsigned long *)(*ret);
 		ret[0] = 0;
 		pgtable_cache_size--;
-	} else
+		preempt_enable();
+	} else {
+		preempt_enable();
 		ret = (unsigned long *)get_pgd_slow();
+	}
 	return (pgd_t *)ret;
 }
 
 static inline void free_pgd_fast(pgd_t *pgd)
 {
+	preempt_disable();
 	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
 	pgd_quicklist = (unsigned long *) pgd;
 	pgtable_cache_size++;
+	preempt_enable();
 }
 
 static inline void free_pgd_slow(pgd_t *pgd)
@@ -119,19 +125,23 @@
 {
 	unsigned long *ret;
 
+	preempt_disable();
 	if ((ret = (unsigned long *)pte_quicklist) != NULL) {
 		pte_quicklist = (unsigned long *)(*ret);
 		ret[0] = ret[1];
 		pgtable_cache_size--;
 	}
+	preempt_enable();
 	return (pte_t *)ret;
 }
 
 static inline void pte_free_fast(pte_t *pte)
 {
+	preempt_disable();
 	*(unsigned long *)pte = (unsigned long) pte_quicklist;
 	pte_quicklist = (unsigned long *) pte;
 	pgtable_cache_size++;
+	preempt_enable();
 }
 
 static __inline__ void pte_free_slow(pte_t *pte)
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/processor.h	Sun Feb 10 19:58:04 2002
@@ -90,6 +90,7 @@
 #define cpu_has_xmm	(test_bit(X86_FEATURE_XMM,  boot_cpu_data.x86_capability))
 #define cpu_has_fpu	(test_bit(X86_FEATURE_FPU,  boot_cpu_data.x86_capability))
 #define cpu_has_apic	(test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability))
+#define cpu_has_mp (test_bit(X86_FEATURE_MP, boot_cpu_data.x86_capability))
 
 extern char ignore_irq13;
 
@@ -438,22 +439,14 @@
 /*
  * Return saved PC of a blocked thread.
  */
-static inline unsigned long thread_saved_pc(struct thread_struct *t)
+static inline unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	return ((unsigned long *)t->esp)[3];
+	return ((unsigned long *)tsk->thread->esp)[3];
 }
 
 unsigned long get_wchan(struct task_struct *p);
-#define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-#define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long) (p), 1)
-#define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
-
-#define init_task	(init_task_union.task)
-#define init_stack	(init_task_union.stack)
+#define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019])
+#define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1022])
 
 struct microcode {
 	unsigned int hdrver;
diff -Nru a/include/asm-i386/rwlock.h b/include/asm-i386/rwlock.h
--- a/include/asm-i386/rwlock.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-i386/rwlock.h	Sun Feb 10 19:58:06 2002
@@ -24,23 +24,23 @@
 	asm volatile(LOCK "subl $1,(%0)\n\t" \
 		     "js 2f\n" \
 		     "1:\n" \
-		     ".section .text.lock,\"ax\"\n" \
+		     LOCK_SECTION_START("") \
 		     "2:\tcall " helper "\n\t" \
 		     "jmp 1b\n" \
-		     ".previous" \
+		     LOCK_SECTION_END \
 		     ::"a" (rw) : "memory")
 
 #define __build_read_lock_const(rw, helper)   \
 	asm volatile(LOCK "subl $1,%0\n\t" \
 		     "js 2f\n" \
 		     "1:\n" \
-		     ".section .text.lock,\"ax\"\n" \
+		     LOCK_SECTION_START("") \
 		     "2:\tpushl %%eax\n\t" \
 		     "leal %0,%%eax\n\t" \
 		     "call " helper "\n\t" \
 		     "popl %%eax\n\t" \
 		     "jmp 1b\n" \
-		     ".previous" \
+		     LOCK_SECTION_END \
 		     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_read_lock(rw, helper)	do { \
@@ -54,23 +54,23 @@
 	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
 		     "jnz 2f\n" \
 		     "1:\n" \
-		     ".section .text.lock,\"ax\"\n" \
+		     LOCK_SECTION_START("") \
 		     "2:\tcall " helper "\n\t" \
 		     "jmp 1b\n" \
-		     ".previous" \
+		     LOCK_SECTION_END \
 		     ::"a" (rw) : "memory")
 
 #define __build_write_lock_const(rw, helper) \
 	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
 		     "jnz 2f\n" \
 		     "1:\n" \
-		     ".section .text.lock,\"ax\"\n" \
+		     LOCK_SECTION_START("") \
 		     "2:\tpushl %%eax\n\t" \
 		     "leal %0,%%eax\n\t" \
 		     "call " helper "\n\t" \
 		     "popl %%eax\n\t" \
 		     "jmp 1b\n" \
-		     ".previous" \
+		     LOCK_SECTION_END \
 		     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_write_lock(rw, helper)	do { \
diff -Nru a/include/asm-i386/rwsem.h b/include/asm-i386/rwsem.h
--- a/include/asm-i386/rwsem.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-i386/rwsem.h	Sun Feb 10 19:58:06 2002
@@ -101,7 +101,7 @@
 LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
 		"  js        2f\n\t" /* jump if we weren't granted the lock */
 		"1:\n\t"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\n\t"
 		"  pushl     %%ecx\n\t"
 		"  pushl     %%edx\n\t"
@@ -109,7 +109,7 @@
 		"  popl      %%edx\n\t"
 		"  popl      %%ecx\n\t"
 		"  jmp       1b\n"
-		".previous"
+		LOCK_SECTION_END
 		"# ending down_read\n\t"
 		: "+m"(sem->count)
 		: "a"(sem)
@@ -130,13 +130,13 @@
 		"  testl     %0,%0\n\t" /* was the count 0 before? */
 		"  jnz       2f\n\t" /* jump if we weren't granted the lock */
 		"1:\n\t"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\n\t"
 		"  pushl     %%ecx\n\t"
 		"  call      rwsem_down_write_failed\n\t"
 		"  popl      %%ecx\n\t"
 		"  jmp       1b\n"
-		".previous\n"
+		LOCK_SECTION_END
 		"# ending down_write"
 		: "+d"(tmp), "+m"(sem->count)
 		: "a"(sem)
@@ -154,7 +154,7 @@
 LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
 		"  js        2f\n\t" /* jump if the lock is being waited upon */
 		"1:\n\t"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\n\t"
 		"  decw      %%dx\n\t" /* do nothing if still outstanding active readers */
 		"  jnz       1b\n\t"
@@ -162,7 +162,7 @@
 		"  call      rwsem_wake\n\t"
 		"  popl      %%ecx\n\t"
 		"  jmp       1b\n"
-		".previous\n"
+		LOCK_SECTION_END
 		"# ending __up_read\n"
 		: "+m"(sem->count), "+d"(tmp)
 		: "a"(sem)
@@ -180,7 +180,7 @@
 LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
 		"  jnz       2f\n\t" /* jump if the lock is being waited upon */
 		"1:\n\t"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\n\t"
 		"  decw      %%dx\n\t" /* did the active count reduce to 0? */
 		"  jnz       1b\n\t" /* jump back if not */
@@ -188,7 +188,7 @@
 		"  call      rwsem_wake\n\t"
 		"  popl      %%ecx\n\t"
 		"  jmp       1b\n"
-		".previous\n"
+		LOCK_SECTION_END
 		"# ending __up_write\n"
 		: "+m"(sem->count)
 		: "a"(sem), "i"(-RWSEM_ACTIVE_WRITE_BIAS)
diff -Nru a/include/asm-i386/scatterlist.h b/include/asm-i386/scatterlist.h
--- a/include/asm-i386/scatterlist.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-i386/scatterlist.h	Sun Feb 10 19:58:06 2002
@@ -2,13 +2,10 @@
 #define _I386_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to, NULL for
-			 * highmem page */
-    struct page * page; /* Location for highmem page, if any */
-    unsigned int offset;/* for highmem, page offset */
-
-    dma_addr_t dma_address;
-    unsigned int length;
+    struct page		*page;
+    unsigned int	offset;
+    dma_addr_t		dma_address;
+    unsigned int	length;
 };
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
diff -Nru a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
--- a/include/asm-i386/semaphore.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/semaphore.h	Sun Feb 10 19:58:05 2002
@@ -122,10 +122,10 @@
 		LOCK "decl %0\n\t"     /* --sem->count */
 		"js 2f\n"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\tcall __down_failed\n\t"
 		"jmp 1b\n"
-		".previous"
+		LOCK_SECTION_END
 		:"=m" (sem->count)
 		:"c" (sem)
 		:"memory");
@@ -149,10 +149,10 @@
 		"js 2f\n\t"
 		"xorl %0,%0\n"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\tcall __down_failed_interruptible\n\t"
 		"jmp 1b\n"
-		".previous"
+		LOCK_SECTION_END
 		:"=a" (result), "=m" (sem->count)
 		:"c" (sem)
 		:"memory");
@@ -177,10 +177,10 @@
 		"js 2f\n\t"
 		"xorl %0,%0\n"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\tcall __down_failed_trylock\n\t"
 		"jmp 1b\n"
-		".previous"
+		LOCK_SECTION_END
 		:"=a" (result), "=m" (sem->count)
 		:"c" (sem)
 		:"memory");
@@ -203,10 +203,11 @@
 		LOCK "incl %0\n\t"     /* ++sem->count */
 		"jle 2f\n"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
+		LOCK_SECTION_START("")
 		"2:\tcall __up_wakeup\n\t"
 		"jmp 1b\n"
-		".previous"
+		LOCK_SECTION_END
+		".subsection 0\n"
 		:"=m" (sem->count)
 		:"c" (sem)
 		:"memory");
diff -Nru a/include/asm-i386/siginfo.h b/include/asm-i386/siginfo.h
--- a/include/asm-i386/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -107,6 +107,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-i386/smp.h b/include/asm-i386/smp.h
--- a/include/asm-i386/smp.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/smp.h	Sun Feb 10 19:58:04 2002
@@ -105,7 +105,7 @@
  * so this is correct in the x86 case.
  */
 
-#define smp_processor_id() (current->cpu)
+#define smp_processor_id() (current_thread_info()->cpu)
 
 static __inline int hard_smp_processor_id(void)
 {
diff -Nru a/include/asm-i386/smplock.h b/include/asm-i386/smplock.h
--- a/include/asm-i386/smplock.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/smplock.h	Sun Feb 10 19:58:05 2002
@@ -10,7 +10,16 @@
 
 extern spinlock_t kernel_flag;
 
+#ifdef CONFIG_SMP
 #define kernel_locked()		spin_is_locked(&kernel_flag)
+#else
+#ifdef CONFIG_PREEMPT
+#define kernel_locked()		preempt_get_count()
+#define global_irq_holder	0
+#else
+#define kernel_locked()		1
+#endif
+#endif
 
 /*
  * Release global kernel lock and global interrupt lock
@@ -43,6 +52,11 @@
  */
 static __inline__ void lock_kernel(void)
 {
+#ifdef CONFIG_PREEMPT
+	if (current->lock_depth == -1)
+		spin_lock(&kernel_flag);
+	++current->lock_depth;
+#else
 #if 1
 	if (!++current->lock_depth)
 		spin_lock(&kernel_flag);
@@ -54,6 +68,7 @@
 		"\n9:"
 		:"=m" (__dummy_lock(&kernel_flag)),
 		 "=m" (current->lock_depth));
+#endif
 #endif
 }
 
diff -Nru a/include/asm-i386/softirq.h b/include/asm-i386/softirq.h
--- a/include/asm-i386/softirq.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-i386/softirq.h	Sun Feb 10 19:58:06 2002
@@ -5,9 +5,9 @@
 #include <asm/hardirq.h>
 
 #define __cpu_bh_enable(cpu) \
-		do { barrier(); local_bh_count(cpu)--; } while (0)
+		do { barrier(); local_bh_count(cpu)--; preempt_enable(); } while (0)
 #define cpu_bh_disable(cpu) \
-		do { local_bh_count(cpu)++; barrier(); } while (0)
+		do { preempt_disable(); local_bh_count(cpu)++; barrier(); } while (0)
 
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 #define __local_bh_enable()	__cpu_bh_enable(smp_processor_id())
@@ -22,7 +22,7 @@
  * If you change the offsets in irq_stat then you have to
  * update this code as well.
  */
-#define local_bh_enable()						\
+#define _local_bh_enable()						\
 do {									\
 	unsigned int *ptr = &local_bh_count(smp_processor_id());	\
 									\
@@ -33,16 +33,18 @@
 			"jnz 2f;"					\
 			"1:;"						\
 									\
-			".section .text.lock,\"ax\";"			\
+			LOCK_SECTION_START("")				\
 			"2: pushl %%eax; pushl %%ecx; pushl %%edx;"	\
 			"call %c1;"					\
 			"popl %%edx; popl %%ecx; popl %%eax;"		\
 			"jmp 1b;"					\
-			".previous;"					\
+			LOCK_SECTION_END				\
 									\
 		: /* no output */					\
 		: "r" (ptr), "i" (do_softirq)				\
 		/* no registers clobbered */ );				\
 } while (0)
+
+#define local_bh_enable() do { _local_bh_enable(); preempt_enable(); } while (0)
 
 #endif	/* __ASM_SOFTIRQ_H */
diff -Nru a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
--- a/include/asm-i386/spinlock.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-i386/spinlock.h	Sun Feb 10 19:58:05 2002
@@ -56,13 +56,13 @@
 	"\n1:\t" \
 	"lock ; decb %0\n\t" \
 	"js 2f\n" \
-	".section .text.lock,\"ax\"\n" \
+	LOCK_SECTION_START("") \
 	"2:\t" \
 	"cmpb $0,%0\n\t" \
 	"rep;nop\n\t" \
 	"jle 2b\n\t" \
 	"jmp 1b\n" \
-	".previous"
+	LOCK_SECTION_END
 
 /*
  * This works. Despite all the confusion.
@@ -77,7 +77,7 @@
 		:"=m" (lock->lock) : : "memory"
 
 
-static inline void spin_unlock(spinlock_t *lock)
+static inline void _raw_spin_unlock(spinlock_t *lock)
 {
 #if SPINLOCK_DEBUG
 	if (lock->magic != SPINLOCK_MAGIC)
@@ -97,7 +97,7 @@
 		:"=q" (oldval), "=m" (lock->lock) \
 		:"0" (oldval) : "memory"
 
-static inline void spin_unlock(spinlock_t *lock)
+static inline void _raw_spin_unlock(spinlock_t *lock)
 {
 	char oldval = 1;
 #if SPINLOCK_DEBUG
@@ -113,7 +113,7 @@
 
 #endif
 
-static inline int spin_trylock(spinlock_t *lock)
+static inline int _raw_spin_trylock(spinlock_t *lock)
 {
 	char oldval;
 	__asm__ __volatile__(
@@ -123,7 +123,7 @@
 	return oldval > 0;
 }
 
-static inline void spin_lock(spinlock_t *lock)
+static inline void _raw_spin_lock(spinlock_t *lock)
 {
 #if SPINLOCK_DEBUG
 	__label__ here;
@@ -179,7 +179,7 @@
  */
 /* the spinlock helpers are in arch/i386/kernel/semaphore.c */
 
-static inline void read_lock(rwlock_t *rw)
+static inline void _raw_read_lock(rwlock_t *rw)
 {
 #if SPINLOCK_DEBUG
 	if (rw->magic != RWLOCK_MAGIC)
@@ -188,7 +188,7 @@
 	__build_read_lock(rw, "__read_lock_failed");
 }
 
-static inline void write_lock(rwlock_t *rw)
+static inline void _raw_write_lock(rwlock_t *rw)
 {
 #if SPINLOCK_DEBUG
 	if (rw->magic != RWLOCK_MAGIC)
@@ -197,10 +197,10 @@
 	__build_write_lock(rw, "__write_lock_failed");
 }
 
-#define read_unlock(rw)		asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
-#define write_unlock(rw)	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
+#define _raw_read_unlock(rw)		asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
+#define _raw_write_unlock(rw)	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
 
-static inline int write_trylock(rwlock_t *lock)
+static inline int _raw_write_trylock(rwlock_t *lock)
 {
 	atomic_t *count = (atomic_t *)lock;
 	if (atomic_sub_and_test(RW_LOCK_BIAS, count))
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/thread_info.h	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,115 @@
+/* thread_info.h: i386 low-level thread information
+ *
+ * Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#endif
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants must also be changed
+ */
+#ifndef __ASSEMBLY__
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	__u32			flags;		/* low level flags */
+	__u32			cpu;		/* current CPU */
+	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+
+	mm_segment_t		addr_limit;	/* thread address space:
+					 	   0-0xBFFFFFFF for user-thead
+						   0-0xFFFFFFFF for kernel-thread
+						*/
+
+	__u8			supervisor_stack[0];
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK		0x00000000
+#define TI_EXEC_DOMAIN	0x00000004
+#define TI_FLAGS	0x00000008
+#define TI_CPU		0x0000000C
+#define TI_PRE_COUNT	0x00000010
+#define TI_ADDR_LIMIT	0x00000014
+
+#endif
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#ifndef __ASSEMBLY__
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	task:		&tsk,			\
+	exec_domain:	&default_exec_domain,	\
+	flags:		0,			\
+	cpu:		0,			\
+	addr_limit:	KERNEL_DS,		\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~8191UL));
+	return ti;
+}
+
+/* thread information allocation */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+/* how to get the thread information struct from ASM */
+#define GET_THREAD_INFO(reg) \
+	movl $-8192, reg; \
+	andl %esp, reg
+
+#endif
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
+#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_USEDFPU		(1<<TIF_USEDFPU)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff -Nru a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
--- a/include/asm-i386/uaccess.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/uaccess.h	Sun Feb 10 19:58:04 2002
@@ -5,6 +5,7 @@
  * User space memory access functions
  */
 #include <linux/config.h>
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/prefetch.h>
 #include <asm/page.h>
@@ -27,14 +28,14 @@
 #define USER_DS		MAKE_MM_SEG(PAGE_OFFSET)
 
 #define get_ds()	(KERNEL_DS)
-#define get_fs()	(current->addr_limit)
-#define set_fs(x)	(current->addr_limit = (x))
+#define get_fs()	(current_thread_info()->addr_limit)
+#define set_fs(x)	(current_thread_info()->addr_limit = (x))
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
 extern int __verify_write(const void *, unsigned long);
 
-#define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg))
+#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
 
 /*
  * Uhhuh, this needs 33-bit arithmetic. We have a carry..
@@ -43,7 +44,7 @@
 	unsigned long flag,sum; \
 	asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
 		:"=&r" (flag), "=r" (sum) \
-		:"1" (addr),"g" ((int)(size)),"g" (current->addr_limit.seg)); \
+		:"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \
 	flag; })
 
 #ifdef CONFIG_X86_WP_WORKS_OK
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/unistd.h	Sun Feb 10 19:58:04 2002
@@ -242,6 +242,7 @@
 #define __NR_removexattr	235
 #define __NR_lremovexattr	236
 #define __NR_fremovexattr	237
+#define __NR_tkill		238
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -Nru a/include/asm-i386/xor.h b/include/asm-i386/xor.h
--- a/include/asm-i386/xor.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-i386/xor.h	Sun Feb 10 19:58:04 2002
@@ -20,7 +20,7 @@
 
 #define FPU_SAVE							\
   do {									\
-	if (!(current->flags & PF_USEDFPU))				\
+	if (!test_thread_flag(TIF_USEDFPU))				\
 		__asm__ __volatile__ (" clts;\n");			\
 	__asm__ __volatile__ ("fsave %0; fwait": "=m"(fpu_save[0]));	\
   } while (0)
@@ -28,7 +28,7 @@
 #define FPU_RESTORE							\
   do {									\
 	__asm__ __volatile__ ("frstor %0": : "m"(fpu_save[0]));		\
-	if (!(current->flags & PF_USEDFPU))				\
+	if (!test_thread_flag(TIF_USEDFPU))				\
 		stts();							\
   } while (0)
 
diff -Nru a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h
--- a/include/asm-ia64/scatterlist.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-ia64/scatterlist.h	Sun Feb 10 19:58:03 2002
@@ -7,8 +7,6 @@
  */
 
 struct scatterlist {
-	/* This will disappear in 2.5.x: */
-	char *address;		/* location data is to be transferred to, NULL for highmem page */
 	char *orig_address;	/* for use by swiotlb */
 
 	/* These two are only valid if ADDRESS member of this struct is NULL.  */
diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
--- a/include/asm-ia64/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-ia64/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -124,6 +124,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-ia64/unistd.h	Sun Feb 10 19:58:04 2002
@@ -206,6 +206,7 @@
 #define __NR_getdents64			1214
 #define __NR_getunwind			1215
 #define __NR_readahead			1216
+#define __NR_tkill			1217
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
diff -Nru a/include/asm-m68k/scatterlist.h b/include/asm-m68k/scatterlist.h
--- a/include/asm-m68k/scatterlist.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-m68k/scatterlist.h	Sun Feb 10 19:58:03 2002
@@ -2,7 +2,8 @@
 #define _M68K_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
     unsigned long dvma_address;
 };
diff -Nru a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
--- a/include/asm-m68k/semaphore.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-m68k/semaphore.h	Sun Feb 10 19:58:06 2002
@@ -9,6 +9,7 @@
 #include <linux/wait.h>
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
+#include <linux/stringify.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -94,11 +95,10 @@
 		"subql #1,%0@\n\t"
 		"jmi 2f\n\t"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
+		LOCK_SECTION_START(".even\n\t")
 		"2:\tpea 1b\n\t"
 		"jbra __down_failed\n"
-		".previous"
+		LOCK_SECTION_END
 		: /* no outputs */
 		: "a" (sem1)
 		: "memory");
@@ -119,11 +119,10 @@
 		"jmi 2f\n\t"
 		"clrl %0\n"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
+		LOCK_SECTION_START(".even\n\t")
 		"2:\tpea 1b\n\t"
 		"jbra __down_failed_interruptible\n"
-		".previous"
+		LOCK_SECTION_END
 		: "=d" (result)
 		: "a" (sem1)
 		: "memory");
@@ -145,11 +144,10 @@
 		"jmi 2f\n\t"
 		"clrl %0\n"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
+		LOCK_SECTION_START(".even\n\t")
 		"2:\tpea 1b\n\t"
 		"jbra __down_failed_trylock\n"
-		".previous"
+		LOCK_SECTION_END
 		: "=d" (result)
 		: "a" (sem1)
 		: "memory");
@@ -175,12 +173,11 @@
 		"addql #1,%0@\n\t"
 		"jle 2f\n"
 		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
+		LOCK_SECTION_START(".even\n\t")
 		"2:\t"
 		"pea 1b\n\t"
 		"jbra __up_wakeup\n"
-		".previous"
+		LOCK_SECTION_END
 		: /* no outputs */
 		: "a" (sem1)
 		: "memory");
diff -Nru a/include/asm-m68k/siginfo.h b/include/asm-m68k/siginfo.h
--- a/include/asm-m68k/siginfo.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-m68k/siginfo.h	Sun Feb 10 19:58:03 2002
@@ -117,6 +117,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
--- a/include/asm-m68k/unistd.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-m68k/unistd.h	Sun Feb 10 19:58:06 2002
@@ -222,6 +222,8 @@
 #define __NR_setfsuid32		215
 #define __NR_setfsgid32		216
 #define __NR_getdents64		220
+#define __NR_gettid		221
+#define __NR_tkill		222
 
 /* user-visible error numbers are in the range -1 - -122: see
    <asm-m68k/errno.h> */
diff -Nru a/include/asm-mips/scatterlist.h b/include/asm-mips/scatterlist.h
--- a/include/asm-mips/scatterlist.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-mips/scatterlist.h	Sun Feb 10 19:58:04 2002
@@ -2,7 +2,8 @@
 #define __ASM_MIPS_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
     
     __u32 dvma_address;
diff -Nru a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h
--- a/include/asm-mips/siginfo.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-mips/siginfo.h	Sun Feb 10 19:58:06 2002
@@ -127,6 +127,7 @@
 #define SI_TIMER __SI_CODE(__SI_TIMER,-3) /* sent by timer expiration */
 #define SI_MESGQ	-4	/* sent by real time mesq state change */
 #define SI_SIGIO	-5	/* sent by queued SIGIO */
+#define SI_TKILL	-6	/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
--- a/include/asm-mips/unistd.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-mips/unistd.h	Sun Feb 10 19:58:03 2002
@@ -233,6 +233,8 @@
 #define __NR_madvise			(__NR_Linux + 218)
 #define __NR_getdents64			(__NR_Linux + 219)
 #define __NR_fcntl64			(__NR_Linux + 220)
+#define __NR_gettid			(__NR_Linux + 221)
+#define __NR_tkill			(__NR_Linux + 222)
 
 /*
  * Offset of the last Linux flavoured syscall
diff -Nru a/include/asm-mips64/scatterlist.h b/include/asm-mips64/scatterlist.h
--- a/include/asm-mips64/scatterlist.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-mips64/scatterlist.h	Sun Feb 10 19:58:05 2002
@@ -2,7 +2,8 @@
 #define __ASM_MIPS64_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
     
     __u32 dvma_address;
diff -Nru a/include/asm-mips64/siginfo.h b/include/asm-mips64/siginfo.h
--- a/include/asm-mips64/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-mips64/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -127,6 +127,7 @@
 #define SI_TIMER __SI_CODE(__SI_TIMER,-3) /* sent by timer expiration */
 #define SI_MESGQ	-4	/* sent by real time mesq state change */
 #define SI_SIGIO	-5	/* sent by queued SIGIO */
+#define SI_TKILL	-6	/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-mips64/unistd.h b/include/asm-mips64/unistd.h
--- a/include/asm-mips64/unistd.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-mips64/unistd.h	Sun Feb 10 19:58:05 2002
@@ -461,11 +461,13 @@
 #define __NR_mincore			(__NR_Linux + 211)
 #define __NR_madvise			(__NR_Linux + 212)
 #define __NR_getdents64			(__NR_Linux + 213)
+#define __NR_gettid			(__NR_Linux + 214)
+#define __NR_tkill			(__NR_Linux + 215)
 
 /*
  * Offset of the last Linux flavoured syscall
  */
-#define __NR_Linux_syscalls		213
+#define __NR_Linux_syscalls		215
 
 #ifndef _LANGUAGE_ASSEMBLY
 
diff -Nru a/include/asm-parisc/scatterlist.h b/include/asm-parisc/scatterlist.h
--- a/include/asm-parisc/scatterlist.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-parisc/scatterlist.h	Sun Feb 10 19:58:04 2002
@@ -2,7 +2,8 @@
 #define _ASM_PARISC_SCATTERLIST_H
 
 struct scatterlist {
-	char *  address;    /* Location data is to be transferred to */
+	struct page *page;
+	unsigned int offset;
 	unsigned int length;
 
 	/* an IOVA can be 64-bits on some PA-Risc platforms. */
diff -Nru a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
--- a/include/asm-parisc/semaphore.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-parisc/semaphore.h	Sun Feb 10 19:58:03 2002
@@ -12,10 +12,6 @@
  *
  */
 
-/* if you're going to use out-of-line slowpaths, use .section .lock.text,
- * not .text.lock or the -ffunction-sections monster will eat you alive
- */
-
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 
diff -Nru a/include/asm-parisc/siginfo.h b/include/asm-parisc/siginfo.h
--- a/include/asm-parisc/siginfo.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-parisc/siginfo.h	Sun Feb 10 19:58:06 2002
@@ -107,6 +107,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
--- a/include/asm-parisc/spinlock.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-parisc/spinlock.h	Sun Feb 10 19:58:05 2002
@@ -3,10 +3,6 @@
 
 #include <asm/system.h>
 
-/* if you're going to use out-of-line slowpaths, use .section .lock.text,
- * not .text.lock or the -ffunction-sections monster will eat you alive
- */
-
 /* we seem to be the only architecture that uses 0 to mean locked - but we
  * have to.  prumpf */
 
diff -Nru a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
--- a/include/asm-parisc/unistd.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-parisc/unistd.h	Sun Feb 10 19:58:03 2002
@@ -689,8 +689,10 @@
 
 #define __NR_getpmsg            (__NR_Linux + 196)      /* some people actually want streams */
 #define __NR_putpmsg            (__NR_Linux + 197)      /* some people actually want streams */
+#define __NR_gettid             (__NR_Linux + 198)
+#define __NR_tkill              (__NR_Linux + 199)
 
-#define __NR_Linux_syscalls     197
+#define __NR_Linux_syscalls     199
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
diff -Nru a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
--- a/include/asm-ppc/pci.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-ppc/pci.h	Sun Feb 10 19:58:04 2002
@@ -157,15 +157,10 @@
 	 * temporary 2.4 hack
 	 */
 	for (i = 0; i < nents; i++) {
-		if (sg[i].address && sg[i].page)
-			BUG();
-		else if (!sg[i].address && !sg[i].page)
+		if (!sg[i].page)
 			BUG();
 
-		if (sg[i].address)
-			sg[i].dma_address = virt_to_bus(sg[i].address);
-		else
-			sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
+		sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
 	}
 
 	return nents;
diff -Nru a/include/asm-ppc/scatterlist.h b/include/asm-ppc/scatterlist.h
--- a/include/asm-ppc/scatterlist.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-ppc/scatterlist.h	Sun Feb 10 19:58:04 2002
@@ -8,10 +8,8 @@
 #include <asm/dma.h>
 
 struct scatterlist {
-	char *address;		/* Location data is to be transferred to,
-				 * or NULL for highmem page */
-	struct page * page;	/* Location for highmem page, if any */
-	unsigned int offset;	/* for highmem, page offset */
+	struct page * page;
+	unsigned int offset;
 
 	dma_addr_t dma_address;	/* phys/bus dma address		 */
 	unsigned int length;	/* length			 */
diff -Nru a/include/asm-ppc/siginfo.h b/include/asm-ppc/siginfo.h
--- a/include/asm-ppc/siginfo.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-ppc/siginfo.h	Sun Feb 10 19:58:03 2002
@@ -108,6 +108,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-ppc/unistd.h	Sun Feb 10 19:58:04 2002
@@ -215,6 +215,7 @@
 #define __NR_madvise		205
 #define __NR_mincore		206
 #define __NR_gettid		207
+#define __NR_tkill		208
 
 #define __NR(n)	#n
 
diff -Nru a/include/asm-s390/scatterlist.h b/include/asm-s390/scatterlist.h
--- a/include/asm-s390/scatterlist.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-s390/scatterlist.h	Sun Feb 10 19:58:06 2002
@@ -2,7 +2,8 @@
 #define _ASMS390X_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
 };
 
diff -Nru a/include/asm-s390/siginfo.h b/include/asm-s390/siginfo.h
--- a/include/asm-s390/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-s390/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -115,6 +115,7 @@
 #define SI_MESGQ	-3	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4	/* sent by AIO completion */
 #define SI_SIGIO	-5	/* sent by queued SIGIO */
+#define SI_TKILL	-6	/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
--- a/include/asm-s390/unistd.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-s390/unistd.h	Sun Feb 10 19:58:06 2002
@@ -211,6 +211,8 @@
 #define __NR_mincore            218
 #define __NR_madvise            219
 #define __NR_getdents64		220
+#define __NR_gettid		226
+#define __NR_tkill		227
 
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
diff -Nru a/include/asm-s390x/scatterlist.h b/include/asm-s390x/scatterlist.h
--- a/include/asm-s390x/scatterlist.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-s390x/scatterlist.h	Sun Feb 10 19:58:05 2002
@@ -2,7 +2,8 @@
 #define _ASMS390X_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
 };
 
diff -Nru a/include/asm-s390x/siginfo.h b/include/asm-s390x/siginfo.h
--- a/include/asm-s390x/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-s390x/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -115,6 +115,7 @@
 #define SI_MESGQ	-3	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4	/* sent by AIO completion */
 #define SI_SIGIO	-5	/* sent by queued SIGIO */
+#define SI_TKILL	-6	/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-s390x/unistd.h b/include/asm-s390x/unistd.h
--- a/include/asm-s390x/unistd.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-s390x/unistd.h	Sun Feb 10 19:58:04 2002
@@ -181,6 +181,8 @@
 #define __NR_mincore            218
 #define __NR_madvise            219
 #define __NR_getdents64         220
+#define __NR_gettid		226
+#define __NR_tkill 	        227
 
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
diff -Nru a/include/asm-sh/pci.h b/include/asm-sh/pci.h
--- a/include/asm-sh/pci.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sh/pci.h	Sun Feb 10 19:58:04 2002
@@ -149,7 +149,7 @@
 	int i;
 
 	for (i=0; i<nents; i++)
-		dma_cache_wback_inv(sg[i].address, sg[i].length);
+		dma_cache_wback_inv(page_address(sg[i].page) + sg[i].offset, sg[i].length);
 #endif
 	if (direction == PCI_DMA_NONE)
                 BUG();
@@ -206,7 +206,7 @@
 	int i;
 
 	for (i=0; i<nelems; i++)
-		dma_cache_wback_inv(sg[i].address, sg[i].length);
+		dma_cache_wback_inv(page_address(sg[i].page) + sg[i].offset, sg[i].length);
 #endif
 }
 
diff -Nru a/include/asm-sh/scatterlist.h b/include/asm-sh/scatterlist.h
--- a/include/asm-sh/scatterlist.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-sh/scatterlist.h	Sun Feb 10 19:58:03 2002
@@ -2,8 +2,6 @@
 #define __ASM_SH_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to, NULL for
-			 * highmem page */
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
     dma_addr_t dma_address;
diff -Nru a/include/asm-sh/siginfo.h b/include/asm-sh/siginfo.h
--- a/include/asm-sh/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sh/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -107,6 +107,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
--- a/include/asm-sh/unistd.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sh/unistd.h	Sun Feb 10 19:58:05 2002
@@ -231,6 +231,8 @@
 #define __NR_madvise		219
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
+#define __NR_gettid		222
+#define __NR_tkill		223
 
 /* user-visible error numbers are in the range -1 - -125: see <asm-sh/errno.h> */
 
diff -Nru a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
--- a/include/asm-sparc/checksum.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-sparc/checksum.h	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.32 2001/10/30 04:32:24 davem Exp $ */
+/* $Id: checksum.h,v 1.33 2002/02/01 22:01:05 davem Exp $ */
 #ifndef __SPARC_CHECKSUM_H
 #define __SPARC_CHECKSUM_H
 
@@ -16,6 +16,7 @@
  *      RFC1071 Computing the Internet Checksum
  */
  
+#include <linux/in6.h>
 #include <asm/uaccess.h>
 #include <asm/cprefix.h>
 
diff -Nru a/include/asm-sparc/scatterlist.h b/include/asm-sparc/scatterlist.h
--- a/include/asm-sparc/scatterlist.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc/scatterlist.h	Sun Feb 10 19:58:05 2002
@@ -1,16 +1,10 @@
-/* $Id: scatterlist.h,v 1.7 2001/10/30 04:34:57 davem Exp $ */
+/* $Id: scatterlist.h,v 1.8 2001/12/17 07:05:15 davem Exp $ */
 #ifndef _SPARC_SCATTERLIST_H
 #define _SPARC_SCATTERLIST_H
 
 #include <linux/types.h>
 
 struct scatterlist {
-	/* This will disappear in 2.5.x */
-	char *address;
-
-	/* These two are only valid if ADDRESS member of this
-	 * struct is NULL.
-	 */
 	struct page *page;
 	unsigned int offset;
 
diff -Nru a/include/asm-sparc/siginfo.h b/include/asm-sparc/siginfo.h
--- a/include/asm-sparc/siginfo.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc/siginfo.h	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.8 2000/05/27 00:49:37 davem Exp $
+/* $Id: siginfo.h,v 1.9 2002/02/08 03:57:18 davem Exp $
  * siginfo.c:
  */
 
@@ -112,6 +112,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc/unistd.h	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.72 2001/10/18 08:27:05 davem Exp $ */
+/* $Id: unistd.h,v 1.74 2002/02/08 03:57:18 davem Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -184,25 +184,25 @@
 /* #define __NR_exportfs        166    SunOS Specific                              */
 #define __NR_mount              167 /* Common                                      */
 #define __NR_ustat              168 /* Common                                      */
-/* #define __NR_semsys          169    SunOS Specific                              */
-/* #define __NR_msgsys          170    SunOS Specific                              */
-/* #define __NR_shmsys          171    SunOS Specific                              */
-/* #define __NR_auditsys        172    SunOS Specific                              */
-/* #define __NR_rfssys          173    SunOS Specific                              */
+#define __NR_setxattr           169 /* SunOS: semsys                               */
+#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
+#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
+#define __NR_getxattr           172 /* SunOS: auditsys                             */
+#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
 #define __NR_getdents           174 /* Common                                      */
 #define __NR_setsid             175 /* Common                                      */
 #define __NR_fchdir             176 /* Common                                      */
-/* #define __NR_fchroot         177    SunOS Specific                              */
-/* #define __NR_vpixsys         178    SunOS Specific                              */
-/* #define __NR_aioread         179    SunOS Specific                              */
-/* #define __NR_aiowrite        180    SunOS Specific                              */
-/* #define __NR_aiowait         181    SunOS Specific                              */
-/* #define __NR_aiocancel       182    SunOS Specific                              */
+#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
+#define __NR_listxattr          178 /* SunOS: vpixsys                              */
+#define __NR_llistxattr         179 /* SunOS: aioread                              */
+#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
+#define __NR_removexattr        181 /* SunOS: aiowait                              */
+#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
 #define __NR_sigpending         183 /* Common                                      */
 #define __NR_query_module	184 /* Linux Specific				   */
 #define __NR_setpgid            185 /* Common                                      */
-/* #define __NR_pathconf        186    SunOS Specific                              */
-/* #define __NR_fpathconf       187    SunOS Specific                              */
+#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
+#define __NR_tkill              187 /* SunOS: fpathconf                            */
 /* #define __NR_sysconf         188    SunOS Specific                              */
 #define __NR_uname              189 /* Linux Specific                              */
 #define __NR_init_module        190 /* Linux Specific                              */
diff -Nru a/include/asm-sparc64/a.out.h b/include/asm-sparc64/a.out.h
--- a/include/asm-sparc64/a.out.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/a.out.h	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: a.out.h,v 1.7 2001/04/24 01:09:12 davem Exp $ */
+/* $Id: a.out.h,v 1.8 2002/02/09 19:49:31 davem Exp $ */
 #ifndef __SPARC64_A_OUT_H__
 #define __SPARC64_A_OUT_H__
 
@@ -95,7 +95,7 @@
 
 #ifdef __KERNEL__
 
-#define STACK_TOP (current->thread.flags & SPARC_FLAG_32BIT ? 0xf0000000 : 0x80000000000L)
+#define STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
 
 #endif
 
diff -Nru a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
--- a/include/asm-sparc64/bitops.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/bitops.h	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.38 2001/11/19 18:36:34 davem Exp $
+/* $Id: bitops.h,v 1.39 2002/01/30 01:40:00 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -64,54 +64,38 @@
 #define smp_mb__before_clear_bit()	do { } while(0)
 #define smp_mb__after_clear_bit()	do { } while(0)
 
-extern __inline__ int test_bit(int nr, __const__ void *addr)
+static __inline__ int test_bit(int nr, __const__ void *addr)
 {
 	return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL;
 }
 
 /* The easy/cheese version for now. */
-extern __inline__ unsigned long ffz(unsigned long word)
+static __inline__ unsigned long ffz(unsigned long word)
 {
 	unsigned long result;
 
-#ifdef ULTRA_HAS_POPULATION_COUNT	/* Thanks for nothing Sun... */
-	__asm__ __volatile__(
-"	brz,pn	%0, 1f\n"
-"	 neg	%0, %%g1\n"
-"	xnor	%0, %%g1, %%g2\n"
-"	popc	%%g2, %0\n"
-"1:	" : "=&r" (result)
-	  : "0" (word)
-	  : "g1", "g2");
-#else
-#if 1 /* def EASY_CHEESE_VERSION */
 	result = 0;
 	while(word & 1) {
 		result++;
 		word >>= 1;
 	}
-#else
-	unsigned long tmp;
+	return result;
+}
 
-	result = 0;	
-	tmp = ~word & -~word;
-	if (!(unsigned)tmp) {
-		tmp >>= 32;
-		result = 32;
-	}
-	if (!(unsigned short)tmp) {
-		tmp >>= 16;
-		result += 16;
-	}
-	if (!(unsigned char)tmp) {
-		tmp >>= 8;
-		result += 8;
-	}
-	if (tmp & 0xf0) result += 4;
-	if (tmp & 0xcc) result += 2;
-	if (tmp & 0xaa) result ++;
-#endif
-#endif
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+	unsigned long result = 0;
+
+	while (!(word & 1UL)) {
+		result++;
+		word >>= 1;
+	}
 	return result;
 }
 
@@ -122,8 +106,12 @@
  * the libc and compiler builtin ffs routines, therefore
  * differs in spirit from the above ffz (man ffs).
  */
-
-#define ffs(x) generic_ffs(x)
+static __inline__ int ffs(int x)
+{
+	if (!x)
+		return 0;
+	return __ffs((unsigned long)x);
+}
 
 /*
  * hweightN: returns the hamming weight (i.e. the number
@@ -132,7 +120,7 @@
 
 #ifdef ULTRA_HAS_POPULATION_COUNT
 
-extern __inline__ unsigned int hweight32(unsigned int w)
+static __inline__ unsigned int hweight32(unsigned int w)
 {
 	unsigned int res;
 
@@ -140,7 +128,7 @@
 	return res;
 }
 
-extern __inline__ unsigned int hweight16(unsigned int w)
+static __inline__ unsigned int hweight16(unsigned int w)
 {
 	unsigned int res;
 
@@ -148,7 +136,7 @@
 	return res;
 }
 
-extern __inline__ unsigned int hweight8(unsigned int w)
+static __inline__ unsigned int hweight8(unsigned int w)
 {
 	unsigned int res;
 
@@ -165,12 +153,67 @@
 #endif
 #endif /* __KERNEL__ */
 
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+static __inline__ unsigned long find_next_bit(void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
+	unsigned long result = offset & ~63UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 63UL;
+	if (offset) {
+		tmp = *(p++);
+		tmp &= (~0UL << offset);
+		if (size < 64)
+			goto found_first;
+		if (tmp)
+			goto found_middle;
+		size -= 64;
+		result += 64;
+	}
+	while (size & ~63UL) {
+		if ((tmp = *(p++)))
+			goto found_middle;
+		result += 64;
+		size -= 64;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp &= (~0UL >> (64 - size));
+	if (tmp == 0UL)        /* Are any bits set? */
+		return result + size; /* Nope. */
+found_middle:
+	return result + __ffs(tmp);
+}
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+#define find_first_bit(addr, size) \
+	find_next_bit((addr), (size), 0)
+
 /* find_next_zero_bit() finds the first zero bit in a bit string of length
  * 'size' bits, starting the search at bit 'offset'. This is largely based
  * on Linus's ALPHA routines, which are pretty portable BTW.
  */
 
-extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+static __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
 	unsigned long result = offset & ~63UL;
@@ -219,7 +262,7 @@
 #define set_le_bit(nr,addr)		((void)___test_and_set_le_bit(nr,addr))
 #define clear_le_bit(nr,addr)		((void)___test_and_clear_le_bit(nr,addr))
 
-extern __inline__ int test_le_bit(int nr, __const__ void * addr)
+static __inline__ int test_le_bit(int nr, __const__ void * addr)
 {
 	int			mask;
 	__const__ unsigned char	*ADDR = (__const__ unsigned char *) addr;
@@ -232,7 +275,7 @@
 #define find_first_zero_le_bit(addr, size) \
         find_next_zero_le_bit((addr), (size), 0)
 
-extern __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset)
+static __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
 	unsigned long result = offset & ~63UL;
diff -Nru a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
--- a/include/asm-sparc64/checksum.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/checksum.h	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.17 2001/04/24 01:09:12 davem Exp $ */
+/* $Id: checksum.h,v 1.19 2002/02/09 19:49:31 davem Exp $ */
 #ifndef __SPARC64_CHECKSUM_H
 #define __SPARC64_CHECKSUM_H
 
@@ -16,7 +16,8 @@
  *      RFC1071 Computing the Internet Checksum
  */
 
-#include <asm/uaccess.h> 
+#include <linux/in6.h>
+#include <asm/uaccess.h>
 
 /* computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
@@ -44,7 +45,7 @@
 			   unsigned int sum)
 {
 	int ret;
-	unsigned char cur_ds = current->thread.current_ds.seg;
+	unsigned char cur_ds = get_thread_current_ds();
 	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_P));
 	ret = csum_partial_copy_sparc64(src, dst, len, sum);
 	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" (cur_ds));
diff -Nru a/include/asm-sparc64/current.h b/include/asm-sparc64/current.h
--- a/include/asm-sparc64/current.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/current.h	Sun Feb 10 19:58:04 2002
@@ -1,7 +1,8 @@
 #ifndef _SPARC64_CURRENT_H
 #define _SPARC64_CURRENT_H
 
-/* Sparc rules... */
-register struct task_struct *current asm("g6");
+#include <asm/thread_info.h>
+
+#define current		(current_thread_info()->task)
 
 #endif /* !(_SPARC64_CURRENT_H) */
diff -Nru a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
--- a/include/asm-sparc64/delay.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/delay.h	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: delay.h,v 1.12 2001/04/24 01:09:12 davem Exp $
+/* $Id: delay.h,v 1.13 2002/02/02 03:33:48 kanoj Exp $
  * delay.h: Linux delay routines on the V9.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
@@ -9,9 +9,13 @@
 
 #include <linux/config.h>
 #include <linux/param.h>
+
+#ifndef __ASSEMBLY__
+
 #ifdef CONFIG_SMP
-#include <linux/sched.h>
 #include <asm/smp.h>
+#else
+extern unsigned long loops_per_jiffy;
 #endif 
 
 extern __inline__ void __delay(unsigned long loops)
@@ -48,5 +52,7 @@
 #endif
 
 #define udelay(usecs) __udelay((usecs),__udelay_val)
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* defined(__SPARC64_DELAY_H) */
diff -Nru a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
--- a/include/asm-sparc64/elf.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/elf.h	Sun Feb 10 19:58:05 2002
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.31 2002/01/08 16:00:20 davem Exp $ */
+/* $Id: elf.h,v 1.32 2002/02/09 19:49:31 davem Exp $ */
 #ifndef __ASM_SPARC64_ELF_H
 #define __ASM_SPARC64_ELF_H
 
@@ -69,16 +69,11 @@
 
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex, ibcs2)			\
-do {	unsigned char flags = current->thread.flags;	\
-	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)	\
-		flags |= SPARC_FLAG_32BIT;		\
+do {	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)	\
+		set_thread_flag(TIF_32BIT);		\
 	else						\
-		flags &= ~SPARC_FLAG_32BIT;		\
-	if (flags != current->thread.flags) {		\
-		/* flush_thread will update pgd cache */\
-		current->thread.flags = flags;		\
-	}						\
-							\
+		clear_thread_flag(TIF_32BIT);		\
+	/* flush_thread will update pgd cache */	\
 	if (ibcs2)					\
 		set_personality(PER_SVR4);		\
 	else if (current->personality != PER_LINUX32)	\
diff -Nru a/include/asm-sparc64/fpumacro.h b/include/asm-sparc64/fpumacro.h
--- a/include/asm-sparc64/fpumacro.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/fpumacro.h	Sun Feb 10 19:58:04 2002
@@ -14,7 +14,7 @@
 	u32	regs[64];
 };
 
-#define FPUSTATE (struct fpustate *)(((unsigned long)current) + AOFF_task_fpregs)
+#define FPUSTATE (struct fpustate *)(current_thread_info()->fpregs)
 
 extern __inline__ unsigned long fprs_read(void)
 {
diff -Nru a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
--- a/include/asm-sparc64/hardirq.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/hardirq.h	Sun Feb 10 19:58:04 2002
@@ -56,6 +56,8 @@
 
 #define synchronize_irq()	barrier()
 
+#define release_irqlock(cpu)	do { } while (0)
+
 #else /* (CONFIG_SMP) */
 
 static __inline__ int irqs_running(void)
diff -Nru a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
--- a/include/asm-sparc64/mmu_context.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-sparc64/mmu_context.h	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.52 2002/01/11 08:45:38 davem Exp $ */
+/* $Id: mmu_context.h,v 1.54 2002/02/09 19:49:31 davem Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
@@ -30,22 +30,20 @@
 /*
  * Every architecture must define this function. It's the fastest
  * way of searching a 168-bit bitmap where the first 128 bits are
- * unlikely to be clear. It's guaranteed that at least one of the 168
+ * unlikely to be set. It's guaranteed that at least one of the 168
  * bits is cleared.
  */
 #if MAX_RT_PRIO != 128 || MAX_PRIO != 168
 # error update this function.
 #endif
 
-static inline int sched_find_first_zero_bit(unsigned long *b)
+static inline int sched_find_first_bit(unsigned long *b)
 {
-	unsigned long rt;
-
-	rt = b[0] & b[1];
-	if (unlikely(rt != 0xffffffffffffffff))
-		return find_first_zero_bit(b, MAX_RT_PRIO);
-
-	return ffz(b[2]) + MAX_RT_PRIO;
+	if (unlikely(b[0]))
+		return __ffs(b[0]);
+	if (unlikely(b[1]))
+		return __ffs(b[1]) + 64;
+	return __ffs(b[2]) + 128;
 }
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
@@ -103,7 +101,7 @@
 	register unsigned long pgd_cache asm("o4"); \
 	paddr = __pa((__mm)->pgd); \
 	pgd_cache = 0UL; \
-	if ((__tsk)->thread.flags & SPARC_FLAG_32BIT) \
+	if ((__tsk)->thread_info->flags & _TIF_32BIT) \
 		pgd_cache = pgd_val((__mm)->pgd[0]) << 11UL; \
 	__asm__ __volatile__("wrpr	%%g0, 0x494, %%pstate\n\t" \
 			     "mov	%3, %%g4\n\t" \
diff -Nru a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
--- a/include/asm-sparc64/page.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-sparc64/page.h	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.38 2001/11/30 01:04:10 davem Exp $ */
+/* $Id: page.h,v 1.39 2002/02/09 19:49:31 davem Exp $ */
 
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
@@ -95,7 +95,7 @@
 
 #endif /* (STRICT_MM_TYPECHECKS) */
 
-#define TASK_UNMAPPED_BASE	((current->thread.flags & SPARC_FLAG_32BIT) ? \
+#define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_32BIT) ? \
 				 (0x0000000070000000UL) : (PAGE_OFFSET))
 
 #endif /* !(__ASSEMBLY__) */
diff -Nru a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
--- a/include/asm-sparc64/pgalloc.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/pgalloc.h	Sun Feb 10 19:58:05 2002
@@ -158,6 +158,7 @@
 {
 	struct page *page = virt_to_page(pgd);
 
+	preempt_disable();
 	if (!page->pprev_hash) {
 		(unsigned long *)page->next_hash = pgd_quicklist;
 		pgd_quicklist = (unsigned long *)page;
@@ -165,12 +166,14 @@
 	(unsigned long)page->pprev_hash |=
 		(((unsigned long)pgd & (PAGE_SIZE / 2)) ? 2 : 1);
 	pgd_cache_size++;
+	preempt_enable();
 }
 
 extern __inline__ pgd_t *get_pgd_fast(void)
 {
         struct page *ret;
 
+	preempt_disable();
         if ((ret = (struct page *)pgd_quicklist) != NULL) {
                 unsigned long mask = (unsigned long)ret->pprev_hash;
 		unsigned long off = 0;
@@ -186,16 +189,22 @@
 			pgd_quicklist = (unsigned long *)ret->next_hash;
                 ret = (struct page *)(__page_address(ret) + off);
                 pgd_cache_size--;
+		preempt_enable();
         } else {
-		struct page *page = alloc_page(GFP_KERNEL);
+		struct page *page;
 
+		preempt_enable();
+		page = alloc_page(GFP_KERNEL);
 		if (page) {
 			ret = (struct page *)page_address(page);
 			clear_page(ret);
 			(unsigned long)page->pprev_hash = 2;
+
+			preempt_disable();
 			(unsigned long *)page->next_hash = pgd_quicklist;
 			pgd_quicklist = (unsigned long *)page;
 			pgd_cache_size++;
+			preempt_enable();
 		}
         }
         return (pgd_t *)ret;
@@ -205,20 +214,25 @@
 
 extern __inline__ void free_pgd_fast(pgd_t *pgd)
 {
+	preempt_disable();
 	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
 	pgd_quicklist = (unsigned long *) pgd;
 	pgtable_cache_size++;
+	preempt_enable();
 }
 
 extern __inline__ pgd_t *get_pgd_fast(void)
 {
 	unsigned long *ret;
 
+	preempt_disable();
 	if((ret = pgd_quicklist) != NULL) {
 		pgd_quicklist = (unsigned long *)(*ret);
 		ret[0] = 0;
 		pgtable_cache_size--;
+		preempt_enable();
 	} else {
+		preempt_enable();
 		ret = (unsigned long *) __get_free_page(GFP_KERNEL);
 		if(ret)
 			memset(ret, 0, PAGE_SIZE);
@@ -258,20 +272,27 @@
 
 	if (pte_quicklist[color] == NULL)
 		color = 1;
+
+	preempt_disable();
 	if((ret = (unsigned long *)pte_quicklist[color]) != NULL) {
 		pte_quicklist[color] = (unsigned long *)(*ret);
 		ret[0] = 0;
 		pgtable_cache_size--;
 	}
+	preempt_enable();
+
 	return (pmd_t *)ret;
 }
 
 extern __inline__ void free_pmd_fast(pmd_t *pmd)
 {
 	unsigned long color = DCACHE_COLOR((unsigned long)pmd);
+
+	preempt_disable();
 	*(unsigned long *)pmd = (unsigned long) pte_quicklist[color];
 	pte_quicklist[color] = (unsigned long *) pmd;
 	pgtable_cache_size++;
+	preempt_enable();
 }
 
 extern __inline__ void free_pmd_slow(pmd_t *pmd)
@@ -288,20 +309,25 @@
 	unsigned long color = VPTE_COLOR(address);
 	unsigned long *ret;
 
+	preempt_disable();
 	if((ret = (unsigned long *)pte_quicklist[color]) != NULL) {
 		pte_quicklist[color] = (unsigned long *)(*ret);
 		ret[0] = 0;
 		pgtable_cache_size--;
 	}
+	preempt_enable();
 	return (pte_t *)ret;
 }
 
 extern __inline__ void free_pte_fast(pte_t *pte)
 {
 	unsigned long color = DCACHE_COLOR((unsigned long)pte);
+
+	preempt_disable();
 	*(unsigned long *)pte = (unsigned long) pte_quicklist[color];
 	pte_quicklist[color] = (unsigned long *) pte;
 	pgtable_cache_size++;
+	preempt_enable();
 }
 
 extern __inline__ void free_pte_slow(pte_t *pte)
diff -Nru a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
--- a/include/asm-sparc64/pgtable.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-sparc64/pgtable.h	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.155 2001/12/21 04:56:17 davem Exp $
+/* $Id: pgtable.h,v 1.156 2002/02/09 19:49:31 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -76,7 +76,7 @@
  * is different so we can optimize correctly for 32-bit tasks.
  */
 #define REAL_PTRS_PER_PMD	(1UL << PMD_BITS)
-#define PTRS_PER_PMD		((const int)((current->thread.flags & SPARC_FLAG_32BIT) ? \
+#define PTRS_PER_PMD		((const int)(test_thread_flag(TIF_32BIT) ? \
 				 (1UL << (32 - (PAGE_SHIFT-3) - PAGE_SHIFT)) : (REAL_PTRS_PER_PMD)))
 
 /*
@@ -90,8 +90,8 @@
 			(PAGE_SHIFT-3) + PMD_BITS)))
 
 /* Kernel has a separate 44bit address space. */
-#define USER_PTRS_PER_PGD	((const int)((current->thread.flags & SPARC_FLAG_32BIT) ? \
-				 (1) : (PTRS_PER_PGD)))
+#define USER_PTRS_PER_PGD	((const int)(test_thread_flag(TIF_32BIT)) ? \
+				 (1) : (PTRS_PER_PGD))
 #define FIRST_USER_PGD_NR	0
 
 #define pte_ERROR(e)	__builtin_trap()
diff -Nru a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
--- a/include/asm-sparc64/processor.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-sparc64/processor.h	Sun Feb 10 19:58:03 2002
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.80 2001/11/17 00:10:48 davem Exp $
+/* $Id: processor.h,v 1.83 2002/02/10 06:04:33 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -21,6 +21,7 @@
 #include <asm/signal.h>
 #include <asm/segment.h>
 #include <asm/page.h>
+#include <asm/delay.h>
 
 /* Bus types */
 #define EISA_bus 0
@@ -43,29 +44,13 @@
 
 #ifndef __ASSEMBLY__
 
-#define NSWINS		7
-
 typedef struct {
 	unsigned char seg;
 } mm_segment_t;
 
 /* The Sparc processor specific thread struct. */
+/* XXX This should die, everything can go into thread_info now. */
 struct thread_struct {
-	/* D$ line 1 */
-	unsigned long ksp __attribute__ ((aligned(16)));
-	unsigned char wstate, cwp, flags;
-	mm_segment_t current_ds;
-	unsigned char w_saved, fpdepth, fault_code, use_blkcommit;
-	unsigned long fault_address;
-	unsigned char fpsaved[7];
-	unsigned char __pad2;
-	
-	/* D$ line 2, 3, 4 */
-	struct pt_regs *kregs;
-	unsigned long *utraps;
-	unsigned long gsr[7];
-	unsigned long xfsr[7];
-
 #ifdef CONFIG_DEBUG_SPINLOCK
 	/* How many spinlocks held by this thread.
 	 * Used with spin lock debugging to catch tasks
@@ -73,96 +58,29 @@
 	 */
 	int smp_lock_count;
 	unsigned int smp_lock_pc;
+#else
+	int dummy; /* f'in gcc bug... */
 #endif
-
-	struct reg_window reg_window[NSWINS];
-	unsigned long rwbuf_stkptrs[NSWINS];
-	
-	/* Performance counter state */
-	u64 *user_cntd0, *user_cntd1;
-	u64 kernel_cntd0, kernel_cntd1;
-	u64 pcr_reg;
 };
 
 #endif /* !(__ASSEMBLY__) */
 
-#define SPARC_FLAG_UNALIGNED    0x01    /* is allowed to do unaligned accesses	*/
-#define SPARC_FLAG_NEWSIGNALS   0x02    /* task wants new-style signals		*/
-#define SPARC_FLAG_32BIT        0x04    /* task is older 32-bit binary		*/
-#define SPARC_FLAG_NEWCHILD     0x08    /* task is just-spawned child process	*/
-#define SPARC_FLAG_PERFCTR	0x10    /* task has performance counters active	*/
-
-#define FAULT_CODE_WRITE	0x01	/* Write access, implies D-TLB		*/
-#define FAULT_CODE_DTLB		0x02	/* Miss happened in D-TLB		*/
-#define FAULT_CODE_ITLB		0x04	/* Miss happened in I-TLB		*/
-#define FAULT_CODE_WINFIXUP	0x08	/* Miss happened during spill/fill	*/
-
 #ifndef CONFIG_DEBUG_SPINLOCK
-#define INIT_THREAD  {					\
-/* ksp, wstate, cwp, flags, current_ds, */ 		\
-   0,   0,      0,   0,     KERNEL_DS,			\
-/* w_saved, fpdepth, fault_code, use_blkcommit, */	\
-   0,       0,       0,          0,			\
-/* fault_address, fpsaved, __pad2, kregs, */		\
-   0,             { 0 },   0,      0,			\
-/* utraps, gsr,   xfsr, */				\
-   0,	   { 0 }, { 0 },				\
-/* reg_window */					\
-   { { { 0, }, { 0, } }, }, 				\
-/* rwbuf_stkptrs */					\
-   { 0, 0, 0, 0, 0, 0, 0, },				\
-/* user_cntd0, user_cndd1, kernel_cntd0, kernel_cntd0, pcr_reg */ \
-   0,          0,          0,		 0,            0, \
+#define INIT_THREAD  {			\
+	0,				\
 }
 #else /* CONFIG_DEBUG_SPINLOCK */
 #define INIT_THREAD  {					\
-/* ksp, wstate, cwp, flags, current_ds, */ 		\
-   0,   0,      0,   0,     KERNEL_DS,			\
-/* w_saved, fpdepth, fault_code, use_blkcommit, */	\
-   0,       0,       0,          0,			\
-/* fault_address, fpsaved, __pad2, kregs, */		\
-   0,             { 0 },   0,      0,			\
-/* utraps, gsr,   xfsr,  smp_lock_count, smp_lock_pc, */\
-   0,	   { 0 }, { 0 }, 0,		 0,		\
-/* reg_window */					\
-   { { { 0, }, { 0, } }, }, 				\
-/* rwbuf_stkptrs */					\
-   { 0, 0, 0, 0, 0, 0, 0, },				\
-/* user_cntd0, user_cndd1, kernel_cntd0, kernel_cntd0, pcr_reg */ \
-   0,          0,          0,		 0,            0, \
+/* smp_lock_count, smp_lock_pc, */			\
+   0,		   0,					\
 }
 #endif /* !(CONFIG_DEBUG_SPINLOCK) */
 
-#ifdef __KERNEL__
-#if PAGE_SHIFT == 13
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define THREAD_SHIFT (PAGE_SHIFT + 1)
-#else /* PAGE_SHIFT == 13 */
-#define THREAD_SIZE PAGE_SIZE
-#define THREAD_SHIFT PAGE_SHIFT
-#endif /* PAGE_SHIFT == 13 */
-#endif /* __KERNEL__ */
-
 #ifndef __ASSEMBLY__
 
 /* Return saved PC of a blocked thread. */
-extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
-{
-	unsigned long ret = 0xdeadbeefUL;
-	
-	if (t->ksp) {
-		unsigned long *sp;
-		sp = (unsigned long *)(t->ksp + STACK_BIAS);
-		if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL &&
-		    sp[14]) {
-			unsigned long *fp;
-			fp = (unsigned long *)(sp[14] + STACK_BIAS);
-			if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL)
-				ret = fp[15];
-		}
-	}
-	return ret;
-}
+struct task_struct;
+extern unsigned long thread_saved_pc(struct task_struct *);
 
 /* On Uniprocessor, even in RMO processes see TSO semantics */
 #ifdef CONFIG_SMP
@@ -178,13 +96,13 @@
 	regs->tpc = ((pc & (~3)) - 4); \
 	regs->tnpc = regs->tpc + 4; \
 	regs->y = 0; \
-	current->thread.wstate = (1 << 3); \
-	if (current->thread.utraps) { \
-		if (*(current->thread.utraps) < 2) \
-			kfree (current->thread.utraps); \
+	set_thread_wstate(1 << 3); \
+	if (current_thread_info()->utraps) { \
+		if (*(current_thread_info()->utraps) < 2) \
+			kfree(current_thread_info()->utraps); \
 		else \
-			(*(current->thread.utraps))--; \
-		current->thread.utraps = NULL; \
+			(*(current_thread_info()->utraps))--; \
+		current_thread_info()->utraps = NULL; \
 	} \
 	__asm__ __volatile__( \
 	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
@@ -207,7 +125,7 @@
 	: \
 	: "r" (regs), "r" (sp - REGWIN_SZ - STACK_BIAS), \
 	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
-} while(0)
+} while (0)
 
 #define start_thread32(regs, pc, sp) \
 do { \
@@ -218,13 +136,13 @@
 	regs->tpc = ((pc & (~3)) - 4); \
 	regs->tnpc = regs->tpc + 4; \
 	regs->y = 0; \
-	current->thread.wstate = (2 << 3); \
-	if (current->thread.utraps) { \
-		if (*(current->thread.utraps) < 2) \
-			kfree (current->thread.utraps); \
+	set_thread_wstate(2 << 3); \
+	if (current_thread_info()->utraps) { \
+		if (*(current_thread_info()->utraps) < 2) \
+			kfree(current_thread_info()->utraps); \
 		else \
-			(*(current->thread.utraps))--; \
-		current->thread.utraps = NULL; \
+			(*(current_thread_info()->utraps))--; \
+		current_thread_info()->utraps = NULL; \
 	} \
 	__asm__ __volatile__( \
 	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
@@ -247,10 +165,10 @@
 	: \
 	: "r" (regs), "r" (sp - REGWIN32_SZ), \
 	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
-} while(0)
+} while (0)
 
 /* Free all resources held by a thread. */
-#define release_thread(tsk)		do { } while(0)
+#define release_thread(tsk)		do { } while (0)
 
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
@@ -261,19 +179,20 @@
 ({	extern void scheduling_functions_start_here(void); \
 	extern void scheduling_functions_end_here(void); \
 	unsigned long pc, fp, bias = 0; \
-	unsigned long task_base = (unsigned long) (__TSK); \
+	unsigned long thread_info_base; \
 	struct reg_window *rw; \
         unsigned long __ret = 0; \
 	int count = 0; \
 	if (!(__TSK) || (__TSK) == current || \
             (__TSK)->state == TASK_RUNNING) \
 		goto __out; \
+	thread_info_base = (unsigned long) ((__TSK)->thread_info); \
 	bias = STACK_BIAS; \
-	fp = (__TSK)->thread.ksp + bias; \
+	fp = (__TSK)->thread_info->ksp + bias; \
 	do { \
 		/* Bogus frame pointer? */ \
-		if (fp < (task_base + sizeof(struct task_struct)) || \
-		    fp >= (task_base + THREAD_SIZE)) \
+		if (fp < (thread_info_base + sizeof(struct thread_info)) || \
+		    fp >= (thread_info_base + THREAD_SIZE)) \
 			break; \
 		rw = (struct reg_window *) fp; \
 		pc = rw->ins[7]; \
@@ -287,26 +206,10 @@
 __out:	__ret; \
 })
 
-#define KSTK_EIP(tsk)  ((tsk)->thread.kregs->tpc)
-#define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
-
-#ifdef __KERNEL__
-/* Allocation and freeing of task_struct and kernel stack. */
-#if PAGE_SHIFT == 13
-#define alloc_task_struct()   ((struct task_struct *)__get_free_pages(GFP_KERNEL, 1))
-#define free_task_struct(tsk) free_pages((unsigned long)(tsk),1)
-#else /* PAGE_SHIFT == 13 */
-#define alloc_task_struct()   ((struct task_struct *)__get_free_pages(GFP_KERNEL, 0))
-#define free_task_struct(tsk) free_pages((unsigned long)(tsk),0)
-#endif /* PAGE_SHIFT == 13 */
-#define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
-
-#define init_task	(init_task_union.task)
-#define init_stack	(init_task_union.stack)
-
-#define cpu_relax()	do { } while (0)
+#define KSTK_EIP(tsk)  ((tsk)->thread_info->kregs->tpc)
+#define KSTK_ESP(tsk)  ((tsk)->thread_info->kregs->u_regs[UREG_FP])
 
-#endif /* __KERNEL__ */
+#define cpu_relax()	udelay(1 + smp_processor_id())
 
 #endif /* !(__ASSEMBLY__) */
 
diff -Nru a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
--- a/include/asm-sparc64/ptrace.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/ptrace.h	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: ptrace.h,v 1.13 1997/09/17 17:27:51 davem Exp $ */
+/* $Id: ptrace.h,v 1.14 2002/02/09 19:49:32 davem Exp $ */
 #ifndef _SPARC64_PTRACE_H
 #define _SPARC64_PTRACE_H
 
@@ -110,8 +110,6 @@
 #define TRACEREG32_SZ		0x50
 #define STACKFRAME32_SZ		0x60
 #define REGWIN32_SZ		0x40
-
-#include <asm/asm_offsets.h>
 #endif
 
 #ifdef __KERNEL__
diff -Nru a/include/asm-sparc64/scatterlist.h b/include/asm-sparc64/scatterlist.h
--- a/include/asm-sparc64/scatterlist.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-sparc64/scatterlist.h	Sun Feb 10 19:58:06 2002
@@ -1,23 +1,17 @@
-/* $Id: scatterlist.h,v 1.10 2001/10/09 02:24:35 davem Exp $ */
+/* $Id: scatterlist.h,v 1.11 2001/12/17 07:05:15 davem Exp $ */
 #ifndef _SPARC64_SCATTERLIST_H
 #define _SPARC64_SCATTERLIST_H
 
 #include <asm/page.h>
 
 struct scatterlist {
-	/* This will disappear in 2.5.x */
-	char *address;
+	struct page	*page;
+	unsigned int	offset;
 
-	/* These two are only valid if ADDRESS member of this
-	 * struct is NULL.
-	 */
-	struct page *page;
-	unsigned int offset;
+	unsigned int	length;
 
-	unsigned int length;
-
-	dma_addr_t dma_address;
-	__u32 dma_length;
+	dma_addr_t	dma_address;
+	__u32		dma_length;
 };
 
 #define sg_dma_address(sg)	((sg)->dma_address)
diff -Nru a/include/asm-sparc64/sfp-machine.h b/include/asm-sparc64/sfp-machine.h
--- a/include/asm-sparc64/sfp-machine.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/sfp-machine.h	Sun Feb 10 19:58:05 2002
@@ -74,7 +74,7 @@
 
 /* Obtain the current rounding mode. */
 #ifndef FP_ROUNDMODE
-#define FP_ROUNDMODE	((current->thread.xfsr[0] >> 30) & 0x3)
+#define FP_ROUNDMODE	((current_thread_info()->xfsr[0] >> 30) & 0x3)
 #endif
 
 /* Exception flags. */
@@ -86,6 +86,6 @@
 
 #define FP_HANDLE_EXCEPTIONS return _fex
 
-#define FP_INHIBIT_RESULTS ((current->thread.xfsr[0] >> 23) & _fex)
+#define FP_INHIBIT_RESULTS ((current_thread_info()->xfsr[0] >> 23) & _fex)
 
 #endif
diff -Nru a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
--- a/include/asm-sparc64/siginfo.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/siginfo.h	Sun Feb 10 19:58:05 2002
@@ -172,6 +172,7 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
+#define SI_TKILL	-6		/* sent by tkill system call */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
--- a/include/asm-sparc64/smp.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/smp.h	Sun Feb 10 19:58:05 2002
@@ -103,7 +103,7 @@
 	}
 }
 
-#define smp_processor_id() (current->cpu)
+#define smp_processor_id() (current_thread_info()->cpu)
 
 /* This needn't do anything as we do not sleep the cpu
  * inside of the idler task, so an interrupt is not needed
diff -Nru a/include/asm-sparc64/smplock.h b/include/asm-sparc64/smplock.h
--- a/include/asm-sparc64/smplock.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/smplock.h	Sun Feb 10 19:58:05 2002
@@ -9,9 +9,17 @@
 
 extern spinlock_t kernel_flag;
 
+#ifdef CONFIG_SMP
 #define kernel_locked()			\
 	(spin_is_locked(&kernel_flag) &&\
 	 (current->lock_depth >= 0))
+#else
+#ifdef CONFIG_PREEMPT
+#define kernel_locked()			preempt_get_count()
+#else
+#define kernel_locked()			1
+#endif
+#endif
 
 /*
  * Release global kernel lock and global interrupt lock
diff -Nru a/include/asm-sparc64/softirq.h b/include/asm-sparc64/softirq.h
--- a/include/asm-sparc64/softirq.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-sparc64/softirq.h	Sun Feb 10 19:58:06 2002
@@ -10,14 +10,15 @@
 #include <asm/hardirq.h>
 #include <asm/system.h>		/* for membar() */
 
-#define local_bh_disable()	(local_bh_count(smp_processor_id())++)
-#define __local_bh_enable()	(local_bh_count(smp_processor_id())--)
+#define local_bh_disable()	do { barrier(); preempt_disable(); local_bh_count(smp_processor_id())++; } while (0)
+#define __local_bh_enable()	do { local_bh_count(smp_processor_id())--; preempt_enable(); barrier(); } while (0)
 #define local_bh_enable()			  \
 do { if (!--local_bh_count(smp_processor_id()) && \
 	 softirq_pending(smp_processor_id())) {   \
 		do_softirq();			  \
 		__sti();			  \
      }						  \
+     preempt_enable();				  \
 } while (0)
 
 #define in_softirq() (local_bh_count(smp_processor_id()) != 0)
diff -Nru a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
--- a/include/asm-sparc64/spinlock.h	Sun Feb 10 19:58:05 2002
+++ b/include/asm-sparc64/spinlock.h	Sun Feb 10 19:58:05 2002
@@ -40,7 +40,7 @@
 do {	membar("#LoadLoad");	\
 } while(*((volatile unsigned char *)lock))
 
-extern __inline__ void spin_lock(spinlock_t *lock)
+extern __inline__ void _raw_spin_lock(spinlock_t *lock)
 {
 	__asm__ __volatile__(
 "1:	ldstub		[%0], %%g7\n"
@@ -57,7 +57,7 @@
 	: "g7", "memory");
 }
 
-extern __inline__ int spin_trylock(spinlock_t *lock)
+extern __inline__ int _raw_spin_trylock(spinlock_t *lock)
 {
 	unsigned int result;
 	__asm__ __volatile__("ldstub [%1], %0\n\t"
@@ -68,7 +68,7 @@
 	return (result == 0);
 }
 
-extern __inline__ void spin_unlock(spinlock_t *lock)
+extern __inline__ void _raw_spin_unlock(spinlock_t *lock)
 {
 	__asm__ __volatile__("membar	#StoreStore | #LoadStore\n\t"
 			     "stb	%%g0, [%0]"
@@ -99,9 +99,9 @@
 extern void _do_spin_unlock (spinlock_t *lock);
 extern int _spin_trylock (spinlock_t *lock);
 
-#define spin_trylock(lp)	_spin_trylock(lp)
-#define spin_lock(lock)		_do_spin_lock(lock, "spin_lock")
-#define spin_unlock(lock)	_do_spin_unlock(lock)
+#define _raw_spin_trylock(lp)	_spin_trylock(lp)
+#define _raw_spin_lock(lock)	_do_spin_lock(lock, "spin_lock")
+#define _raw_spin_unlock(lock)	_do_spin_unlock(lock)
 
 #endif /* CONFIG_DEBUG_SPINLOCK */
 
@@ -118,10 +118,10 @@
 extern void __write_lock(rwlock_t *);
 extern void __write_unlock(rwlock_t *);
 
-#define read_lock(p)	__read_lock(p)
-#define read_unlock(p)	__read_unlock(p)
-#define write_lock(p)	__write_lock(p)
-#define write_unlock(p)	__write_unlock(p)
+#define _raw_read_lock(p)	__read_lock(p)
+#define _raw_read_unlock(p)	__read_unlock(p)
+#define _raw_write_lock(p)	__write_lock(p)
+#define _raw_write_unlock(p)	__write_unlock(p)
 
 #else /* !(CONFIG_DEBUG_SPINLOCK) */
 
@@ -138,28 +138,28 @@
 extern void _do_write_lock(rwlock_t *rw, char *str);
 extern void _do_write_unlock(rwlock_t *rw);
 
-#define read_lock(lock)	\
+#define _raw_read_lock(lock) \
 do {	unsigned long flags; \
 	__save_and_cli(flags); \
 	_do_read_lock(lock, "read_lock"); \
 	__restore_flags(flags); \
 } while(0)
 
-#define read_unlock(lock) \
+#define _raw_read_unlock(lock) \
 do {	unsigned long flags; \
 	__save_and_cli(flags); \
 	_do_read_unlock(lock, "read_unlock"); \
 	__restore_flags(flags); \
 } while(0)
 
-#define write_lock(lock) \
+#define _raw_write_lock(lock) \
 do {	unsigned long flags; \
 	__save_and_cli(flags); \
 	_do_write_lock(lock, "write_lock"); \
 	__restore_flags(flags); \
 } while(0)
 
-#define write_unlock(lock) \
+#define _raw_write_unlock(lock) \
 do {	unsigned long flags; \
 	__save_and_cli(flags); \
 	_do_write_unlock(lock); \
diff -Nru a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
--- a/include/asm-sparc64/system.h	Sun Feb 10 19:58:03 2002
+++ b/include/asm-sparc64/system.h	Sun Feb 10 19:58:03 2002
@@ -1,12 +1,12 @@
-/* $Id: system.h,v 1.68 2001/11/18 00:12:56 davem Exp $ */
+/* $Id: system.h,v 1.69 2002/02/09 19:49:31 davem Exp $ */
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
 #include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/asm_offsets.h>
 #include <asm/visasm.h>
+#include <asm/thread_info.h>
 
 #ifndef __ASSEMBLY__
 /*
@@ -174,19 +174,19 @@
 	 */
 #define switch_to(prev, next, last)						\
 do {	CHECK_LOCKS(prev);							\
-	if (current->thread.flags & SPARC_FLAG_PERFCTR) {			\
+	if (test_thread_flag(TIF_PERFCTR)) {					\
 		unsigned long __tmp;						\
 		read_pcr(__tmp);						\
-		current->thread.pcr_reg = __tmp;				\
+		current_thread_info()->pcr_reg = __tmp;				\
 		read_pic(__tmp);						\
-		current->thread.kernel_cntd0 += (unsigned int)(__tmp);		\
-		current->thread.kernel_cntd1 += ((__tmp) >> 32);		\
+		current_thread_info()->kernel_cntd0 += (unsigned int)(__tmp);	\
+		current_thread_info()->kernel_cntd1 += ((__tmp) >> 32);		\
 	}									\
 	save_and_clear_fpu();							\
 	/* If you are tempted to conditionalize the following */		\
 	/* so that ASI is only written if it changes, think again. */		\
 	__asm__ __volatile__("wr %%g0, %0, %%asi"				\
-			     : : "r" (next->thread.current_ds.seg));		\
+	: : "r" (__thread_flag_byte_ptr(next->thread_info)[TI_FLAG_BYTE_CURRENT_DS]));	\
 	__asm__ __volatile__(							\
 	"mov	%%g6, %%g5\n\t"							\
 	"wrpr	%%g0, 0x95, %%pstate\n\t"					\
@@ -202,7 +202,7 @@
 	"wrpr	%%g1, %%cwp\n\t"						\
 	"ldx	[%%g6 + %3], %%o6\n\t"						\
 	"ldub	[%%g6 + %2], %%o5\n\t"						\
-	"ldub	[%%g6 + %4], %%o7\n\t"						\
+	"ldx	[%%g6 + %4], %%o7\n\t"						\
 	"mov	%%g6, %%l2\n\t"							\
 	"wrpr	%%o5, 0x0, %%wstate\n\t"					\
 	"ldx	[%%sp + 2047 + 0x70], %%i6\n\t"					\
@@ -212,21 +212,18 @@
 	"wrpr	%%g0, 0x96, %%pstate\n\t"					\
 	"andcc	%%o7, %6, %%g0\n\t"						\
 	"bne,pn	%%icc, ret_from_syscall\n\t"					\
-	" mov	%%g5, %0\n\t"							\
+	" ldx	[%%g5 + %7], %0\n\t"						\
 	: "=&r" (last)								\
-	: "r" (next),								\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.wstate)),\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.ksp)),	\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.flags)),\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.cwp)),	\
-	  "i" (SPARC_FLAG_NEWCHILD)						\
+	: "r" (next->thread_info),						\
+	  "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_FLAGS), "i" (TI_CWP),		\
+	  "i" (_TIF_NEWCHILD), "i" (TI_TASK)					\
 	: "cc", "g1", "g2", "g3", "g5", "g7",					\
 	  "l2", "l3", "l4", "l5", "l6", "l7",					\
 	  "i0", "i1", "i2", "i3", "i4", "i5",					\
 	  "o0", "o1", "o2", "o3", "o4", "o5", "o7");				\
 	/* If you fuck with this, update ret_from_syscall code too. */		\
-	if (current->thread.flags & SPARC_FLAG_PERFCTR) {			\
-		write_pcr(current->thread.pcr_reg);				\
+	if (test_thread_flag(TIF_PERFCTR)) {					\
+		write_pcr(current_thread_info()->pcr_reg);			\
 		reset_pic();							\
 	}									\
 } while(0)
diff -Nru a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-sparc64/thread_info.h	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,214 @@
+/* $Id: thread_info.h,v 1.1 2002/02/10 00:00:58 davem Exp $
+ * thread_info.h: sparc64 low-level thread information
+ *
+ * Copyright (C) 2002  David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#define NSWINS		7
+
+#define TI_FLAG_BYTE_FAULT_CODE		0
+#define TI_FLAG_FAULT_CODE_SHIFT	56
+#define TI_FLAG_BYTE_WSTATE		1
+#define TI_FLAG_WSTATE_SHIFT		48
+#define TI_FLAG_BYTE_CWP		2
+#define TI_FLAG_CWP_SHIFT		40
+#define TI_FLAG_BYTE_CURRENT_DS		3
+#define TI_FLAG_CURRENT_DS_SHIFT	32
+#define TI_FLAG_BYTE_FPDEPTH		4
+#define TI_FLAG_FPDEPTH_SHIFT		24
+#define TI_FLAG_BYTE_WSAVED		5
+#define TI_FLAG_WSAVED_SHIFT		16
+
+#ifndef __ASSEMBLY__
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+struct task_struct;
+struct exec_domain;
+
+struct thread_info {
+	/* D$ line 1 */
+	struct task_struct	*task;
+	unsigned long		flags;
+	__u8			cpu;
+	__u8			fpsaved[7];
+	unsigned long		ksp;
+
+	/* D$ line 2 */
+	unsigned long		fault_address;
+	struct pt_regs		*kregs;
+	struct exec_domain	*exec_domain;
+	int			preempt_count;
+
+	unsigned long		*utraps;
+
+	struct reg_window 	reg_window[NSWINS];
+	unsigned long 		rwbuf_stkptrs[NSWINS];
+
+	unsigned long		gsr[7];
+	unsigned long		xfsr[7];
+
+	__u64			*user_cntd0, *user_cntd1;
+	__u64			kernel_cntd0, kernel_cntd1;
+	__u64			pcr_reg;
+
+	__u64			cee_stuff;
+
+	unsigned long		fpregs[0] __attribute__ ((aligned(64)));
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK		0x00000000
+#define TI_FLAGS	0x00000008
+#define TI_FAULT_CODE	(TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
+#define TI_WSTATE	(TI_FLAGS + TI_FLAG_BYTE_WSTATE)
+#define TI_CWP		(TI_FLAGS + TI_FLAG_BYTE_CWP)
+#define TI_CURRENT_DS	(TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
+#define TI_FPDEPTH	(TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
+#define TI_WSAVED	(TI_FLAGS + TI_FLAG_BYTE_WSAVED)
+#define TI_CPU		0x00000010
+#define TI_FPSAVED	0x00000011
+#define TI_KSP		0x00000018
+#define TI_FAULT_ADDR	0x00000020
+#define TI_KREGS	0x00000028
+#define TI_EXEC_DOMAIN	0x00000030
+#define TI_PRE_COUNT	0x00000038
+#define TI_UTRAPS	0x00000040
+#define TI_REG_WINDOW	0x00000048
+#define TI_RWIN_SPTRS	0x000003c8	
+#define TI_GSR		0x00000400
+#define TI_XFSR		0x00000438
+#define TI_USER_CNTD0	0x00000470
+#define TI_USER_CNTD1	0x00000478
+#define TI_KERN_CNTD0	0x00000480
+#define TI_KERN_CNTD1	0x00000488
+#define TI_PCR		0x00000490
+#define TI_CEE_STUFF	0x00000498
+#define TI_FPREGS	0x000004c0
+
+/* We embed this in the uppermost byte of thread_info->flags */
+#define FAULT_CODE_WRITE	0x01	/* Write access, implies D-TLB		*/
+#define FAULT_CODE_DTLB		0x02	/* Miss happened in D-TLB		*/
+#define FAULT_CODE_ITLB		0x04	/* Miss happened in I-TLB		*/
+#define FAULT_CODE_WINFIXUP	0x08	/* Miss happened during spill/fill	*/
+
+#if PAGE_SHIFT == 13
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define THREAD_SHIFT (PAGE_SHIFT + 1)
+#else /* PAGE_SHIFT == 13 */
+#define THREAD_SIZE PAGE_SIZE
+#define THREAD_SHIFT PAGE_SHIFT
+#endif /* PAGE_SHIFT == 13 */
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)				\
+{							\
+	task:		&tsk,				\
+	flags:		((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
+	exec_domain:	&default_exec_domain,		\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+register struct thread_info *current_thread_info_reg asm("g6");
+#define current_thread_info()	(current_thread_info_reg)
+
+/* thread information allocation */
+#if PAGE_SHIFT == 13
+#define alloc_thread_info()   ((struct thread_info *)__get_free_pages(GFP_KERNEL, 1))
+#define free_thread_info(ti)  free_pages((unsigned long)(ti),1)
+#else /* PAGE_SHIFT == 13 */
+#define alloc_thread_info()   ((struct thread_info *)__get_free_pages(GFP_KERNEL, 0))
+#define free_thread_info(ti)  free_pages((unsigned long)(ti),0)
+#endif /* PAGE_SHIFT == 13 */
+
+#define __thread_flag_byte_ptr(ti)	\
+	((unsigned char *)(&((ti)->flags)))
+#define __cur_thread_flag_byte_ptr	__thread_flag_byte_ptr(current_thread_info())
+
+#define get_thread_fault_code()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE])
+#define set_thread_fault_code(val)	(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE] = (val))
+#define get_thread_wstate()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE])
+#define set_thread_wstate(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
+#define get_thread_cwp()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
+#define set_thread_cwp(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
+#define get_thread_current_ds()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS])
+#define set_thread_current_ds(val)	(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val))
+#define get_thread_fpdepth()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
+#define set_thread_fpdepth(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
+#define get_thread_wsaved()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
+#define set_thread_wsaved(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
+
+#endif /* !(__ASSEMBLY__) */
+
+/*
+ * Thread information flags, only 16 bits are available as we encode
+ * other values into the upper 6 bytes.
+ *
+ * On trap return we need to test several values:
+ *
+ * user:	need_resched, notify_resume, sigpending, wsaved, perfctr
+ * kernel:	fpdepth
+ *
+ * So to check for work in the kernel case we simply load the fpdepth
+ * byte out of the flags and test it.  For the user case we encode the
+ * lower 3 bytes of flags as follows:
+ *	----------------------------------------
+ *	| wsaved | flags byte 1 | flags byte 2 |
+ *	----------------------------------------
+ * This optimizes the user test into:
+ *	ldx		[%g6 + TI_FLAGS], REG1
+ *	sethi		%hi(_TIF_USER_WORK_MASK), REG2
+ *	or		REG2, %lo(_TIF_USER_WORK_MASK), REG2
+ *	andcc		REG1, REG2, %g0
+ *	be,pt		no_work_to_do
+ *	 nop
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_PERFCTR		4	/* performance counters active */
+#define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
+#define TIF_NEWSIGNALS		6	/* wants new-style signals */
+#define TIF_32BIT		7	/* 32-bit binary */
+#define TIF_NEWCHILD		8	/* just-spawned child process */
+
+/* XXX Make this one FAULT_CODE_BLKCOMMIT XXX */
+#define TIF_BLKCOMMIT		9	/* use ASI_BLK_COMMIT_* in copy_user_page */
+
+#define TIF_POLLING_NRFLAG	10
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_PERFCTR		(1<<TIF_PERFCTR)
+#define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
+#define _TIF_NEWSIGNALS		(1<<TIF_NEWSIGNALS)
+#define _TIF_32BIT		(1<<TIF_32BIT)
+#define _TIF_NEWCHILD		(1<<TIF_NEWCHILD)
+#define _TIF_BLKCOMMIT		(1<<TIF_BLKCOMMIT)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
+				 (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
+				  _TIF_NEED_RESCHED | _TIF_PERFCTR))
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff -Nru a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
--- a/include/asm-sparc64/ttable.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/ttable.h	Sun Feb 10 19:58:04 2002
@@ -1,9 +1,9 @@
-/* $Id: ttable.h,v 1.17 2001/11/28 23:32:16 davem Exp $ */
+/* $Id: ttable.h,v 1.18 2002/02/09 19:49:32 davem Exp $ */
 #ifndef _SPARC64_TTABLE_H
 #define _SPARC64_TTABLE_H
 
 #include <linux/config.h>
-#include <asm/asm_offsets.h>
+#include <asm/thread_info.h>
 #include <asm/utrap.h>
 
 #define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop;
@@ -104,14 +104,14 @@
 	 mov	num, %g1;				\
 	nop;nop;nop;
 	
-#define TRAP_UTRAP(handler,lvl)						\
-	ldx	[%g6 + AOFF_task_thread + AOFF_thread_utraps], %g1;	\
-	sethi	%hi(109f), %g7;						\
-	brz,pn	%g1, utrap;						\
-	 or	%g7, %lo(109f), %g7;					\
-	ba,pt	%xcc, utrap;						\
-109:	 ldx	[%g1 + handler*8], %g1;					\
-	ba,pt	%xcc, utrap_ill;					\
+#define TRAP_UTRAP(handler,lvl)				\
+	ldx	[%g6 + TI_UTRAPS], %g1;			\
+	sethi	%hi(109f), %g7;				\
+	brz,pn	%g1, utrap;				\
+	 or	%g7, %lo(109f), %g7;			\
+	ba,pt	%xcc, utrap;				\
+109:	 ldx	[%g1 + handler*8], %g1;			\
+	ba,pt	%xcc, utrap_ill;			\
 	 mov	lvl, %o1;
 
 #ifdef CONFIG_SUNOS_EMUL
@@ -140,7 +140,7 @@
 	mov	level, %o0;				\
 	call	routine;				\
 	 add	%sp, STACK_BIAS + REGWIN_SZ, %o1;	\
-	ba,a,pt	%xcc, rtrap_clr_l6;
+	ba,a,pt	%xcc, rtrap_irq;
 	
 #define TICK_SMP_IRQ					\
 	rdpr	%pil, %g2;				\
@@ -150,7 +150,7 @@
 109:	 or	%g7, %lo(109b), %g7;			\
 	call	smp_percpu_timer_interrupt;		\
 	 add	%sp, STACK_BIAS + REGWIN_SZ, %o0;	\
-	ba,a,pt	%xcc, rtrap_clr_l6;
+	ba,a,pt	%xcc, rtrap_irq;
 
 #define TRAP_IVEC TRAP_NOSAVE(do_ivec)
 
diff -Nru a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
--- a/include/asm-sparc64/uaccess.h	Sun Feb 10 19:58:06 2002
+++ b/include/asm-sparc64/uaccess.h	Sun Feb 10 19:58:06 2002
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.34 2001/09/27 04:36:24 kanoj Exp $ */
+/* $Id: uaccess.h,v 1.35 2002/02/09 19:49:31 davem Exp $ */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
@@ -36,14 +36,14 @@
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
 
-#define get_fs() (current->thread.current_ds)
+#define get_fs() ((mm_segment_t) { get_thread_current_ds() })
 #define get_ds() (KERNEL_DS)
 
 #define segment_eq(a,b)  ((a).seg == (b).seg)
 
 #define set_fs(val)								\
 do {										\
-	current->thread.current_ds = (val);					\
+	set_thread_current_ds((val).seg);					\
 	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));	\
 } while(0)
 
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	Sun Feb 10 19:58:04 2002
+++ b/include/asm-sparc64/unistd.h	Sun Feb 10 19:58:04 2002
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.49 2001/10/18 08:27:05 davem Exp $ */
+/* $Id: unistd.h,v 1.50 2002/02/08 03:57:18 davem Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -202,7 +202,7 @@
 #define __NR_query_module	184 /* Linux Specific				   */
 #define __NR_setpgid            185 /* Common                                      */
 /* #define __NR_pathconf        186    SunOS Specific                              */
-/* #define __NR_fpathconf       187    SunOS Specific                              */
+#define __NR_tkill              187 /* SunOS: fpathconf                            */
 /* #define __NR_sysconf         188    SunOS Specific                              */
 #define __NR_uname              189 /* Linux Specific                              */
 #define __NR_init_module        190 /* Linux Specific                              */
diff -Nru a/include/linux/affs_fs_i.h b/include/linux/affs_fs_i.h
--- a/include/linux/affs_fs_i.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/affs_fs_i.h	Sun Feb 10 19:58:05 2002
@@ -2,6 +2,8 @@
 #define _AFFS_FS_I
 
 #include <linux/a.out.h>
+#include <linux/fs.h>
+#include <asm/semaphore.h>
 
 #define AFFS_CACHE_SIZE		PAGE_SIZE
 //#define AFFS_CACHE_SIZE		(4*4)
diff -Nru a/include/linux/ax25.h b/include/linux/ax25.h
--- a/include/linux/ax25.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/ax25.h	Sun Feb 10 19:58:04 2002
@@ -6,6 +6,8 @@
 #ifndef	AX25_KERNEL_H
 #define	AX25_KERNEL_H
 
+#include <linux/socket.h>
+
 #define AX25_MTU	256
 #define AX25_MAX_DIGIS  8
 
diff -Nru a/include/linux/bfs_fs_i.h b/include/linux/bfs_fs_i.h
--- a/include/linux/bfs_fs_i.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/bfs_fs_i.h	Sun Feb 10 19:58:05 2002
@@ -6,6 +6,8 @@
 #ifndef _LINUX_BFS_FS_I
 #define _LINUX_BFS_FS_I
 
+#include <linux/fs.h>
+
 /*
  * BFS file system in-core inode info
  */
diff -Nru a/include/linux/brlock.h b/include/linux/brlock.h
--- a/include/linux/brlock.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/brlock.h	Sun Feb 10 19:58:05 2002
@@ -171,11 +171,11 @@
 }
 
 #else
-# define br_read_lock(idx)	((void)(idx))
-# define br_read_unlock(idx)	((void)(idx))
-# define br_write_lock(idx)	((void)(idx))
-# define br_write_unlock(idx)	((void)(idx))
-#endif
+# define br_read_lock(idx)	({ (void)(idx); preempt_disable(); })
+# define br_read_unlock(idx)	({ (void)(idx); preempt_enable(); })
+# define br_write_lock(idx)	({ (void)(idx); preempt_disable(); })
+# define br_write_unlock(idx)	({ (void)(idx); preempt_enable(); })
+#endif	/* CONFIG_SMP */
 
 /*
  * Now enumerate all of the possible sw/hw IRQ protected
diff -Nru a/include/linux/capability.h b/include/linux/capability.h
--- a/include/linux/capability.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/capability.h	Sun Feb 10 19:58:05 2002
@@ -14,7 +14,6 @@
 #define _LINUX_CAPABILITY_H
 
 #include <linux/types.h>
-#include <linux/fs.h>
 
 /* User-level do most of the mapping between kernel and user
    capabilities based on the version tag given by the kernel. The
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/device.h	Sun Feb 10 19:58:05 2002
@@ -66,10 +66,8 @@
 
 struct device {
 	struct list_head node;		/* node in sibling list */
-	struct iobus	*parent;	/* parent bus */
-
-	struct iobus	*subordinate;	/* only valid if this device is a
-					   bridge device */
+	struct list_head children;
+	struct device 	* parent;
 
 	char	name[DEVICE_NAME_SIZE];	/* descriptive ascii string */
 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
@@ -113,36 +111,12 @@
 	int	(*add_device)	(struct iobus*, char*);
 };
 
-struct iobus {
-	spinlock_t	lock;		/* lock for bus */
-	atomic_t	refcount;
-
-	struct list_head node;		/* node in sibling list */
-	struct iobus *parent;		/* parent bus */
-	struct list_head children;	/* children buses */
-	struct list_head devices;	/* children devices */
-
-	struct device *self;		/* pointer to controlling device */
-	struct driver_dir_entry	dir;	/* driverfs directory */
-
-	char	name[DEVICE_NAME_SIZE];
-	char	bus_id[BUS_ID_SIZE];
-
-	struct	iobus_driver *driver;	/* bus operations */
-};
-
 static inline struct device *
 list_to_dev(struct list_head *node)
 {
 	return list_entry(node, struct device, node);
 }
 
-static inline struct iobus *
-list_to_iobus(const struct list_head *node)
-{
-	return list_entry(node, struct iobus, node);
-}
-
 /*
  * High level routines for use by the bus drivers
  */
@@ -163,9 +137,6 @@
 
 extern int (*platform_notify_remove)(struct device * dev);
 
-extern int device_driver_init(void);
-
-
 /* device and bus locking helpers.
  *
  * FIXME: Is there anything else we need to do?
@@ -191,23 +162,5 @@
 }
 
 extern void put_device(struct device * dev);
-
-static inline void lock_iobus(struct iobus * iobus)
-{
-	spin_lock(&iobus->lock);
-}
-
-static inline void unlock_iobus(struct iobus * iobus)
-{
-	spin_unlock(&iobus->lock);
-}
-
-static inline void get_iobus(struct iobus * iobus)
-{
-	BUG_ON(!atomic_read(&iobus->refcount));
-	atomic_inc(&iobus->refcount);
-}
-
-extern void put_iobus(struct iobus * iobus);
 
 #endif /* _DEVICE_H_ */
diff -Nru a/include/linux/efs_fs.h b/include/linux/efs_fs.h
--- a/include/linux/efs_fs.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/efs_fs.h	Sun Feb 10 19:58:05 2002
@@ -27,6 +27,7 @@
 #define	EFS_BLOCKSIZE_BITS	9
 #define	EFS_BLOCKSIZE		(1 << EFS_BLOCKSIZE_BITS)
 
+#include <linux/fs.h>
 #include <linux/efs_fs_i.h>
 #include <linux/efs_dir.h>
 
@@ -47,7 +48,7 @@
 extern struct file_operations efs_dir_operations;
 extern struct address_space_operations efs_symlink_aops;
 
-extern struct super_block *efs_read_super(struct super_block *, void *, int);
+extern int efs_fill_super(struct super_block *, void *, int);
 extern int efs_statfs(struct super_block *, struct statfs *);
 
 extern void efs_read_inode(struct inode *);
diff -Nru a/include/linux/err.h b/include/linux/err.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/err.h	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,29 @@
+#ifndef _LINUX_ERR_H
+#define _LINUX_ERR_H
+
+#include <asm/errno.h>
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+static inline void *ERR_PTR(long error)
+{
+	return (void *) error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+	return (long) ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+	return (unsigned long)ptr > (unsigned long)-1000L;
+}
+
+#endif /* _LINUX_ERR_H */
diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
--- a/include/linux/ext3_fs.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/ext3_fs.h	Sun Feb 10 19:58:04 2002
@@ -671,7 +671,6 @@
 extern void ext3_write_super_lockfs (struct super_block *);
 extern void ext3_unlockfs (struct super_block *);
 extern int ext3_remount (struct super_block *, int *, char *);
-extern struct super_block * ext3_read_super (struct super_block *,void *,int);
 extern int ext3_statfs (struct super_block *, struct statfs *);
 
 #define ext3_std_error(sb, errno)				\
diff -Nru a/include/linux/file.h b/include/linux/file.h
--- a/include/linux/file.h	Sun Feb 10 19:58:03 2002
+++ b/include/linux/file.h	Sun Feb 10 19:58:03 2002
@@ -8,6 +8,7 @@
 #include <asm/atomic.h>
 #include <linux/posix_types.h>
 #include <linux/compiler.h>
+#include <linux/spinlock.h>
 
 /*
  * The default fd array needs to be at least BITS_PER_LONG,
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/fs.h	Sun Feb 10 19:58:05 2002
@@ -91,7 +91,6 @@
 #define FS_NO_PRELIM	4 /* prevent preloading of dentries, even if
 			   * FS_NO_DCACHE is not set.
 			   */
-#define FS_SINGLE	8 /* Filesystem that can have only one superblock */
 #define FS_NOMOUNT	16 /* Never mount from userland */
 #define FS_LITTER	32 /* Keeps the tree in dcache */
 #define FS_ODD_RENAME	32768	/* Temporary stuff; will go away as soon
@@ -208,6 +207,7 @@
 extern void buffer_init(unsigned long);
 extern void inode_init(unsigned long);
 extern void mnt_init(unsigned long);
+extern void files_init(unsigned long);
 
 /* bh state bits */
 enum bh_state_bits {
@@ -289,7 +289,6 @@
 #include <linux/pipe_fs_i.h>
 /* #include <linux/umsdos_fs_i.h> */
 #include <linux/romfs_fs_i.h>
-#include <linux/proc_fs_i.h>
 #include <linux/cramfs_fs_sb.h>
 
 /*
@@ -455,12 +454,25 @@
 	union {
 		/* struct umsdos_inode_info	umsdos_i; */
 		struct romfs_inode_info		romfs_i;
-		struct proc_inode_info		proc_i;
-		struct socket			socket_i;
 		void				*generic_ip;
 	} u;
 };
 
+struct socket_alloc {
+	struct socket socket;
+	struct inode vfs_inode;
+};
+
+static inline struct socket *SOCKET_I(struct inode *inode)
+{
+	return &list_entry(inode, struct socket_alloc, vfs_inode)->socket;
+}
+
+static inline struct inode *SOCK_INODE(struct socket *socket)
+{
+	return &list_entry(socket, struct socket_alloc, socket)->vfs_inode;
+}
+
 #include <linux/shmem_fs.h>
 /* will die */
 #include <linux/coda_fs_i.h>
@@ -507,6 +519,14 @@
 
 #define	MAX_NON_LFS	((1UL<<31) - 1)
 
+/* Page cache limit. The filesystems should put that into their s_maxbytes 
+   limits, otherwise bad things can happen in VM. */ 
+#if BITS_PER_LONG==32
+#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) 
+#elif BITS_PER_LONG==64
+#define MAX_LFS_FILESIZE 	0x7fffffffffffffff
+#endif
+
 #define FL_POSIX	1
 #define FL_FLOCK	2
 #define FL_BROKEN	4	/* broken flock() emulation */
@@ -917,22 +937,21 @@
 struct file_system_type {
 	const char *name;
 	int fs_flags;
-	struct super_block *(*read_super) (struct super_block *, void *, int);
+	struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
 	struct module *owner;
 	struct file_system_type * next;
 	struct list_head fs_supers;
 };
 
-#define DECLARE_FSTYPE(var,type,read,flags) \
-struct file_system_type var = { \
-	name:		type, \
-	read_super:	read, \
-	fs_flags:	flags, \
-	owner:		THIS_MODULE, \
-}
-
-#define DECLARE_FSTYPE_DEV(var,type,read) \
-	DECLARE_FSTYPE(var,type,read,FS_REQUIRES_DEV)
+struct super_block *get_sb_bdev(struct file_system_type *fs_type,
+	int flags, char *dev_name, void * data,
+	int (*fill_super)(struct super_block *, void *, int));
+struct super_block *get_sb_single(struct file_system_type *fs_type,
+	int flags, void *data,
+	int (*fill_super)(struct super_block *, void *, int));
+struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+	int flags, void *data,
+	int (*fill_super)(struct super_block *, void *, int));
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
 #define fops_get(fops) \
@@ -1238,28 +1257,7 @@
 extern int is_subdir(struct dentry *, struct dentry *);
 extern ino_t find_inode_number(struct dentry *, struct qstr *);
 
-/*
- * Kernel pointers have redundant information, so we can use a
- * scheme where we can return either an error code or a dentry
- * pointer with the same return value.
- *
- * This should be a per-architecture thing, to allow different
- * error and pointer decisions.
- */
-static inline void *ERR_PTR(long error)
-{
-	return (void *) error;
-}
-
-static inline long PTR_ERR(const void *ptr)
-{
-	return (long) ptr;
-}
-
-static inline long IS_ERR(const void *ptr)
-{
-	return (unsigned long)ptr > (unsigned long)-1000L;
-}
+#include <linux/err.h>
 
 /*
  * The bitmask for a lookup event:
@@ -1449,6 +1447,7 @@
 extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
+extern loff_t remote_llseek(struct file *file, loff_t offset, int origin);
 extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
 extern int generic_file_open(struct inode * inode, struct file * filp);
 
@@ -1463,6 +1462,10 @@
 extern int vfs_readdir(struct file *, filldir_t, void *);
 extern int dcache_readdir(struct file *, void *, filldir_t);
 
+extern int vfs_stat(char *, struct kstat *);
+extern int vfs_lstat(char *, struct kstat *);
+extern int vfs_fstat(unsigned int, struct kstat *);
+
 extern struct file_system_type *get_fs_type(const char *name);
 extern struct super_block *get_super(kdev_t);
 extern void drop_super(struct super_block *sb);
@@ -1475,8 +1478,6 @@
 	}
 	return 0;
 }
-unsigned long generate_cluster(kdev_t, int b[], int);
-unsigned long generate_cluster_swab32(kdev_t, int b[], int);
 extern kdev_t ROOT_DEV;
 extern char root_device_name[];
 
diff -Nru a/include/linux/fs_struct.h b/include/linux/fs_struct.h
--- a/include/linux/fs_struct.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/fs_struct.h	Sun Feb 10 19:58:04 2002
@@ -2,6 +2,9 @@
 #define _LINUX_FS_STRUCT_H
 #ifdef __KERNEL__
 
+#include <linux/mount.h>
+#include <linux/dcache.h>
+
 struct fs_struct {
 	atomic_t count;
 	rwlock_t lock;
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/gameport.h	Sun Feb 10 19:58:06 2002
@@ -2,11 +2,9 @@
 #define _GAMEPORT_H
 
 /*
- * $Id: gameport.h,v 1.11 2001/04/26 10:24:46 vojtech Exp $
+ * $Id: gameport.h,v 1.20 2002/01/03 08:55:05 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
 /*
@@ -26,21 +24,27 @@
  *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
-#include <linux/sched.h>
-#include <linux/delay.h>
 #include <asm/io.h>
+#include <linux/input.h>
 
 struct gameport;
 
 struct gameport {
 
-	void *private;
-
+	void *private;	/* Private pointer for joystick drivers */
+	void *driver;	/* Private pointer for gameport drivers */
+	char *name;
+	char *phys;
 	int number;
 
+	unsigned short idbus;
+	unsigned short idvendor;
+	unsigned short idproduct;
+	unsigned short idversion;
+
 	int io;
 	int speed;
 	int fuzz;
@@ -59,6 +63,7 @@
 struct gameport_dev {
 
 	void *private;
+	char *name;
 
 	void (*connect)(struct gameport *, struct gameport_dev *dev);
 	void (*disconnect)(struct gameport *);
@@ -70,12 +75,12 @@
 void gameport_close(struct gameport *gameport);
 void gameport_rescan(struct gameport *gameport);
 
-#if defined(CONFIG_INPUT_GAMEPORT) || defined(CONFIG_INPUT_GAMEPORT_MODULE)
+#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
 void gameport_register_port(struct gameport *gameport);
 void gameport_unregister_port(struct gameport *gameport);
 #else
-static void __inline__ gameport_register_port(struct gameport *gameport) { return; }
-static void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
+void __inline__ gameport_register_port(struct gameport *gameport) { return; }
+void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
 #endif
 
 void gameport_register_device(struct gameport_dev *dev);
@@ -94,6 +99,7 @@
 #define GAMEPORT_ID_VENDOR_MICROSOFT	0x0007
 #define GAMEPORT_ID_VENDOR_THRUSTMASTER	0x0008
 #define GAMEPORT_ID_VENDOR_GRAVIS	0x0009
+#define GAMEPORT_ID_VENDOR_GUILLEMOT	0x000a
 
 static __inline__ void gameport_trigger(struct gameport *gameport)
 {
@@ -134,7 +140,7 @@
 
 static __inline__ void wait_ms(unsigned int ms)
 {
-	current->state = TASK_UNINTERRUPTIBLE;
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(1 + ms * HZ / 1000);
 }
 
diff -Nru a/include/linux/generic_serial.h b/include/linux/generic_serial.h
--- a/include/linux/generic_serial.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/generic_serial.h	Sun Feb 10 19:58:05 2002
@@ -12,9 +12,6 @@
 #ifndef GENERIC_SERIAL_H
 #define GENERIC_SERIAL_H
 
-
-
-
 struct real_driver {
   void                    (*disable_tx_interrupts) (void *);
   void                    (*enable_tx_interrupts) (void *);
@@ -98,7 +95,7 @@
                      struct termios * old_termios);
 int  gs_init_port(struct gs_port *port);
 int  gs_setserial(struct gs_port *port, struct serial_struct *sp);
-void gs_getserial(struct gs_port *port, struct serial_struct *sp);
+int  gs_getserial(struct gs_port *port, struct serial_struct *sp);
 void gs_got_break(struct gs_port *port);
 
 extern int gs_debug;
diff -Nru a/include/linux/hfs_fs.h b/include/linux/hfs_fs.h
--- a/include/linux/hfs_fs.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/hfs_fs.h	Sun Feb 10 19:58:04 2002
@@ -301,7 +301,7 @@
 extern void hfs_sngl_ifill(struct inode *, ino_t, const int);
 
 /* super.c */
-extern struct super_block *hfs_read_super(struct super_block *,void *,int);
+extern int hfs_fill_super(struct super_block *,void *,int);
 
 /* trans.c */
 extern void hfs_colon2mac(struct hfs_name *, const char *, int);
diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h
--- a/include/linux/highmem.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/highmem.h	Sun Feb 10 19:58:05 2002
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/bio.h>
+#include <linux/fs.h>
 #include <asm/pgalloc.h>
 
 #ifdef CONFIG_HIGHMEM
diff -Nru a/include/linux/hpfs_fs_sb.h b/include/linux/hpfs_fs_sb.h
--- a/include/linux/hpfs_fs_sb.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/hpfs_fs_sb.h	Sun Feb 10 19:58:05 2002
@@ -30,9 +30,8 @@
 					/*	128 bytes lowercasing table */
 	unsigned *sb_bmp_dir;		/* main bitmap directory */
 	unsigned sb_c_bitmap;		/* current bitmap */
-	wait_queue_head_t sb_creation_de;/* when creating dirents, nobody else
+	struct semaphore hpfs_creation_de; /* when creating dirents, nobody else
 					   can alloc blocks */
-	unsigned sb_creation_de_lock : 1;
 	/*unsigned sb_mounting : 1;*/
 	int sb_timeshift;
 };
@@ -60,8 +59,6 @@
 #define s_hpfs_cp_table u.hpfs_sb.sb_cp_table
 #define s_hpfs_bmp_dir u.hpfs_sb.sb_bmp_dir
 #define s_hpfs_c_bitmap u.hpfs_sb.sb_c_bitmap
-#define s_hpfs_creation_de u.hpfs_sb.sb_creation_de
-#define s_hpfs_creation_de_lock u.hpfs_sb.sb_creation_de_lock
 #define s_hpfs_iget_q u.hpfs_sb.sb_iget_q
 /*#define s_hpfs_mounting u.hpfs_sb.sb_mounting*/
 #define s_hpfs_timeshift u.hpfs_sb.sb_timeshift
diff -Nru a/include/linux/in.h b/include/linux/in.h
--- a/include/linux/in.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/in.h	Sun Feb 10 19:58:06 2002
@@ -19,6 +19,7 @@
 #define _LINUX_IN_H
 
 #include <linux/types.h>
+#include <linux/socket.h>
 
 /* Standard well-defined IP protocols.  */
 enum {
diff -Nru a/include/linux/inet.h b/include/linux/inet.h
--- a/include/linux/inet.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/inet.h	Sun Feb 10 19:58:05 2002
@@ -44,6 +44,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/net.h>
+
 extern void		inet_proto_init(struct net_proto *pro);
 extern char		*in_ntoa(__u32 in);
 extern __u32		in_aton(const char *str);
diff -Nru a/include/linux/init_task.h b/include/linux/init_task.h
--- a/include/linux/init_task.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/init_task.h	Sun Feb 10 19:58:04 2002
@@ -35,14 +35,6 @@
 	siglock:	SPIN_LOCK_UNLOCKED 		\
 }
 
-#define INIT_TASK_WORK				\
-{						\
-	need_resched:	0,			\
-	syscall_trace:	0,			\
-	sigpending:	0,			\
-	notify_resume:	0,			\
-}
-
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -50,10 +42,8 @@
 #define INIT_TASK(tsk)	\
 {									\
     state:		0,						\
+    thread_info:	&init_thread_info,				\
     flags:		0,						\
-    work:		INIT_TASK_WORK,					\
-    addr_limit:		KERNEL_DS,					\
-    exec_domain:	&default_exec_domain,				\
     lock_depth:		-1,						\
     __nice:		DEF_USER_NICE,					\
     policy:		SCHED_OTHER,					\
diff -Nru a/include/linux/input.h b/include/linux/input.h
--- a/include/linux/input.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/input.h	Sun Feb 10 19:58:06 2002
@@ -2,11 +2,9 @@
 #define _INPUT_H
 
 /*
- * $Id: input.h,v 1.34 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: input.h,v 1.57 2002/01/02 11:59:56 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
 /*
@@ -17,7 +15,7 @@
  *
  * 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
+ * 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
@@ -25,8 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #ifdef __KERNEL__
@@ -64,17 +62,20 @@
 #define EVIOCSREP		_IOW('E', 0x03, int[2])			/* get repeat settings */
 #define EVIOCGKEYCODE		_IOR('E', 0x04, int[2])			/* get keycode */
 #define EVIOCSKEYCODE		_IOW('E', 0x04, int[2])			/* set keycode */
-#define EVIOCGKEY		_IOR('E', 0x05, int[2])			/* get key value */
+
 #define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */
-#define EVIOCGBUS		_IOR('E', 0x07, short[4])		/* get bus address */
+#define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */
+#define EVIOCGUNIQ(len)		_IOC(_IOC_READ, 'E', 0x08, len)		/* get unique identifier */
+
+#define EVIOCGKEY(len)		_IOC(_IOC_READ, 'E', 0x18, len)		/* get global keystate */
+#define EVIOCGLED(len)		_IOC(_IOC_READ, 'E', 0x19, len)		/* get all LEDs */
+#define EVIOCGSND(len)		_IOC(_IOC_READ, 'E', 0x1a, len)		/* get all sounds status */
 
 #define EVIOCGBIT(ev,len)	_IOC(_IOC_READ, 'E', 0x20 + ev, len)	/* get event bits */
 #define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, int[5])		/* get abs value/limits */
 
 #define EVIOCSFF		_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))	/* send a force effect to a force feedback device */
 #define EVIOCRMFF		_IOW('E', 0x81, int)			/* Erase a force effect */
-#define EVIOCSGAIN		_IOW('E', 0x82, unsigned short)		/* Set overall gain */
-#define EVIOCSAUTOCENTER	_IOW('E', 0x83, unsigned short)		/* Enable or disable auto-centering */
 #define EVIOCGEFFECTS		_IOR('E', 0x84, int)			/* Report number of effects playable at the same time */
 
 /*
@@ -90,6 +91,8 @@
 #define EV_SND			0x12
 #define EV_REP			0x14
 #define EV_FF			0x15
+#define EV_PWR			0x16
+#define EV_FF_STATUS		0x17
 #define EV_MAX			0x1f
 
 /*
@@ -304,8 +307,23 @@
 #define KEY_PROG4		203
 #define KEY_SUSPEND		205
 #define KEY_CLOSE		206
+#define KEY_PLAY		207
+#define KEY_FASTFORWARD		208
+#define KEY_BASSBOOST		209
+#define KEY_PRINT		210
+#define KEY_HP			211
+#define KEY_CAMERA		212
+#define KEY_SOUND		213
+#define KEY_QUESTION		214
+#define KEY_EMAIL		215
+#define KEY_CHAT		216
+#define KEY_SEARCH		217
+#define KEY_CONNECT		218
+#define KEY_FINANCE		219
+#define KEY_SPORT		220
+#define KEY_SHOP		221
 
-#define KEY_UNKNOWN		220
+#define KEY_UNKNOWN		240
 
 #define BTN_MISC		0x100
 #define BTN_0			0x100
@@ -415,14 +433,16 @@
 #define ABS_DISTANCE		0x19
 #define ABS_TILT_X		0x1a
 #define ABS_TILT_Y		0x1b
-#define ABS_MISC		0x1c
-#define ABS_MAX			0x1f
+#define ABS_VOLUME		0x20
+#define ABS_MISC		0x28
+#define ABS_MAX			0x3f
 
 /*
  * Misc events
  */
 
 #define MSC_SERIAL		0x00
+#define MSC_PULSELED		0x01
 #define MSC_MAX			0x07
 
 /*
@@ -468,6 +488,7 @@
 #define BUS_PCI			0x01
 #define BUS_ISAPNP		0x02
 #define BUS_USB			0x03
+#define BUS_HIL			0x04
 
 #define BUS_ISA			0x10
 #define BUS_I8042		0x11
@@ -480,32 +501,42 @@
 #define BUS_I2C			0x18
 
 /*
+ * Values describing the status of an effect
+ */
+#define FF_STATUS_STOPPED	0x00
+#define FF_STATUS_PLAYING	0x01
+#define FF_STATUS_MAX		0x01
+
+/*
  * Structures used in ioctls to upload effects to a device
  * The first structures are not passed directly by using ioctls.
  * They are sub-structures of the actually sent structure (called ff_effect)
+ *
+ * Ranges:
+ *  0 <= __u16 <= 65535
+ *  -32767 <= __s16 <= +32767     ! Not -32768 for lower bound !
  */
 
 struct ff_replay {
-	__u16 length;		/* Duration of an effect */
+	__u16 length;		/* Duration of an effect in ms. All other times are also expressed in ms */
 	__u16 delay;		/* Time to wait before to start playing an effect */
 };
 
 struct ff_trigger {
 	__u16 button;		/* Number of button triggering an effect */
-	__u16 interval;		/* Time to wait before an effect can be re-triggered */
+	__u16 interval;		/* Time to wait before an effect can be re-triggered (ms) */
 };
 
 struct ff_shape {
-	__u16 attack_length;	/* Duration of attack */
-	__s16 attack_level;	/* Level at beginning of attack */
-	__u16 fade_length;	/* Duration of fade */
-	__s16 fade_level;	/* Level at end of fade */
+	__u16 attack_length;	/* Duration of attack (ms) */
+	__u16 attack_level;	/* Level at beginning of attack */
+	__u16 fade_length;	/* Duration of fade (ms) */
+	__u16 fade_level;	/* Level at end of fade */
 };
 
 /* FF_CONSTANT */
 struct ff_constant_effect {
-	__s16 level;		/* Strength of effect */
-	__u16 direction;	/* Direction of effect (see periodic effects) */
+	__s16 level;		/* Strength of effect. Negative values are OK */
 	struct ff_shape shape;
 };
 
@@ -514,12 +545,13 @@
 /* Axis along which effect must be created. If null, the field named direction
  * is used
  * It is a bit array (ie to enable axes X and Y, use BIT(ABS_X) | BIT(ABS_Y)
+ * It overrides the value of ff_effect::direction, which is used only if
+ * axis == 0
  */
 	__u16 axis;
-	__u16 direction;
 
-	__s16 right_saturation; /* Max level when joystick is on the right */
-	__s16 left_saturation;  /* Max level when joystick in on the left */
+	__u16 right_saturation; /* Max level when joystick is on the right */
+	__u16 left_saturation;	/* Max level when joystick in on the left */
 
 	__s16 right_coeff;	/* Indicates how fast the force grows when the
 				   joystick moves to the right */
@@ -533,12 +565,10 @@
 /* FF_PERIODIC */
 struct ff_periodic_effect {
 	__u16 waveform;		/* Kind of wave (sine, square...) */
-	__u16 period;
+	__u16 period;		/* in ms */
 	__s16 magnitude;	/* Peak value */
 	__s16 offset;		/* Mean value of wave (roughly) */
 	__u16 phase;		/* 'Horizontal' shift */
-	__u16 direction;	/* Direction. 0 deg -> 0x0000
-					     90 deg -> 0x4000 */
 
 	struct ff_shape shape;
 };
@@ -549,10 +579,17 @@
 struct ff_effect {
 	__u16 type;
 /* Following field denotes the unique id assigned to an effect.
- * It is set by the driver.
+ * If user sets if to -1, a new effect is created, and its id is returned in the same field
+ * Else, the user sets it to the effect id it wants to update.
  */
 	__s16 id;
 
+	__u16 direction;	/* Direction. 0 deg -> 0x0000 (down)
+					     90 deg -> 0x4000 (left)
+					    180 deg -> 0x8000 (up)
+					    270 deg -> 0xC000 (right)
+				*/
+
 	struct ff_trigger trigger;
 	struct ff_replay replay;
 
@@ -564,7 +601,7 @@
 };
 
 /*
- * Buttons that can trigger effects.  Use for example FF_BTN(BTN_TRIGGER) to
+ * Buttons that can trigger effects. Use for example FF_BTN(BTN_TRIGGER) to
  * access the bitmap.
  */
 
@@ -625,8 +662,11 @@
 
 	void *private;
 
-	int number;
 	char *name;
+	char *phys;
+	char *uniq;
+	int number;
+
 	unsigned short idbus;
 	unsigned short idvendor;
 	unsigned short idproduct;
@@ -649,6 +689,9 @@
 	unsigned int repeat_key;
 	struct timer_list timer;
 
+	struct pm_dev *pm_dev;
+	int state;
+
 	int abs[ABS_MAX + 1];
 	int rep[REP_MAX + 1];
 
@@ -661,8 +704,12 @@
 	int absfuzz[ABS_MAX + 1];
 	int absflat[ABS_MAX + 1];
 
+	int only_one_writer;
+
 	int (*open)(struct input_dev *dev);
 	void (*close)(struct input_dev *dev);
+	int (*accept)(struct input_dev *dev, struct file *file);
+	int (*flush)(struct input_dev *dev, struct file *file);
 	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 	int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
 	int (*erase_effect)(struct input_dev *dev, int effect_id);
@@ -671,16 +718,63 @@
 	struct input_dev *next;
 };
 
+/*
+ * Structure for hotplug & device<->driver matching.
+ */
+
+#define INPUT_DEVICE_ID_MATCH_BUS	1
+#define INPUT_DEVICE_ID_MATCH_VENDOR	2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT	4
+#define INPUT_DEVICE_ID_MATCH_VERSION	8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT	0x010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT	0x020
+#define INPUT_DEVICE_ID_MATCH_RELBIT	0x040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT	0x080
+#define INPUT_DEVICE_ID_MATCH_MSCIT	0x100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT	0x200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT	0x400
+#define INPUT_DEVICE_ID_MATCH_FFBIT	0x800
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE\
+	(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+	(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
+
+struct input_device_id {
+
+	unsigned long flags;
+
+	unsigned short idbus;
+	unsigned short idvendor;
+	unsigned short idproduct;
+	unsigned short idversion;
+
+	unsigned long evbit[NBITS(EV_MAX)];
+	unsigned long keybit[NBITS(KEY_MAX)];
+	unsigned long relbit[NBITS(REL_MAX)];
+	unsigned long absbit[NBITS(ABS_MAX)];
+	unsigned long mscbit[NBITS(MSC_MAX)];
+	unsigned long ledbit[NBITS(LED_MAX)];
+	unsigned long sndbit[NBITS(SND_MAX)];
+	unsigned long ffbit[NBITS(FF_MAX)];
+
+	unsigned long driver_info;
+};
+
 struct input_handler {
 
 	void *private;
 
 	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
-	struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev);
+	struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
 	void (*disconnect)(struct input_handle *handle);
 
 	struct file_operations *fops;
 	int minor;
+	char *name;
+
+	struct input_device_id *id_table;
 
 	struct input_handle *handle;
 	struct input_handler *next;
@@ -691,6 +785,7 @@
 	void *private;
 
 	int open;
+	char *name;
 
 	struct input_dev *dev;
 	struct input_handler *handler;
@@ -708,6 +803,9 @@
 int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
+int input_accept_process(struct input_handle *handle, struct file *file);
+int input_flush_device(struct input_handle* handle, struct file* file);
+
 devfs_handle_t input_register_minor(char *name, int minor, int minor_base);
 void input_unregister_minor(devfs_handle_t handle);
 
@@ -716,6 +814,8 @@
 #define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
 #define input_report_rel(a,b,c) input_event(a, EV_REL, b, c)
 #define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c)
+#define input_report_ff(a,b,c)	input_event(a, EV_FF, b, c)
+#define input_report_ff_status(a,b,c)	input_event(a, EV_FF_STATUS, b, c)
 
 #endif
 #endif
diff -Nru a/include/linux/iso_fs_i.h b/include/linux/iso_fs_i.h
--- a/include/linux/iso_fs_i.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/iso_fs_i.h	Sun Feb 10 19:58:05 2002
@@ -1,6 +1,8 @@
 #ifndef _ISO_FS_I
 #define _ISO_FS_I
 
+#include <linux/fs.h>
+
 enum isofs_file_format {
 	isofs_file_normal = 0,
 	isofs_file_sparse = 1,
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	Sun Feb 10 19:58:03 2002
+++ b/include/linux/kernel.h	Sun Feb 10 19:58:03 2002
@@ -91,6 +91,9 @@
 
 extern int tainted;
 extern const char *print_tainted(void);
+#define TAINT_PROPRIETORY_MODULE	(1<<0)
+#define TAINT_FORCED_MODULE		(1<<1)
+#define TAINT_UNSAFE_SMP		(1<<2)
 
 #if DEBUG
 #define pr_debug(fmt,arg...) \
diff -Nru a/include/linux/lp.h b/include/linux/lp.h
--- a/include/linux/lp.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/lp.h	Sun Feb 10 19:58:05 2002
@@ -98,6 +98,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/wait.h>
+#include <asm/semaphore.h>
+
 /* Magic numbers for defining port-device mappings */
 #define LP_PARPORT_UNSPEC -4
 #define LP_PARPORT_AUTO -3
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/mm.h	Sun Feb 10 19:58:04 2002
@@ -13,6 +13,7 @@
 #include <linux/mmzone.h>
 #include <linux/swap.h>
 #include <linux/rbtree.h>
+#include <linux/fs.h>
 
 extern unsigned long max_mapnr;
 extern unsigned long num_physpages;
diff -Nru a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
--- a/include/linux/msdos_fs.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/msdos_fs.h	Sun Feb 10 19:58:05 2002
@@ -330,8 +330,7 @@
 extern int msdos_unlink(struct inode *dir, struct dentry *dentry);
 extern int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
 			struct inode *new_dir, struct dentry *new_dentry);
-extern struct super_block *msdos_read_super(struct super_block *sb,
-					    void *data, int silent);
+extern int msdos_fill_super(struct super_block *sb, void *data, int silent);
 
 /* vfat/namei.c - these are for dmsdos */
 extern struct dentry *vfat_lookup(struct inode *dir, struct dentry *);
@@ -341,8 +340,7 @@
 extern int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode);
 extern int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 		       struct inode *new_dir, struct dentry *new_dentry);
-extern struct super_block *vfat_read_super(struct super_block *sb, void *data,
-					   int silent);
+extern int vfat_fill_super(struct super_block *sb, void *data, int silent);
 
 /* vfat/vfatfs_syms.c */
 extern struct file_system_type vfat_fs_type;
diff -Nru a/include/linux/msdos_fs_i.h b/include/linux/msdos_fs_i.h
--- a/include/linux/msdos_fs_i.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/msdos_fs_i.h	Sun Feb 10 19:58:06 2002
@@ -1,6 +1,8 @@
 #ifndef _MSDOS_FS_I
 #define _MSDOS_FS_I
 
+#include <linux/fs.h>
+
 /*
  * MS-DOS file system inode data in memory
  */
diff -Nru a/include/linux/namespace.h b/include/linux/namespace.h
--- a/include/linux/namespace.h	Sun Feb 10 19:58:03 2002
+++ b/include/linux/namespace.h	Sun Feb 10 19:58:03 2002
@@ -9,6 +9,8 @@
 	struct rw_semaphore	sem;
 };
 
+void umount_tree(struct vfsmount *mnt);
+
 static inline void put_namespace(struct namespace *namespace)
 {
 	if (atomic_dec_and_test(&namespace->count)) {
diff -Nru a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
--- a/include/linux/ncp_fs.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/ncp_fs.h	Sun Feb 10 19:58:05 2002
@@ -228,7 +228,6 @@
 
 /* linux/fs/ncpfs/inode.c */
 int ncp_notify_change(struct dentry *, struct iattr *);
-struct super_block *ncp_read_super(struct super_block *, void *, int);
 struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
 void ncp_update_inode(struct inode *, struct ncp_entry_info *);
 void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
diff -Nru a/include/linux/net.h b/include/linux/net.h
--- a/include/linux/net.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/net.h	Sun Feb 10 19:58:05 2002
@@ -23,6 +23,7 @@
 #include <linux/wait.h>
 
 struct poll_table_struct;
+struct inode;
 
 #define NPROTO		32		/* should be enough for now..	*/
 
@@ -68,7 +69,6 @@
 
 	unsigned long		flags;
 	struct proto_ops	*ops;
-	struct inode		*inode;
 	struct fasync_struct	*fasync_list;	/* Asynchronous wake up list	*/
 	struct file		*file;		/* File back pointer for gc	*/
 	struct sock		*sk;
@@ -77,8 +77,6 @@
 	short			type;
 	unsigned char		passcred;
 };
-
-#define SOCK_INODE(S)	((S)->inode)
 
 struct scm_cookie;
 struct vm_area_struct;
diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
--- a/include/linux/nfs_fs.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/nfs_fs.h	Sun Feb 10 19:58:05 2002
@@ -92,7 +92,6 @@
 	/*
 	 * The 64bit 'inode number'
 	 */
-	__u64 fsid;
 	__u64 fileid;
 
 	/*
@@ -130,6 +129,12 @@
 	unsigned long		attrtimeo_timestamp;
 
 	/*
+	 * Timestamp that dates the change made to read_cache_mtime.
+	 * This is of use for dentry revalidation
+	 */
+	unsigned long		cache_mtime_jiffies;
+
+	/*
 	 * This is the cookie verifier used for NFSv3 readdir
 	 * operations
 	 */
@@ -148,11 +153,6 @@
 				ncommit,
 				npages;
 
-	/* Flush daemon info */
-	struct inode		*hash_next,
-				*hash_prev;
-	unsigned long		nextscan;
-
 	/* Credentials for shared mmap */
 	struct rpc_cred		*mm_cred;
 
@@ -183,6 +183,7 @@
 #define NFS_CONGESTED(inode)		(RPC_CONGESTED(NFS_CLIENT(inode)))
 #define NFS_COOKIEVERF(inode)		(NFS_I(inode)->cookieverf)
 #define NFS_READTIME(inode)		(NFS_I(inode)->read_cache_jiffies)
+#define NFS_MTIME_UPDATE(inode)		(NFS_I(inode)->cache_mtime_jiffies)
 #define NFS_CACHE_CTIME(inode)		(NFS_I(inode)->read_cache_ctime)
 #define NFS_CACHE_MTIME(inode)		(NFS_I(inode)->read_cache_mtime)
 #define NFS_CACHE_ISIZE(inode)		(NFS_I(inode)->read_cache_isize)
@@ -206,7 +207,6 @@
 #define NFS_NEW(inode)			(NFS_FLAGS(inode) & NFS_INO_NEW)
 
 #define NFS_FILEID(inode)		(NFS_I(inode)->fileid)
-#define NFS_FSID(inode)			(NFS_I(inode)->fsid)
 
 /* Inode Flags */
 #define NFS_USE_READDIRPLUS(inode)	((NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) ? 1 : 0)
@@ -226,7 +226,6 @@
 /*
  * linux/fs/nfs/inode.c
  */
-extern struct super_block *nfs_read_super(struct super_block *, void *, int);
 extern void nfs_zap_caches(struct inode *);
 extern int nfs_inode_is_stale(struct inode *, struct nfs_fh *,
 				struct nfs_fattr *);
@@ -250,7 +249,9 @@
 static __inline__ struct rpc_cred *
 nfs_file_cred(struct file *file)
 {
-	struct rpc_cred *cred = (struct rpc_cred *)(file->private_data);
+	struct rpc_cred *cred = NULL;
+	if (file)
+		cred = (struct rpc_cred *)file->private_data;
 #ifdef RPC_DEBUG
 	if (cred && cred->cr_magic != RPCAUTH_CRED_MAGIC)
 		BUG();
diff -Nru a/include/linux/nfs_page.h b/include/linux/nfs_page.h
--- a/include/linux/nfs_page.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/nfs_page.h	Sun Feb 10 19:58:04 2002
@@ -41,9 +41,10 @@
 
 #define NFS_WBACK_BUSY(req)	(test_bit(PG_BUSY,&(req)->wb_flags))
 
-extern	struct nfs_page *nfs_create_request(struct file *, struct inode *,
+extern	struct nfs_page *nfs_create_request(struct rpc_cred *, struct inode *,
 					    struct page *,
 					    unsigned int, unsigned int);
+extern	void nfs_clear_request(struct nfs_page *req);
 extern	void nfs_release_request(struct nfs_page *req);
 
 
diff -Nru a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
--- a/include/linux/nfsd/export.h	Sun Feb 10 19:58:03 2002
+++ b/include/linux/nfsd/export.h	Sun Feb 10 19:58:03 2002
@@ -54,11 +54,13 @@
 	int			cl_naddr;
 	struct in_addr		cl_addr[NFSCLNT_ADDRMAX];
 	struct svc_uidmap *	cl_umap;
-	struct svc_export *	cl_export[NFSCLNT_EXPMAX];
+	struct list_head	cl_export[NFSCLNT_EXPMAX];
+	struct list_head	cl_list;
 };
 
 struct svc_export {
-	struct svc_export *	ex_next;
+	struct list_head	ex_hash;
+	struct list_head	ex_list;
 	char			ex_path[NFS_MAXPATHLEN+1];
 	struct svc_export *	ex_parent;
 	struct svc_client *	ex_client;
@@ -90,7 +92,10 @@
 struct svc_client *	exp_getclient(struct sockaddr_in *sin);
 void			exp_putclient(struct svc_client *clp);
 struct svc_export *	exp_get(struct svc_client *clp, kdev_t dev, ino_t ino);
-int			exp_rootfh(struct svc_client *, kdev_t, ino_t,
+struct svc_export *	exp_get_by_name(struct svc_client *clp,
+					struct vfsmount *mnt,
+					struct dentry *dentry);
+int			exp_rootfh(struct svc_client *, 
 					char *path, struct knfsd_fh *, int maxsize);
 int			nfserrno(int errno);
 void			exp_nlmdetach(void);
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/pci.h	Sun Feb 10 19:58:06 2002
@@ -432,8 +432,7 @@
 	unsigned char	productver;	/* product version */
 	unsigned char	checksum;	/* if zero - checksum passed */
 	unsigned char	pad1;
-
-	struct iobus	iobus;		/* Generic device interface */
+	struct	device	* dev;
 };
 
 #define pci_bus_b(n) list_entry(n, struct pci_bus, node)
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/pci_ids.h	Sun Feb 10 19:58:06 2002
@@ -1486,6 +1486,9 @@
 #define PCI_DEVICE_ID_PANACOM_QUADMODEM	0x0400
 #define PCI_DEVICE_ID_PANACOM_DUALMODEM	0x0402
 
+#define PCI_VENDOR_ID_AFAVLAB		0x14db
+#define PCI_DEVICE_ID_AFAVLAB_P028	0x2180
+
 #define PCI_VENDOR_ID_BROADCOM		0x14e4
 #define PCI_DEVICE_ID_TIGON3_5700	0x1644
 #define PCI_DEVICE_ID_TIGON3_5701	0x1645
diff -Nru a/include/linux/pm.h b/include/linux/pm.h
--- a/include/linux/pm.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/pm.h	Sun Feb 10 19:58:04 2002
@@ -103,8 +103,8 @@
 	void		*data;
 
 	unsigned long	 flags;
-	int		 state;
-	int		 prev_state;
+	unsigned long	 state;
+	unsigned long	 prev_state;
 
 	struct list_head entry;
 };
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h	Sun Feb 10 19:58:03 2002
+++ b/include/linux/proc_fs.h	Sun Feb 10 19:58:03 2002
@@ -97,7 +97,7 @@
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
 extern struct vfsmount *proc_mnt;
-extern struct super_block *proc_read_super(struct super_block *,void *,int);
+extern int proc_fill_super(struct super_block *,void *,int);
 extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *);
 
 extern int proc_match(int, const char *,struct proc_dir_entry *);
@@ -204,5 +204,27 @@
 extern struct proc_dir_entry proc_root;
 
 #endif /* CONFIG_PROC_FS */
+
+struct proc_inode {
+	struct task_struct *task;
+	int type;
+	union {
+		int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
+		int (*proc_read)(struct task_struct *task, char *page);
+	} op;
+	struct file *file;
+	struct proc_dir_entry *pde;
+	struct inode vfs_inode;
+};
+
+static inline struct proc_inode *PROC_I(struct inode *inode)
+{
+	return list_entry(inode, struct proc_inode, vfs_inode);
+}
+
+static inline struct proc_dir_entry *PDE(struct inode *inode)
+{
+	return PROC_I(inode)->pde;
+}
 
 #endif /* _LINUX_PROC_FS_H */
diff -Nru a/include/linux/proc_fs_i.h b/include/linux/proc_fs_i.h
--- a/include/linux/proc_fs_i.h	Sun Feb 10 19:58:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,9 +0,0 @@
-struct proc_inode_info {
-	struct task_struct *task;
-	int type;
-	union {
-		int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
-		int (*proc_read)(struct task_struct *task, char *page);
-	} op;
-	struct file *file;
-};
diff -Nru a/include/linux/quotaops.h b/include/linux/quotaops.h
--- a/include/linux/quotaops.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/quotaops.h	Sun Feb 10 19:58:05 2002
@@ -13,9 +13,9 @@
 #include <linux/config.h>
 #include <linux/smp_lock.h>
 
-#if defined(CONFIG_QUOTA)
-
 #include <linux/fs.h>
+
+#if defined(CONFIG_QUOTA)
 
 /*
  * declaration of quota_function calls in kernel.
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/reiserfs_fs.h	Sun Feb 10 19:58:05 2002
@@ -381,7 +381,7 @@
     offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2;
     tmp->linear = le64_to_cpu(tmp->linear);
     tmp->offset_v2.k_type = type;
-    tmp->linear = le64_to_cpu(tmp->linear);
+    tmp->linear = cpu_to_le64(tmp->linear);
 }
  
 static inline loff_t offset_v2_k_offset( const struct offset_v2 *v2 )
@@ -395,7 +395,7 @@
     offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2;
     tmp->linear = le64_to_cpu(tmp->linear);
     tmp->offset_v2.k_offset = offset;
-    tmp->linear = le64_to_cpu(tmp->linear);
+    tmp->linear = cpu_to_le64(tmp->linear);
 }
 #else
 # define offset_v2_k_type(v2)           ((v2)->k_type)
diff -Nru a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
--- a/include/linux/reiserfs_fs_sb.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/reiserfs_fs_sb.h	Sun Feb 10 19:58:06 2002
@@ -131,7 +131,7 @@
   struct buffer_head *bh ;		 /* real buffer head */
   struct super_block *sb ;		 /* dev of real buffer head */
   unsigned long blocknr ;		 /* block number of real buffer head, == 0 when buffer on disk */		 
-  int state ;
+  long state ;
   struct reiserfs_journal_list *jlist ;  /* journal list this cnode lives in */
   struct reiserfs_journal_cnode *next ;  /* next in transaction list */
   struct reiserfs_journal_cnode *prev ;  /* prev in transaction list */
@@ -199,7 +199,7 @@
   struct block_device *j_dev_bd;  
   int j_1st_reserved_block;     /* first block on s_dev of reserved area journal */        
 	
-  int j_state ;			
+  long j_state ;			
   unsigned long j_trans_id ;
   unsigned long j_mount_id ;
   unsigned long j_start ;             /* start of current waiting commit (index into j_ap_blocks) */
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/sched.h	Sun Feb 10 19:58:04 2002
@@ -6,13 +6,15 @@
 extern unsigned long event;
 
 #include <linux/config.h>
-#include <linux/binfmts.h>
+#include <linux/capability.h>
+#include <linux/tqueue.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/times.h>
 #include <linux/timex.h>
 #include <linux/rbtree.h>
+#include <linux/thread_info.h>
 
 #include <asm/system.h>
 #include <asm/semaphore.h>
@@ -90,6 +92,7 @@
 #define TASK_UNINTERRUPTIBLE	2
 #define TASK_ZOMBIE		4
 #define TASK_STOPPED		8
+#define PREEMPT_ACTIVE		0x4000000
 
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
@@ -229,37 +232,15 @@
 
 typedef struct prio_array prio_array_t;
 
-/* this struct must occupy one 32-bit chunk so that is can be read in one go */
-struct task_work {
-	__s8	need_resched;
-	__u8	syscall_trace;	/* count of syscall interceptors */
-	__u8	sigpending;
-	__u8	notify_resume;	/* request for notification on
-				   userspace execution resumption */
-} __attribute__((packed));
-
 struct task_struct {
-	/*
-	 * offsets of these are hardcoded elsewhere - touch with care
-	 */
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
+	struct thread_info *thread_info;
+	atomic_t usage;
 	unsigned long flags;	/* per process flags, defined below */
-	volatile struct task_work work;
-
-	mm_segment_t addr_limit;	/* thread address space:
-					 	0-0xBFFFFFFF for user-thead
-						0-0xFFFFFFFF for kernel-thread
-					 */
-	struct exec_domain *exec_domain;
-	long __pad;
 	unsigned long ptrace;
 
 	int lock_depth;		/* Lock depth */
 
-	/*
-	 * offset 32 begins here on 32-bit platforms.
-	 */
-	unsigned int cpu;
 	int prio;
 	long __nice;
 	list_t run_list;
@@ -368,6 +349,11 @@
 	void *journal_info;
 };
 
+extern void __put_task_struct(struct task_struct *tsk);
+#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
+#define put_task_struct(tsk) \
+do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
+
 /*
  * Per process flags
  */
@@ -384,17 +370,14 @@
 #define PF_FREE_PAGES	0x00002000	/* per process page freeing */
 #define PF_NOIO		0x00004000	/* avoid generating further I/O */
 
-#define PF_USEDFPU	0x00100000	/* task used FPU this quantum (SMP) */
-
 /*
  * Ptrace flags
  */
 
 #define PT_PTRACED	0x00000001
-#define PT_SYSCALLTRACE	0x00000002	/* T if syscall_trace is +1 for ptrace() */
-#define PT_DTRACE	0x00000004	/* delayed trace (used on m68k, i386) */
-#define PT_TRACESYSGOOD	0x00000008
-#define PT_PTRACE_CAP	0x00000010	/* ptracer can follow suid-exec */
+#define PT_DTRACE	0x00000002	/* delayed trace (used on m68k, i386) */
+#define PT_TRACESYSGOOD	0x00000004
+#define PT_PTRACE_CAP	0x00000008	/* ptracer can follow suid-exec */
 
 /*
  * Limit the stack by to some sane default: root can always
@@ -470,16 +453,17 @@
  */
 extern struct exec_domain	default_exec_domain;
 
-#ifndef INIT_TASK_SIZE
-# define INIT_TASK_SIZE	2048*sizeof(long)
+#ifndef INIT_THREAD_SIZE
+# define INIT_THREAD_SIZE	2048*sizeof(long)
 #endif
 
-union task_union {
-	struct task_struct task;
-	unsigned long stack[INIT_TASK_SIZE/sizeof(long)];
+union thread_union {
+	struct thread_info thread_info;
+	unsigned long stack[INIT_THREAD_SIZE/sizeof(long)];
 };
 
-extern union task_union init_task_union;
+extern union thread_union init_thread_union;
+extern struct task_struct init_task;
 
 extern struct   mm_struct init_mm;
 extern struct task_struct *init_tasks[NR_CPUS];
@@ -526,15 +510,12 @@
 extern unsigned long volatile jiffies;
 extern unsigned long itimer_ticks;
 extern unsigned long itimer_next;
-extern struct timeval xtime;
 extern void do_timer(struct pt_regs *);
 
 extern unsigned int * prof_buffer;
 extern unsigned long prof_len;
 extern unsigned long prof_shift;
 
-#define CURRENT_TIME (xtime.tv_sec)
-
 extern void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode, int nr));
 extern void FASTCALL(__wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr));
 extern void FASTCALL(sleep_on(wait_queue_head_t *q));
@@ -564,6 +545,7 @@
 extern void proc_caches_init(void);
 extern void flush_signals(struct task_struct *);
 extern void flush_signal_handlers(struct task_struct *);
+extern void sig_exit(int, int, struct siginfo *);
 extern int dequeue_signal(sigset_t *, siginfo_t *);
 extern void block_all_signals(int (*notifier)(void *priv), void *priv,
 			      sigset_t *mask);
@@ -583,22 +565,6 @@
 extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *);
 extern int do_sigaltstack(const stack_t *, stack_t *, unsigned long);
 
-static inline int signal_pending(struct task_struct *p)
-{
-	return (p->work.sigpending != 0);
-}
-  
-static inline int need_resched(void)
-{
-	return unlikely(current->work.need_resched != 0);
-}
-
-static inline void cond_resched(void)
-{
-	if (need_resched())
-		schedule();
-}
-
 /*
  * Re-calculate pending state from the set of locally pending
  * signals, globally pending signals, and blocked signals.
@@ -629,15 +595,6 @@
 	return ready !=	0;
 }
 
-/* Reevaluate whether the task has signals pending delivery.
-   This is required every time the blocked sigset_t changes.
-   All callers should have t->sigmask_lock.  */
-
-static inline void recalc_sigpending(struct task_struct *t)
-{
-	t->work.sigpending = has_pending_signals(&t->pending.signal, &t->blocked);
-}
-
 /* True if we are on the alternate signal stack.  */
 
 static inline int on_sig_stack(unsigned long sp)
@@ -839,9 +796,14 @@
 #define for_each_task(p) \
 	for (p = &init_task ; (p = p->next_task) != &init_task ; )
 
+#define for_each_thread(task) \
+	for (task = next_thread(current) ; task != current ; task = next_thread(task))
+
 #define next_thread(p) \
 	list_entry((p)->thread_group.next, struct task_struct, thread_group)
 
+#define thread_group_leader(p)	(p->pid == p->tgid)
+
 static inline void unhash_process(struct task_struct *p)
 {
 	write_lock_irq(&tasklist_lock);
@@ -880,6 +842,72 @@
 	dput(root);
 	mntput(rootmnt);
 	return res;
+}
+
+/* set thread flags in other task's structures
+ * - see asm/thread_info.h for TIF_xxxx flags available
+ */
+static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	set_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline void clear_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	clear_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	return test_and_set_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	return test_and_clear_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	return test_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline void set_tsk_need_resched(struct task_struct *tsk)
+{
+	set_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
+}
+
+static inline void clear_tsk_need_resched(struct task_struct *tsk)
+{
+	clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
+}
+
+static inline int signal_pending(struct task_struct *p)
+{
+	return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING));
+}
+  
+static inline int need_resched(void)
+{
+	return unlikely(test_thread_flag(TIF_NEED_RESCHED));
+}
+
+static inline void cond_resched(void)
+{
+	if (need_resched())
+		schedule();
+}
+
+/* Reevaluate whether the task has signals pending delivery.
+   This is required every time the blocked sigset_t changes.
+   Athread cathreaders should have t->sigmask_lock.  */
+
+static inline void recalc_sigpending(struct task_struct *t)
+{
+	if (has_pending_signals(&t->pending.signal, &t->blocked))
+		set_thread_flag(TIF_SIGPENDING);
+	else
+		clear_thread_flag(TIF_SIGPENDING);
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/serialP.h b/include/linux/serialP.h
--- a/include/linux/serialP.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/serialP.h	Sun Feb 10 19:58:04 2002
@@ -70,7 +70,7 @@
 	int			x_char;	/* xon/xoff character */
 	int			close_delay;
 	unsigned short		closing_wait;
-	unsigned short		closing_wait2;
+	unsigned short		closing_wait2; /* obsolete */
 	int			IER; 	/* Interrupt Enable Register */
 	int			MCR; 	/* Modem control register */
 	int			LCR; 	/* Line control register */
diff -Nru a/include/linux/serio.h b/include/linux/serio.h
--- a/include/linux/serio.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/serio.h	Sun Feb 10 19:58:04 2002
@@ -2,31 +2,29 @@
 #define _SERIO_H
 
 /*
- * $Id: serio.h,v 1.11 2001/05/29 02:58:50 jsimmons Exp $
+ * $Id: serio.h,v 1.21 2001/12/19 05:15:21 skids Exp $
  *
- * Copyright (C) 1999 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (C) 1999-2001 Vojtech Pavlik
  */
 
 /*
  * 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 
+ * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
+ *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 /*
@@ -42,23 +40,31 @@
 
 	void *private;
 	void *driver;
+	char *name;
+	char *phys;
+	int number;
+
+	unsigned short idbus;
+	unsigned short idvendor;
+	unsigned short idproduct;
+	unsigned short idversion;
 
 	unsigned long type;
-	int number;
 
 	int (*write)(struct serio *, unsigned char);
 	int (*open)(struct serio *);
 	void (*close)(struct serio *);
 
 	struct serio_dev *dev;
-
 	struct serio *next;
 };
 
 struct serio_dev {
 
 	void *private;
+	char *name;
 
+	void (*write_wakeup)(struct serio *);
 	void (*interrupt)(struct serio *, unsigned char, unsigned int);
 	void (*connect)(struct serio *, struct serio_dev *dev);
 	void (*disconnect)(struct serio *);
@@ -80,6 +86,13 @@
 	return serio->write(serio, data);
 }
 
+static __inline__ void serio_dev_write_wakeup(struct serio *serio)
+{
+	if (serio->dev && serio->dev->write_wakeup) {
+		serio->dev->write_wakeup(serio);
+	}
+}
+
 #define SERIO_TIMEOUT	1
 #define SERIO_PARITY	2
 
@@ -87,6 +100,7 @@
 #define SERIO_XT	0x00000000UL
 #define SERIO_8042	0x01000000UL
 #define SERIO_RS232	0x02000000UL
+#define SERIO_HIL_MLC	0x03000000UL
 
 #define SERIO_PROTO	0xFFUL
 #define SERIO_MSC	0x01
@@ -108,6 +122,9 @@
 #define SERIO_STOWAWAY	0x20
 #define SERIO_H3600	0x21
 #define SERIO_PS2SER	0x22
+#define SERIO_TWIDKBD	0x23
+#define SERIO_TWIDJOY	0x24
+#define SERIO_HIL	0x25
 
 #define SERIO_ID	0xff00UL
 #define SERIO_EXTRA	0xff0000UL
diff -Nru a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
--- a/include/linux/shmem_fs.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/shmem_fs.h	Sun Feb 10 19:58:05 2002
@@ -1,21 +1,11 @@
 #ifndef __SHMEM_FS_H
 #define __SHMEM_FS_H
 
+#include <linux/swap.h>
+
 /* inode in-kernel data */
 
 #define SHMEM_NR_DIRECT 16
-
-/*
- * A swap entry has to fit into a "unsigned long", as
- * the entry is hidden in the "index" field of the
- * swapper address space.
- *
- * We have to move it here, since not every user of fs.h is including
- * mm.h, but mm.h is including fs.h via sched .h :-/
- */
-typedef struct {
-	unsigned long val;
-} swp_entry_t;
 
 extern atomic_t shmem_nrpages;
 
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/skbuff.h	Sun Feb 10 19:58:04 2002
@@ -25,6 +25,8 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
+#include <linux/poll.h>
+#include <linux/net.h>
 
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
diff -Nru a/include/linux/slab.h b/include/linux/slab.h
--- a/include/linux/slab.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/slab.h	Sun Feb 10 19:58:06 2002
@@ -62,11 +62,6 @@
 extern void kfree(const void *);
 
 extern int FASTCALL(kmem_cache_reap(int));
-extern int slabinfo_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data);
-struct file;
-extern int slabinfo_write_proc(struct file *file, const char *buffer,
-			   unsigned long count, void *data);
 
 /* System wide caches */
 extern kmem_cache_t	*vm_area_cachep;
diff -Nru a/include/linux/smb.h b/include/linux/smb.h
--- a/include/linux/smb.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/smb.h	Sun Feb 10 19:58:04 2002
@@ -10,6 +10,7 @@
 #define _LINUX_SMB_H
 
 #include <linux/types.h>
+#include <linux/kdev_t.h>
 
 enum smb_protocol { 
 	SMB_PROTOCOL_NONE, 
diff -Nru a/include/linux/smb_fs_i.h b/include/linux/smb_fs_i.h
--- a/include/linux/smb_fs_i.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/smb_fs_i.h	Sun Feb 10 19:58:06 2002
@@ -11,6 +11,7 @@
 
 #ifdef __KERNEL__
 #include <linux/types.h>
+#include <linux/fs.h>
 
 /*
  * smb fs inode data (in memory only)
diff -Nru a/include/linux/smp.h b/include/linux/smp.h
--- a/include/linux/smp.h	Sun Feb 10 19:58:03 2002
+++ b/include/linux/smp.h	Sun Feb 10 19:58:03 2002
@@ -81,7 +81,9 @@
 #define smp_processor_id()			0
 #define hard_smp_processor_id()			0
 #define smp_threads_ready			1
+#ifndef CONFIG_PREEMPT
 #define kernel_lock()
+#endif
 #define cpu_logical_map(cpu)			0
 #define cpu_number_map(cpu)			0
 #define smp_call_function(func,info,retry,wait)	({ 0; })
diff -Nru a/include/linux/smp_lock.h b/include/linux/smp_lock.h
--- a/include/linux/smp_lock.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/smp_lock.h	Sun Feb 10 19:58:05 2002
@@ -3,7 +3,7 @@
 
 #include <linux/config.h>
 
-#ifndef CONFIG_SMP
+#if !defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT)
 
 #define lock_kernel()				do { } while(0)
 #define unlock_kernel()				do { } while(0)
diff -Nru a/include/linux/sound.h b/include/linux/sound.h
--- a/include/linux/sound.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/sound.h	Sun Feb 10 19:58:05 2002
@@ -3,6 +3,8 @@
  * Minor numbers for the sound driver.
  */
 
+#include <linux/fs.h>
+
 #define SND_DEV_CTL		0	/* Control port /dev/mixer */
 #define SND_DEV_SEQ		1	/* Sequencer output /dev/sequencer (FM
 						synthesizer and MIDI output) */
diff -Nru a/include/linux/spinlock.h b/include/linux/spinlock.h
--- a/include/linux/spinlock.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/spinlock.h	Sun Feb 10 19:58:06 2002
@@ -2,6 +2,10 @@
 #define __LINUX_SPINLOCK_H
 
 #include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/compiler.h>
+#include <linux/thread_info.h>
+#include <linux/kernel.h>
 
 /*
  * These are the generic versions of the spinlocks and read-write
@@ -35,6 +39,23 @@
 						if (!__r) local_bh_enable();   \
 						__r; })
 
+/* Must define these before including other files, inline functions need them */
+
+#include <linux/stringify.h>
+
+#define LOCK_SECTION_NAME			\
+	".text.lock." __stringify(KBUILD_BASENAME)
+
+#define LOCK_SECTION_START(extra)		\
+	".subsection 1\n\t"			\
+	extra					\
+	".ifndef " LOCK_SECTION_NAME "\n\t"	\
+	LOCK_SECTION_NAME ":\n\t"		\
+	".endif\n\t"
+
+#define LOCK_SECTION_END			\
+	".previous\n\t"
+
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
 
@@ -45,8 +66,10 @@
 
 #if (DEBUG_SPINLOCKS < 1)
 
+#ifndef CONFIG_PREEMPT
 #define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
 #define ATOMIC_DEC_AND_LOCK
+#endif
 
 /*
  * Your basic spinlocks, allowing only a single CPU anywhere
@@ -62,11 +85,11 @@
 #endif
 
 #define spin_lock_init(lock)	do { } while(0)
-#define spin_lock(lock)		(void)(lock) /* Not "unused variable". */
+#define _raw_spin_lock(lock)	(void)(lock) /* Not "unused variable". */
 #define spin_is_locked(lock)	(0)
-#define spin_trylock(lock)	({1; })
+#define _raw_spin_trylock(lock)	({1; })
 #define spin_unlock_wait(lock)	do { } while(0)
-#define spin_unlock(lock)	do { } while(0)
+#define _raw_spin_unlock(lock)	do { } while(0)
 
 #elif (DEBUG_SPINLOCKS < 2)
 
@@ -125,12 +148,78 @@
 #endif
 
 #define rwlock_init(lock)	do { } while(0)
-#define read_lock(lock)		(void)(lock) /* Not "unused variable". */
-#define read_unlock(lock)	do { } while(0)
-#define write_lock(lock)	(void)(lock) /* Not "unused variable". */
-#define write_unlock(lock)	do { } while(0)
+#define _raw_read_lock(lock)	(void)(lock) /* Not "unused variable". */
+#define _raw_read_unlock(lock)	do { } while(0)
+#define _raw_write_lock(lock)	(void)(lock) /* Not "unused variable". */
+#define _raw_write_unlock(lock)	do { } while(0)
 
 #endif /* !SMP */
+
+#ifdef CONFIG_PREEMPT
+
+asmlinkage void preempt_schedule(void);
+
+#define preempt_get_count() (current_thread_info()->preempt_count)
+
+#define preempt_disable() \
+do { \
+	++current_thread_info()->preempt_count; \
+	barrier(); \
+} while (0)
+
+#define preempt_enable_no_resched() \
+do { \
+	--current_thread_info()->preempt_count; \
+	barrier(); \
+} while (0)
+
+#define preempt_enable() \
+do { \
+	--current_thread_info()->preempt_count; \
+	barrier(); \
+	if (unlikely(!(current_thread_info()->preempt_count) && \
+		test_thread_flag(TIF_NEED_RESCHED))) \
+			preempt_schedule(); \
+} while (0)
+
+#define spin_lock(lock)	\
+do { \
+	preempt_disable(); \
+	_raw_spin_lock(lock); \
+} while(0)
+
+#define spin_trylock(lock)	({preempt_disable(); _raw_spin_trylock(lock) ? \
+				1 : ({preempt_enable(); 0;});})
+#define spin_unlock(lock) \
+do { \
+	_raw_spin_unlock(lock); \
+	preempt_enable(); \
+} while (0)
+
+#define read_lock(lock)		({preempt_disable(); _raw_read_lock(lock);})
+#define read_unlock(lock)	({_raw_read_unlock(lock); preempt_enable();})
+#define write_lock(lock)	({preempt_disable(); _raw_write_lock(lock);})
+#define write_unlock(lock)	({_raw_write_unlock(lock); preempt_enable();})
+#define write_trylock(lock)	({preempt_disable();_raw_write_trylock(lock) ? \
+				1 : ({preempt_enable(); 0;});})
+
+#else
+
+#define preempt_get_count()	do { } while (0)
+#define preempt_disable()	do { } while (0)
+#define preempt_enable_no_resched()	do {} while(0)
+#define preempt_enable()	do { } while (0)
+
+#define spin_lock(lock)		_raw_spin_lock(lock)
+#define spin_trylock(lock)	_raw_spin_trylock(lock)
+#define spin_unlock(lock)	_raw_spin_unlock(lock)
+
+#define read_lock(lock)		_raw_read_lock(lock)
+#define read_unlock(lock)	_raw_read_unlock(lock)
+#define write_lock(lock)	_raw_write_lock(lock)
+#define write_unlock(lock)	_raw_write_unlock(lock)
+#define write_trylock(lock)	_raw_write_trylock(lock)
+#endif
 
 /* "lock on reference count zero" */
 #ifndef ATOMIC_DEC_AND_LOCK
diff -Nru a/include/linux/stat.h b/include/linux/stat.h
--- a/include/linux/stat.h	Sun Feb 10 19:58:05 2002
+++ b/include/linux/stat.h	Sun Feb 10 19:58:05 2002
@@ -52,6 +52,25 @@
 #define S_IRUGO		(S_IRUSR|S_IRGRP|S_IROTH)
 #define S_IWUGO		(S_IWUSR|S_IWGRP|S_IWOTH)
 #define S_IXUGO		(S_IXUSR|S_IXGRP|S_IXOTH)
+
+#include <linux/types.h>
+
+struct kstat {
+	unsigned long	ino;
+	dev_t		dev;
+	umode_t		mode;
+	nlink_t		nlink;
+	uid_t		uid;
+	gid_t		gid;
+	dev_t		rdev;
+	loff_t		size;
+	time_t		atime;
+	time_t		mtime;
+	time_t		ctime;
+	unsigned long	blksize;
+	unsigned long	blocks;
+};
+
 #endif
 
 #endif
diff -Nru a/include/linux/stringify.h b/include/linux/stringify.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/stringify.h	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,12 @@
+#ifndef __LINUX_STRINGIFY_H
+#define __LINUX_STRINGIFY_H
+
+/* Indirect stringification.  Doing two levels allows the parameter to be a
+ * macro itself.  For example, compile with -DFOO=bar, __stringify(FOO)
+ * converts to "bar".
+ */
+
+#define __stringify_1(x)	#x
+#define __stringify(x)		__stringify_1(x)
+
+#endif	/* !__LINUX_STRINGIFY_H */
diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
--- a/include/linux/sunrpc/svc.h	Sun Feb 10 19:58:03 2002
+++ b/include/linux/sunrpc/svc.h	Sun Feb 10 19:58:03 2002
@@ -14,6 +14,7 @@
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcauth.h>
+#include <linux/wait.h>
 
 /*
  * RPC service.
diff -Nru a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
--- a/include/linux/sunrpc/xdr.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/sunrpc/xdr.h	Sun Feb 10 19:58:06 2002
@@ -10,6 +10,7 @@
 #ifdef __KERNEL__
 
 #include <linux/uio.h>
+#include <asm/byteorder.h>
 
 /*
  * Buffer adjustment
diff -Nru a/include/linux/swap.h b/include/linux/swap.h
--- a/include/linux/swap.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/swap.h	Sun Feb 10 19:58:04 2002
@@ -2,6 +2,9 @@
 #define _LINUX_SWAP_H
 
 #include <linux/spinlock.h>
+#include <linux/kdev_t.h>
+#include <linux/linkage.h>
+#include <linux/mmzone.h>
 #include <asm/page.h>
 
 #define SWAP_FLAG_PREFER	0x8000	/* set if swap priority specified */
@@ -39,6 +42,14 @@
 	} info;
 };
 
+ /* A swap entry has to fit into a "unsigned long", as
+  * the entry is hidden in the "index" field of the
+  * swapper address space.
+  */
+typedef struct {
+	unsigned long val;
+} swp_entry_t;
+
 #ifdef __KERNEL__
 
 /*
@@ -50,8 +61,12 @@
 
 #include <asm/atomic.h>
 
-#define SWP_USED	1
-#define SWP_WRITEOK	3
+enum {
+	SWP_USED	= (1 << 0),	/* is slot in swap_info[] used? */
+	SWP_WRITEOK	= (1 << 1),	/* ok to write to this swap?	*/
+	SWP_BLOCKDEV	= (1 << 2),	/* is this swap a block device? */
+	SWP_ACTIVE	= (SWP_USED | SWP_WRITEOK),
+};
 
 #define SWAP_CLUSTER_MAX 32
 
@@ -63,7 +78,6 @@
  */
 struct swap_info_struct {
 	unsigned int flags;
-	kdev_t swap_device;
 	spinlock_t sdev_lock;
 	struct file *swap_file;
 	unsigned short * swap_map;
diff -Nru a/include/linux/thread_info.h b/include/linux/thread_info.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/thread_info.h	Sun Feb 10 19:58:06 2002
@@ -0,0 +1,82 @@
+/* thread_info.h: common low-level thread information accessors
+ *
+ * Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ * - Incorporating suggestions made by Linus Torvalds
+ */
+
+#ifndef _LINUX_THREAD_INFO_H
+#define _LINUX_THREAD_INFO_H
+
+#include <asm/thread_info.h>
+#include <asm/bitops.h>
+
+#ifdef __KERNEL__
+
+/*
+ * flag set/clear/test wrappers
+ * - pass TIF_xxxx constants to these functions
+ */
+
+static inline void set_thread_flag(int flag)
+{
+	set_bit(flag,&current_thread_info()->flags);
+}
+
+static inline void clear_thread_flag(int flag)
+{
+	clear_bit(flag,&current_thread_info()->flags);
+}
+
+static inline int test_and_set_thread_flag(int flag)
+{
+	return test_and_set_bit(flag,&current_thread_info()->flags);
+}
+
+static inline int test_and_clear_thread_flag(int flag)
+{
+	return test_and_clear_bit(flag,&current_thread_info()->flags);
+}
+
+static inline int test_thread_flag(int flag)
+{
+	return test_bit(flag,&current_thread_info()->flags);
+}
+
+static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	set_bit(flag,&ti->flags);
+}
+
+static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	clear_bit(flag,&ti->flags);
+}
+
+static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_set_bit(flag,&ti->flags);
+}
+
+static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_clear_bit(flag,&ti->flags);
+}
+
+static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_bit(flag,&ti->flags);
+}
+
+static inline void set_need_resched(void)
+{
+	set_thread_flag(TIF_NEED_RESCHED);
+}
+
+static inline void clear_need_resched(void)
+{
+	clear_thread_flag(TIF_NEED_RESCHED);
+}
+
+#endif
+
+#endif /* _LINUX_THREAD_INFO_H */
diff -Nru a/include/linux/time.h b/include/linux/time.h
--- a/include/linux/time.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/time.h	Sun Feb 10 19:58:04 2002
@@ -82,6 +82,10 @@
 	)*60 + sec; /* finally seconds */
 }
 
+extern struct timeval xtime;
+
+#define CURRENT_TIME (xtime.tv_sec)
+
 #endif /* __KERNEL__ */
 
 
diff -Nru a/include/linux/timex.h b/include/linux/timex.h
--- a/include/linux/timex.h	Sun Feb 10 19:58:04 2002
+++ b/include/linux/timex.h	Sun Feb 10 19:58:04 2002
@@ -51,6 +51,7 @@
 #ifndef _LINUX_TIMEX_H
 #define _LINUX_TIMEX_H
 
+#include <linux/time.h>
 #include <asm/param.h>
 
 /*
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/usb.h	Sun Feb 10 19:58:06 2002
@@ -1,6 +1,8 @@
 #ifndef __LINUX_USB_H
 #define __LINUX_USB_H
 
+#include <linux/device.h>
+
 /* USB constants */
 
 /*
@@ -260,6 +262,7 @@
 	int max_altsetting;             /* total memory allocated */
  
 	struct usb_driver *driver;	/* driver */
+	struct device dev;		/* interface specific device info */
 	void *private_data;
 };
 
@@ -857,7 +860,7 @@
 extern void usb_free_urb(struct urb *urb);
 #define usb_put_urb usb_free_urb
 extern struct urb *usb_get_urb(struct urb *urb);
-extern int usb_submit_urb(struct urb *urb);
+extern int usb_submit_urb(struct urb *urb, int mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 
 /*-------------------------------------------------------------------*
@@ -906,7 +909,7 @@
 	int (*allocate)(struct usb_device *);
 	int (*deallocate)(struct usb_device *);
 	int (*get_frame_number) (struct usb_device *usb_dev);
-	int (*submit_urb) (struct urb *urb);
+	int (*submit_urb) (struct urb *urb, int mem_flags);
 	int (*unlink_urb) (struct urb *urb);
 };
 
@@ -945,6 +948,7 @@
 extern void usb_free_bus(struct usb_bus *);
 extern void usb_register_bus(struct usb_bus *);
 extern void usb_deregister_bus(struct usb_bus *);
+extern int usb_register_root_hub(struct usb_device *usb_dev, struct device *parent_dev);
 
 extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
 extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
@@ -1040,6 +1044,8 @@
 
 	struct usb_device *parent;
 	struct usb_bus *bus;		/* Bus we're part of */
+
+	struct device dev;		/* Generic device interface */
 
 	struct usb_device_descriptor descriptor;/* Descriptor */
 	struct usb_config_descriptor *config;	/* All of the configs */
diff -Nru a/include/linux/vmalloc.h b/include/linux/vmalloc.h
--- a/include/linux/vmalloc.h	Sun Feb 10 19:58:06 2002
+++ b/include/linux/vmalloc.h	Sun Feb 10 19:58:06 2002
@@ -1,7 +1,6 @@
 #ifndef __LINUX_VMALLOC_H
 #define __LINUX_VMALLOC_H
 
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 
diff -Nru a/include/linux/zconf.h b/include/linux/zconf.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/zconf.h	Sun Feb 10 19:58:05 2002
@@ -0,0 +1,90 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+#if defined(__GNUC__) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+
+#if defined(__STDC__) || defined(__cplusplus)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  define MAX_MEM_LEVEL 9
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef FAR
+#   define FAR
+#endif
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+typedef Byte  FAR Bytef;
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+typedef void FAR *voidpf;
+typedef void     *voidp;
+
+#include <linux/types.h> /* for off_t */
+#include <linux/unistd.h>    /* for SEEK_* and off_t */
+#define z_off_t  off_t
+
+#endif /* _ZCONF_H */
diff -Nru a/include/linux/zutil.h b/include/linux/zutil.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/zutil.h	Sun Feb 10 19:58:04 2002
@@ -0,0 +1,126 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include <linux/zlib.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+        /* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+         /* functions */
+
+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
+				       uInt len));
+
+
+                        /* checksum functions */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+static inline uLong zlib_adler32(uLong adler,
+				 const Bytef *buf,
+				 uInt len)
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+	    buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+	    s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
+
+#endif /* _Z_UTIL_H */
diff -Nru a/include/net/neighbour.h b/include/net/neighbour.h
--- a/include/net/neighbour.h	Sun Feb 10 19:58:06 2002
+++ b/include/net/neighbour.h	Sun Feb 10 19:58:06 2002
@@ -46,6 +46,8 @@
 #include <asm/atomic.h>
 #include <linux/skbuff.h>
 
+#include <linux/err.h>
+
 #define NUD_IN_TIMER	(NUD_INCOMPLETE|NUD_DELAY|NUD_PROBE)
 #define NUD_VALID	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
 #define NUD_CONNECTED	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
diff -Nru a/include/net/scm.h b/include/net/scm.h
--- a/include/net/scm.h	Sun Feb 10 19:58:06 2002
+++ b/include/net/scm.h	Sun Feb 10 19:58:06 2002
@@ -1,6 +1,8 @@
 #ifndef __LINUX_NET_SCM_H
 #define __LINUX_NET_SCM_H
 
+#include <linux/limits.h>
+
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
  */
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	Sun Feb 10 19:58:04 2002
+++ b/include/net/sock.h	Sun Feb 10 19:58:04 2002
@@ -106,6 +106,8 @@
 #include <asm/atomic.h>
 #include <net/dst.h>
 
+#include <linux/fs.h>	/* just for inode - yeuch.*/
+
 
 /* The AF_UNIX specific socket options */
 struct unix_opt {
@@ -1022,7 +1024,7 @@
 	int uid;
 
 	read_lock(&sk->callback_lock);
-	uid = sk->socket ? sk->socket->inode->i_uid : 0;
+	uid = sk->socket ? SOCK_INODE(sk->socket)->i_uid : 0;
 	read_unlock(&sk->callback_lock);
 	return uid;
 }
@@ -1032,7 +1034,7 @@
 	unsigned long ino;
 
 	read_lock(&sk->callback_lock);
-	ino = sk->socket ? sk->socket->inode->i_ino : 0;
+	ino = sk->socket ? SOCK_INODE(sk->socket)->i_ino : 0;
 	read_unlock(&sk->callback_lock);
 	return ino;
 }
diff -Nru a/init/Config.in b/init/Config.in
--- a/init/Config.in	Sun Feb 10 19:58:04 2002
+++ b/init/Config.in	Sun Feb 10 19:58:04 2002
@@ -1,16 +1,14 @@
 mainmenu_option next_comment
-comment 'General setup'
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
 
+mainmenu_option next_comment
+comment 'General setup'
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
-
-endmenu
-
-mainmenu_option next_comment
-comment 'Code maturity level options'
-bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
 endmenu
 
 mainmenu_option next_comment
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Sun Feb 10 19:58:04 2002
+++ b/init/main.c	Sun Feb 10 19:58:04 2002
@@ -31,8 +31,6 @@
 #include <asm/io.h>
 #include <asm/bugs.h>
 
-#include <linux/device.h>
-
 #if defined(CONFIG_ARCH_S390)
 #include <asm/s390mach.h>
 #include <asm/ccwcache.h>
@@ -446,10 +444,6 @@
 #if defined(CONFIG_ARCH_S390)
 	s390_init_machine_check();
 #endif
-
-	/* bring up the device tree */
-	device_driver_init();
-
 	/* Networking initialization needs a process context */ 
 	sock_init();
 
diff -Nru a/kernel/exec_domain.c b/kernel/exec_domain.c
--- a/kernel/exec_domain.c	Sun Feb 10 19:58:04 2002
+++ b/kernel/exec_domain.c	Sun Feb 10 19:58:04 2002
@@ -67,8 +67,8 @@
 	}
 	set_personality(pers);
 
-	if (current->exec_domain->handler != default_handler)
-		current->exec_domain->handler(segment, regp);
+	if (current_thread_info()->exec_domain->handler != default_handler)
+		current_thread_info()->exec_domain->handler(segment, regp);
 	else
 		send_sig(SIGSEGV, current, 1);
 }
@@ -162,7 +162,7 @@
 	struct exec_domain	*ep, *oep;
 
 	ep = lookup_exec_domain(personality);
-	if (ep == current->exec_domain) {
+	if (ep == current_thread_info()->exec_domain) {
 		current->personality = personality;
 		return 0;
 	}
@@ -190,8 +190,8 @@
 	 */
 
 	current->personality = personality;
-	oep = current->exec_domain;
-	current->exec_domain = ep;
+	oep = current_thread_info()->exec_domain;
+	current_thread_info()->exec_domain = ep;
 	set_fs_altroot();
 
 	put_exec_domain(oep);
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Sun Feb 10 19:58:05 2002
+++ b/kernel/exit.c	Sun Feb 10 19:58:05 2002
@@ -18,6 +18,7 @@
 #include <linux/acct.h>
 #endif
 #include <linux/file.h>
+#include <linux/binfmts.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -65,7 +66,7 @@
 	__restore_flags(flags);
 
 	p->pid = 0;
-	free_task_struct(p);
+	put_task_struct(p);
 }
 
 /*
@@ -390,8 +391,8 @@
 		/* more a memory barrier than a real lock */
 		task_lock(tsk);
 		tsk->mm = NULL;
-		task_unlock(tsk);
 		enter_lazy_tlb(mm, current, smp_processor_id());
+		task_unlock(tsk);
 		mmput(mm);
 	}
 }
@@ -529,7 +530,7 @@
 	if (current->leader)
 		disassociate_ctty(1);
 
-	put_exec_domain(tsk->exec_domain);
+	put_exec_domain(tsk->thread_info->exec_domain);
 	if (tsk->binfmt && tsk->binfmt->module)
 		__MOD_DEC_USE_COUNT(tsk->binfmt->module);
 
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Sun Feb 10 19:58:04 2002
+++ b/kernel/fork.c	Sun Feb 10 19:58:04 2002
@@ -22,12 +22,16 @@
 #include <linux/namespace.h>
 #include <linux/personality.h>
 #include <linux/file.h>
+#include <linux/binfmts.h>
+#include <linux/fs.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
+static kmem_cache_t *task_struct_cachep;
+
 /* The idle threads do not count.. */
 int nr_threads;
 
@@ -70,6 +74,14 @@
 
 void __init fork_init(unsigned long mempages)
 {
+	/* create a slab on which task_structs can be allocated */
+	task_struct_cachep =
+		kmem_cache_create("task_struct",
+				  sizeof(struct task_struct),0,
+				  SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (!task_struct_cachep)
+		panic("fork_init(): cannot create task_struct SLAB cache");
+
 	/*
 	 * The default maximum number of threads is set to a safe
 	 * value: the thread structures can take up at most half
@@ -81,6 +93,35 @@
 	init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
 }
 
+struct task_struct *dup_task_struct(struct task_struct *orig)
+{
+	struct task_struct *tsk;
+	struct thread_info *ti;
+
+	ti = alloc_thread_info();
+	if (!ti) return NULL;
+
+	tsk = kmem_cache_alloc(task_struct_cachep,GFP_ATOMIC);
+	if (!tsk) {
+		free_thread_info(ti);
+		return NULL;
+	}
+
+	*ti = *orig->thread_info;
+	*tsk = *orig;
+	tsk->thread_info = ti;
+	ti->task = tsk;
+	atomic_set(&tsk->usage,1);
+
+	return tsk;
+}
+
+void __put_task_struct(struct task_struct *tsk)
+{
+	free_thread_info(tsk->thread_info);
+	kmem_cache_free(task_struct_cachep,tsk);
+}
+
 /* Protects next_safe and last_pid. */
 spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
 
@@ -546,7 +587,7 @@
 {
 	unsigned long new_flags = p->flags;
 
-	new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU);
+	new_flags &= ~PF_SUPERPRIV;
 	new_flags |= PF_FORKNOEXEC;
 	if (!(clone_flags & CLONE_PTRACE))
 		p->ptrace = 0;
@@ -585,12 +626,10 @@
 	}
 
 	retval = -ENOMEM;
-	p = alloc_task_struct();
+	p = dup_task_struct(current);
 	if (!p)
 		goto fork_out;
 
-	*p = *current;
-
 	retval = -EAGAIN;
 	if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) {
 		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
@@ -608,11 +647,18 @@
 	if (nr_threads >= max_threads)
 		goto bad_fork_cleanup_count;
 	
-	get_exec_domain(p->exec_domain);
+	get_exec_domain(p->thread_info->exec_domain);
 
 	if (p->binfmt && p->binfmt->module)
 		__MOD_INC_USE_COUNT(p->binfmt->module);
 
+#ifdef CONFIG_PREEMPT
+	/*
+	 * schedule_tail drops this_rq()->lock so we compensate with a count
+	 * of 1.  Also, we want to start with kernel preemption disabled.
+	 */
+	p->thread_info->preempt_count = 1;
+#endif
 	p->did_exec = 0;
 	p->swappable = 0;
 	p->state = TASK_UNINTERRUPTIBLE;
@@ -631,7 +677,7 @@
 	}
 	spin_lock_init(&p->alloc_lock);
 
-	p->work.sigpending = 0;
+	clear_tsk_thread_flag(p,TIF_SIGPENDING);
 	init_sigpending(&p->pending);
 
 	p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
@@ -724,10 +770,10 @@
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
 
-	/* CLONE_PARENT and CLONE_THREAD re-use the old parent */
+	/* CLONE_PARENT re-uses the old parent */
 	p->p_opptr = current->p_opptr;
 	p->p_pptr = current->p_pptr;
-	if (!(clone_flags & (CLONE_PARENT | CLONE_THREAD))) {
+	if (!(clone_flags & CLONE_PARENT)) {
 		p->p_opptr = current;
 		if (!(p->ptrace & PT_PTRACED))
 			p->p_pptr = current;
@@ -755,7 +801,7 @@
 		 * Let the child process run first, to avoid most of the
 		 * COW overhead when the child exec()s afterwards.
 		 */
-		current->work.need_resched = 1;
+		set_need_resched();
 
 fork_out:
 	return retval;
@@ -771,14 +817,14 @@
 bad_fork_cleanup_files:
 	exit_files(p); /* blocking */
 bad_fork_cleanup:
-	put_exec_domain(p->exec_domain);
+	put_exec_domain(p->thread_info->exec_domain);
 	if (p->binfmt && p->binfmt->module)
 		__MOD_DEC_USE_COUNT(p->binfmt->module);
 bad_fork_cleanup_count:
 	atomic_dec(&p->user->processes);
 	free_uid(p->user);
 bad_fork_free:
-	free_task_struct(p);
+	put_task_struct(p);
 	goto fork_out;
 }
 
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Sun Feb 10 19:58:03 2002
+++ b/kernel/ksyms.c	Sun Feb 10 19:58:03 2002
@@ -47,6 +47,7 @@
 #include <linux/in6.h>
 #include <linux/completion.h>
 #include <linux/seq_file.h>
+#include <linux/binfmts.h>
 #include <asm/checksum.h>
 
 #if defined(CONFIG_PROC_FS)
@@ -249,8 +250,12 @@
 EXPORT_SYMBOL(vfs_unlink);
 EXPORT_SYMBOL(vfs_rename);
 EXPORT_SYMBOL(vfs_statfs);
+EXPORT_SYMBOL(vfs_fstat);
+EXPORT_SYMBOL(vfs_stat);
+EXPORT_SYMBOL(vfs_lstat);
 EXPORT_SYMBOL(generic_read_dir);
 EXPORT_SYMBOL(generic_file_llseek);
+EXPORT_SYMBOL(remote_llseek);
 EXPORT_SYMBOL(no_llseek);
 EXPORT_SYMBOL(__pollwait);
 EXPORT_SYMBOL(poll_freewait);
@@ -274,6 +279,9 @@
 EXPORT_SYMBOL(dcache_readdir);
 EXPORT_SYMBOL(fd_install);
 EXPORT_SYMBOL(put_unused_fd);
+EXPORT_SYMBOL(get_sb_bdev);
+EXPORT_SYMBOL(get_sb_nodev);
+EXPORT_SYMBOL(get_sb_single);
 
 /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
 EXPORT_SYMBOL(default_llseek);
@@ -441,6 +449,9 @@
 EXPORT_SYMBOL(interruptible_sleep_on);
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 EXPORT_SYMBOL(schedule);
+#ifdef CONFIG_PREEMPT
+EXPORT_SYMBOL(preempt_schedule);
+#endif
 EXPORT_SYMBOL(schedule_timeout);
 EXPORT_SYMBOL(sys_sched_yield);
 EXPORT_SYMBOL(set_user_nice);
@@ -559,7 +570,8 @@
 
 /* init task, for moving kthread roots - ought to export a function ?? */
 
-EXPORT_SYMBOL(init_task_union);
+EXPORT_SYMBOL(init_task);
+EXPORT_SYMBOL(init_thread_union);
 
 EXPORT_SYMBOL(tasklist_lock);
 EXPORT_SYMBOL(pidhash);
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Sun Feb 10 19:58:04 2002
+++ b/kernel/module.c	Sun Feb 10 19:58:04 2002
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/kmod.h>
 #include <linux/seq_file.h>
+#include <linux/fs.h>
 
 /*
  * Originally by Anonymous (as far as I know...)
@@ -1074,84 +1075,67 @@
 /*
  * Called by the /proc file system to return a current list of modules.
  */
-
-int get_module_list(char *p)
+static void *m_start(struct seq_file *m, loff_t *pos)
 {
-	size_t left = PAGE_SIZE;
-	struct module *mod;
-	char tmpstr[64];
-	struct module_ref *ref;
-
-	for (mod = module_list; mod != &kernel_module; mod = mod->next) {
-		long len;
-		const char *q;
-
-#define safe_copy_str(str, len)						\
-		do {							\
-			if (left < len)					\
-				goto fini;				\
-			memcpy(p, str, len); p += len, left -= len;	\
-		} while (0)
-#define safe_copy_cstr(str)	safe_copy_str(str, sizeof(str)-1)
-
-		len = strlen(mod->name);
-		safe_copy_str(mod->name, len);
-
-		if ((len = 20 - len) > 0) {
-			if (left < len)
-				goto fini;
-			memset(p, ' ', len);
-			p += len;
-			left -= len;
-		}
-
-		len = sprintf(tmpstr, "%8lu", mod->size);
-		safe_copy_str(tmpstr, len);
-
-		if (mod->flags & MOD_RUNNING) {
-			len = sprintf(tmpstr, "%4ld",
-				      (mod_member_present(mod, can_unload)
-				       && mod->can_unload
-				       ? -1L : (long)atomic_read(&mod->uc.usecount)));
-			safe_copy_str(tmpstr, len);
-		}
-
-		if (mod->flags & MOD_DELETED)
-			safe_copy_cstr(" (deleted)");
-		else if (mod->flags & MOD_RUNNING) {
-			if (mod->flags & MOD_AUTOCLEAN)
-				safe_copy_cstr(" (autoclean)");
-			if (!(mod->flags & MOD_USED_ONCE))
-				safe_copy_cstr(" (unused)");
-		}
-		else if (mod->flags & MOD_INITIALIZING)
-			safe_copy_cstr(" (initializing)");
-		else
-			safe_copy_cstr(" (uninitialized)");
-
-		if ((ref = mod->refs) != NULL) {
-			safe_copy_cstr(" [");
-			while (1) {
-				q = ref->ref->name;
-				len = strlen(q);
-				safe_copy_str(q, len);
-
-				if ((ref = ref->next_ref) != NULL)
-					safe_copy_cstr(" ");
-				else
-					break;
-			}
-			safe_copy_cstr("]");
-		}
-		safe_copy_cstr("\n");
+	struct module *v;
+	loff_t n = *pos;
+	lock_kernel();
+	for (v = module_list; v && n--; v = v->next)
+		;
+	return v;
+}
+static void *m_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	struct module *v = p;
+	(*pos)++;
+	return v->next;
+}
+static void m_stop(struct seq_file *m, void *p)
+{
+	unlock_kernel();
+}
+static int m_show(struct seq_file *m, void *p)
+{
+	struct module *mod = p;
+	struct module_ref *ref = mod->refs;
 
-#undef safe_copy_str
-#undef safe_copy_cstr
-	}
+	if (mod == &kernel_module)
+		return 0;
 
-fini:
-	return PAGE_SIZE - left;
-}
+	seq_printf(m, "%-20s%8lu", mod->name, mod->size);
+	if (mod->flags & MOD_RUNNING)
+		seq_printf(m, "%4ld",
+			      (mod_member_present(mod, can_unload)
+			       && mod->can_unload
+			       ? -1L : (long)atomic_read(&mod->uc.usecount)));
+
+	if (mod->flags & MOD_DELETED)
+		seq_puts(m, " (deleted)");
+	else if (mod->flags & MOD_RUNNING) {
+		if (mod->flags & MOD_AUTOCLEAN)
+			seq_puts(m, " (autoclean)");
+		if (!(mod->flags & MOD_USED_ONCE))
+			seq_puts(m, " (unused)");
+	} else if (mod->flags & MOD_INITIALIZING)
+		seq_puts(m, " (initializing)");
+	else
+		seq_puts(m, " (uninitialized)");
+	if (ref) {
+		char c;
+		seq_putc(m, ' ');
+		for (c = '[' ; ref; c = ' ', ref = ref->next_ref)
+			seq_printf(m, "%c%s", c, ref->ref->name);
+		seq_putc(m, ']');
+	}
+	seq_putc(m, '\n');
+	return 0;
+}
+struct seq_operations modules_op = {
+	start:	m_start,
+	next:	m_next,
+	stop:	m_stop,
+	show:	m_show
+};
 
 /*
  * Called by the /proc file system to return a current list of ksyms.
diff -Nru a/kernel/panic.c b/kernel/panic.c
--- a/kernel/panic.c	Sun Feb 10 19:58:05 2002
+++ b/kernel/panic.c	Sun Feb 10 19:58:05 2002
@@ -103,6 +103,10 @@
 /**
  *	print_tainted - return a string to represent the kernel taint state.
  *
+ *  'P' - Proprietory module has been loaded.
+ *  'F' - Module has been forcibly loaded.
+ *  'S' - SMP with CPUs not designed for SMP.
+ *
  *	The string is overwritten by the next call to print_taint().
  */
  
@@ -110,9 +114,10 @@
 {
 	static char buf[20];
 	if (tainted) {
-		snprintf(buf, sizeof(buf), "Tainted: %c%c",
-			tainted & 1 ? 'P' : 'G',
-			tainted & 2 ? 'F' : ' ');
+		snprintf(buf, sizeof(buf), "Tainted: %c%c%c",
+			tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
+			tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
+			tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
 	}
 	else
 		snprintf(buf, sizeof(buf), "Not tainted");
diff -Nru a/kernel/pm.c b/kernel/pm.c
--- a/kernel/pm.c	Sun Feb 10 19:58:04 2002
+++ b/kernel/pm.c	Sun Feb 10 19:58:04 2002
@@ -154,7 +154,7 @@
 int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
 	int status = 0;
-	int prev_state, next_state;
+	unsigned long prev_state, next_state;
 
 	if (in_interrupt())
 		BUG();
@@ -163,7 +163,7 @@
 	case PM_SUSPEND:
 	case PM_RESUME:
 		prev_state = dev->state;
-		next_state = (int) data;
+		next_state = (unsigned long) data;
 		if (prev_state != next_state) {
 			if (dev->callback)
 				status = (*dev->callback)(dev, rqst, data);
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Sun Feb 10 19:58:05 2002
+++ b/kernel/sched.c	Sun Feb 10 19:58:05 2002
@@ -18,6 +18,7 @@
 #include <asm/uaccess.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/completion.h>
 #include <asm/mmu_context.h>
 
 #define BITMAP_SIZE ((((MAX_PRIO+7)/8)+sizeof(long)-1)/sizeof(long))
@@ -51,7 +52,7 @@
 
 #define cpu_rq(cpu)		(runqueues + (cpu))
 #define this_rq()		cpu_rq(smp_processor_id())
-#define task_rq(p)		cpu_rq((p)->cpu)
+#define task_rq(p)		cpu_rq((p)->thread_info->cpu)
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define rt_task(p)		((p)->policy != SCHED_OTHER)
 
@@ -61,10 +62,12 @@
 	struct runqueue *__rq;
 
 repeat_lock_task:
+	preempt_disable();
 	__rq = task_rq(p);
 	spin_lock_irqsave(&__rq->lock, *flags);
 	if (unlikely(__rq != task_rq(p))) {
 		spin_unlock_irqrestore(&__rq->lock, *flags);
+		preempt_enable();
 		goto repeat_lock_task;
 	}
 	return __rq;
@@ -73,6 +76,7 @@
 static inline void unlock_task_rq(runqueue_t *rq, unsigned long *flags)
 {
 	spin_unlock_irqrestore(&rq->lock, *flags);
+	preempt_enable();
 }
 /*
  * Adding/removing a task to/from a priority array:
@@ -192,13 +196,21 @@
 
 static inline void resched_task(task_t *p)
 {
-	int need_resched;
+#ifdef CONFIG_SMP
+	int need_resched, nrpolling;
 
-	need_resched = p->work.need_resched;
-	wmb();
-	p->work.need_resched = 1;
-	if (!need_resched && (p->cpu != smp_processor_id()))
-		smp_send_reschedule(p->cpu);
+	preempt_disable();
+	/* minimise the chance of sending an interrupt to poll_idle() */
+	nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
+	need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED);
+	nrpolling |= test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
+
+	if (!need_resched && !nrpolling && (p->thread_info->cpu != smp_processor_id()))
+		smp_send_reschedule(p->thread_info->cpu);
+	preempt_enable();
+#else
+	set_tsk_need_resched(p);
+#endif
 }
 
 #ifdef CONFIG_SMP
@@ -213,6 +225,7 @@
 	runqueue_t *rq;
 
 repeat:
+	preempt_disable();
 	rq = task_rq(p);
 	while (unlikely(rq->curr == p)) {
 		cpu_relax();
@@ -221,9 +234,11 @@
 	rq = lock_task_rq(p, &flags);
 	if (unlikely(rq->curr == p)) {
 		unlock_task_rq(rq, &flags);
+		preempt_enable();
 		goto repeat;
 	}
 	unlock_task_rq(rq, &flags);
+	preempt_enable();
 }
 
 /*
@@ -236,7 +251,7 @@
 void sched_task_migrated(task_t *new_task)
 {
 	wait_task_inactive(new_task);
-	new_task->cpu = smp_processor_id();
+	new_task->thread_info->cpu = smp_processor_id();
 	wake_up_process(new_task);
 }
 
@@ -289,7 +304,10 @@
 
 void wake_up_forked_process(task_t * p)
 {
-	runqueue_t *rq = this_rq();
+	runqueue_t *rq;
+	
+	preempt_disable();
+	rq = this_rq();
 
 	p->state = TASK_RUNNING;
 	if (!rt_task(p)) {
@@ -299,9 +317,10 @@
 		current->sleep_avg = current->sleep_avg * PARENT_FORK_PENALTY / 100;
 	}
 	spin_lock_irq(&rq->lock);
-	p->cpu = smp_processor_id();
+	p->thread_info->cpu = smp_processor_id();
 	activate_task(p, rq);
 	spin_unlock_irq(&rq->lock);
+	preempt_enable();
 }
 
 asmlinkage void schedule_tail(task_t *prev)
@@ -519,11 +538,11 @@
 	 */
 	dequeue_task(next, array);
 	busiest->nr_running--;
-	next->cpu = this_cpu;
+	next->thread_info->cpu = this_cpu;
 	this_rq->nr_running++;
 	enqueue_task(next, this_rq->active);
 	if (next->prio < current->prio)
-		current->work.need_resched = 1;
+		set_need_resched();
 	if (!idle && --imbalance) {
 		if (array == busiest->expired) {
 			array = busiest->active;
@@ -572,7 +591,7 @@
 #endif
 	/* Task might have expired already, but not scheduled off yet */
 	if (p->array != rq->active) {
-		p->work.need_resched = 1;
+		set_tsk_need_resched(p);
 		return;
 	}
 	spin_lock(&rq->lock);
@@ -583,7 +602,7 @@
 		 */
 		if ((p->policy == SCHED_RR) && !--p->time_slice) {
 			p->time_slice = NICE_TO_TIMESLICE(p->__nice);
-			p->work.need_resched = 1;
+			set_tsk_need_resched(p);
 
 			/* put it at the end of the queue: */
 			dequeue_task(p, rq->active);
@@ -603,7 +622,7 @@
 		p->sleep_avg--;
 	if (!--p->time_slice) {
 		dequeue_task(p, rq->active);
-		p->work.need_resched = 1;
+		set_tsk_need_resched(p);
 		p->prio = effective_prio(p);
 		p->time_slice = NICE_TO_TIMESLICE(p->__nice);
 
@@ -629,17 +648,31 @@
  */
 asmlinkage void schedule(void)
 {
-	task_t *prev = current, *next;
-	runqueue_t *rq = this_rq();
+	task_t *prev, *next;
+	runqueue_t *rq;
 	prio_array_t *array;
 	list_t *queue;
 	int idx;
 
 	if (unlikely(in_interrupt()))
 		BUG();
+
+	preempt_disable();
+	prev = current;
+	rq = this_rq();
+	
 	release_kernel_lock(prev, smp_processor_id());
 	spin_lock_irq(&rq->lock);
 
+#ifdef CONFIG_PREEMPT
+	/*
+	 * if entering from preempt_schedule, off a kernel preemption,
+	 * go straight to picking the next task.
+	 */
+	if (unlikely(preempt_get_count() & PREEMPT_ACTIVE))
+		goto pick_next_task;
+#endif
+	
 	switch (prev->state) {
 	case TASK_RUNNING:
 		prev->sleep_timestamp = jiffies;
@@ -653,7 +686,7 @@
 	default:
 		deactivate_task(prev, rq);
 	}
-#if CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
 pick_next_task:
 #endif
 	if (unlikely(!rq->nr_running)) {
@@ -684,7 +717,7 @@
 
 switch_tasks:
 	prefetch(next);
-	prev->work.need_resched = 0;
+	clear_tsk_need_resched(prev);
 
 	if (likely(prev != next)) {
 		rq->nr_switches++;
@@ -701,9 +734,25 @@
 	spin_unlock_irq(&rq->lock);
 
 	reacquire_kernel_lock(current);
+	preempt_enable_no_resched();
 	return;
 }
 
+#ifdef CONFIG_PREEMPT
+/*
+ * this is is the entry point to schedule() from in-kernel preemption.
+ */
+asmlinkage void preempt_schedule(void)
+{
+	do {
+		current_thread_info()->preempt_count += PREEMPT_ACTIVE;
+		schedule();
+		current_thread_info()->preempt_count -= PREEMPT_ACTIVE;
+		barrier();
+	} while (test_thread_flag(TIF_NEED_RESCHED));
+}
+#endif /* CONFIG_PREEMPT */
+
 /*
  * The core wakeup function.  Non-exclusive wakeups (nr_exclusive == 0) just
  * wake everything up.  If it's an exclusive wakeup (nr_exclusive == small +ve
@@ -1099,9 +1148,12 @@
 
 asmlinkage long sys_sched_yield(void)
 {
-	runqueue_t *rq = this_rq();
+	runqueue_t *rq;
 	prio_array_t *array;
 
+	preempt_disable();
+	rq = this_rq();
+
 	/*
 	 * Decrease the yielding task's priority by one, to avoid
 	 * livelocks. This priority loss is temporary, it's recovered
@@ -1128,6 +1180,7 @@
 		__set_bit(current->prio, array->bitmap);
 	}
 	spin_unlock(&rq->lock);
+	preempt_enable_no_resched();
 
 	schedule();
 
@@ -1203,12 +1256,12 @@
 	if (p == current)
 		printk(" current  ");
 	else
-		printk(" %08lX ", thread_saved_pc(&p->thread));
+		printk(" %08lX ", thread_saved_pc(p));
 #else
 	if (p == current)
 		printk("   current task   ");
 	else
-		printk(" %016lx ", thread_saved_pc(&p->thread));
+		printk(" %016lx ", thread_saved_pc(p));
 #endif
 	{
 		unsigned long * n = (unsigned long *) (p+1);
@@ -1316,9 +1369,9 @@
 	idle->array = NULL;
 	idle->prio = MAX_PRIO;
 	idle->state = TASK_RUNNING;
-	idle->cpu = cpu;
+	idle->thread_info->cpu = cpu;
 	double_rq_unlock(idle_rq, rq);
-	idle->work.need_resched = 1;
+	set_tsk_need_resched(idle);
 	__restore_flags(flags);
 }
 
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Sun Feb 10 19:58:05 2002
+++ b/kernel/signal.c	Sun Feb 10 19:58:05 2002
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 
@@ -23,7 +24,7 @@
 #define DEBUG_SIG 0
 
 #if DEBUG_SIG
-#define SIG_SLAB_DEBUG	(SLAB_DEBUG_FREE | SLAB_RED_ZONE /* | SLAB_POISON */)
+#define SIG_SLAB_DEBUG	(SLAB_RED_ZONE /* | SLAB_POISON */)
 #else
 #define SIG_SLAB_DEBUG	0
 #endif
@@ -105,7 +106,7 @@
 void
 flush_signals(struct task_struct *t)
 {
-	t->work.sigpending = 0;
+	clear_tsk_thread_flag(t,TIF_SIGPENDING);
 	flush_sigqueue(&t->pending);
 }
 
@@ -119,7 +120,7 @@
 		if (atomic_dec_and_test(&sig->count))
 			kmem_cache_free(sigact_cachep, sig);
 	}
-	tsk->work.sigpending = 0;
+	clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
 	flush_sigqueue(&tsk->pending);
 	spin_unlock_irq(&tsk->sigmask_lock);
 }
@@ -142,6 +143,35 @@
 	}
 }
 
+/*
+ * sig_exit - cause the current task to exit due to a signal.
+ */
+
+void
+sig_exit(int sig, int exit_code, struct siginfo *info)
+{
+	struct task_struct *t;
+
+	sigaddset(&current->pending.signal, sig);
+	recalc_sigpending(current);
+	current->flags |= PF_SIGNALED;
+
+	/* Propagate the signal to all the tasks in
+	 *  our thread group
+	 */
+	if (info && (unsigned long)info != 1
+	    && info->si_code != SI_TKILL) {
+		read_lock(&tasklist_lock);
+		for_each_thread(t) {
+			force_sig_info(sig, info, t);
+		}
+		read_unlock(&tasklist_lock);
+	}
+
+	do_exit(exit_code);
+	/* NOTREACHED */
+}
+
 /* Notify the system that a driver wants to block all signals for this
  * process, and wants to be notified if any signals at all were to be
  * sent/acted upon.  If the notifier routine returns non-zero, then the
@@ -246,7 +276,7 @@
 		if (current->notifier) {
 			if (sigismember(current->notifier_mask, sig)) {
 				if (!(current->notifier)(current->notifier_data)) {
-					current->work.sigpending = 0;
+					clear_thread_flag(TIF_SIGPENDING);
 					return 0;
 				}
 			}
@@ -465,7 +495,7 @@
  */
 static inline void signal_wake_up(struct task_struct *t)
 {
-	t->work.sigpending = 1;
+	set_tsk_thread_flag(t,TIF_SIGPENDING);
 
 #ifdef CONFIG_SMP
 	/*
@@ -478,7 +508,7 @@
 	 * process of changing - but no harm is done by that
 	 * other than doing an extra (lightweight) IPI interrupt.
 	 */
-	if ((t->state == TASK_RUNNING) && (t->cpu != smp_processor_id()))
+	if ((t->state == TASK_RUNNING) && (t->thread_info->cpu != smp_processor_id()))
 		kick_if_running(t);
 #endif
 	if (t->state & TASK_INTERRUPTIBLE) {
@@ -589,7 +619,7 @@
 		retval = -ESRCH;
 		read_lock(&tasklist_lock);
 		for_each_task(p) {
-			if (p->pgrp == pgrp) {
+			if (p->pgrp == pgrp && thread_group_leader(p)) {
 				int err = send_sig_info(sig, info, p);
 				if (retval)
 					retval = err;
@@ -636,8 +666,15 @@
 	read_lock(&tasklist_lock);
 	p = find_task_by_pid(pid);
 	error = -ESRCH;
-	if (p)
+	if (p) {
+		if (!thread_group_leader(p)) {
+                       struct task_struct *tg;
+                       tg = find_task_by_pid(p->tgid);
+                       if (tg)
+                               p = tg;
+                }
 		error = send_sig_info(sig, info, p);
+	}
 	read_unlock(&tasklist_lock);
 	return error;
 }
@@ -660,7 +697,7 @@
 
 		read_lock(&tasklist_lock);
 		for_each_task(p) {
-			if (p->pid > 1 && p != current) {
+			if (p->pid > 1 && p != current && thread_group_leader(p)) {
 				int err = send_sig_info(sig, info, p);
 				++count;
 				if (err != -EPERM)
@@ -983,6 +1020,36 @@
 	info.si_uid = current->uid;
 
 	return kill_something_info(sig, &info, pid);
+}
+
+/*
+ *  Kill only one task, even if it's a CLONE_THREAD task.
+ */
+asmlinkage long
+sys_tkill(int pid, int sig)
+{
+       struct siginfo info;
+       int error;
+       struct task_struct *p;
+
+       /* This is only valid for single tasks */
+       if (pid <= 0)
+           return -EINVAL;
+
+       info.si_signo = sig;
+       info.si_errno = 0;
+       info.si_code = SI_TKILL;
+       info.si_pid = current->pid;
+       info.si_uid = current->uid;
+
+       read_lock(&tasklist_lock);
+       p = find_task_by_pid(pid);
+       error = -ESRCH;
+       if (p) {
+               error = send_sig_info(sig, &info, p);
+       }
+       read_unlock(&tasklist_lock);
+       return error;
 }
 
 asmlinkage long
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Sun Feb 10 19:58:04 2002
+++ b/kernel/sys.c	Sun Feb 10 19:58:04 2002
@@ -14,6 +14,7 @@
 #include <linux/prctl.h>
 #include <linux/init.h>
 #include <linux/highuid.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Sun Feb 10 19:58:04 2002
+++ b/kernel/sysctl.c	Sun Feb 10 19:58:04 2002
@@ -677,7 +677,7 @@
 	size_t res;
 	ssize_t error;
 	
-	de = (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip;
+	de = PDE(file->f_dentry->d_inode);
 	if (!de || !de->data)
 		return -ENOTDIR;
 	table = (struct ctl_table *) de->data;
diff -Nru a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c	Sun Feb 10 19:58:05 2002
+++ b/kernel/time.c	Sun Feb 10 19:58:05 2002
@@ -24,7 +24,6 @@
  *	(Even though the technical memorandum forbids it)
  */
 
-#include <linux/mm.h>
 #include <linux/timex.h>
 #include <linux/smp_lock.h>
 
diff -Nru a/lib/crc32.c b/lib/crc32.c
--- a/lib/crc32.c	Sun Feb 10 19:58:03 2002
+++ b/lib/crc32.c	Sun Feb 10 19:58:03 2002
@@ -564,7 +564,7 @@
 	crc32cleanup_be();
 }
 
-module_init(init_crc32);
+fs_initcall(init_crc32);
 module_exit(cleanup_crc32);
 
 EXPORT_SYMBOL(crc32_le);
diff -Nru a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c
--- a/lib/zlib_inflate/inflate_syms.c	Sun Feb 10 19:58:03 2002
+++ b/lib/zlib_inflate/inflate_syms.c	Sun Feb 10 19:58:03 2002
@@ -18,4 +18,5 @@
 EXPORT_SYMBOL(zlib_inflateSync);
 EXPORT_SYMBOL(zlib_inflateReset);
 EXPORT_SYMBOL(zlib_inflateSyncPoint);
+EXPORT_SYMBOL(zlib_inflateIncomp); 
 MODULE_LICENSE("GPL");
diff -Nru a/lib/zlib_inflate/infutil.h b/lib/zlib_inflate/infutil.h
--- a/lib/zlib_inflate/infutil.h	Sun Feb 10 19:58:05 2002
+++ b/lib/zlib_inflate/infutil.h	Sun Feb 10 19:58:05 2002
@@ -11,7 +11,7 @@
 #ifndef _INFUTIL_H
 #define _INFUTIL_H
 
-#include "zconf.h"
+#include <linux/zconf.h>
 #include "inftrees.h"
 #include "infcodes.h"
 
diff -Nru a/linux/zconf.h b/linux/zconf.h
--- a/linux/zconf.h	Sun Feb 10 19:58:05 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,90 +0,0 @@
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#ifndef _ZCONF_H
-#define _ZCONF_H
-
-#if defined(__GNUC__) || defined(__386__) || defined(i386)
-#  ifndef __32BIT__
-#    define __32BIT__
-#  endif
-#endif
-
-#if defined(__STDC__) || defined(__cplusplus)
-#  ifndef STDC
-#    define STDC
-#  endif
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  define MAX_MEM_LEVEL 9
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-#ifndef ZEXPORT
-#  define ZEXPORT
-#endif
-#ifndef ZEXPORTVA
-#  define ZEXPORTVA
-#endif
-#ifndef ZEXTERN
-#  define ZEXTERN extern
-#endif
-#ifndef FAR
-#   define FAR
-#endif
-
-typedef unsigned char  Byte;  /* 8 bits */
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-typedef Byte  FAR Bytef;
-typedef char  FAR charf;
-typedef int   FAR intf;
-typedef uInt  FAR uIntf;
-typedef uLong FAR uLongf;
-
-typedef void FAR *voidpf;
-typedef void     *voidp;
-
-#include <linux/types.h> /* for off_t */
-#include <linux/unistd.h>    /* for SEEK_* and off_t */
-#define z_off_t  off_t
-
-#endif /* _ZCONF_H */
diff -Nru a/linux/zutil.h b/linux/zutil.h
--- a/linux/zutil.h	Sun Feb 10 19:58:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,126 +0,0 @@
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */
-
-#ifndef _Z_UTIL_H
-#define _Z_UTIL_H
-
-#include <linux/zlib.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-        /* common constants */
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
-
-        /* target dependencies */
-
-        /* Common defaults */
-
-#ifndef OS_CODE
-#  define OS_CODE  0x03  /* assume Unix */
-#endif
-
-         /* functions */
-
-typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
-				       uInt len));
-
-
-                        /* checksum functions */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
-#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf)   DO8(buf,0); DO8(buf,8);
-
-/* ========================================================================= */
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-static inline uLong zlib_adler32(uLong adler,
-				 const Bytef *buf,
-				 uInt len)
-{
-    unsigned long s1 = adler & 0xffff;
-    unsigned long s2 = (adler >> 16) & 0xffff;
-    int k;
-
-    if (buf == Z_NULL) return 1L;
-
-    while (len > 0) {
-        k = len < NMAX ? len : NMAX;
-        len -= k;
-        while (k >= 16) {
-            DO16(buf);
-	    buf += 16;
-            k -= 16;
-        }
-        if (k != 0) do {
-            s1 += *buf++;
-	    s2 += s1;
-        } while (--k);
-        s1 %= BASE;
-        s2 %= BASE;
-    }
-    return (s2 << 16) | s1;
-}
-
-#endif /* _Z_UTIL_H */
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
--- a/mm/bootmem.c	Sun Feb 10 19:58:05 2002
+++ b/mm/bootmem.c	Sun Feb 10 19:58:05 2002
@@ -247,19 +247,30 @@
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long i, count, total = 0;
 	unsigned long idx;
+	unsigned long *map; 
 
 	if (!bdata->node_bootmem_map) BUG();
 
 	count = 0;
 	idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
-	for (i = 0; i < idx; i++, page++) {
-		if (!test_bit(i, bdata->node_bootmem_map)) {
+	map = bdata->node_bootmem_map;
+	for (i = 0; i < idx; ) {
+		unsigned long v = ~map[i / BITS_PER_LONG];
+		if (v) { 
+			unsigned long m;
+			for (m = 1; m && i < idx; m<<=1, page++, i++) { 
+				if (v & m) {
 			count++;
 			ClearPageReserved(page);
 			set_page_count(page, 1);
 			__free_page(page);
 		}
 	}
+		} else {
+			i+=BITS_PER_LONG;
+			page+=BITS_PER_LONG; 
+		} 	
+	}	
 	total += count;
 
 	/*
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Sun Feb 10 19:58:05 2002
+++ b/mm/filemap.c	Sun Feb 10 19:58:05 2002
@@ -24,6 +24,7 @@
 #include <linux/mm.h>
 #include <linux/iobuf.h>
 #include <linux/compiler.h>
+#include <linux/fs.h>
 
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	Sun Feb 10 19:58:05 2002
+++ b/mm/mprotect.c	Sun Feb 10 19:58:05 2002
@@ -8,6 +8,7 @@
 #include <linux/smp_lock.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	Sun Feb 10 19:58:03 2002
+++ b/mm/mremap.c	Sun Feb 10 19:58:03 2002
@@ -10,6 +10,7 @@
 #include <linux/shm.h>
 #include <linux/mman.h>
 #include <linux/swap.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	Sun Feb 10 19:58:06 2002
+++ b/mm/shmem.c	Sun Feb 10 19:58:06 2002
@@ -1267,7 +1267,7 @@
 }
 #endif
 
-static struct super_block *shmem_read_super(struct super_block * sb, void * data, int silent)
+static int shmem_fill_super(struct super_block * sb, void * data, int silent)
 {
 	struct inode * inode;
 	struct dentry * root;
@@ -1286,7 +1286,7 @@
 #ifdef CONFIG_TMPFS
 	if (shmem_parse_options (data, &mode, &blocks, &inodes)) {
 		printk(KERN_ERR "tmpfs invalid option\n");
-		return NULL;
+		return -EINVAL;
 	}
 #endif
 
@@ -1302,15 +1302,15 @@
 	sb->s_op = &shmem_ops;
 	inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
 	if (!inode)
-		return NULL;
+		return -ENOMEM;
 
 	root = d_alloc_root(inode);
 	if (!root) {
 		iput(inode);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root = root;
-	return sb;
+	return 0;
 }
 
 static kmem_cache_t * shmem_inode_cachep;
@@ -1410,12 +1410,33 @@
 	nopage:	shmem_nopage,
 };
 
+static struct super_block *shmem_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, shmem_fill_super);
+}
+
 #ifdef CONFIG_TMPFS
 /* type "shm" will be tagged obsolete in 2.5 */
-static DECLARE_FSTYPE(shmem_fs_type, "shm", shmem_read_super, FS_LITTER);
-static DECLARE_FSTYPE(tmpfs_fs_type, "tmpfs", shmem_read_super, FS_LITTER);
+static struct file_system_type shmem_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"shmem",
+	get_sb:		shmem_get_sb,
+	fs_flags:	FS_LITTER,
+};
+static struct file_system_type tmpfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"tmpfs",
+	get_sb:		shmem_get_sb,
+	fs_flags:	FS_LITTER,
+};
 #else
-static DECLARE_FSTYPE(tmpfs_fs_type, "tmpfs", shmem_read_super, FS_LITTER|FS_NOMOUNT);
+static struct file_system_type tmpfs_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"tmpfs",
+	get_sb:		shmem_get_sb,
+	fs_flags:	FS_LITTER|FS_NOMOUNT,
+};
 #endif
 static struct vfsmount *shm_mnt;
 
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Sun Feb 10 19:58:05 2002
+++ b/mm/slab.c	Sun Feb 10 19:58:05 2002
@@ -49,7 +49,8 @@
  *  constructors and destructors are called without any locking.
  *  Several members in kmem_cache_t and slab_t never change, they
  *	are accessed without any locking.
- *  The per-cpu arrays are never accessed from the wrong cpu, no locking.
+ *  The per-cpu arrays are never accessed from the wrong cpu, no locking,
+ *  	and local interrupts are disabled so slab code is preempt-safe.
  *  The non-constant members are protected with a per-cache irq spinlock.
  *
  * Further notes from the original documentation:
@@ -75,6 +76,7 @@
 #include	<linux/interrupt.h>
 #include	<linux/init.h>
 #include	<linux/compiler.h>
+#include	<linux/seq_file.h>
 #include	<asm/uaccess.h>
 
 /*
@@ -186,8 +188,6 @@
  * manages a cache.
  */
 
-#define CACHE_NAMELEN	20	/* max name length for a slab cache */
-
 struct kmem_cache_s {
 /* 1) each alloc & free */
 	/* full, partial first, then free */
@@ -225,7 +225,7 @@
 	unsigned long		failures;
 
 /* 3) cache creation/removal */
-	char			name[CACHE_NAMELEN];
+	const char		*name;
 	struct list_head	next;
 #ifdef CONFIG_SMP
 /* 4) per-cpu data */
@@ -335,6 +335,7 @@
 	kmem_cache_t	*cs_dmacachep;
 } cache_sizes_t;
 
+/* These are the default caches for kmalloc. Custom caches can have other sizes. */
 static cache_sizes_t cache_sizes[] = {
 #if PAGE_SIZE == 4096
 	{    32,	NULL, NULL},
@@ -353,6 +354,29 @@
 	{131072,	NULL, NULL},
 	{     0,	NULL, NULL}
 };
+/* Must match cache_sizes above. Out of line to keep cache footprint low. */
+#define CN(x) { x, x " (DMA)" }
+static struct { 
+	char *name; 
+	char *name_dma;
+} cache_names[] = { 
+#if PAGE_SIZE == 4096
+	CN("size-32"),
+#endif
+	CN("size-64"),
+	CN("size-128"),
+	CN("size-256"),
+	CN("size-512"),
+	CN("size-1024"),
+	CN("size-2048"),
+	CN("size-4096"),
+	CN("size-8192"),
+	CN("size-16384"),
+	CN("size-32768"),
+	CN("size-65536"),
+	CN("size-131072")
+}; 
+#undef CN
 
 /* internal cache of cache description objs */
 static kmem_cache_t cache_cache = {
@@ -437,7 +461,6 @@
 void __init kmem_cache_sizes_init(void)
 {
 	cache_sizes_t *sizes = cache_sizes;
-	char name[20];
 	/*
 	 * Fragmentation resistance on low memory - only use bigger
 	 * page orders on machines with more than 32MB of memory.
@@ -450,9 +473,9 @@
 		 * eliminates "false sharing".
 		 * Note for systems short on memory removing the alignment will
 		 * allow tighter packing of the smaller caches. */
-		sprintf(name,"size-%Zd",sizes->cs_size);
 		if (!(sizes->cs_cachep =
-			kmem_cache_create(name, sizes->cs_size,
+			kmem_cache_create(cache_names[sizes-cache_sizes].name, 
+					  sizes->cs_size,
 					0, SLAB_HWCACHE_ALIGN, NULL, NULL))) {
 			BUG();
 		}
@@ -462,9 +485,10 @@
 			offslab_limit = sizes->cs_size-sizeof(slab_t);
 			offslab_limit /= 2;
 		}
-		sprintf(name, "size-%Zd(DMA)",sizes->cs_size);
-		sizes->cs_dmacachep = kmem_cache_create(name, sizes->cs_size, 0,
-			      SLAB_CACHE_DMA|SLAB_HWCACHE_ALIGN, NULL, NULL);
+		sizes->cs_dmacachep = kmem_cache_create(
+		    cache_names[sizes-cache_sizes].name_dma, 
+			sizes->cs_size, 0,
+			SLAB_CACHE_DMA|SLAB_HWCACHE_ALIGN, NULL, NULL);
 		if (!sizes->cs_dmacachep)
 			BUG();
 		sizes++;
@@ -604,6 +628,11 @@
  * Cannot be called within a int, but can be interrupted.
  * The @ctor is run when new pages are allocated by the cache
  * and the @dtor is run before the pages are handed back.
+ *
+ * @name must be valid until the cache is destroyed. This implies that
+ * the module calling this has to destroy the cache before getting 
+ * unloaded.
+ * 
  * The flags are
  *
  * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5)
@@ -632,7 +661,6 @@
 	 * Sanity checks... these are all serious usage bugs.
 	 */
 	if ((!name) ||
-		((strlen(name) >= CACHE_NAMELEN - 1)) ||
 		in_interrupt() ||
 		(size < BYTES_PER_WORD) ||
 		(size > (1<<MAX_OBJ_ORDER)*PAGE_SIZE) ||
@@ -797,8 +825,7 @@
 		cachep->slabp_cache = kmem_find_general_cachep(slab_size,0);
 	cachep->ctor = ctor;
 	cachep->dtor = dtor;
-	/* Copy name over so we don't have problems with unloaded modules */
-	strcpy(cachep->name, name);
+	cachep->name = name;
 
 #ifdef CONFIG_SMP
 	if (g_cpucache_up)
@@ -811,10 +838,20 @@
 
 		list_for_each(p, &cache_chain) {
 			kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
-
-			/* The name field is constant - no lock needed. */
-			if (!strcmp(pc->name, name))
-				BUG();
+			char tmp;
+			/* This happens when the module gets unloaded and doesn't
+			   destroy its slab cache and noone else reuses the vmalloc
+			   area of the module. Print a warning. */
+			if (__get_user(tmp,pc->name)) { 
+				printk("SLAB: cache with size %d has lost its name\n", 
+					pc->objsize); 
+				continue; 
+			} 	
+			if (!strcmp(pc->name,name)) { 
+				printk("kmem_cache_create: duplicate cache %s\n",name); 
+				up(&cache_chain_sem); 
+				BUG(); 
+			}	
 		}
 	}
 
@@ -1834,31 +1871,56 @@
 }
 
 #ifdef CONFIG_PROC_FS
-/* /proc/slabinfo
- *	cache-name num-active-objs total-objs
- *	obj-size num-active-slabs total-slabs
- *	num-pages-per-slab
- */
-#define FIXUP(t)				\
-	do {					\
-		if (len <= off) {		\
-			off -= len;		\
-			len = 0;		\
-		} else {			\
-			if (len-off > count)	\
-				goto t;		\
-		}				\
-	} while (0)
 
-static int proc_getdata (char*page, char**start, off_t off, int count)
+static void *s_start(struct seq_file *m, loff_t *pos)
 {
+	loff_t n = *pos;
 	struct list_head *p;
-	int len = 0;
 
-	/* Output format version, so at least we can change it without _too_
-	 * many complaints.
-	 */
-	len += sprintf(page+len, "slabinfo - version: 1.1"
+	down(&cache_chain_sem);
+	if (!n)
+		return (void *)1;
+	p = &cache_cache.next;
+	while (--n) {
+		p = p->next;
+		if (p == &cache_cache.next)
+			return NULL;
+	}
+	return list_entry(p, kmem_cache_t, next);
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	kmem_cache_t *cachep = p;
+	++*pos;
+	if (p == (void *)1)
+		return &cache_cache;
+	cachep = list_entry(cachep->next.next, kmem_cache_t, next);
+	return cachep == &cache_cache ? NULL : cachep;
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+	up(&cache_chain_sem);
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+	kmem_cache_t *cachep = p;
+	struct list_head *q;
+	slab_t		*slabp;
+	unsigned long	active_objs;
+	unsigned long	num_objs;
+	unsigned long	active_slabs = 0;
+	unsigned long	num_slabs;
+	const char *name; 
+
+	if (p == (void*)1) {
+		/*
+		 * Output format version, so at least we can change it
+		 * without _too_ many complaints.
+		 */
+		seq_puts(m, "slabinfo - version: 1.1"
 #if STATS
 				" (statistics)"
 #endif
@@ -1866,108 +1928,89 @@
 				" (SMP)"
 #endif
 				"\n");
-	FIXUP(got_data);
-
-	down(&cache_chain_sem);
-	p = &cache_cache.next;
-	do {
-		kmem_cache_t	*cachep;
-		struct list_head *q;
-		slab_t		*slabp;
-		unsigned long	active_objs;
-		unsigned long	num_objs;
-		unsigned long	active_slabs = 0;
-		unsigned long	num_slabs;
-		cachep = list_entry(p, kmem_cache_t, next);
+		return 0;
+	}
 
-		spin_lock_irq(&cachep->spinlock);
-		active_objs = 0;
-		num_slabs = 0;
-		list_for_each(q,&cachep->slabs_full) {
-			slabp = list_entry(q, slab_t, list);
-			if (slabp->inuse != cachep->num)
-				BUG();
-			active_objs += cachep->num;
-			active_slabs++;
-		}
-		list_for_each(q,&cachep->slabs_partial) {
-			slabp = list_entry(q, slab_t, list);
-			if (slabp->inuse == cachep->num || !slabp->inuse)
-				BUG();
-			active_objs += slabp->inuse;
-			active_slabs++;
-		}
-		list_for_each(q,&cachep->slabs_free) {
-			slabp = list_entry(q, slab_t, list);
-			if (slabp->inuse)
-				BUG();
-			num_slabs++;
-		}
-		num_slabs+=active_slabs;
-		num_objs = num_slabs*cachep->num;
+	spin_lock_irq(&cachep->spinlock);
+	active_objs = 0;
+	num_slabs = 0;
+	list_for_each(q,&cachep->slabs_full) {
+		slabp = list_entry(q, slab_t, list);
+		if (slabp->inuse != cachep->num)
+			BUG();
+		active_objs += cachep->num;
+		active_slabs++;
+	}
+	list_for_each(q,&cachep->slabs_partial) {
+		slabp = list_entry(q, slab_t, list);
+		if (slabp->inuse == cachep->num || !slabp->inuse)
+			BUG();
+		active_objs += slabp->inuse;
+		active_slabs++;
+	}
+	list_for_each(q,&cachep->slabs_free) {
+		slabp = list_entry(q, slab_t, list);
+		if (slabp->inuse)
+			BUG();
+		num_slabs++;
+	}
+	num_slabs+=active_slabs;
+	num_objs = num_slabs*cachep->num;
 
-		len += sprintf(page+len, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
-			cachep->name, active_objs, num_objs, cachep->objsize,
-			active_slabs, num_slabs, (1<<cachep->gfporder));
+	name = cachep->name; 
+	{
+	char tmp; 
+	if (__get_user(tmp, name)) 
+		name = "broken"; 
+	} 	
+
+	seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
+		name, active_objs, num_objs, cachep->objsize,
+		active_slabs, num_slabs, (1<<cachep->gfporder));
 
 #if STATS
-		{
-			unsigned long errors = cachep->errors;
-			unsigned long high = cachep->high_mark;
-			unsigned long grown = cachep->grown;
-			unsigned long reaped = cachep->reaped;
-			unsigned long allocs = cachep->num_allocations;
+	{
+		unsigned long errors = cachep->errors;
+		unsigned long high = cachep->high_mark;
+		unsigned long grown = cachep->grown;
+		unsigned long reaped = cachep->reaped;
+		unsigned long allocs = cachep->num_allocations;
 
-			len += sprintf(page+len, " : %6lu %7lu %5lu %4lu %4lu",
-					high, allocs, grown, reaped, errors);
-		}
+		seq_printf(m, " : %6lu %7lu %5lu %4lu %4lu",
+				high, allocs, grown, reaped, errors);
+	}
 #endif
 #ifdef CONFIG_SMP
-		{
-			unsigned int batchcount = cachep->batchcount;
-			unsigned int limit;
+	{
+		unsigned int batchcount = cachep->batchcount;
+		unsigned int limit;
 
-			if (cc_data(cachep))
-				limit = cc_data(cachep)->limit;
-			 else
-				limit = 0;
-			len += sprintf(page+len, " : %4u %4u",
-					limit, batchcount);
-		}
+		if (cc_data(cachep))
+			limit = cc_data(cachep)->limit;
+		 else
+			limit = 0;
+		seq_printf(m, " : %4u %4u", limit, batchcount);
+	}
 #endif
 #if STATS && defined(CONFIG_SMP)
-		{
-			unsigned long allochit = atomic_read(&cachep->allochit);
-			unsigned long allocmiss = atomic_read(&cachep->allocmiss);
-			unsigned long freehit = atomic_read(&cachep->freehit);
-			unsigned long freemiss = atomic_read(&cachep->freemiss);
-			len += sprintf(page+len, " : %6lu %6lu %6lu %6lu",
-					allochit, allocmiss, freehit, freemiss);
-		}
+	{
+		unsigned long allochit = atomic_read(&cachep->allochit);
+		unsigned long allocmiss = atomic_read(&cachep->allocmiss);
+		unsigned long freehit = atomic_read(&cachep->freehit);
+		unsigned long freemiss = atomic_read(&cachep->freemiss);
+		seq_printf(m, " : %6lu %6lu %6lu %6lu",
+				allochit, allocmiss, freehit, freemiss);
+	}
 #endif
-		len += sprintf(page+len,"\n");
-		spin_unlock_irq(&cachep->spinlock);
-		FIXUP(got_data_up);
-		p = cachep->next.next;
-	} while (p != &cache_cache.next);
-got_data_up:
-	up(&cache_chain_sem);
-
-got_data:
-	*start = page+off;
-	return len;
+	spin_unlock_irq(&cachep->spinlock);
+	seq_putc(m, '\n');
+	return 0;
 }
 
 /**
- * slabinfo_read_proc - generates /proc/slabinfo
- * @page: scratch area, one page long
- * @start: pointer to the pointer to the output buffer
- * @off: offset within /proc/slabinfo the caller is interested in
- * @count: requested len in bytes
- * @eof: eof marker
- * @data: unused
+ * slabinfo_op - iterator that generates /proc/slabinfo
  *
- * The contents of the buffer are
+ * Output layout:
  * cache-name
  * num-active-objs
  * total-objs
@@ -1977,28 +2020,24 @@
  * num-pages-per-slab
  * + further values on SMP and with statistics enabled
  */
-int slabinfo_read_proc (char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
-{
-	int len = proc_getdata(page, start, off, count);
-	len -= (*start-page);
-	if (len <= count)
-		*eof = 1;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-	return len;
-}
+
+struct seq_operations slabinfo_op = {
+	start:	s_start,
+	next:	s_next,
+	stop:	s_stop,
+	show:	s_show
+};
 
 #define MAX_SLABINFO_WRITE 128
 /**
- * slabinfo_write_proc - SMP tuning for the slab allocator
+ * slabinfo_write - SMP tuning for the slab allocator
  * @file: unused
  * @buffer: user buffer
  * @count: data len
  * @data: unused
  */
-int slabinfo_write_proc (struct file *file, const char *buffer,
-				unsigned long count, void *data)
+ssize_t slabinfo_write(struct file *file, const char *buffer,
+				size_t count, loff_t *ppos)
 {
 #ifdef CONFIG_SMP
 	char kbuf[MAX_SLABINFO_WRITE+1], *tmp;
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	Sun Feb 10 19:58:05 2002
+++ b/mm/swapfile.c	Sun Feb 10 19:58:05 2002
@@ -114,7 +114,7 @@
 
 	while (1) {
 		p = &swap_info[type];
-		if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
+		if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) {
 			swap_device_lock(p);
 			offset = scan_swap_map(p);
 			swap_device_unlock(p);
@@ -729,7 +729,7 @@
 	swap_list_lock();
 	for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
 		p = swap_info + type;
-		if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
+		if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) {
 			if (p->swap_file->f_dentry == nd.dentry)
 				break;
 		}
@@ -752,7 +752,7 @@
 	}
 	nr_swap_pages -= p->pages;
 	total_swap_pages -= p->pages;
-	p->flags = SWP_USED;
+	p->flags &= ~SWP_WRITEOK;
 	swap_list_unlock();
 	unlock_kernel();
 	err = try_to_unuse(type);
@@ -770,7 +770,7 @@
 			swap_info[prev].next = p - swap_info;
 		nr_swap_pages += p->pages;
 		total_swap_pages += p->pages;
-		p->flags = SWP_WRITEOK;
+		p->flags |= SWP_WRITEOK;
 		swap_list_unlock();
 		goto out_dput;
 	}
@@ -778,7 +778,6 @@
 	swap_device_lock(p);
 	swap_file = p->swap_file;
 	p->swap_file = NULL;
-	p->swap_device = NODEV;
 	p->max = 0;
 	swap_map = p->swap_map;
 	p->swap_map = NULL;
@@ -822,7 +821,8 @@
 				}
 			len += sprintf(buf + len, "%-39s %s\t%d\t%d\t%d\n",
 				       path,
-				       !kdev_none(ptr->swap_device) ? "partition" : "file\t",
+				       (ptr->flags & SWP_BLOCKDEV) ?
+				       		"partition" : "file\t",
 				       ptr->pages << (PAGE_SHIFT - 10),
 				       usedswap << (PAGE_SHIFT - 10),
 				       ptr->prio);
@@ -837,9 +837,10 @@
 	int i;
 
 	for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
-		if (ptr->flags & SWP_USED)
-			if (kdev_same(ptr->swap_device, dev))
-				return 1;
+		if ((ptr->flags & SWP_USED) &&
+		    (ptr->flags & SWP_BLOCKDEV) &&
+		    (kdev_same(ptr->swap_file->f_dentry->d_inode->i_rdev, dev)))
+			return 1;
 	}
 	return 0;
 }
@@ -883,7 +884,6 @@
 		nr_swapfiles = type+1;
 	p->flags = SWP_USED;
 	p->swap_file = NULL;
-	p->swap_device = NODEV;
 	p->swap_map = NULL;
 	p->lowest_bit = 0;
 	p->highest_bit = 0;
@@ -911,8 +911,10 @@
 
 	error = -EINVAL;
 	if (S_ISBLK(swap_file->f_dentry->d_inode->i_mode)) {
-		p->swap_device = swap_file->f_dentry->d_inode->i_rdev;
-		set_blocksize(p->swap_device, PAGE_SIZE);
+		error = set_blocksize(swap_file->f_dentry->d_inode->i_rdev,
+				      PAGE_SIZE);
+		if (error < 0)
+			goto bad_swap;
 	} else if (!S_ISREG(swap_file->f_dentry->d_inode->i_mode))
 		goto bad_swap;
 
@@ -1035,7 +1037,9 @@
 	swap_list_lock();
 	swap_device_lock(p);
 	p->max = maxpages;
-	p->flags = SWP_WRITEOK;
+	p->flags = SWP_ACTIVE;
+	if (S_ISBLK(swap_file->f_dentry->d_inode->i_mode))
+		p->flags |= SWP_BLOCKDEV;
 	p->pages = nr_good_pages;
 	nr_swap_pages += nr_good_pages;
 	total_swap_pages += nr_good_pages;
@@ -1064,7 +1068,6 @@
 bad_swap_2:
 	swap_list_lock();
 	swap_map = p->swap_map;
-	p->swap_device = NODEV;
 	p->swap_file = NULL;
 	p->swap_map = NULL;
 	p->flags = 0;
@@ -1090,7 +1093,7 @@
 	swap_list_lock();
 	for (i = 0; i < nr_swapfiles; i++) {
 		unsigned int j;
-		if (swap_info[i].flags != SWP_USED)
+		if (!(swap_info[i].flags & SWP_USED))
 			continue;
 		for (j = 0; j < swap_info[i].max; ++j) {
 			switch (swap_info[i].swap_map[j]) {
diff -Nru a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
--- a/net/8021q/vlanproc.c	Sun Feb 10 19:58:05 2002
+++ b/net/8021q/vlanproc.c	Sun Feb 10 19:58:05 2002
@@ -236,7 +236,7 @@
 	if (count <= 0)
 		return 0;
 
-	dent = inode->u.generic_ip;
+	dent = PDE(inode);
 	if ((dent == NULL) || (dent->get_info == NULL))
 		return 0;
 
diff -Nru a/net/atm/proc.c b/net/atm/proc.c
--- a/net/atm/proc.c	Sun Feb 10 19:58:05 2002
+++ b/net/atm/proc.c	Sun Feb 10 19:58:05 2002
@@ -498,8 +498,7 @@
 	if (count == 0) return 0;
 	page = get_free_page(GFP_KERNEL);
 	if (!page) return -ENOMEM;
-	dev = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
-	    ->data;
+	dev = PDE(file->f_dentry->d_inode)->data;
 	if (!dev->ops->proc_read)
 		length = -EINVAL;
 	else {
@@ -521,8 +520,7 @@
 	unsigned long page;
 	int length;
 	int (*info)(loff_t,char *);
-	info = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
-	    ->data;
+	info = PDE(file->f_dentry->d_inode)->data;
 
 	if (count == 0) return 0;
 	page = get_free_page(GFP_KERNEL);
diff -Nru a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
--- a/net/ax25/af_ax25.c	Sun Feb 10 19:58:05 2002
+++ b/net/ax25/af_ax25.c	Sun Feb 10 19:58:05 2002
@@ -1756,7 +1756,7 @@
 			len += sprintf(buffer + len, " %d %d %ld\n",
 				atomic_read(&ax25->sk->wmem_alloc),
 				atomic_read(&ax25->sk->rmem_alloc),
-				ax25->sk->socket != NULL ? ax25->sk->socket->inode->i_ino : 0L);
+				ax25->sk->socket != NULL ? SOCK_INODE(ax25->sk->socket)->i_ino : 0L);
 		} else {
 			len += sprintf(buffer + len, " * * *\n");
 		}
diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c	Sun Feb 10 19:58:05 2002
+++ b/net/ipv6/icmp.c	Sun Feb 10 19:58:05 2002
@@ -637,21 +637,11 @@
 	struct sock *sk;
 	int err;
 
-	icmpv6_socket = sock_alloc();
-	if (icmpv6_socket == NULL) {
-		printk(KERN_ERR
-		       "Failed to create the ICMP6 control socket.\n");
-		return -1;
-	}
-	icmpv6_socket->inode->i_uid = 0;
-	icmpv6_socket->inode->i_gid = 0;
-	icmpv6_socket->type = SOCK_RAW;
-
-	if ((err = ops->create(icmpv6_socket, IPPROTO_ICMPV6)) < 0) {
+	err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &icmpv6_socket);
+	if (err < 0) {
 		printk(KERN_ERR
 		       "Failed to initialize the ICMP6 control socket (err %d).\n",
 		       err);
-		sock_release(icmpv6_socket);
 		icmpv6_socket = NULL; /* for safety */
 		return err;
 	}
diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c
--- a/net/ipv6/mcast.c	Sun Feb 10 19:58:05 2002
+++ b/net/ipv6/mcast.c	Sun Feb 10 19:58:05 2002
@@ -751,21 +751,11 @@
 	struct sock *sk;
 	int err;
 
-	igmp6_socket = sock_alloc();
-	if (igmp6_socket == NULL) {
+	err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
+	if (err < 0) {
 		printk(KERN_ERR
-		       "Failed to create the IGMP6 control socket.\n");
-		return -1;
-	}
-	igmp6_socket->inode->i_uid = 0;
-	igmp6_socket->inode->i_gid = 0;
-	igmp6_socket->type = SOCK_RAW;
-
-	if((err = ops->create(igmp6_socket, IPPROTO_ICMPV6)) < 0) {
-		printk(KERN_DEBUG 
 		       "Failed to initialize the IGMP6 control socket (err %d).\n",
 		       err);
-		sock_release(igmp6_socket);
 		igmp6_socket = NULL; /* For safety. */
 		return err;
 	}
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	Sun Feb 10 19:58:04 2002
+++ b/net/ipv6/ndisc.c	Sun Feb 10 19:58:04 2002
@@ -1214,21 +1214,11 @@
 	struct sock *sk;
         int err;
 
-	ndisc_socket = sock_alloc();
-	if (ndisc_socket == NULL) {
+	err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
+	if (err < 0) {
 		printk(KERN_ERR
-		       "Failed to create the NDISC control socket.\n");
-		return -1;
-	}
-	ndisc_socket->inode->i_uid = 0;
-	ndisc_socket->inode->i_gid = 0;
-	ndisc_socket->type = SOCK_RAW;
-
-	if((err = ops->create(ndisc_socket, IPPROTO_ICMPV6)) < 0) {
-		printk(KERN_DEBUG 
 		       "Failed to initialize the NDISC control socket (err %d).\n",
 		       err);
-		sock_release(ndisc_socket);
 		ndisc_socket = NULL; /* For safety. */
 		return err;
 	}
diff -Nru a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c
--- a/net/netlink/netlink_dev.c	Sun Feb 10 19:58:05 2002
+++ b/net/netlink/netlink_dev.c	Sun Feb 10 19:58:05 2002
@@ -98,11 +98,6 @@
 	return sock_recvmsg(sock, &msg, count, msg.msg_flags);
 }
 
-static loff_t netlink_lseek(struct file * file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-
 static int netlink_open(struct inode * inode, struct file * file)
 {
 	unsigned int minor = minor(inode->i_rdev);
@@ -166,7 +161,7 @@
 
 static struct file_operations netlink_fops = {
 	owner:		THIS_MODULE,
-	llseek:		netlink_lseek,
+	llseek:		no_llseek,
 	read:		netlink_read,
 	write:		netlink_write,
 	poll:		netlink_poll,
diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
--- a/net/netrom/af_netrom.c	Sun Feb 10 19:58:06 2002
+++ b/net/netrom/af_netrom.c	Sun Feb 10 19:58:06 2002
@@ -1204,7 +1204,7 @@
 			s->protinfo.nr->window,
 			atomic_read(&s->wmem_alloc),
 			atomic_read(&s->rmem_alloc),
-			s->socket != NULL ? s->socket->inode->i_ino : 0L);
+			s->socket != NULL ? SOCK_INODE(s->socket)->i_ino : 0L);
 
 		pos = begin + len;
 
diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c
--- a/net/packet/af_packet.c	Sun Feb 10 19:58:04 2002
+++ b/net/packet/af_packet.c	Sun Feb 10 19:58:04 2002
@@ -1575,7 +1575,7 @@
 {
 	struct file *file = vma->vm_file;
 	struct inode *inode = file->f_dentry->d_inode;
-	struct socket * sock = &inode->u.socket_i;
+	struct socket * sock = SOCKET_I(inode);
 	struct sock *sk = sock->sk;
 	
 	if (sk)
@@ -1586,7 +1586,7 @@
 {
 	struct file *file = vma->vm_file;
 	struct inode *inode = file->f_dentry->d_inode;
-	struct socket * sock = &inode->u.socket_i;
+	struct socket * sock = SOCKET_I(inode);
 	struct sock *sk = sock->sk;
 	
 	if (sk)
diff -Nru a/net/rose/af_rose.c b/net/rose/af_rose.c
--- a/net/rose/af_rose.c	Sun Feb 10 19:58:06 2002
+++ b/net/rose/af_rose.c	Sun Feb 10 19:58:06 2002
@@ -1370,7 +1370,7 @@
 			s->protinfo.rose->idle / (60 * HZ),
 			atomic_read(&s->wmem_alloc),
 			atomic_read(&s->rmem_alloc),
-			s->socket != NULL ? s->socket->inode->i_ino : 0L);
+			s->socket != NULL ? SOCK_INODE(s->socket)->i_ino : 0L);
 
 		pos = begin + len;
 
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	Sun Feb 10 19:58:05 2002
+++ b/net/socket.c	Sun Feb 10 19:58:05 2002
@@ -86,7 +86,6 @@
 #include <linux/netfilter.h>
 
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
-static loff_t sock_lseek(struct file *file, loff_t offset, int whence);
 static ssize_t sock_read(struct file *file, char *buf,
 			 size_t size, loff_t *ppos);
 static ssize_t sock_write(struct file *file, const char *buf,
@@ -113,7 +112,7 @@
  */
 
 static struct file_operations socket_file_ops = {
-	llseek:		sock_lseek,
+	llseek:		no_llseek,
 	read:		sock_read,
 	write:		sock_write,
 	poll:		sock_poll,
@@ -133,7 +132,7 @@
 
 static struct net_proto_family *net_families[NPROTO];
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 static atomic_t net_family_lockct = ATOMIC_INIT(0);
 static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
 
@@ -272,36 +271,87 @@
 	return 0;
 }
 
+static kmem_cache_t * sock_inode_cachep;
+
+static struct inode *sock_alloc_inode(struct super_block *sb)
+{
+	struct socket_alloc *ei;
+	ei = (struct socket_alloc *)kmem_cache_alloc(sock_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	init_waitqueue_head(&ei->socket.wait);
+	return &ei->vfs_inode;
+}
+
+static void sock_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(sock_inode_cachep,
+			list_entry(inode, struct socket_alloc, vfs_inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct socket_alloc *ei = (struct socket_alloc *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
+					     sizeof(struct socket_alloc),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (sock_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
 static struct super_operations sockfs_ops = {
+	alloc_inode:	sock_alloc_inode,
+	destroy_inode:	sock_destroy_inode,
 	statfs:		sockfs_statfs,
 };
 
-static struct super_block * sockfs_read_super(struct super_block *sb, void *data, int silent)
+static int sockfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *root;
 	sb->s_blocksize = 1024;
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = SOCKFS_MAGIC;
-	sb->s_op	= &sockfs_ops;
+	sb->s_op = &sockfs_ops;
 	root = new_inode(sb);
 	if (!root)
-		return NULL;
+		return -ENOMEM;
 	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
 	root->i_uid = root->i_gid = 0;
 	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
 	sb->s_root = d_alloc(NULL, &(const struct qstr) { "socket:", 7, 0 });
 	if (!sb->s_root) {
 		iput(root);
-		return NULL;
+		return -ENOMEM;
 	}
 	sb->s_root->d_sb = sb;
 	sb->s_root->d_parent = sb->s_root;
 	d_instantiate(sb->s_root, root);
-	return sb;
+	return 0;
+}
+
+static struct super_block *sockfs_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, sockfs_fill_super);
 }
 
 static struct vfsmount *sock_mnt;
-static DECLARE_FSTYPE(sock_fs_type, "sockfs", sockfs_read_super, FS_NOMOUNT);
+
+static struct file_system_type sock_fs_type = {
+	name:		"sockfs",
+	get_sb:		sockfs_get_sb,
+	fs_flags:	FS_NOMOUNT,
+};
 static int sockfs_delete_dentry(struct dentry *dentry)
 {
 	return 1;
@@ -347,10 +397,10 @@
 			goto out;
 		}
 
-		sprintf(name, "[%lu]", sock->inode->i_ino);
+		sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
 		this.name = name;
 		this.len = strlen(name);
-		this.hash = sock->inode->i_ino;
+		this.hash = SOCK_INODE(sock)->i_ino;
 
 		file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
 		if (!file->f_dentry) {
@@ -360,11 +410,11 @@
 			goto out;
 		}
 		file->f_dentry->d_op = &sockfs_dentry_operations;
-		d_add(file->f_dentry, sock->inode);
+		d_add(file->f_dentry, SOCK_INODE(sock));
 		file->f_vfsmnt = mntget(sock_mnt);
 
 		sock->file = file;
-		file->f_op = sock->inode->i_fop = &socket_file_ops;
+		file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
 		file->f_mode = 3;
 		file->f_flags = O_RDWR;
 		file->f_pos = 0;
@@ -375,11 +425,6 @@
 	return fd;
 }
 
-extern __inline__ struct socket *socki_lookup(struct inode *inode)
-{
-	return &inode->u.socket_i;
-}
-
 /**
  *	sockfd_lookup	- 	Go from a file number to its socket slot
  *	@fd: file handle
@@ -406,7 +451,7 @@
 	}
 
 	inode = file->f_dentry->d_inode;
-	if (!inode->i_sock || !(sock = socki_lookup(inode)))
+	if (!inode->i_sock || !(sock = SOCKET_I(inode)))
 	{
 		*err = -ENOTSOCK;
 		fput(file);
@@ -443,15 +488,13 @@
 		return NULL;
 
 	inode->i_dev = NODEV;
-	sock = socki_lookup(inode);
+	sock = SOCKET_I(inode);
 
 	inode->i_mode = S_IFSOCK|S_IRWXUGO;
 	inode->i_sock = 1;
 	inode->i_uid = current->fsuid;
 	inode->i_gid = current->fsgid;
 
-	sock->inode = inode;
-	init_waitqueue_head(&sock->wait);
 	sock->fasync_list = NULL;
 	sock->state = SS_UNCONNECTED;
 	sock->flags = 0;
@@ -493,7 +536,7 @@
 
 	sockets_in_use[smp_processor_id()].counter--;
 	if (!sock->file) {
-		iput(sock->inode);
+		iput(SOCK_INODE(sock));
 		return;
 	}
 	sock->file=NULL;
@@ -527,15 +570,6 @@
 
 
 /*
- *	Sockets are not seekable.
- */
-
-static loff_t sock_lseek(struct file *file, loff_t offset, int whence)
-{
-	return -ESPIPE;
-}
-
-/*
  *	Read data from a socket. ubuf is a user mode pointer. We make sure the user
  *	area ubuf...ubuf+size-1 is writable before asking the protocol.
  */
@@ -553,7 +587,7 @@
 	if (size==0)		/* Match SYS5 behaviour */
 		return 0;
 
-	sock = socki_lookup(file->f_dentry->d_inode); 
+	sock = SOCKET_I(file->f_dentry->d_inode); 
 
 	msg.msg_name=NULL;
 	msg.msg_namelen=0;
@@ -586,7 +620,7 @@
 	if(size==0)		/* Match SYS5 behaviour */
 		return 0;
 
-	sock = socki_lookup(file->f_dentry->d_inode); 
+	sock = SOCKET_I(file->f_dentry->d_inode); 
 
 	msg.msg_name=NULL;
 	msg.msg_namelen=0;
@@ -612,7 +646,7 @@
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
-	sock = socki_lookup(file->f_dentry->d_inode);
+	sock = SOCKET_I(file->f_dentry->d_inode);
 
 	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
 	if (more)
@@ -627,7 +661,7 @@
 	struct msghdr msg;
 	struct socket *sock;
 
-	sock = socki_lookup(inode);
+	sock = SOCKET_I(inode);
 
 	msg.msg_name = NULL;
 	msg.msg_namelen = 0;
@@ -681,7 +715,7 @@
 	int err;
 
 	unlock_kernel();
-	sock = socki_lookup(inode);
+	sock = SOCKET_I(inode);
 	err = sock->ops->ioctl(sock, cmd, arg);
 	lock_kernel();
 
@@ -697,13 +731,13 @@
 	/*
 	 *	We can't return errors to poll, so it's either yes or no. 
 	 */
-	sock = socki_lookup(file->f_dentry->d_inode);
+	sock = SOCKET_I(file->f_dentry->d_inode);
 	return sock->ops->poll(file, sock, wait);
 }
 
 static int sock_mmap(struct file * file, struct vm_area_struct * vma)
 {
-	struct socket *sock = socki_lookup(file->f_dentry->d_inode);
+	struct socket *sock = SOCKET_I(file->f_dentry->d_inode);
 
 	return sock->ops->mmap(file, sock, vma);
 }
@@ -721,7 +755,7 @@
 		return 0;
 	}
 	sock_fasync(-1, filp, 0);
-	sock_release(socki_lookup(inode));
+	sock_release(SOCKET_I(inode));
 	return 0;
 }
 
@@ -754,7 +788,7 @@
 	}
 
 
-	sock = socki_lookup(filp->f_dentry->d_inode);
+	sock = SOCKET_I(filp->f_dentry->d_inode);
 	
 	if ((sk=sock->sk) == NULL)
 		return -EINVAL;
@@ -1521,7 +1555,7 @@
 {
 	struct socket *sock;
 
-	sock = socki_lookup (filp->f_dentry->d_inode);
+	sock = SOCKET_I (filp->f_dentry->d_inode);
 	if (sock && sock->ops)
 		return sock_no_fcntl(sock, cmd, arg);
 	return(-EINVAL);
@@ -1711,6 +1745,7 @@
 	 *	Initialize the protocols module. 
 	 */
 
+	init_inodecache();
 	register_filesystem(&sock_fs_type);
 	sock_mnt = kern_mount(&sock_fs_type);
 	/* The real protocol initialization is performed when
diff -Nru a/net/sunrpc/sched.c b/net/sunrpc/sched.c
--- a/net/sunrpc/sched.c	Sun Feb 10 19:58:03 2002
+++ b/net/sunrpc/sched.c	Sun Feb 10 19:58:03 2002
@@ -1109,7 +1109,7 @@
 	unsigned long flags;
 
 	while (all_tasks) {
-		current->work.sigpending = 0;
+		clear_thread_flag(TIF_SIGPENDING);
 		rpc_killall_tasks(NULL);
 		__rpc_schedule();
 		if (all_tasks) {
@@ -1183,7 +1183,7 @@
 	 * Usually rpciod will exit very quickly, so we
 	 * wait briefly before checking the process id.
 	 */
-	current->work.sigpending = 0;
+	clear_thread_flag(TIF_SIGPENDING);
 	yield();
 	/*
 	 * Display a message if we're going to wait longer.
diff -Nru a/net/sunrpc/svc.c b/net/sunrpc/svc.c
--- a/net/sunrpc/svc.c	Sun Feb 10 19:58:05 2002
+++ b/net/sunrpc/svc.c	Sun Feb 10 19:58:05 2002
@@ -185,7 +185,7 @@
 		progp->pg_name, proto == IPPROTO_UDP? "udp" : "tcp", port);
 
 	if (!port)
-		current->work.sigpending = 0;
+		clear_thread_flag(TIF_SIGPENDING);
 
 	for (i = 0; i < progp->pg_nvers; i++) {
 		if (progp->pg_vers[i] == NULL)
diff -Nru a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
--- a/net/sunrpc/svcauth.c	Sun Feb 10 19:58:05 2002
+++ b/net/sunrpc/svcauth.c	Sun Feb 10 19:58:05 2002
@@ -15,6 +15,7 @@
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcauth.h>
 #include <linux/sunrpc/svcsock.h>
+#include <linux/err.h>
 
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	Sun Feb 10 19:58:04 2002
+++ b/net/unix/af_unix.c	Sun Feb 10 19:58:04 2002
@@ -711,7 +711,7 @@
 		/*
 		 * All right, let's create it.
 		 */
-		mode = S_IFSOCK | (sock->inode->i_mode & ~current->fs->umask);
+		mode = S_IFSOCK | (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
 		err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
 		if (err)
 			goto out_mknod_dput;
diff -Nru a/net/unix/garbage.c b/net/unix/garbage.c
--- a/net/unix/garbage.c	Sun Feb 10 19:58:05 2002
+++ b/net/unix/garbage.c	Sun Feb 10 19:58:05 2002
@@ -101,7 +101,7 @@
 	 *	Socket ?
 	 */
 	if (inode->i_sock) {
-		struct socket * sock = &inode->u.socket_i;
+		struct socket * sock = SOCKET_I(inode);
 		struct sock * s = sock->sk;
 
 		/*
diff -Nru a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
--- a/net/wanrouter/wanmain.c	Sun Feb 10 19:58:04 2002
+++ b/net/wanrouter/wanmain.c	Sun Feb 10 19:58:04 2002
@@ -500,7 +500,7 @@
 	if ((cmd >> 8) != ROUTER_IOCTL)
 		return -EINVAL;
 		
-	dent = inode->u.generic_ip;
+	dent = PDE(inode);
 	if ((dent == NULL) || (dent->data == NULL))
 		return -EINVAL;
 		
diff -Nru a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
--- a/net/wanrouter/wanproc.c	Sun Feb 10 19:58:06 2002
+++ b/net/wanrouter/wanproc.c	Sun Feb 10 19:58:06 2002
@@ -248,7 +248,7 @@
 		if (count <= 0)
 			return 0;
 			
-		dent = inode->u.generic_ip;
+		dent = PDE(inode);
 		if ((dent == NULL) || (dent->get_info == NULL))
 			return 0;
 			
@@ -794,7 +794,7 @@
 		if (count <= 0)
 			return 0;
 			
-		dent = inode->u.generic_ip;
+		dent = PDE(inode);
 		if ((dent == NULL) || (dent->get_info == NULL))
 			return 0;
 			
@@ -828,7 +828,7 @@
 
 		if (count <= 0)
 			return 0;
-		dent = inode->u.generic_ip;
+		dent = PDE(inode);
 		if ((dent == NULL) || (dent->get_info == NULL))
 			return -ENODATA;
 		err = verify_area(VERIFY_WRITE, buf, count);
@@ -1068,7 +1068,7 @@
 
         if (err) return err;
 
-        dent = inode->u.generic_ip;
+        dent = PDE(inode);
         if ((dent == NULL) || (dent->data == NULL))
                 return -ENODATA;
 
diff -Nru a/net/x25/af_x25.c b/net/x25/af_x25.c
--- a/net/x25/af_x25.c	Sun Feb 10 19:58:05 2002
+++ b/net/x25/af_x25.c	Sun Feb 10 19:58:05 2002
@@ -1239,7 +1239,7 @@
 			s->protinfo.x25->t23 / HZ,
 			atomic_read(&s->wmem_alloc),
 			atomic_read(&s->rmem_alloc),
-			s->socket != NULL ? s->socket->inode->i_ino : 0L);
+			s->socket != NULL ? SOCK_INODE(s->socket)->i_ino : 0L);
 
 		pos = begin + len;
 
diff -Nru a/scripts/header.tk b/scripts/header.tk
--- a/scripts/header.tk	Sun Feb 10 19:58:06 2002
+++ b/scripts/header.tk	Sun Feb 10 19:58:06 2002
@@ -449,29 +449,24 @@
 	catch {destroy $w}
 	toplevel $w -class Dialog
 
-	set filefound 0
 	set found 0
-	set lineno 0
 
-	if { [file readable Documentation/Configure.help] == 1} then {
-		set filefound 1
-		# First escape sed regexp special characters in var:
-		set var [exec echo "$var" | sed s/\[\]\[\/.^$*\]/\\\\&/g]
-		# Now pick out right help text:
-		set message [exec sed -n "
-			/^$var\[ 	\]*\$/,\${
-				/^$var\[ 	\]*\$/c\\
+	# First escape sed regexp special characters in var:
+	set var [exec echo "$var" | sed s/\[\]\[\/.^$*\]/\\\\&/g]
+	# Now pick out right help text:
+	set message [exec find . -name Config.help | xargs sed -n "
+		/^$var\[ 	\]*\$/,\${
+			/^$var\[ 	\]*\$/c\\
 ${var}:\\
 
-				/^#/b
-				/^\[^ 	\]/q
-				s/^  //
-				/<file:\\(\[^>\]*\\)>/s//\\1/g
-				p
-			}
-			" Documentation/Configure.help]
-		set found [expr [string length "$message"] > 0]
-	}
+			/^#/b
+			/^\[^ 	\]/q
+			s/^  //
+			/<file:\\(\[^>\]*\\)>/s//\\1/g
+			p
+		}
+		" /dev/null ]
+	set found [expr [string length "$message"] > 0]
 
 	frame $w.f1
 	pack $w.f1 -fill both -expand on
@@ -494,13 +489,8 @@
 	pack $w.f1.canvas -side right -fill y -expand on
 
 	if { $found == 0 } then {
-		if { $filefound == 0 } then {
-		message $w.f1.f.m -width 750 -aspect 300 -relief flat -text \
-			"No help available - unable to open file Documentation/Configure.help.  This file should have come with your kernel."
-		} else {
 		message $w.f1.f.m -width 400 -aspect 300 -relief flat -text \
 			"No help available for $var"
-		}
 		label $w.f1.bm -bitmap error
 		wm title $w "RTFM"
 	} else {
